diff --git a/.qmake.conf b/.qmake.conf index de7af300dcd..dfdd8e2c962 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -2,6 +2,7 @@ load(qt_build_config) CONFIG += warning_clean DEFINES += QT_NO_JAVA_STYLE_ITERATORS +DEFINES += QT_NO_LINKED_LIST QT_SOURCE_TREE = $$PWD QT_BUILD_TREE = $$shadowed($$PWD) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index 7793811c9f0..8226edfb76f 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -1092,7 +1092,7 @@ foreach my $lib (@modules_to_sync) { # } my $class_header = "$class "; $pri_install_gfiles .= $class_header - unless ($shadow || $pri_install_gfiles =~ $class_header); + unless ($shadow || $pri_install_gfiles =~ m/\b$class_header/); $injection .= ":$class"; } diff --git a/config.tests/arch/arch.pro b/config.tests/arch/arch.pro index 2ffdb2c8898..45a7eb33af9 100644 --- a/config.tests/arch/arch.pro +++ b/config.tests/arch/arch.pro @@ -1,2 +1 @@ -TARGET = arch SOURCES = arch.cpp diff --git a/config.tests/arch/arch_host.pro b/config.tests/arch/arch_host.pro index f7acef0c5dd..cefdbc77ef1 100644 --- a/config.tests/arch/arch_host.pro +++ b/config.tests/arch/arch_host.pro @@ -1,2 +1,2 @@ option(host_build) -include(arch.pro) +SOURCES = arch.cpp diff --git a/configure b/configure index 945e6e82ccf..f99499c53e8 100755 --- a/configure +++ b/configure @@ -417,7 +417,7 @@ if [ -z "$QT_MAJOR_VERSION" ]; then fi } #------------------------------------------------------------------------------- -# initalize variables +# initialize variables #------------------------------------------------------------------------------- # QTDIR may be set and point to an old or system-wide Qt installation diff --git a/configure.json b/configure.json index 33e429338b7..e3eb2e152c8 100644 --- a/configure.json +++ b/configure.json @@ -252,12 +252,14 @@ "label": "target architecture", "type": "architecture", "test": "arch", + "output": "arch", "log": "arch" }, "host_architecture": { "label": "host architecture", "type": "architecture", "test": "arch", + "output": "arch_host", "host": true, "pro": "arch_host.pro", "log": "arch" @@ -1323,7 +1325,7 @@ "ccache": { "label": "Using ccache", "autoDetect": false, - "condition": "config.unix && tests.ccache", + "condition": "tests.ccache", "output": [ "privateConfig" ] }, "msvc_mp": { diff --git a/configure.pri b/configure.pri index 81133da3d7e..7b8dee0953c 100644 --- a/configure.pri +++ b/configure.pri @@ -286,20 +286,39 @@ defineTest(qtConfTest_architecture) { !qtConfTest_compile($${1}): \ error("Could not determine $$eval($${1}.label). See config.log for details.") + host = $$eval($${1}.host) + isEmpty(host): host = false + file_prefix = + exts = - + $$host { + equals(QMAKE_HOST.os, Windows): \ + exts = .exe + } else { + win32 { + exts = .exe + } else:android { + file_prefix = lib + exts = .so + } else:wasm { + exts = .wasm .o + } + } + test = $$eval($${1}.test) + output = $$eval($${1}.output) test_out_dir = $$OUT_PWD/$$basename(QMAKE_CONFIG_TESTS_DIR)/$$test - unix:exists($$test_out_dir/arch): \ - content = $$cat($$test_out_dir/arch, blob) - else: win32:exists($$test_out_dir/arch.exe): \ - content = $$cat($$test_out_dir/arch.exe, blob) - else: android:exists($$test_out_dir/libarch.so): \ - content = $$cat($$test_out_dir/libarch.so, blob) - else: wasm:exists($$test_out_dir/arch.wasm): \ - content = $$cat($$test_out_dir/arch.wasm, blob) - else: wasm:exists($$test_out_dir/arch.o): \ - content = $$cat($$test_out_dir/arch.o, blob) - else: \ + test_out_file = + for(ext, exts) { + equals(ext, -): ext = + f = $$test_out_dir/$$file_prefix$$output$$ext + exists($$f) { + test_out_file = $$f + break() + } + } + isEmpty(test_out_file): \ error("$$eval($${1}.label) detection binary not found.") + content = $$cat($$test_out_file, blob) arch_magic = ".*==Qt=magic=Qt== Architecture:([^\\0]*).*" subarch_magic = ".*==Qt=magic=Qt== Sub-architecture:([^\\0]*).*" diff --git a/dependencies.yaml b/dependencies.yaml deleted file mode 100644 index 32cf5dda7ed..00000000000 --- a/dependencies.yaml +++ /dev/null @@ -1 +0,0 @@ -dependencies: [] diff --git a/examples/opengl/legacy/hellogl/glwidget.cpp b/examples/opengl/legacy/hellogl/glwidget.cpp index 22934136e52..059a9bb96d9 100644 --- a/examples/opengl/legacy/hellogl/glwidget.cpp +++ b/examples/opengl/legacy/hellogl/glwidget.cpp @@ -140,10 +140,10 @@ void GLWidget::initializeGL() { initializeOpenGLFunctions(); - qglClearColor(qtPurple.dark()); + qglClearColor(qtPurple.darker()); logo = new QtLogo(this, 64); - logo->setColor(qtGreen.dark()); + logo->setColor(qtGreen.darker()); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); diff --git a/examples/opengl/legacy/overpainting/glwidget.cpp b/examples/opengl/legacy/overpainting/glwidget.cpp index 0094f8ead72..c4558ce785d 100644 --- a/examples/opengl/legacy/overpainting/glwidget.cpp +++ b/examples/opengl/legacy/overpainting/glwidget.cpp @@ -130,7 +130,7 @@ void GLWidget::initializeGL() glEnable(GL_MULTISAMPLE); logo = new QtLogo(this); - logo->setColor(qtGreen.dark()); + logo->setColor(qtGreen.darker()); } //! [2] @@ -163,7 +163,7 @@ void GLWidget::paintEvent(QPaintEvent *event) //! [4] //! [6] - qglClearColor(qtPurple.dark()); + qglClearColor(qtPurple.darker()); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); diff --git a/examples/opengl/qopenglwindow/background_renderer.cpp b/examples/opengl/qopenglwindow/background_renderer.cpp index 9da1b9bf99a..acbbe748411 100644 --- a/examples/opengl/qopenglwindow/background_renderer.cpp +++ b/examples/opengl/qopenglwindow/background_renderer.cpp @@ -91,6 +91,9 @@ FragmentToy::FragmentToy(const QString &fragmentSource, QObject *parent) } } +FragmentToy::~FragmentToy() + = default; + void FragmentToy::draw(const QSize &windowSize) { if (!m_program) @@ -120,7 +123,7 @@ void FragmentToy::draw(const QSize &windowSize) if (!m_vertex_shader->compileSourceCode(vertex_shader)) { qWarning() << "Failed to compile the vertex shader:" << m_vertex_shader->log(); } - if (!m_program->addShader(m_vertex_shader.data())) { + if (!m_program->addShader(m_vertex_shader.get())) { qWarning() << "Failed to add vertex shader to program:" << m_program->log(); } } @@ -153,7 +156,7 @@ void FragmentToy::draw(const QSize &windowSize) } if (m_fragment_shader) { - if (!m_program->addShader(m_fragment_shader.data())) { + if (!m_program->addShader(m_fragment_shader.get())) { qWarning() << "Failed to add fragment shader to program:" << m_program->log(); } } @@ -197,14 +200,14 @@ void FragmentToy::fileChanged(const QString &path) m_fragment_file_last_modified = fragment_source.lastModified(); m_recompile_shaders = true; if (m_program) { - m_program->removeShader(m_fragment_shader.data()); + m_program->removeShader(m_fragment_shader.get()); m_fragment_shader.reset(nullptr); } } } else { m_recompile_shaders = true; if (m_program) { - m_program->removeShader(m_fragment_shader.data()); + m_program->removeShader(m_fragment_shader.get()); m_fragment_shader.reset(nullptr); } } diff --git a/examples/opengl/qopenglwindow/background_renderer.h b/examples/opengl/qopenglwindow/background_renderer.h index d99b7ddbeb8..0e3caf59816 100644 --- a/examples/opengl/qopenglwindow/background_renderer.h +++ b/examples/opengl/qopenglwindow/background_renderer.h @@ -62,11 +62,14 @@ #include #include +#include + class FragmentToy : public QObject, protected QOpenGLFunctions { Q_OBJECT public: - FragmentToy(const QString &fragmentSource, QObject *parent = 0); + explicit FragmentToy(const QString &fragmentSource, QObject *parent = nullptr); + ~FragmentToy(); void draw(const QSize &windowSize); @@ -79,9 +82,9 @@ private: QString m_fragment_file; QDateTime m_fragment_file_last_modified; - QScopedPointer m_program; - QScopedPointer m_vertex_shader; - QScopedPointer m_fragment_shader; + std::unique_ptr m_program; + std::unique_ptr m_vertex_shader; + std::unique_ptr m_fragment_shader; QOpenGLVertexArrayObject m_vao; QOpenGLBuffer m_vertex_buffer; GLuint m_vertex_coord_pos; diff --git a/examples/widgets/desktop/systray/window.cpp b/examples/widgets/desktop/systray/window.cpp index 31fcd84821e..e30166beac9 100644 --- a/examples/widgets/desktop/systray/window.cpp +++ b/examples/widgets/desktop/systray/window.cpp @@ -160,9 +160,10 @@ void Window::iconActivated(QSystemTrayIcon::ActivationReason reason) void Window::showMessage() { showIconCheckBox->setChecked(true); - QSystemTrayIcon::MessageIcon msgIcon = QSystemTrayIcon::MessageIcon( - typeComboBox->itemData(typeComboBox->currentIndex()).toInt()); - if (msgIcon == QSystemTrayIcon::NoIcon) { + int selectedIcon = typeComboBox->itemData(typeComboBox->currentIndex()).toInt(); + QSystemTrayIcon::MessageIcon msgIcon = QSystemTrayIcon::MessageIcon(selectedIcon); + + if (selectedIcon == -1) { // custom icon QIcon icon(iconComboBox->itemIcon(iconComboBox->currentIndex())); trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), icon, durationSpinBox->value() * 1000); @@ -222,7 +223,7 @@ void Window::createMessageGroupBox() QStyle::SP_MessageBoxCritical), tr("Critical"), QSystemTrayIcon::Critical); typeComboBox->addItem(QIcon(), tr("Custom icon"), - QSystemTrayIcon::NoIcon); + -1); typeComboBox->setCurrentIndex(1); durationLabel = new QLabel(tr("Duration:")); diff --git a/examples/widgets/dialogs/standarddialogs/dialog.cpp b/examples/widgets/dialogs/standarddialogs/dialog.cpp index c91a594490b..df77d035671 100644 --- a/examples/widgets/dialogs/standarddialogs/dialog.cpp +++ b/examples/widgets/dialogs/standarddialogs/dialog.cpp @@ -317,7 +317,7 @@ void Dialog::setInteger() { //! [0] bool ok; - int i = QInputDialog::getInt(this, tr("QInputDialog::getInteger()"), + int i = QInputDialog::getInt(this, tr("QInputDialog::getInt()"), tr("Percentage:"), 25, 0, 100, 1, &ok); if (ok) integerLabel->setText(tr("%1%").arg(i)); diff --git a/examples/widgets/painting/shared/arthurstyle.cpp b/examples/widgets/painting/shared/arthurstyle.cpp index 3fc461bbd29..31be8993578 100644 --- a/examples/widgets/painting/shared/arthurstyle.cpp +++ b/examples/widgets/painting/shared/arthurstyle.cpp @@ -457,7 +457,7 @@ void ArthurStyle::polish(QWidget *widget) QPalette pal = widget->palette(); if (widget->isWindow()) { - pal.setColor(QPalette::Background, QColor(241, 241, 241)); + pal.setColor(QPalette::Window, QColor(241, 241, 241)); widget->setPalette(pal); } @@ -474,7 +474,7 @@ void ArthurStyle::unpolish(QWidget *widget) void ArthurStyle::polish(QPalette &palette) { - palette.setColor(QPalette::Background, QColor(241, 241, 241)); + palette.setColor(QPalette::Window, QColor(241, 241, 241)); } QRect ArthurStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const diff --git a/examples/widgets/painting/shared/arthurwidgets.cpp b/examples/widgets/painting/shared/arthurwidgets.cpp index bdac5de13c0..285be99d20c 100644 --- a/examples/widgets/painting/shared/arthurwidgets.cpp +++ b/examples/widgets/painting/shared/arthurwidgets.cpp @@ -153,7 +153,7 @@ void ArthurFrame::paintEvent(QPaintEvent *e) int o = 10; - QBrush bg = palette().brush(QPalette::Background); + QBrush bg = palette().brush(QPalette::Window); painter.fillRect(0, 0, o, o, bg); painter.fillRect(width() - o, 0, o, o, bg); painter.fillRect(0, height() - o, o, o, bg); diff --git a/examples/widgets/statemachine/trafficlight/main.cpp b/examples/widgets/statemachine/trafficlight/main.cpp index 1a7050c28df..a12d2f10d1d 100644 --- a/examples/widgets/statemachine/trafficlight/main.cpp +++ b/examples/widgets/statemachine/trafficlight/main.cpp @@ -105,7 +105,7 @@ public: m_green = new LightWidget(Qt::green); vbox->addWidget(m_green); QPalette pal = palette(); - pal.setColor(QPalette::Background, Qt::black); + pal.setColor(QPalette::Window, Qt::black); setPalette(pal); setAutoFillBackground(true); } diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf index 00da9bd33f1..376a7ded5d8 100644 --- a/mkspecs/features/create_cmake.prf +++ b/mkspecs/features/create_cmake.prf @@ -26,6 +26,10 @@ contains(CMAKE_INSTALL_LIBS_DIR, ^(/usr)?/lib(64)?.*): CMAKE_USR_MOVE_WORKAROUND CMAKE_OUT_DIR = $$MODULE_BASE_OUTDIR/lib/cmake +internal_module { + MODULE = "$${MODULE}_private" +} + # Core, Network, an external module named Foo CMAKE_MODULE_NAME = $$cmakeModuleName($${MODULE}) @@ -112,6 +116,10 @@ win32:!static:!staticlib { static|staticlib:CMAKE_STATIC_TYPE = true +internal_module { + CMAKE_INTERNAL_MODULE = true +} + CMAKE_DEBUG_TYPE = CMAKE_RELEASE_TYPE = @@ -133,6 +141,24 @@ equals(QMAKE_HOST.os, Windows): CMAKE_BIN_SUFFIX = ".exe" if(build_all|CONFIG(debug, debug|release)): CMAKE_DEBUG_TYPE = debug if(build_all|CONFIG(release, debug|release)): CMAKE_RELEASE_TYPE = release +# CMAKE_DEBUG_AND_RELEASE is used to tell the _populate_$${CMAKE_MODULE_NAME}_target_properties +# functions whether a Configuration specific generator expression needs to be added to the values +# of INTERFACE_LINK_LIBRARIES and INTERFACE_LINK_OPTIONS. For debug_and_release builds, we do need +# configuration specific values. For singular builds (only release or only debug), we want the +# values to be applied regardless of the configuration. +# This would allow on Linux and macOS (and with a recent enough version of CMake on Windows) to +# build a Debug configuration of an application, even if Qt was built in a Release configuration. +# +# All IMPORTED_LOCATION_ paths are automatically considered by CMake if there is no +# equivalent to the value specified by CMAKE_BUILD_TYPE. +# This means that when Qt was built in a Release configuration, and the application in a Debug +# configuration, IMPORTED_LOCATION_RELEASE will be used for the Qt libraries. +debug_and_release { + CMAKE_DEBUG_AND_RELEASE = TRUE +} else { + CMAKE_DEBUG_AND_RELEASE = FALSE +} + contains(CONFIG, plugin) { !isEmpty(PLUGIN_EXTENDS):!equals(PLUGIN_EXTENDS, -) { count(PLUGIN_EXTENDS, 1, greaterThan): \ @@ -341,7 +367,7 @@ cmake_qt5_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5$${CMAKE_MODULE_NAME} # Other modules should either create proper tests in tests/auto/cmake or, as # a temporary measure, disable the generation of cmake files # with 'CONFIG -= create_cmake' -!equals(CMAKE_MODULE_TESTS, -) { +!internal_module:!equals(CMAKE_MODULE_TESTS, -) { isEmpty(CMAKE_MODULE_TESTS): CMAKE_MODULE_TESTS = $$MODULE_BASE_INDIR/tests/auto/cmake !exists($$CMAKE_MODULE_TESTS): \ error("Missing CMake tests. Either create tests in tests/auto/cmake," \ diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in index ba7d9575c0d..d4fd057682d 100644 --- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in +++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in @@ -75,7 +75,7 @@ function(_qt5_$${CMAKE_MODULE_NAME}_process_prl_file prl_file_location Configura # Handle normal libraries passed as -lfoo set(_lib \"${CMAKE_MATCH_1}\") foreach(_standard_library ${_standard_libraries}) - if(_standard_library MATCHES \"^${_lib}(\\.lib)?$\") + if(_standard_library MATCHES \"^${_lib}(\\\\.lib)?$\") set(_lib_is_default_linked TRUE) break() endif() @@ -119,7 +119,8 @@ endfunction() !!ENDIF !!IF !equals(TEMPLATE, aux) -macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATION IMPLIB_LOCATION) +macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATION IMPLIB_LOCATION + IsDebugAndRelease) set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${Configuration}) !!IF isEmpty(CMAKE_DLL_DIR_IS_ABSOLUTE) @@ -130,24 +131,48 @@ macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATI _qt5_$${CMAKE_MODULE_NAME}_check_file_exists(${imported_location}) set(_deps ${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES} + ) + set(_static_deps !!IF !isEmpty(CMAKE_STATIC_TYPE) ${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${Configuration}_LIB_DEPENDENCIES} !!ENDIF ) + set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES - \"INTERFACE_LINK_LIBRARIES\" \"${_deps}\" \"IMPORTED_LOCATION_${Configuration}\" ${imported_location} !!IF !isEmpty(CMAKE_LIB_SONAME) \"IMPORTED_SONAME_${Configuration}\" \"$${CMAKE_LIB_SONAME}\" !!ENDIF # For backward compatibility with CMake < 2.8.12 - \"IMPORTED_LINK_INTERFACE_LIBRARIES_${Configuration}\" \"${_deps}\" + \"IMPORTED_LINK_INTERFACE_LIBRARIES_${Configuration}\" \"${_deps};${_static_deps}\" + ) + set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY INTERFACE_LINK_LIBRARIES + \"${_deps}\" ) -!!IF !isEmpty(CMAKE_STATIC_TYPE) - if(NOT CMAKE_VERSION VERSION_LESS \"3.13\") - set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES - \"INTERFACE_LINK_OPTIONS\" \"${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${Configuration}_LINK_FLAGS}\" +!!IF !isEmpty(CMAKE_STATIC_TYPE) + if(NOT "${IsDebugAndRelease}") + set(_genex_condition \"1\") + else() + if("${Configuration}" STREQUAL "DEBUG") + set(_genex_condition \"$\") + else() + set(_genex_condition \"$>\") + endif() + endif() + + if(_static_deps) + set(_static_deps_genex \"$<${_genex_condition}:${_static_deps}>\") + set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY INTERFACE_LINK_LIBRARIES + \"${_static_deps_genex}\" + ) + endif() + + set(_static_link_flags \"${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${Configuration}_LINK_FLAGS}\") + if(NOT CMAKE_VERSION VERSION_LESS \"3.13\" AND _static_link_flags) + set(_static_link_flags_genex \"$<${_genex_condition}:${_static_link_flags}>\") + set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY INTERFACE_LINK_OPTIONS + \"${_static_link_flags_genex}\" ) endif() !!ENDIF @@ -382,9 +407,9 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) !!IF !equals(TEMPLATE, aux) !!IF !isEmpty(CMAKE_RELEASE_TYPE) !!IF !isEmpty(CMAKE_STATIC_WINDOWS_BUILD) - _populate_$${CMAKE_MODULE_NAME}_target_properties(RELEASE \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" \"\" ) + _populate_$${CMAKE_MODULE_NAME}_target_properties(RELEASE \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" \"\" $${CMAKE_DEBUG_AND_RELEASE}) !!ELSE - _populate_$${CMAKE_MODULE_NAME}_target_properties(RELEASE \"$${CMAKE_LIB_FILE_LOCATION_RELEASE}\" \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" ) + _populate_$${CMAKE_MODULE_NAME}_target_properties(RELEASE \"$${CMAKE_LIB_FILE_LOCATION_RELEASE}\" \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" $${CMAKE_DEBUG_AND_RELEASE}) !!ENDIF // CMAKE_STATIC_WINDOWS_BUILD !!IF !isEmpty(CMAKE_FIND_OTHER_LIBRARY_BUILD) @@ -395,7 +420,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) !!ELSE // CMAKE_LIB_DIR_IS_ABSOLUTE if (EXISTS \"$${CMAKE_IMPLIB_FILE_LOCATION_DEBUG}\" ) !!ENDIF // CMAKE_LIB_DIR_IS_ABSOLUTE - _populate_$${CMAKE_MODULE_NAME}_target_properties(DEBUG \"$${CMAKE_IMPLIB_FILE_LOCATION_DEBUG}\" \"\" ) + _populate_$${CMAKE_MODULE_NAME}_target_properties(DEBUG \"$${CMAKE_IMPLIB_FILE_LOCATION_DEBUG}\" \"\" $${CMAKE_DEBUG_AND_RELEASE}) !!ELSE // CMAKE_STATIC_WINDOWS_BUILD if (EXISTS !!IF isEmpty(CMAKE_DLL_DIR_IS_ABSOLUTE) @@ -409,7 +434,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) !!ELSE \"$${CMAKE_IMPLIB_FILE_LOCATION_DEBUG}\" ) !!ENDIF - _populate_$${CMAKE_MODULE_NAME}_target_properties(DEBUG \"$${CMAKE_LIB_FILE_LOCATION_DEBUG}\" \"$${CMAKE_IMPLIB_FILE_LOCATION_DEBUG}\" ) + _populate_$${CMAKE_MODULE_NAME}_target_properties(DEBUG \"$${CMAKE_LIB_FILE_LOCATION_DEBUG}\" \"$${CMAKE_IMPLIB_FILE_LOCATION_DEBUG}\" $${CMAKE_DEBUG_AND_RELEASE}) !!ENDIF // CMAKE_STATIC_WINDOWS_BUILD endif() !!ENDIF // CMAKE_DEBUG_TYPE @@ -419,9 +444,9 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) !!IF !isEmpty(CMAKE_DEBUG_TYPE) !!IF !isEmpty(CMAKE_STATIC_WINDOWS_BUILD) - _populate_$${CMAKE_MODULE_NAME}_target_properties(DEBUG \"$${CMAKE_IMPLIB_FILE_LOCATION_DEBUG}\" \"\" ) + _populate_$${CMAKE_MODULE_NAME}_target_properties(DEBUG \"$${CMAKE_IMPLIB_FILE_LOCATION_DEBUG}\" \"\" $${CMAKE_DEBUG_AND_RELEASE}) !!ELSE - _populate_$${CMAKE_MODULE_NAME}_target_properties(DEBUG \"$${CMAKE_LIB_FILE_LOCATION_DEBUG}\" \"$${CMAKE_IMPLIB_FILE_LOCATION_DEBUG}\" ) + _populate_$${CMAKE_MODULE_NAME}_target_properties(DEBUG \"$${CMAKE_LIB_FILE_LOCATION_DEBUG}\" \"$${CMAKE_IMPLIB_FILE_LOCATION_DEBUG}\" $${CMAKE_DEBUG_AND_RELEASE}) !!ENDIF // CMAKE_STATIC_WINDOWS_BUILD !!IF !isEmpty(CMAKE_FIND_OTHER_LIBRARY_BUILD) @@ -432,7 +457,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) !!ELSE // CMAKE_LIB_DIR_IS_ABSOLUTE if (EXISTS \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" ) !!ENDIF // CMAKE_LIB_DIR_IS_ABSOLUTE - _populate_$${CMAKE_MODULE_NAME}_target_properties(RELEASE \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" \"\" ) + _populate_$${CMAKE_MODULE_NAME}_target_properties(RELEASE \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" \"\" $${CMAKE_DEBUG_AND_RELEASE}) !!ELSE // CMAKE_STATIC_WINDOWS_BUILD if (EXISTS !!IF isEmpty(CMAKE_DLL_DIR_IS_ABSOLUTE) @@ -446,7 +471,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) !!ELSE \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" ) !!ENDIF - _populate_$${CMAKE_MODULE_NAME}_target_properties(RELEASE \"$${CMAKE_LIB_FILE_LOCATION_RELEASE}\" \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" ) + _populate_$${CMAKE_MODULE_NAME}_target_properties(RELEASE \"$${CMAKE_LIB_FILE_LOCATION_RELEASE}\" \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" $${CMAKE_DEBUG_AND_RELEASE}) !!ENDIF // CMAKE_STATIC_WINDOWS_BUILD endif() !!ENDIF // CMAKE_RELEASE_TYPE @@ -459,6 +484,8 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) ) !!ENDIF // TEMPLATE != aux +!!IF isEmpty(CMAKE_INTERNAL_MODULE) + file(GLOB pluginTargets \"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}_*Plugin.cmake\") macro(_populate_$${CMAKE_MODULE_NAME}_plugin_properties Plugin Configuration PLUGIN_LOCATION) @@ -481,6 +508,8 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) endforeach() endif() +!!ENDIF // isEmpty(CMAKE_INTERNAL_MODULE) + !!IF !isEmpty(CMAKE_MODULE_EXTRAS) include(\"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}ConfigExtras.cmake\") diff --git a/mkspecs/features/exclusive_builds.prf b/mkspecs/features/exclusive_builds.prf index b28e74146ab..a41c5ab4150 100644 --- a/mkspecs/features/exclusive_builds.prf +++ b/mkspecs/features/exclusive_builds.prf @@ -37,6 +37,9 @@ defineTest(addExclusiveBuilds) { addExclusiveBuildsProper($$join(ARGS, _and_), $$ARGS) } -# Default directories to process -QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR LRELEASE_DIR LEX_DIR YACC_DIR -QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR DESTDIR $$QMAKE_DIR_REPLACE_SANE +QMAKE_DEFAULT_DIRS_TO_PROCESS = QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR LRELEASE_DIR LEX_DIR YACC_DIR +QMAKE_DIR_REPLACE_SANE += $$QMAKE_DEFAULT_DIRS_TO_PROCESS +QMAKE_DIR_REPLACE = \ + OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR DESTDIR \ + $$QMAKE_DEFAULT_DIRS_TO_PROCESS +unset(QMAKE_DEFAULT_DIRS_TO_PROCESS) diff --git a/mkspecs/features/qt_docs.prf b/mkspecs/features/qt_docs.prf index 3b74cd4dd5c..deb4ac28292 100644 --- a/mkspecs/features/qt_docs.prf +++ b/mkspecs/features/qt_docs.prf @@ -27,6 +27,24 @@ QT_TOOL_ENV = qtver qtmver qtvertag qtdocs builddir qtPrepareTool(QDOC, qdoc) QT_TOOL_ENV = +# On Windows, put the includes into a .inc file which QDoc will read, if the project +# has too many includes. We do this to overcome a command-line limit on Windows. +WIN_INCLUDETEMP= +INCLUDE_PATHS=$$INCPATH +win32:count(INCLUDE_PATHS, 30, >) { + WIN_INCLUDETEMP = $$OUT_PWD/qdocincludepaths.inc + WIN_INCLUDETEMP_CONTENT = + for (inc, INCLUDE_PATHS): \ + WIN_INCLUDETEMP_CONTENT += -I$$inc + write_file($$absolute_path($$WIN_INCLUDETEMP, $$OUT_PWD), WIN_INCLUDETEMP_CONTENT)|error() +} + +isEmpty(WIN_INCLUDETEMP) { + QDOC_INCLUDE_PATHS=$(INCPATH) +} else { + QDOC_INCLUDE_PATHS=@$$shell_quote($$WIN_INCLUDETEMP) +} + !build_online_docs: qtPrepareTool(QHELPGENERATOR, qhelpgenerator) qtPrepareTool(QTATTRIBUTIONSSCANNER, qtattributionsscanner) @@ -75,12 +93,13 @@ qtattributionsscanner.CONFIG += phony QMAKE_EXTRA_TARGETS += qtattributionsscanner doc_command = $$QDOC $$QMAKE_DOCS + prepare_docs { - prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors $(INCPATH) - generate_docs.commands += $$doc_command -generate $$DOC_INDEXES $(INCPATH) + prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors $$QDOC_INCLUDE_PATHS + generate_docs.commands += $$doc_command -generate $$DOC_INDEXES $$QDOC_INCLUDE_PATHS prepare_docs.depends += qtattributionsscanner } else { - html_docs.commands += $$doc_command $$DOC_INDEXES $(INCPATH) + html_docs.commands += $$doc_command $$DOC_INDEXES $(QDOC_INCLUDE_PATHS) html_docs.depends += qtattributionsscanner } diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 24512eeb767..169d91c7463 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -117,7 +117,7 @@ unset(QT_FOR_PRIVATE) QMAKE_USE_PRIVATE += $$QMAKE_USE_FOR_PRIVATE unset(QMAKE_USE_FOR_PRIVATE) -!internal_module:CONFIG += create_cmake +CONFIG += create_cmake contains(TARGET, QtAddOn.*): \ DEFINES += QT_BUILD_ADDON_$${ucmodule}_LIB diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index 899a40103ae..7ee1a956f4d 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -304,7 +304,6 @@ headersclean:!internal_module { header_check.variable_out = PRE_TARGETDEPS header_check.name = headercheck ${QMAKE_FILE_IN} header_check.commands = $$hcleanCOMMAND - silent:header_check.commands = @echo compiling[header] ${QMAKE_FILE_IN} && $$hcleanCOMMAND QMAKE_EXTRA_COMPILERS += header_check } unset(hcleanCOMMAND) diff --git a/mkspecs/features/uikit/devices.py b/mkspecs/features/uikit/devices.py index 0443e838f2b..8cdcb370a07 100755 --- a/mkspecs/features/uikit/devices.py +++ b/mkspecs/features/uikit/devices.py @@ -46,11 +46,17 @@ import json import subprocess from distutils.version import StrictVersion +def is_available(object): + if "isAvailable" in object: + return object["isAvailable"] # introduced in Xcode 11 + else: + return "unavailable" not in object["availability"] + def is_suitable_runtime(runtimes, runtime_name, platform, min_version): for runtime in runtimes: identifier = runtime["identifier"] if (runtime["name"] == runtime_name or identifier == runtime_name) \ - and "unavailable" not in runtime["availability"] \ + and is_available(runtime) \ and identifier.startswith("com.apple.CoreSimulator.SimRuntime.{}".format(platform)) \ and StrictVersion(runtime["version"]) >= min_version: return True @@ -77,6 +83,6 @@ if __name__ == "__main__": for runtime_name in device_dict: if is_suitable_runtime(runtimes, runtime_name, args.platform, args.minimum_deployment_target): for device in device_dict[runtime_name]: - if "unavailable" not in device["availability"] \ + if is_available(device) \ and (args.state is None or device["state"].lower() in args.state): print(device["udid"]) diff --git a/mkspecs/features/unsupported/testserver.prf b/mkspecs/features/unsupported/testserver.prf index 32bd4df30ca..bca88ea2d82 100644 --- a/mkspecs/features/unsupported/testserver.prf +++ b/mkspecs/features/unsupported/testserver.prf @@ -58,9 +58,9 @@ debug_and_release:!build_pass: return() DOCKER_ENABLED = 1 -equals(QMAKE_HOST.os, Darwin) | equals(QMAKE_HOST.os, Windows) { +equals(QMAKE_HOST.os, Darwin) { DOCKER_ENABLED = 0 - message("Not using docker network test server on macOS and Windows, see QTQAINFRA-2717 and QTQAINFRA-2750") + message("Not using docker network test server on macOS, see QTQAINFRA-2717 and QTQAINFRA-2750") } TESTSERVER_VERSION = "" diff --git a/qmake/.prev_CMakeLists.txt b/qmake/.prev_CMakeLists.txt index 085a4e72645..dfbafc4ef0c 100644 --- a/qmake/.prev_CMakeLists.txt +++ b/qmake/.prev_CMakeLists.txt @@ -44,22 +44,12 @@ add_qt_executable(qmake ../src/corelib/tools/qarraydataops.h ../src/corelib/tools/qarraydatapointer.h ../src/corelib/tools/qbitarray.cpp ../src/corelib/tools/qbitarray.h - ../src/corelib/tools/qbytearray.cpp ../src/corelib/tools/qbytearray.h - ../src/corelib/tools/qbytearraymatcher.cpp ../src/corelib/tools/qbytearraymatcher.h - ../src/corelib/tools/qchar.h ../src/corelib/tools/qcryptographichash.cpp ../src/corelib/tools/qcryptographichash.h ../src/corelib/tools/qhash.cpp ../src/corelib/tools/qhash.h ../src/corelib/tools/qlist.cpp ../src/corelib/tools/qlist.h - ../src/corelib/tools/qlocale.cpp ../src/corelib/tools/qlocale.h - ../src/corelib/tools/qlocale_tools.cpp ../src/corelib/tools/qlocale_tools_p.h ../src/corelib/tools/qmap.cpp ../src/corelib/tools/qmap.h - ../src/corelib/tools/qregexp.cpp ../src/corelib/tools/qregexp.h - ../src/corelib/tools/qstring.cpp ../src/corelib/tools/qstring.h - ../src/corelib/tools/qstringlist.cpp ../src/corelib/tools/qstringlist.h - ../src/corelib/tools/qstringmatcher.h ../src/corelib/tools/qvector.h ../src/corelib/tools/qversionnumber.cpp ../src/corelib/tools/qversionnumber.h - ../src/corelib/tools/qvsnprintf.cpp cachekeys.h generators/mac/pbuilder_pbx.cpp generators/mac/pbuilder_pbx.h generators/makefile.cpp generators/makefile.h @@ -89,9 +79,18 @@ add_qt_executable(qmake option.cpp option.h project.cpp project.h property.cpp property.h + qbytearray.cpp-NOTFOUND qbytearray.h-NOTFOUND + qbytearraymatcher.cpp-NOTFOUND qbytearraymatcher.h-NOTFOUND + qchar.h-NOTFOUND qdatetime.cpp-NOTFOUND qdatetime.h-NOTFOUND qdatetime_p.h-NOTFOUND + qlocale.cpp-NOTFOUND qlocale.h-NOTFOUND + qlocale_tools.cpp-NOTFOUND qlocale_tools_p.h-NOTFOUND + qregexp.cpp-NOTFOUND qregexp.h-NOTFOUND + qstring.cpp-NOTFOUND qstring.h-NOTFOUND + qstringlist.cpp-NOTFOUND qstringlist.h-NOTFOUND + qstringmatcher.h-NOTFOUND + qvsnprintf.cpp-NOTFOUND DEFINES - =\"\" PROEVALUATOR_FULL QT_BOOTSTRAPPED QT_BUILD_QMAKE @@ -99,21 +98,23 @@ add_qt_executable(qmake QT_VERSION_MAJOR= QT_VERSION_MINOR= QT_VERSION_PATCH= + join(QT_VERSION_STR=\"\") INCLUDE_DIRECTORIES . - ../include - ../include/QtCore ../include/QtCore - ../include/QtCore//QtCore - ../src/corelib/global generators generators/mac generators/unix generators/win32 + join(..)/include + join(..)/include/QtCore join(..)/include/QtCore + join(..)/include/QtCore//QtCore + join(..)/src/corelib/global library + PUBLIC_LIBRARIES + Qt::Gui ) #### Keys ignored in scope 1:.:.:qmake.pro:: -# CONFIG = "cmdline" "-qt" # PRECOMPILED_HEADER = "qmake_pch.h" # _OPTION = "host_build" @@ -128,7 +129,7 @@ extend_target(qmake CONDITION WIN32 ../src/corelib/io/qfsfileengine_win.cpp ../src/corelib/io/qsettings_win.cpp ../src/corelib/plugin/qsystemlibrary.cpp - ../src/corelib/tools/qlocale_win.cpp + qlocale_win.cpp-NOTFOUND registry.cpp-NOTFOUND DEFINES UNICODE @@ -148,7 +149,7 @@ extend_target(qmake CONDITION UNIX ../src/corelib/io/qfilesystemiterator_unix.cpp ../src/corelib/io/qfsfileengine_unix.cpp ../src/corelib/kernel/qcore_unix.cpp - ../src/corelib/tools/qlocale_unix.cpp + qlocale_unix.cpp-NOTFOUND ) extend_target(qmake CONDITION APPLE_OSX diff --git a/qmake/CMakeLists.txt b/qmake/CMakeLists.txt index 438f21d767e..fce7e536bd5 100644 --- a/qmake/CMakeLists.txt +++ b/qmake/CMakeLists.txt @@ -51,24 +51,24 @@ add_qt_tool(qmake # special case ../src/corelib/tools/qarraydataops.h ../src/corelib/tools/qarraydatapointer.h ../src/corelib/tools/qbitarray.cpp ../src/corelib/tools/qbitarray.h - ../src/corelib/tools/qbytearray.cpp ../src/corelib/tools/qbytearray.h - ../src/corelib/tools/qbytearraymatcher.cpp ../src/corelib/tools/qbytearraymatcher.h - ../src/corelib/tools/qchar.h + ../src/corelib/text/qbytearray.cpp ../src/corelib/text/qbytearray.h + ../src/corelib/text/qbytearraymatcher.cpp ../src/corelib/text/qbytearraymatcher.h + ../src/corelib/text/qchar.h ../src/corelib/tools/qcryptographichash.cpp ../src/corelib/tools/qcryptographichash.h ../src/corelib/time/qdatetime.cpp ../src/corelib/time/qdatetime.h ../src/corelib/time/qdatetime_p.h # special case ../src/corelib/tools/qhash.cpp ../src/corelib/tools/qhash.h ../src/corelib/tools/qlist.cpp ../src/corelib/tools/qlist.h - ../src/corelib/tools/qlocale.cpp ../src/corelib/tools/qlocale.h - ../src/corelib/tools/qlocale_tools.cpp ../src/corelib/tools/qlocale_tools_p.h + ../src/corelib/text/qlocale.cpp ../src/corelib/text/qlocale.h + ../src/corelib/text/qlocale_tools.cpp ../src/corelib/text/qlocale_tools_p.h ../src/corelib/tools/qmap.cpp ../src/corelib/tools/qmap.h - ../src/corelib/tools/qregexp.cpp ../src/corelib/tools/qregexp.h + ../src/corelib/text/qregexp.cpp ../src/corelib/text/qregexp.h ../src/corelib/tools/qringbuffer.cpp # special case - ../src/corelib/tools/qstring.cpp ../src/corelib/tools/qstring.h - ../src/corelib/tools/qstringlist.cpp ../src/corelib/tools/qstringlist.h - ../src/corelib/tools/qstringmatcher.h + ../src/corelib/text/qstring.cpp ../src/corelib/text/qstring.h + ../src/corelib/text/qstringlist.cpp ../src/corelib/text/qstringlist.h + ../src/corelib/text/qstringmatcher.h ../src/corelib/tools/qvector.h ../src/corelib/tools/qversionnumber.cpp ../src/corelib/tools/qversionnumber.h - ../src/corelib/tools/qvsnprintf.cpp + ../src/corelib/text/qvsnprintf.cpp cachekeys.h generators/mac/pbuilder_pbx.cpp generators/mac/pbuilder_pbx.h generators/makefile.cpp generators/makefile.h @@ -108,8 +108,7 @@ add_qt_tool(qmake # special case QT_VERSION_MINOR=${PROJECT_VERSION_MINOR} # special case QT_VERSION_PATCH=${PROJECT_VERSION_PATCH} # special case INCLUDE_DIRECTORIES - # . # special case - library + # . # special case remove generators generators/mac generators/unix @@ -122,7 +121,6 @@ add_qt_tool(qmake # special case qt_internal_add_target_aliases(Bootstrap) # special case #### Keys ignored in scope 1:.:.:qmake.pro:: -# CONFIG = "cmdline" "-qt" # PRECOMPILED_HEADER = "qmake_pch.h" # _OPTION = "host_build" @@ -137,7 +135,7 @@ extend_target(qmake CONDITION WIN32 ../src/corelib/io/qfsfileengine_win.cpp ../src/corelib/io/qsettings_win.cpp ../src/corelib/plugin/qsystemlibrary.cpp - ../src/corelib/tools/qlocale_win.cpp + ../src/corelib/text/qlocale_win.cpp # special case library/registry.cpp # special case DEFINES UNICODE @@ -157,7 +155,7 @@ extend_target(qmake CONDITION UNIX ../src/corelib/io/qfilesystemiterator_unix.cpp ../src/corelib/io/qfsfileengine_unix.cpp ../src/corelib/kernel/qcore_unix.cpp - ../src/corelib/tools/qlocale_unix.cpp + ../src/corelib/text/qlocale_unix.cpp ) extend_target(qmake CONDITION APPLE_OSX @@ -180,7 +178,7 @@ extend_target(qmake CONDITION WIN32 ../src/corelib/io/qfilesystemengine_win.cpp ../src/corelib/io/qfilesystemiterator_win.cpp ../src/corelib/io/qfsfileengine_win.cpp - ../src/corelib/tools/qlocale_win.cpp + ../src/corelib/text/qlocale_win.cpp ../src/corelib/io/qsettings_win.cpp # ../src/corelib/global/qoperatingsystemversion.cpp special case: remove this ../src/corelib/plugin/qsystemlibrary.cpp diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 069cb0f12d8..68f173cd1ba 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -105,24 +105,24 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/serialization/qtextstream.cpp \ $(SOURCE_PATH)/src/corelib/serialization/qxmlstream.cpp \ $(SOURCE_PATH)/src/corelib/serialization/qxmlutils.cpp \ + $(SOURCE_PATH)/src/corelib/text/qbytearray.cpp\ + $(SOURCE_PATH)/src/corelib/text/qbytearraymatcher.cpp \ + $(SOURCE_PATH)/src/corelib/text/qlocale.cpp \ + $(SOURCE_PATH)/src/corelib/text/qlocale_tools.cpp \ + $(SOURCE_PATH)/src/corelib/text/qregexp.cpp \ + $(SOURCE_PATH)/src/corelib/text/qstringbuilder.cpp \ + $(SOURCE_PATH)/src/corelib/text/qstring.cpp \ + $(SOURCE_PATH)/src/corelib/text/qstringlist.cpp \ + $(SOURCE_PATH)/src/corelib/text/qvsnprintf.cpp \ $(SOURCE_PATH)/src/corelib/time/qdatetime.cpp \ $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp \ $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\ - $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \ $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp \ $(SOURCE_PATH)/src/corelib/tools/qhash.cpp \ $(SOURCE_PATH)/src/corelib/tools/qlist.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp \ $(SOURCE_PATH)/src/corelib/tools/qmap.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \ $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qstring.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp \ $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp \ $(QTSRCS) $(QTSRCS2) # QTSRCS and QTSRCS2 come from Makefile.unix.* (concatenated with this # by configure); QTSRCS2 may include *.mm entries on macOS. @@ -302,13 +302,13 @@ qglobal.o: $(SOURCE_PATH)/src/corelib/global/qglobal.cpp qarraydata.o: $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qbytearray.o: $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp +qbytearray.o: $(SOURCE_PATH)/src/corelib/text/qbytearray.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qvsnprintf.o: $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp +qvsnprintf.o: $(SOURCE_PATH)/src/corelib/text/qvsnprintf.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qbytearraymatcher.o: $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp +qbytearraymatcher.o: $(SOURCE_PATH)/src/corelib/text/qbytearraymatcher.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< qmetatype.o: $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp @@ -338,22 +338,22 @@ qcore_foundation.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm qutfcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qstring.o: $(SOURCE_PATH)/src/corelib/tools/qstring.cpp +qstring.o: $(SOURCE_PATH)/src/corelib/text/qstring.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qstringbuilder.o: $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp +qstringbuilder.o: $(SOURCE_PATH)/src/corelib/text/qstringbuilder.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qlocale.o: $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp +qlocale.o: $(SOURCE_PATH)/src/corelib/text/qlocale.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qlocale_tools.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp +qlocale_tools.o: $(SOURCE_PATH)/src/corelib/text/qlocale_tools.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qlocale_unix.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp +qlocale_unix.o: $(SOURCE_PATH)/src/corelib/text/qlocale_unix.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qlocale_win.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp +qlocale_win.o: $(SOURCE_PATH)/src/corelib/text/qlocale_win.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< qversionnumber.o: $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp @@ -407,7 +407,7 @@ qabstractfileengine.o: $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp qtemporaryfile.o: $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qregexp.o: $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp +qregexp.o: $(SOURCE_PATH)/src/corelib/text/qregexp.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< qbitarray.o: $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp @@ -428,7 +428,7 @@ qfileinfo.o: $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp qdatetime.o: $(SOURCE_PATH)/src/corelib/time/qdatetime.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp +qstringlist.o: $(SOURCE_PATH)/src/corelib/text/qstringlist.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< qmap.o: $(SOURCE_PATH)/src/corelib/tools/qmap.cpp diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index d300e492153..43059f9af0b 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -196,6 +196,9 @@ qmake_pch.obj: {$(SOURCE_PATH)\src\corelib\serialization}.cpp{}.obj:: $(CXX) $(CXXFLAGS) $< +{$(SOURCE_PATH)\src\corelib\text}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< + {$(SOURCE_PATH)\src\corelib\time}.cpp{}.obj:: $(CXX) $(CXXFLAGS) $< diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index ff936bf1ee3..2082bd6dc30 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -167,14 +167,8 @@ MakefileGenerator::initOutPaths() ProString &pathRef = v[dkey].first(); pathRef = fileFixify(pathRef.toQString(), FileFixifyFromOutdir); -#ifdef Q_OS_WIN - // We don't want to add a separator for DLLDESTDIR on Windows (###why?) - if (dkey != "DLLDESTDIR") -#endif - { - if(!pathRef.endsWith(Option::dir_sep)) - pathRef += Option::dir_sep; - } + if (!pathRef.endsWith(Option::dir_sep)) + pathRef += Option::dir_sep; if (noIO() || (project->first("TEMPLATE") == "subdirs")) continue; @@ -2233,21 +2227,6 @@ MakefileGenerator::writeDummyMakefile(QTextStream &t) return true; } -bool -MakefileGenerator::writeStubMakefile(QTextStream &t) -{ - t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl; - const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); - for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) - t << *it << " "; - //const QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.fileName())); - t << "first all clean install distclean uninstall: qmake\n" - << "qmake_all:\n"; - writeMakeQmake(t); - t << "FORCE:\n\n"; - return true; -} - bool MakefileGenerator::writeMakefile(QTextStream &t) { @@ -2299,9 +2278,9 @@ QString MakefileGenerator::buildArgs(bool withExtra) //could get stored argv, but then it would have more options than are //probably necesary this will try to guess the bare minimum.. -QString MakefileGenerator::build_args() +QString MakefileGenerator::fullBuildArgs() { - QString ret = "$(QMAKE)"; + QString ret; //output QString ofile = fileFixify(Option::output.fileName()); @@ -2326,7 +2305,7 @@ MakefileGenerator::writeHeader(QTextStream &t) t << "# Project: " << fileFixify(project->projectFile()) << Qt::endl; t << "# Template: " << var("TEMPLATE") << Qt::endl; if(!project->isActiveConfig("build_pass")) - t << "# Command: " << build_args().replace(QLatin1String("$(QMAKE)"), var("QMAKE_QMAKE")) << Qt::endl; + t << "# Command: " << var("QMAKE_QMAKE") << fullBuildArgs() << Qt::endl; t << "#############################################################################\n"; t << Qt::endl; QString ofile = Option::fixPathToTargetOS(Option::output.fileName()); @@ -2792,7 +2771,7 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll) << "@$(QMAKE) -prl " << files.join(' ') << ' ' << buildArgs(true) << Qt::endl; } - QString qmake = build_args(); + QString qmake = "$(QMAKE)" + fullBuildArgs(); if(!ofile.isEmpty() && !project->isActiveConfig("no_autoqmake")) { t << escapeDependencyPath(ofile) << ": " << escapeDependencyPath(fileFixify(project->projectFile())) << " "; @@ -3429,9 +3408,9 @@ MakefileGenerator::writePkgConfigFile() t << Qt::endl; // requires - const QString requires = project->values("QMAKE_PKGCONFIG_REQUIRES").join(' '); - if (!requires.isEmpty()) { - t << "Requires: " << requires << Qt::endl; + const QString requiresString = project->values("QMAKE_PKGCONFIG_REQUIRES").join(' '); + if (!requiresString.isEmpty()) { + t << "Requires: " << requiresString << Qt::endl; } t << Qt::endl; diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index c7b2bee0b4f..ac1d5abb11e 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -58,7 +58,7 @@ class MakefileGenerator : protected QMakeSourceFileInfo bool resolveDependenciesInFrameworks = false; QHash init_compiler_already; QString makedir, chkexists; - QString build_args(); + QString fullBuildArgs(); //internal caches mutable QHash depHeuristicsCache; @@ -90,7 +90,6 @@ protected: void writeExtraCompilerTargets(QTextStream &t); void writeExtraCompilerVariables(QTextStream &t); bool writeDummyMakefile(QTextStream &t); - virtual bool writeStubMakefile(QTextStream &t); virtual bool writeMakefile(QTextStream &t); virtual void writeDefaultVariables(QTextStream &t); diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp index f9159ccd75e..705ad7008a1 100644 --- a/qmake/generators/metamakefile.cpp +++ b/qmake/generators/metamakefile.cpp @@ -57,6 +57,7 @@ private: QList makefiles; void clearBuilds(); MakefileGenerator *processBuild(const ProString &); + void accumulateVariableFromBuilds(const ProKey &name, Build *build) const; public: @@ -95,9 +96,6 @@ BuildsMetaMakefileGenerator::init() if(builds.count() > 1 && Option::output.fileName() == "-") { use_single_build = true; warn_msg(WarnLogic, "Cannot direct to stdout when using multiple BUILDS."); - } else if(0 && !use_single_build && project->first("TEMPLATE") == "subdirs") { - use_single_build = true; - warn_msg(WarnLogic, "Cannot specify multiple builds with TEMPLATE subdirs."); } if(!use_single_build) { for(int i = 0; i < builds.count(); i++) { @@ -188,6 +186,7 @@ BuildsMetaMakefileGenerator::write() if(!build->makefile) { ret = false; } else if(build == glue) { + accumulateVariableFromBuilds("QMAKE_INTERNAL_INCLUDED_FILES", build); ret = build->makefile->writeProjectMakefile(); } else { ret = build->makefile->write(); @@ -230,6 +229,16 @@ MakefileGenerator return nullptr; } +void BuildsMetaMakefileGenerator::accumulateVariableFromBuilds(const ProKey &name, Build *dst) const +{ + ProStringList &values = dst->makefile->projectFile()->values(name); + for (auto build : makefiles) { + if (build != dst) + values += build->makefile->projectFile()->values(name); + } + values.removeDuplicates(); +} + class SubdirsMetaMakefileGenerator : public MetaMakefileGenerator { protected: @@ -327,17 +336,13 @@ SubdirsMetaMakefileGenerator::init() hasError |= tmpError; } sub->makefile = MetaMakefileGenerator::createMetaGenerator(sub_proj, sub_name); - if(0 && sub->makefile->type() == SUBDIRSMETATYPE) { - subs.append(sub); - } else { - const QString output_name = Option::output.fileName(); - Option::output.setFileName(sub->output_file); - hasError |= !sub->makefile->write(); - delete sub; - qmakeClearCaches(); - sub = nullptr; - Option::output.setFileName(output_name); - } + const QString output_name = Option::output.fileName(); + Option::output.setFileName(sub->output_file); + hasError |= !sub->makefile->write(); + delete sub; + qmakeClearCaches(); + sub = nullptr; + Option::output.setFileName(output_name); Option::output_dir = old_output_dir; qmake_setpwd(oldpwd); diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index ef55af365c3..227dc8908ad 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -497,21 +497,20 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) // Make sure we keep the dependency order of libraries lflags[arch].removeAll(opt); lflags[arch].append(opt); - } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-framework")) { - if (opt.length() > 10) { - opt = opt.mid(10).trimmed(); - } else { - opt = l.at(++lit); - if (opt.startsWith("-Xarch")) - opt = l.at(++lit); // The user has done the right thing and prefixed each part - } + } else if (target_mode == TARG_MAC_MODE + && (opt == "-framework" || opt == "-force_load")) { + // Handle space separated options + ProString dashOpt = opt; + opt = l.at(++lit); + if (opt.startsWith("-Xarch")) + opt = l.at(++lit); // The user has done the right thing and prefixed each part for(int x = 0; x < lflags[arch].size(); ++x) { - if (lflags[arch].at(x) == "-framework" && lflags[arch].at(++x) == opt) { + if (lflags[arch].at(x) == dashOpt && lflags[arch].at(++x) == opt) { lflags[arch].remove(x - 1, 2); break; } } - lflags[arch].append("-framework"); + lflags[arch].append(dashOpt); lflags[arch].append(opt); } else { lflags[arch].append(opt); diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h index 901419d3cc2..79b161f6da2 100644 --- a/qmake/generators/unix/unixmake.h +++ b/qmake/generators/unix/unixmake.h @@ -42,7 +42,6 @@ class UnixMakefileGenerator : public MakefileGenerator protected: virtual bool doPrecompiledHeaders() const { return project->isActiveConfig("precompile_header"); } - bool doDepends() const override { return !Option::mkfile::do_stub_makefile && MakefileGenerator::doDepends(); } #ifdef Q_OS_WIN // MinGW x-compiling for QNX QString installRoot() const override; #endif diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index c8efd0680ba..8d1bd081972 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -66,8 +66,6 @@ UnixMakefileGenerator::writeMakefile(QTextStream &t) if (project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib" || project->first("TEMPLATE") == "aux") { - if(Option::mkfile::do_stub_makefile && MakefileGenerator::writeStubMakefile(t)) - return true; writeMakeParts(t); return MakefileGenerator::writeMakefile(t); } else if (project->first("TEMPLATE") == "subdirs") { diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 6f80b933070..40114948c27 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -93,18 +93,6 @@ bool MingwMakefileGenerator::writeMakefile(QTextStream &t) project->first("TEMPLATE") == "aux") { if(project->isActiveConfig("create_pc") && project->first("TEMPLATE") == "lib") writePkgConfigFile(); - - if(Option::mkfile::do_stub_makefile) { - t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl; - const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); - for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) - t << escapeDependencyPath(*it) << ' '; - t << "first all clean install distclean uninstall: qmake\n" - << "qmake_all:\n"; - writeMakeQmake(t); - t << "FORCE:\n\n"; - return true; - } writeMingwParts(t); return MakefileGenerator::writeMakefile(t); } @@ -127,7 +115,7 @@ QString MingwMakefileGenerator::installRoot() const return QStringLiteral("$(INSTALL_ROOT:@msyshack@%=%)"); } -void createLdResponseFile(const QString &fileName, const ProStringList &objList) +static void createResponseFile(const QString &fileName, const ProStringList &objList) { QString filePath = Option::output_dir + QDir::separator() + fileName; QFile file(filePath); @@ -151,23 +139,6 @@ void createLdResponseFile(const QString &fileName, const ProStringList &objList) } } -void createArObjectScriptFile(const QString &fileName, const QString &target, const ProStringList &objList) -{ - QString filePath = Option::output_dir + QDir::separator() + fileName; - QFile file(filePath); - if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { - QTextStream t(&file); - // ### quoting? - t << "CREATE " << target << Qt::endl; - for (ProStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) { - t << "ADDMOD " << *it << Qt::endl; - } - t << "SAVE\n"; - t.flush(); - file.close(); - } -} - void MingwMakefileGenerator::writeMingwParts(QTextStream &t) { writeStandardParts(t); @@ -294,26 +265,25 @@ void MingwMakefileGenerator::writeObjectsPart(QTextStream &t) if (objmax.isEmpty() || project->values("OBJECTS").count() < objmax.toInt()) { objectsLinkLine = "$(OBJECTS)"; } else if (project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") { - QString ar_script_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET"); + QString ar_response_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET"); if (!var("BUILD_NAME").isEmpty()) { - ar_script_file += "." + var("BUILD_NAME"); + ar_response_file += "." + var("BUILD_NAME"); } if (!var("MAKEFILE").isEmpty()) - ar_script_file += "." + var("MAKEFILE"); + ar_response_file += "." + var("MAKEFILE"); // QMAKE_LIB is used for win32, including mingw, whereas QMAKE_AR is used on Unix. - // Strip off any options since the ar commands will be read from file. - QString ar_cmd = var("QMAKE_LIB").section(" ", 0, 0); + QString ar_cmd = var("QMAKE_LIB"); if (ar_cmd.isEmpty()) - ar_cmd = "ar"; - createArObjectScriptFile(ar_script_file, var("DEST_TARGET"), project->values("OBJECTS")); - objectsLinkLine = ar_cmd + " -M < " + escapeFilePath(ar_script_file); + ar_cmd = "ar -rc"; + createResponseFile(ar_response_file, project->values("OBJECTS")); + objectsLinkLine = ar_cmd + ' ' + var("DEST_TARGET") + " @" + escapeFilePath(ar_response_file); } else { QString ld_response_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET"); if (!var("BUILD_NAME").isEmpty()) ld_response_file += "." + var("BUILD_NAME"); if (!var("MAKEFILE").isEmpty()) ld_response_file += "." + var("MAKEFILE"); - createLdResponseFile(ld_response_file, project->values("OBJECTS")); + createResponseFile(ld_response_file, project->values("OBJECTS")); objectsLinkLine = "@" + escapeFilePath(ld_response_file); } Win32MakefileGenerator::writeObjectsPart(t); diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 1f6223f01d1..67b478ae288 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -48,10 +48,6 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib" || project->first("TEMPLATE") == "aux") { -#if 0 - if(Option::mkfile::do_stub_makefile) - return MakefileGenerator::writeStubMakefile(t); -#endif writeNmakeParts(t); return MakefileGenerator::writeMakefile(t); } diff --git a/qmake/library/proitems.cpp b/qmake/library/proitems.cpp index 41bed69f00a..9330c2b1bf8 100644 --- a/qmake/library/proitems.cpp +++ b/qmake/library/proitems.cpp @@ -238,7 +238,7 @@ ProString &ProString::append(const ProString &other, bool *pending) QChar *ptr; if (pending && !*pending) { ptr = prepareExtend(1 + other.m_length, 0, m_length); - *ptr++ = 32; + *ptr++ = QLatin1Char(' '); } else { ptr = prepareExtend(other.m_length, 0, m_length); } @@ -276,7 +276,7 @@ ProString &ProString::append(const ProStringList &other, bool *pending, bool ski QChar *ptr = prepareExtend(totalLength, 0, m_length); for (int i = startIdx; i < sz; ++i) { if (putSpace) - *ptr++ = 32; + *ptr++ = QLatin1Char(' '); else putSpace = true; const ProString &str = other.at(i); diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h index cc65421556e..4569d7c3ff0 100644 --- a/qmake/library/proitems.h +++ b/qmake/library/proitems.h @@ -68,6 +68,7 @@ class ProString { public: ProString(); ProString(const ProString &other); + ProString &operator=(const ProString &) = default; PROITEM_EXPLICIT ProString(const QString &str); PROITEM_EXPLICIT ProString(const QStringRef &str); PROITEM_EXPLICIT ProString(const char *str); @@ -432,11 +433,12 @@ public: ProFunctionDef(const ProFunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); } ProFunctionDef(ProFunctionDef &&other) noexcept : m_pro(other.m_pro), m_offset(other.m_offset) { other.m_pro = nullptr; } - ~ProFunctionDef() { m_pro->deref(); } + ~ProFunctionDef() { if (m_pro) m_pro->deref(); } ProFunctionDef &operator=(const ProFunctionDef &o) { if (this != &o) { - m_pro->deref(); + if (m_pro) + m_pro->deref(); m_pro = o.m_pro; m_pro->ref(); m_offset = o.m_offset; diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index ba617932ce1..70897214b29 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -1130,48 +1130,35 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) } superdir = qdfi.path(); } + QString sdir = inDir; QString dir = m_outputDir; forever { + conffile = sdir + QLatin1String("/.qmake.conf"); + if (!m_vfs->exists(conffile, flags)) + conffile.clear(); cachefile = dir + QLatin1String("/.qmake.cache"); if (!m_vfs->exists(cachefile, flags)) cachefile.clear(); - if (!cachefile.isEmpty()) { + if (!conffile.isEmpty() || !cachefile.isEmpty()) { + if (dir != sdir) + m_sourceRoot = sdir; m_buildRoot = dir; break; } if (dir == superdir) goto no_cache; - QFileInfo qdfi(dir); - if (qdfi.isRoot()) { - cachefile.clear(); - break; - } - dir = qdfi.path(); - } - QString sdir = inDir; - forever { - conffile = sdir + QLatin1String("/.qmake.conf"); - if (!m_vfs->exists(conffile, flags)) - conffile.clear(); - if (!conffile.isEmpty()) { - if (sdir != m_buildRoot) - m_sourceRoot = sdir; - break; - } QFileInfo qsdfi(sdir); - if (qsdfi.isRoot()) { - conffile.clear(); - break; - } + QFileInfo qdfi(dir); + if (qsdfi.isRoot() || qdfi.isRoot()) + goto no_cache; sdir = qsdfi.path(); + dir = qdfi.path(); } } else { m_buildRoot = QFileInfo(cachefile).path(); } - if (!conffile.isEmpty()) - m_conffile = QDir::cleanPath(conffile); - if (!cachefile.isEmpty()) - m_cachefile = QDir::cleanPath(cachefile); + m_conffile = QDir::cleanPath(conffile); + m_cachefile = QDir::cleanPath(cachefile); } no_cache: @@ -1583,8 +1570,8 @@ void QMakeEvaluator::updateFeaturePaths() } for (int i = 0; i < feature_roots.count(); ++i) - if (!feature_roots.at(i).endsWith((ushort)'/')) - feature_roots[i].append((ushort)'/'); + if (!feature_roots.at(i).endsWith(QLatin1Char('/'))) + feature_roots[i].append(QLatin1Char('/')); feature_roots.removeDuplicates(); diff --git a/qmake/library/qmakeparser.cpp b/qmake/library/qmakeparser.cpp index 4c8360b4598..ffe90ebda71 100644 --- a/qmake/library/qmakeparser.cpp +++ b/qmake/library/qmakeparser.cpp @@ -621,7 +621,7 @@ void QMakeParser::read(ProFile *pro, const QStringRef &in, int line, SubGrammar if (c != term) { parseError(fL1S("Missing %1 terminator [found %2]") .arg(QChar(term)) - .arg(c ? QString(c) : QString::fromLatin1("end-of-line"))); + .arg(c ? QString(QChar(c)) : QString::fromLatin1("end-of-line"))); m_inError = true; // Just parse on, as if there was a terminator ... } else { diff --git a/qmake/library/qmakeparser.h b/qmake/library/qmakeparser.h index 7b96d4e88f8..c8c5c7718ed 100644 --- a/qmake/library/qmakeparser.h +++ b/qmake/library/qmakeparser.h @@ -111,7 +111,6 @@ private: struct BlockScope { BlockScope() : start(nullptr), braceLevel(0), special(false), inBranch(false), nest(NestNone) {} - BlockScope(const BlockScope &other) { *this = other; } ushort *start; // Where this block started; store length here int braceLevel; // Nesting of braces in scope bool special; // Single-line conditionals inside loops, etc. cannot have else branches diff --git a/qmake/option.cpp b/qmake/option.cpp index dcebeadcb82..1e31ecd6b71 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -93,7 +93,6 @@ bool Option::mkfile::do_deps = true; bool Option::mkfile::do_mocs = true; bool Option::mkfile::do_dep_heuristics = true; bool Option::mkfile::do_preprocess = false; -bool Option::mkfile::do_stub_makefile = false; QStringList Option::mkfile::project_files; static Option::QMAKE_MODE default_mode(QString progname) @@ -254,8 +253,6 @@ Option::parseCommandLine(QStringList &args, QMakeCmdLineParserState &state) Option::mkfile::do_deps = false; } else if (arg == "-nomoc") { Option::mkfile::do_mocs = false; - } else if (arg == "-createstub") { - Option::mkfile::do_stub_makefile = true; } else if (arg == "-nodependheuristics") { Option::mkfile::do_dep_heuristics = false; } else if (arg == "-E") { diff --git a/qmake/option.h b/qmake/option.h index 25b2d64aaa1..d7f4e87c701 100644 --- a/qmake/option.h +++ b/qmake/option.h @@ -189,7 +189,6 @@ struct Option static bool do_mocs; static bool do_dep_heuristics; static bool do_preprocess; - static bool do_stub_makefile; static int cachefile_depth; static QStringList project_files; }; diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 9679fd40f4d..c33d5016cef 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -178,6 +178,9 @@ public class QtNative return fdDesc.detachFd(); } catch (FileNotFoundException e) { return -1; + } catch (SecurityException e) { + Log.e(QtTAG, "Exception when opening file", e); + return -1; } } diff --git a/src/corelib/.prev_CMakeLists.txt b/src/corelib/.prev_CMakeLists.txt index eb02076dfe7..13f0ad99756 100644 --- a/src/corelib/.prev_CMakeLists.txt +++ b/src/corelib/.prev_CMakeLists.txt @@ -143,6 +143,31 @@ add_qt_module(Core statemachine/qsignaltransition.cpp statemachine/qsignaltransition.h statemachine/qsignaltransition_p.h statemachine/qstate.cpp statemachine/qstate.h statemachine/qstate_p.h statemachine/qstatemachine.cpp statemachine/qstatemachine.h statemachine/qstatemachine_p.h + text/qbytearray.cpp text/qbytearray.h text/qbytearray_p.h + text/qbytearraylist.cpp text/qbytearraylist.h + text/qbytearraymatcher.cpp text/qbytearraymatcher.h + text/qbytedata_p.h + text/qchar.h + text/qcollator.cpp text/qcollator.h text/qcollator_p.h + text/qdoublescanprint_p.h + text/qharfbuzz.cpp text/qharfbuzz_p.h + text/qlocale.cpp text/qlocale.h text/qlocale_p.h + text/qlocale_data_p.h + text/qlocale_tools.cpp text/qlocale_tools_p.h + text/qregexp.cpp text/qregexp.h + text/qstring.cpp text/qstring.h + text/qstring_compat.cpp + text/qstringalgorithms.h text/qstringalgorithms_p.h + text/qstringbuilder.cpp text/qstringbuilder.h + text/qstringiterator_p.h + text/qstringlist.cpp text/qstringlist.h + text/qstringliteral.h + text/qstringmatcher.h + text/qstringview.cpp text/qstringview.h + text/qtextboundaryfinder.cpp text/qtextboundaryfinder.h + text/qunicodetables_p.h + text/qunicodetools.cpp text/qunicodetools_p.h + text/qvsnprintf.cpp thread/qmutex.h thread/qreadwritelock.h thread/qrunnable.cpp thread/qrunnable.h @@ -155,30 +180,19 @@ add_qt_module(Core tools/qarraydataops.h tools/qarraydatapointer.h tools/qbitarray.cpp tools/qbitarray.h - tools/qbytearray.cpp tools/qbytearray.h tools/qbytearray_p.h - tools/qbytearraylist.cpp tools/qbytearraylist.h - tools/qbytearraymatcher.cpp tools/qbytearraymatcher.h - tools/qbytedata_p.h tools/qcache.h - tools/qchar.h - tools/qcollator.cpp tools/qcollator.h tools/qcollator_p.h tools/qcontainerfwd.h tools/qcontainertools_impl.h tools/qcontiguouscache.cpp tools/qcontiguouscache.h tools/qcryptographichash.cpp tools/qcryptographichash.h - tools/qdoublescanprint_p.h tools/qeasingcurve.cpp tools/qeasingcurve.h tools/qfreelist.cpp tools/qfreelist_p.h - tools/qharfbuzz.cpp tools/qharfbuzz_p.h tools/qhash.cpp tools/qhash.h tools/qhashfunctions.h tools/qiterator.h tools/qline.cpp tools/qline.h tools/qlinkedlist.cpp tools/qlinkedlist.h tools/qlist.cpp tools/qlist.h - tools/qlocale.cpp tools/qlocale.h tools/qlocale_p.h - tools/qlocale_data_p.h - tools/qlocale_tools.cpp tools/qlocale_tools_p.h tools/qmakearray_p.h tools/qmap.cpp tools/qmap.h tools/qmargins.cpp tools/qmargins.h @@ -189,7 +203,6 @@ add_qt_module(Core tools/qqueue.h tools/qrect.cpp tools/qrect.h tools/qrefcount.cpp tools/qrefcount.h - tools/qregexp.cpp tools/qregexp.h tools/qringbuffer.cpp tools/qringbuffer_p.h tools/qscopedpointer.h tools/qscopedpointer_p.h tools/qscopedvaluerollback.h @@ -201,24 +214,11 @@ add_qt_module(Core tools/qsimd.cpp tools/qsimd_p.h tools/qsize.cpp tools/qsize.h tools/qstack.h - tools/qstring.cpp tools/qstring.h - tools/qstring_compat.cpp - tools/qstringalgorithms.h tools/qstringalgorithms_p.h - tools/qstringbuilder.cpp tools/qstringbuilder.h - tools/qstringiterator_p.h - tools/qstringlist.cpp tools/qstringlist.h - tools/qstringliteral.h - tools/qstringmatcher.h - tools/qstringview.cpp tools/qstringview.h - tools/qtextboundaryfinder.cpp tools/qtextboundaryfinder.h tools/qtimeline.cpp tools/qtimeline.h tools/qtools_p.h - tools/qunicodetables_p.h - tools/qunicodetools.cpp tools/qunicodetools_p.h tools/qvarlengtharray.h tools/qvector.h tools/qversionnumber.cpp tools/qversionnumber.h - tools/qvsnprintf.cpp DEFINES QT_NO_FOREACH QT_NO_USING_NAMESPACE @@ -236,7 +236,7 @@ add_qt_module(Core add_qt_simd_part(Core SIMD mips_dsp SOURCES ../gui/painting/qt_mips_asm_dsp_p.h - tools/qstring_mips_dsp_asm.S + text/qstring_mips_dsp_asm.S ) @@ -254,10 +254,9 @@ if(ANDROID) endif() #### Keys ignored in scope 1:.:.:corelib.pro:: -# CMAKE_DISABLED_FEATURES = "$$joinQT_DISABLED_FEATURES,"$$escape_expand(\\n) "" -# CMAKE_HOST_DATA_DIR = "$$cmakeRelativePath$$[QT_HOST_DATA/src],$$[QT_INSTALL_PREFIX]" -# CMAKE_INSTALL_DATA_DIR = "$$cmakeRelativePath$$[QT_HOST_DATA],$$[QT_INSTALL_PREFIX]" -# CONFIG = "exceptions" "qt_tracepoints" "$$MODULE_CONFIG" "simd" "optimize_full" +# CMAKE_DISABLED_FEATURES = "join(QT_DISABLED_FEATURES,"$$escape_expand(\\n) ")" +# CMAKE_HOST_DATA_DIR = "join($$[QT_HOST_DATA/src],$$[QT_INSTALL_PREFIX])" +# CMAKE_INSTALL_DATA_DIR = "join($$[QT_HOST_DATA],$$[QT_INSTALL_PREFIX])" # HOST_BINS = "$$[QT_HOST_BINS]" # INSTALLS = "ctest_qt5_module_files" "cmake_qt5_umbrella_module_files" # MODULE = "core" @@ -432,7 +431,7 @@ extend_target(Core CONDITION _ss_f16c_cxx extend_target(Core CONDITION linux_x_ OR hurd_x_ AND NOT cross_compile AND NOT static AND NOT _x_-armcc_x_ DEFINES - ELF_INTERPRETER=\\\"=Creadelf-l/bin/ls|perl-n-e\'/programinterpreter:.*]/{print$1;}\'\\\" + ELF_INTERPRETER=\\\"=Creadelf-l/bin/ls|perl-n-e\'['quote', ['if', ['/program', 'interpreter:', ['.*'], ']/'], '{', 'print', '$1;', '}']]\'\\\" LINK_OPTIONS "-Wl,-e,qt_core_boilerplate" ) @@ -508,7 +507,6 @@ extend_target(Core CONDITION QT_FEATURE_thread thread/qfutex_p.h thread/qgenericatomic.h thread/qmutex.cpp thread/qmutex_p.h - thread/qmutexpool.cpp thread/qmutexpool_p.h thread/qorderedmutexlocker_p.h thread/qreadwritelock.cpp thread/qreadwritelock_p.h thread/qsemaphore.cpp thread/qsemaphore.h @@ -569,52 +567,6 @@ extend_target(Core CONDITION MSVC tools/qvector_msvc.cpp ) -extend_target(Core CONDITION APPLE AND NOT NACL - SOURCES - kernel/qelapsedtimer_mac.cpp - tools/qlocale_mac.mm -) - -extend_target(Core CONDITION UNIX AND (NACL OR NOT APPLE) - SOURCES - tools/qlocale_unix.cpp -) - -extend_target(Core CONDITION WIN32 AND (NACL OR NOT APPLE) - SOURCES - tools/qlocale_win.cpp -) - -extend_target(Core CONDITION QT_FEATURE_icu - SOURCES - tools/qcollator_icu.cpp - tools/qlocale_icu.cpp - LIBRARIES - ICU::i18n ICU::uc ICU::data -) - -extend_target(Core CONDITION WIN32 AND NOT QT_FEATURE_icu - SOURCES - tools/qcollator_win.cpp -) - -extend_target(Core CONDITION APPLE_OSX AND NOT QT_FEATURE_icu - SOURCES - tools/qcollator_macx.cpp -) - -extend_target(Core CONDITION UNIX AND NOT APPLE_OSX AND NOT QT_FEATURE_icu - SOURCES - tools/qcollator_posix.cpp -) - -extend_target(Core CONDITION QT_FEATURE_regularexpression - SOURCES - tools/qregularexpression.cpp tools/qregularexpression.h - LIBRARIES - WrapPCRE2::WrapPCRE2 -) - extend_target(Core CONDITION QT_FEATURE_commandlineparser SOURCES tools/qcommandlineoption.cpp tools/qcommandlineoption.h @@ -626,6 +578,51 @@ extend_target(Core CONDITION UNIX AND NOT HAIKU AND NOT INTEGRITY AND NOT VXWORK m ) +extend_target(Core CONDITION APPLE_OSX AND NOT NACL + SOURCES + text/qlocale_mac.mm +) + +extend_target(Core CONDITION UNIX AND (NACL OR NOT APPLE_OSX) + SOURCES + text/qlocale_unix.cpp +) + +extend_target(Core CONDITION WIN32 AND (NACL OR NOT APPLE_OSX) + SOURCES + text/qlocale_win.cpp +) + +extend_target(Core CONDITION QT_FEATURE_icu + SOURCES + text/qcollator_icu.cpp + text/qlocale_icu.cpp + LIBRARIES + ICU::i18n ICU::uc ICU::data +) + +extend_target(Core CONDITION WIN32 AND NOT QT_FEATURE_icu + SOURCES + text/qcollator_win.cpp +) + +extend_target(Core CONDITION APPLE_OSX AND NOT QT_FEATURE_icu + SOURCES + text/qcollator_macx.cpp +) + +extend_target(Core CONDITION UNIX AND NOT APPLE_OSX AND NOT QT_FEATURE_icu + SOURCES + text/qcollator_posix.cpp +) + +extend_target(Core CONDITION QT_FEATURE_regularexpression + SOURCES + text/qregularexpression.cpp text/qregularexpression.h + LIBRARIES + WrapPCRE2::WrapPCRE2 +) + extend_target(Core CONDITION QT_FEATURE_timezone SOURCES time/qtimezone.cpp time/qtimezone.h @@ -841,6 +838,11 @@ extend_target(Core CONDITION QT_FEATURE_dlopen AND QT_FEATURE_library ${CMAKE_DL_LIBS} ) +extend_target(Core CONDITION APPLE AND NOT NACL + SOURCES + kernel/qelapsedtimer_mac.cpp +) + extend_target(Core CONDITION APPLE AND (APPLE_IOS OR APPLE_TVOS) LIBRARIES ${FWUIKit} @@ -968,15 +970,19 @@ extend_target(Core CONDITION QT_FEATURE_mimetype # Resources: set_source_files_properties("mimetypes/mime/packages/freedesktop.org.xml" - PROPERTIES alias "freedesktop.org.xml" + PROPERTIES QT_RESOURCE_ALIAS "freedesktop.org.xml" ) +set(mimetypes_resource_files + "mime/packages/freedesktop.org.xml" +) + add_qt_resource(Core "mimetypes" PREFIX "/qt-project.org/qmime/packages" BASE "mimetypes" FILES - mime/packages/freedesktop.org.xml + ${mimetypes_resource_files} ) diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 94afbf76c2e..8d676e1be07 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -157,6 +157,31 @@ add_qt_module(Core statemachine/qsignaltransition.cpp statemachine/qsignaltransition.h statemachine/qsignaltransition_p.h statemachine/qstate.cpp statemachine/qstate.h statemachine/qstate_p.h statemachine/qstatemachine.cpp statemachine/qstatemachine.h statemachine/qstatemachine_p.h + text/qbytearray.cpp text/qbytearray.h text/qbytearray_p.h + text/qbytearraylist.cpp text/qbytearraylist.h + text/qbytearraymatcher.cpp text/qbytearraymatcher.h + text/qbytedata_p.h + text/qchar.h + text/qcollator.cpp text/qcollator.h text/qcollator_p.h + text/qdoublescanprint_p.h + text/qharfbuzz.cpp text/qharfbuzz_p.h + text/qlocale.cpp text/qlocale.h text/qlocale_p.h + text/qlocale_data_p.h + text/qlocale_tools.cpp text/qlocale_tools_p.h + text/qregexp.cpp text/qregexp.h + text/qstring.cpp text/qstring.h + text/qstring_compat.cpp + text/qstringalgorithms.h text/qstringalgorithms_p.h + text/qstringbuilder.cpp text/qstringbuilder.h + text/qstringiterator_p.h + text/qstringlist.cpp text/qstringlist.h + text/qstringliteral.h + text/qstringmatcher.h + text/qstringview.cpp text/qstringview.h + text/qtextboundaryfinder.cpp text/qtextboundaryfinder.h + text/qunicodetables_p.h + text/qunicodetools.cpp text/qunicodetools_p.h + text/qvsnprintf.cpp thread/qmutex.h thread/qreadwritelock.h thread/qrunnable.cpp thread/qrunnable.h @@ -169,30 +194,19 @@ add_qt_module(Core tools/qarraydataops.h tools/qarraydatapointer.h tools/qbitarray.cpp tools/qbitarray.h - tools/qbytearray.cpp tools/qbytearray.h tools/qbytearray_p.h - tools/qbytearraylist.cpp tools/qbytearraylist.h - tools/qbytearraymatcher.cpp tools/qbytearraymatcher.h - tools/qbytedata_p.h tools/qcache.h - tools/qchar.h - tools/qcollator.cpp tools/qcollator.h tools/qcollator_p.h tools/qcontainerfwd.h tools/qcontainertools_impl.h tools/qcontiguouscache.cpp tools/qcontiguouscache.h tools/qcryptographichash.cpp tools/qcryptographichash.h - tools/qdoublescanprint_p.h tools/qeasingcurve.cpp tools/qeasingcurve.h tools/qfreelist.cpp tools/qfreelist_p.h - tools/qharfbuzz.cpp tools/qharfbuzz_p.h tools/qhash.cpp tools/qhash.h tools/qhashfunctions.h tools/qiterator.h tools/qline.cpp tools/qline.h tools/qlinkedlist.cpp tools/qlinkedlist.h tools/qlist.cpp tools/qlist.h - tools/qlocale.cpp tools/qlocale.h tools/qlocale_p.h - tools/qlocale_data_p.h - tools/qlocale_tools.cpp tools/qlocale_tools_p.h tools/qmakearray_p.h tools/qmap.cpp tools/qmap.h tools/qmargins.cpp tools/qmargins.h @@ -203,7 +217,6 @@ add_qt_module(Core tools/qqueue.h tools/qrect.cpp tools/qrect.h tools/qrefcount.cpp tools/qrefcount.h - tools/qregexp.cpp tools/qregexp.h tools/qringbuffer.cpp tools/qringbuffer_p.h tools/qscopedpointer.h tools/qscopedpointer_p.h tools/qscopedvaluerollback.h @@ -215,24 +228,11 @@ add_qt_module(Core tools/qsimd.cpp tools/qsimd_p.h tools/qsize.cpp tools/qsize.h tools/qstack.h - tools/qstring.cpp tools/qstring.h - tools/qstring_compat.cpp - tools/qstringalgorithms.h tools/qstringalgorithms_p.h - tools/qstringbuilder.cpp tools/qstringbuilder.h - tools/qstringiterator_p.h - tools/qstringlist.cpp tools/qstringlist.h - tools/qstringliteral.h - tools/qstringmatcher.h - tools/qstringview.cpp tools/qstringview.h - tools/qtextboundaryfinder.cpp tools/qtextboundaryfinder.h tools/qtimeline.cpp tools/qtimeline.h tools/qtools_p.h - tools/qunicodetables_p.h - tools/qunicodetools.cpp tools/qunicodetools_p.h tools/qvarlengtharray.h tools/qvector.h tools/qversionnumber.cpp tools/qversionnumber.h - tools/qvsnprintf.cpp DEFINES QT_NO_FOREACH QT_NO_USING_NAMESPACE @@ -318,7 +318,7 @@ endif() add_qt_simd_part(Core SIMD mips_dsp SOURCES ../gui/painting/qt_mips_asm_dsp_p.h - tools/qstring_mips_dsp_asm.S + text/qstring_mips_dsp_asm.S ) @@ -336,10 +336,9 @@ if(ANDROID) endif() #### Keys ignored in scope 1:.:.:corelib.pro:: -# CMAKE_DISABLED_FEATURES = "$$joinQT_DISABLED_FEATURES,"$$escape_expand(\\n) "" -# CMAKE_HOST_DATA_DIR = "$$cmakeRelativePath$$[QT_HOST_DATA/src],$$[QT_INSTALL_PREFIX]" -# CMAKE_INSTALL_DATA_DIR = "$$cmakeRelativePath$$[QT_HOST_DATA],$$[QT_INSTALL_PREFIX]" -# CONFIG = "exceptions" "qt_tracepoints" "$$MODULE_CONFIG" "simd" "optimize_full" +# CMAKE_DISABLED_FEATURES = "join(QT_DISABLED_FEATURES,"$$escape_expand(\\n) ")" +# CMAKE_HOST_DATA_DIR = "join($$[QT_HOST_DATA/src],$$[QT_INSTALL_PREFIX])" +# CMAKE_INSTALL_DATA_DIR = "join($$[QT_HOST_DATA],$$[QT_INSTALL_PREFIX])" # HOST_BINS = "$$[QT_HOST_BINS]" # INSTALLS = "ctest_qt5_module_files" "cmake_qt5_umbrella_module_files" # MODULE = "core" @@ -508,12 +507,15 @@ extend_target(Core CONDITION INTEGRITY #### Keys ignored in scope 27:.:global:global/global.pri:else: # F16C_SOURCES = "global/qfloat16_f16c.c" -extend_target(Core CONDITION linux_x_ OR hurd_x_ AND NOT cross_compile AND NOT static AND NOT _x_-armcc_x_ - DEFINES - ELF_INTERPRETER=\\\"=Creadelf-l/bin/ls|perl-n-e\'/programinterpreter:.*]/{print$1;}\'\\\" - LINK_OPTIONS - "-Wl,-e,qt_core_boilerplate" -) +# special case begin +# Remove this because it's handled manually +#extend_target(Core CONDITION linux_x_ OR hurd_x_ AND NOT cross_compile AND NOT static AND NOT _x_-armcc_x_ +# DEFINES +# ELF_INTERPRETER=\\\"=Creadelf-l/bin/ls|perl-n-e\'['quote', ['if', ['/program', 'interpreter:', ['.*'], ']/'], '{', 'print', '$1;', '}']]\'\\\" +# LINK_OPTIONS +# "-Wl,-e,qt_core_boilerplate" +#) +# special case end extend_target(Core CONDITION LINUX AND NOT static SOURCES @@ -586,7 +588,6 @@ extend_target(Core CONDITION QT_FEATURE_thread thread/qfutex_p.h thread/qgenericatomic.h thread/qmutex.cpp thread/qmutex_p.h - thread/qmutexpool.cpp thread/qmutexpool_p.h thread/qorderedmutexlocker_p.h thread/qreadwritelock.cpp thread/qreadwritelock_p.h thread/qsemaphore.cpp thread/qsemaphore.h @@ -647,52 +648,6 @@ extend_target(Core CONDITION MSVC tools/qvector_msvc.cpp ) -extend_target(Core CONDITION APPLE AND NOT NACL - SOURCES - kernel/qelapsedtimer_mac.cpp - tools/qlocale_mac.mm -) - -extend_target(Core CONDITION UNIX AND (NACL OR NOT APPLE) - SOURCES - tools/qlocale_unix.cpp -) - -extend_target(Core CONDITION WIN32 AND (NACL OR NOT APPLE) - SOURCES - tools/qlocale_win.cpp -) - -extend_target(Core CONDITION QT_FEATURE_icu - SOURCES - tools/qcollator_icu.cpp - tools/qlocale_icu.cpp - LIBRARIES - ICU::i18n ICU::uc ICU::data -) - -extend_target(Core CONDITION WIN32 AND NOT QT_FEATURE_icu - SOURCES - tools/qcollator_win.cpp -) - -extend_target(Core CONDITION APPLE_OSX AND NOT QT_FEATURE_icu - SOURCES - tools/qcollator_macx.cpp -) - -extend_target(Core CONDITION UNIX AND NOT APPLE_OSX AND NOT QT_FEATURE_icu - SOURCES - tools/qcollator_posix.cpp -) - -extend_target(Core CONDITION QT_FEATURE_regularexpression - SOURCES - tools/qregularexpression.cpp tools/qregularexpression.h - LIBRARIES - WrapPCRE2::WrapPCRE2 -) - extend_target(Core CONDITION QT_FEATURE_commandlineparser SOURCES tools/qcommandlineoption.cpp tools/qcommandlineoption.h @@ -704,6 +659,51 @@ extend_target(Core CONDITION UNIX AND NOT HAIKU AND NOT INTEGRITY AND NOT VXWORK m ) +extend_target(Core CONDITION APPLE_OSX AND NOT NACL + SOURCES + text/qlocale_mac.mm +) + +extend_target(Core CONDITION UNIX AND (NACL OR NOT APPLE_OSX) + SOURCES + text/qlocale_unix.cpp +) + +extend_target(Core CONDITION WIN32 AND (NACL OR NOT APPLE_OSX) + SOURCES + text/qlocale_win.cpp +) + +extend_target(Core CONDITION QT_FEATURE_icu + SOURCES + text/qcollator_icu.cpp + text/qlocale_icu.cpp + LIBRARIES + ICU::i18n ICU::uc ICU::data +) + +extend_target(Core CONDITION WIN32 AND NOT QT_FEATURE_icu + SOURCES + text/qcollator_win.cpp +) + +extend_target(Core CONDITION APPLE_OSX AND NOT QT_FEATURE_icu + SOURCES + text/qcollator_macx.cpp +) + +extend_target(Core CONDITION UNIX AND NOT APPLE_OSX AND NOT QT_FEATURE_icu + SOURCES + text/qcollator_posix.cpp +) + +extend_target(Core CONDITION QT_FEATURE_regularexpression + SOURCES + text/qregularexpression.cpp text/qregularexpression.h + LIBRARIES + WrapPCRE2::WrapPCRE2 +) + extend_target(Core CONDITION QT_FEATURE_timezone SOURCES time/qtimezone.cpp time/qtimezone.h @@ -919,6 +919,11 @@ extend_target(Core CONDITION QT_FEATURE_dlopen AND QT_FEATURE_library ${CMAKE_DL_LIBS} ) +extend_target(Core CONDITION APPLE AND NOT NACL + SOURCES + kernel/qelapsedtimer_mac.cpp +) + extend_target(Core CONDITION APPLE AND (APPLE_IOS OR APPLE_TVOS) LIBRARIES ${FWUIKit} diff --git a/src/corelib/codecs/qlatincodec.cpp b/src/corelib/codecs/qlatincodec.cpp index 463c5a56ae6..55e6f0ba4d7 100644 --- a/src/corelib/codecs/qlatincodec.cpp +++ b/src/corelib/codecs/qlatincodec.cpp @@ -62,7 +62,7 @@ QByteArray QLatin1Codec::convertFromUnicode(const QChar *ch, int len, ConverterS char *d = r.data(); int invalid = 0; for (int i = 0; i < len; ++i) { - if (ch[i] > 0xff) { + if (ch[i] > QChar(0xff)) { d[i] = replacement; ++invalid; } else { @@ -112,28 +112,28 @@ QString QLatin15Codec::convertToUnicode(const char* chars, int len, ConverterSta while(len--) { switch(uc->unicode()) { case 0xa4: - *uc = 0x20ac; + *uc = QChar(0x20ac); break; case 0xa6: - *uc = 0x0160; + *uc = QChar(0x0160); break; case 0xa8: - *uc = 0x0161; + *uc = QChar(0x0161); break; case 0xb4: - *uc = 0x017d; + *uc = QChar(0x017d); break; case 0xb8: - *uc = 0x017e; + *uc = QChar(0x017e); break; case 0xbc: - *uc = 0x0152; + *uc = QChar(0x0152); break; case 0xbd: - *uc = 0x0153; + *uc = QChar(0x0153); break; case 0xbe: - *uc = 0x0178; + *uc = QChar(0x0178); break; default: break; diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index 85cfcdbf484..8639e4f2f04 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -544,11 +544,9 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name) #if !QT_CONFIG(icu) QTextCodecCache *cache = &globalData->codecCache; QTextCodec *codec; - if (cache) { - codec = cache->value(name); - if (codec) - return codec; - } + codec = cache->value(name); + if (codec) + return codec; for (TextCodecListConstIt it = globalData->allCodecs.constBegin(), cend = globalData->allCodecs.constEnd(); it != cend; ++it) { QTextCodec *cursor = *it; @@ -560,8 +558,7 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name) QList aliases = cursor->aliases(); for (ByteArrayListConstIt ait = aliases.constBegin(), acend = aliases.constEnd(); ait != acend; ++ait) { if (qTextCodecNameMatch(*ait, name)) { - if (cache) - cache->insert(name, cursor); + cache->insert(name, cursor); return cursor; } } diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp index 85736fdf025..af36bd7e2fa 100644 --- a/src/corelib/codecs/qutfcodec.cpp +++ b/src/corelib/codecs/qutfcodec.cpp @@ -951,10 +951,10 @@ QString QUtf32::convertToUnicode(const char *chars, int len, QTextCodec::Convert } uint code = (endian == BigEndianness) ? qFromBigEndian(tuple) : qFromLittleEndian(tuple); if (QChar::requiresSurrogates(code)) { - *qch++ = QChar::highSurrogate(code); - *qch++ = QChar::lowSurrogate(code); + *qch++ = QChar(QChar::highSurrogate(code)); + *qch++ = QChar(QChar::lowSurrogate(code)); } else { - *qch++ = code; + *qch++ = QChar(code); } num = 0; } diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake index 1a34662fbb9..42ebab7773c 100644 --- a/src/corelib/configure.cmake +++ b/src/corelib/configure.cmake @@ -472,7 +472,7 @@ qDoubleSscanf(argv[0], invalidLocale, \"invalid format\", &a, &argc); /* END TEST: */ return 0; } -"# FIXME: qmake: DEFINES += QDSP_P_H=$$shell_quote(\"@PWD@/tools/qdoublescanprint_p.h\") +"# FIXME: qmake: DEFINES += QDSP_P_H=$$shell_quote(\"@PWD@/text/qdoublescanprint_p.h\") ) diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 6274a556b39..f1f1f0641fb 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -596,7 +596,7 @@ "qDoubleSnprintf(argv[0], 1, invalidLocale, \"invalid format\", a);", "qDoubleSscanf(argv[0], invalidLocale, \"invalid format\", &a, &argc);" ], - "qmake": "DEFINES += QDSP_P_H=$$shell_quote(\\\"@PWD@/tools/qdoublescanprint_p.h\\\")" + "qmake": "DEFINES += QDSP_P_H=$$shell_quote(\\\"@PWD@/text/qdoublescanprint_p.h\\\")" } } }, diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 521f8402920..b9bcc70e175 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -36,6 +36,7 @@ qtConfig(animation): include(animation/animation.pri) include(global/global.pri) include(thread/thread.pri) include(tools/tools.pri) +include(text/text.pri) include(time/time.pri) include(io/io.pri) include(itemmodels/itemmodels.pri) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index f85824c7b3c..736378508fb 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2019 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -613,7 +613,8 @@ using qsizetype = QIntegerForSizeof::Signed; # define Q_ALWAYS_INLINE inline #endif -#if defined(Q_CC_GNU) && defined(Q_OS_WIN) +#if defined(Q_CC_GNU) && defined(Q_OS_WIN) && !defined(QT_NO_DATA_RELOCATION) +// ### Qt6: you can remove me # define QT_INIT_METAOBJECT __attribute__((init_priority(101))) #else # define QT_INIT_METAOBJECT @@ -1002,6 +1003,29 @@ QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantic # endif #endif +// Work around MSVC warning about use of 3-arg algorithms +// until we can depend on the C++14 4-arg ones. +// +// These algortithms do NOT check for equal length. +// They need to be treated as if they called the 3-arg version (which they do)! +#ifdef Q_CC_MSVC +# define QT_3ARG_ALG(alg, f1, l1, f2, l2) \ + std::alg(f1, l1, f2, l2) +#else +# define QT_3ARG_ALG(alg, f1, l1, f2, l2) \ + [&f1, &l1, &f2, &l2]() { \ + Q_UNUSED(l2); \ + return std::alg(f1, l1, f2); \ + }() +#endif +template +inline bool qt_is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2) +{ + return QT_3ARG_ALG(is_permutation, first1, last1, first2, last2); +} +#undef QT_3ARG_ALG + // this adds const to non-const objects (like std::as_const) template Q_DECL_CONSTEXPR typename std::add_const::type &qAsConst(T &t) noexcept { return t; } diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index 02e2f77c6b4..4ebbe16ead9 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -1,6 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2019 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -180,6 +181,12 @@ #if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT) # define Q_OS_WINDOWS # define Q_OS_WIN +# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +// On Windows, pointers to dllimport'ed variables are not constant expressions, +// so to keep to certain initializations (like QMetaObject) constexpr, we need +// to use functions instead. +# define QT_NO_DATA_RELOCATION +# endif #endif #if defined(Q_OS_WIN) diff --git a/src/corelib/global/qt_pch.h b/src/corelib/global/qt_pch.h index 39729916185..0dfd6c745f8 100644 --- a/src/corelib/global/qt_pch.h +++ b/src/corelib/global/qt_pch.h @@ -55,6 +55,10 @@ #include #include #ifdef Q_OS_WIN +# ifdef Q_CC_MINGW +// must be included before any other header pulls in . +# include // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r() +# endif # define _POSIX_ # include # undef _POSIX_ diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 62dae3577c6..fae935fc246 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -153,7 +153,7 @@ QDirPrivate::QDirPrivate(const QDirPrivate ©) bool QDirPrivate::exists() const { - if (fileEngine.isNull()) { + if (!fileEngine) { QFileSystemEngine::fillMetaData(dirEntry, metaData, QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType); // always stat return metaData.exists() && metaData.isDirectory(); @@ -226,7 +226,7 @@ inline void QDirPrivate::resolveAbsoluteEntry() const return; QString absoluteName; - if (fileEngine.isNull()) { + if (!fileEngine) { if (!dirEntry.isRelative() && dirEntry.isClean()) { absoluteDirEntry = dirEntry; return; @@ -693,7 +693,7 @@ QString QDir::absolutePath() const QString QDir::canonicalPath() const { const QDirPrivate* d = d_ptr.constData(); - if (d->fileEngine.isNull()) { + if (!d->fileEngine) { QFileSystemEntry answer = QFileSystemEngine::canonicalName(d->dirEntry, d->metaData); return answer.filePath(); } @@ -947,6 +947,12 @@ QString QDir::fromNativeSeparators(const QString &pathName) int i = pathName.indexOf(QLatin1Char('\\')); if (i != -1) { QString n(pathName); + if (n.startsWith(QLatin1String("\\\\?\\"))) { + n.remove(0, 4); + i = n.indexOf(QLatin1Char('\\')); + if (i == -1) + return n; + } QChar * const data = n.data(); data[i++] = QLatin1Char('/'); @@ -1496,7 +1502,7 @@ bool QDir::mkdir(const QString &dirName) const } QString fn = filePath(dirName); - if (d->fileEngine.isNull()) + if (!d->fileEngine) return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), false); return d->fileEngine->mkdir(fn, false); } @@ -1520,7 +1526,7 @@ bool QDir::rmdir(const QString &dirName) const } QString fn = filePath(dirName); - if (d->fileEngine.isNull()) + if (!d->fileEngine) return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), false); return d->fileEngine->rmdir(fn, false); @@ -1548,7 +1554,7 @@ bool QDir::mkpath(const QString &dirPath) const } QString fn = filePath(dirPath); - if (d->fileEngine.isNull()) + if (!d->fileEngine) return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), true); return d->fileEngine->mkdir(fn, true); } @@ -1574,7 +1580,7 @@ bool QDir::rmpath(const QString &dirPath) const } QString fn = filePath(dirPath); - if (d->fileEngine.isNull()) + if (!d->fileEngine) return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), true); return d->fileEngine->rmdir(fn, true); } @@ -1647,7 +1653,7 @@ bool QDir::isReadable() const { const QDirPrivate* d = d_ptr.constData(); - if (d->fileEngine.isNull()) { + if (!d->fileEngine) { if (!d->metaData.hasFlags(QFileSystemMetaData::UserReadPermission)) QFileSystemEngine::fillMetaData(d->dirEntry, d->metaData, QFileSystemMetaData::UserReadPermission); @@ -1692,7 +1698,7 @@ bool QDir::exists() const */ bool QDir::isRoot() const { - if (d_ptr->fileEngine.isNull()) + if (!d_ptr->fileEngine) return d_ptr->dirEntry.isRoot(); return d_ptr->fileEngine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::RootFlag; } @@ -1724,7 +1730,7 @@ bool QDir::isRoot() const */ bool QDir::isRelative() const { - if (d_ptr->fileEngine.isNull()) + if (!d_ptr->fileEngine) return d_ptr->dirEntry.isRelative(); return d_ptr->fileEngine->isRelativePath(); } @@ -1741,7 +1747,7 @@ bool QDir::makeAbsolute() { const QDirPrivate *d = d_ptr.constData(); QScopedPointer dir; - if (!d->fileEngine.isNull()) { + if (!!d->fileEngine) { QString absolutePath = d->fileEngine->fileName(QAbstractFileEngine::AbsoluteName); if (QDir::isRelativePath(absolutePath)) return false; @@ -1774,8 +1780,8 @@ bool QDir::operator==(const QDir &dir) const if (d == other) return true; Qt::CaseSensitivity sensitive; - if (d->fileEngine.isNull() || other->fileEngine.isNull()) { - if (d->fileEngine.data() != other->fileEngine.data()) // one is native, the other is a custom file-engine + if (!d->fileEngine || !other->fileEngine) { + if (d->fileEngine.get() != other->fileEngine.get()) // one is native, the other is a custom file-engine return false; sensitive = QFileSystemEngine::isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive; @@ -2339,6 +2345,11 @@ static QString qt_cleanPath(const QString &path, bool *ok) if (path.isEmpty()) return path; QString name = path; +#if defined (Q_OS_WIN) + if (name.startsWith(QLatin1String("\\\\?\\"))) + name.remove(0, 4); +#endif + QChar dir_separator = QDir::separator(); if (dir_separator != QLatin1Char('/')) name.replace(dir_separator, QLatin1Char('/')); diff --git a/src/corelib/io/qdir_p.h b/src/corelib/io/qdir_p.h index 0f3ab7f899b..af105de8db7 100644 --- a/src/corelib/io/qdir_p.h +++ b/src/corelib/io/qdir_p.h @@ -54,6 +54,8 @@ #include "qfilesystementry_p.h" #include "qfilesystemmetadata_p.h" +#include + QT_BEGIN_NAMESPACE class QDirPrivate : public QSharedData @@ -82,7 +84,7 @@ public: static inline QChar getFilterSepChar(const QString &nameFilter); - static inline QStringList splitFilters(const QString &nameFilter, QChar sep = 0); + static inline QStringList splitFilters(const QString &nameFilter, QChar sep = {}); void setPath(const QString &path); @@ -98,7 +100,7 @@ public: QDir::SortFlags sort; QDir::Filters filters; - QScopedPointer fileEngine; + std::unique_ptr fileEngine; QFileSystemEntry dirEntry; mutable QFileSystemEntry absoluteDirEntry; diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp index 303caf29a45..ce436b06e32 100644 --- a/src/corelib/io/qdiriterator.cpp +++ b/src/corelib/io/qdiriterator.cpp @@ -107,6 +107,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE template @@ -132,7 +134,7 @@ public: void checkAndPushDirectory(const QFileInfo &); bool matchesFilters(const QString &fileName, const QFileInfo &fi) const; - QScopedPointer engine; + std::unique_ptr engine; QFileSystemEntry dirEntry; const QStringList nameFilters; @@ -435,7 +437,7 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags) { const QDirPrivate *other = dir.d_ptr.constData(); - d.reset(new QDirIteratorPrivate(other->dirEntry, other->nameFilters, other->filters, flags, !other->fileEngine.isNull())); + d.reset(new QDirIteratorPrivate(other->dirEntry, other->nameFilters, other->filters, flags, bool(other->fileEngine))); } /*! diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 9f9a9e30402..95f03ef8162 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -55,6 +55,8 @@ # include "qcoreapplication.h" #endif +#include + #ifdef QT_NO_QOBJECT #define tr(X) QString::fromLatin1(X) #endif @@ -85,10 +87,9 @@ QFilePrivate::openExternalFile(int flags, int fd, QFile::FileHandleFlags handleF Q_UNUSED(fd); return false; #else - delete fileEngine; - fileEngine = nullptr; - QFSFileEngine *fe = new QFSFileEngine; - fileEngine = fe; + auto fs = qt_make_unique(); + auto fe = fs.get(); + fileEngine = std::move(fs); return fe->open(QIODevice::OpenMode(flags), fd, handleFlags); #endif } @@ -101,10 +102,9 @@ QFilePrivate::openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handl Q_UNUSED(fh); return false; #else - delete fileEngine; - fileEngine = nullptr; - QFSFileEngine *fe = new QFSFileEngine; - fileEngine = fe; + auto fs = qt_make_unique(); + auto fe = fs.get(); + fileEngine = std::move(fs); return fe->open(QIODevice::OpenMode(flags), fh, handleFlags); #endif } @@ -112,8 +112,8 @@ QFilePrivate::openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handl QAbstractFileEngine *QFilePrivate::engine() const { if (!fileEngine) - fileEngine = QAbstractFileEngine::create(fileName); - return fileEngine; + fileEngine.reset(QAbstractFileEngine::create(fileName)); + return fileEngine.get(); } //************* QFile @@ -334,10 +334,7 @@ QFile::setFileName(const QString &name) file_already_open(*this, "setFileName"); close(); } - if(d->fileEngine) { //get a new file engine later - delete d->fileEngine; - d->fileEngine = nullptr; - } + d->fileEngine.reset(); //get a new file engine later d->fileName = name; } diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index 2f74547054e..ee619d99cc2 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -42,6 +42,8 @@ #include "qfiledevice_p.h" #include "qfsfileengine_p.h" +#include + #ifdef QT_NO_QOBJECT #define tr(X) QString::fromLatin1(X) #endif @@ -53,24 +55,20 @@ QT_BEGIN_NAMESPACE #endif QFileDevicePrivate::QFileDevicePrivate() - : fileEngine(nullptr), - cachedSize(0), + : cachedSize(0), error(QFile::NoError), lastWasWrite(false) { writeBufferChunkSize = QFILE_WRITEBUFFER_SIZE; } QFileDevicePrivate::~QFileDevicePrivate() -{ - delete fileEngine; - fileEngine = nullptr; -} + = default; QAbstractFileEngine * QFileDevicePrivate::engine() const { if (!fileEngine) - fileEngine = new QFSFileEngine; - return fileEngine; + fileEngine = qt_make_unique(); + return fileEngine.get(); } void QFileDevicePrivate::setError(QFileDevice::FileError err) diff --git a/src/corelib/io/qfiledevice_p.h b/src/corelib/io/qfiledevice_p.h index 47053d01b71..aef3fca811b 100644 --- a/src/corelib/io/qfiledevice_p.h +++ b/src/corelib/io/qfiledevice_p.h @@ -53,6 +53,8 @@ #include "private/qiodevice_p.h" +#include + QT_BEGIN_NAMESPACE class QAbstractFileEngine; @@ -75,7 +77,7 @@ protected: void setError(QFileDevice::FileError err, const QString &errorString); void setError(QFileDevice::FileError err, int errNum); - mutable QAbstractFileEngine *fileEngine; + mutable std::unique_ptr fileEngine; mutable qint64 cachedSize; QFileDevice::FileHandleFlags handleFlags; diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index f5b398feaec..a5a3bc8b3ef 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -707,11 +707,11 @@ bool QFileInfo::exists(const QString &file) return false; QFileSystemEntry entry(file); QFileSystemMetaData data; - QAbstractFileEngine *engine = - QFileSystemEngine::resolveEntryAndCreateLegacyEngine(entry, data); + std::unique_ptr engine + {QFileSystemEngine::resolveEntryAndCreateLegacyEngine(entry, data)}; // Expensive fallback to non-QFileSystemEngine implementation if (engine) - return QFileInfo(new QFileInfoPrivate(entry, data, engine)).exists(); + return QFileInfo(new QFileInfoPrivate(entry, data, std::move(engine))).exists(); QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute); return data.exists(); diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h index 36f440812f2..333ea70adc6 100644 --- a/src/corelib/io/qfileinfo_p.h +++ b/src/corelib/io/qfileinfo_p.h @@ -61,6 +61,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE class QFileInfoPrivate : public QSharedData @@ -126,10 +128,10 @@ public: metaData = QFileSystemMetaData(); } - inline QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data, QAbstractFileEngine *engine) + inline QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data, std::unique_ptr engine) : fileEntry(file), metaData(data), - fileEngine(engine), + fileEngine{std::move(engine)}, cachedFlags(0), #ifndef QT_NO_FSFILEENGINE isDefaultConstructed(false), @@ -163,7 +165,7 @@ public: QFileSystemEntry fileEntry; mutable QFileSystemMetaData metaData; - QScopedPointer const fileEngine; + std::unique_ptr const fileEngine; mutable QString fileNames[QAbstractFileEngine::NFileNames]; mutable QString fileOwners[2]; // QAbstractFileEngine::FileOwner: OwnerUser and OwnerGroup diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 066a7c3f01c..74865fe31f7 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -822,6 +822,8 @@ QString QFileSystemEngine::resolveUserName(uint userId) #endif if (pw) return QFile::decodeName(QByteArray(pw->pw_name)); +#else // Integrity || WASM + Q_UNUSED(userId); #endif return QString(); } @@ -859,6 +861,8 @@ QString QFileSystemEngine::resolveGroupName(uint groupId) #endif if (gr) return QFile::decodeName(QByteArray(gr->gr_name)); +#else // Integrity || WASM + Q_UNUSED(groupId); #endif return QString(); } diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp index 5ac7e13a2e7..2d09c277eb2 100644 --- a/src/corelib/io/qfilesystemiterator_unix.cpp +++ b/src/corelib/io/qfilesystemiterator_unix.cpp @@ -40,13 +40,54 @@ #include "qplatformdefs.h" #include "qfilesystemiterator_p.h" +#if QT_CONFIG(textcodec) +# include +# include +#endif + #ifndef QT_NO_FILESYSTEMITERATOR +#include + #include #include QT_BEGIN_NAMESPACE +static bool checkNameDecodable(const char *d_name, qsizetype len) +{ + // This function is called in a loop from advance() below, but the loop is + // usually run only once. + +#if QT_CONFIG(textcodec) + // We identify the codecs by their RFC 2978 MIBenum values. In this + // function: + // 3 US-ASCII (ANSI X3.4-1986) + // 4 Latin1 (ISO-8859-1) + // 106 UTF-8 + QTextCodec *codec = QTextCodec::codecForLocale(); +# ifdef QT_LOCALE_IS_UTF8 + int mibEnum = 106; +# else + int mibEnum = codec->mibEnum(); +# endif + if (Q_LIKELY(mibEnum == 106)) // UTF-8 + return QUtf8::isValidUtf8(d_name, len).isValidUtf8; + if (mibEnum == 3) // US-ASCII + return QtPrivate::isAscii(QLatin1String(d_name, len)); + if (mibEnum == 4) // Latin 1 + return true; + + // fall back to generic QTextCodec + QTextCodec::ConverterState cs(QTextCodec::IgnoreHeader); + codec->toUnicode(d_name, len, &cs); + return cs.invalidChars == 0 && cs.remainingChars == 0; +#else + // if we have no text codecs, then QString::fromLocal8Bit is fromLatin1 + return true; +#endif +} + QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters, const QStringList &nameFilters, QDirIterator::IteratorFlags flags) : nativePath(entry.nativeFilePath()) @@ -81,9 +122,9 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa dirEntry = QT_READDIR(dir); if (dirEntry) { - // process entries with correct UTF-8 names only - if (QFile::encodeName(QFile::decodeName(dirEntry->d_name)) == dirEntry->d_name) { - fileEntry = QFileSystemEntry(nativePath + QByteArray(dirEntry->d_name), QFileSystemEntry::FromNativePath()); + qsizetype len = strlen(dirEntry->d_name); + if (checkNameDecodable(dirEntry->d_name, len)) { + fileEntry = QFileSystemEntry(nativePath + QByteArray(dirEntry->d_name, len), QFileSystemEntry::FromNativePath()); metaData.fillFromDirEnt(*dirEntry); return true; } diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index 5fb5685f429..ca1f6cc359e 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -422,16 +422,27 @@ void QInotifyFileSystemWatcherEngine::readFromInotify() } } +template +typename Hash::const_iterator +find_last_in_equal_range(const Hash &c, const Key &key) +{ + // find c.equal_range(key).second - 1 without backwards iteration: + auto i = c.find(key); + const auto end = c.cend(); + if (i == end) + return end; + decltype(i) prev; + do { + prev = i; + ++i; + } while (i != end && i.key() == key); + return prev; +} + QString QInotifyFileSystemWatcherEngine::getPathFromID(int id) const { - QHash::const_iterator i = idToPath.find(id); - while (i != idToPath.constEnd() && i.key() == id) { - if ((i + 1) == idToPath.constEnd() || (i + 1).key() != id) { - return i.value(); - } - ++i; - } - return QString(); + auto i = find_last_in_equal_range(idToPath, id); + return i == idToPath.cend() ? QString() : i.value() ; } QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 0db27f3e250..0d73839f8dc 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -167,19 +167,21 @@ QFSFileEngine::QFSFileEngine(QFSFileEnginePrivate &dd) /*! \internal */ -bool QFSFileEngine::processOpenModeFlags(QIODevice::OpenMode *mode) +ProcessOpenModeResult processOpenModeFlags(QIODevice::OpenMode openMode) { - QIODevice::OpenMode &openMode = *mode; + ProcessOpenModeResult result; + result.ok = false; if ((openMode & QFile::NewOnly) && (openMode & QFile::ExistingOnly)) { qWarning("NewOnly and ExistingOnly are mutually exclusive"); - setError(QFile::OpenError, QLatin1String("NewOnly and ExistingOnly are mutually exclusive")); - return false; + result.error = QLatin1String("NewOnly and ExistingOnly are mutually exclusive"); + return result; } if ((openMode & QFile::ExistingOnly) && !(openMode & (QFile::ReadOnly | QFile::WriteOnly))) { qWarning("ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite"); - setError(QFile::OpenError, QLatin1String("ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite")); - return false; + result.error = QLatin1String( + "ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite"); + return result; } // Either Append or NewOnly implies WriteOnly @@ -190,7 +192,9 @@ bool QFSFileEngine::processOpenModeFlags(QIODevice::OpenMode *mode) if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append | QFile::NewOnly))) openMode |= QFile::Truncate; - return true; + result.ok = true; + result.openMode = openMode; + return result; } /*! @@ -234,16 +238,19 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode) return false; } - if (!processOpenModeFlags(&openMode)) + const ProcessOpenModeResult res = processOpenModeFlags(openMode); + if (!res.ok) { + setError(QFileDevice::OpenError, res.error); return false; + } - d->openMode = openMode; + d->openMode = res.openMode; d->lastFlushFailed = false; d->tried_stat = 0; d->fh = nullptr; d->fd = -1; - return d->nativeOpen(openMode); + return d->nativeOpen(d->openMode); } /*! @@ -262,17 +269,20 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHand Q_D(QFSFileEngine); - if (!processOpenModeFlags(&openMode)) + const ProcessOpenModeResult res = processOpenModeFlags(openMode); + if (!res.ok) { + setError(QFileDevice::OpenError, res.error); return false; + } - d->openMode = openMode; + d->openMode = res.openMode; d->lastFlushFailed = false; d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle); d->fileEntry.clear(); d->tried_stat = 0; d->fd = -1; - return d->openFh(openMode, fh); + return d->openFh(d->openMode, fh); } /*! @@ -321,10 +331,13 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandle { Q_D(QFSFileEngine); - if (!processOpenModeFlags(&openMode)) + const ProcessOpenModeResult res = processOpenModeFlags(openMode); + if (!res.ok) { + setError(QFileDevice::OpenError, res.error); return false; + } - d->openMode = openMode; + d->openMode = res.openMode; d->lastFlushFailed = false; d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle); d->fileEntry.clear(); @@ -332,7 +345,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandle d->fd = -1; d->tried_stat = 0; - return d->openFd(openMode, fd); + return d->openFd(d->openMode, fd); } diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 0f416f4886f..639c01571a8 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -61,6 +61,13 @@ QT_BEGIN_NAMESPACE +struct ProcessOpenModeResult { + bool ok; + QIODevice::OpenMode openMode; + QString error; +}; +Q_CORE_EXPORT ProcessOpenModeResult processOpenModeFlags(QIODevice::OpenMode mode); + class QFSFileEnginePrivate; class Q_CORE_EXPORT QFSFileEngine : public QAbstractFileEngine @@ -131,9 +138,6 @@ public: protected: QFSFileEngine(QFSFileEnginePrivate &dd); - -private: - inline bool processOpenModeFlags(QIODevice::OpenMode *mode); }; class Q_AUTOTEST_EXPORT QFSFileEnginePrivate : public QAbstractFileEnginePrivate diff --git a/src/corelib/io/qipaddress.cpp b/src/corelib/io/qipaddress.cpp index b3421fca8fd..ddc5b6607f6 100644 --- a/src/corelib/io/qipaddress.cpp +++ b/src/corelib/io/qipaddress.cpp @@ -312,7 +312,7 @@ void toString(QString &appendTo, const IPv6Address address) } } - const QChar colon = ushort(':'); + const QChar colon = u':'; if (zeroRunLength < 4) zeroRunOffset = -1; else if (zeroRunOffset == 0) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 0b964e6a21c..35ca2542f78 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -202,6 +202,7 @@ void QProcessEnvironmentPrivate::insert(const QProcessEnvironmentPrivate &other) vars.insert(it.key(), it.value()); #ifdef Q_OS_UNIX + const OrderedNameMapMutexLocker locker(this, &other); auto nit = other.nameMap.constBegin(); const auto nend = other.nameMap.constEnd(); for ( ; nit != nend; ++nit) @@ -275,7 +276,6 @@ bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const return true; if (d) { if (other.d) { - QProcessEnvironmentPrivate::OrderedMutexLocker locker(d, other.d); return d->vars == other.d->vars; } else { return isEmpty(); @@ -322,7 +322,6 @@ bool QProcessEnvironment::contains(const QString &name) const { if (!d) return false; - QProcessEnvironmentPrivate::MutexLocker locker(d); return d->vars.contains(d->prepareName(name)); } @@ -373,7 +372,6 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa if (!d) return defaultValue; - QProcessEnvironmentPrivate::MutexLocker locker(d); const auto it = d->vars.constFind(d->prepareName(name)); if (it == d->vars.constEnd()) return defaultValue; @@ -398,7 +396,6 @@ QStringList QProcessEnvironment::toStringList() const { if (!d) return QStringList(); - QProcessEnvironmentPrivate::MutexLocker locker(d); return d->toList(); } @@ -412,7 +409,6 @@ QStringList QProcessEnvironment::keys() const { if (!d) return QStringList(); - QProcessEnvironmentPrivate::MutexLocker locker(d); return d->keys(); } @@ -429,7 +425,6 @@ void QProcessEnvironment::insert(const QProcessEnvironment &e) return; // our re-impl of detach() detaches from null - QProcessEnvironmentPrivate::MutexLocker locker(e.d); d->insert(*e.d); } diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index d02e87837c4..2587530c095 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -146,16 +146,22 @@ public: inline QString nameToString(const Key &name) const { return name; } inline Value prepareValue(const QString &value) const { return value; } inline QString valueToString(const Value &value) const { return value; } - struct MutexLocker { - MutexLocker(const QProcessEnvironmentPrivate *) {} - }; - struct OrderedMutexLocker { - OrderedMutexLocker(const QProcessEnvironmentPrivate *, - const QProcessEnvironmentPrivate *) {} - }; #else + struct NameMapMutexLocker : public QMutexLocker + { + NameMapMutexLocker(const QProcessEnvironmentPrivate *d) : QMutexLocker(&d->nameMapMutex) {} + }; + struct OrderedNameMapMutexLocker : public QOrderedMutexLocker + { + OrderedNameMapMutexLocker(const QProcessEnvironmentPrivate *d1, + const QProcessEnvironmentPrivate *d2) + : QOrderedMutexLocker(&d1->nameMapMutex, &d2->nameMapMutex) + {} + }; + inline Key prepareName(const QString &name) const { + const NameMapMutexLocker locker(this); Key &ent = nameMap[name]; if (ent.isEmpty()) ent = name.toLocal8Bit(); @@ -164,40 +170,27 @@ public: inline QString nameToString(const Key &name) const { const QString sname = QString::fromLocal8Bit(name); - nameMap[sname] = name; + { + const NameMapMutexLocker locker(this); + nameMap[sname] = name; + } return sname; } inline Value prepareValue(const QString &value) const { return Value(value); } inline QString valueToString(const Value &value) const { return value.string(); } - struct MutexLocker : public QMutexLocker - { - MutexLocker(const QProcessEnvironmentPrivate *d) : QMutexLocker(&d->mutex) {} - }; - struct OrderedMutexLocker : public QOrderedMutexLocker - { - OrderedMutexLocker(const QProcessEnvironmentPrivate *d1, - const QProcessEnvironmentPrivate *d2) : - QOrderedMutexLocker(&d1->mutex, &d2->mutex) - {} - }; - QProcessEnvironmentPrivate() : QSharedData() {} QProcessEnvironmentPrivate(const QProcessEnvironmentPrivate &other) : - QSharedData() + QSharedData(), vars(other.vars) { - // This being locked ensures that the functions that only assign - // d pointers don't need explicit locking. // We don't need to lock our own mutex, as this object is new and // consequently not shared. For the same reason, non-const methods // do not need a lock, as they detach objects (however, we need to // ensure that they really detach before using prepareName()). - MutexLocker locker(&other); - vars = other.vars; + NameMapMutexLocker locker(&other); nameMap = other.nameMap; - // We need to detach our members, so that our mutex can protect them. - // As we are being detached, they likely would be detached a moment later anyway. - vars.detach(); + // We need to detach our nameMap, so that our mutex can protect it. + // As we are being detached, it likely would be detached a moment later anyway. nameMap.detach(); } #endif @@ -208,8 +201,7 @@ public: #ifdef Q_OS_UNIX typedef QHash NameHash; mutable NameHash nameMap; - - mutable QMutex mutex; + mutable QMutex nameMapMutex; #endif static QProcessEnvironment fromList(const QStringList &list); diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 1d5b76a8a49..951fc4ccaa7 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -438,7 +438,6 @@ void QProcessPrivate::startProcess() int envc = 0; char **envp = 0; if (environment.d.constData()) { - QProcessEnvironmentPrivate::MutexLocker locker(environment.d); envp = _q_dupEnvironment(environment.d.constData()->vars, &envc); } @@ -970,7 +969,6 @@ bool QProcessPrivate::startDetached(qint64 *pid) int envc = 0; char **envp = nullptr; if (environment.d.constData()) { - QProcessEnvironmentPrivate::MutexLocker locker(environment.d); envp = _q_dupEnvironment(environment.d.constData()->vars, &envc); } diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index fcc5b69179b..52b746d04a2 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. -** Copyright (C) 2018 Intel Corporation. +** Copyright (C) 2019 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -279,14 +279,14 @@ static inline QStringList *resourceSearchPaths() This enum is used by compressionAlgorithm() to indicate which algorithm the RCC tool used to compress the payload. - \value NoCompression Contents are not compressed (isCompressed() is false). + \value NoCompression Contents are not compressed \value ZlibCompression Contents are compressed using \l{zlib}{https://zlib.net} and can be decompressed using the qUncompress() function. \value ZstdCompression Contents are compressed using \l{zstd}{https://zstd.net}. To decompress, use the \c{ZSTD_decompress} function from the zstd library. - \sa compressionAlgorithm(), isCompressed() + \sa compressionAlgorithm() */ class QResourcePrivate { @@ -551,13 +551,20 @@ bool QResource::isValid() const \sa isDir() */ - +#if QT_DEPRECATED_SINCE(5, 13) /*! + \obsolete + Returns \c true if the resource represents a file and the data backing it is in a compressed format, false otherwise. If the data is compressed, check compressionAlgorithm() to verify what algorithm to use to decompress the data. + \note This function is deprecated and can be replaced with + \code + compressionAlgorithm() != NoCompression + \endcode + \sa data(), compressionAlgorithm(), isFile() */ @@ -565,6 +572,7 @@ bool QResource::isCompressed() const { return compressionAlgorithm() != NoCompression; } +#endif /*! \since 5.13 @@ -582,7 +590,7 @@ bool QResource::isCompressed() const See \l{http://facebook.github.io/zstd/zstd_manual.html}{Zstandard manual}. - \sa isCompressed(), data(), isFile() + \sa data(), isFile() */ QResource::Compression QResource::compressionAlgorithm() const { @@ -606,11 +614,11 @@ qint64 QResource::size() const /*! Returns direct access to a read only segment of data that this resource - represents. If the resource is compressed the data returns is - compressed and qUncompress() must be used to access the data. If the - resource is a directory \nullptr is returned. + represents. If the resource is compressed the data returned is compressed + and the appropriate library functions must be used to access the data. If + the resource is a directory \nullptr is returned. - \sa size(), isCompressed(), isFile() + \sa size(), compressionAlgorithm(), isFile() */ const uchar *QResource::data() const @@ -940,12 +948,15 @@ bool QResourceRoot::mappingRootSubdir(const QString &path, QString *match) const Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree, const unsigned char *name, const unsigned char *data) { + if (resourceGlobalData.isDestroyed()) + return false; QMutexLocker lock(resourceMutex()); - if (version >= 0x01 && version <= 0x3 && resourceList()) { + ResourceList *list = resourceList(); + if (version >= 0x01 && version <= 0x3) { bool found = false; QResourceRoot res(version, tree, name, data); - for(int i = 0; i < resourceList()->size(); ++i) { - if(*resourceList()->at(i) == res) { + for (int i = 0; i < list->size(); ++i) { + if (*list->at(i) == res) { found = true; break; } @@ -953,7 +964,7 @@ Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree, if(!found) { QResourceRoot *root = new QResourceRoot(version, tree, name, data); root->ref.ref(); - resourceList()->append(root); + list->append(root); } return true; } @@ -967,11 +978,12 @@ Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tre return false; QMutexLocker lock(resourceMutex()); - if (version >= 0x01 && version <= 0x3 && resourceList()) { + if (version >= 0x01 && version <= 0x3) { QResourceRoot res(version, tree, name, data); - for(int i = 0; i < resourceList()->size(); ) { - if(*resourceList()->at(i) == res) { - QResourceRoot *root = resourceList()->takeAt(i); + ResourceList *list = resourceList(); + for (int i = 0; i < list->size(); ) { + if (*list->at(i) == res) { + QResourceRoot *root = list->takeAt(i); if(!root->ref.deref()) delete root; } else { @@ -1217,7 +1229,7 @@ QResource::unregisterResource(const QString &rccFilename, const QString &resourc if(res->type() == QResourceRoot::Resource_File) { QDynamicFileResourceRoot *root = reinterpret_cast(res); if (root->mappingFile() == rccFilename && root->mappingRoot() == r) { - resourceList()->removeAt(i); + list->removeAt(i); if(!root->ref.deref()) { delete root; return true; @@ -1288,7 +1300,7 @@ QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot) if(res->type() == QResourceRoot::Resource_Buffer) { QDynamicBufferResourceRoot *root = reinterpret_cast(res); if (root->mappingBuffer() == rccData && root->mappingRoot() == r) { - resourceList()->removeAt(i); + list->removeAt(i); if(!root->ref.deref()) { delete root; return true; @@ -1366,9 +1378,15 @@ bool QResourceFileEngine::open(QIODevice::OpenMode flags) qWarning("QResourceFileEngine::open: Missing file name"); return false; } - if(flags & QIODevice::WriteOnly) + if (flags & QIODevice::WriteOnly) return false; - d->uncompress(); + if (d->resource.compressionAlgorithm() != QResource::NoCompression) { + d->uncompress(); + if (d->uncompressed.isNull()) { + d->errorString = QSystemError::stdString(EIO); + return false; + } + } if (!d->resource.isValid()) { d->errorString = QSystemError::stdString(ENOENT); return false; @@ -1395,7 +1413,7 @@ qint64 QResourceFileEngine::read(char *data, qint64 len) len = size()-d->offset; if(len <= 0) return 0; - if(d->resource.isCompressed()) + if (!d->uncompressed.isNull()) memcpy(data, d->uncompressed.constData()+d->offset, len); else memcpy(data, d->resource.data()+d->offset, len); @@ -1431,9 +1449,9 @@ bool QResourceFileEngine::link(const QString &) qint64 QResourceFileEngine::size() const { Q_D(const QResourceFileEngine); - if(!d->resource.isValid()) + if (!d->resource.isValid()) return 0; - if (d->resource.isCompressed()) { + if (d->resource.compressionAlgorithm() != QResource::NoCompression) { d->uncompress(); return d->uncompressed.size(); } @@ -1596,7 +1614,7 @@ uchar *QResourceFileEnginePrivate::map(qint64 offset, qint64 size, QFile::Memory Q_UNUSED(flags); qint64 max = resource.size(); - if (resource.isCompressed()) { + if (resource.compressionAlgorithm() != QResource::NoCompression) { uncompress(); max = uncompressed.size(); } @@ -1609,7 +1627,7 @@ uchar *QResourceFileEnginePrivate::map(qint64 offset, qint64 size, QFile::Memory } const uchar *address = resource.data(); - if (resource.isCompressed()) + if (resource.compressionAlgorithm() != QResource::NoCompression) address = reinterpret_cast(uncompressed.constData()); return const_cast(address) + offset; diff --git a/src/corelib/io/qresource.h b/src/corelib/io/qresource.h index 5e798de436a..5ee8d5d266a 100644 --- a/src/corelib/io/qresource.h +++ b/src/corelib/io/qresource.h @@ -72,7 +72,6 @@ public: bool isValid() const; - bool isCompressed() const; Compression compressionAlgorithm() const; qint64 size() const; const uchar *data() const; @@ -84,6 +83,10 @@ public: QT_DEPRECATED_X("Use QDir::searchPaths() instead") static QStringList searchPaths(); #endif +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED_VERSION_X_5_15("Use QResource::compressionAlgorithm() instead") + bool isCompressed() const; +#endif static bool registerResource(const QString &rccFilename, const QString &resourceRoot=QString()); static bool unregisterResource(const QString &rccFilename, const QString &resourceRoot=QString()); diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp index 915d0a0a003..f41e6302a29 100644 --- a/src/corelib/io/qsavefile.cpp +++ b/src/corelib/io/qsavefile.cpp @@ -150,8 +150,7 @@ QSaveFile::~QSaveFile() QFileDevice::close(); if (d->fileEngine) { d->fileEngine->remove(); - delete d->fileEngine; - d->fileEngine = nullptr; + d->fileEngine.reset(); } } @@ -197,6 +196,7 @@ bool QSaveFile::open(OpenMode mode) return false; } unsetError(); + d->writeError = QFileDevice::NoError; if ((mode & (ReadOnly | WriteOnly)) == 0) { qWarning("QSaveFile::open: Open mode not specified"); return false; @@ -234,7 +234,7 @@ bool QSaveFile::open(OpenMode mode) } auto openDirectly = [&]() { - d->fileEngine = QAbstractFileEngine::create(d->finalFileName); + d->fileEngine.reset(QAbstractFileEngine::create(d->finalFileName)); if (d->fileEngine->open(mode | QIODevice::Unbuffered)) { d->useTemporaryFile = false; QFileDevice::open(mode); @@ -251,8 +251,7 @@ bool QSaveFile::open(OpenMode mode) if (openDirectly()) return true; d->setError(d->fileEngine->error(), d->fileEngine->errorString()); - delete d->fileEngine; - d->fileEngine = nullptr; + d->fileEngine.reset(); } else { QString msg = QSaveFile::tr("QSaveFile cannot open '%1' without direct write fallback " @@ -264,18 +263,17 @@ bool QSaveFile::open(OpenMode mode) } #endif - d->fileEngine = new QTemporaryFileEngine(&d->finalFileName, QTemporaryFileEngine::Win32NonShared); + d->fileEngine.reset(new QTemporaryFileEngine(&d->finalFileName, QTemporaryFileEngine::Win32NonShared)); // if the target file exists, we'll copy its permissions below, // but until then, let's ensure the temporary file is not accessible // to a third party int perm = (existingFile.exists() ? 0600 : 0666); - static_cast(d->fileEngine)->initialize(d->finalFileName, perm); + static_cast(d->fileEngine.get())->initialize(d->finalFileName, perm); // Same as in QFile: QIODevice provides the buffering, so there's no need to request it from the file engine. if (!d->fileEngine->open(mode | QIODevice::Unbuffered)) { QFileDevice::FileError err = d->fileEngine->error(); #ifdef Q_OS_UNIX if (d->directWriteFallback && err == QFileDevice::OpenError && errno == EACCES) { - delete d->fileEngine; if (openDirectly()) return true; err = d->fileEngine->error(); @@ -284,8 +282,7 @@ bool QSaveFile::open(OpenMode mode) if (err == QFileDevice::UnspecifiedError) err = QFileDevice::OpenError; d->setError(err, d->fileEngine->errorString()); - delete d->fileEngine; - d->fileEngine = nullptr; + d->fileEngine.reset(); return false; } @@ -331,30 +328,26 @@ bool QSaveFile::commit() } QFileDevice::close(); // calls flush() + const auto fe = std::move(d->fileEngine); + // Sync to disk if possible. Ignore errors (e.g. not supported). - d->fileEngine->syncToDisk(); + fe->syncToDisk(); if (d->useTemporaryFile) { if (d->writeError != QFileDevice::NoError) { - d->fileEngine->remove(); + fe->remove(); d->writeError = QFileDevice::NoError; - delete d->fileEngine; - d->fileEngine = nullptr; return false; } // atomically replace old file with new file // Can't use QFile::rename for that, must use the file engine directly - Q_ASSERT(d->fileEngine); - if (!d->fileEngine->renameOverwrite(d->finalFileName)) { - d->setError(d->fileEngine->error(), d->fileEngine->errorString()); - d->fileEngine->remove(); - delete d->fileEngine; - d->fileEngine = nullptr; + Q_ASSERT(fe); + if (!fe->renameOverwrite(d->finalFileName)) { + d->setError(fe->error(), fe->errorString()); + fe->remove(); return false; } } - delete d->fileEngine; - d->fileEngine = nullptr; return true; } diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index dbf650d5f60..f56fef7f8e1 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -297,7 +297,7 @@ QT_BEGIN_NAMESPACE \li "/tmp" \row \li HomeLocation \li "/files" - \li "" (not writable) + \li system defined \row \li DataLocation \li "/files", "//files" \li "/Library/Application Support" diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index f4f87879689..6425890e3f8 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -71,6 +71,28 @@ static void appendOrganizationAndApp(QString &path) #endif } +#if QT_CONFIG(regularexpression) +static QLatin1String xdg_key_name(QStandardPaths::StandardLocation type) +{ + switch (type) { + case QStandardPaths::DesktopLocation: + return QLatin1String("DESKTOP"); + case QStandardPaths::DocumentsLocation: + return QLatin1String("DOCUMENTS"); + case QStandardPaths::PicturesLocation: + return QLatin1String("PICTURES"); + case QStandardPaths::MusicLocation: + return QLatin1String("MUSIC"); + case QStandardPaths::MoviesLocation: + return QLatin1String("VIDEOS"); + case QStandardPaths::DownloadLocation: + return QLatin1String("DOWNLOAD"); + default: + return QLatin1String(); + } +} +#endif + QString QStandardPaths::writableLocation(StandardLocation type) { switch (type) { @@ -182,61 +204,32 @@ QString QStandardPaths::writableLocation(StandardLocation type) if (xdgConfigHome.isEmpty()) xdgConfigHome = QDir::homePath() + QLatin1String("/.config"); QFile file(xdgConfigHome + QLatin1String("/user-dirs.dirs")); - if (!isTestModeEnabled() && file.open(QIODevice::ReadOnly)) { - QHash lines; + const QLatin1String key = xdg_key_name(type); + if (!key.isEmpty() && !isTestModeEnabled() && file.open(QIODevice::ReadOnly)) { QTextStream stream(&file); // Only look for lines like: XDG_DESKTOP_DIR="$HOME/Desktop" QRegularExpression exp(QLatin1String("^XDG_(.*)_DIR=(.*)$")); + QString result; while (!stream.atEnd()) { const QString &line = stream.readLine(); QRegularExpressionMatch match = exp.match(line); - if (match.hasMatch()) { - const QStringList lst = match.capturedTexts(); - const QString key = lst.at(1); - QString value = lst.at(2); + if (match.hasMatch() && match.capturedView(1) == key) { + QStringView value = match.capturedView(2); if (value.length() > 2 && value.startsWith(QLatin1Char('\"')) && value.endsWith(QLatin1Char('\"'))) value = value.mid(1, value.length() - 2); - // Store the key and value: "DESKTOP", "$HOME/Desktop" - lines[key] = value; - } - } - - QString key; - switch (type) { - case DesktopLocation: - key = QLatin1String("DESKTOP"); - break; - case DocumentsLocation: - key = QLatin1String("DOCUMENTS"); - break; - case PicturesLocation: - key = QLatin1String("PICTURES"); - break; - case MusicLocation: - key = QLatin1String("MUSIC"); - break; - case MoviesLocation: - key = QLatin1String("VIDEOS"); - break; - case DownloadLocation: - key = QLatin1String("DOWNLOAD"); - break; - default: - break; - } - if (!key.isEmpty()) { - QString value = lines.value(key); - if (!value.isEmpty()) { // value can start with $HOME if (value.startsWith(QLatin1String("$HOME"))) - value = QDir::homePath() + value.midRef(5); - if (value.length() > 1 && value.endsWith(QLatin1Char('/'))) - value.chop(1); - return value; + result = QDir::homePath() + value.mid(5); + else + result = value.toString(); + if (result.length() > 1 && result.endsWith(QLatin1Char('/'))) + result.chop(1); } } + if (!result.isNull()) + return result; } #endif // QT_CONFIG(regularexpression) diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 4669c20711a..1e72241e685 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -468,8 +468,18 @@ inline bool QStorageIterator::next() size_t len = strlen(buffer.data()); if (len == 0) return false; - if (ptr[len - 1] == '\n') - ptr[len - 1] = '\0'; + while (Q_UNLIKELY(ptr[len - 1] != '\n' && !feof(fp))) { + // buffer wasn't large enough. Enlarge and try again. + // (we're readidng from the kernel, so OOM is unlikely) + buffer.resize((buffer.size() + 4096) & ~4095); + ptr = buffer.data(); + if (fgets(ptr + len, buffer.size() - len, fp) == nullptr) + return false; + + len += strlen(ptr + len); + Q_ASSERT(len < size_t(buffer.size())); + } + ptr[len - 1] = '\0'; // parse the line bool ok; diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index c89ad06a1f2..acd31f4d84a 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -544,10 +544,10 @@ QTemporaryFilePrivate::~QTemporaryFilePrivate() QAbstractFileEngine *QTemporaryFilePrivate::engine() const { if (!fileEngine) { - fileEngine = new QTemporaryFileEngine(&templateName); + fileEngine.reset(new QTemporaryFileEngine(&templateName)); resetFileEngine(); } - return fileEngine; + return fileEngine.get(); } void QTemporaryFilePrivate::resetFileEngine() const @@ -555,7 +555,7 @@ void QTemporaryFilePrivate::resetFileEngine() const if (!fileEngine) return; - QTemporaryFileEngine *tef = static_cast(fileEngine); + QTemporaryFileEngine *tef = static_cast(fileEngine.get()); if (fileName.isEmpty()) tef->initialize(templateName, 0600); else @@ -568,7 +568,7 @@ void QTemporaryFilePrivate::materializeUnnamedFile() if (!fileName.isEmpty() || !fileEngine) return; - auto *tef = static_cast(fileEngine); + auto *tef = static_cast(fileEngine.get()); fileName = tef->fileName(QAbstractFileEngine::DefaultName); #endif } @@ -792,7 +792,7 @@ void QTemporaryFile::setAutoRemove(bool b) QString QTemporaryFile::fileName() const { Q_D(const QTemporaryFile); - auto tef = static_cast(d->fileEngine); + auto tef = static_cast(d->fileEngine.get()); if (tef && tef->isReallyOpen()) const_cast(d)->materializeUnnamedFile(); @@ -841,7 +841,7 @@ void QTemporaryFile::setFileTemplate(const QString &name) bool QTemporaryFile::rename(const QString &newName) { Q_D(QTemporaryFile); - auto tef = static_cast(d->fileEngine); + auto tef = static_cast(d->fileEngine.get()); if (!tef || !tef->isReallyOpen() || !tef->filePathWasTemplate) return QFile::rename(newName); @@ -947,7 +947,7 @@ QTemporaryFile *QTemporaryFile::createNativeFile(QFile &file) bool QTemporaryFile::open(OpenMode flags) { Q_D(QTemporaryFile); - auto tef = static_cast(d->fileEngine); + auto tef = static_cast(d->fileEngine.get()); if (tef && tef->isReallyOpen()) { setOpenMode(flags); return true; @@ -961,7 +961,7 @@ bool QTemporaryFile::open(OpenMode flags) d->resetFileEngine(); if (QFile::open(flags)) { - tef = static_cast(d->fileEngine); + tef = static_cast(d->fileEngine.get()); if (tef->isUnnamedFile()) d->fileName.clear(); else diff --git a/src/corelib/io/qtldurl.cpp b/src/corelib/io/qtldurl.cpp index a934d19fa26..912609ec91b 100644 --- a/src/corelib/io/qtldurl.cpp +++ b/src/corelib/io/qtldurl.cpp @@ -59,9 +59,9 @@ enum TLDMatchType { static bool containsTLDEntry(QStringView entry, TLDMatchType match) { const QStringView matchSymbols[] = { - QStringViewLiteral(""), - QStringViewLiteral("*"), - QStringViewLiteral("!"), + u"", + u"*", + u"!", }; const auto symbol = matchSymbols[match]; int index = qt_hash(entry, qt_hash(symbol)) % tldCount; diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index d9ebc6c750c..878e007fb0d 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -1010,7 +1010,7 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro for (int i = needsLowercasing; i >= 0; --i) { ushort c = schemeData[i].unicode(); if (c >= 'A' && c <= 'Z') - schemeData[i] = c + 0x20; + schemeData[i] = QChar(c + 0x20); } } diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp index 2f89d226600..a2f0caa6065 100644 --- a/src/corelib/io/qurlidna.cpp +++ b/src/corelib/io/qurlidna.cpp @@ -2220,9 +2220,8 @@ Q_AUTOTEST_EXPORT void qt_punycodeEncoder(const QChar *s, int ucLength, QString bool skipped = false; // copy all basic code points verbatim to output. for (uint j = 0; j < (uint) ucLength; ++j) { - ushort js = s[j].unicode(); - if (js < 0x80) - *d++ = js; + if (s[j].unicode() < 0x80) + *d++ = s[j]; else skipped = true; } diff --git a/src/corelib/io/qurlquery.cpp b/src/corelib/io/qurlquery.cpp index 36a2880bf16..8d80a2d8bdb 100644 --- a/src/corelib/io/qurlquery.cpp +++ b/src/corelib/io/qurlquery.cpp @@ -146,7 +146,7 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QUrlQuery(std::initializer_list> list) + \fn QUrlQuery::QUrlQuery(std::initializer_list> list) \since 5.13 @@ -293,9 +293,9 @@ void QUrlQueryPrivate::setQuery(const QString &query) const QChar *delimiter = nullptr; while (pos != end) { // scan for the component parts of this pair - if (!delimiter && pos->unicode() == valueDelimiter) + if (!delimiter && *pos == valueDelimiter) delimiter = pos; - if (pos->unicode() == pairDelimiter) + if (*pos == pairDelimiter) break; ++pos; } @@ -584,8 +584,8 @@ QString QUrlQuery::query(QUrl::ComponentFormattingOptions encoding) const */ void QUrlQuery::setQueryDelimiters(QChar valueDelimiter, QChar pairDelimiter) { - d->valueDelimiter = valueDelimiter.unicode(); - d->pairDelimiter = pairDelimiter.unicode(); + d->valueDelimiter = valueDelimiter; + d->pairDelimiter = pairDelimiter; } /*! diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index 2eacb3cc94f..e19d9479f8c 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -532,21 +532,16 @@ void QAbstractItemModelPrivate::invalidatePersistentIndex(const QModelIndex &ind } } -namespace { - struct DefaultRoleNames : public QHash +using DefaultRoleNames = QHash; +Q_GLOBAL_STATIC_WITH_ARGS(DefaultRoleNames, qDefaultRoleNames, ( { - DefaultRoleNames() { - (*this)[Qt::DisplayRole] = "display"; - (*this)[Qt::DecorationRole] = "decoration"; - (*this)[Qt::EditRole] = "edit"; - (*this)[Qt::ToolTipRole] = "toolTip"; - (*this)[Qt::StatusTipRole] = "statusTip"; - (*this)[Qt::WhatsThisRole] = "whatsThis"; - } - }; -} - -Q_GLOBAL_STATIC(DefaultRoleNames, qDefaultRoleNames) + { Qt::DisplayRole, "display" }, + { Qt::DecorationRole, "decoration" }, + { Qt::EditRole, "edit" }, + { Qt::ToolTipRole, "toolTip" }, + { Qt::StatusTipRole, "statusTip" }, + { Qt::WhatsThisRole, "whatsThis" }, + })) const QHash &QAbstractItemModelPrivate::defaultRoleNames() { diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index d13e6199dbc..675bf4b8c3a 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -64,11 +64,7 @@ struct QSortFilterProxyModelDataChanged static inline QSet qVectorToSet(const QVector &vector) { - QSet set; - set.reserve(vector.size()); - for(int i=0; i < vector.size(); ++i) - set << vector.at(i); - return set; + return {vector.begin(), vector.end()}; } class QSortFilterProxyModelLessThan @@ -130,7 +126,7 @@ struct QRowsRemoval { } - bool contains(QModelIndex parent, int row) + bool contains(QModelIndex parent, int row) const { do { if (parent == parent_source) @@ -470,8 +466,8 @@ bool QSortFilterProxyModelPrivate::filterRecursiveAcceptsRow(int source_row, con void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source_parent) { if (Mapping *m = source_index_mapping.take(source_parent)) { - for (int i = 0; i < m->mapped_children.size(); ++i) - remove_from_mapping(m->mapped_children.at(i)); + for (const QModelIndex &mappedIdx : qAsConst(m->mapped_children)) + remove_from_mapping(mappedIdx); delete m; } } @@ -607,9 +603,9 @@ void QSortFilterProxyModelPrivate::sort() Q_Q(QSortFilterProxyModel); emit q->layoutAboutToBeChanged(QList(), QAbstractItemModel::VerticalSortHint); QModelIndexPairList source_indexes = store_persistent_indexes(); - IndexMap::const_iterator it = source_index_mapping.constBegin(); - for (; it != source_index_mapping.constEnd(); ++it) { - QModelIndex source_parent = it.key(); + const auto end = source_index_mapping.constEnd(); + for (auto it = source_index_mapping.constBegin(); it != end; ++it) { + const QModelIndex &source_parent = it.key(); Mapping *m = it.value(); sort_source_rows(m->source_rows, source_parent); build_source_to_proxy_mapping(m->source_rows, m->proxy_rows); @@ -735,13 +731,14 @@ void QSortFilterProxyModelPrivate::remove_source_items( if (!proxy_parent.isValid() && source_parent.isValid()) return; // nothing to do (already removed) - QVector > proxy_intervals; - proxy_intervals = proxy_intervals_for_source_items(source_to_proxy, source_items); + const auto proxy_intervals = proxy_intervals_for_source_items( + source_to_proxy, source_items); - for (int i = proxy_intervals.size()-1; i >= 0; --i) { - QPair interval = proxy_intervals.at(i); - int proxy_start = interval.first; - int proxy_end = interval.second; + const auto end = proxy_intervals.rend(); + for (auto it = proxy_intervals.rbegin(); it != end; ++it) { + const QPair &interval = *it; + const int proxy_start = interval.first; + const int proxy_end = interval.second; remove_proxy_interval(source_to_proxy, proxy_to_source, proxy_start, proxy_end, proxy_parent, orient, emit_signal); } @@ -875,15 +872,15 @@ void QSortFilterProxyModelPrivate::insert_source_items( if (!proxy_parent.isValid() && source_parent.isValid()) return; // nothing to do (source_parent is not mapped) - QVector > > proxy_intervals; - proxy_intervals = proxy_intervals_for_source_items_to_add( + const auto proxy_intervals = proxy_intervals_for_source_items_to_add( proxy_to_source, source_items, source_parent, orient); - for (int i = proxy_intervals.size()-1; i >= 0; --i) { - QPair > interval = proxy_intervals.at(i); - int proxy_start = interval.first; - QVector source_items = interval.second; - int proxy_end = proxy_start + source_items.size() - 1; + const auto end = proxy_intervals.rend(); + for (auto it = proxy_intervals.rbegin(); it != end; ++it) { + const QPair > &interval = *it; + const int proxy_start = interval.first; + const QVector &source_items = interval.second; + const int proxy_end = proxy_start + source_items.size() - 1; if (emit_signal) { if (orient == Qt::Vertical) @@ -1195,8 +1192,8 @@ QModelIndexPairList QSortFilterProxyModelPrivate::store_persistent_indexes() con Q_Q(const QSortFilterProxyModel); QModelIndexPairList source_indexes; source_indexes.reserve(persistent.indexes.count()); - for (QPersistentModelIndexData *data : qAsConst(persistent.indexes)) { - QModelIndex proxy_index = data->index; + for (const QPersistentModelIndexData *data : qAsConst(persistent.indexes)) { + const QModelIndex &proxy_index = data->index; QModelIndex source_index = q->mapToSource(proxy_index); source_indexes.append(qMakePair(proxy_index, QPersistentModelIndex(source_index))); } @@ -1217,9 +1214,9 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes( const int numSourceIndexes = source_indexes.count(); from.reserve(numSourceIndexes); to.reserve(numSourceIndexes); - for (int i = 0; i < numSourceIndexes; ++i) { - QModelIndex source_index = source_indexes.at(i).second; - QModelIndex old_proxy_index = source_indexes.at(i).first; + for (const auto &indexPair : source_indexes) { + const QPersistentModelIndex &source_index = indexPair.second; + const QModelIndex &old_proxy_index = indexPair.first; create_mapping(source_index.parent()); QModelIndex proxy_index = q->mapFromSource(source_index); from << old_proxy_index; @@ -1264,7 +1261,7 @@ void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_pare const QVector mappedChildren = m->mapped_children; QVector indexesToRemove; for (int i = 0; i < mappedChildren.size(); ++i) { - const QModelIndex source_child_index = mappedChildren.at(i); + const QModelIndex &source_child_index = mappedChildren.at(i); if (rows_removed.contains(source_child_index.row()) || columns_removed.contains(source_child_index.column())) { indexesToRemove.push_back(i); remove_from_mapping(source_child_index); @@ -2296,10 +2293,9 @@ QMimeData *QSortFilterProxyModel::mimeData(const QModelIndexList &indexes) const { Q_D(const QSortFilterProxyModel); QModelIndexList source_indexes; - const int numIndexes = indexes.count(); - source_indexes.reserve(numIndexes); - for (int i = 0; i < numIndexes; ++i) - source_indexes << mapToSource(indexes.at(i)); + source_indexes.reserve(indexes.count()); + for (const QModelIndex &idx : indexes) + source_indexes << mapToSource(idx); return d->model->mimeData(source_indexes); } diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 15b69acbd43..9e9e71c3972 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -514,10 +514,9 @@ Q_CONSTRUCTOR_FUNCTION(qt_apple_check_os_version); // ------------------------------------------------------------------------- -void QMacKeyValueObserver::addObserver() +void QMacKeyValueObserver::addObserver(NSKeyValueObservingOptions options) { - [object addObserver:observer forKeyPath:keyPath - options:NSKeyValueObservingOptionNew context:callback.get()]; + [object addObserver:observer forKeyPath:keyPath options:options context:callback.get()]; } void QMacKeyValueObserver::removeObserver() { diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 0e1a5fe345e..447dcd9cbe8 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -350,8 +350,12 @@ public: QMacKeyValueObserver() {} // Note: QMacKeyValueObserver must not outlive the object observed! - QMacKeyValueObserver(id object, NSString *keyPath, Callback callback) - : object(object), keyPath(keyPath), callback(new Callback(callback)) { addObserver(); } + QMacKeyValueObserver(id object, NSString *keyPath, Callback callback, + NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew) + : object(object), keyPath(keyPath), callback(new Callback(callback)) + { + addObserver(options); + } QMacKeyValueObserver(const QMacKeyValueObserver &other) : QMacKeyValueObserver(other.object, other.keyPath, *other.callback.get()) {} @@ -381,7 +385,7 @@ private: std::swap(first.callback, second.callback); } - void addObserver(); + void addObserver(NSKeyValueObservingOptions options); id object = nil; NSString *keyPath = nullptr; diff --git a/src/corelib/kernel/qeventdispatcher_winrt_p.h b/src/corelib/kernel/qeventdispatcher_winrt_p.h index 8b998a7958c..2672f111236 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt_p.h +++ b/src/corelib/kernel/qeventdispatcher_winrt_p.h @@ -57,7 +57,7 @@ #include -namespace std { template class function; } +#include QT_BEGIN_NAMESPACE diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 56217262f27..acb1f54bdf3 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -953,7 +953,7 @@ static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, co return self; if (self->d.relatedMetaObjects) { Q_ASSERT(priv(self->d.data)->revision >= 2); - const QMetaObject * const *e = self->d.relatedMetaObjects; + const auto *e = self->d.relatedMetaObjects; if (e) { while (*e) { if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name)) diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index d2030f0275b..f77c4ce32fd 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -747,7 +747,7 @@ void QMetaObjectBuilder::addMetaObject if ((members & RelatedMetaObjects) != 0) { Q_ASSERT(priv(prototype->d.data)->revision >= 2); - const QMetaObject * const *objects = prototype->d.relatedMetaObjects; + const auto *objects = prototype->d.relatedMetaObjects; if (objects) { while (*objects != 0) { addRelatedMetaObject(*objects); @@ -1464,16 +1464,16 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, // Create the relatedMetaObjects block if we need one. if (d->relatedMetaObjects.size() > 0) { - ALIGN(size, QMetaObject *); - const QMetaObject **objects = - reinterpret_cast(buf + size); + using SuperData = QMetaObject::SuperData; + ALIGN(size, SuperData); + auto objects = reinterpret_cast(buf + size); if (buf) { meta->d.relatedMetaObjects = objects; for (index = 0; index < d->relatedMetaObjects.size(); ++index) objects[index] = d->relatedMetaObjects[index]; - objects[index] = 0; + objects[index] = nullptr; } - size += sizeof(QMetaObject *) * (d->relatedMetaObjects.size() + 1); + size += sizeof(SuperData) * (d->relatedMetaObjects.size() + 1); } // Align the final size and return it. diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index a97764ede45..44cce733599 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -216,7 +216,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); F(QQueue) \ F(QStack) \ F(QSet) \ - F(QLinkedList) + /*end*/ #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \ F(QHash, class) \ diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 5c1ae8aa43e..d364ae10876 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -93,12 +93,6 @@ QAbstractDynamicMetaObject::~QAbstractDynamicMetaObject() { } - -struct QSlotObjectBaseDeleter { // for use with QScopedPointer - static void cleanup(QtPrivate::QSlotObjectBase *slot) { - if (slot) slot->destroyIfLastRef(); - } -}; static int *queuedConnectionTypes(const QList &typeNames) { int *types = new int [typeNames.count() + 1]; @@ -3380,7 +3374,7 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, type &= Qt::UniqueConnection - 1; } - QScopedPointer c(new QObjectPrivate::Connection); + std::unique_ptr c{new QObjectPrivate::Connection}; c->sender = s; c->signal_index = signal_index; c->receiver.storeRelaxed(r); @@ -3394,14 +3388,14 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, c->argumentTypes.storeRelaxed(types); c->callFunction = callFunction; - QObjectPrivate::get(s)->addConnection(signal_index, c.data()); + QObjectPrivate::get(s)->addConnection(signal_index, c.get()); locker.unlock(); QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index); if (smethod.isValid()) s->connectNotify(smethod); - return c.take(); + return c.release(); } /*! @@ -3791,10 +3785,16 @@ void doActivate(QObject *sender, int signal_index, void **argv) if (c->isSlotObject) { c->slotObj->ref(); - QScopedPointer obj(c->slotObj); + + struct Deleter { + void operator()(QtPrivate::QSlotObjectBase *slot) const { + if (slot) slot->destroyIfLastRef(); + } + }; + const std::unique_ptr obj{c->slotObj}; { - Q_TRACE_SCOPE(QMetaObject_activate_slot_functor, obj.data()); + Q_TRACE_SCOPE(QMetaObject_activate_slot_functor, obj.get()); obj->call(receiver, argv); } } else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) { @@ -4947,7 +4947,7 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s type = static_cast(type ^ Qt::UniqueConnection); } - QScopedPointer c(new QObjectPrivate::Connection); + std::unique_ptr c{new QObjectPrivate::Connection}; c->sender = s; c->signal_index = signal_index; QThreadData *td = r->d_func()->threadData; @@ -4962,8 +4962,8 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s c->ownArgumentTypes = false; } - QObjectPrivate::get(s)->addConnection(signal_index, c.data()); - QMetaObject::Connection ret(c.take()); + QObjectPrivate::get(s)->addConnection(signal_index, c.get()); + QMetaObject::Connection ret(c.release()); locker.unlock(); QMetaMethod method = QMetaObjectPrivate::signal(senderMetaObject, signal_index); diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 9cf1bfed08f..95ffc1b2e84 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -486,8 +486,11 @@ class Q_CORE_EXPORT QAbstractMetaCallEvent : public QEvent { public: QAbstractMetaCallEvent(const QObject *sender, int signalId, QSemaphore *semaphore = nullptr) - : QEvent(MetaCall), signalId_(signalId), sender_(sender), semaphore_(semaphore) - {} + : QEvent(MetaCall), signalId_(signalId), sender_(sender) +#if QT_CONFIG(thread) + , semaphore_(semaphore) +#endif + { Q_UNUSED(semaphore); } ~QAbstractMetaCallEvent(); virtual void placeMetaCall(QObject *object) = 0; @@ -498,7 +501,9 @@ public: private: int signalId_; const QObject *sender_; +#if QT_CONFIG(thread) QSemaphore *semaphore_; +#endif }; class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index ef22b6e67fa..dc2d832fe5b 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2019 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -572,13 +572,42 @@ struct Q_CORE_EXPORT QMetaObject int static_metacall(Call, int, void **) const; static int metacall(QObject *, Call, int, void **); + template static constexpr const QMetaObject *staticMetaObject() + { + return &MO; + } + + struct SuperData { + const QMetaObject *direct; + SuperData() = default; + constexpr SuperData(std::nullptr_t) : direct(nullptr) {} + constexpr SuperData(const QMetaObject *mo) : direct(mo) {} + + constexpr const QMetaObject *operator->() const { return operator const QMetaObject *(); } + +#ifdef QT_NO_DATA_RELOCATION + using Getter = const QMetaObject *(*)(); + Getter indirect = nullptr; + constexpr SuperData(Getter g) : direct(nullptr), indirect(g) {} + constexpr operator const QMetaObject *() const + { return indirect ? indirect() : direct; } + template static constexpr SuperData link() + { return SuperData(QMetaObject::staticMetaObject); } +#else + constexpr operator const QMetaObject *() const + { return direct; } + template static constexpr SuperData link() + { return SuperData(QMetaObject::staticMetaObject()); } +#endif + }; + struct { // private data - const QMetaObject *superdata; + SuperData superdata; const QByteArrayData *stringdata; const uint *data; typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); StaticMetacallFunction static_metacall; - const QMetaObject * const *relatedMetaObjects; + const SuperData *relatedMetaObjects; void *extradata; //reserved for future use } d; diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp index 34fea861cda..24b174972f4 100644 --- a/src/corelib/kernel/qsignalmapper.cpp +++ b/src/corelib/kernel/qsignalmapper.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "qglobal.h" -#if QT_DEPRECATED_SINCE(5, 10) #include "qsignalmapper.h" #include "qhash.h" @@ -64,7 +63,6 @@ public: /*! \class QSignalMapper \inmodule QtCore - \obsolete The recommended solution is connecting the signal to a lambda. \brief The QSignalMapper class bundles signals from identifiable senders. \ingroup objectmodel @@ -72,7 +70,9 @@ public: This class collects a set of parameterless signals, and re-emits them with integer, string or widget parameters corresponding to - the object that sent the signal. + the object that sent the signal. Note that in most cases you can + use lambdas for passing custom parameters to slots. This is less + costly and will simplify the code. The class supports the mapping of particular strings or integers with particular objects using setMapping(). The objects' signals @@ -314,5 +314,3 @@ void QSignalMapper::map(QObject *sender) QT_END_NAMESPACE #include "moc_qsignalmapper.cpp" - -#endif diff --git a/src/corelib/kernel/qsignalmapper.h b/src/corelib/kernel/qsignalmapper.h index 6c4cfa96277..0da1e8f87da 100644 --- a/src/corelib/kernel/qsignalmapper.h +++ b/src/corelib/kernel/qsignalmapper.h @@ -42,8 +42,6 @@ #include -#if QT_DEPRECATED_SINCE(5, 10) - QT_BEGIN_NAMESPACE class QSignalMapperPrivate; @@ -53,7 +51,7 @@ class Q_CORE_EXPORT QSignalMapper : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QSignalMapper) public: - QT_DEPRECATED explicit QSignalMapper(QObject *parent = nullptr); + explicit QSignalMapper(QObject *parent = nullptr); ~QSignalMapper(); void setMapping(QObject *sender, int id); @@ -84,6 +82,4 @@ private: QT_END_NAMESPACE -#endif - #endif // QSIGNALMAPPER_H diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 637ef84d21a..ddb96ecad65 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -528,7 +528,8 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo // memory, so no need to use QFile to copy it again. Q_ASSERT(!d->resource); d->resource = new QResource(realname); - if (resource->isValid() && !resource->isCompressed() && resource->size() >= MagicLength + if (resource->isValid() && resource->compressionAlgorithm() == QResource::NoCompression + && resource->size() >= MagicLength && !memcmp(resource->data(), magic, MagicLength)) { d->unmapLength = resource->size(); d->unmapPointer = reinterpret_cast(const_cast(resource->data())); diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index c8cb5518637..39b7e4c0cef 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -362,7 +362,7 @@ class Q_CORE_EXPORT QVariant static inline QVariant fromValue(const T &value) { return QVariant(qMetaTypeId(), &value, QTypeInfo::isPointer); } -#if QT_HAS_INCLUDE() && __cplusplus >= 201703L +#if (QT_HAS_INCLUDE() && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC) template static inline QVariant fromStdVariant(const std::variant &value) { diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index 00480198bd8..4e0c3a511b5 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -92,7 +92,7 @@ QT_BEGIN_NAMESPACE but if other instances of QPluginLoader are using the same library, the call will fail, and unloading will only happen when every instance has called unload(). Right before the unloading - happen, the root component will also be deleted. + happens, the root component will also be deleted. See \l{How to Create Qt Plugins} for more information about how to make your application extensible through plugins. diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp index 28ae40f3df4..ca0156e07de 100644 --- a/src/corelib/serialization/qcborarray.cpp +++ b/src/corelib/serialization/qcborarray.cpp @@ -273,7 +273,7 @@ QCborValue QCborArray::at(qsizetype i) const not be empty. QCborValueRef has the exact same API as \l QCborValue, with one important - difference: if you assign new values to it, this map will be updated with + difference: if you assign new values to it, this array will be updated with that new value. \sa operator[](), at(), last(), insert(), prepend(), append(), @@ -287,7 +287,7 @@ QCborValue QCborArray::at(qsizetype i) const not be empty. QCborValueRef has the exact same API as \l QCborValue, with one important - difference: if you assign new values to it, this map will be updated with + difference: if you assign new values to it, this array will be updated with that new value. \sa operator[](), at(), first(), insert(), prepend(), append(), @@ -302,7 +302,7 @@ QCborValue QCborArray::at(qsizetype i) const with undefined entries, until it has an entry at the specified index. QCborValueRef has the exact same API as \l QCborValue, with one important - difference: if you assign new values to it, this map will be updated with + difference: if you assign new values to it, this array will be updated with that new value. \sa at(), first(), last(), insert(), prepend(), append(), diff --git a/src/corelib/serialization/qcborstream.cpp b/src/corelib/serialization/qcborstream.cpp index 078c14a32d4..c598eee2133 100644 --- a/src/corelib/serialization/qcborstream.cpp +++ b/src/corelib/serialization/qcborstream.cpp @@ -1972,7 +1972,15 @@ inline void QCborStreamReader::preparse() if (lastError() == QCborError::NoError) { type_ = cbor_value_get_type(&d->currentElement); - if (type_ != CborInvalidType) { + if (type_ == CborInvalidType) { + // We may have reached the end. + if (d->device && d->containerStack.isEmpty()) { + d->buffer.clear(); + if (d->bufferStart) + d->device->skip(d->bufferStart); + d->bufferStart = 0; + } + } else { d->lastError = {}; // Undo the type mapping that TinyCBOR does (we have an explicit type // for negative integer and we don't have separate types for Boolean, diff --git a/src/corelib/serialization/qjson.cpp b/src/corelib/serialization/qjson.cpp index d74ffb2a205..76f1eae1ce2 100644 --- a/src/corelib/serialization/qjson.cpp +++ b/src/corelib/serialization/qjson.cpp @@ -175,7 +175,7 @@ void Base::removeItems(int pos, int numItems) length -= numItems; } -int Object::indexOf(const QString &key, bool *exists) const +int Object::indexOf(QStringView key, bool *exists) const { int min = 0; int n = length; @@ -257,7 +257,7 @@ bool Array::isValid(int maxSize) const } -bool Entry::operator ==(const QString &key) const +bool Entry::operator ==(QStringView key) const { if (value.latinKey) return (shallowLatin1Key() == key); @@ -270,7 +270,7 @@ bool Entry::operator==(QLatin1String key) const if (value.latinKey) return shallowLatin1Key() == key; else - return shallowKey() == key; + return shallowKey() == QString(key); // ### conversion to QString } bool Entry::operator ==(const Entry &other) const diff --git a/src/corelib/serialization/qjson_p.h b/src/corelib/serialization/qjson_p.h index 9de53d5b74a..7978bed7da9 100644 --- a/src/corelib/serialization/qjson_p.h +++ b/src/corelib/serialization/qjson_p.h @@ -66,11 +66,13 @@ #include #include +#include QT_BEGIN_NAMESPACE // in qstring.cpp void qt_to_latin1_unchecked(uchar *dst, const ushort *uc, qsizetype len); +void qt_from_latin1(ushort *dst, const char *str, size_t size) noexcept; /* This defines a binary data structure for Json data. The data structure is optimised for fast reading @@ -153,16 +155,24 @@ typedef qle_uint offset; // round the size up to the next 4 byte boundary inline int alignedSize(int size) { return (size + 3) & ~3; } -static inline bool useCompressed(const QString &s) +const int MaxLatin1Length = 0x7fff; + +static inline bool useCompressed(QStringView s) { - if (s.length() >= 0x8000) + if (s.length() > MaxLatin1Length) return false; return QtPrivate::isLatin1(s); } -static inline int qStringSize(const QString &string, bool compress) +static inline bool useCompressed(QLatin1String s) { - int l = 2 + string.length(); + return s.size() <= MaxLatin1Length; +} + +template +static inline int qStringSize(T string, bool compress) +{ + int l = 2 + string.size(); if (!compress) l *= 2; return alignedSize(l); @@ -214,37 +224,49 @@ public: return maxSize >= 0 && uint(d->length) <= maxSize / sizeof(ushort); } - inline String &operator=(const QString &str) + inline String &operator=(QStringView str) { d->length = str.length(); -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - const ushort *uc = (const ushort *)str.unicode(); - for (int i = 0; i < str.length(); ++i) - d->utf16[i] = uc[i]; -#else - memcpy(d->utf16, str.unicode(), str.length()*sizeof(ushort)); -#endif - if (str.length() & 1) - d->utf16[str.length()] = 0; + qToLittleEndian(str.utf16(), str.length(), d->utf16); + fillTrailingZeros(); return *this; } - inline bool operator ==(const QString &str) const { + inline String &operator=(QLatin1String str) + { + d->length = str.size(); +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + for (int i = 0; i < str.size(); ++i) + d->utf16[i] = str[i].unicode(); +#else + qt_from_latin1((ushort *)d->utf16, str.data(), str.size()); +#endif + fillTrailingZeros(); + return *this; + } + + void fillTrailingZeros() + { + if (d->length & 1) + d->utf16[d->length] = 0; + } + + inline bool operator ==(QStringView str) const { int slen = str.length(); int l = d->length; if (slen != l) return false; - const ushort *s = (const ushort *)str.constData(); + const ushort *s = (const ushort *)str.utf16(); const qle_ushort *a = d->utf16; const ushort *b = s; while (l-- && *a == *b) a++,b++; return (l == -1); } - inline bool operator !=(const QString &str) const { + inline bool operator !=(QStringView str) const { return !operator ==(str); } - inline bool operator >=(const QString &str) const { + inline bool operator >=(QStringView str) const { // ### return toString() >= str; } @@ -292,18 +314,34 @@ public: return byteSize() <= maxSize; } - inline Latin1String &operator=(const QString &str) + inline Latin1String &operator=(QStringView str) { int len = d->length = str.length(); uchar *l = (uchar *)d->latin1; - const ushort *uc = (const ushort *)str.unicode(); + const ushort *uc = (const ushort *)str.utf16(); qt_to_latin1_unchecked(l, uc, len); - for ( ; (quintptr)(l+len) & 0x3; ++len) - l[len] = 0; + fillTrailingZeros(); return *this; } + inline Latin1String &operator=(QLatin1String str) + { + int len = d->length = str.size(); + uchar *l = (uchar *)d->latin1; + memcpy(l, str.data(), len); + + fillTrailingZeros(); + return *this; + } + + void fillTrailingZeros() + { + uchar *l = (uchar *)d->latin1; + for (int len = d->length; (quintptr)(l + len) & 0x3; ++len) + l[len] = 0; + } + QLatin1String toQLatin1String() const noexcept { return QLatin1String(d->latin1, d->length); } @@ -351,11 +389,11 @@ public: { \ return lhs.toQLatin1String() op rhs; \ } \ - inline bool operator op(const QString &lhs, Latin1String rhs) noexcept \ + inline bool operator op(QStringView lhs, Latin1String rhs) noexcept \ { \ return lhs op rhs.toQLatin1String(); \ } \ - inline bool operator op(Latin1String lhs, const QString &rhs) noexcept \ + inline bool operator op(Latin1String lhs, QStringView rhs) noexcept \ { \ return lhs.toQLatin1String() op rhs; \ } \ @@ -419,7 +457,8 @@ inline bool String::operator<(const Latin1String &str) const } -static inline void copyString(char *dest, const QString &str, bool compress) +template +static inline void copyString(char *dest, T str, bool compress) { if (compress) { Latin1String string(dest); @@ -469,7 +508,7 @@ public: Entry *entryAt(int i) const { return reinterpret_cast(((char *)this) + table()[i]); } - int indexOf(const QString &key, bool *exists) const; + int indexOf(QStringView key, bool *exists) const; int indexOf(QLatin1String key, bool *exists) const; bool isValid(int maxSize) const; @@ -577,9 +616,9 @@ public: return shallowKey().isValid(maxSize); } - bool operator ==(const QString &key) const; - inline bool operator !=(const QString &key) const { return !operator ==(key); } - inline bool operator >=(const QString &key) const; + bool operator ==(QStringView key) const; + inline bool operator !=(QStringView key) const { return !operator ==(key); } + inline bool operator >=(QStringView key) const; bool operator==(QLatin1String key) const; inline bool operator!=(QLatin1String key) const { return !operator ==(key); } @@ -589,7 +628,7 @@ public: bool operator >=(const Entry &other) const; }; -inline bool Entry::operator >=(const QString &key) const +inline bool Entry::operator >=(QStringView key) const { if (value.latinKey) return (shallowLatin1Key() >= key); @@ -602,10 +641,10 @@ inline bool Entry::operator >=(QLatin1String key) const if (value.latinKey) return shallowLatin1Key() >= key; else - return shallowKey() >= key; + return shallowKey() >= QString(key); // ### conversion to QString } -inline bool operator <(const QString &key, const Entry &e) +inline bool operator <(QStringView key, const Entry &e) { return e >= key; } inline bool operator<(QLatin1String key, const Entry &e) diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp index 6b327619ad6..9636ac5856f 100644 --- a/src/corelib/serialization/qjsonarray.cpp +++ b/src/corelib/serialization/qjsonarray.cpp @@ -845,7 +845,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const The return value is of type QJsonValueRef, a helper class for QJsonArray and QJsonObject. When you get an object of type QJsonValueRef, you can use it as if it were a reference to a QJsonValue. If you assign to it, - the assignment will apply to the character in the QJsonArray of QJsonObject + the assignment will apply to the element in the QJsonArray or QJsonObject from which you got the reference. \sa operator+() diff --git a/src/corelib/serialization/qjsoncbor.cpp b/src/corelib/serialization/qjsoncbor.cpp index e0c390f610d..d6a0c8c48a4 100644 --- a/src/corelib/serialization/qjsoncbor.cpp +++ b/src/corelib/serialization/qjsoncbor.cpp @@ -421,7 +421,7 @@ QJsonArray QCborArray::toJsonArray() const } /*! - Recursively converts every \l QCborValue value in this array to JSON using + Recursively converts every \l QCborValue value in this map to JSON using QCborValue::toJsonValue() and creates a string key for all keys that aren't strings, then returns the corresponding QJsonObject composed of those associations. diff --git a/src/corelib/serialization/qjsondocument.cpp b/src/corelib/serialization/qjsondocument.cpp index f8027efb585..193b80ee226 100644 --- a/src/corelib/serialization/qjsondocument.cpp +++ b/src/corelib/serialization/qjsondocument.cpp @@ -544,6 +544,7 @@ void QJsonDocument::setArray(const QJsonArray &array) d->ref.ref(); } +#if QT_STRINGVIEW_LEVEL < 2 /*! Returns a QJsonValue representing the value for the key \a key. @@ -557,6 +558,16 @@ void QJsonDocument::setArray(const QJsonArray &array) \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject */ const QJsonValue QJsonDocument::operator[](const QString &key) const +{ + return (*this)[QStringView(key)]; +} +#endif + +/*! + \overload + \since 5.14 +*/ +const QJsonValue QJsonDocument::operator[](QStringView key) const { if (!isObject()) return QJsonValue(QJsonValue::Undefined); diff --git a/src/corelib/serialization/qjsondocument.h b/src/corelib/serialization/qjsondocument.h index a8006a6cc56..a8e7485f5dd 100644 --- a/src/corelib/serialization/qjsondocument.h +++ b/src/corelib/serialization/qjsondocument.h @@ -146,7 +146,10 @@ public: void setObject(const QJsonObject &object); void setArray(const QJsonArray &array); +#if QT_STRINGVIEW_LEVEL < 2 const QJsonValue operator[](const QString &key) const; +#endif + const QJsonValue operator[](QStringView key) const; const QJsonValue operator[](QLatin1String key) const; const QJsonValue operator[](int i) const; diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp index c1a6328b2fb..329bc4d2c9a 100644 --- a/src/corelib/serialization/qjsonobject.cpp +++ b/src/corelib/serialization/qjsonobject.cpp @@ -377,6 +377,7 @@ bool QJsonObject::isEmpty() const return !o->length; } +#if QT_STRINGVIEW_LEVEL < 2 /*! Returns a QJsonValue representing the value for the key \a key. @@ -386,14 +387,17 @@ bool QJsonObject::isEmpty() const */ QJsonValue QJsonObject::value(const QString &key) const { - if (!d) - return QJsonValue(QJsonValue::Undefined); + return value(QStringView(key)); +} +#endif - bool keyExists; - int i = o->indexOf(key, &keyExists); - if (!keyExists) - return QJsonValue(QJsonValue::Undefined); - return QJsonValue(d, o, o->entryAt(i)->value); +/*! + \overload + \since 5.14 +*/ +QJsonValue QJsonObject::value(QStringView key) const +{ + return valueImpl(key); } /*! @@ -401,6 +405,15 @@ QJsonValue QJsonObject::value(const QString &key) const \since 5.7 */ QJsonValue QJsonObject::value(QLatin1String key) const +{ + return valueImpl(key); +} + +/*! + \internal +*/ +template +QJsonValue QJsonObject::valueImpl(T key) const { if (!d) return QJsonValue(QJsonValue::Undefined); @@ -412,6 +425,7 @@ QJsonValue QJsonObject::value(QLatin1String key) const return QJsonValue(d, o, o->entryAt(i)->value); } +#if QT_STRINGVIEW_LEVEL < 2 /*! Returns a QJsonValue representing the value for the key \a key. @@ -423,8 +437,16 @@ QJsonValue QJsonObject::value(QLatin1String key) const */ QJsonValue QJsonObject::operator [](const QString &key) const { - return value(key); + return (*this)[QStringView(key)]; } +#endif + +/*! + \fn QJsonValue QJsonObject::operator [](QStringView key) const + + \overload + \since 5.14 +*/ /*! \fn QJsonValue QJsonObject::operator [](QLatin1String key) const @@ -433,6 +455,7 @@ QJsonValue QJsonObject::operator [](const QString &key) const \since 5.7 */ +#if QT_STRINGVIEW_LEVEL < 2 /*! Returns a reference to the value for \a key. @@ -446,14 +469,17 @@ QJsonValue QJsonObject::operator [](const QString &key) const */ QJsonValueRef QJsonObject::operator [](const QString &key) { - // ### somewhat inefficient, as we lookup the key twice if it doesn't yet exist - bool keyExists = false; - int index = o ? o->indexOf(key, &keyExists) : -1; - if (!keyExists) { - iterator i = insert(key, QJsonValue()); - index = i.i; - } - return QJsonValueRef(this, index); + return (*this)[QStringView(key)]; +} +#endif + +/*! + \overload + \since 5.14 +*/ +QJsonValueRef QJsonObject::operator [](QStringView key) +{ + return atImpl(key); } /*! @@ -462,10 +488,25 @@ QJsonValueRef QJsonObject::operator [](const QString &key) */ QJsonValueRef QJsonObject::operator [](QLatin1String key) { - // ### optimize me - return operator[](QString(key)); + return atImpl(key); } +/*! + \internal +*/ +template +QJsonValueRef QJsonObject::atImpl(T key) +{ + bool keyExists = false; + int index = o ? o->indexOf(key, &keyExists) : 0; + if (!keyExists) { + iterator i = insertAt(index, key, QJsonValue(), false); + index = i.i; + } + return QJsonValueRef(this, index); +} + +#if QT_STRINGVIEW_LEVEL < 2 /*! Inserts a new item with the key \a key and a value of \a value. @@ -480,11 +521,50 @@ QJsonValueRef QJsonObject::operator [](QLatin1String key) \sa remove(), take(), QJsonObject::iterator, end() */ QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue &value) +{ + return insert(QStringView(key), value); +} +#endif + +/*! + \overload + \since 5.14 +*/ +QJsonObject::iterator QJsonObject::insert(QStringView key, const QJsonValue &value) +{ + return insertImpl(key, value); +} + +/*! + \overload + \since 5.14 +*/ +QJsonObject::iterator QJsonObject::insert(QLatin1String key, const QJsonValue &value) +{ + return insertImpl(key, value); +} + +/*! + \internal +*/ +template +QJsonObject::iterator QJsonObject::insertImpl(T key, const QJsonValue &value) { if (value.t == QJsonValue::Undefined) { remove(key); return end(); } + bool keyExists = false; + int pos = o ? o->indexOf(key, &keyExists) : 0; + return insertAt(pos, key, value, keyExists); +} + +/*! + \internal + */ +template +QJsonObject::iterator QJsonObject::insertAt(int pos, T key, const QJsonValue &value, bool keyExists) +{ QJsonValue val = value; bool latinOrIntValue; @@ -500,8 +580,6 @@ QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue & if (!o->length) o->tableOffset = sizeof(QJsonPrivate::Object); - bool keyExists = false; - int pos = o->indexOf(key, &keyExists); if (keyExists) ++d->compactionCounter; @@ -518,18 +596,46 @@ QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue & if (valueSize) QJsonPrivate::Value::copyData(val, (char *)e + valueOffset, latinOrIntValue); - if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) - compact(); + compactIfNeeded(); return iterator(this, pos); } +#if QT_STRINGVIEW_LEVEL < 2 /*! Removes \a key from the object. \sa insert(), take() */ void QJsonObject::remove(const QString &key) +{ + remove(QStringView(key)); +} +#endif + +/*! + \overload + \since 5.14 +*/ +void QJsonObject::remove(QStringView key) +{ + removeImpl(key); +} + +/*! + \overload + \since 5.14 +*/ +void QJsonObject::remove(QLatin1String key) +{ + removeImpl(key); +} + +/*! + \internal +*/ +template +void QJsonObject::removeImpl(T key) { if (!d) return; @@ -539,13 +645,10 @@ void QJsonObject::remove(const QString &key) if (!keyExists) return; - detach2(); - o->removeItems(index, 1); - ++d->compactionCounter; - if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) - compact(); + removeAt(index); } +#if QT_STRINGVIEW_LEVEL < 2 /*! Removes \a key from the object. @@ -556,6 +659,34 @@ void QJsonObject::remove(const QString &key) \sa insert(), remove(), QJsonValue */ QJsonValue QJsonObject::take(const QString &key) +{ + return take(QStringView(key)); +} +#endif + +/*! + \overload + \since 5.14 +*/ +QJsonValue QJsonObject::take(QStringView key) +{ + return takeImpl(key); +} + +/*! + \overload + \since 5.14 +*/ +QJsonValue QJsonObject::take(QLatin1String key) +{ + return takeImpl(key); +} + +/*! + \internal +*/ +template +QJsonValue QJsonObject::takeImpl(T key) { if (!o) return QJsonValue(QJsonValue::Undefined); @@ -566,15 +697,12 @@ QJsonValue QJsonObject::take(const QString &key) return QJsonValue(QJsonValue::Undefined); QJsonValue v(d, o, o->entryAt(index)->value); - detach2(); - o->removeItems(index, 1); - ++d->compactionCounter; - if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) - compact(); + removeAt(index); return v; } +#if QT_STRINGVIEW_LEVEL < 2 /*! Returns \c true if the object contains key \a key. @@ -582,12 +710,17 @@ QJsonValue QJsonObject::take(const QString &key) */ bool QJsonObject::contains(const QString &key) const { - if (!o) - return false; + return contains(QStringView(key)); +} +#endif - bool keyExists; - o->indexOf(key, &keyExists); - return keyExists; +/*! + \overload + \since 5.14 +*/ +bool QJsonObject::contains(QStringView key) const +{ + return containsImpl(key); } /*! @@ -595,6 +728,15 @@ bool QJsonObject::contains(const QString &key) const \since 5.7 */ bool QJsonObject::contains(QLatin1String key) const +{ + return containsImpl(key); +} + +/*! + \internal +*/ +template +bool QJsonObject::containsImpl(T key) const { if (!o) return false; @@ -652,15 +794,13 @@ QJsonObject::iterator QJsonObject::erase(QJsonObject::iterator it) int index = it.i; - o->removeItems(index, 1); - ++d->compactionCounter; - if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) - compact(); + removeAt(index); // iterator hasn't changed return it; } +#if QT_STRINGVIEW_LEVEL < 2 /*! Returns an iterator pointing to the item with key \a key in the map. @@ -670,12 +810,17 @@ QJsonObject::iterator QJsonObject::erase(QJsonObject::iterator it) */ QJsonObject::iterator QJsonObject::find(const QString &key) { - bool keyExists = false; - int index = o ? o->indexOf(key, &keyExists) : 0; - if (!keyExists) - return end(); - detach2(); - return iterator(this, index); + return find(QStringView(key)); +} +#endif + +/*! + \overload + \since 5.14 +*/ +QJsonObject::iterator QJsonObject::find(QStringView key) +{ + return findImpl(key); } /*! @@ -683,6 +828,15 @@ QJsonObject::iterator QJsonObject::find(const QString &key) \since 5.7 */ QJsonObject::iterator QJsonObject::find(QLatin1String key) +{ + return findImpl(key); +} + +/*! + \internal +*/ +template +QJsonObject::iterator QJsonObject::findImpl(T key) { bool keyExists = false; int index = o ? o->indexOf(key, &keyExists) : 0; @@ -692,10 +846,18 @@ QJsonObject::iterator QJsonObject::find(QLatin1String key) return iterator(this, index); } +#if QT_STRINGVIEW_LEVEL < 2 /*! \fn QJsonObject::const_iterator QJsonObject::find(const QString &key) const \overload */ +#endif + +/*! \fn QJsonObject::const_iterator QJsonObject::find(QStringView key) const + + \overload + \since 5.14 +*/ /*! \fn QJsonObject::const_iterator QJsonObject::find(QLatin1String key) const @@ -703,6 +865,7 @@ QJsonObject::iterator QJsonObject::find(QLatin1String key) \since 5.7 */ +#if QT_STRINGVIEW_LEVEL < 2 /*! Returns a const iterator pointing to the item with key \a key in the map. @@ -712,11 +875,17 @@ QJsonObject::iterator QJsonObject::find(QLatin1String key) */ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const { - bool keyExists = false; - int index = o ? o->indexOf(key, &keyExists) : 0; - if (!keyExists) - return end(); - return const_iterator(this, index); + return constFind(QStringView(key)); +} +#endif + +/*! + \overload + \since 5.14 +*/ +QJsonObject::const_iterator QJsonObject::constFind(QStringView key) const +{ + return constFindImpl(key); } /*! @@ -724,6 +893,15 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const \since 5.7 */ QJsonObject::const_iterator QJsonObject::constFind(QLatin1String key) const +{ + return constFindImpl(key); +} + +/*! + \internal +*/ +template +QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const { bool keyExists = false; int index = o ? o->indexOf(key, &keyExists) : 0; @@ -1258,6 +1436,15 @@ void QJsonObject::compact() o = static_cast(d->header->root()); } +/*! + \internal + */ +void QJsonObject::compactIfNeeded() +{ + if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) + compact(); +} + /*! \internal */ @@ -1289,7 +1476,21 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val) Q_ASSERT(o && i >= 0 && i < (int)o->length); QJsonPrivate::Entry *e = o->entryAt(i); - insert(e->key(), val); + if (val.t == QJsonValue::Undefined) + removeAt(i); + else + insertAt(i, e->key(), val, true); +} + +/*! + \internal + */ +void QJsonObject::removeAt(int index) +{ + detach2(); + o->removeItems(index, 1); + ++d->compactionCounter; + compactIfNeeded(); } uint qHash(const QJsonObject &object, uint seed) diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h index d8e2ab9ca73..05463f6f364 100644 --- a/src/corelib/serialization/qjsonobject.h +++ b/src/corelib/serialization/qjsonobject.h @@ -100,16 +100,28 @@ public: inline int length() const { return size(); } bool isEmpty() const; +#if QT_STRINGVIEW_LEVEL < 2 QJsonValue value(const QString &key) const; - QJsonValue value(QLatin1String key) const; QJsonValue operator[] (const QString &key) const; - QJsonValue operator[] (QLatin1String key) const { return value(key); } QJsonValueRef operator[] (const QString &key); +#endif + QJsonValue value(QStringView key) const; + QJsonValue value(QLatin1String key) const; + QJsonValue operator[] (QStringView key) const { return value(key); } + QJsonValue operator[] (QLatin1String key) const { return value(key); } + QJsonValueRef operator[] (QStringView key); QJsonValueRef operator[] (QLatin1String key); +#if QT_STRINGVIEW_LEVEL < 2 void remove(const QString &key); QJsonValue take(const QString &key); bool contains(const QString &key) const; +#endif + void remove(QStringView key); + void remove(QLatin1String key); + QJsonValue take(QStringView key); + QJsonValue take(QLatin1String key); + bool contains(QStringView key) const; bool contains(QLatin1String key) const; bool operator==(const QJsonObject &other) const; @@ -218,13 +230,20 @@ public: // more Qt typedef iterator Iterator; typedef const_iterator ConstIterator; +#if QT_STRINGVIEW_LEVEL < 2 iterator find(const QString &key); - iterator find(QLatin1String key); const_iterator find(const QString &key) const { return constFind(key); } - const_iterator find(QLatin1String key) const { return constFind(key); } const_iterator constFind(const QString &key) const; - const_iterator constFind(QLatin1String key) const; iterator insert(const QString &key, const QJsonValue &value); +#endif + iterator find(QStringView key); + iterator find(QLatin1String key); + const_iterator find(QStringView key) const { return constFind(key); } + const_iterator find(QLatin1String key) const { return constFind(key); } + const_iterator constFind(QStringView key) const; + const_iterator constFind(QLatin1String key) const; + iterator insert(QStringView key, const QJsonValue &value); + iterator insert(QLatin1String key, const QJsonValue &value); // STL compatibility typedef QJsonValue mapped_type; @@ -247,10 +266,22 @@ private: void detach(uint reserve = 0); bool detach2(uint reserve = 0); void compact(); + void compactIfNeeded(); + + template QJsonValue valueImpl(T key) const; + template QJsonValueRef atImpl(T key); + template void removeImpl(T key); + template QJsonValue takeImpl(T key); + template bool containsImpl(T key) const; + template iterator findImpl(T key); + template const_iterator constFindImpl(T key) const; + template iterator insertImpl(T key, const QJsonValue &value); QString keyAt(int i) const; QJsonValue valueAt(int i) const; void setValueAt(int i, const QJsonValue &val); + void removeAt(int i); + template iterator insertAt(int i, T key, const QJsonValue &val, bool exists); QJsonPrivate::Data *d; QJsonPrivate::Object *o; diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp index 0bd28581f3a..5f07a6a03e4 100644 --- a/src/corelib/serialization/qjsonvalue.cpp +++ b/src/corelib/serialization/qjsonvalue.cpp @@ -694,6 +694,7 @@ QJsonObject QJsonValue::toObject() const return toObject(QJsonObject()); } +#if QT_STRINGVIEW_LEVEL < 2 /*! Returns a QJsonValue representing the value for the key \a key. @@ -707,6 +708,16 @@ QJsonObject QJsonValue::toObject() const \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject */ const QJsonValue QJsonValue::operator[](const QString &key) const +{ + return (*this)[QStringView(key)]; +} +#endif + +/*! + \overload + \since 5.14 +*/ +const QJsonValue QJsonValue::operator[](QStringView key) const { if (!isObject()) return QJsonValue(QJsonValue::Undefined); diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h index 37d84f9e602..430fa06c0fc 100644 --- a/src/corelib/serialization/qjsonvalue.h +++ b/src/corelib/serialization/qjsonvalue.h @@ -137,7 +137,10 @@ public: QJsonObject toObject() const; QJsonObject toObject(const QJsonObject &defaultValue) const; +#if QT_STRINGVIEW_LEVEL < 2 const QJsonValue operator[](const QString &key) const; +#endif + const QJsonValue operator[](QStringView key) const; const QJsonValue operator[](QLatin1String key) const; const QJsonValue operator[](int i) const; diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp index 9d4bc223ab4..a675c3cede4 100644 --- a/src/corelib/serialization/qtextstream.cpp +++ b/src/corelib/serialization/qtextstream.cpp @@ -888,7 +888,7 @@ inline bool QTextStreamPrivate::getChar(QChar *ch) if ((string && stringOffset == string->size()) || (device && readBuffer.isEmpty() && !fillReadBuffer())) { if (ch) - *ch = 0; + *ch = QChar(); return false; } if (ch) diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index be3a476cb2e..500e0aa6beb 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -782,8 +782,8 @@ QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack() tagStackStringStorage.reserve(32); tagStackStringStorageSize = 0; NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push(); - namespaceDeclaration.prefix = addToStringStorage(QStringViewLiteral("xml")); - namespaceDeclaration.namespaceUri = addToStringStorage(QStringViewLiteral("http://www.w3.org/XML/1998/namespace")); + namespaceDeclaration.prefix = addToStringStorage(u"xml"); + namespaceDeclaration.namespaceUri = addToStringStorage(u"http://www.w3.org/XML/1998/namespace"); initialTagStackStringStorageSize = tagStackStringStorageSize; } @@ -1423,7 +1423,7 @@ inline int QXmlStreamReaderPrivate::fastScanNMTOKEN() int n = 0; uint c; while ((c = getChar()) != StreamEOF) { - if (fastDetermineNameChar(c) == NotName) { + if (fastDetermineNameChar(QChar(c)) == NotName) { putChar(c); return n; } else { diff --git a/src/corelib/tools/UNICODE_LICENSE.txt b/src/corelib/text/UNICODE_LICENSE.txt similarity index 100% rename from src/corelib/tools/UNICODE_LICENSE.txt rename to src/corelib/text/UNICODE_LICENSE.txt diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/text/qbytearray.cpp similarity index 99% rename from src/corelib/tools/qbytearray.cpp rename to src/corelib/text/qbytearray.cpp index ecbb4743afb..c50e087c103 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -40,7 +40,7 @@ #include "qbytearray.h" #include "qbytearraymatcher.h" -#include "qtools_p.h" +#include "private/qtools_p.h" #include "qstring.h" #include "qlist.h" #include "qlocale.h" @@ -972,12 +972,11 @@ QByteArray qUncompress(const uchar* data, int nbytes) \section2 8-bit Character Comparisons In QByteArray, the notion of uppercase and lowercase and of which - character is greater than or less than another character is - locale dependent. This affects functions that support a case + character is greater than or less than another character is done + in the Latin-1 locale. This affects functions that support a case insensitive option or that compare or lowercase or uppercase their arguments. Case insensitive operations and comparisons will - be accurate if both strings contain only ASCII characters. (If \c - $LC_CTYPE is set, most Unix systems do "the right thing".) + be accurate if both strings contain only Latin-1 characters. Functions that this affects include contains(), indexOf(), lastIndexOf(), operator<(), operator<=(), operator>(), operator>=(), isLower(), isUpper(), toLower() and toUpper(). diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/text/qbytearray.h similarity index 100% rename from src/corelib/tools/qbytearray.h rename to src/corelib/text/qbytearray.h diff --git a/src/corelib/tools/qbytearray_p.h b/src/corelib/text/qbytearray_p.h similarity index 98% rename from src/corelib/tools/qbytearray_p.h rename to src/corelib/text/qbytearray_p.h index 6ebff739cdd..3c6257f7860 100644 --- a/src/corelib/tools/qbytearray_p.h +++ b/src/corelib/text/qbytearray_p.h @@ -52,7 +52,7 @@ // #include -#include "qtools_p.h" +#include "private/qtools_p.h" QT_BEGIN_NAMESPACE diff --git a/src/corelib/tools/qbytearraylist.cpp b/src/corelib/text/qbytearraylist.cpp similarity index 100% rename from src/corelib/tools/qbytearraylist.cpp rename to src/corelib/text/qbytearraylist.cpp diff --git a/src/corelib/tools/qbytearraylist.h b/src/corelib/text/qbytearraylist.h similarity index 100% rename from src/corelib/tools/qbytearraylist.h rename to src/corelib/text/qbytearraylist.h diff --git a/src/corelib/tools/qbytearraymatcher.cpp b/src/corelib/text/qbytearraymatcher.cpp similarity index 100% rename from src/corelib/tools/qbytearraymatcher.cpp rename to src/corelib/text/qbytearraymatcher.cpp diff --git a/src/corelib/tools/qbytearraymatcher.h b/src/corelib/text/qbytearraymatcher.h similarity index 100% rename from src/corelib/tools/qbytearraymatcher.h rename to src/corelib/text/qbytearraymatcher.h diff --git a/src/corelib/tools/qbytedata_p.h b/src/corelib/text/qbytedata_p.h similarity index 100% rename from src/corelib/tools/qbytedata_p.h rename to src/corelib/text/qbytedata_p.h diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/text/qchar.cpp similarity index 99% rename from src/corelib/tools/qchar.cpp rename to src/corelib/text/qchar.cpp index e097e4a5fe2..0c190c6a3d6 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/text/qchar.cpp @@ -1885,11 +1885,11 @@ static void composeHelper(QString *str, QChar::UnicodeVersion version, int from) QChar *d = s.data(); // ligatureHelper() never changes planes if (QChar::requiresSurrogates(ligature)) { - d[starter] = QChar::highSurrogate(ligature); - d[starter + 1] = QChar::lowSurrogate(ligature); + d[starter] = QChar(QChar::highSurrogate(ligature)); + d[starter + 1] = QChar(QChar::lowSurrogate(ligature)); s.remove(i, 2); } else { - d[starter] = ligature; + d[starter] = QChar(ligature); s.remove(i, 1); } continue; @@ -1962,16 +1962,16 @@ static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, in int p = pos; // exchange characters if (!QChar::requiresSurrogates(u2)) { - uc[p++] = u2; + uc[p++] = QChar(u2); } else { - uc[p++] = QChar::highSurrogate(u2); - uc[p++] = QChar::lowSurrogate(u2); + uc[p++] = QChar(QChar::highSurrogate(u2)); + uc[p++] = QChar(QChar::lowSurrogate(u2)); } if (!QChar::requiresSurrogates(u1)) { - uc[p++] = u1; + uc[p++] = QChar(u1); } else { - uc[p++] = QChar::highSurrogate(u1); - uc[p++] = QChar::lowSurrogate(u1); + uc[p++] = QChar(QChar::highSurrogate(u1)); + uc[p++] = QChar(QChar::lowSurrogate(u1)); } if (pos > 0) --pos; diff --git a/src/corelib/tools/qchar.h b/src/corelib/text/qchar.h similarity index 98% rename from src/corelib/tools/qchar.h rename to src/corelib/text/qchar.h index 73344ecf525..e028a24c24f 100644 --- a/src/corelib/tools/qchar.h +++ b/src/corelib/text/qchar.h @@ -443,17 +443,17 @@ public: #endif inline unsigned char combiningClass() const noexcept { return QChar::combiningClass(ucs); } - inline QChar mirroredChar() const noexcept { return QChar::mirroredChar(ucs); } + inline QChar mirroredChar() const noexcept { return QChar(QChar::mirroredChar(ucs)); } inline bool hasMirrored() const noexcept { return QChar::hasMirrored(ucs); } QString decomposition() const; inline Decomposition decompositionTag() const noexcept { return QChar::decompositionTag(ucs); } inline int digitValue() const noexcept { return QChar::digitValue(ucs); } - inline QChar toLower() const noexcept { return QChar::toLower(ucs); } - inline QChar toUpper() const noexcept { return QChar::toUpper(ucs); } - inline QChar toTitleCase() const noexcept { return QChar::toTitleCase(ucs); } - inline QChar toCaseFolded() const noexcept { return QChar::toCaseFolded(ucs); } + inline QChar toLower() const noexcept { return QChar(QChar::toLower(ucs)); } + inline QChar toUpper() const noexcept { return QChar(QChar::toUpper(ucs)); } + inline QChar toTitleCase() const noexcept { return QChar(QChar::toTitleCase(ucs)); } + inline QChar toCaseFolded() const noexcept { return QChar(QChar::toCaseFolded(ucs)); } inline Script script() const noexcept { return QChar::script(ucs); } diff --git a/src/corelib/tools/qcollator.cpp b/src/corelib/text/qcollator.cpp similarity index 100% rename from src/corelib/tools/qcollator.cpp rename to src/corelib/text/qcollator.cpp diff --git a/src/corelib/tools/qcollator.h b/src/corelib/text/qcollator.h similarity index 100% rename from src/corelib/tools/qcollator.h rename to src/corelib/text/qcollator.h diff --git a/src/corelib/tools/qcollator_icu.cpp b/src/corelib/text/qcollator_icu.cpp similarity index 100% rename from src/corelib/tools/qcollator_icu.cpp rename to src/corelib/text/qcollator_icu.cpp diff --git a/src/corelib/tools/qcollator_macx.cpp b/src/corelib/text/qcollator_macx.cpp similarity index 100% rename from src/corelib/tools/qcollator_macx.cpp rename to src/corelib/text/qcollator_macx.cpp diff --git a/src/corelib/tools/qcollator_p.h b/src/corelib/text/qcollator_p.h similarity index 100% rename from src/corelib/tools/qcollator_p.h rename to src/corelib/text/qcollator_p.h diff --git a/src/corelib/tools/qcollator_posix.cpp b/src/corelib/text/qcollator_posix.cpp similarity index 100% rename from src/corelib/tools/qcollator_posix.cpp rename to src/corelib/text/qcollator_posix.cpp diff --git a/src/corelib/tools/qcollator_win.cpp b/src/corelib/text/qcollator_win.cpp similarity index 100% rename from src/corelib/tools/qcollator_win.cpp rename to src/corelib/text/qcollator_win.cpp diff --git a/src/corelib/tools/qdoublescanprint_p.h b/src/corelib/text/qdoublescanprint_p.h similarity index 100% rename from src/corelib/tools/qdoublescanprint_p.h rename to src/corelib/text/qdoublescanprint_p.h diff --git a/src/corelib/tools/qharfbuzz.cpp b/src/corelib/text/qharfbuzz.cpp similarity index 100% rename from src/corelib/tools/qharfbuzz.cpp rename to src/corelib/text/qharfbuzz.cpp diff --git a/src/corelib/tools/qharfbuzz_p.h b/src/corelib/text/qharfbuzz_p.h similarity index 100% rename from src/corelib/tools/qharfbuzz_p.h rename to src/corelib/text/qharfbuzz_p.h diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/text/qlocale.cpp similarity index 95% rename from src/corelib/tools/qlocale.cpp rename to src/corelib/text/qlocale.cpp index 939f8eb34d8..5685d87c856 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2019 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -304,7 +304,8 @@ QByteArray QLocaleId::name(char separator) const (script_id != QLocale::AnyScript ? script_code_list + 4 * script_id : nullptr); const unsigned char *country = (country_id != QLocale::AnyCountry ? country_code_list + 3 * country_id : nullptr); - char len = (lang[2] != 0 ? 3 : 2) + (script ? 4+1 : 0) + (country ? (country[2] != 0 ? 3 : 2)+1 : 0); + char len = (lang[2] != 0 ? 3 : 2) + (script ? 4 + 1 : 0) + + (country ? (country[2] != 0 ? 3 : 2) + 1 : 0); QByteArray name(len, Qt::Uninitialized); char *uc = name.data(); *uc++ = lang[0]; @@ -335,7 +336,8 @@ QByteArray QLocalePrivate::bcp47Name(char separator) const if (m_data->m_language_id == QLocale::C) return QByteArrayLiteral("en"); - QLocaleId localeId = QLocaleId::fromIds(m_data->m_language_id, m_data->m_script_id, m_data->m_country_id); + QLocaleId localeId = QLocaleId::fromIds(m_data->m_language_id, m_data->m_script_id, + m_data->m_country_id); return localeId.withLikelySubtagsRemoved().name(separator); } @@ -367,8 +369,10 @@ static const QLocaleData *findLocaleDataById(const QLocaleId &localeId) } while (data->m_language_id && data->m_language_id == localeId.language_id); } else { do { - if (data->m_script_id == localeId.script_id && data->m_country_id == localeId.country_id) + if (data->m_script_id == localeId.script_id + && data->m_country_id == localeId.country_id) { return data; + } ++data; } while (data->m_language_id && data->m_language_id == localeId.language_id); } @@ -376,7 +380,8 @@ static const QLocaleData *findLocaleDataById(const QLocaleId &localeId) return nullptr; } -const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLocale::Script script, QLocale::Country country) +const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLocale::Script script, + QLocale::Country country) { QLocaleId localeId = QLocaleId::fromIds(language, script, country); QLocaleId likelyId = localeId.withLikelySubtagsAdded(); @@ -438,7 +443,8 @@ const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLoca return locale_data + idx; } -static bool parse_locale_tag(const QString &input, int &i, QString *result, const QString &separators) +static bool parse_locale_tag(const QString &input, int &i, QString *result, + const QString &separators) { *result = QString(8, Qt::Uninitialized); // worst case according to BCP47 QChar *pch = result->data(); @@ -487,7 +493,8 @@ bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QSt state = ScriptState; break; case ScriptState: { - QString scripts = QString::fromLatin1((const char *)script_code_list, sizeof(script_code_list) - 1); + QString scripts = QString::fromLatin1((const char *)script_code_list, + sizeof(script_code_list) - 1); if (value.length() == 4 && scripts.indexOf(value) % 4 == 0) { // script name is always 4 characters script = value; @@ -560,8 +567,8 @@ QString qt_readEscapedFormatString(QStringView format, int *idx) while (i < format.size()) { if (format.at(i).unicode() == '\'') { - if (i + 1 < format.size() && format.at(i + 1).unicode() == '\'') { - // "''" inside of a quoted string + if (format.mid(i + 1).startsWith(QLatin1Char('\''))) { + // "''" inside a quoted string result.append(QLatin1Char('\'')); i += 2; } else { @@ -610,7 +617,8 @@ static QLocale::NumberOptions default_number_options = QLocale::DefaultNumberOpt static const QLocaleData *const c_data = locale_data; static QLocalePrivate *c_private() { - static QLocalePrivate c_locale = { c_data, Q_BASIC_ATOMIC_INITIALIZER(1), QLocale::OmitGroupSeparator }; + static QLocalePrivate c_locale = + { c_data, Q_BASIC_ATOMIC_INITIALIZER(1), QLocale::OmitGroupSeparator }; return &c_locale; } @@ -833,9 +841,11 @@ QLocale::QLocale(QLocalePrivate &dd) "language[_script][_country][.codeset][@modifier]" or "C", where: \list - \li language is a lowercase, two-letter, ISO 639 language code (also some three-letter codes), + \li language is a lowercase, two-letter, ISO 639 language code (also some + three-letter codes), \li script is a titlecase, four-letter, ISO 15924 script code, - \li country is an uppercase, two-letter, ISO 3166 country code (also "419" as defined by United Nations), + \li country is an uppercase, two-letter, ISO 3166 country code + (also "419" as defined by United Nations), \li and codeset and modifier are ignored. \endlist @@ -1036,9 +1046,11 @@ QString QLocale::quoteString(const QStringRef &str, QuotationStyle style) const if (d->m_data == systemData()) { QVariant res; if (style == QLocale::AlternateQuotation) - res = systemLocale()->query(QSystemLocale::StringToAlternateQuotation, QVariant::fromValue(str)); + res = systemLocale()->query(QSystemLocale::StringToAlternateQuotation, + QVariant::fromValue(str)); if (res.isNull() || style == QLocale::StandardQuotation) - res = systemLocale()->query(QSystemLocale::StringToStandardQuotation, QVariant::fromValue(str)); + res = systemLocale()->query(QSystemLocale::StringToStandardQuotation, + QVariant::fromValue(str)); if (!res.isNull()) return res.toString(); } @@ -1046,8 +1058,9 @@ QString QLocale::quoteString(const QStringRef &str, QuotationStyle style) const if (style == QLocale::StandardQuotation) return QChar(d->m_data->m_quotation_start) % str % QChar(d->m_data->m_quotation_end); - else - return QChar(d->m_data->m_alternate_quotation_start) % str % QChar(d->m_data->m_alternate_quotation_end); + + return QChar(d->m_data->m_alternate_quotation_start) + % str % QChar(d->m_data->m_alternate_quotation_end); } /*! @@ -1060,8 +1073,8 @@ QString QLocale::createSeparatedList(const QStringList &list) const { #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { - QVariant res; - res = systemLocale()->query(QSystemLocale::ListToSeparatedString, QVariant::fromValue(list)); + QVariant res = + systemLocale()->query(QSystemLocale::ListToSeparatedString, QVariant::fromValue(list)); if (!res.isNull()) return res.toString(); @@ -1072,12 +1085,20 @@ QString QLocale::createSeparatedList(const QStringList &list) const if (size == 1) { return list.at(0); } else if (size == 2) { - QString format = getLocaleData(list_pattern_part_data + d->m_data->m_list_pattern_part_two_idx, d->m_data->m_list_pattern_part_two_size); + QString format = getLocaleData( + list_pattern_part_data + d->m_data->m_list_pattern_part_two_idx, + d->m_data->m_list_pattern_part_two_size); return format.arg(list.at(0), list.at(1)); } else if (size > 2) { - QString formatStart = getLocaleData(list_pattern_part_data + d->m_data->m_list_pattern_part_start_idx, d->m_data->m_list_pattern_part_start_size); - QString formatMid = getLocaleData(list_pattern_part_data + d->m_data->m_list_pattern_part_mid_idx, d->m_data->m_list_pattern_part_mid_size); - QString formatEnd = getLocaleData(list_pattern_part_data + d->m_data->m_list_pattern_part_end_idx, d->m_data->m_list_pattern_part_end_size); + QString formatStart = getLocaleData( + list_pattern_part_data + d->m_data->m_list_pattern_part_start_idx, + d->m_data->m_list_pattern_part_start_size); + QString formatMid = getLocaleData( + list_pattern_part_data + d->m_data->m_list_pattern_part_mid_idx, + d->m_data->m_list_pattern_part_mid_size); + QString formatEnd = getLocaleData( + list_pattern_part_data + d->m_data->m_list_pattern_part_end_idx, + d->m_data->m_list_pattern_part_end_size); QString result = formatStart.arg(list.at(0), list.at(1)); for (int i = 2; i < size - 1; ++i) result = formatMid.arg(result, list.at(i)); @@ -1187,7 +1208,8 @@ static qulonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool template static inline T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok) { - using Int64 = typename std::conditional::value, qulonglong, qlonglong>::type; + using Int64 = + typename std::conditional::value, qulonglong, qlonglong>::type; // we select the right overload by the last, unused parameter Int64 val = toIntegral_helper(d->m_data, str, ok, d->m_numberOptions, Int64()); @@ -1203,8 +1225,8 @@ T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok) /*! \since 4.8 - Returns the dash-separated language, script and country (and possibly other BCP47 fields) - of this locale as a string. + Returns the dash-separated language, script and country (and possibly other + BCP47 fields) of this locale as a string. Unlike the uiLanguages() the returned value of the bcp47Name() represents the locale name of the QLocale data but not the language the user-interface @@ -1966,7 +1988,8 @@ QString QLocale::toString(const QDate &date, FormatType format) const #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QVariant res = systemLocale()->query(format == LongFormat - ? QSystemLocale::DateToStringLong : QSystemLocale::DateToStringShort, + ? QSystemLocale::DateToStringLong + : QSystemLocale::DateToStringShort, date); if (!res.isNull()) return res.toString(); @@ -2094,7 +2117,8 @@ QString QLocale::toString(const QTime &time, FormatType format) const #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QVariant res = systemLocale()->query(format == LongFormat - ? QSystemLocale::TimeToStringLong : QSystemLocale::TimeToStringShort, + ? QSystemLocale::TimeToStringLong + : QSystemLocale::TimeToStringShort, time); if (!res.isNull()) return res.toString(); @@ -2121,7 +2145,8 @@ QString QLocale::dateFormat(FormatType format) const #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QVariant res = systemLocale()->query(format == LongFormat - ? QSystemLocale::DateFormatLong : QSystemLocale::DateFormatShort, + ? QSystemLocale::DateFormatLong + : QSystemLocale::DateFormatShort, QVariant()); if (!res.isNull()) return res.toString(); @@ -2158,7 +2183,8 @@ QString QLocale::timeFormat(FormatType format) const #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QVariant res = systemLocale()->query(format == LongFormat - ? QSystemLocale::TimeFormatLong : QSystemLocale::TimeFormatShort, + ? QSystemLocale::TimeFormatLong + : QSystemLocale::TimeFormatShort, QVariant()); if (!res.isNull()) return res.toString(); @@ -2499,8 +2525,8 @@ QString QLocale::toString(double i, char f, int prec) const /*! Returns a QLocale object initialized to the system locale. - On Windows and Mac, this locale will use the decimal/grouping characters and date/time - formats specified in the system configuration panel. + On Windows and Mac, this locale will use the decimal/grouping characters and + date/time formats specified in the system configuration panel. \sa c() */ @@ -2521,10 +2547,12 @@ QLocale QLocale::system() script and \a country. Getting a list of all locales: - QList allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry); + QList allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, + QLocale::AnyCountry); Getting a list of locales suitable for Russia: - QList locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::Russia); + QList locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, + QLocale::Russia); */ QList QLocale::matchingLocales(QLocale::Language language, QLocale::Script script, @@ -2538,8 +2566,10 @@ QList QLocale::matchingLocales(QLocale::Language language, return QList() << QLocale(QLocale::C); QList result; - if (language == QLocale::AnyLanguage && script == QLocale::AnyScript && country == QLocale::AnyCountry) + if (language == QLocale::AnyLanguage && script == QLocale::AnyScript + && country == QLocale::AnyCountry) { result.reserve(locale_data_size); + } const QLocaleData *data = locale_data + locale_index[language]; while ( (data != locale_data + locale_data_size) && (language == QLocale::AnyLanguage || data->m_language_id == uint(language))) { @@ -2599,7 +2629,8 @@ QString QLocale::monthName(int month, FormatType type) const #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QVariant res = systemLocale()->query(type == LongFormat - ? QSystemLocale::MonthNameLong : QSystemLocale::MonthNameShort, + ? QSystemLocale::MonthNameLong + : QSystemLocale::MonthNameShort, month); if (!res.isNull()) return res.toString(); @@ -2645,7 +2676,8 @@ QString QLocale::standaloneMonthName(int month, FormatType type) const #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QVariant res = systemLocale()->query(type == LongFormat - ? QSystemLocale::StandaloneMonthNameLong : QSystemLocale::StandaloneMonthNameShort, + ? QSystemLocale::StandaloneMonthNameLong + : QSystemLocale::StandaloneMonthNameShort, month); if (!res.isNull()) return res.toString(); @@ -2692,7 +2724,8 @@ QString QLocale::dayName(int day, FormatType type) const #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QVariant res = systemLocale()->query(type == LongFormat - ? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort, + ? QSystemLocale::DayNameLong + : QSystemLocale::DayNameShort, day); if (!res.isNull()) return res.toString(); @@ -2741,7 +2774,8 @@ QString QLocale::standaloneDayName(int day, FormatType type) const #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QVariant res = systemLocale()->query(type == LongFormat - ? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort, + ? QSystemLocale::DayNameLong + : QSystemLocale::DayNameShort, day); if (!res.isNull()) return res.toString(); @@ -3025,7 +3059,8 @@ QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &da case 4: { const int yr = date.year(); const int len = (yr < 0) ? 5 : 4; - result.append(m_data->longLongToString(yr, -1, 10, len, QLocaleData::ZeroPadded)); + result.append(m_data->longLongToString(yr, -1, 10, len, + QLocaleData::ZeroPadded)); break; } case 2: @@ -3047,7 +3082,8 @@ QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &da result.append(m_data->longLongToString(date.month())); break; case 2: - result.append(m_data->longLongToString(date.month(), -1, 10, 2, QLocaleData::ZeroPadded)); + result.append(m_data->longLongToString(date.month(), -1, 10, 2, + QLocaleData::ZeroPadded)); break; case 3: result.append(q->monthName(date.month(), QLocale::ShortFormat)); @@ -3066,7 +3102,8 @@ QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &da result.append(m_data->longLongToString(date.day())); break; case 2: - result.append(m_data->longLongToString(date.day(), -1, 10, 2, QLocaleData::ZeroPadded)); + result.append(m_data->longLongToString(date.day(), -1, 10, 2, + QLocaleData::ZeroPadded)); break; case 3: result.append(q->dayName(date.dayOfWeek(), QLocale::ShortFormat)); @@ -3099,7 +3136,8 @@ QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &da result.append(m_data->longLongToString(hour)); break; case 2: - result.append(m_data->longLongToString(hour, -1, 10, 2, QLocaleData::ZeroPadded)); + result.append(m_data->longLongToString(hour, -1, 10, 2, + QLocaleData::ZeroPadded)); break; } break; @@ -3112,7 +3150,8 @@ QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &da result.append(m_data->longLongToString(time.hour())); break; case 2: - result.append(m_data->longLongToString(time.hour(), -1, 10, 2, QLocaleData::ZeroPadded)); + result.append(m_data->longLongToString(time.hour(), -1, 10, 2, + QLocaleData::ZeroPadded)); break; } break; @@ -3125,7 +3164,8 @@ QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &da result.append(m_data->longLongToString(time.minute())); break; case 2: - result.append(m_data->longLongToString(time.minute(), -1, 10, 2, QLocaleData::ZeroPadded)); + result.append(m_data->longLongToString(time.minute(), -1, 10, 2, + QLocaleData::ZeroPadded)); break; } break; @@ -3138,42 +3178,32 @@ QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &da result.append(m_data->longLongToString(time.second())); break; case 2: - result.append(m_data->longLongToString(time.second(), -1, 10, 2, QLocaleData::ZeroPadded)); + result.append(m_data->longLongToString(time.second(), -1, 10, 2, + QLocaleData::ZeroPadded)); break; } break; case 'a': used = true; - if (i + 1 < format.size() && format.at(i + 1).unicode() == 'p') { - repeat = 2; - } else { - repeat = 1; - } + repeat = format.mid(i + 1).startsWith(QLatin1Char('p')) ? 2 : 1; result.append(time.hour() < 12 ? q->amText().toLower() : q->pmText().toLower()); break; case 'A': used = true; - if (i + 1 < format.size() && format.at(i + 1).unicode() == 'P') { - repeat = 2; - } else { - repeat = 1; - } + repeat = format.mid(i + 1).startsWith(QLatin1Char('P')) ? 2 : 1; result.append(time.hour() < 12 ? q->amText().toUpper() : q->pmText().toUpper()); break; case 'z': used = true; - if (repeat >= 3) { - repeat = 3; - } else { - repeat = 1; - } + repeat = (repeat >= 3) ? 3 : 1; // note: the millisecond component is treated like the decimal part of the seconds // so ms == 2 is always printed as "002", but ms == 200 can be either "2" or "200" - result.append(m_data->longLongToString(time.msec(), -1, 10, 3, QLocaleData::ZeroPadded)); + result.append(m_data->longLongToString(time.msec(), -1, 10, 3, + QLocaleData::ZeroPadded)); if (repeat == 1) { if (result.endsWith(zero())) result.chop(1); @@ -3187,20 +3217,16 @@ QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &da used = true; repeat = 1; // If we have a QDateTime use the time spec otherwise use the current system tzname - if (formatDate) { - result.append(datetime.timeZoneAbbreviation()); - } else { - result.append(QDateTime::currentDateTime().timeZoneAbbreviation()); - } + result.append(formatDate ? datetime.timeZoneAbbreviation() + : QDateTime::currentDateTime().timeZoneAbbreviation()); break; default: break; } } - if (!used) { + if (!used) result.append(QString(repeat, c)); - } i += repeat; } @@ -3216,7 +3242,8 @@ QString QLocaleData::doubleToString(double d, int precision, DoubleForm form, QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const QChar minus, const QChar exponential, const QChar group, const QChar decimal, - double d, int precision, DoubleForm form, int width, unsigned flags) + double d, int precision, DoubleForm form, int width, + unsigned flags) { if (precision != QLocale::FloatingPointShortest && precision < 0) precision = 6; @@ -3589,11 +3616,14 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o return false; // check distance from the last separator or from the beginning of the digits - // ### FIXME: Some locales allow other groupings! See https://en.wikipedia.org/wiki/Thousands_separator + // ### FIXME: Some locales allow other groupings! + // See https://en.wikipedia.org/wiki/Thousands_separator if (last_separator_idx != -1 && idx - last_separator_idx != 4) return false; - if (last_separator_idx == -1 && (start_of_digits_idx == -1 || idx - start_of_digits_idx > 3)) + if (last_separator_idx == -1 + && (start_of_digits_idx == -1 || idx - start_of_digits_idx > 3)) { return false; + } last_separator_idx = idx; ++group_cnt; @@ -3603,7 +3633,8 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o continue; } else if (out == '.' || out == 'e' || out == 'E') { // check distance from the last separator - // ### FIXME: Some locales allow other groupings! See https://en.wikipedia.org/wiki/Thousands_separator + // ### FIXME: Some locales allow other groupings! + // See https://en.wikipedia.org/wiki/Thousands_separator if (last_separator_idx != -1 && idx - last_separator_idx != 4) return false; @@ -3663,9 +3694,10 @@ bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray // The only non-digit character after the 'e' can be '+' or '-'. // If a zero is directly after that, then the exponent is zero-padded. - if ((number_options & QLocale::RejectLeadingZeroInExponent) && c == '0' && eCnt > 0 && - !lastWasDigit) + if ((number_options & QLocale::RejectLeadingZeroInExponent) + && c == '0' && eCnt > 0 && !lastWasDigit) { return false; + } lastWasDigit = true; } else { @@ -3917,7 +3949,8 @@ QString QLocale::toCurrencyString(qlonglong value, const QString &symbol) const #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QSystemLocale::CurrencyToStringArgument arg(value, symbol); - QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg)); + QVariant res = + systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg)); if (!res.isNull()) return res.toString(); } @@ -3947,7 +3980,8 @@ QString QLocale::toCurrencyString(qulonglong value, const QString &symbol) const #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QSystemLocale::CurrencyToStringArgument arg(value, symbol); - QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg)); + QVariant res = + systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg)); if (!res.isNull()) return res.toString(); } @@ -3989,7 +4023,8 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci #ifndef QT_NO_SYSTEMLOCALE if (d->m_data == systemData()) { QSystemLocale::CurrencyToStringArgument arg(value, symbol); - QVariant res = systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg)); + QVariant res = + systemLocale()->query(QSystemLocale::CurrencyToString, QVariant::fromValue(arg)); if (!res.isNull()) return res.toString(); } @@ -4126,7 +4161,8 @@ QStringList QLocale::uiLanguages() const } } #endif - QLocaleId id = QLocaleId::fromIds(d->m_data->m_language_id, d->m_data->m_script_id, d->m_data->m_country_id); + QLocaleId id = QLocaleId::fromIds(d->m_data->m_language_id, d->m_data->m_script_id, + d->m_data->m_country_id); const QLocaleId max = id.withLikelySubtagsAdded(); const QLocaleId min = max.withLikelySubtagsRemoved(); @@ -4182,7 +4218,8 @@ QString QLocale::nativeLanguageName() const return res.toString(); } #endif - return getLocaleData(endonyms_data + d->m_data->m_language_endonym_idx, d->m_data->m_language_endonym_size); + return getLocaleData(endonyms_data + d->m_data->m_language_endonym_idx, + d->m_data->m_language_endonym_size); } /*! @@ -4202,7 +4239,8 @@ QString QLocale::nativeCountryName() const return res.toString(); } #endif - return getLocaleData(endonyms_data + d->m_data->m_country_endonym_idx, d->m_data->m_country_endonym_size); + return getLocaleData(endonyms_data + d->m_data->m_country_endonym_idx, + d->m_data->m_country_endonym_size); } #ifndef QT_NO_DEBUG_STREAM diff --git a/src/corelib/tools/qlocale.h b/src/corelib/text/qlocale.h similarity index 100% rename from src/corelib/tools/qlocale.h rename to src/corelib/text/qlocale.h diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/text/qlocale.qdoc similarity index 100% rename from src/corelib/tools/qlocale.qdoc rename to src/corelib/text/qlocale.qdoc diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/text/qlocale_data_p.h similarity index 100% rename from src/corelib/tools/qlocale_data_p.h rename to src/corelib/text/qlocale_data_p.h diff --git a/src/corelib/tools/qlocale_icu.cpp b/src/corelib/text/qlocale_icu.cpp similarity index 100% rename from src/corelib/tools/qlocale_icu.cpp rename to src/corelib/text/qlocale_icu.cpp diff --git a/src/corelib/tools/qlocale_mac.mm b/src/corelib/text/qlocale_mac.mm similarity index 100% rename from src/corelib/tools/qlocale_mac.mm rename to src/corelib/text/qlocale_mac.mm diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/text/qlocale_p.h similarity index 98% rename from src/corelib/tools/qlocale_p.h rename to src/corelib/text/qlocale_p.h index 1e3da35a024..37afb8542b6 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/text/qlocale_p.h @@ -285,9 +285,9 @@ public: quint16 m_language_id, m_script_id, m_country_id; // FIXME QTBUG-69324: not all unicode code-points map to single-token UTF-16 :-( - quint16 m_decimal, m_group, m_list, m_percent, m_zero, m_minus, m_plus, m_exponential; - quint16 m_quotation_start, m_quotation_end; - quint16 m_alternate_quotation_start, m_alternate_quotation_end; + char16_t m_decimal, m_group, m_list, m_percent, m_zero, m_minus, m_plus, m_exponential; + char16_t m_quotation_start, m_quotation_end; + char16_t m_alternate_quotation_start, m_alternate_quotation_end; quint16 m_list_pattern_part_start_idx, m_list_pattern_part_start_size; quint16 m_list_pattern_part_mid_idx, m_list_pattern_part_mid_size; @@ -417,7 +417,7 @@ inline char QLocaleData::digitToCLocale(QChar in) const if (in == m_group) return ','; - if (in == m_exponential || in == QChar::toUpper(m_exponential)) + if (in == m_exponential || in == QChar(QChar::toUpper(m_exponential))) return 'e'; // In several languages group() is a non-breaking space (U+00A0) or its thin diff --git a/src/corelib/tools/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp similarity index 100% rename from src/corelib/tools/qlocale_tools.cpp rename to src/corelib/text/qlocale_tools.cpp diff --git a/src/corelib/tools/qlocale_tools_p.h b/src/corelib/text/qlocale_tools_p.h similarity index 100% rename from src/corelib/tools/qlocale_tools_p.h rename to src/corelib/text/qlocale_tools_p.h diff --git a/src/corelib/tools/qlocale_unix.cpp b/src/corelib/text/qlocale_unix.cpp similarity index 100% rename from src/corelib/tools/qlocale_unix.cpp rename to src/corelib/text/qlocale_unix.cpp diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp similarity index 100% rename from src/corelib/tools/qlocale_win.cpp rename to src/corelib/text/qlocale_win.cpp diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/text/qregexp.cpp similarity index 99% rename from src/corelib/tools/qregexp.cpp rename to src/corelib/text/qregexp.cpp index dd38ba03607..d81826b47b4 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/text/qregexp.cpp @@ -2035,7 +2035,7 @@ bool QRegExpMatchState::matchHere() #ifndef QT_NO_REGEXP_CCLASS const QRegExpCharClass &cc = eng->cl.at(m ^ QRegExpEngine::CharClassBit); if (eng->cs) - inside = cc.in(ch); + inside = cc.in(QChar(ch)); else if (cc.negative()) inside = cc.in(QChar(ch).toLower()) && cc.in(QChar(ch).toUpper()); diff --git a/src/corelib/tools/qregexp.h b/src/corelib/text/qregexp.h similarity index 100% rename from src/corelib/tools/qregexp.h rename to src/corelib/text/qregexp.h diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/text/qregularexpression.cpp similarity index 100% rename from src/corelib/tools/qregularexpression.cpp rename to src/corelib/text/qregularexpression.cpp diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/text/qregularexpression.h similarity index 100% rename from src/corelib/tools/qregularexpression.h rename to src/corelib/text/qregularexpression.h diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/text/qstring.cpp similarity index 99% rename from src/corelib/tools/qstring.cpp rename to src/corelib/text/qstring.cpp index 47db97cdfce..375843e36e8 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -49,8 +49,8 @@ #include #endif #include -#include -#include "qsimd_p.h" +#include "qlocale_tools_p.h" +#include "private/qsimd_p.h" #include #include #include @@ -59,7 +59,6 @@ #include "qstringbuilder.h" #include "qstringmatcher.h" #include "qvarlengtharray.h" -#include "qtools_p.h" #include "qdebug.h" #include "qendian.h" #include "qcollator.h" @@ -2092,7 +2091,7 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out) If \a size is negative, \a unicode is assumed to point to a \\0'-terminated array and its length is determined dynamically. The terminating - nul-character is not considered part of the string. + null character is not considered part of the string. QString makes a deep copy of the string data. The unicode data is copied as is and the Byte Order Mark is preserved if present. @@ -3208,7 +3207,7 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs return remove(ch, cs); if (after.d->size == 1) - return replace(ch, after.d->data()[0], cs); + return replace(ch, after.front(), cs); if (d->size == 0) return *this; @@ -5770,7 +5769,7 @@ QString QString::trimmed_helper(QString &str) The return value is of type QCharRef, a helper class for QString. When you get an object of type QCharRef, you can use it as if it - were a QChar &. If you assign to it, the assignment will apply to + were a reference to a QChar. If you assign to it, the assignment will apply to the character in the QString from which you got the reference. \note Before Qt 5.14 it was possible to use this operator to access @@ -6666,7 +6665,7 @@ static QString detachAndConvertCase(T &str, QStringIterator it) } else if (Q_UNLIKELY(QChar::requiresSurrogates(uc))) { // so far, case convertion never changes planes (guaranteed by the qunicodetables generator) pp++; - *pp++ = QChar::lowSurrogate(uc + caseDiff); + *pp++ = QChar(QChar::lowSurrogate(uc + caseDiff)); } else { *pp++ = QChar(uc + caseDiff); } @@ -11439,7 +11438,7 @@ bool QStringRef::isRightToLeft() const \sa QString::isRightToLeft() */ -bool QtPrivate::isRightToLeft(QStringView string) +bool QtPrivate::isRightToLeft(QStringView string) noexcept { const ushort *p = reinterpret_cast(string.data()); const ushort * const end = p + string.size(); diff --git a/src/corelib/tools/qstring.h b/src/corelib/text/qstring.h similarity index 98% rename from src/corelib/tools/qstring.h rename to src/corelib/text/qstring.h index 6788e530574..88286b902ab 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/text/qstring.h @@ -89,6 +89,10 @@ class QTextCodec; class QStringRef; template class QVector; +namespace QtPrivate { +template class BoolList; +} + class QLatin1String { public: @@ -231,7 +235,7 @@ QT_DEPRECATED_X("Use QLatin1String") typedef QLatin1String QLatin1Literal; // // QLatin1String inline implementations // -inline bool QtPrivate::isLatin1(QLatin1String) noexcept +Q_DECL_CONSTEXPR bool QtPrivate::isLatin1(QLatin1String) noexcept { return true; } // @@ -333,6 +337,7 @@ public: QChar fillChar = QLatin1Char(' ')) const; Q_REQUIRED_RESULT QString arg(QLatin1String a, int fieldWidth = 0, QChar fillChar = QLatin1Char(' ')) const; +#if QT_STRINGVIEW_LEVEL < 2 Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2) const; Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2, const QString &a3) const; Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2, const QString &a3, @@ -350,6 +355,33 @@ public: Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2, const QString &a3, const QString &a4, const QString &a5, const QString &a6, const QString &a7, const QString &a8, const QString &a9) const; +#endif +private: + template + struct is_convertible_to_view_or_qstring_helper + : std::integral_constant::value || + std::is_convertible::value || + std::is_convertible::value> {}; + template + struct is_convertible_to_view_or_qstring + : is_convertible_to_view_or_qstring_helper::type> {}; +public: + template + Q_REQUIRED_RESULT +#ifdef Q_CLANG_QDOC + QString +#else + typename std::enable_if< + sizeof...(Args) >= 2 && std::is_same< + QtPrivate::BoolList::value..., true>, + QtPrivate::BoolList::value...> + >::value, + QString + >::type +#endif + arg(Args &&...args) const + { return qToStringViewIgnoringNull(*this).arg(std::forward(args)...); } #if QT_DEPRECATED_SINCE(5, 14) QT_DEPRECATED_X("Use vasprintf(), arg() or QTextStream instead") @@ -1002,11 +1034,11 @@ inline QString::QString(QLatin1String aLatin1) : d(fromLatin1_helper(aLatin1.lat inline int QString::length() const { return d->size; } inline const QChar QString::at(int i) const -{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; } +{ Q_ASSERT(uint(i) < uint(size())); return QChar(d->data()[i]); } inline const QChar QString::operator[](int i) const -{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; } +{ Q_ASSERT(uint(i) < uint(size())); return QChar(d->data()[i]); } inline const QChar QString::operator[](uint i) const -{ Q_ASSERT(i < uint(size())); return d->data()[i]; } +{ Q_ASSERT(i < uint(size())); return QChar(d->data()[i]); } inline bool QString::isEmpty() const { return d->size == 0; } inline const QChar *QString::unicode() const @@ -1053,6 +1085,7 @@ inline QString QString::arg(short a, int fieldWidth, int base, QChar fillChar) c { return arg(qlonglong(a), fieldWidth, base, fillChar); } inline QString QString::arg(ushort a, int fieldWidth, int base, QChar fillChar) const { return arg(qulonglong(a), fieldWidth, base, fillChar); } +#if QT_STRINGVIEW_LEVEL < 2 inline QString QString::arg(const QString &a1, const QString &a2) const { return qToStringViewIgnoringNull(*this).arg(a1, a2); } inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3) const @@ -1078,6 +1111,7 @@ inline QString QString::arg(const QString &a1, const QString &a2, const QString const QString &a4, const QString &a5, const QString &a6, const QString &a7, const QString &a8, const QString &a9) const { return qToStringViewIgnoringNull(*this).arg(a1, a2, a3, a4, a5, a6, a7, a8, a9); } +#endif inline QString QString::section(QChar asep, int astart, int aend, SectionFlags aflags) const { return section(QString(asep), astart, aend, aflags); } @@ -1088,7 +1122,19 @@ QT_WARNING_DISABLE_INTEL(111) // "statement is unreachable" inline int QString::toWCharArray(wchar_t *array) const { - return QStringView(*this).toWCharArray(array); + return qToStringViewIgnoringNull(*this).toWCharArray(array); +} + +int QStringView::toWCharArray(wchar_t *array) const +{ + if (sizeof(wchar_t) == sizeof(QChar)) { + if (auto src = data()) + memcpy(array, src, sizeof(QChar) * size()); + return size(); + } else { + return QString::toUcs4_helper(reinterpret_cast(data()), int(size()), + reinterpret_cast(array)); + } } QT_WARNING_POP @@ -1118,11 +1164,11 @@ public: { using namespace QtPrivate::DeprecatedRefClassBehavior; if (Q_LIKELY(i < s.d->size)) - return s.d->data()[i]; + return QChar(s.d->data()[i]); #ifdef QT_DEBUG warn(WarningType::OutOfRange, EmittingClass::QCharRef); #endif - return 0; + return QChar(); } inline QCharRef &operator=(QChar c) { @@ -2014,6 +2060,7 @@ Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString argToQStringDispatch(StringView patter return QtPrivate::argToQString(pattern, sizeof...(Args), argBases); } + inline QStringViewArg qStringLikeToArg(const QString &s) noexcept { return QStringViewArg{qToStringViewIgnoringNull(s)}; } Q_DECL_CONSTEXPR inline QStringViewArg qStringLikeToArg(QStringView s) noexcept { return QStringViewArg{s}; } inline QStringViewArg qStringLikeToArg(const QChar &c) noexcept { return QStringViewArg{QStringView{&c, 1}}; } Q_DECL_CONSTEXPR inline QLatin1StringArg qStringLikeToArg(QLatin1String s) noexcept { return QLatin1StringArg{s}; } diff --git a/src/corelib/tools/qstring_compat.cpp b/src/corelib/text/qstring_compat.cpp similarity index 100% rename from src/corelib/tools/qstring_compat.cpp rename to src/corelib/text/qstring_compat.cpp diff --git a/src/corelib/tools/qstring_mips_dsp_asm.S b/src/corelib/text/qstring_mips_dsp_asm.S similarity index 100% rename from src/corelib/tools/qstring_mips_dsp_asm.S rename to src/corelib/text/qstring_mips_dsp_asm.S diff --git a/src/corelib/tools/qstringalgorithms.h b/src/corelib/text/qstringalgorithms.h similarity index 93% rename from src/corelib/tools/qstringalgorithms.h rename to src/corelib/text/qstringalgorithms.h index 2b480b1e4c2..d54e376aa91 100644 --- a/src/corelib/tools/qstringalgorithms.h +++ b/src/corelib/text/qstringalgorithms.h @@ -92,12 +92,13 @@ Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLatin1(QStringView str); Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToUtf8(QStringView str); Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLocal8Bit(QStringView str); Q_REQUIRED_RESULT Q_CORE_EXPORT QVector convertToUcs4(QStringView str); -Q_REQUIRED_RESULT Q_CORE_EXPORT bool isRightToLeft(QStringView string); -Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QLatin1String s) noexcept; -Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QStringView s) noexcept; -Q_REQUIRED_RESULT bool isLatin1(QLatin1String s) noexcept; // in qstring.h -Q_REQUIRED_RESULT Q_CORE_EXPORT bool isLatin1(QStringView s) noexcept; +Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isRightToLeft(QStringView string) noexcept; + +Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QLatin1String s) noexcept; +Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QStringView s) noexcept; +Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline bool isLatin1(QLatin1String s) noexcept; +Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isLatin1(QStringView s) noexcept; } // namespace QtPRivate diff --git a/src/corelib/tools/qstringalgorithms_p.h b/src/corelib/text/qstringalgorithms_p.h similarity index 100% rename from src/corelib/tools/qstringalgorithms_p.h rename to src/corelib/text/qstringalgorithms_p.h diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/text/qstringbuilder.cpp similarity index 100% rename from src/corelib/tools/qstringbuilder.cpp rename to src/corelib/text/qstringbuilder.cpp diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/text/qstringbuilder.h similarity index 100% rename from src/corelib/tools/qstringbuilder.h rename to src/corelib/text/qstringbuilder.h diff --git a/src/corelib/tools/qstringiterator.qdoc b/src/corelib/text/qstringiterator.qdoc similarity index 100% rename from src/corelib/tools/qstringiterator.qdoc rename to src/corelib/text/qstringiterator.qdoc diff --git a/src/corelib/tools/qstringiterator_p.h b/src/corelib/text/qstringiterator_p.h similarity index 100% rename from src/corelib/tools/qstringiterator_p.h rename to src/corelib/text/qstringiterator_p.h diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/text/qstringlist.cpp similarity index 100% rename from src/corelib/tools/qstringlist.cpp rename to src/corelib/text/qstringlist.cpp diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/text/qstringlist.h similarity index 100% rename from src/corelib/tools/qstringlist.h rename to src/corelib/text/qstringlist.h diff --git a/src/corelib/tools/qstringliteral.h b/src/corelib/text/qstringliteral.h similarity index 100% rename from src/corelib/tools/qstringliteral.h rename to src/corelib/text/qstringliteral.h diff --git a/src/corelib/tools/qstringmatcher.cpp b/src/corelib/text/qstringmatcher.cpp similarity index 100% rename from src/corelib/tools/qstringmatcher.cpp rename to src/corelib/text/qstringmatcher.cpp diff --git a/src/corelib/tools/qstringmatcher.h b/src/corelib/text/qstringmatcher.h similarity index 100% rename from src/corelib/tools/qstringmatcher.h rename to src/corelib/text/qstringmatcher.h diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/text/qstringview.cpp similarity index 97% rename from src/corelib/tools/qstringview.cpp rename to src/corelib/text/qstringview.cpp index cc852dd042f..75de8275838 100644 --- a/src/corelib/tools/qstringview.cpp +++ b/src/corelib/text/qstringview.cpp @@ -57,9 +57,8 @@ QT_BEGIN_NAMESPACE The UTF-16 string may be represented as an array (or an array-compatible data-structure such as QString, - std::basic_string, etc.) of QChar, \c ushort, \c char16_t (on compilers that - support C++11 Unicode strings) or (on platforms, such as Windows, - where it is a 16-bit type) \c wchar_t. + std::basic_string, etc.) of QChar, \c ushort, \c char16_t or + (on platforms, such as Windows, where it is a 16-bit type) \c wchar_t. QStringView is designed as an interface type; its main use-case is as a function parameter type. When QStringViews are used as automatic @@ -115,8 +114,7 @@ QT_BEGIN_NAMESPACE /*! \typedef QStringView::storage_type - Alias for \c{char16_t} for non-Windows or if Q_COMPILER_UNICODE_STRINGS - is defined. Otherwise, alias for \c{wchar_t}. + Alias for \c{char16_t}. */ /*! @@ -532,6 +530,7 @@ QT_BEGIN_NAMESPACE /*! \fn QString QStringView::arg(Args &&...args) const \fn QString QLatin1String::arg(Args &&...args) const + \fn QString QString::arg(Args &&...args) const \since 5.14 Replaces occurrences of \c{%N} in this string with the corresponding @@ -539,8 +538,8 @@ QT_BEGIN_NAMESPACE the \a args replaces the \c{%N} with the lowest \c{N} (all of them), the second of the \a args the \c{%N} with the next-lowest \c{N} etc. - \c Args can consist of anything that implicitly converts to QStringView - or QLatin1String. + \c Args can consist of anything that implicitly converts to QString, + QStringView or QLatin1String. In addition, the following types are also supported: QChar, QLatin1Char. @@ -866,11 +865,12 @@ QT_BEGIN_NAMESPACE */ /*! + \fn QStringView::toWCharArray(wchar_t *array) const \since 5.14 Transcribes this string into the given \a array. - Caller is responsible for ensuring \a array is large enough to hold the + The caller is responsible for ensuring \a array is large enough to hold the \c wchar_t encoding of this string (allocating the array with the same length as the string is always sufficient). The array is encoded in UTF-16 on platforms where \c wchar_t is 2 bytes wide (e.g. Windows); otherwise (Unix @@ -884,15 +884,4 @@ QT_BEGIN_NAMESPACE \sa QString::toWCharArray() */ -int QStringView::toWCharArray(wchar_t *array) const -{ - if (sizeof(wchar_t) == sizeof(QChar)) { - memcpy(array, data(), sizeof(QChar) * size()); - return size(); - } else { - return QString::toUcs4_helper(reinterpret_cast(data()), int(size()), - reinterpret_cast(array)); - } -} - QT_END_NAMESPACE diff --git a/src/corelib/tools/qstringview.h b/src/corelib/text/qstringview.h similarity index 98% rename from src/corelib/tools/qstringview.h rename to src/corelib/text/qstringview.h index b84b2995b9c..0a82ac42012 100644 --- a/src/corelib/tools/qstringview.h +++ b/src/corelib/text/qstringview.h @@ -62,9 +62,7 @@ struct IsCompatibleCharTypeHelper : std::integral_constant::value || std::is_same::value || -#if defined(Q_COMPILER_UNICODE_STRINGS) std::is_same::value || -#endif (std::is_same::value && sizeof(wchar_t) == sizeof(QChar))> {}; template struct IsCompatibleCharType @@ -105,11 +103,7 @@ struct IsCompatibleStdBasicString class QStringView { public: -#if defined(Q_OS_WIN) && !defined(Q_COMPILER_UNICODE_STRINGS) - typedef wchar_t storage_type; -#else typedef char16_t storage_type; -#endif typedef const QChar value_type; typedef std::ptrdiff_t difference_type; typedef qsizetype size_type; @@ -294,7 +288,7 @@ public: Q_REQUIRED_RESULT bool isRightToLeft() const noexcept { return QtPrivate::isRightToLeft(*this); } - Q_REQUIRED_RESULT Q_CORE_EXPORT int toWCharArray(wchar_t *array) const; + Q_REQUIRED_RESULT inline int toWCharArray(wchar_t *array) const; // defined in qstring.h // // STL compatibility API: diff --git a/src/corelib/tools/qt_attribution.json b/src/corelib/text/qt_attribution.json similarity index 100% rename from src/corelib/tools/qt_attribution.json rename to src/corelib/text/qt_attribution.json diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/text/qtextboundaryfinder.cpp similarity index 100% rename from src/corelib/tools/qtextboundaryfinder.cpp rename to src/corelib/text/qtextboundaryfinder.cpp diff --git a/src/corelib/tools/qtextboundaryfinder.h b/src/corelib/text/qtextboundaryfinder.h similarity index 100% rename from src/corelib/tools/qtextboundaryfinder.h rename to src/corelib/text/qtextboundaryfinder.h diff --git a/src/corelib/tools/qunicodetables.cpp b/src/corelib/text/qunicodetables.cpp similarity index 100% rename from src/corelib/tools/qunicodetables.cpp rename to src/corelib/text/qunicodetables.cpp diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/text/qunicodetables_p.h similarity index 100% rename from src/corelib/tools/qunicodetables_p.h rename to src/corelib/text/qunicodetables_p.h diff --git a/src/corelib/tools/qunicodetools.cpp b/src/corelib/text/qunicodetools.cpp similarity index 100% rename from src/corelib/tools/qunicodetools.cpp rename to src/corelib/text/qunicodetools.cpp diff --git a/src/corelib/tools/qunicodetools_p.h b/src/corelib/text/qunicodetools_p.h similarity index 100% rename from src/corelib/tools/qunicodetools_p.h rename to src/corelib/text/qunicodetools_p.h diff --git a/src/corelib/tools/qvsnprintf.cpp b/src/corelib/text/qvsnprintf.cpp similarity index 100% rename from src/corelib/tools/qvsnprintf.cpp rename to src/corelib/text/qvsnprintf.cpp diff --git a/src/corelib/text/text.pri b/src/corelib/text/text.pri new file mode 100644 index 00000000000..25e281f37a2 --- /dev/null +++ b/src/corelib/text/text.pri @@ -0,0 +1,100 @@ +# Qt text / string / character / unicode / byte array module + +HEADERS += \ + text/qbytearray.h \ + text/qbytearray_p.h \ + text/qbytearraylist.h \ + text/qbytearraymatcher.h \ + text/qbytedata_p.h \ + text/qchar.h \ + text/qcollator.h \ + text/qcollator_p.h \ + text/qdoublescanprint_p.h \ + text/qlocale.h \ + text/qlocale_p.h \ + text/qlocale_tools_p.h \ + text/qlocale_data_p.h \ + text/qregexp.h \ + text/qstring.h \ + text/qstringalgorithms.h \ + text/qstringalgorithms_p.h \ + text/qstringbuilder.h \ + text/qstringiterator_p.h \ + text/qstringlist.h \ + text/qstringliteral.h \ + text/qstringmatcher.h \ + text/qstringview.h \ + text/qtextboundaryfinder.h \ + text/qunicodetables_p.h \ + text/qunicodetools_p.h + + +SOURCES += \ + text/qbytearray.cpp \ + text/qbytearraylist.cpp \ + text/qbytearraymatcher.cpp \ + text/qcollator.cpp \ + text/qlocale.cpp \ + text/qlocale_tools.cpp \ + text/qregexp.cpp \ + text/qstring.cpp \ + text/qstringbuilder.cpp \ + text/qstringlist.cpp \ + text/qstringview.cpp \ + text/qtextboundaryfinder.cpp \ + text/qunicodetools.cpp \ + text/qvsnprintf.cpp + +NO_PCH_SOURCES += text/qstring_compat.cpp +false: SOURCES += $$NO_PCH_SOURCES # Hack for QtCreator + +!nacl:macos: { + SOURCES += text/qlocale_mac.mm +} +else:unix { + SOURCES += text/qlocale_unix.cpp +} +else:win32 { + SOURCES += text/qlocale_win.cpp +} else:integrity { + SOURCES += text/qlocale_unix.cpp +} + +qtConfig(icu) { + QMAKE_USE_PRIVATE += icu + + SOURCES += text/qlocale_icu.cpp \ + text/qcollator_icu.cpp +} else: win32 { + SOURCES += text/qcollator_win.cpp +} else: macos { + SOURCES += text/qcollator_macx.cpp +} else { + SOURCES += text/qcollator_posix.cpp +} + +qtConfig(regularexpression) { + QMAKE_USE_PRIVATE += pcre2 + + HEADERS += \ + text/qregularexpression.h + SOURCES += text/qregularexpression.cpp +} + +INCLUDEPATH += ../3rdparty/harfbuzz/src +HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h +SOURCES += ../3rdparty/harfbuzz/src/harfbuzz-buffer.c \ + ../3rdparty/harfbuzz/src/harfbuzz-gdef.c \ + ../3rdparty/harfbuzz/src/harfbuzz-gsub.c \ + ../3rdparty/harfbuzz/src/harfbuzz-gpos.c \ + ../3rdparty/harfbuzz/src/harfbuzz-impl.c \ + ../3rdparty/harfbuzz/src/harfbuzz-open.c \ + ../3rdparty/harfbuzz/src/harfbuzz-stream.c \ + ../3rdparty/harfbuzz/src/harfbuzz-shaper-all.cpp \ + text/qharfbuzz.cpp +HEADERS += text/qharfbuzz_p.h + +TR_EXCLUDE += ../3rdparty/* + +# MIPS DSP +MIPS_DSP_ASM += text/qstring_mips_dsp_asm.S diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp deleted file mode 100644 index 3ece30c01c7..00000000000 --- a/src/corelib/thread/qmutexpool.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qatomic.h" -#include "qmutexpool_p.h" - -QT_BEGIN_NAMESPACE - -Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (QMutex::Recursive)) - -/*! - \class QMutexPool - \inmodule QtCore - \brief The QMutexPool class provides a pool of QMutex objects. - - \internal - - \ingroup thread - - QMutexPool is a convenience class that provides access to a fixed - number of QMutex objects. - - Typical use of a QMutexPool is in situations where it is not - possible or feasible to use one QMutex for every protected object. - The mutex pool will return a mutex based on the address of the - object that needs protection. - - For example, consider this simple class: - - \snippet code/src_corelib_thread_qmutexpool.cpp 0 - - Adding a QMutex member to the Number class does not make sense, - because it is so small. However, in order to ensure that access to - each Number is protected, you need to use a mutex. In this case, a - QMutexPool would be ideal. - - Code to calculate the square of a number would then look something - like this: - - \snippet code/src_corelib_thread_qmutexpool.cpp 1 - - This function will safely calculate the square of a number, since - it uses a mutex from a QMutexPool. The mutex is locked and - unlocked automatically by the QMutexLocker class. See the - QMutexLocker documentation for more details. -*/ - -/*! - Constructs a QMutexPool, reserving space for \a size QMutexes. All - mutexes in the pool are created with \a recursionMode. By default, - all mutexes are non-recursive. - - The QMutexes are created when needed, and deleted when the - QMutexPool is destructed. -*/ -QMutexPool::QMutexPool(QMutex::RecursionMode recursionMode, int size) - : mutexes(size), recursionMode(recursionMode) -{ - for (int index = 0; index < mutexes.count(); ++index) { - mutexes[index].storeRelaxed(0); - } -} - -/*! - Destructs a QMutexPool. All QMutexes that were created by the pool - are deleted. -*/ -QMutexPool::~QMutexPool() -{ - for (int index = 0; index < mutexes.count(); ++index) - delete mutexes[index].loadAcquire(); -} - -/*! - Returns the global QMutexPool instance. -*/ -QMutexPool *QMutexPool::instance() -{ - return globalMutexPool(); -} - -/*! - \fn QMutexPool::get(const void *address) - Returns a QMutex from the pool. QMutexPool uses the value \a address - to determine which mutex is returned from the pool. -*/ - -/*! - \internal - create the mutex for the given index - */ -QMutex *QMutexPool::createMutex(int index) -{ - // mutex not created, create one - QMutex *newMutex = new QMutex(recursionMode); - if (!mutexes[index].testAndSetRelease(nullptr, newMutex)) { - delete newMutex; - return mutexes[index].loadAcquire(); - } else { - return newMutex; - } -} - -/*! - Returns a QMutex from the global mutex pool. -*/ -QMutex *QMutexPool::globalInstanceGet(const void *address) -{ - QMutexPool * const globalInstance = globalMutexPool(); - if (globalInstance == 0) - return 0; - return globalInstance->get(address); -} - -QT_END_NAMESPACE diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index e0a67388d49..570c5262257 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -159,7 +159,7 @@ public: void relock() {} void unlock() {} - static bool relock(QBasicMutex *, QBasicMutex *) {} + static bool relock(QBasicMutex *, QBasicMutex *) { return false; } }; using QBasicMutexLocker = QMutexLocker; diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 280c785049b..9fd1dd059dc 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -851,7 +851,7 @@ Qt::HANDLE QThread::currentThreadId() noexcept QThread *QThread::currentThread() { - return QThreadData::current()->thread; + return QThreadData::current()->thread.loadAcquire(); } int QThread::idealThreadCount() noexcept @@ -883,11 +883,11 @@ QThreadData *QThreadData::current(bool createIfNecessary) if (!data && createIfNecessary) { data = new QThreadData; data->thread = new QAdoptedThread(data); - data->threadId.storeRelaxed(Qt::HANDLE(data->thread)); + data->threadId.storeRelaxed(Qt::HANDLE(data->thread.loadAcquire())); data->deref(); data->isAdopted = true; - if (!QCoreApplicationPrivate::theMainThread) - QCoreApplicationPrivate::theMainThread = data->thread.loadRelaxed(); + if (!QCoreApplicationPrivate::theMainThread.loadAcquire()) + QCoreApplicationPrivate::theMainThread.storeRelease(data->thread.loadRelaxed()); } return data; } diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 22f0de05231..d11e6500ff4 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -28,7 +28,6 @@ qtConfig(thread) { thread/qbasicatomic.h \ thread/qfutex_p.h \ thread/qgenericatomic.h \ - thread/qmutexpool_p.h \ thread/qmutex_p.h \ thread/qorderedmutexlocker_p.h \ thread/qreadwritelock_p.h \ @@ -40,7 +39,6 @@ qtConfig(thread) { SOURCES += \ thread/qatomic.cpp \ thread/qmutex.cpp \ - thread/qmutexpool.cpp \ thread/qreadwritelock.cpp \ thread/qsemaphore.cpp \ thread/qthreadpool.cpp \ diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 31206f779d3..64943bdaaf4 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -346,11 +346,10 @@ static constexpr int daysInUsualMonth(int month) // (February isn't usual.) setDate(). The fromString() function returns a QDate given a string and a date format which is used to interpret the date within the string. - The year(), month(), and day() functions provide access to the - year, month, and day numbers. Also, dayOfWeek() and dayOfYear() - functions are provided. The same information is provided in - textual format by the toString(), shortDayName(), longDayName(), - shortMonthName(), and longMonthName() functions. + The year(), month(), and day() functions provide access to the year, month, + and day numbers. Also, dayOfWeek() and dayOfYear() functions are + provided. The same information is provided in textual format by + toString(). The day and month numbers can be mapped to names using QLocale. QDate provides a full set of operators to compare two QDate objects where smaller means earlier, and larger means later. @@ -1076,11 +1075,10 @@ static QString toStringIsoDate(qint64 jd) Returns the date as a string. The \a format parameter determines the format of the string. - If the \a format is Qt::TextDate, the string is formatted in - the default way. QDate::shortDayName() and QDate::shortMonthName() - are used to generate the string, so the day and month names will - be localized names using the system locale, i.e. QLocale::system(). An - example of this formatting is "Sat May 20 1995". + If the \a format is Qt::TextDate, the string is formatted in the default + way. The day and month names will be localized names using the system + locale, i.e. QLocale::system(). An example of this formatting + is "Sat May 20 1995". If the \a format is Qt::ISODate, the string format corresponds to the ISO 8601 extended specification for representations of @@ -1112,7 +1110,7 @@ static QString toStringIsoDate(qint64 jd) range 0 to 9999. This restriction may apply to locale-aware formats as well, depending on the locale settings. - \sa fromString(), shortDayName(), shortMonthName(), QLocale::toString() + \sa fromString(), QLocale::toString() */ QString QDate::toString(Qt::DateFormat format) const { @@ -1131,7 +1129,7 @@ QString QDate::toString(Qt::DateFormat format) const case Qt::DefaultLocaleLongDate: return QLocale().toString(*this, QLocale::LongFormat); case Qt::RFC2822Date: - return QLocale::c().toString(*this, QStringViewLiteral("dd MMM yyyy")); + return QLocale::c().toString(*this, u"dd MMM yyyy"); default: #if QT_CONFIG(textdate) case Qt::TextDate: @@ -3272,10 +3270,9 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT provides functions for comparing datetimes and for manipulating a datetime by adding a number of seconds, days, months, or years. - QDateTime can describe datetimes with respect to - \l{Qt::LocalTime}{local time}, to \l{Qt::UTC}{UTC}, to a specified - \l{Qt::OffsetFromUTC}{offset from UTC} or to a specified - \l{Qt::TimeZone}{time zone}, in conjunction + QDateTime can describe datetimes with respect to \l{Qt::LocalTime}{local + time}, to \l{Qt::UTC}{UTC}, to a specified \l{Qt::OffsetFromUTC}{offset + from UTC} or to a specified \l{Qt::TimeZone}{time zone}, in conjunction with the QTimeZone class. For example, a time zone of "Europe/Berlin" will apply the daylight-saving rules as used in Germany since 1970. In contrast, an offset from UTC of +3600 seconds is one hour ahead of UTC (usually @@ -4065,12 +4062,10 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC) Returns the datetime as a string in the \a format given. - If the \a format is Qt::TextDate, the string is formatted in - the default way. QDate::shortDayName(), QDate::shortMonthName(), - and QTime::toString() are used to generate the string, so the - day and month names will be localized names using the system locale, - i.e. QLocale::system(). An example of this formatting is - "Wed May 20 03:40:13 1998". + If the \a format is Qt::TextDate, the string is formatted in the default + way. The day and month names will be localized names using the system + locale, i.e. QLocale::system(). An example of this formatting is "Wed May 20 + 03:40:13 1998". If the \a format is Qt::ISODate, the string format corresponds to the ISO 8601 extended specification for representations of @@ -4127,7 +4122,7 @@ QString QDateTime::toString(Qt::DateFormat format) const case Qt::DefaultLocaleLongDate: return QLocale().toString(*this, QLocale::LongFormat); case Qt::RFC2822Date: { - buf = QLocale::c().toString(*this, QStringViewLiteral("dd MMM yyyy hh:mm:ss ")); + buf = QLocale::c().toString(*this, u"dd MMM yyyy hh:mm:ss "); buf += toOffsetString(Qt::TextDate, offsetFromUtc()); return buf; } @@ -5239,18 +5234,14 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format) \row \li dd \li the day as number with a leading zero (01 to 31) \row \li ddd \li the abbreviated localized day name (e.g. 'Mon' to 'Sun'). - Uses QDate::shortDayName(). \row \li dddd \li the long localized day name (e.g. 'Monday' to 'Sunday'). - Uses QDate::longDayName(). \row \li M \li the month as number without a leading zero (1-12) \row \li MM \li the month as number with a leading zero (01-12) \row \li MMM \li the abbreviated localized month name (e.g. 'Jan' to 'Dec'). - Uses QDate::shortMonthName(). \row \li MMMM \li the long localized month name (e.g. 'January' to 'December'). - Uses QDate::longMonthName(). \row \li yy \li the year as two digit number (00-99) \row \li yyyy \li the year as four digit number \endtable @@ -5631,7 +5622,7 @@ QDebug operator<<(QDebug dbg, const QTime &time) QDebugStateSaver saver(dbg); dbg.nospace() << "QTime("; if (time.isValid()) - dbg.nospace() << time.toString(QStringViewLiteral("HH:mm:ss.zzz")); + dbg.nospace() << time.toString(u"HH:mm:ss.zzz"); else dbg.nospace() << "Invalid"; dbg.nospace() << ')'; @@ -5644,7 +5635,7 @@ QDebug operator<<(QDebug dbg, const QDateTime &date) dbg.nospace() << "QDateTime("; if (date.isValid()) { const Qt::TimeSpec ts = date.timeSpec(); - dbg.noquote() << date.toString(QStringViewLiteral("yyyy-MM-dd HH:mm:ss.zzz t")) + dbg.noquote() << date.toString(u"yyyy-MM-dd HH:mm:ss.zzz t") << ' ' << ts; switch (ts) { case Qt::UTC: diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc index a73ec1e22a5..c86e69f9c35 100644 --- a/src/corelib/tools/qalgorithms.qdoc +++ b/src/corelib/tools/qalgorithms.qdoc @@ -155,8 +155,8 @@ \section2 Porting guidelines - Most of the times, an application using the deprecated Qt algorithmic functions - can be easily ported to use the equivalent STL functions. You need to + Most of the time, an application using the deprecated Qt algorithmic functions + can be easily ported to use the equivalent STL functions. You need to: \list 1 \li add the \c{#include } preprocessor directive; diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h index 0322615f91c..af5173c9ad9 100644 --- a/src/corelib/tools/qarraydatapointer.h +++ b/src/corelib/tools/qarraydatapointer.h @@ -202,22 +202,11 @@ inline bool operator!=(const QArrayDataPointer &lhs, const QArrayDataPointer< } template -inline void qSwap(QArrayDataPointer &p1, QArrayDataPointer &p2) +inline void swap(QArrayDataPointer &p1, QArrayDataPointer &p2) { p1.swap(p2); } QT_END_NAMESPACE -namespace std -{ - template - inline void swap( - QT_PREPEND_NAMESPACE(QArrayDataPointer) &p1, - QT_PREPEND_NAMESPACE(QArrayDataPointer) &p2) - { - p1.swap(p2); - } -} - #endif // include guard diff --git a/src/corelib/tools/qcontainerfwd.h b/src/corelib/tools/qcontainerfwd.h index 646d8908c31..532b4c95ce4 100644 --- a/src/corelib/tools/qcontainerfwd.h +++ b/src/corelib/tools/qcontainerfwd.h @@ -47,7 +47,9 @@ QT_BEGIN_NAMESPACE template class QCache; template class QHash; +#ifndef QT_NO_LINKED_LIST template class QLinkedList; +#endif template class QList; template class QMap; template class QMultiHash; diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index c807bbd2e1f..8e00c46b41d 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -907,6 +907,10 @@ struct TCBEase : public BezierEase return BezierEase::value(x); } + QEasingCurveFunction *copy() const override + { + return new TCBEase{*this}; + } }; struct ElasticEase : public QEasingCurveFunction diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 4b4cb2d5f05..236e4331018 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -136,7 +136,7 @@ struct QHashDummyValue { }; -inline bool operator==(const QHashDummyValue & /* v1 */, const QHashDummyValue & /* v2 */) +constexpr bool operator==(const QHashDummyValue &, const QHashDummyValue &) noexcept { return true; } @@ -957,44 +957,32 @@ Q_OUTOFLINE_TEMPLATE typename QHash::Node **QHash::findNode(cons template Q_OUTOFLINE_TEMPLATE bool QHash::operator==(const QHash &other) const { - if (size() != other.size()) - return false; if (d == other.d) return true; + if (size() != other.size()) + return false; const_iterator it = begin(); while (it != end()) { // Build two equal ranges for i.key(); one for *this and one for other. // For *this we can avoid a lookup via equal_range, as we know the beginning of the range. - auto thisEqualRangeEnd = it; - while (thisEqualRangeEnd != end() && it.key() == thisEqualRangeEnd.key()) - ++thisEqualRangeEnd; + auto thisEqualRangeStart = it; + const Key &thisEqualRangeKey = it.key(); + size_type n = 0; + do { + ++it; + ++n; + } while (it != end() && it.key() == thisEqualRangeKey); - const auto otherEqualRange = other.equal_range(it.key()); + const auto otherEqualRange = other.equal_range(thisEqualRangeKey); - if (std::distance(it, thisEqualRangeEnd) != std::distance(otherEqualRange.first, otherEqualRange.second)) + if (n != std::distance(otherEqualRange.first, otherEqualRange.second)) return false; // Keys in the ranges are equal by construction; this checks only the values. - // - // When using the 3-arg std::is_permutation, MSVC will emit warning C4996, - // passing an unchecked iterator to a Standard Library algorithm. We don't - // want to suppress the warning, and we can't use stdext::make_checked_array_iterator - // because QHash::(const_)iterator does not work with size_t and thus will - // emit more warnings. Use the 4-arg std::is_permutation instead (which - // is supported since MSVC 2015). - // - // ### Qt 6: if C++14 library support is a mandated minimum, remove the ifdef for MSVC. - if (!std::is_permutation(it, thisEqualRangeEnd, otherEqualRange.first -#ifdef Q_CC_MSVC - , otherEqualRange.second -#endif - )) { + if (!qt_is_permutation(thisEqualRangeStart, it, otherEqualRange.first, otherEqualRange.second)) return false; - } - - it = thisEqualRangeEnd; } return true; diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp index d239fe0ef4d..3b1bc8aab1e 100644 --- a/src/corelib/tools/qlinkedlist.cpp +++ b/src/corelib/tools/qlinkedlist.cpp @@ -37,6 +37,10 @@ ** ****************************************************************************/ +#ifdef QT_NO_LINKED_LIST +# undef QT_NO_LINKED_LIST +#endif + #include "qlinkedlist.h" QT_BEGIN_NAMESPACE diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index d4e5bca0ed5..996a50fd1ba 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -40,6 +40,10 @@ #ifndef QLINKEDLIST_H #define QLINKEDLIST_H +#include + +#ifndef QT_NO_LINKED_LIST + #include #include #include @@ -581,4 +585,8 @@ inline QDataStream &operator<<(QDataStream &s, const QLinkedList &l) QT_END_NAMESPACE +Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(QLinkedList) + +#endif // QT_NO_LINKED_LIST + #endif // QLINKEDLIST_H diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index ab54c767208..f123f8e7b90 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -297,25 +297,13 @@ template inline bool operator==(const QExplicitlySharedDataPointer } template -Q_INLINE_TEMPLATE void qSwap(QSharedDataPointer &p1, QSharedDataPointer &p2) +Q_INLINE_TEMPLATE void swap(QSharedDataPointer &p1, QSharedDataPointer &p2) { p1.swap(p2); } template -Q_INLINE_TEMPLATE void qSwap(QExplicitlySharedDataPointer &p1, QExplicitlySharedDataPointer &p2) +Q_INLINE_TEMPLATE void swap(QExplicitlySharedDataPointer &p1, QExplicitlySharedDataPointer &p2) { p1.swap(p2); } -QT_END_NAMESPACE -namespace std { - template - Q_INLINE_TEMPLATE void swap(QT_PREPEND_NAMESPACE(QSharedDataPointer) &p1, QT_PREPEND_NAMESPACE(QSharedDataPointer) &p2) - { p1.swap(p2); } - - template - Q_INLINE_TEMPLATE void swap(QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer) &p1, QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer) &p2) - { p1.swap(p2); } -} -QT_BEGIN_NAMESPACE - template Q_INLINE_TEMPLATE uint qHash(const QSharedDataPointer &ptr, uint seed = 0) noexcept { diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp index fa6c45aa11d..0b11e7c77ba 100644 --- a/src/corelib/tools/qtimeline.cpp +++ b/src/corelib/tools/qtimeline.cpp @@ -526,29 +526,24 @@ QTimeLine::CurveShape QTimeLine::curveShape() const return EaseInOutCurve; } -void QTimeLine::setCurveShape(CurveShape shape) +static QEasingCurve::Type convert(QTimeLine::CurveShape shape) { switch (shape) { - default: - case EaseInOutCurve: - setEasingCurve(QEasingCurve(QEasingCurve::InOutSine)); - break; - case EaseInCurve: - setEasingCurve(QEasingCurve(QEasingCurve::InCurve)); - break; - case EaseOutCurve: - setEasingCurve(QEasingCurve(QEasingCurve::OutCurve)); - break; - case LinearCurve: - setEasingCurve(QEasingCurve(QEasingCurve::Linear)); - break; - case SineCurve: - setEasingCurve(QEasingCurve(QEasingCurve::SineCurve)); - break; - case CosineCurve: - setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve)); - break; +#define CASE(x, y) case QTimeLine::x: return QEasingCurve::y + CASE(EaseInOutCurve, InOutSine); + CASE(EaseInCurve, InCurve); + CASE(EaseOutCurve, OutCurve); + CASE(LinearCurve, Linear); + CASE(SineCurve, SineCurve); + CASE(CosineCurve, CosineCurve); +#undef CASE } + Q_UNREACHABLE(); +} + +void QTimeLine::setCurveShape(CurveShape shape) +{ + setEasingCurve(convert(shape)); } /*! diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index ba65ae7ef2b..2f625260760 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -112,7 +112,9 @@ public: inline void removeLast() { Q_ASSERT(s > 0); - realloc(s - 1, a); + if (QTypeInfo::isComplex) + ptr[s - 1].~T(); + --s; } inline int size() const { return s; } inline int count() const { return s; } diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 65a5174abf6..ebe6527d899 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -424,7 +424,7 @@ template void QVector::resize(int asize) { if (asize == d->size) - return; + return detach(); if (asize > int(d->alloc) || !isDetached()) { // there is not enough space QArrayData::AllocationOptions opt = asize > int(d->alloc) ? QArrayData::Grow : QArrayData::Default; realloc(qMax(int(d->alloc), asize), opt); diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 52eddd5d6b4..a2236f90f27 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -8,19 +8,10 @@ HEADERS += \ tools/qarraydataops.h \ tools/qarraydatapointer.h \ tools/qbitarray.h \ - tools/qbytearray.h \ - tools/qbytearray_p.h \ - tools/qbytearraylist.h \ - tools/qbytearraymatcher.h \ - tools/qbytedata_p.h \ tools/qcache.h \ - tools/qchar.h \ - tools/qcollator.h \ - tools/qcollator_p.h \ tools/qcontainerfwd.h \ tools/qcontainertools_impl.h \ tools/qcryptographichash.h \ - tools/qdoublescanprint_p.h \ tools/qeasingcurve.h \ tools/qfreelist_p.h \ tools/qhash.h \ @@ -29,10 +20,6 @@ HEADERS += \ tools/qline.h \ tools/qlinkedlist.h \ tools/qlist.h \ - tools/qlocale.h \ - tools/qlocale_p.h \ - tools/qlocale_tools_p.h \ - tools/qlocale_data_p.h \ tools/qmakearray_p.h \ tools/qmap.h \ tools/qmargins.h \ @@ -43,7 +30,6 @@ HEADERS += \ tools/qpoint.h \ tools/qqueue.h \ tools/qrect.h \ - tools/qregexp.h \ tools/qringbuffer_p.h \ tools/qrefcount.h \ tools/qscopeguard.h \ @@ -57,20 +43,8 @@ HEADERS += \ tools/qsimd_p.h \ tools/qsize.h \ tools/qstack.h \ - tools/qstring.h \ - tools/qstringalgorithms.h \ - tools/qstringalgorithms_p.h \ - tools/qstringbuilder.h \ - tools/qstringiterator_p.h \ - tools/qstringlist.h \ - tools/qstringliteral.h \ - tools/qstringmatcher.h \ - tools/qstringview.h \ - tools/qtextboundaryfinder.h \ tools/qtimeline.h \ tools/qtools_p.h \ - tools/qunicodetables_p.h \ - tools/qunicodetools_p.h \ tools/qvarlengtharray.h \ tools/qvector.h \ tools/qversionnumber.h @@ -79,10 +53,6 @@ HEADERS += \ SOURCES += \ tools/qarraydata.cpp \ tools/qbitarray.cpp \ - tools/qbytearray.cpp \ - tools/qbytearraylist.cpp \ - tools/qbytearraymatcher.cpp \ - tools/qcollator.cpp \ tools/qcryptographichash.cpp \ tools/qeasingcurve.cpp \ tools/qfreelist.cpp \ @@ -90,47 +60,24 @@ SOURCES += \ tools/qline.cpp \ tools/qlinkedlist.cpp \ tools/qlist.cpp \ - tools/qlocale.cpp \ - tools/qlocale_tools.cpp \ tools/qpoint.cpp \ tools/qmap.cpp \ tools/qmargins.cpp \ tools/qmessageauthenticationcode.cpp \ tools/qcontiguouscache.cpp \ tools/qrect.cpp \ - tools/qregexp.cpp \ tools/qrefcount.cpp \ tools/qringbuffer.cpp \ tools/qshareddata.cpp \ tools/qsharedpointer.cpp \ tools/qsimd.cpp \ tools/qsize.cpp \ - tools/qstring.cpp \ - tools/qstringbuilder.cpp \ - tools/qstringlist.cpp \ - tools/qstringview.cpp \ - tools/qtextboundaryfinder.cpp \ tools/qtimeline.cpp \ - tools/qunicodetools.cpp \ - tools/qvsnprintf.cpp \ tools/qversionnumber.cpp -NO_PCH_SOURCES = tools/qstring_compat.cpp msvc: NO_PCH_SOURCES += tools/qvector_msvc.cpp false: SOURCES += $$NO_PCH_SOURCES # Hack for QtCreator -!nacl:mac: { - SOURCES += tools/qlocale_mac.mm -} -else:unix { - SOURCES += tools/qlocale_unix.cpp -} -else:win32 { - SOURCES += tools/qlocale_win.cpp -} else:integrity { - SOURCES += tools/qlocale_unix.cpp -} - qtConfig(system-zlib) { include($$PWD/../../3rdparty/zlib_dependency.pri) } else { @@ -138,27 +85,6 @@ qtConfig(system-zlib) { include($$PWD/../../3rdparty/zlib.pri) } -qtConfig(icu) { - QMAKE_USE_PRIVATE += icu - - SOURCES += tools/qlocale_icu.cpp \ - tools/qcollator_icu.cpp -} else: win32 { - SOURCES += tools/qcollator_win.cpp -} else: macx { - SOURCES += tools/qcollator_macx.cpp -} else { - SOURCES += tools/qcollator_posix.cpp -} - -qtConfig(regularexpression) { - QMAKE_USE_PRIVATE += pcre2 - - HEADERS += \ - tools/qregularexpression.h - SOURCES += tools/qregularexpression.cpp -} - qtConfig(commandlineparser) { HEADERS += \ tools/qcommandlineoption.h \ @@ -168,19 +94,6 @@ qtConfig(commandlineparser) { tools/qcommandlineparser.cpp } -INCLUDEPATH += ../3rdparty/harfbuzz/src -HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h -SOURCES += ../3rdparty/harfbuzz/src/harfbuzz-buffer.c \ - ../3rdparty/harfbuzz/src/harfbuzz-gdef.c \ - ../3rdparty/harfbuzz/src/harfbuzz-gsub.c \ - ../3rdparty/harfbuzz/src/harfbuzz-gpos.c \ - ../3rdparty/harfbuzz/src/harfbuzz-impl.c \ - ../3rdparty/harfbuzz/src/harfbuzz-open.c \ - ../3rdparty/harfbuzz/src/harfbuzz-stream.c \ - ../3rdparty/harfbuzz/src/harfbuzz-shaper-all.cpp \ - tools/qharfbuzz.cpp -HEADERS += tools/qharfbuzz_p.h - INCLUDEPATH += ../3rdparty/md5 \ ../3rdparty/md4 \ ../3rdparty/sha3 @@ -197,5 +110,4 @@ unix:!macx-icc:!vxworks:!haiku:!integrity:!wasm: LIBS_PRIVATE += -lm TR_EXCLUDE += ../3rdparty/* # MIPS DSP -MIPS_DSP_ASM += tools/qstring_mips_dsp_asm.S MIPS_DSP_HEADERS += ../gui/painting/qt_mips_asm_dsp_p.h diff --git a/src/dbus/qdbuserror.h b/src/dbus/qdbuserror.h index bcf68dbcdcd..312bac71de3 100644 --- a/src/dbus/qdbuserror.h +++ b/src/dbus/qdbuserror.h @@ -41,6 +41,7 @@ #define QDBUSERROR_H #include +#include #include #ifndef QT_NO_DBUS @@ -54,6 +55,7 @@ class QDBusMessage; class Q_DBUS_EXPORT QDBusError { + Q_GADGET public: enum ErrorType { NoError = 0, @@ -90,6 +92,7 @@ public: LastErrorType = InvalidMember #endif }; + Q_ENUM(ErrorType) QDBusError(); #ifndef QT_BOOTSTRAPPED diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake index 8924d8da5d3..b08320d69fb 100644 --- a/src/gui/configure.cmake +++ b/src/gui/configure.cmake @@ -790,6 +790,7 @@ qt_feature("xcb_egl_plugin" PRIVATE ) qt_feature("xcb_native_painting" PRIVATE LABEL "Native painting (experimental)" + AUTODETECT OFF CONDITION QT_FEATURE_xcb_xlib AND QT_FEATURE_fontconfig AND XRender_FOUND EMIT_IF QT_FEATURE_xcb ) diff --git a/src/gui/configure.json b/src/gui/configure.json index 7a55efaf856..9d01f549952 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -1549,6 +1549,7 @@ }, "xcb-native-painting": { "label": "Native painting (experimental)", + "autoDetect": false, "emitIf": "features.xcb", "condition": "features.xcb-xlib && features.fontconfig && libs.xrender", "output": [ "privateFeature" ] diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 61d32b0dec1..cd2fe5bc10f 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -5067,12 +5067,12 @@ void QImage::applyColorTransform(const QColorTransform &transform) if (depth() > 32) { for (int i = 0; i < height(); ++i) { QRgba64 *scanline = reinterpret_cast(scanLine(i)); - transform.d_func()->apply(scanline, scanline, width(), flags); + transform.d->apply(scanline, scanline, width(), flags); } } else { for (int i = 0; i < height(); ++i) { QRgb *scanline = reinterpret_cast(scanLine(i)); - transform.d_func()->apply(scanline, scanline, width(), flags); + transform.d->apply(scanline, scanline, width(), flags); } } diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 2762b702b27..6a0763e6966 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -197,7 +197,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, #ifdef QIMAGEREADER_DEBUG qDebug() << "QImageReader::createReadHandler( device =" << (void *)device << ", format =" << format << ")," - << keyMap.size() << "plugins available: " << keyMap.values(); + << keyMap.uniqueKeys().size() << "plugins available: " << keyMap; #endif int suffixPluginIndex = -1; @@ -325,6 +325,29 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, #endif } + if (handler && device && !suffix.isEmpty()) { + Q_ASSERT(qobject_cast(device)); + // We have a file claiming to be of a recognized format. Now confirm that + // the handler also recognizes the file contents. + const qint64 pos = device->pos(); + handler->setDevice(device); + if (!form.isEmpty()) + handler->setFormat(form); + bool canRead = handler->canRead(); + device->seek(pos); + if (canRead) { + // ok, we're done. + return handler; + } +#ifdef QIMAGEREADER_DEBUG + qDebug() << "QImageReader::createReadHandler: the" << suffix << "handler can not read this file"; +#endif + // File may still be valid, just with wrong suffix, so fall back to + // finding a handler based on contents, below. + delete handler; + handler = nullptr; + } + #ifndef QT_NO_IMAGEFORMATPLUGIN if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) { // check if any of our plugins recognize the file from its contents. @@ -336,7 +359,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, if (plugin && plugin->capabilities(device, QByteArray()) & QImageIOPlugin::CanRead) { handler = plugin->create(device, testFormat); #ifdef QIMAGEREADER_DEBUG - qDebug() << "QImageReader::createReadHandler: the" << keyMap.keys().at(i) << "plugin can read this data"; + qDebug() << "QImageReader::createReadHandler: the" << keyMap.value(i) << "plugin can read this data"; #endif break; } @@ -1074,7 +1097,7 @@ QList QImageReader::supportedSubTypes() const \since 5.5 Returns the transformation metadata of the image, including image orientation. If the format - does not support transformation metadata \c QImageIOHandler::Transformation_None is returned. + does not support transformation metadata, QImageIOHandler::TransformationNone is returned. \sa setAutoTransform(), autoTransform() */ diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp index 4b588527aea..3e975115ab6 100644 --- a/src/gui/image/qmovie.cpp +++ b/src/gui/image/qmovie.cpp @@ -207,8 +207,8 @@ public: : pixmap(QPixmap()), delay(QMOVIE_INVALID_DELAY), endMark(false) { } - inline QFrameInfo(const QPixmap &pixmap, int delay) - : pixmap(pixmap), delay(delay), endMark(false) + inline QFrameInfo(QPixmap &&pixmap, int delay) + : pixmap(std::move(pixmap)), delay(delay), endMark(false) { } inline bool isValid() @@ -222,6 +222,7 @@ public: static inline QFrameInfo endMarker() { return QFrameInfo(true); } }; +Q_DECLARE_TYPEINFO(QFrameInfo, Q_MOVABLE_TYPE); class QMoviePrivate : public QObjectPrivate { @@ -380,9 +381,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber) } if (frameNumber > greatestFrameNumber) greatestFrameNumber = frameNumber; - QPixmap aPixmap = QPixmap::fromImage(std::move(anImage)); - int aDelay = reader->nextImageDelay(); - return QFrameInfo(aPixmap, aDelay); + return QFrameInfo(QPixmap::fromImage(std::move(anImage)), reader->nextImageDelay()); } else if (frameNumber != 0) { // We've read all frames now. Return an end marker haveReadAll = true; @@ -406,9 +405,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber) return QFrameInfo(); // Invalid } greatestFrameNumber = i; - QPixmap aPixmap = QPixmap::fromImage(std::move(anImage)); - int aDelay = reader->nextImageDelay(); - QFrameInfo info(aPixmap, aDelay); + QFrameInfo info(QPixmap::fromImage(std::move(anImage)), reader->nextImageDelay()); // Cache it! frameMap.insert(i, info); if (i == frameNumber) { diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index a41ec8f35c9..483d6d79a28 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -42,6 +42,8 @@ #include "qobject.h" #include "qdebug.h" #include "qpixmapcache_p.h" +#include "qthread.h" +#include "qcoreapplication.h" QT_BEGIN_NAMESPACE @@ -83,6 +85,9 @@ QT_BEGIN_NAMESPACE with QPixmapCache} explains how to use QPixmapCache to speed up applications by caching the results of painting. + \note QPixmapCache is only usable from the application's main thread. + Access from other threads will be ignored and return failure. + \sa QCache, QPixmap */ @@ -98,6 +103,14 @@ static inline int cost(const QPixmap &pixmap) return static_cast(qBound(1LL, costKb, costMax)); } +static inline bool qt_pixmapcache_thread_test() +{ + if (Q_LIKELY(QCoreApplication::instance() && QThread::currentThread() == QCoreApplication::instance()->thread())) + return true; + + return false; +} + /*! \class QPixmapCache::Key \brief The QPixmapCache::Key class can be used for efficient access @@ -490,6 +503,8 @@ QPixmapCacheEntry::~QPixmapCacheEntry() QPixmap *QPixmapCache::find(const QString &key) { + if (!qt_pixmapcache_thread_test()) + return nullptr; return pm_cache()->object(key); } @@ -519,6 +534,8 @@ bool QPixmapCache::find(const QString &key, QPixmap &pixmap) bool QPixmapCache::find(const QString &key, QPixmap *pixmap) { + if (!qt_pixmapcache_thread_test()) + return false; QPixmap *ptr = pm_cache()->object(key); if (ptr && pixmap) *pixmap = *ptr; @@ -536,6 +553,8 @@ bool QPixmapCache::find(const QString &key, QPixmap *pixmap) */ bool QPixmapCache::find(const Key &key, QPixmap *pixmap) { + if (!qt_pixmapcache_thread_test()) + return false; //The key is not valid anymore, a flush happened before probably if (!key.d || !key.d->isValid) return false; @@ -567,6 +586,8 @@ bool QPixmapCache::find(const Key &key, QPixmap *pixmap) bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap) { + if (!qt_pixmapcache_thread_test()) + return false; return pm_cache()->insert(key, pixmap, cost(pixmap)); } @@ -587,6 +608,8 @@ bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap) */ QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap) { + if (!qt_pixmapcache_thread_test()) + return QPixmapCache::Key(); return pm_cache()->insert(pixmap, cost(pixmap)); } @@ -601,6 +624,8 @@ QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap) */ bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap) { + if (!qt_pixmapcache_thread_test()) + return false; //The key is not valid anymore, a flush happened before probably if (!key.d || !key.d->isValid) return false; @@ -630,6 +655,8 @@ int QPixmapCache::cacheLimit() void QPixmapCache::setCacheLimit(int n) { + if (!qt_pixmapcache_thread_test()) + return; pm_cache()->setMaxCost(n); } @@ -638,6 +665,8 @@ void QPixmapCache::setCacheLimit(int n) */ void QPixmapCache::remove(const QString &key) { + if (!qt_pixmapcache_thread_test()) + return; pm_cache()->remove(key); } @@ -649,6 +678,8 @@ void QPixmapCache::remove(const QString &key) */ void QPixmapCache::remove(const Key &key) { + if (!qt_pixmapcache_thread_test()) + return; //The key is not valid anymore, a flush happened before probably if (!key.d || !key.d->isValid) return; @@ -661,6 +692,8 @@ void QPixmapCache::remove(const Key &key) void QPixmapCache::clear() { + if (!QCoreApplication::closingDown() && !qt_pixmapcache_thread_test()) + return; QT_TRY { if (pm_cache.exists()) pm_cache->clear(); diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 864a944fcb0..16d6c25b8b7 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -53,7 +53,6 @@ #include #include -#include #include #include @@ -607,9 +606,13 @@ bool QPngHandlerPrivate::readPngHeader() #endif png_uint_32 profLen; png_get_iCCP(png_ptr, info_ptr, &name, &compressionType, &profileData, &profLen); - if (!QIcc::fromIccProfile(QByteArray::fromRawData((const char *)profileData, profLen), &colorSpace)) { + colorSpace = QColorSpace::fromIccProfile(QByteArray::fromRawData((const char *)profileData, profLen)); + if (!colorSpace.isValid()) { qWarning() << "QPngHandler: Failed to parse ICC profile"; } else { + QColorSpacePrivate *csD = QColorSpacePrivate::getWritable(colorSpace); + if (csD->description.isEmpty()) + csD->description = QString::fromLatin1((const char *)name); colorSpaceState = Icc; } } @@ -628,11 +631,25 @@ bool QPngHandlerPrivate::readPngHeader() png_get_gAMA(png_ptr, info_ptr, &file_gamma); fileGamma = file_gamma; if (fileGamma > 0.0f && colorSpaceState <= GammaChrm) { - QColorSpacePrivate *csPrivate = colorSpace.d_func(); - csPrivate->gamut = QColorSpace::Gamut::SRgb; - csPrivate->transferFunction = QColorSpace::TransferFunction::Gamma; - csPrivate->gamma = fileGamma; - csPrivate->initialize(); + QColorSpacePrimaries primaries; + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_cHRM)) { + double white_x, white_y, red_x, red_y; + double green_x, green_y, blue_x, blue_y; + png_get_cHRM(png_ptr, info_ptr, + &white_x, &white_y, &red_x, &red_y, + &green_x, &green_y, &blue_x, &blue_y); + primaries.whitePoint = QPointF(white_x, white_y); + primaries.redPoint = QPointF(red_x, red_y); + primaries.greenPoint = QPointF(green_x, green_y); + primaries.bluePoint = QPointF(blue_x, blue_y); + } + if (primaries.areValid()) { + colorSpace = QColorSpace(primaries.whitePoint, primaries.redPoint, primaries.greenPoint, primaries.bluePoint, + QColorSpace::TransferFunction::Gamma, fileGamma); + } else { + colorSpace = QColorSpace(QColorSpace::Primaries::SRgb, + QColorSpace::TransferFunction::Gamma, fileGamma); + } colorSpaceState = GammaChrm; } } @@ -663,10 +680,7 @@ bool QPngHandlerPrivate::readPngImage(QImage *outImage) // This configuration forces gamma correction and // thus changes the output colorspace png_set_gamma(png_ptr, 1.0f / gamma, fileGamma); - QColorSpacePrivate *csPrivate = colorSpace.d_func(); - csPrivate->transferFunction = QColorSpace::TransferFunction::Gamma; - csPrivate->gamma = gamma; - csPrivate->initialize(); + colorSpace = colorSpace.withTransferFunction(QColorSpace::TransferFunction::Gamma, 1.0f / gamma); colorSpaceState = GammaChrm; } @@ -962,6 +976,26 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i bpc, // per channel color_type, 0, 0, 0); // sets #channels +#ifdef PNG_iCCP_SUPPORTED + if (image.colorSpace().isValid()) { + QColorSpace cs = image.colorSpace(); + // Support the old gamma making it override transferfunction. + if (gamma != 0.0 && !qFuzzyCompare(cs.gamma(), 1.0f / gamma)) + cs = cs.withTransferFunction(QColorSpace::TransferFunction::Gamma, 1.0f / gamma); + QByteArray iccProfileName = QColorSpacePrivate::get(cs)->description.toLatin1(); + if (iccProfileName.isEmpty()) + iccProfileName = QByteArrayLiteral("Custom"); + QByteArray iccProfile = cs.iccProfile(); + png_set_iCCP(png_ptr, info_ptr, + #if PNG_LIBPNG_VER < 10500 + iccProfileName.data(), PNG_COMPRESSION_TYPE_BASE, iccProfile.data(), + #else + iccProfileName.constData(), PNG_COMPRESSION_TYPE_BASE, + (png_const_bytep)iccProfile.constData(), + #endif + iccProfile.length()); + } else +#endif if (gamma != 0.0) { png_set_gAMA(png_ptr, info_ptr, 1.0/gamma); } diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index e1d685b1b00..ec527910101 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -754,31 +754,15 @@ QHoverEvent::~QHoverEvent() \fn Qt::Orientation QWheelEvent::orientation() const \obsolete - Returns the wheel's orientation. - Use angleDelta() instead. */ +#if QT_CONFIG(wheelevent) +#if QT_DEPRECATED_SINCE(5, 15) /*! \obsolete - Constructs a wheel event object. - - Use the constructor taking \e angleDelta and \e pixelDelta QPoints instead. - - The position, \a pos, is the location of the mouse cursor within - the widget. The globalPos() is initialized to QCursor::pos() - which is usually, but not always, correct. - Use the other constructor if you need to specify the global - position explicitly. - - The \a buttons describe the state of the mouse buttons at the time - of the event, \a delta contains the rotation distance, - \a modifiers holds the keyboard modifier flags at the time of the - event, and \a orient holds the wheel's orientation. - - \sa pos(), pixelDelta(), angleDelta() + This constructor has been deprecated. */ -#if QT_CONFIG(wheelevent) QWheelEvent::QWheelEvent(const QPointF &pos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) @@ -792,27 +776,9 @@ QWheelEvent::QWheelEvent(const QPointF &pos, int delta, angleD = QPoint(delta, 0); } -/*! - \internal -*/ -QWheelEvent::~QWheelEvent() -{ -} - /*! \obsolete - Constructs a wheel event object. - - Use the constructor taking \e angleDelta and \e pixelDelta QPoints instead. - - The \a pos provides the location of the mouse cursor - within the widget. The position in global coordinates is specified - by \a globalPos. \a delta contains the rotation distance, \a modifiers - holds the keyboard modifier flags at the time of the event, and - \a orient holds the wheel's orientation. - - - \sa pos(), pixelDelta(), angleDelta() + This constructor has been deprecated. */ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, @@ -827,27 +793,8 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta } /*! - Constructs a wheel event object. - - The \a pos provides the location of the mouse cursor - within the window. The position in global coordinates is specified - by \a globalPos. - - \a pixelDelta contains the scrolling distance in pixels on screen, while - \a angleDelta contains the wheel rotation distance. \a pixelDelta is - optional and can be null. - - The mouse and keyboard states at the time of the event are specified by - \a buttons and \a modifiers. - - For backwards compatibility, the event can also hold monodirectional wheel - event data: \a qt4Delta specifies the rotation, and \a qt4Orientation the - direction. - - The phase() is initialized to Qt::ScrollUpdate. Use the other constructor - to specify the phase explicitly. - - \sa posF(), globalPosF(), angleDelta(), pixelDelta() + \obsolete + This constructor has been deprecated. */ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, @@ -858,26 +805,8 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, {} /*! - Constructs a wheel event object. - - The \a pos provides the location of the mouse cursor - within the window. The position in global coordinates is specified - by \a globalPos. - - \a pixelDelta contains the scrolling distance in pixels on screen, while - \a angleDelta contains the wheel rotation distance. \a pixelDelta is - optional and can be null. - - The mouse and keyboard states at the time of the event are specified by - \a buttons and \a modifiers. - - For backwards compatibility, the event can also hold monodirectional wheel - event data: \a qt4Delta specifies the rotation, and \a qt4Orientation the - direction. - - The scrolling phase of the event is specified by \a phase. - - \sa posF(), globalPosF(), angleDelta(), pixelDelta(), phase() + \obsolete + This constructor has been deprecated. */ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, @@ -888,31 +817,8 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, {} /*! - Constructs a wheel event object. - - The \a pos provides the location of the mouse cursor within the window. The - position in global coordinates is specified by \a globalPos. - - \a pixelDelta contains the scrolling distance in pixels on screen, while - \a angleDelta contains the wheel rotation distance. \a pixelDelta is - optional and can be null. - - The mouse and keyboard states at the time of the event are specified by - \a buttons and \a modifiers. - - For backwards compatibility, the event can also hold monodirectional wheel - event data: \a qt4Delta specifies the rotation, and \a qt4Orientation the - direction. - - The scrolling phase of the event is specified by \a phase. - - If the wheel event comes from a physical mouse wheel, \a source is set to - Qt::MouseEventNotSynthesized. If it comes from a gesture detected by the - operating system, or from a non-mouse hardware device, such that \a pixelDelta is - directly related to finger movement, \a source is set to Qt::MouseEventSynthesizedBySystem. - If it comes from Qt, source would be set to Qt::MouseEventSynthesizedByQt. - - \sa posF(), globalPosF(), angleDelta(), pixelDelta(), phase() + \obsolete + This constructor has been deprecated. */ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, @@ -923,37 +829,8 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, {} /*! - Constructs a wheel event object. - - The \a pos provides the location of the mouse cursor - within the window. The position in global coordinates is specified - by \a globalPos. - - \a pixelDelta contains the scrolling distance in pixels on screen, while - \a angleDelta contains the wheel rotation distance. \a pixelDelta is - optional and can be null. - - The mouse and keyboard states at the time of the event are specified by - \a buttons and \a modifiers. - - For backwards compatibility, the event can also hold monodirectional wheel - event data: \a qt4Delta specifies the rotation, and \a qt4Orientation the - direction. - - The scrolling phase of the event is specified by \a phase. - - If the wheel event comes from a physical mouse wheel, \a source is set to - Qt::MouseEventNotSynthesized. If it comes from a gesture detected by the - operating system, or from a non-mouse hardware device, such that \a - pixelDelta is directly related to finger movement, \a source is set to - Qt::MouseEventSynthesizedBySystem. If it comes from Qt, source would be set - to Qt::MouseEventSynthesizedByQt. - - If the system is configured to invert the delta values delivered with the - event (such as natural scrolling of the touchpad on OS X), \a inverted - should be \c true. Otherwise, \a inverted is \c false - - \sa posF(), globalPosF(), angleDelta(), pixelDelta(), phase() + \obsolete + This constructor has been deprecated. */ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, @@ -962,6 +839,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), src(source), invertedScrolling(inverted), ph(phase) {} +#endif // QT_DEPRECATED_SINCE(5, 15) /*! Constructs a wheel event object. @@ -990,7 +868,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, event (such as natural scrolling of the touchpad on macOS), \a inverted should be \c true. Otherwise, \a inverted is \c false - \sa posF(), globalPosF(), angleDelta(), pixelDelta(), phase() + \sa position(), globalPosition(), angleDelta(), pixelDelta(), phase(), inverted(), source() */ QWheelEvent::QWheelEvent(QPointF pos, QPointF globalPos, QPoint pixelDelta, QPoint angleDelta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, @@ -1002,6 +880,12 @@ QWheelEvent::QWheelEvent(QPointF pos, QPointF globalPos, QPoint pixelDelta, QPoi qt4D = (qt4O == Qt::Horizontal ? angleDelta.x() : angleDelta.y()); } +/*! + \internal +*/ +QWheelEvent::~QWheelEvent() +{ +} #endif // QT_CONFIG(wheelevent) /*! @@ -1061,87 +945,59 @@ QWheelEvent::QWheelEvent(QPointF pos, QPointF globalPos, QPoint pixelDelta, QPoi /*! \fn QPoint QWheelEvent::pos() const + \obsolete - Returns the position of the mouse cursor relative to the widget - that received the event. - - If you move your widgets around in response to mouse events, - use globalPos() instead of this function. - - \sa x(), y(), globalPos() + This function has been deprecated, use position() instead. */ /*! \fn int QWheelEvent::x() const + \obsolete - Returns the x position of the mouse cursor, relative to the - widget that received the event. - - \sa y(), pos() + This function has been deprecated, use position() instead. */ /*! \fn int QWheelEvent::y() const + \obsolete - Returns the y position of the mouse cursor, relative to the - widget that received the event. - - \sa x(), pos() + This function has been deprecated, use position() instead. */ /*! \fn QPoint QWheelEvent::globalPos() const + \obsolete - Returns the global position of the mouse pointer \e{at the time - of the event}. This is important on asynchronous window systems - such as X11; whenever you move your widgets around in response to - mouse events, globalPos() can differ a lot from the current - cursor position returned by QCursor::pos(). - - \sa globalX(), globalY() + This function has been deprecated, use globalPosition() instead. */ /*! \fn int QWheelEvent::globalX() const + \obsolete - Returns the global x position of the mouse cursor at the time of - the event. - - \sa globalY(), globalPos() + This function has been deprecated, use globalPosition() instead. */ /*! \fn int QWheelEvent::globalY() const + \obsolete - Returns the global y position of the mouse cursor at the time of - the event. - - \sa globalX(), globalPos() + This function has been deprecated, use globalPosition() instead. */ /*! \fn const QPointF &QWheelEvent::posF() const + \obsolete - Returns the position of the mouse cursor relative to the widget - that received the event. - - If you move your widgets around in response to mouse events, - use globalPosF() instead of this function. - - \sa globalPosF() + This function has been deprecated, use position() instead. */ /*! \fn const QPointF &QWheelEvent::globalPosF() const + \obsolete - Returns the global position of the mouse pointer \e{at the time - of the event}. This is important on asynchronous window systems - such as X11; whenever you move your widgets around in response to - mouse events, globalPosF() can differ a lot from the current - cursor position returned by QCursor::pos(). - - \sa posF() + This function has been deprecated, use globalPosition() instead. */ /*! @@ -4074,8 +3930,10 @@ QDebug operator<<(QDebug dbg, const QEvent *e) dbg << "QWheelEvent(" << we->phase(); if (!we->pixelDelta().isNull() || !we->angleDelta().isNull()) dbg << ", pixelDelta=" << we->pixelDelta() << ", angleDelta=" << we->angleDelta(); +#if QT_DEPRECATED_SINCE(5, 14) else if (int qt4Delta = we->delta()) dbg << ", delta=" << qt4Delta << ", orientation=" << we->orientation(); +#endif dbg << ')'; } break; diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index eb0a6208a96..b73d90529a4 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -175,24 +175,34 @@ class Q_GUI_EXPORT QWheelEvent : public QInputEvent public: enum { DefaultDeltasPerStep = 120 }; +#if QT_DEPRECATED_SINCE(5, 15) + // Actually deprecated since 5.0, in docs + QT_DEPRECATED_VERSION_X_5_15("Use the last QWheelEvent constructor taking pixelDelta, angleDelta, phase, and inverted") QWheelEvent(const QPointF &pos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient = Qt::Vertical); + // Actually deprecated since 5.0, in docs + QT_DEPRECATED_VERSION_X_5_15("Use the last QWheelEvent constructor taking pixelDelta, angleDelta, phase, and inverted") QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient = Qt::Vertical); + QT_DEPRECATED_VERSION_X_5_15("Use the last QWheelEvent constructor taking pixelDelta, angleDelta, phase, and inverted") QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); + QT_DEPRECATED_VERSION_X_5_15("Use the last QWheelEvent constructor taking pixelDelta, angleDelta, phase, and inverted") QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase); + QT_DEPRECATED_VERSION_X_5_15("Use the last QWheelEvent constructor taking pixelDelta, angleDelta, phase, and inverted") QWheelEvent(const QPointF &pos, const QPointF &globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, Qt::MouseEventSource source); + QT_DEPRECATED_VERSION_X_5_15("Use the last QWheelEvent constructor taking pixelDelta, angleDelta, phase, and inverted") QWheelEvent(const QPointF &pos, const QPointF &globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, Qt::MouseEventSource source, bool inverted); +#endif QWheelEvent(QPointF pos, QPointF globalPos, QPoint pixelDelta, QPoint angleDelta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, @@ -203,19 +213,35 @@ public: inline QPoint pixelDelta() const { return pixelD; } inline QPoint angleDelta() const { return angleD; } +#if QT_DEPRECATED_SINCE(5, 15) + // Actually deprecated since 5.0, in docs + QT_DEPRECATED_VERSION_X_5_15("Use angleDelta()") inline int delta() const { return qt4D; } + // Actually deprecated since 5.0, in docs + QT_DEPRECATED_VERSION_X_5_15("Use angleDelta()") inline Qt::Orientation orientation() const { return qt4O; } - #ifndef QT_NO_INTEGER_EVENT_COORDINATES + QT_DEPRECATED_VERSION_X_5_15("Use position()") inline QPoint pos() const { return p.toPoint(); } + QT_DEPRECATED_VERSION_X_5_15("Use globalPosition()") inline QPoint globalPos() const { return g.toPoint(); } + QT_DEPRECATED_VERSION_X_5_15("Use position()") inline int x() const { return int(p.x()); } + QT_DEPRECATED_VERSION_X_5_15("Use position()") inline int y() const { return int(p.y()); } + QT_DEPRECATED_VERSION_X_5_15("Use globalPosition()") inline int globalX() const { return int(g.x()); } + QT_DEPRECATED_VERSION_X_5_15("Use globalPosition()") inline int globalY() const { return int(g.y()); } #endif + QT_DEPRECATED_VERSION_X_5_15("Use position()") inline const QPointF &posF() const { return p; } + QT_DEPRECATED_VERSION_X_5_15("Use globalPosition()") inline const QPointF &globalPosF() const { return g; } +#endif // QT_DEPRECATED_SINCE(5, 15) + + inline QPointF position() const { return p; } + inline QPointF globalPosition() const { return g; } inline Qt::MouseButtons buttons() const { return mouseState; } @@ -231,7 +257,7 @@ protected: QPoint angleD; int qt4D = 0; Qt::Orientation qt4O = Qt::Vertical; - Qt::MouseButtons mouseState; + Qt::MouseButtons mouseState = Qt::NoButton; uint _unused_ : 2; // Kept for binary compatibility uint src: 2; bool invertedScrolling : 1; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index ceb5055a9d3..426f2aeece8 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2239,8 +2239,13 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh return; } +#if QT_DEPRECATED_SINCE(5, 14) QWheelEvent ev(localPoint, globalPoint, e->pixelDelta, e->angleDelta, e->qt4Delta, e->qt4Orientation, mouse_buttons, e->modifiers, e->phase, e->source, e->inverted); +#else + QWheelEvent ev(localPoint, globalPoint, e->pixelDelta, e->angleDelta, + mouse_buttons, e->modifiers, e->phase, e->inverted, e->source); +#endif ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(window, &ev); #else diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 326d2823eb3..10adee438be 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -611,8 +611,8 @@ bool QOpenGLContext::create() d->platformGLContext = QGuiApplicationPrivate::platformIntegration()->createPlatformOpenGLContext(this); if (!d->platformGLContext) return false; - d->platformGLContext->initialize(); d->platformGLContext->setContext(this); + d->platformGLContext->initialize(); if (!d->platformGLContext->isSharing()) d->shareContext = 0; d->shareGroup = d->shareContext ? d->shareContext->shareGroup() : new QOpenGLContextGroup; diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp index 9b5b7a6f1e1..732ede90d09 100644 --- a/src/gui/kernel/qstylehints.cpp +++ b/src/gui/kernel/qstylehints.cpp @@ -65,6 +65,20 @@ static inline QVariant themeableHint(QPlatformTheme::ThemeHint th, return QGuiApplicationPrivate::platformIntegration()->styleHint(ih); } +static inline QVariant themeableHint(QPlatformTheme::ThemeHint th) +{ + if (!QCoreApplication::instance()) { + qWarning("Must construct a QGuiApplication before accessing a platform theme hint."); + return QVariant(); + } + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + const QVariant themeHint = theme->themeHint(th); + if (themeHint.isValid()) + return themeHint; + } + return QPlatformTheme::defaultThemeHint(th); +} + class QStyleHintsPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QStyleHints) @@ -80,6 +94,8 @@ public: int m_showShortcutsInContextMenus = -1; int m_wheelScrollLines = -1; int m_mouseQuickSelectionThreshold = -1; + int m_mouseDoubleClickDistance = -1; + int m_touchDoubleTapDistance = -1; }; /*! @@ -132,6 +148,34 @@ int QStyleHints::mouseDoubleClickInterval() const themeableHint(QPlatformTheme::MouseDoubleClickInterval, QPlatformIntegration::MouseDoubleClickInterval).toInt(); } +/*! + \property QStyleHints::mouseDoubleClickDistance + \brief the maximum distance, in pixels, that the mouse can be moved between + two consecutive mouse clicks and still have it detected as a double-click + \since 5.14 +*/ +int QStyleHints::mouseDoubleClickDistance() const +{ + Q_D(const QStyleHints); + return d->m_mouseDoubleClickDistance >= 0 ? + d->m_mouseDoubleClickDistance : + themeableHint(QPlatformTheme::MouseDoubleClickDistance).toInt(); +} + +/*! + \property QStyleHints::touchDoubleTapDistance + \brief the maximum distance, in pixels, that a finger can be moved between + two consecutive taps and still have it detected as a double-tap + \since 5.14 +*/ +int QStyleHints::touchDoubleTapDistance() const +{ + Q_D(const QStyleHints); + return d->m_touchDoubleTapDistance >= 0 ? + d->m_touchDoubleTapDistance : + themeableHint(QPlatformTheme::TouchDoubleTapDistance).toInt(); +} + /*! Sets the \a mousePressAndHoldInterval. \internal diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h index 9091db9624e..30d8fdc64de 100644 --- a/src/gui/kernel/qstylehints.h +++ b/src/gui/kernel/qstylehints.h @@ -74,10 +74,14 @@ class Q_GUI_EXPORT QStyleHints : public QObject Q_PROPERTY(bool useHoverEffects READ useHoverEffects WRITE setUseHoverEffects NOTIFY useHoverEffectsChanged FINAL) Q_PROPERTY(int wheelScrollLines READ wheelScrollLines NOTIFY wheelScrollLinesChanged FINAL) Q_PROPERTY(int mouseQuickSelectionThreshold READ mouseQuickSelectionThreshold WRITE setMouseQuickSelectionThreshold NOTIFY mouseQuickSelectionThresholdChanged FINAL) + Q_PROPERTY(int mouseDoubleClickDistance READ mouseDoubleClickDistance STORED false CONSTANT FINAL) + Q_PROPERTY(int touchDoubleTapDistance READ touchDoubleTapDistance STORED false CONSTANT FINAL) public: void setMouseDoubleClickInterval(int mouseDoubleClickInterval); int mouseDoubleClickInterval() const; + int mouseDoubleClickDistance() const; + int touchDoubleTapDistance() const; void setMousePressAndHoldInterval(int mousePressAndHoldInterval); int mousePressAndHoldInterval() const; void setStartDragDistance(int startDragDistance); diff --git a/src/gui/opengl/qopenglprogrambinarycache.cpp b/src/gui/opengl/qopenglprogrambinarycache.cpp index c96021a9696..1f1ac1fd80f 100644 --- a/src/gui/opengl/qopenglprogrambinarycache.cpp +++ b/src/gui/opengl/qopenglprogrambinarycache.cpp @@ -168,12 +168,19 @@ bool QOpenGLProgramBinaryCache::verifyHeader(const QByteArray &buf) const bool QOpenGLProgramBinaryCache::setProgramBinary(uint programId, uint blobFormat, const void *p, uint blobSize) { - QOpenGLExtraFunctions *funcs = QOpenGLContext::currentContext()->extraFunctions(); + QOpenGLContext *context = QOpenGLContext::currentContext(); + QOpenGLExtraFunctions *funcs = context->extraFunctions(); while (true) { GLenum error = funcs->glGetError(); if (error == GL_NO_ERROR || error == GL_CONTEXT_LOST) break; } +#if defined(QT_OPENGL_ES_2) + if (context->isOpenGLES() && context->format().majorVersion() < 3) { + initializeProgramBinaryOES(context); + programBinaryOES(programId, blobFormat, p, blobSize); + } else +#endif funcs->glProgramBinary(programId, blobFormat, p, blobSize); GLenum err = funcs->glGetError(); @@ -347,7 +354,8 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId) GLEnvInfo info; - QOpenGLExtraFunctions *funcs = QOpenGLContext::currentContext()->extraFunctions(); + QOpenGLContext *context = QOpenGLContext::currentContext(); + QOpenGLExtraFunctions *funcs = context->extraFunctions(); GLint blobSize = 0; while (true) { GLenum error = funcs->glGetError(); @@ -390,6 +398,12 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId) *p++ = 0; GLint outSize = 0; +#if defined(QT_OPENGL_ES_2) + if (context->isOpenGLES() && context->format().majorVersion() < 3) { + initializeProgramBinaryOES(context); + getProgramBinaryOES(programId, blobSize, &outSize, &blobFormat, p); + } else +#endif funcs->glGetProgramBinary(programId, blobSize, &outSize, &blobFormat, p); if (blobSize != outSize) { qCDebug(DBG_SHADER_CACHE, "glGetProgramBinary returned size %d instead of %d", outSize, blobSize); @@ -398,14 +412,33 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId) writeUInt(&blobFormatPtr, blobFormat); +#if QT_CONFIG(temporaryfile) QSaveFile f(cacheFileName(cacheKey)); if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { f.write(blob); if (!f.commit()) +#else + QFile f(cacheFileName(cacheKey)); + if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (f.write(blob) < blob.length()) +#endif qCDebug(DBG_SHADER_CACHE, "Failed to write %s to shader cache", qPrintable(f.fileName())); } else { qCDebug(DBG_SHADER_CACHE, "Failed to create %s in shader cache", qPrintable(f.fileName())); } } +#if defined(QT_OPENGL_ES_2) +void QOpenGLProgramBinaryCache::initializeProgramBinaryOES(QOpenGLContext *context) +{ + if (m_programBinaryOESInitialized) + return; + m_programBinaryOESInitialized = true; + + Q_ASSERT(context); + getProgramBinaryOES = (void (QOPENGLF_APIENTRYP)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary))context->getProcAddress("glGetProgramBinaryOES"); + programBinaryOES = (void (QOPENGLF_APIENTRYP)(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length))context->getProcAddress("glProgramBinaryOES"); +} +#endif + QT_END_NAMESPACE diff --git a/src/gui/opengl/qopenglprogrambinarycache_p.h b/src/gui/opengl/qopenglprogrambinarycache_p.h index a0e1f91e254..9fade08e66d 100644 --- a/src/gui/opengl/qopenglprogrambinarycache_p.h +++ b/src/gui/opengl/qopenglprogrambinarycache_p.h @@ -93,6 +93,12 @@ private: uint format; }; QCache m_memCache; +#if defined(QT_OPENGL_ES_2) + void (QOPENGLF_APIENTRYP programBinaryOES)(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length); + void (QOPENGLF_APIENTRYP getProgramBinaryOES)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); + void initializeProgramBinaryOES(QOpenGLContext *context); + bool m_programBinaryOESInitialized = false; +#endif }; QT_END_NAMESPACE diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp index f225d5dc756..3c7bd4f90d3 100644 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ b/src/gui/opengl/qopenglshaderprogram.cpp @@ -3755,8 +3755,14 @@ QOpenGLProgramBinarySupportCheck::QOpenGLProgramBinarySupportCheck(QOpenGLContex if (ctx) { if (ctx->isOpenGLES()) { qCDebug(DBG_SHADER_CACHE, "OpenGL ES v%d context", ctx->format().majorVersion()); - if (ctx->format().majorVersion() >= 3) + if (ctx->format().majorVersion() >= 3) { m_supported = true; + } else { + const bool hasExt = ctx->hasExtension("GL_OES_get_program_binary"); + qCDebug(DBG_SHADER_CACHE, "GL_OES_get_program_binary support = %d", hasExt); + if (hasExt) + m_supported = true; + } } else { const bool hasExt = ctx->hasExtension("GL_ARB_get_program_binary"); qCDebug(DBG_SHADER_CACHE, "GL_ARB_get_program_binary support = %d", hasExt); diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp index e3cbba955d2..490dc997498 100644 --- a/src/gui/opengl/qopengltextureglyphcache.cpp +++ b/src/gui/opengl/qopengltextureglyphcache.cpp @@ -53,8 +53,8 @@ static int next_qopengltextureglyphcache_serial_number() return 1 + serial.fetchAndAddRelaxed(1); } -QOpenGLTextureGlyphCache::QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) - : QImageTextureGlyphCache(format, matrix) +QOpenGLTextureGlyphCache::QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix, const QColor &color) + : QImageTextureGlyphCache(format, matrix, color) , m_textureResource(0) , pex(0) , m_blitProgram(0) diff --git a/src/gui/opengl/qopengltextureglyphcache_p.h b/src/gui/opengl/qopengltextureglyphcache_p.h index aed128cf9e6..4bea4a463a7 100644 --- a/src/gui/opengl/qopengltextureglyphcache_p.h +++ b/src/gui/opengl/qopengltextureglyphcache_p.h @@ -110,7 +110,7 @@ public: class Q_GUI_EXPORT QOpenGLTextureGlyphCache : public QImageTextureGlyphCache { public: - QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat glyphFormat, const QTransform &matrix); + QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat glyphFormat, const QTransform &matrix, const QColor &color = QColor()); ~QOpenGLTextureGlyphCache(); virtual void createTextureData(int width, int height) override; diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 3fab903c4d6..3240b83451a 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -186,7 +186,7 @@ QPaintDevice *QBackingStore::paintDevice() void QBackingStore::endPaint() { if (paintDevice()->paintingActive()) - qWarning() << "QBackingStore::endPaint() called with active painter on backingstore paint device"; + qWarning("QBackingStore::endPaint() called with active painter; did you forget to destroy it or call QPainter::end() on it?"); handle()->endPaint(); } diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp index 8d3bbbe412b..043a9515218 100644 --- a/src/gui/painting/qcolorspace.cpp +++ b/src/gui/painting/qcolorspace.cpp @@ -55,34 +55,34 @@ QT_BEGIN_NAMESPACE QBasicMutex QColorSpacePrivate::s_lutWriteLock; -QColorSpacePrimaries::QColorSpacePrimaries(QColorSpace::Gamut gamut) +QColorSpacePrimaries::QColorSpacePrimaries(QColorSpace::Primaries primaries) { - switch (gamut) { - case QColorSpace::Gamut::SRgb: + switch (primaries) { + case QColorSpace::Primaries::SRgb: redPoint = QPointF(0.640, 0.330); greenPoint = QPointF(0.300, 0.600); bluePoint = QPointF(0.150, 0.060); whitePoint = QColorVector::D65Chromaticity(); break; - case QColorSpace::Gamut::DciP3D65: + case QColorSpace::Primaries::DciP3D65: redPoint = QPointF(0.680, 0.320); greenPoint = QPointF(0.265, 0.690); bluePoint = QPointF(0.150, 0.060); whitePoint = QColorVector::D65Chromaticity(); break; - case QColorSpace::Gamut::Bt2020: + case QColorSpace::Primaries::Bt2020: redPoint = QPointF(0.708, 0.292); greenPoint = QPointF(0.190, 0.797); bluePoint = QPointF(0.131, 0.046); whitePoint = QColorVector::D65Chromaticity(); break; - case QColorSpace::Gamut::AdobeRgb: + case QColorSpace::Primaries::AdobeRgb: redPoint = QPointF(0.640, 0.330); greenPoint = QPointF(0.210, 0.710); bluePoint = QPointF(0.150, 0.060); whitePoint = QColorVector::D65Chromaticity(); break; - case QColorSpace::Gamut::ProPhotoRgb: + case QColorSpace::Primaries::ProPhotoRgb: redPoint = QPointF(0.7347, 0.2653); greenPoint = QPointF(0.1596, 0.8404); bluePoint = QPointF(0.0366, 0.0001); @@ -153,7 +153,7 @@ QColorMatrix QColorSpacePrimaries::toXyzMatrix() const QColorSpacePrivate::QColorSpacePrivate() : id(QColorSpace::Unknown) - , gamut(QColorSpace::Gamut::Custom) + , primaries(QColorSpace::Primaries::Custom) , transferFunction(QColorSpace::TransferFunction::Custom) , gamma(0.0f) , whitePoint(QColorVector::null()) @@ -163,48 +163,43 @@ QColorSpacePrivate::QColorSpacePrivate() QColorSpacePrivate::QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId) : id(colorSpaceId) + , gamma(0.0f) { switch (colorSpaceId) { case QColorSpace::Undefined: - gamut = QColorSpace::Gamut::Custom; + primaries = QColorSpace::Primaries::Custom; transferFunction = QColorSpace::TransferFunction::Custom; - gamma = 0.0f; description = QStringLiteral("Undefined"); break; case QColorSpace::SRgb: - gamut = QColorSpace::Gamut::SRgb; + primaries = QColorSpace::Primaries::SRgb; transferFunction = QColorSpace::TransferFunction::SRgb; - gamma = 2.31f; // ? description = QStringLiteral("sRGB"); break; case QColorSpace::SRgbLinear: - gamut = QColorSpace::Gamut::SRgb; + primaries = QColorSpace::Primaries::SRgb; transferFunction = QColorSpace::TransferFunction::Linear; - gamma = 1.0f; description = QStringLiteral("Linear sRGB"); break; case QColorSpace::AdobeRgb: - gamut = QColorSpace::Gamut::AdobeRgb; + primaries = QColorSpace::Primaries::AdobeRgb; transferFunction = QColorSpace::TransferFunction::Gamma; gamma = 2.19921875f; // Not quite 2.2, see https://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf description = QStringLiteral("Adobe RGB"); break; case QColorSpace::DisplayP3: - gamut = QColorSpace::Gamut::DciP3D65; + primaries = QColorSpace::Primaries::DciP3D65; transferFunction = QColorSpace::TransferFunction::SRgb; - gamma = 2.31f; // ? description = QStringLiteral("Display P3"); break; case QColorSpace::ProPhotoRgb: - gamut = QColorSpace::Gamut::ProPhotoRgb; + primaries = QColorSpace::Primaries::ProPhotoRgb; transferFunction = QColorSpace::TransferFunction::ProPhotoRgb; - gamma = 1.8f; description = QStringLiteral("ProPhoto RGB"); break; case QColorSpace::Bt2020: - gamut = QColorSpace::Gamut::Bt2020; + primaries = QColorSpace::Primaries::Bt2020; transferFunction = QColorSpace::TransferFunction::Bt2020; - gamma = 2.1f; // ? description = QStringLiteral("BT.2020"); break; case QColorSpace::Unknown: @@ -216,8 +211,8 @@ QColorSpacePrivate::QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId) initialize(); } -QColorSpacePrivate::QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma) - : gamut(gamut) +QColorSpacePrivate::QColorSpacePrivate(QColorSpace::Primaries primaries, QColorSpace::TransferFunction fun, float gamma) + : primaries(primaries) , transferFunction(fun) , gamma(gamma) { @@ -229,74 +224,81 @@ QColorSpacePrivate::QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::Tr QColorSpacePrivate::QColorSpacePrivate(const QColorSpacePrimaries &primaries, QColorSpace::TransferFunction fun, float gamma) - : gamut(QColorSpace::Gamut::Custom) + : primaries(QColorSpace::Primaries::Custom) , transferFunction(fun) , gamma(gamma) { Q_ASSERT(primaries.areValid()); toXyz = primaries.toXyzMatrix(); whitePoint = QColorVector(primaries.whitePoint); - if (!identifyColorSpace()) - id = QColorSpace::Unknown; + identifyColorSpace(); setTransferFunction(); } bool QColorSpacePrivate::identifyColorSpace() { - switch (gamut) { - case QColorSpace::Gamut::SRgb: + switch (primaries) { + case QColorSpace::Primaries::SRgb: if (transferFunction == QColorSpace::TransferFunction::SRgb) { id = QColorSpace::SRgb; - description = QStringLiteral("sRGB"); + if (description.isEmpty()) + description = QStringLiteral("sRGB"); return true; } if (transferFunction == QColorSpace::TransferFunction::Linear) { id = QColorSpace::SRgbLinear; - description = QStringLiteral("Linear sRGB"); + if (description.isEmpty()) + description = QStringLiteral("Linear sRGB"); return true; } break; - case QColorSpace::Gamut::AdobeRgb: + case QColorSpace::Primaries::AdobeRgb: if (transferFunction == QColorSpace::TransferFunction::Gamma) { if (qAbs(gamma - 2.19921875f) < (1/1024.0f)) { id = QColorSpace::AdobeRgb; - description = QStringLiteral("Adobe RGB"); + if (description.isEmpty()) + description = QStringLiteral("Adobe RGB"); return true; } } break; - case QColorSpace::Gamut::DciP3D65: + case QColorSpace::Primaries::DciP3D65: if (transferFunction == QColorSpace::TransferFunction::SRgb) { id = QColorSpace::DisplayP3; - description = QStringLiteral("Display P3"); + if (description.isEmpty()) + description = QStringLiteral("Display P3"); return true; } break; - case QColorSpace::Gamut::ProPhotoRgb: + case QColorSpace::Primaries::ProPhotoRgb: if (transferFunction == QColorSpace::TransferFunction::ProPhotoRgb) { id = QColorSpace::ProPhotoRgb; - description = QStringLiteral("ProPhoto RGB"); + if (description.isEmpty()) + description = QStringLiteral("ProPhoto RGB"); return true; } if (transferFunction == QColorSpace::TransferFunction::Gamma) { // ProPhoto RGB's curve is effectively gamma 1.8 for 8bit precision. if (qAbs(gamma - 1.8f) < (1/1024.0f)) { id = QColorSpace::ProPhotoRgb; - description = QStringLiteral("ProPhoto RGB"); + if (description.isEmpty()) + description = QStringLiteral("ProPhoto RGB"); return true; } } break; - case QColorSpace::Gamut::Bt2020: + case QColorSpace::Primaries::Bt2020: if (transferFunction == QColorSpace::TransferFunction::Bt2020) { id = QColorSpace::Bt2020; - description = QStringLiteral("BT.2020"); + if (description.isEmpty()) + description = QStringLiteral("BT.2020"); return true; } break; default: break; } + id = QColorSpace::Unknown; return false; } @@ -308,14 +310,14 @@ void QColorSpacePrivate::initialize() void QColorSpacePrivate::setToXyzMatrix() { - if (gamut == QColorSpace::Gamut::Custom) { + if (primaries == QColorSpace::Primaries::Custom) { toXyz = QColorMatrix::null(); whitePoint = QColorVector::D50(); return; } - QColorSpacePrimaries primaries(gamut); - toXyz = primaries.toXyzMatrix(); - whitePoint = QColorVector(primaries.whitePoint); + QColorSpacePrimaries colorSpacePrimaries(primaries); + toXyz = colorSpacePrimaries.toXyzMatrix(); + whitePoint = QColorVector(colorSpacePrimaries.whitePoint); } void QColorSpacePrivate::setTransferFunction() @@ -324,6 +326,8 @@ void QColorSpacePrivate::setTransferFunction() case QColorSpace::TransferFunction::Linear: trc[0].m_type = QColorTrc::Type::Function; trc[0].m_fun = QColorTransferFunction(); + if (qFuzzyIsNull(gamma)) + gamma = 1.0f; break; case QColorSpace::TransferFunction::Gamma: trc[0].m_type = QColorTrc::Type::Function; @@ -332,14 +336,20 @@ void QColorSpacePrivate::setTransferFunction() case QColorSpace::TransferFunction::SRgb: trc[0].m_type = QColorTrc::Type::Function; trc[0].m_fun = QColorTransferFunction::fromSRgb(); + if (qFuzzyIsNull(gamma)) + gamma = 2.31f; break; case QColorSpace::TransferFunction::ProPhotoRgb: trc[0].m_type = QColorTrc::Type::Function; trc[0].m_fun = QColorTransferFunction::fromProPhotoRgb(); + if (qFuzzyIsNull(gamma)) + gamma = 1.8f; break; case QColorSpace::TransferFunction::Bt2020: trc[0].m_type = QColorTrc::Type::Function; trc[0].m_fun = QColorTransferFunction::fromBt2020(); + if (qFuzzyIsNull(gamma)) + gamma = 1.961f; break; case QColorSpace::TransferFunction::Custom: break; @@ -355,10 +365,12 @@ QColorTransform QColorSpacePrivate::transformationToColorSpace(const QColorSpace { Q_ASSERT(out); QColorTransform combined; - combined.d_ptr.reset(new QColorTransformPrivate); - combined.d_ptr->colorSpaceIn = this; - combined.d_ptr->colorSpaceOut = out; - combined.d_ptr->colorMatrix = out->toXyz.inverted() * toXyz; + auto ptr = new QColorTransformPrivate; + combined.d = ptr; + combined.d->ref.ref(); + ptr->colorSpaceIn = this; + ptr->colorSpaceOut = out; + ptr->colorMatrix = out->toXyz.inverted() * toXyz; return combined; } @@ -381,12 +393,14 @@ QColorTransform QColorSpacePrivate::transformationToColorSpace(const QColorSpace QColorSpace can also represent color spaces defined by ICC profiles or embedded in images, that do not otherwise fit the predefined color spaces. - A color space can generally speaking be conceived as a combination of a transfer - function and a gamut. The gamut defines which colors the color space can represent. - A color space that can represent a wider range of colors is also known as a - wide-gamut color space. The gamut is defined by three primary colors that represent - exactly how red, green, and blue look in this particular color space, and a white - color that represents where and how bright pure white is. + A color space can generally speaking be conceived as a combination of set of primary + colors and a transfer function. The primaries defines the axes of the color space, and + the transfer function how values are mapped on the axes. + The primaries are defined by three primary colors that represent exactly how red, green, + and blue look in this particular color space, and a white color that represents where + and how bright pure white is. The range of colors expressable by the primary colors is + called the gamut, and a color space that can represent a wider range of colors is also + known as a wide-gamut color space. The transfer function or gamma curve determines how each component in the color space is encoded. These are used because human perception does not operate @@ -418,16 +432,16 @@ QColorTransform QColorSpacePrivate::transformationToColorSpace(const QColorSpace */ /*! - \enum QColorSpace::Gamut + \enum QColorSpace::Primaries - Predefined gamuts, or sets of primary colors. + Predefined sets of primary colors. - \value Custom The gamut is undefined or does not match any predefined sets. - \value SRgb The sRGB gamut - \value AdobeRgb The Adobe RGB gamut - \value DciP3D65 The DCI-P3 gamut with the D65 whitepoint - \value ProPhotoRgb The ProPhoto RGB gamut with the D50 whitepoint - \value Bt2020 The BT.2020 gamut + \value Custom The primaries are undefined or does not match any predefined sets. + \value SRgb The sRGB primaries + \value AdobeRgb The Adobe RGB primaries + \value DciP3D65 The DCI-P3 primaries with the D65 whitepoint + \value ProPhotoRgb The ProPhoto RGB primaries with the D50 whitepoint + \value Bt2020 The BT.2020 primaries */ /*! @@ -463,25 +477,25 @@ QColorSpace::QColorSpace(QColorSpace::ColorSpaceId colorSpaceId) } /*! - Creates a custom color space with the gamut \a gamut, using the transfer function \a fun and + Creates a custom color space with the primaries \a primaries, using the transfer function \a fun and optionally \a gamma. */ -QColorSpace::QColorSpace(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma) - : d_ptr(new QColorSpacePrivate(gamut, fun, gamma)) +QColorSpace::QColorSpace(QColorSpace::Primaries primaries, QColorSpace::TransferFunction fun, float gamma) + : d_ptr(new QColorSpacePrivate(primaries, fun, gamma)) { } /*! - Creates a custom color space with the gamut \a gamut, using a gamma transfer function of + Creates a custom color space with the primaries \a primaries, using a gamma transfer function of \a gamma. */ -QColorSpace::QColorSpace(QColorSpace::Gamut gamut, float gamma) - : d_ptr(new QColorSpacePrivate(gamut, TransferFunction::Gamma, gamma)) +QColorSpace::QColorSpace(QColorSpace::Primaries primaries, float gamma) + : d_ptr(new QColorSpacePrivate(primaries, TransferFunction::Gamma, gamma)) { } /*! - Creates a custom colorspace with a gamut based on the chromaticities of the primary colors \a whitePoint, + Creates a custom colorspace with a primaries based on the chromaticities of the primary colors \a whitePoint, \a redPoint, \a greenPoint and \a bluePoint, and using the transfer function \a fun and optionally \a gamma. */ QColorSpace::QColorSpace(const QPointF &whitePoint, const QPointF &redPoint, @@ -501,7 +515,7 @@ QColorSpace::~QColorSpace() { } -QColorSpace::QColorSpace(QColorSpace &&colorSpace) +QColorSpace::QColorSpace(QColorSpace &&colorSpace) noexcept : d_ptr(std::move(colorSpace.d_ptr)) { } @@ -511,7 +525,7 @@ QColorSpace::QColorSpace(const QColorSpace &colorSpace) { } -QColorSpace &QColorSpace::operator=(QColorSpace &&colorSpace) +QColorSpace &QColorSpace::operator=(QColorSpace &&colorSpace) noexcept { d_ptr = std::move(colorSpace.d_ptr); return *this; @@ -523,6 +537,12 @@ QColorSpace &QColorSpace::operator=(const QColorSpace &colorSpace) return *this; } +/*! \fn void QColorSpace::swap(QColorSpace &other) + + Swaps color space \a other with this color space. This operation is very fast and + never fails. +*/ + /*! Returns the id of the predefined color space this object represents or \c Unknown if it doesn't match any of them. @@ -533,19 +553,21 @@ QColorSpace::ColorSpaceId QColorSpace::colorSpaceId() const noexcept } /*! - Returns the predefined gamut of the color space - or \c Gamut::Custom if it doesn't match any of them. + Returns the predefined primaries of the color space + or \c primaries::Custom if it doesn't match any of them. */ -QColorSpace::Gamut QColorSpace::gamut() const noexcept +QColorSpace::Primaries QColorSpace::primaries() const noexcept { - return d_ptr->gamut; + if (Q_UNLIKELY(!d_ptr)) + return QColorSpace::Primaries::Custom; + return d_ptr->primaries; } /*! Returns the predefined transfer function of the color space or \c TransferFunction::Custom if it doesn't match any of them. - \sa gamma() + \sa gamma(), setTransferFunction(), withTransferFunction() */ QColorSpace::TransferFunction QColorSpace::transferFunction() const noexcept { @@ -564,6 +586,91 @@ float QColorSpace::gamma() const noexcept return d_ptr->gamma; } +/*! + Sets the transfer function to \a transferFunction and \a gamma. + + \note This also changes colorSpaceId(). + + \sa transferFunction(), gamma(), withTransferFunction() +*/ +void QColorSpace::setTransferFunction(QColorSpace::TransferFunction transferFunction, float gamma) +{ + if (!isValid() || transferFunction == QColorSpace::TransferFunction::Custom) + return; + if (d_ptr->transferFunction == transferFunction && d_ptr->gamma == gamma) + return; + d_ptr.detach(); + d_ptr->description.clear(); + d_ptr->transferFunction = transferFunction; + d_ptr->gamma = gamma; + d_ptr->identifyColorSpace(); + d_ptr->setTransferFunction(); +} + +/*! + Returns a copy of this color space, except using the transfer function + \a transferFunction and \a gamma. + + \sa transferFunction(), gamma(), setTransferFunction() +*/ +QColorSpace QColorSpace::withTransferFunction(QColorSpace::TransferFunction transferFunction, float gamma) const +{ + if (!isValid() || transferFunction == QColorSpace::TransferFunction::Custom) + return *this; + if (d_ptr->transferFunction == transferFunction && d_ptr->gamma == gamma) + return *this; + QColorSpace out(*this); + out.setTransferFunction(transferFunction, gamma); + return out; +} + +/*! + Sets the primaries to those of the \a primariesId set. + + \note This also changes colorSpaceId(). + + \sa primaries() +*/ +void QColorSpace::setPrimaries(QColorSpace::Primaries primariesId) +{ + if (!isValid() || primariesId == QColorSpace::Primaries::Custom) + return; + if (d_ptr->primaries == primariesId) + return; + d_ptr.detach(); + d_ptr->description.clear(); + d_ptr->primaries = primariesId; + d_ptr->identifyColorSpace(); + d_ptr->setToXyzMatrix(); +} + +/*! + Set primaries to the chromaticities of \a whitePoint, \a redPoint, \a greenPoint + and \a bluePoint. + + \note This also changes colorSpaceId(). + + \sa primaries() +*/ +void QColorSpace::setPrimaries(const QPointF &whitePoint, const QPointF &redPoint, + const QPointF &greenPoint, const QPointF &bluePoint) +{ + if (!isValid()) + return; + QColorSpacePrimaries primaries(whitePoint, redPoint, greenPoint, bluePoint); + if (!primaries.areValid()) + return; + QColorMatrix toXyz = primaries.toXyzMatrix(); + if (QColorVector(primaries.whitePoint) == d_ptr->whitePoint && toXyz == d_ptr->toXyz) + return; + d_ptr.detach(); + d_ptr->description.clear(); + d_ptr->primaries = QColorSpace::Primaries::Custom; + d_ptr->toXyz = toXyz; + d_ptr->whitePoint = QColorVector(primaries.whitePoint); + d_ptr->identifyColorSpace(); +} + /*! Returns an ICC profile representing the color space. @@ -631,8 +738,8 @@ bool operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2) if (colorSpace1.colorSpaceId() != QColorSpace::Unknown && colorSpace2.colorSpaceId() != QColorSpace::Unknown) return colorSpace1.colorSpaceId() == colorSpace2.colorSpaceId(); - if (colorSpace1.gamut() != QColorSpace::Gamut::Custom && colorSpace2.gamut() != QColorSpace::Gamut::Custom) { - if (colorSpace1.gamut() != colorSpace2.gamut()) + if (colorSpace1.primaries() != QColorSpace::Primaries::Custom && colorSpace2.primaries() != QColorSpace::Primaries::Custom) { + if (colorSpace1.primaries() != colorSpace2.primaries()) return false; } else { if (colorSpace1.d_ptr->toXyz != colorSpace2.d_ptr->toXyz) @@ -644,7 +751,7 @@ bool operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2) if (colorSpace1.transferFunction() != colorSpace2.transferFunction()) return false; if (colorSpace1.transferFunction() == QColorSpace::TransferFunction::Gamma) - return colorSpace1.gamma() == colorSpace2.gamma(); + return (qAbs(colorSpace1.gamma() - colorSpace2.gamma()) <= (1.0f / 512.0f)); return true; } @@ -676,20 +783,6 @@ QColorTransform QColorSpace::transformationToColorSpace(const QColorSpace &color return d_ptr->transformationToColorSpace(colorspace.d_ptr.constData()); } -/*! - \internal -*/ -QColorSpacePrivate *QColorSpace::d_func() -{ - d_ptr.detach(); - return d_ptr.data(); -} - -/*! - \fn const QColorSpacePrivate* QColorSpacePrivate::d_func() const - \internal -*/ - /***************************************************************************** QColorSpace stream functions *****************************************************************************/ @@ -734,7 +827,7 @@ QDebug operator<<(QDebug dbg, const QColorSpace &colorSpace) QDebugStateSaver saver(dbg); dbg.nospace(); dbg << "QColorSpace("; - dbg << colorSpace.colorSpaceId() << ", " << colorSpace.gamut() << ", " << colorSpace.transferFunction(); + dbg << colorSpace.colorSpaceId() << ", " << colorSpace.primaries() << ", " << colorSpace.transferFunction(); dbg << ", gamma=" << colorSpace.gamma(); dbg << ')'; return dbg; diff --git a/src/gui/painting/qcolorspace.h b/src/gui/painting/qcolorspace.h index 56676826a9a..a7c10919116 100644 --- a/src/gui/painting/qcolorspace.h +++ b/src/gui/painting/qcolorspace.h @@ -63,7 +63,7 @@ public: Bt2020, }; Q_ENUM(ColorSpaceId) - enum class Gamut { + enum class Primaries { Custom = 0, SRgb, AdobeRgb, @@ -71,7 +71,7 @@ public: ProPhotoRgb, Bt2020, }; - Q_ENUM(Gamut) + Q_ENUM(Primaries) enum class TransferFunction { Custom = 0, Linear, @@ -83,23 +83,33 @@ public: Q_ENUM(TransferFunction) QColorSpace(ColorSpaceId colorSpaceId = Undefined); - QColorSpace(Gamut gamut, TransferFunction fun, float gamma = 0.0f); - QColorSpace(Gamut gamut, float gamma); + QColorSpace(Primaries primaries, TransferFunction fun, float gamma = 0.0f); + QColorSpace(Primaries primaries, float gamma); QColorSpace(const QPointF &whitePoint, const QPointF &redPoint, const QPointF &greenPoint, const QPointF &bluePoint, TransferFunction fun, float gamma = 0.0f); ~QColorSpace(); - QColorSpace(QColorSpace &&colorSpace); + QColorSpace(QColorSpace &&colorSpace) noexcept; QColorSpace(const QColorSpace &colorSpace); - QColorSpace &operator=(QColorSpace &&colorSpace); + QColorSpace &operator=(QColorSpace &&colorSpace) noexcept; QColorSpace &operator=(const QColorSpace &colorSpace); + void swap(QColorSpace &colorSpace) noexcept + { qSwap(d_ptr, colorSpace.d_ptr); } + ColorSpaceId colorSpaceId() const noexcept; - Gamut gamut() const noexcept; + Primaries primaries() const noexcept; TransferFunction transferFunction() const noexcept; float gamma() const noexcept; + void setTransferFunction(TransferFunction transferFunction, float gamma = 0.0f); + QColorSpace withTransferFunction(TransferFunction transferFunction, float gamma = 0.0f) const; + + void setPrimaries(Primaries primariesId); + void setPrimaries(const QPointF &whitePoint, const QPointF &redPoint, + const QPointF &greenPoint, const QPointF &bluePoint); + bool isValid() const noexcept; friend Q_GUI_EXPORT bool operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2); @@ -110,11 +120,9 @@ public: QColorTransform transformationToColorSpace(const QColorSpace &colorspace) const; - QColorSpacePrivate *d_func(); - inline const QColorSpacePrivate *d_func() const { return d_ptr.constData(); } private: - friend class QColorSpacePrivate; + Q_DECLARE_PRIVATE(QColorSpace) QExplicitlySharedDataPointer d_ptr; }; @@ -124,6 +132,8 @@ inline bool operator!=(const QColorSpace &colorSpace1, const QColorSpace &colorS return !(colorSpace1 == colorSpace2); } +Q_DECLARE_SHARED(QColorSpace) + // QColorSpace stream functions #if !defined(QT_NO_DATASTREAM) Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QColorSpace &); diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h index 95e0655d0cf..2a40a0cfd8b 100644 --- a/src/gui/painting/qcolorspace_p.h +++ b/src/gui/painting/qcolorspace_p.h @@ -66,7 +66,7 @@ class Q_GUI_EXPORT QColorSpacePrimaries { public: QColorSpacePrimaries() = default; - QColorSpacePrimaries(QColorSpace::Gamut gamut); + QColorSpacePrimaries(QColorSpace::Primaries primaries); QColorSpacePrimaries(QPointF whitePoint, QPointF redPoint, QPointF greenPoint, @@ -91,10 +91,21 @@ class QColorSpacePrivate : public QSharedData public: QColorSpacePrivate(); QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId); - QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma); + QColorSpacePrivate(QColorSpace::Primaries primaries, QColorSpace::TransferFunction fun, float gamma); QColorSpacePrivate(const QColorSpacePrimaries &primaries, QColorSpace::TransferFunction fun, float gamma); QColorSpacePrivate(const QColorSpacePrivate &other) = default; + static QColorSpacePrivate *getWritable(QColorSpace &colorSpace) + { + colorSpace.d_ptr.detach(); + return colorSpace.d_ptr.data(); + } + + static const QColorSpacePrivate *get(const QColorSpace &colorSpace) + { + return colorSpace.d_ptr.data(); + } + void initialize(); void setToXyzMatrix(); void setTransferFunction(); @@ -102,7 +113,7 @@ public: QColorTransform transformationToColorSpace(const QColorSpacePrivate *out) const; QColorSpace::ColorSpaceId id; - QColorSpace::Gamut gamut; + QColorSpace::Primaries primaries; QColorSpace::TransferFunction transferFunction; float gamma; QColorVector whitePoint; diff --git a/src/gui/painting/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp index de08bf42211..53fd1dfbaac 100644 --- a/src/gui/painting/qcolortransform.cpp +++ b/src/gui/painting/qcolortransform.cpp @@ -134,8 +134,18 @@ void QColorTransformPrivate::updateLutsOut() const */ -QColorTransform::~QColorTransform() noexcept +QColorTransform::QColorTransform(const QColorTransform &colorTransform) noexcept + : d(colorTransform.d) { + if (d) + d->ref.ref(); +} + + +QColorTransform::~QColorTransform() +{ + if (d && !d->ref.deref()) + delete d; } /*! @@ -143,11 +153,10 @@ QColorTransform::~QColorTransform() noexcept The input should be opaque or unpremultiplied. */ -QRgb QColorTransform::map(const QRgb &argb) const +QRgb QColorTransform::map(QRgb argb) const { - if (!d_ptr) + if (!d) return argb; - Q_D(const QColorTransform); constexpr float f = 1.0f / 255.0f; QColorVector c = { qRed(argb) * f, qGreen(argb) * f, qBlue(argb) * f }; c.x = d->colorSpaceIn->trc[0].apply(c.x); @@ -175,11 +184,10 @@ QRgb QColorTransform::map(const QRgb &argb) const The input should be opaque or unpremultiplied. */ -QRgba64 QColorTransform::map(const QRgba64 &rgba64) const +QRgba64 QColorTransform::map(QRgba64 rgba64) const { - if (!d_ptr) + if (!d) return rgba64; - Q_D(const QColorTransform); constexpr float f = 1.0f / 65535.0f; QColorVector c = { rgba64.red() * f, rgba64.green() * f, rgba64.blue() * f }; c.x = d->colorSpaceIn->trc[0].apply(c.x); @@ -208,9 +216,8 @@ QRgba64 QColorTransform::map(const QRgba64 &rgba64) const */ QColor QColorTransform::map(const QColor &color) const { - if (!d_ptr) + if (!d) return color; - Q_D(const QColorTransform); QColor clr = color; if (color.spec() != QColor::ExtendedRgb || color.spec() != QColor::Rgb) clr = clr.toRgb(); @@ -228,7 +235,7 @@ QColor QColorTransform::map(const QColor &color) const c = d->colorMatrix.map(c); bool inGamut = c.x >= 0.0f && c.x <= 1.0f && c.y >= 0.0f && c.y <= 1.0f && c.z >= 0.0f && c.z <= 1.0f; if (inGamut) { - if (d_ptr->colorSpaceOut->lut.generated.loadAcquire()) { + if (d->colorSpaceOut->lut.generated.loadAcquire()) { c.x = d->colorSpaceOut->lut[0]->fromLinear(c.x); c.y = d->colorSpaceOut->lut[1]->fromLinear(c.y); c.z = d->colorSpaceOut->lut[2]->fromLinear(c.z); diff --git a/src/gui/painting/qcolortransform.h b/src/gui/painting/qcolortransform.h index 9274387b97b..5fb51739a7c 100644 --- a/src/gui/painting/qcolortransform.h +++ b/src/gui/painting/qcolortransform.h @@ -51,43 +51,42 @@ class QRgba64; class QColorSpacePrivate; class QColorTransformPrivate; -class Q_GUI_EXPORT QColorTransform +class QColorTransform { public: - QColorTransform() noexcept : d_ptr(nullptr) { } - ~QColorTransform() noexcept; - QColorTransform(const QColorTransform &colorTransform) noexcept - : d_ptr(colorTransform.d_ptr) - { } + QColorTransform() noexcept : d(nullptr) { } + Q_GUI_EXPORT ~QColorTransform(); + Q_GUI_EXPORT QColorTransform(const QColorTransform &colorTransform) noexcept; QColorTransform(QColorTransform &&colorTransform) noexcept - : d_ptr(std::move(colorTransform.d_ptr)) + : d{qExchange(colorTransform.d, nullptr)} { } QColorTransform &operator=(const QColorTransform &other) noexcept { - d_ptr = other.d_ptr; + QColorTransform{other}.swap(*this); return *this; } QColorTransform &operator=(QColorTransform &&other) noexcept { - d_ptr = std::move(other.d_ptr); + QColorTransform{std::move(other)}.swap(*this); return *this; } - bool isNull() const { return d_ptr.isNull(); } + void swap(QColorTransform &other) noexcept { qSwap(d, other.d); } - QRgb map(const QRgb &argb) const; - QRgba64 map(const QRgba64 &rgba64) const; - QColor map(const QColor &color) const; + Q_GUI_EXPORT QRgb map(QRgb argb) const; + Q_GUI_EXPORT QRgba64 map(QRgba64 rgba64) const; + Q_GUI_EXPORT QColor map(const QColor &color) const; private: friend class QColorSpace; friend class QColorSpacePrivate; friend class QImage; - Q_DECLARE_PRIVATE(QColorTransform) - QSharedPointer d_ptr; + const QColorTransformPrivate *d; }; +Q_DECLARE_SHARED(QColorTransform) + QT_END_NAMESPACE #endif // QCOLORTRANSFORM_H diff --git a/src/gui/painting/qcolortransform_p.h b/src/gui/painting/qcolortransform_p.h index 74a1e7fe0a8..5d7116248d6 100644 --- a/src/gui/painting/qcolortransform_p.h +++ b/src/gui/painting/qcolortransform_p.h @@ -54,9 +54,11 @@ #include "qcolormatrix_p.h" #include "qcolorspace_p.h" +#include + QT_BEGIN_NAMESPACE -class QColorTransformPrivate +class QColorTransformPrivate : public QSharedData { public: QColorMatrix colorMatrix; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 006befea224..674f52678dd 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -2053,6 +2053,23 @@ inline void fetchTransformed_pixelBounds(int max, int l1, int l2, int &v) } } +static inline bool canUseFastMatrixPath(const qreal cx, const qreal cy, const qsizetype length, const QSpanData *data) +{ + if (Q_UNLIKELY(!data->fast_matrix)) + return false; + + qreal fx = (data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale; + qreal fy = (data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale; + qreal minc = std::min(fx, fy); + qreal maxc = std::max(fx, fy); + fx += std::trunc(data->m11 * fixed_scale) * length; + fy += std::trunc(data->m12 * fixed_scale) * length; + minc = std::min(minc, std::min(fx, fy)); + maxc = std::max(maxc, std::max(fx, fy)); + + return minc >= std::numeric_limits::min() && maxc <= std::numeric_limits::max(); +} + template static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *data, int y, int x, int length) @@ -2070,7 +2087,7 @@ static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *dat // When templated 'fetch' should be inlined at compile time: const FetchPixelFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : FetchPixelFunc(fetchPixel); - if (data->fast_matrix) { + if (canUseFastMatrixPath(cx, cy, length, data)) { // The increment pr x in the scanline int fdx = (int)(data->m11 * fixed_scale); int fdy = (int)(data->m12 * fixed_scale); @@ -3026,7 +3043,7 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c uint *end = buffer + length; uint *b = buffer; - if (data->fast_matrix) { + if (canUseFastMatrixPath(cx, cy, length, data)) { // The increment pr x in the scanline int fdx = (int)(data->m11 * fixed_scale); int fdy = (int)(data->m12 * fixed_scale); @@ -3383,7 +3400,7 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper const qreal cx = x + qreal(0.5); const qreal cy = y + qreal(0.5); - if (data->fast_matrix) { + if (canUseFastMatrixPath(cx, cy, length, data)) { // The increment pr x in the scanline int fdx = (int)(data->m11 * fixed_scale); int fdy = (int)(data->m12 * fixed_scale); @@ -3570,7 +3587,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint32(QRgba64 *buf QRgba64 *end = buffer + length; QRgba64 *b = buffer; - if (data->fast_matrix) { + if (canUseFastMatrixPath(cx, cy, length, data)) { // The increment pr x in the scanline const int fdx = (int)(data->m11 * fixed_scale); const int fdy = (int)(data->m12 * fixed_scale); @@ -3728,7 +3745,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint64(QRgba64 *buf QRgba64 *end = buffer + length; QRgba64 *b = buffer; - if (data->fast_matrix) { + if (canUseFastMatrixPath(cx, cy, length, data)) { // The increment pr x in the scanline const int fdx = (int)(data->m11 * fixed_scale); const int fdy = (int)(data->m12 * fixed_scale); diff --git a/src/gui/painting/qicc.cpp b/src/gui/painting/qicc.cpp index d88b0057827..6cb7b574939 100644 --- a/src/gui/painting/qicc.cpp +++ b/src/gui/painting/qicc.cpp @@ -42,8 +42,9 @@ #include #include #include -#include #include +#include +#include #include "qcolorspace_p.h" #include "qcolortrc_p.h" @@ -117,6 +118,7 @@ enum class Tag : quint32 { bkpt = IccTag('b', 'k', 'p', 't'), mft1 = IccTag('m', 'f', 't', '1'), mft2 = IccTag('m', 'f', 't', '2'), + mluc = IccTag('m', 'l', 'u', 'c'), mAB_ = IccTag('m', 'A', 'B', ' '), mBA_ = IccTag('m', 'B', 'A', ' '), chad = IccTag('c', 'h', 'a', 'd'), @@ -164,6 +166,25 @@ struct ParaTagData : GenericTagData { quint32_be parameter[1]; }; +struct DescTagData : GenericTagData { + quint32_be asciiDescriptionLength; + char asciiDescription[1]; + // .. we ignore the rest +}; + +struct MlucTagRecord { + quint16_be languageCode; + quint16_be countryCode; + quint32_be size; + quint32_be offset; +}; + +struct MlucTagData : GenericTagData { + quint32_be recordCount; + quint32_be recordSize; // = sizeof(MlucTagRecord) + MlucTagRecord records[1]; +}; + // For both mAB and mBA struct mABTagData : GenericTagData { quint8 inputChannels; @@ -190,23 +211,17 @@ static float fromFixedS1516(int x) return x * (1.0f / 65536.0f); } -QColorVector fromXyzData(const XYZTagData *xyz) -{ - const float x = fromFixedS1516(xyz->fixedX); - const float y = fromFixedS1516(xyz->fixedY); - const float z = fromFixedS1516(xyz->fixedZ); - qCDebug(lcIcc) << "XYZ_ " << x << y << z; - - return QColorVector(x, y, z); -} - static bool isValidIccProfile(const ICCProfileHeader &header) { if (header.signature != uint(Tag::acsp)) { qCWarning(lcIcc, "Failed ICC signature test"); return false; } - if (header.profileSize < (sizeof(ICCProfileHeader) + header.tagCount * sizeof(TagTableEntry))) { + + // Don't overflow 32bit integers: + if (header.tagCount >= INT32_MAX / sizeof(TagTableEntry)) + return false; + if (header.profileSize - sizeof(ICCProfileHeader) < header.tagCount * sizeof(TagTableEntry)) { qCWarning(lcIcc, "Failed basic size sanity"); return false; } @@ -288,7 +303,7 @@ QByteArray toIccProfile(const QColorSpace &space) if (!space.isValid()) return QByteArray(); - const QColorSpacePrivate *spaceDPtr = space.d_func(); + const QColorSpacePrivate *spaceDPtr = QColorSpacePrivate::get(space); constexpr int tagCount = 9; constexpr uint profileDataOffset = 128 + 4 + 12 * tagCount; @@ -413,17 +428,44 @@ QByteArray toIccProfile(const QColorSpace &space) return iccProfile; } -bool parseTRC(const GenericTagData *trcData, QColorTrc &gamma) +struct TagEntry { + quint32 offset; + quint32 size; +}; + +bool parseXyzData(const QByteArray &data, const TagEntry &tagEntry, QColorVector &colorVector) { + if (tagEntry.size < sizeof(XYZTagData)) { + qCWarning(lcIcc) << "Undersized XYZ tag"; + return false; + } + const XYZTagData *xyz = reinterpret_cast(data.constData() + tagEntry.offset); + if (xyz->type != quint32(Tag::XYZ_)) { + qCWarning(lcIcc) << "Bad XYZ content type"; + return false; + } + const float x = fromFixedS1516(xyz->fixedX); + const float y = fromFixedS1516(xyz->fixedY); + const float z = fromFixedS1516(xyz->fixedZ); + + colorVector = QColorVector(x, y, z); + return true; +} + +bool parseTRC(const QByteArray &data, const TagEntry &tagEntry, QColorTrc &gamma) +{ + const GenericTagData *trcData = reinterpret_cast(data.constData() + tagEntry.offset); if (trcData->type == quint32(Tag::curv)) { - const CurvTagData *curv = reinterpret_cast(trcData); - qCDebug(lcIcc) << "curv" << uint(curv->valueCount); + const CurvTagData *curv = static_cast(trcData); + if (curv->valueCount > (1 << 16)) + return false; + if (tagEntry.size - 12 < 2 * curv->valueCount) + return false; if (curv->valueCount == 0) { gamma.m_type = QColorTrc::Type::Function; gamma.m_fun = QColorTransferFunction(); // Linear } else if (curv->valueCount == 1) { float g = curv->value[0] * (1.0f / 256.0f); - qCDebug(lcIcc) << g; gamma.m_type = QColorTrc::Type::Function; gamma.m_fun = QColorTransferFunction::fromGamma(g); } else { @@ -445,49 +487,54 @@ bool parseTRC(const GenericTagData *trcData, QColorTrc &gamma) return true; } if (trcData->type == quint32(Tag::para)) { - const ParaTagData *para = reinterpret_cast(trcData); - qCDebug(lcIcc) << "para" << uint(para->curveType); + if (tagEntry.size < sizeof(ParaTagData)) + return false; + const ParaTagData *para = static_cast(trcData); switch (para->curveType) { case 0: { float g = fromFixedS1516(para->parameter[0]); - qCDebug(lcIcc) << g; gamma.m_type = QColorTrc::Type::Function; gamma.m_fun = QColorTransferFunction::fromGamma(g); break; } case 1: { + if (tagEntry.size < sizeof(ParaTagData) + 2 * 4) + return false; float g = fromFixedS1516(para->parameter[0]); float a = fromFixedS1516(para->parameter[1]); float b = fromFixedS1516(para->parameter[2]); float d = -b / a; - qCDebug(lcIcc) << g << a << b; gamma.m_type = QColorTrc::Type::Function; gamma.m_fun = QColorTransferFunction(a, b, 0.0f, d, 0.0f, 0.0f, g); break; } case 2: { + if (tagEntry.size < sizeof(ParaTagData) + 3 * 4) + return false; float g = fromFixedS1516(para->parameter[0]); float a = fromFixedS1516(para->parameter[1]); float b = fromFixedS1516(para->parameter[2]); float c = fromFixedS1516(para->parameter[3]); float d = -b / a; - qCDebug(lcIcc) << g << a << b << c; gamma.m_type = QColorTrc::Type::Function; gamma.m_fun = QColorTransferFunction(a, b, 0.0f, d, c, c, g); break; } case 3: { + if (tagEntry.size < sizeof(ParaTagData) + 4 * 4) + return false; float g = fromFixedS1516(para->parameter[0]); float a = fromFixedS1516(para->parameter[1]); float b = fromFixedS1516(para->parameter[2]); float c = fromFixedS1516(para->parameter[3]); float d = fromFixedS1516(para->parameter[4]); - qCDebug(lcIcc) << g << a << b << c << d; gamma.m_type = QColorTrc::Type::Function; gamma.m_fun = QColorTransferFunction(a, b, c, d, 0.0f, 0.0f, g); break; } case 4: { + if (tagEntry.size < sizeof(ParaTagData) + 6 * 4) + return false; float g = fromFixedS1516(para->parameter[0]); float a = fromFixedS1516(para->parameter[1]); float b = fromFixedS1516(para->parameter[2]); @@ -495,7 +542,6 @@ bool parseTRC(const GenericTagData *trcData, QColorTrc &gamma) float d = fromFixedS1516(para->parameter[4]); float e = fromFixedS1516(para->parameter[5]); float f = fromFixedS1516(para->parameter[6]); - qCDebug(lcIcc) << g << a << b << c << d << e << f; gamma.m_type = QColorTrc::Type::Function; gamma.m_fun = QColorTransferFunction(a, b, c, d, e, f, g); break; @@ -510,6 +556,53 @@ bool parseTRC(const GenericTagData *trcData, QColorTrc &gamma) return false; } +bool parseDesc(const QByteArray &data, const TagEntry &tagEntry, QString &descName) +{ + const GenericTagData *tag = (const GenericTagData *)(data.constData() + tagEntry.offset); + + // Either 'desc' (ICCv2) or 'mluc' (ICCv4) + if (tag->type == quint32(Tag::desc)) { + if (tagEntry.size < sizeof(DescTagData)) + return false; + const DescTagData *desc = (const DescTagData *)(data.constData() + tagEntry.offset); + const quint32 len = desc->asciiDescriptionLength; + if (len < 1) + return false; + if (tagEntry.size - 12 < len) + return false; + if (desc->asciiDescription[len - 1] != '\0') + return false; + descName = QString::fromLatin1(desc->asciiDescription, len - 1); + return true; + } + if (tag->type != quint32(Tag::mluc)) + return false; + + if (tagEntry.size < sizeof(MlucTagData)) + return false; + const MlucTagData *mluc = (const MlucTagData *)(data.constData() + tagEntry.offset); + if (mluc->recordCount < 1) + return false; + if (mluc->recordSize < 12) + return false; + // We just use the primary record regardless of language or country. + const quint32 stringOffset = mluc->records[0].offset; + const quint32 stringSize = mluc->records[0].size; + if (tagEntry.size < stringOffset || tagEntry.size - stringOffset < stringSize ) + return false; + if ((stringSize | stringOffset) & 1) + return false; + quint32 stringLen = stringSize / 2; + const ushort *unicodeString = (const ushort *)(data.constData() + tagEntry.offset + stringOffset); + // The given length shouldn't include 0-termination, but might. + if (stringLen > 1 && unicodeString[stringLen - 1] == 0) + --stringLen; + QVarLengthArray utf16hostendian(stringLen); + qFromBigEndian(unicodeString, stringLen, utf16hostendian.data()); + descName = QString::fromUtf16(utf16hostendian.data(), stringLen); + return true; +} + bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace) { if (data.size() < qsizetype(sizeof(ICCProfileHeader))) { @@ -529,8 +622,12 @@ bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace) // Read tag index const TagTableEntry *tagTable = (const TagTableEntry *)(data.constData() + sizeof(ICCProfileHeader)); const qsizetype offsetToData = sizeof(ICCProfileHeader) + header->tagCount * sizeof(TagTableEntry); + if (offsetToData > data.size()) { + qCWarning(lcIcc) << "fromIccProfile: failed index size sanity"; + return false; + } - QHash tagIndex; + QHash tagIndex; for (uint i = 0; i < header->tagCount; ++i) { // Sanity check tag sizes and offsets: if (qsizetype(tagTable[i].offset) < offsetToData) { @@ -542,15 +639,24 @@ bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace) qCWarning(lcIcc) << "fromIccProfile: failed tag offset sanity 2"; return false; } - if ((tagTable[i].offset + tagTable[i].size) > header->profileSize) { + if (tagTable[i].size < 12) { + qCWarning(lcIcc) << "fromIccProfile: failed minimal tag size sanity"; + return false; + } + if (tagTable[i].size > header->profileSize - tagTable[i].offset) { qCWarning(lcIcc) << "fromIccProfile: failed tag offset + size sanity"; return false; } + if (tagTable[i].offset & 0x03) { + qCWarning(lcIcc) << "fromIccProfile: invalid tag offset alignment"; + return false; + } // printf("'%4s' %d %d\n", (const char *)&tagTable[i].signature, // quint32(tagTable[i].offset), // quint32(tagTable[i].size)); - tagIndex.insert(Tag(quint32(tagTable[i].signature)), tagTable[i].offset); + tagIndex.insert(Tag(quint32(tagTable[i].signature)), { tagTable[i].offset, tagTable[i].size }); } + // Check the profile is three-component matrix based (what we currently support): if (!tagIndex.contains(Tag::rXYZ) || !tagIndex.contains(Tag::gXYZ) || !tagIndex.contains(Tag::bXYZ) || !tagIndex.contains(Tag::rTRC) || !tagIndex.contains(Tag::gTRC) || !tagIndex.contains(Tag::bTRC) || @@ -559,70 +665,70 @@ bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace) return false; } + QColorSpacePrivate *colorspaceDPtr = QColorSpacePrivate::getWritable(*colorSpace); + // Parse XYZ tags - const XYZTagData *rXyz = (const XYZTagData *)(data.constData() + tagIndex[Tag::rXYZ]); - const XYZTagData *gXyz = (const XYZTagData *)(data.constData() + tagIndex[Tag::gXYZ]); - const XYZTagData *bXyz = (const XYZTagData *)(data.constData() + tagIndex[Tag::bXYZ]); - const XYZTagData *wXyz = (const XYZTagData *)(data.constData() + tagIndex[Tag::wtpt]); - if (rXyz->type != quint32(Tag::XYZ_) || gXyz->type != quint32(Tag::XYZ_) || - wXyz->type != quint32(Tag::XYZ_) || wXyz->type != quint32(Tag::XYZ_)) { - qCWarning(lcIcc) << "fromIccProfile: Bad XYZ data type"; + if (!parseXyzData(data, tagIndex[Tag::rXYZ], colorspaceDPtr->toXyz.r)) + return false; + if (!parseXyzData(data, tagIndex[Tag::gXYZ], colorspaceDPtr->toXyz.g)) + return false; + if (!parseXyzData(data, tagIndex[Tag::bXYZ], colorspaceDPtr->toXyz.b)) + return false; + if (!parseXyzData(data, tagIndex[Tag::wtpt], colorspaceDPtr->whitePoint)) return false; - } - QColorSpacePrivate *colorspaceDPtr = colorSpace->d_func(); - colorspaceDPtr->toXyz.r = fromXyzData(rXyz); - colorspaceDPtr->toXyz.g = fromXyzData(gXyz); - colorspaceDPtr->toXyz.b = fromXyzData(bXyz); - QColorVector whitePoint = fromXyzData(wXyz); - colorspaceDPtr->whitePoint = whitePoint; - - colorspaceDPtr->gamut = QColorSpace::Gamut::Custom; + colorspaceDPtr->primaries = QColorSpace::Primaries::Custom; if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromSRgb()) { - qCDebug(lcIcc) << "fromIccProfile: sRGB gamut detected"; - colorspaceDPtr->gamut = QColorSpace::Gamut::SRgb; + qCDebug(lcIcc) << "fromIccProfile: sRGB primaries detected"; + colorspaceDPtr->primaries = QColorSpace::Primaries::SRgb; } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromAdobeRgb()) { - qCDebug(lcIcc) << "fromIccProfile: Adobe RGB gamut detected"; - colorspaceDPtr->gamut = QColorSpace::Gamut::AdobeRgb; + qCDebug(lcIcc) << "fromIccProfile: Adobe RGB primaries detected"; + colorspaceDPtr->primaries = QColorSpace::Primaries::AdobeRgb; } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromDciP3D65()) { - qCDebug(lcIcc) << "fromIccProfile: DCI-P3 D65 gamut detected"; - colorspaceDPtr->gamut = QColorSpace::Gamut::DciP3D65; + qCDebug(lcIcc) << "fromIccProfile: DCI-P3 D65 primaries detected"; + colorspaceDPtr->primaries = QColorSpace::Primaries::DciP3D65; } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromBt2020()) { - qCDebug(lcIcc) << "fromIccProfile: BT.2020 gamut detected"; - colorspaceDPtr->gamut = QColorSpace::Gamut::Bt2020; + qCDebug(lcIcc) << "fromIccProfile: BT.2020 primaries detected"; + colorspaceDPtr->primaries = QColorSpace::Primaries::Bt2020; } if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromProPhotoRgb()) { - qCDebug(lcIcc) << "fromIccProfile: ProPhoto RGB gamut detected"; - colorspaceDPtr->gamut = QColorSpace::Gamut::ProPhotoRgb; + qCDebug(lcIcc) << "fromIccProfile: ProPhoto RGB primaries detected"; + colorspaceDPtr->primaries = QColorSpace::Primaries::ProPhotoRgb; } // Reset the matrix to our canonical values: - if (colorspaceDPtr->gamut != QColorSpace::Gamut::Custom) + if (colorspaceDPtr->primaries != QColorSpace::Primaries::Custom) colorspaceDPtr->setToXyzMatrix(); // Parse TRC tags - const GenericTagData *rTrc; - const GenericTagData *gTrc; - const GenericTagData *bTrc; + TagEntry rTrc; + TagEntry gTrc; + TagEntry bTrc; if (tagIndex.contains(Tag::aarg) && tagIndex.contains(Tag::aagg) && tagIndex.contains(Tag::aabg)) { // Apple extension for parametric version of TRCs in ICCv2: - rTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::aarg]); - gTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::aagg]); - bTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::aabg]); + rTrc = tagIndex[Tag::aarg]; + gTrc = tagIndex[Tag::aagg]; + bTrc = tagIndex[Tag::aabg]; } else { - rTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::rTRC]); - gTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::gTRC]); - bTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::bTRC]); + rTrc = tagIndex[Tag::rTRC]; + gTrc = tagIndex[Tag::gTRC]; + bTrc = tagIndex[Tag::bTRC]; } QColorTrc rCurve; QColorTrc gCurve; QColorTrc bCurve; - if (!parseTRC(rTrc, rCurve)) + if (!parseTRC(data, rTrc, rCurve)) { + qCWarning(lcIcc) << "fromIccProfile: Invalid rTRC"; return false; - if (!parseTRC(gTrc, gCurve)) + } + if (!parseTRC(data, gTrc, gCurve)) { + qCWarning(lcIcc) << "fromIccProfile: Invalid gTRC"; return false; - if (!parseTRC(bTrc, bCurve)) + } + if (!parseTRC(data, bTrc, bCurve)) { + qCWarning(lcIcc) << "fromIccProfile: Invalid bTRC"; return false; + } if (rCurve == gCurve && gCurve == bCurve && rCurve.m_type == QColorTrc::Type::Function) { if (rCurve.m_fun.isLinear()) { qCDebug(lcIcc) << "fromIccProfile: Linear gamma detected"; @@ -652,7 +758,12 @@ bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace) colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Custom; } - // FIXME: try to parse the description.. + if (tagIndex.contains(Tag::desc)) { + if (!parseDesc(data, tagIndex[Tag::desc], colorspaceDPtr->description)) + qCWarning(lcIcc) << "fromIccProfile: Failed to parse description"; + else + qCDebug(lcIcc) << "fromIccProfile: Description" << colorspaceDPtr->description; + } if (!colorspaceDPtr->identifyColorSpace()) colorspaceDPtr->id = QColorSpace::Unknown; diff --git a/src/gui/painting/qpagedpaintdevice.cpp b/src/gui/painting/qpagedpaintdevice.cpp index 72b2834470c..3fdd0206b7c 100644 --- a/src/gui/painting/qpagedpaintdevice.cpp +++ b/src/gui/painting/qpagedpaintdevice.cpp @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE +// ### Qt 6: remove when the deprecated constructor is removed class QDummyPagedPaintDevicePrivate : public QPagedPaintDevicePrivate { bool setPageLayout(const QPageLayout &newPageLayout) override @@ -85,7 +86,7 @@ QPagedPaintDevicePrivate::~QPagedPaintDevicePrivate() \class QPagedPaintDevice \inmodule QtGui - \brief The QPagedPaintDevice class is a represents a paintdevice that supports + \brief The QPagedPaintDevice class represents a paint device that supports multiple pages. \ingroup painting diff --git a/src/gui/painting/qpagedpaintdevice.h b/src/gui/painting/qpagedpaintdevice.h index 1c37c17fa3b..21e23e0eb4d 100644 --- a/src/gui/painting/qpagedpaintdevice.h +++ b/src/gui/painting/qpagedpaintdevice.h @@ -213,6 +213,7 @@ public: Envelope10 = Comm10E }; + // keep in sync with QPdfEngine::PdfVersion! enum PdfVersion { PdfVersion_1_4, PdfVersion_A1b, PdfVersion_1_6 }; // ### Qt6 Make these virtual diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 461ad51200f..0a440e5b75c 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2902,9 +2902,9 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat != QFontEngine::Format_None ? fontEngine->glyphFormat : d->glyphCacheFormat; QImageTextureGlyphCache *cache = - static_cast(fontEngine->glyphCache(0, glyphFormat, s->matrix)); + static_cast(fontEngine->glyphCache(0, glyphFormat, s->matrix, QColor(s->penData.solidColor))); if (!cache) { - cache = new QImageTextureGlyphCache(glyphFormat, s->matrix); + cache = new QImageTextureGlyphCache(glyphFormat, s->matrix, QColor(s->penData.solidColor)); fontEngine->setGlyphCache(0, cache); } @@ -4295,7 +4295,7 @@ protected: QSharedPointer addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { if (cache.size() == maxCacheSize()) { // may remove more than 1, but OK - cache.erase(cache.begin() + QRandomGenerator::global()->bounded(maxCacheSize())); + cache.erase(std::next(cache.begin(), QRandomGenerator::global()->bounded(maxCacheSize()))); } auto cache_entry = QSharedPointer::create(gradient.stops(), opacity, gradient.interpolationMode()); generateGradientColorTable(gradient, cache_entry->buffer64, paletteSize(), opacity); diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 8801e66b0f9..b1d1f30800b 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -661,6 +661,7 @@ void QPainterPath::clear() detach(); d_func()->clear(); + d_func()->elements.append( {0, 0, MoveToElement} ); } /*! @@ -2337,12 +2338,12 @@ bool QPainterPath::operator==(const QPainterPath &path) const { QPainterPathData *d = reinterpret_cast(d_func()); QPainterPathData *other_d = path.d_func(); - if (other_d == d) + if (other_d == d) { return true; - else if (!d || !other_d) { - if (!d && other_d->elements.empty() && other_d->fillRule == Qt::OddEvenFill) + } else if (!d || !other_d) { + if (!other_d && isEmpty() && elementAt(0) == QPointF() && d->fillRule == Qt::OddEvenFill) return true; - if (!other_d && d && d->elements.empty() && d->fillRule == Qt::OddEvenFill) + if (!d && path.isEmpty() && path.elementAt(0) == QPointF() && other_d->fillRule == Qt::OddEvenFill) return true; return false; } diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h index 22bdbde2a90..a420e0b3d9f 100644 --- a/src/gui/painting/qpainterpath_p.h +++ b/src/gui/painting/qpainterpath_p.h @@ -313,7 +313,7 @@ inline void QPainterPathData::clear() elements.clear(); cStart = 0; - + fillRule = Qt::OddEvenFill; bounds = {}; controlBounds = {}; diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 25d488961cb..f560e1f0f08 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1570,12 +1570,14 @@ void QPdfEnginePrivate::writeHeader() { addXrefEntry(0,false); - static const QHash mapping { - {QPdfEngine::Version_1_4, "1.4"}, - {QPdfEngine::Version_A1b, "1.4"}, - {QPdfEngine::Version_1_6, "1.6"} + // Keep in sync with QPdfEngine::PdfVersion! + static const char mapping[][4] = { + "1.4", // Version_1_4 + "1.4", // Version_A1b + "1.6", // Version_1_6 }; - const char *verStr = mapping.value(pdfVersion, "1.4"); + static const size_t numMappings = sizeof mapping / sizeof *mapping; + const char *verStr = mapping[size_t(pdfVersion) < numMappings ? pdfVersion : 0]; xprintf("%%PDF-%s\n", verStr); xprintf("%%\303\242\303\243\n"); diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h index e337c61f64e..89e549614a0 100644 --- a/src/gui/painting/qpdf_p.h +++ b/src/gui/painting/qpdf_p.h @@ -168,6 +168,7 @@ class Q_GUI_EXPORT QPdfEngine : public QPaintEngine Q_DECLARE_PRIVATE(QPdfEngine) friend class QPdfWriter; public: + // keep in sync with QPagedPaintDevice::PdfVersion and QPdfEnginePrivate::writeHeader()::mapping! enum PdfVersion { Version_1_4, diff --git a/src/gui/painting/qpdfwriter.cpp b/src/gui/painting/qpdfwriter.cpp index 7f18ce42be6..bf7e2d3dca2 100644 --- a/src/gui/painting/qpdfwriter.cpp +++ b/src/gui/painting/qpdfwriter.cpp @@ -170,17 +170,11 @@ void QPdfWriter::setPdfVersion(PdfVersion version) { Q_D(QPdfWriter); - static const QHash engineMapping { - {QPdfWriter::PdfVersion_1_4, QPdfEngine::Version_1_4}, - {QPdfWriter::PdfVersion_A1b, QPdfEngine::Version_A1b}, - {QPdfWriter::PdfVersion_1_6, QPdfEngine::Version_1_6} - }; - if (d->pdfVersion == version) return; d->pdfVersion = version; - d->engine->setPdfVersion(engineMapping.value(version, QPdfEngine::Version_1_4)); + d->engine->setPdfVersion(static_cast(static_cast(version))); } /*! diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index e8c47df21c5..7a3dd049655 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -267,7 +267,7 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition case QFontEngine::Format_A32: return m_current_fontengine->alphaRGBMapForGlyph(g, subPixelPosition, m_transform); case QFontEngine::Format_ARGB: - return m_current_fontengine->bitmapForGlyph(g, subPixelPosition, m_transform); + return m_current_fontengine->bitmapForGlyph(g, subPixelPosition, m_transform, color()); default: return m_current_fontengine->alphaMapForGlyph(g, subPixelPosition, m_transform); } diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index 1e83ab46d15..b6fc7230a8a 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -74,8 +74,8 @@ class QTextItemInt; class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache { public: - QTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) - : QFontEngineGlyphCache(format, matrix), m_current_fontengine(nullptr), + QTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix, const QColor &color = QColor()) + : QFontEngineGlyphCache(format, matrix, color), m_current_fontengine(nullptr), m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0) { } @@ -165,8 +165,8 @@ inline uint qHash(const QTextureGlyphCache::GlyphAndSubPixelPosition &g) class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache { public: - QImageTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) - : QTextureGlyphCache(format, matrix) { } + QImageTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix, const QColor &color = QColor()) + : QTextureGlyphCache(format, matrix, color) { } ~QImageTextureGlyphCache(); virtual void createTextureData(int width, int height) override; diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index d7c1607e576..7443c0a04fb 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -36,6 +36,7 @@ #include "qrhi_p_p.h" #include +#include #include "qrhinull_p_p.h" #ifndef QT_NO_OPENGL @@ -54,6 +55,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general") + /*! \class QRhi \inmodule QtRhi @@ -260,6 +263,12 @@ QT_BEGIN_NAMESPACE tied to those concepts, however, and is thus a topic that is currently out of scope, but may be introduced in the future. + \note The Metal backend requires that an autorelease pool is available on + the rendering thread, ideally wrapping each iteration of the render loop. + This needs no action from the users of QRhi when rendering on the main + (gui) thread, but becomes important when a separate, dedicated render + thread is used. + \section3 Resource synchronization QRhi does not expose APIs for resource barriers or image layout @@ -383,6 +392,22 @@ QT_BEGIN_NAMESPACE texture object is "exported" via QRhi::nativeHandles() or QRhiTexture::nativeHandles(). Most importantly, passing pointers in structs and via setters does not transfer ownership. + + \section2 Troubleshooting + + Errors are printed to the output via qWarning(). Additional debug messages + can be enabled via the following logging categories. Messages from these + categories are not printed by default unless explicitly enabled via + QRhi::EnableProfiling or the facilities of QLoggingCategory (such as, the + \c QT_LOGGING_RULES environment variable). + + \list + \li \c{qt.rhi.general} + \endlist + + It is strongly advised to inspect the output with the logging categories + (\c{qt.rhi.*}) enabled whenever a QRhi-based application is not behaving as + expected. */ /*! @@ -403,7 +428,8 @@ QT_BEGIN_NAMESPACE \value EnableProfiling Enables gathering timing (CPU, GPU) and resource (QRhiBuffer, QRhiTexture, etc.) information and additional metadata. See QRhiProfiler. Avoid enabling in production builds as it may involve a - performance penalty. + performance penalty. Also enables debug messages from the \c{qt.rhi.*} + logging categories. \value EnableDebugMarkers Enables debug marker groups. Without this frame debugging features like making debug groups and custom resource name @@ -3867,11 +3893,21 @@ QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRh if (r->d) { r->d->q = r.data(); + if (flags.testFlag(EnableProfiling)) { QRhiProfilerPrivate *profD = QRhiProfilerPrivate::get(&r->d->profiler); profD->rhiDWhenEnabled = r->d; + const_cast(QRHI_LOG_INFO()).setEnabled(QtDebugMsg, true); } + + // Play nice with QSG_INFO since that is still the most commonly used + // way to get graphics info printed from Qt Quick apps, and the Quick + // scenegraph is our primary user. + if (qEnvironmentVariableIsSet("QSG_INFO")) + const_cast(QRHI_LOG_INFO()).setEnabled(QtDebugMsg, true); + r->d->debugMarkers = flags.testFlag(EnableDebugMarkers); + if (r->d->create(flags)) { r->d->implType = impl; r->d->implThread = QThread::currentThread(); @@ -4911,6 +4947,11 @@ QRhiShaderResourceBindings *QRhi::newShaderResourceBindings() backends. See \l{QRhiBuffer::UsageFlag}{UsageFlags} and \l{QRhi::NonDynamicUniformBuffers}{the feature flags}. + \note Backends may choose to allocate buffers bigger than \a size. This is + done transparently to applications, so there are no special restrictions on + the value of \a size. QRhiBuffer::size() will always report back the value + that was requested in \a size. + \sa QRhiResource::release() */ QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type, @@ -5331,4 +5372,32 @@ void QRhiPassResourceTracker::registerTexture(QRhiTexture *tex, TextureAccess *a m_textures.append(t); } +QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages) +{ + // pick the earlier stage (as this is going to be dstAccessMask) + if (stages.testFlag(QRhiShaderResourceBinding::VertexStage)) + return QRhiPassResourceTracker::BufVertexStage; + if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage)) + return QRhiPassResourceTracker::BufFragmentStage; + if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage)) + return QRhiPassResourceTracker::BufComputeStage; + + Q_UNREACHABLE(); + return QRhiPassResourceTracker::BufVertexStage; +} + +QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages) +{ + // pick the earlier stage (as this is going to be dstAccessMask) + if (stages.testFlag(QRhiShaderResourceBinding::VertexStage)) + return QRhiPassResourceTracker::TexVertexStage; + if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage)) + return QRhiPassResourceTracker::TexFragmentStage; + if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage)) + return QRhiPassResourceTracker::TexComputeStage; + + Q_UNREACHABLE(); + return QRhiPassResourceTracker::TexVertexStage; +} + QT_END_NAMESPACE diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h index 83d521f4416..b592fe82f25 100644 --- a/src/gui/rhi/qrhi_p_p.h +++ b/src/gui/rhi/qrhi_p_p.h @@ -52,6 +52,7 @@ #include "qrhiprofiler_p_p.h" #include #include +#include QT_BEGIN_NAMESPACE @@ -60,6 +61,8 @@ QT_BEGIN_NAMESPACE #define QRHI_PROF QRhiProfilerPrivate *rhiP = m_rhi->profilerPrivateOrNull() #define QRHI_PROF_F(f) for (bool qrhip_enabled = rhiP != nullptr; qrhip_enabled; qrhip_enabled = false) rhiP->f +Q_DECLARE_LOGGING_CATEGORY(QRHI_LOG_INFO) + class QRhiImplementation { public: @@ -553,6 +556,9 @@ public: }; const QVector *textures() const { return &m_textures; } + static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages); + static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages); + private: QVector m_buffers; QVector m_textures; diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index a8a490eb5cd..0c5df600a0c 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -189,10 +189,10 @@ bool QRhiD3D11::create(QRhi::Flags flags) DXGI_ADAPTER_DESC1 desc; adapter->GetDesc1(&desc); const QString name = QString::fromUtf16((char16_t *) desc.Description); - qDebug("Adapter %d: '%s' (flags 0x%x)", adapterIndex, qPrintable(name), desc.Flags); + qCDebug(QRHI_LOG_INFO, "Adapter %d: '%s' (flags 0x%x)", adapterIndex, qPrintable(name), desc.Flags); if (!adapterToUse && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) { adapterToUse = adapter; - qDebug(" using this adapter"); + qCDebug(QRHI_LOG_INFO, " using this adapter"); } else { adapter->Release(); } diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 22cb030c275..379801efbda 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -47,12 +47,13 @@ QT_BEGIN_NAMESPACE OpenGL backend. Binding vertex attribute locations and decomposing uniform buffers into uniforms are handled transparently to the application via the reflection data (QShaderDescription). Real uniform buffers are never used, - regardless of the GLSL version. Textures and buffers feature no special logic, - it's all just glTexSubImage2D and glBufferSubData (with "dynamic" buffers set - to GL_DYNAMIC_DRAW). The swapchain and the associated renderbuffer for - depth-stencil will be dummies since we have no control over the underlying - buffers here. While we try to keep this backend clean GLES 2.0, some GL(ES) - 3.0 features like multisample renderbuffers and blits are used when available. + regardless of the GLSL version. Textures and buffers feature no special + logic, it's all just glTexSubImage2D and glBufferSubData (with "dynamic" + buffers set to GL_DYNAMIC_DRAW). The swapchain and the associated + renderbuffer for depth-stencil will be dummies since we have no control over + the underlying buffers here. While the baseline here is plain GLES 2.0, some + modern GL(ES) features like multisample renderbuffers, blits, and compute are + used when available. Also functional with core profile contexts. */ /*! @@ -239,6 +240,34 @@ QT_BEGIN_NAMESPACE #define GL_MAX_SAMPLES 0x8D57 #endif +#ifndef GL_SHADER_STORAGE_BUFFER +#define GL_SHADER_STORAGE_BUFFER 0x90D2 +#endif + +#ifndef GL_READ_ONLY +#define GL_READ_ONLY 0x88B8 +#endif + +#ifndef GL_WRITE_ONLY +#define GL_WRITE_ONLY 0x88B9 +#endif + +#ifndef GL_READ_WRITE +#define GL_READ_WRITE 0x88BA +#endif + +#ifndef GL_COMPUTE_SHADER +#define GL_COMPUTE_SHADER 0x91B9 +#endif + +#ifndef GL_ALL_BARRIER_BITS +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF +#endif + +#ifndef GL_VERTEX_PROGRAM_POINT_SIZE +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#endif + /*! Constructs a new QRhiGles2InitParams. @@ -356,7 +385,7 @@ bool QRhiGles2::create(QRhi::Flags flags) ctx = nullptr; return false; } - qDebug() << "Created OpenGL context" << ctx->format(); + qCDebug(QRHI_LOG_INFO) << "Created OpenGL context" << ctx->format(); } if (!ensureContext(maybeWindow ? maybeWindow : fallbackSurface)) // see 'window' discussion in QRhiGles2InitParams comments @@ -368,7 +397,7 @@ bool QRhiGles2::create(QRhi::Flags flags) const char *renderer = reinterpret_cast(f->glGetString(GL_RENDERER)); const char *version = reinterpret_cast(f->glGetString(GL_VERSION)); if (vendor && renderer && version) - qDebug("OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version); + qCDebug(QRHI_LOG_INFO, "OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version); const QSurfaceFormat actualFormat = ctx->format(); @@ -400,9 +429,9 @@ bool QRhiGles2::create(QRhi::Flags flags) caps.gles = actualFormat.renderableType() == QSurfaceFormat::OpenGLES; if (caps.gles) - caps.fixedIndexPrimitiveRestart = caps.ctxMajor >= 3; + caps.fixedIndexPrimitiveRestart = caps.ctxMajor >= 3; // ES 3.0 else - caps.fixedIndexPrimitiveRestart = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3); + caps.fixedIndexPrimitiveRestart = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3); // 4.3 if (caps.fixedIndexPrimitiveRestart) f->glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); @@ -411,8 +440,8 @@ bool QRhiGles2::create(QRhi::Flags flags) caps.bgraInternalFormat = caps.bgraExternalFormat && caps.gles; caps.r8Format = f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats); caps.r16Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats); - caps.floatFormats = caps.ctxMajor >= 3; - caps.depthTexture = caps.ctxMajor >= 3; + caps.floatFormats = caps.ctxMajor >= 3; // 3.0 or ES 3.0 + caps.depthTexture = caps.ctxMajor >= 3; // 3.0 or ES 3.0 caps.packedDepthStencil = f->hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil); #ifdef Q_OS_WASM caps.needsDepthStencilCombinedAttach = true; @@ -421,12 +450,31 @@ bool QRhiGles2::create(QRhi::Flags flags) #endif caps.srgbCapableDefaultFramebuffer = f->hasOpenGLExtension(QOpenGLExtensions::SRGBFrameBuffer); caps.coreProfile = actualFormat.profile() == QSurfaceFormat::CoreProfile; - caps.uniformBuffers = caps.ctxMajor >= 3 && (caps.gles || caps.ctxMinor >= 1); + + if (caps.gles) + caps.uniformBuffers = caps.ctxMajor >= 3; // ES 3.0 + else + caps.uniformBuffers = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1); // 3.1 + caps.elementIndexUint = f->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint); caps.depth24 = f->hasOpenGLExtension(QOpenGLExtensions::Depth24); caps.rgba8Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats); - caps.instancing = caps.ctxMajor >= 3 && (caps.gles || caps.ctxMinor >= 3); - caps.baseVertex = caps.ctxMajor >= 3 && caps.ctxMinor >= 2; + + if (caps.gles) + caps.instancing = caps.ctxMajor >= 3; // ES 3.0 + else + caps.instancing = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3); // 3.3 + + caps.baseVertex = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2); // 3.2 or ES 3.2 + + if (caps.gles) + caps.compute = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1); // ES 3.1 + else + caps.compute = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3); // 4.3 + + if (!caps.gles) + f->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + // else (with gles) this is always on nativeHandlesStruct.context = ctx; @@ -683,7 +731,7 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const case QRhi::ElementIndexUint: return caps.elementIndexUint; case QRhi::Compute: - return false; + return caps.compute; case QRhi::WideLines: return true; case QRhi::VertexShaderPointSize: @@ -778,10 +826,11 @@ void QRhiGles2::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::RenderPass); QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, ps); - const bool pipelineChanged = cbD->currentPipeline != ps || cbD->currentPipelineGeneration != psD->generation; + const bool pipelineChanged = cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation; if (pipelineChanged) { - cbD->currentPipeline = ps; + cbD->currentGraphicsPipeline = ps; + cbD->currentComputePipeline = nullptr; cbD->currentPipelineGeneration = psD->generation; QGles2CommandBuffer::Command cmd; @@ -796,35 +845,92 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) { QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); - Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::RenderPass); - Q_ASSERT(cbD->currentPipeline); + Q_ASSERT(cbD->recordingPass != QGles2CommandBuffer::NoPass); + QGles2GraphicsPipeline *gfxPsD = QRHI_RES(QGles2GraphicsPipeline, cbD->currentGraphicsPipeline); + QGles2ComputePipeline *compPsD = QRHI_RES(QGles2ComputePipeline, cbD->currentComputePipeline); - if (!srb) - srb = QRHI_RES(QGles2GraphicsPipeline, cbD->currentPipeline)->m_shaderResourceBindings; + if (!srb) { + if (gfxPsD) + srb = gfxPsD->m_shaderResourceBindings; + else + srb = compPsD->m_shaderResourceBindings; + } + QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]); QGles2ShaderResourceBindings *srbD = QRHI_RES(QGles2ShaderResourceBindings, srb); bool hasDynamicOffsetInSrb = false; for (int i = 0, ie = srbD->m_bindings.count(); i != ie; ++i) { const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->m_bindings[i]); switch (b->type) { case QRhiShaderResourceBinding::UniformBuffer: + // no BufUniformRead / AccessUniform because no real uniform buffers are used if (b->u.ubuf.hasDynamicOffset) hasDynamicOffsetInSrb = true; break; + case QRhiShaderResourceBinding::SampledTexture: + trackedRegisterTexture(&passResTracker, + QRHI_RES(QGles2Texture, b->u.stex.tex), + QRhiPassResourceTracker::TexSample, + QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage)); + break; + case QRhiShaderResourceBinding::ImageLoad: + Q_FALLTHROUGH(); + case QRhiShaderResourceBinding::ImageStore: + Q_FALLTHROUGH(); + case QRhiShaderResourceBinding::ImageLoadStore: + { + QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.simage.tex); + QRhiPassResourceTracker::TextureAccess access; + if (b->type == QRhiShaderResourceBinding::ImageLoad) + access = QRhiPassResourceTracker::TexStorageLoad; + else if (b->type == QRhiShaderResourceBinding::ImageStore) + access = QRhiPassResourceTracker::TexStorageStore; + else + access = QRhiPassResourceTracker::TexStorageLoadStore; + trackedRegisterTexture(&passResTracker, texD, access, + QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage)); + } + break; + case QRhiShaderResourceBinding::BufferLoad: + Q_FALLTHROUGH(); + case QRhiShaderResourceBinding::BufferStore: + Q_FALLTHROUGH(); + case QRhiShaderResourceBinding::BufferLoadStore: + { + QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.sbuf.buf); + QRhiPassResourceTracker::BufferAccess access; + if (b->type == QRhiShaderResourceBinding::BufferLoad) + access = QRhiPassResourceTracker::BufStorageLoad; + else if (b->type == QRhiShaderResourceBinding::BufferStore) + access = QRhiPassResourceTracker::BufStorageStore; + else + access = QRhiPassResourceTracker::BufStorageLoadStore; + trackedRegisterBuffer(&passResTracker, bufD, access, + QRhiPassResourceTracker::toPassTrackerBufferStage(b->stage)); + } + break; default: break; } } - const bool srbChanged = cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation; + const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb); + const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation; - if (srbChanged || hasDynamicOffsetInSrb) { - cbD->currentSrb = srb; + if (srbChanged || srbRebuilt || hasDynamicOffsetInSrb) { + if (gfxPsD) { + cbD->currentGraphicsSrb = srb; + cbD->currentComputeSrb = nullptr; + } else { + cbD->currentGraphicsSrb = nullptr; + cbD->currentComputeSrb = srb; + } cbD->currentSrbGeneration = srbD->generation; QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::BindShaderResources; - cmd.args.bindShaderResources.ps = cbD->currentPipeline; + cmd.args.bindShaderResources.maybeGraphicsPs = gfxPsD; + cmd.args.bindShaderResources.maybeComputePs = compPsD; cmd.args.bindShaderResources.srb = srb; cmd.args.bindShaderResources.dynamicOffsetCount = 0; if (hasDynamicOffsetInSrb) { @@ -851,30 +957,39 @@ void QRhiGles2::setVertexInput(QRhiCommandBuffer *cb, { QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::RenderPass); + QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]); for (int i = 0; i < bindingCount; ++i) { QRhiBuffer *buf = bindings[i].first; quint32 ofs = bindings[i].second; QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, buf); Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer)); + QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::BindVertexBuffer; - cmd.args.bindVertexBuffer.ps = cbD->currentPipeline; + cmd.args.bindVertexBuffer.ps = cbD->currentGraphicsPipeline; cmd.args.bindVertexBuffer.buffer = bufD->buffer; cmd.args.bindVertexBuffer.offset = ofs; cmd.args.bindVertexBuffer.binding = startBinding + i; cbD->commands.append(cmd); + + trackedRegisterBuffer(&passResTracker, bufD, QRhiPassResourceTracker::BufVertexInput, + QRhiPassResourceTracker::BufVertexInputStage); } if (indexBuf) { QGles2Buffer *ibufD = QRHI_RES(QGles2Buffer, indexBuf); Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer)); + QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::BindIndexBuffer; cmd.args.bindIndexBuffer.buffer = ibufD->buffer; cmd.args.bindIndexBuffer.offset = indexOffset; cmd.args.bindIndexBuffer.type = indexFormat == QRhiCommandBuffer::IndexUInt16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; cbD->commands.append(cmd); + + trackedRegisterBuffer(&passResTracker, ibufD, QRhiPassResourceTracker::BufIndexRead, + QRhiPassResourceTracker::BufVertexInputStage); } } @@ -932,7 +1047,7 @@ void QRhiGles2::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::StencilRef; cmd.args.stencilRef.ref = refValue; - cmd.args.stencilRef.ps = cbD->currentPipeline; + cmd.args.stencilRef.ps = cbD->currentGraphicsPipeline; cbD->commands.append(cmd); } @@ -944,7 +1059,7 @@ void QRhiGles2::draw(QRhiCommandBuffer *cb, quint32 vertexCount, QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::Draw; - cmd.args.draw.ps = cbD->currentPipeline; + cmd.args.draw.ps = cbD->currentGraphicsPipeline; cmd.args.draw.vertexCount = vertexCount; cmd.args.draw.firstVertex = firstVertex; cmd.args.draw.instanceCount = instanceCount; @@ -960,7 +1075,7 @@ void QRhiGles2::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::DrawIndexed; - cmd.args.drawIndexed.ps = cbD->currentPipeline; + cmd.args.drawIndexed.ps = cbD->currentGraphicsPipeline; cmd.args.drawIndexed.indexCount = indexCount; cmd.args.drawIndexed.firstIndex = firstIndex; cmd.args.drawIndexed.instanceCount = instanceCount; @@ -1126,9 +1241,48 @@ QRhi::FrameOpResult QRhiGles2::flushCommandBuffer() return QRhi::FrameOpSuccess; } +void QRhiGles2::trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access) +{ + Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::NoPass); // this is for resource updates only + const QGles2Buffer::Access prevAccess = bufD->usageState.access; + if (access == prevAccess) + return; + + if (prevAccess == QGles2Buffer::AccessStorageWrite || prevAccess == QGles2Buffer::AccessStorageReadWrite) { + // Generating the minimal barrier set is way too complicated to do + // correctly (prevAccess is overwritten so we won't have proper + // tracking across multiple passes) so setting all barrier bits will do + // for now. + QGles2CommandBuffer::Command cmd; + cmd.cmd = QGles2CommandBuffer::Command::Barrier; + cmd.args.barrier.barriers = GL_ALL_BARRIER_BITS; + cbD->commands.append(cmd); + } + + bufD->usageState.access = access; +} + +void QRhiGles2::trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access) +{ + Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::NoPass); // this is for resource updates only + const QGles2Texture::Access prevAccess = texD->usageState.access; + if (access == prevAccess) + return; + + if (prevAccess == QGles2Texture::AccessStorageWrite || prevAccess == QGles2Texture::AccessStorageReadWrite) { + QGles2CommandBuffer::Command cmd; + cmd.cmd = QGles2CommandBuffer::Command::Barrier; + cmd.args.barrier.barriers = GL_ALL_BARRIER_BITS; + cbD->commands.append(cmd); + } + + texD->usageState.access = access; +} + void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc) { + trackedImageBarrier(cbD, texD, QGles2Texture::AccessUpdate); const bool isCompressed = isCompressedFormat(texD->m_format); const bool isCubeMap = texD->m_flags.testFlag(QRhiTexture::CubeMap); const GLenum faceTargetBase = isCubeMap ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target; @@ -1229,9 +1383,10 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) { memcpy(bufD->ubuf.data() + u.offset, u.data.constData(), u.data.size()); } else { + trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate); QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::BufferSubData; - cmd.args.bufferSubData.target = bufD->target; + cmd.args.bufferSubData.target = bufD->targetForDataOps; cmd.args.bufferSubData.buffer = bufD->buffer; cmd.args.bufferSubData.offset = u.offset; cmd.args.bufferSubData.size = u.data.size(); @@ -1247,9 +1402,10 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) { memcpy(bufD->ubuf.data() + u.offset, u.data.constData(), u.data.size()); } else { + trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate); QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::BufferSubData; - cmd.args.bufferSubData.target = bufD->target; + cmd.args.bufferSubData.target = bufD->targetForDataOps; cmd.args.bufferSubData.buffer = bufD->buffer; cmd.args.bufferSubData.offset = u.offset; cmd.args.bufferSubData.size = u.data.size(); @@ -1273,6 +1429,9 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate QGles2Texture *srcD = QRHI_RES(QGles2Texture, u.copy.src); QGles2Texture *dstD = QRHI_RES(QGles2Texture, u.copy.dst); + trackedImageBarrier(cbD, srcD, QGles2Texture::AccessRead); + trackedImageBarrier(cbD, dstD, QGles2Texture::AccessUpdate); + const QSize size = u.copy.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.copy.desc.pixelSize(); // do not translate coordinates, even if sp is bottom-left from gl's pov const QPoint sp = u.copy.desc.sourceTopLeft(); @@ -1308,6 +1467,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate cmd.cmd = QGles2CommandBuffer::Command::ReadPixels; cmd.args.readPixels.result = u.read.result; QGles2Texture *texD = QRHI_RES(QGles2Texture, u.read.rb.texture()); + trackedImageBarrier(cbD, texD, QGles2Texture::AccessRead); cmd.args.readPixels.texture = texD ? texD->texture : 0; if (texD) { cmd.args.readPixels.w = texD->m_pixelSize.width(); @@ -1320,9 +1480,10 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate } cbD->commands.append(cmd); } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::MipGen) { + QGles2Texture *texD = QRHI_RES(QGles2Texture, u.mipgen.tex); + trackedImageBarrier(cbD, texD, QGles2Texture::AccessFramebuffer); QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::GenMip; - QGles2Texture *texD = QRHI_RES(QGles2Texture, u.mipgen.tex); cmd.args.genMip.target = texD->target; cmd.args.genMip.texture = texD->texture; cbD->commands.append(cmd); @@ -1571,6 +1732,88 @@ static inline GLenum toGlTextureCompareFunc(QRhiSampler::CompareOp op) } } +static inline QGles2Buffer::Access toGlAccess(QRhiPassResourceTracker::BufferAccess access) +{ + switch (access) { + case QRhiPassResourceTracker::BufVertexInput: + return QGles2Buffer::AccessVertex; + case QRhiPassResourceTracker::BufIndexRead: + return QGles2Buffer::AccessIndex; + case QRhiPassResourceTracker::BufUniformRead: + return QGles2Buffer::AccessUniform; + case QRhiPassResourceTracker::BufStorageLoad: + return QGles2Buffer::AccessStorageRead; + case QRhiPassResourceTracker::BufStorageStore: + return QGles2Buffer::AccessStorageWrite; + case QRhiPassResourceTracker::BufStorageLoadStore: + return QGles2Buffer::AccessStorageReadWrite; + default: + Q_UNREACHABLE(); + break; + } + return QGles2Buffer::AccessNone; +} + +static inline QRhiPassResourceTracker::UsageState toPassTrackerUsageState(const QGles2Buffer::UsageState &bufUsage) +{ + QRhiPassResourceTracker::UsageState u; + u.layout = 0; // N/A + u.access = bufUsage.access; + u.stage = 0; // N/A + return u; +} + +static inline QGles2Texture::Access toGlAccess(QRhiPassResourceTracker::TextureAccess access) +{ + switch (access) { + case QRhiPassResourceTracker::TexSample: + return QGles2Texture::AccessSample; + case QRhiPassResourceTracker::TexColorOutput: + return QGles2Texture::AccessFramebuffer; + case QRhiPassResourceTracker::TexDepthOutput: + return QGles2Texture::AccessFramebuffer; + case QRhiPassResourceTracker::TexStorageLoad: + return QGles2Texture::AccessStorageRead; + case QRhiPassResourceTracker::TexStorageStore: + return QGles2Texture::AccessStorageWrite; + case QRhiPassResourceTracker::TexStorageLoadStore: + return QGles2Texture::AccessStorageReadWrite; + default: + Q_UNREACHABLE(); + break; + } + return QGles2Texture::AccessNone; +} + +static inline QRhiPassResourceTracker::UsageState toPassTrackerUsageState(const QGles2Texture::UsageState &texUsage) +{ + QRhiPassResourceTracker::UsageState u; + u.layout = 0; // N/A + u.access = texUsage.access; + u.stage = 0; // N/A + return u; +} + +void QRhiGles2::trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker, + QGles2Buffer *bufD, + QRhiPassResourceTracker::BufferAccess access, + QRhiPassResourceTracker::BufferStage stage) +{ + QGles2Buffer::UsageState &u(bufD->usageState); + passResTracker->registerBuffer(bufD, 0, &access, &stage, toPassTrackerUsageState(u)); + u.access = toGlAccess(access); +} + +void QRhiGles2::trackedRegisterTexture(QRhiPassResourceTracker *passResTracker, + QGles2Texture *texD, + QRhiPassResourceTracker::TextureAccess access, + QRhiPassResourceTracker::TextureStage stage) +{ + QGles2Texture::UsageState &u(texD->usageState); + passResTracker->registerTexture(texD, &access, &stage, toPassTrackerUsageState(u)); + u.access = toGlAccess(access); +} + void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) { QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); @@ -1747,7 +1990,8 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) executeBindGraphicsPipeline(cmd.args.bindGraphicsPipeline.ps); break; case QGles2CommandBuffer::Command::BindShaderResources: - bindShaderResources(cmd.args.bindShaderResources.ps, + bindShaderResources(cmd.args.bindShaderResources.maybeGraphicsPs, + cmd.args.bindShaderResources.maybeComputePs, cmd.args.bindShaderResources.srb, cmd.args.bindShaderResources.dynamicOffsetPairs, cmd.args.bindShaderResources.dynamicOffsetCount); @@ -1890,6 +2134,51 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) f->glBindTexture(cmd.args.genMip.target, cmd.args.genMip.texture); f->glGenerateMipmap(cmd.args.genMip.target); break; + case QGles2CommandBuffer::Command::BindComputePipeline: + { + QGles2ComputePipeline *psD = QRHI_RES(QGles2ComputePipeline, cmd.args.bindComputePipeline.ps); + f->glUseProgram(psD->program); + } + break; + case QGles2CommandBuffer::Command::Dispatch: + f->glDispatchCompute(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z); + break; + case QGles2CommandBuffer::Command::BarriersForPass: + { + GLbitfield barriers = 0; + QRhiPassResourceTracker &tracker(cbD->passResTrackers[cmd.args.barriersForPass.trackerIndex]); + const QVector *buffers = tracker.buffers(); + // we only care about after-write, not any other accesses, and + // cannot tell if something was written in a shader several passes + // ago: now the previously written resource may be used with an + // access that was not in the previous passes, result in a missing + // barrier in theory. Hence setting all barrier bits whenever + // something previously written is used for the first time in a + // subsequent pass. + for (const QRhiPassResourceTracker::Buffer &b : *buffers) { + QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(b.stateAtPassBegin.access); + if (accessBeforePass == QGles2Buffer::AccessStorageWrite + || accessBeforePass == QGles2Buffer::AccessStorageReadWrite) + { + barriers |= GL_ALL_BARRIER_BITS; + } + } + const QVector *textures = tracker.textures(); + for (const QRhiPassResourceTracker::Texture &t : *textures) { + QGles2Texture::Access accessBeforePass = QGles2Texture::Access(t.stateAtPassBegin.access); + if (accessBeforePass == QGles2Texture::AccessStorageWrite + || accessBeforePass == QGles2Texture::AccessStorageReadWrite) + { + barriers |= GL_ALL_BARRIER_BITS; + } + } + if (barriers) + f->glMemoryBarrier(barriers); + } + break; + case QGles2CommandBuffer::Command::Barrier: + f->glMemoryBarrier(cmd.args.barrier.barriers); + break; default: break; } @@ -1969,10 +2258,10 @@ void QRhiGles2::executeBindGraphicsPipeline(QRhiGraphicsPipeline *ps) f->glUseProgram(psD->program); } -void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *ps, QRhiShaderResourceBindings *srb, +void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs, + QRhiShaderResourceBindings *srb, const uint *dynOfsPairs, int dynOfsCount) { - QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, ps); QGles2ShaderResourceBindings *srbD = QRHI_RES(QGles2ShaderResourceBindings, srb); int texUnit = 0; @@ -1994,7 +2283,9 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *ps, QRhiShaderResource QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.ubuf.buf); const QByteArray bufView = QByteArray::fromRawData(bufD->ubuf.constData() + viewOffset, b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size); - for (QGles2GraphicsPipeline::Uniform &uniform : psD->uniforms) { + QVector &uniforms(maybeGraphicsPs ? QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->uniforms + : QRHI_RES(QGles2ComputePipeline, maybeComputePs)->uniforms); + for (QGles2UniformDescription &uniform : uniforms) { if (uniform.binding == b->binding) { // in a uniform buffer everything is at least 4 byte aligned // so this should not cause unaligned reads @@ -2034,6 +2325,30 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *ps, QRhiShaderResource case QShaderDescription::Int4: f->glUniform4iv(uniform.glslLocation, 1, reinterpret_cast(src)); break; + case QShaderDescription::Uint: + f->glUniform1ui(uniform.glslLocation, *reinterpret_cast(src)); + break; + case QShaderDescription::Uint2: + f->glUniform2uiv(uniform.glslLocation, 1, reinterpret_cast(src)); + break; + case QShaderDescription::Uint3: + f->glUniform3uiv(uniform.glslLocation, 1, reinterpret_cast(src)); + break; + case QShaderDescription::Uint4: + f->glUniform4uiv(uniform.glslLocation, 1, reinterpret_cast(src)); + break; + case QShaderDescription::Bool: // a glsl bool is 4 bytes, like (u)int + f->glUniform1i(uniform.glslLocation, *reinterpret_cast(src)); + break; + case QShaderDescription::Bool2: + f->glUniform2iv(uniform.glslLocation, 1, reinterpret_cast(src)); + break; + case QShaderDescription::Bool3: + f->glUniform3iv(uniform.glslLocation, 1, reinterpret_cast(src)); + break; + case QShaderDescription::Bool4: + f->glUniform4iv(uniform.glslLocation, 1, reinterpret_cast(src)); + break; // ### more types default: break; @@ -2046,8 +2361,10 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *ps, QRhiShaderResource { QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.stex.tex); QGles2Sampler *samplerD = QRHI_RES(QGles2Sampler, b->u.stex.sampler); + QVector &samplers(maybeGraphicsPs ? QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->samplers + : QRHI_RES(QGles2ComputePipeline, maybeComputePs)->samplers); - for (QGles2GraphicsPipeline::Sampler &sampler : psD->samplers) { + for (QGles2SamplerDescription &sampler : samplers) { if (sampler.binding == b->binding) { f->glActiveTexture(GL_TEXTURE0 + texUnit); f->glBindTexture(texD->target, texD->texture); @@ -2074,6 +2391,38 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *ps, QRhiShaderResource } } break; + case QRhiShaderResourceBinding::ImageLoad: + Q_FALLTHROUGH(); + case QRhiShaderResourceBinding::ImageStore: + Q_FALLTHROUGH(); + case QRhiShaderResourceBinding::ImageLoadStore: + { + QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.simage.tex); + const bool layered = texD->m_flags.testFlag(QRhiTexture::CubeMap); + GLenum access = GL_READ_WRITE; + if (b->type == QRhiShaderResourceBinding::ImageLoad) + access = GL_READ_ONLY; + else if (b->type == QRhiShaderResourceBinding::ImageStore) + access = GL_WRITE_ONLY; + f->glBindImageTexture(b->binding, texD->texture, + b->u.simage.level, layered, 0, + access, texD->glsizedintformat); + } + break; + case QRhiShaderResourceBinding::BufferLoad: + Q_FALLTHROUGH(); + case QRhiShaderResourceBinding::BufferStore: + Q_FALLTHROUGH(); + case QRhiShaderResourceBinding::BufferLoadStore: + { + QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.sbuf.buf); + if (b->u.sbuf.offset == 0 && b->u.sbuf.maybeSize == 0) + f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, b->binding, bufD->buffer); + else + f->glBindBufferRange(GL_SHADER_STORAGE_BUFFER, b->binding, bufD->buffer, + b->u.sbuf.offset, b->u.sbuf.maybeSize ? b->u.sbuf.maybeSize : bufD->m_size); + } + break; default: Q_UNREACHABLE(); break; @@ -2095,8 +2444,11 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt, bool *wantsColorClear, bool *wantsDsClear) { QGles2RenderTargetData *rtD = nullptr; + QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]); + QGles2CommandBuffer::Command fbCmd; fbCmd.cmd = QGles2CommandBuffer::Command::BindFramebuffer; + switch (rt->resourceType()) { case QRhiResource::RenderTarget: rtD = &QRHI_RES(QGles2ReferenceRenderTarget, rt)->d; @@ -2117,14 +2469,39 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt, *wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents); fbCmd.args.bindFramebuffer.fbo = rtTex->framebuffer; fbCmd.args.bindFramebuffer.colorAttCount = rtD->colorAttCount; + + const QVector colorAttachments = rtTex->m_desc.colorAttachments(); + for (const QRhiColorAttachment &colorAttachment : colorAttachments) { + QGles2Texture *texD = QRHI_RES(QGles2Texture, colorAttachment.texture()); + QGles2Texture *resolveTexD = QRHI_RES(QGles2Texture, colorAttachment.resolveTexture()); + if (texD) { + trackedRegisterTexture(&passResTracker, texD, + QRhiPassResourceTracker::TexColorOutput, + QRhiPassResourceTracker::TexColorOutputStage); + } + if (resolveTexD) { + trackedRegisterTexture(&passResTracker, resolveTexD, + QRhiPassResourceTracker::TexColorOutput, + QRhiPassResourceTracker::TexColorOutputStage); + } + // renderbuffers cannot be written in shaders (no image store) so + // they do not matter here + } + if (rtTex->m_desc.depthTexture()) { + trackedRegisterTexture(&passResTracker, QRHI_RES(QGles2Texture, rtTex->m_desc.depthTexture()), + QRhiPassResourceTracker::TexDepthOutput, + QRhiPassResourceTracker::TexDepthOutputStage); + } } break; default: Q_UNREACHABLE(); break; } + fbCmd.args.bindFramebuffer.srgb = rtD->srgbUpdateAndBlend; cbD->commands.append(fbCmd); + return rtD; } @@ -2140,6 +2517,15 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb, if (resourceUpdates) enqueueResourceUpdates(cb, resourceUpdates); + // Get a new resource tracker. Then add a command that will generate + // glMemoryBarrier() calls based on that tracker when submitted. + cbD->passResTrackers.append(QRhiPassResourceTracker()); + cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1; + QGles2CommandBuffer::Command cmd; + cmd.cmd = QGles2CommandBuffer::Command::BarriersForPass; + cmd.args.barriersForPass.trackerIndex = cbD->currentPassResTrackerIndex; + cbD->commands.append(cmd); + bool wantsColorClear, wantsDsClear; QGles2RenderTargetData *rtD = enqueueBindFramebuffer(rt, cbD, &wantsColorClear, &wantsDsClear); @@ -2160,6 +2546,8 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb, cbD->recordingPass = QGles2CommandBuffer::RenderPass; cbD->currentTarget = rt; + + cbD->resetCachedState(); } void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) @@ -2212,7 +2600,16 @@ void QRhiGles2::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch if (resourceUpdates) enqueueResourceUpdates(cb, resourceUpdates); + cbD->passResTrackers.append(QRhiPassResourceTracker()); + cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1; + QGles2CommandBuffer::Command cmd; + cmd.cmd = QGles2CommandBuffer::Command::BarriersForPass; + cmd.args.barriersForPass.trackerIndex = cbD->currentPassResTrackerIndex; + cbD->commands.append(cmd); + cbD->recordingPass = QGles2CommandBuffer::ComputePass; + + cbD->resetCachedState(); } void QRhiGles2::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) @@ -2228,16 +2625,189 @@ void QRhiGles2::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *r void QRhiGles2::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) { - Q_UNUSED(cb); - Q_UNUSED(ps); + QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); + Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::ComputePass); + QGles2ComputePipeline *psD = QRHI_RES(QGles2ComputePipeline, ps); + const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation; + + if (pipelineChanged) { + cbD->currentGraphicsPipeline = nullptr; + cbD->currentComputePipeline = ps; + cbD->currentPipelineGeneration = psD->generation; + + QGles2CommandBuffer::Command cmd; + cmd.cmd = QGles2CommandBuffer::Command::BindComputePipeline; + cmd.args.bindComputePipeline.ps = ps; + cbD->commands.append(cmd); + } } void QRhiGles2::dispatch(QRhiCommandBuffer *cb, int x, int y, int z) { - Q_UNUSED(cb); - Q_UNUSED(x); - Q_UNUSED(y); - Q_UNUSED(z); + QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); + Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::ComputePass); + + QGles2CommandBuffer::Command cmd; + cmd.cmd = QGles2CommandBuffer::Command::Dispatch; + cmd.args.dispatch.x = x; + cmd.args.dispatch.y = y; + cmd.args.dispatch.z = z; + cbD->commands.append(cmd); +} + +static inline GLenum toGlShaderType(QRhiShaderStage::Type type) +{ + switch (type) { + case QRhiShaderStage::Vertex: + return GL_VERTEX_SHADER; + case QRhiShaderStage::Fragment: + return GL_FRAGMENT_SHADER; + case QRhiShaderStage::Compute: + return GL_COMPUTE_SHADER; + default: + Q_UNREACHABLE(); + return GL_VERTEX_SHADER; + } +} + +bool QRhiGles2::compileShader(GLuint program, const QRhiShaderStage &shaderStage, + QShaderDescription *desc, int *glslVersionUsed) +{ + GLuint shader = f->glCreateShader(toGlShaderType(shaderStage.type())); + const QShader bakedShader = shaderStage.shader(); + QVector versionsToTry; + QByteArray source; + if (caps.gles) { + if (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2)) { + versionsToTry << 320 << 310 << 300 << 100; + } else if (caps.ctxMajor == 3 && caps.ctxMinor == 1) { + versionsToTry << 310 << 300 << 100; + } else if (caps.ctxMajor == 3 && caps.ctxMinor == 0) { + versionsToTry << 300 << 100; + } else { + versionsToTry << 100; + } + for (int v : versionsToTry) { + QShaderVersion ver(v, QShaderVersion::GlslEs); + source = bakedShader.shader({ QShader::GlslShader, ver, shaderStage.shaderVariant() }).shader(); + if (!source.isEmpty()) { + if (glslVersionUsed) + *glslVersionUsed = v; + break; + } + } + } else { + if (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 6)) { + versionsToTry << 460 << 450 << 440 << 430 << 420 << 410 << 400 << 330 << 150; + } else if (caps.ctxMajor == 4 && caps.ctxMinor == 5) { + versionsToTry << 450 << 440 << 430 << 420 << 410 << 400 << 330 << 150; + } else if (caps.ctxMajor == 4 && caps.ctxMinor == 4) { + versionsToTry << 440 << 430 << 420 << 410 << 400 << 330 << 150; + } else if (caps.ctxMajor == 4 && caps.ctxMinor == 3) { + versionsToTry << 430 << 420 << 410 << 400 << 330 << 150; + } else if (caps.ctxMajor == 4 && caps.ctxMinor == 2) { + versionsToTry << 420 << 410 << 400 << 330 << 150; + } else if (caps.ctxMajor == 4 && caps.ctxMinor == 1) { + versionsToTry << 410 << 400 << 330 << 150; + } else if (caps.ctxMajor == 4 && caps.ctxMinor == 0) { + versionsToTry << 400 << 330 << 150; + } else if (caps.ctxMajor == 3 && caps.ctxMinor == 3) { + versionsToTry << 330 << 150; + } else if (caps.ctxMajor == 3 && caps.ctxMinor == 2) { + versionsToTry << 150; + } + if (!caps.coreProfile) + versionsToTry << 120; + for (int v : versionsToTry) { + source = bakedShader.shader({ QShader::GlslShader, v, shaderStage.shaderVariant() }).shader(); + if (!source.isEmpty()) { + if (glslVersionUsed) + *glslVersionUsed = v; + break; + } + } + } + if (source.isEmpty()) { + qWarning() << "No GLSL shader code found (versions tried: " << versionsToTry + << ") in baked shader" << bakedShader; + return false; + } + + const char *srcStr = source.constData(); + const GLint srcLength = source.count(); + f->glShaderSource(shader, 1, &srcStr, &srcLength); + f->glCompileShader(shader); + GLint compiled = 0; + f->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) { + GLint infoLogLength = 0; + f->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); + QByteArray log; + if (infoLogLength > 1) { + GLsizei length = 0; + log.resize(infoLogLength); + f->glGetShaderInfoLog(shader, infoLogLength, &length, log.data()); + } + qWarning("Failed to compile shader: %s\nSource was:\n%s", log.constData(), source.constData()); + return false; + } + + f->glAttachShader(program, shader); + f->glDeleteShader(shader); + + *desc = bakedShader.description(); + return true; +} + +bool QRhiGles2::linkProgram(GLuint program) +{ + f->glLinkProgram(program); + GLint linked = 0; + f->glGetProgramiv(program, GL_LINK_STATUS, &linked); + if (!linked) { + GLint infoLogLength = 0; + f->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); + QByteArray log; + if (infoLogLength > 1) { + GLsizei length = 0; + log.resize(infoLogLength); + f->glGetProgramInfoLog(program, infoLogLength, &length, log.data()); + } + qWarning("Failed to link shader program: %s", log.constData()); + return false; + } + return true; +} + +void QRhiGles2::gatherUniforms(GLuint program, const QShaderDescription::UniformBlock &ub, + QVector *dst) +{ + const QByteArray prefix = ub.structName.toUtf8() + '.'; + for (const QShaderDescription::BlockVariable &blockMember : ub.members) { + // ### no array support for now + QGles2UniformDescription uniform; + uniform.type = blockMember.type; + const QByteArray name = prefix + blockMember.name.toUtf8(); + uniform.glslLocation = f->glGetUniformLocation(program, name.constData()); + if (uniform.glslLocation >= 0) { + uniform.binding = ub.binding; + uniform.offset = blockMember.offset; + uniform.size = blockMember.size; + dst->append(uniform); + } + } +} + +void QRhiGles2::gatherSamplers(GLuint program, const QShaderDescription::InOutVariable &v, + QVector *dst) +{ + QGles2SamplerDescription sampler; + const QByteArray name = v.name.toUtf8(); + sampler.glslLocation = f->glGetUniformLocation(program, name.constData()); + if (sampler.glslLocation >= 0) { + sampler.binding = v.binding; + dst->append(sampler); + } } QGles2Buffer::QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size) @@ -2277,34 +2847,34 @@ bool QGles2Buffer::build() QRHI_RES_RHI(QRhiGles2); QRHI_PROF; + const int nonZeroSize = m_size <= 0 ? 256 : m_size; + if (m_usage.testFlag(QRhiBuffer::UniformBuffer)) { - if (m_usage.testFlag(QRhiBuffer::VertexBuffer) || m_usage.testFlag(QRhiBuffer::IndexBuffer)) { + if (int(m_usage) != QRhiBuffer::UniformBuffer) { qWarning("Uniform buffer: multiple usages specified, this is not supported by the OpenGL backend"); return false; } - ubuf.resize(m_size); - QRHI_PROF_F(newBuffer(this, m_size, 0, 1)); + ubuf.resize(nonZeroSize); + QRHI_PROF_F(newBuffer(this, nonZeroSize, 0, 1)); return true; } if (!rhiD->ensureContext()) return false; - if (m_usage.testFlag(QRhiBuffer::VertexBuffer)) { - if (m_usage.testFlag(QRhiBuffer::IndexBuffer)) { - qWarning("Vertex buffer: multiple usages specified, this is not supported by the OpenGL backend"); - return false; - } - target = GL_ARRAY_BUFFER; - } + targetForDataOps = GL_ARRAY_BUFFER; if (m_usage.testFlag(QRhiBuffer::IndexBuffer)) - target = GL_ELEMENT_ARRAY_BUFFER; + targetForDataOps = GL_ELEMENT_ARRAY_BUFFER; + else if (m_usage.testFlag(QRhiBuffer::StorageBuffer)) + targetForDataOps = GL_SHADER_STORAGE_BUFFER; rhiD->f->glGenBuffers(1, &buffer); - rhiD->f->glBindBuffer(target, buffer); - rhiD->f->glBufferData(target, m_size, nullptr, m_type == Dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); + rhiD->f->glBindBuffer(targetForDataOps, buffer); + rhiD->f->glBufferData(targetForDataOps, nonZeroSize, nullptr, m_type == Dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); - QRHI_PROF_F(newBuffer(this, m_size, 1, 0)); + usageState.access = AccessNone; + + QRHI_PROF_F(newBuffer(this, nonZeroSize, 1, 0)); rhiD->registerResource(this); return true; } @@ -2473,58 +3043,73 @@ bool QGles2Texture::prepareBuild(QSize *adjustedSize) gltype = GL_UNSIGNED_BYTE; if (isCompressed) { + if (m_flags.testFlag(UsedWithLoadStore)) { + qWarning("Compressed texture cannot be used with image load/store"); + return false; + } glintformat = toGlCompressedTextureFormat(m_format, m_flags); if (!glintformat) { qWarning("Compressed format %d not mappable to GL compressed format", m_format); return false; } + glsizedintformat = glintformat; glformat = GL_RGBA; } else { switch (m_format) { case QRhiTexture::RGBA8: glintformat = GL_RGBA; + glsizedintformat = rhiD->caps.rgba8Format ? GL_RGBA8 : GL_RGBA; glformat = GL_RGBA; break; case QRhiTexture::BGRA8: glintformat = rhiD->caps.bgraInternalFormat ? GL_BGRA : GL_RGBA; + glsizedintformat = rhiD->caps.rgba8Format ? GL_RGBA8 : GL_RGBA; glformat = GL_BGRA; break; case QRhiTexture::R16: glintformat = GL_R16; + glsizedintformat = glintformat; glformat = GL_RED; gltype = GL_UNSIGNED_SHORT; break; case QRhiTexture::R8: glintformat = GL_R8; + glsizedintformat = glintformat; glformat = GL_RED; break; case QRhiTexture::RED_OR_ALPHA8: glintformat = rhiD->caps.coreProfile ? GL_R8 : GL_ALPHA; + glsizedintformat = glintformat; glformat = rhiD->caps.coreProfile ? GL_RED : GL_ALPHA; break; case QRhiTexture::RGBA16F: glintformat = GL_RGBA16F; + glsizedintformat = glintformat; glformat = GL_RGBA; gltype = GL_HALF_FLOAT; break; case QRhiTexture::RGBA32F: glintformat = GL_RGBA32F; + glsizedintformat = glintformat; glformat = GL_RGBA; gltype = GL_FLOAT; break; case QRhiTexture::D16: glintformat = GL_DEPTH_COMPONENT16; + glsizedintformat = glintformat; glformat = GL_DEPTH_COMPONENT; gltype = GL_UNSIGNED_SHORT; break; case QRhiTexture::D32F: glintformat = GL_DEPTH_COMPONENT32F; + glsizedintformat = glintformat; glformat = GL_DEPTH_COMPONENT; gltype = GL_FLOAT; break; default: Q_UNREACHABLE(); glintformat = GL_RGBA; + glsizedintformat = rhiD->caps.rgba8Format ? GL_RGBA8 : GL_RGBA; glformat = GL_RGBA; break; } @@ -2532,6 +3117,8 @@ bool QGles2Texture::prepareBuild(QSize *adjustedSize) samplerState = QGles2SamplerData(); + usageState.access = AccessNone; + if (adjustedSize) *adjustedSize = size; @@ -2552,18 +3139,25 @@ bool QGles2Texture::build() const bool isCompressed = rhiD->isCompressedFormat(m_format); if (!isCompressed) { rhiD->f->glBindTexture(target, texture); - if (hasMipMaps || isCube) { - const GLenum faceTargetBase = isCube ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target; - for (int layer = 0, layerCount = isCube ? 6 : 1; layer != layerCount; ++layer) { - for (int level = 0; level != mipLevelCount; ++level) { - const QSize mipSize = rhiD->q->sizeForMipLevel(level, size); - rhiD->f->glTexImage2D(faceTargetBase + layer, level, glintformat, - mipSize.width(), mipSize.height(), 0, - glformat, gltype, nullptr); + if (!m_flags.testFlag(UsedWithLoadStore)) { + if (hasMipMaps || isCube) { + const GLenum faceTargetBase = isCube ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target; + for (int layer = 0, layerCount = isCube ? 6 : 1; layer != layerCount; ++layer) { + for (int level = 0; level != mipLevelCount; ++level) { + const QSize mipSize = rhiD->q->sizeForMipLevel(level, size); + rhiD->f->glTexImage2D(faceTargetBase + layer, level, glsizedintformat, + mipSize.width(), mipSize.height(), 0, + glformat, gltype, nullptr); + } } + } else { + rhiD->f->glTexImage2D(target, 0, glsizedintformat, size.width(), size.height(), + 0, glformat, gltype, nullptr); } } else { - rhiD->f->glTexImage2D(target, 0, glintformat, size.width(), size.height(), 0, glformat, gltype, nullptr); + // Must be specified with immutable storage functions otherwise + // bindImageTexture may fail. + rhiD->f->glTexStorage2D(target, mipLevelCount, glsizedintformat, size.width(), size.height()); } specified = true; } else { @@ -2900,161 +3494,39 @@ bool QGles2GraphicsPipeline::build() program = rhiD->f->glCreateProgram(); - int sourceVer = 0; + QShaderDescription vsDesc; + QShaderDescription fsDesc; for (const QRhiShaderStage &shaderStage : qAsConst(m_shaderStages)) { const bool isVertex = shaderStage.type() == QRhiShaderStage::Vertex; const bool isFragment = shaderStage.type() == QRhiShaderStage::Fragment; - if (!isVertex && !isFragment) - continue; - - GLuint shader = rhiD->f->glCreateShader(isVertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER); - const QShader bakedShader = shaderStage.shader(); - QVector versionsToTry; - QByteArray source; - if (rhiD->caps.gles) { - if (rhiD->caps.ctxMajor > 3 || (rhiD->caps.ctxMajor == 3 && rhiD->caps.ctxMinor >= 2)) { - versionsToTry << 320 << 310 << 300 << 100; - } else if (rhiD->caps.ctxMajor == 3 && rhiD->caps.ctxMinor == 1) { - versionsToTry << 310 << 300 << 100; - } else if (rhiD->caps.ctxMajor == 3 && rhiD->caps.ctxMinor == 0) { - versionsToTry << 300 << 100; - } else { - versionsToTry << 100; - } - for (int v : versionsToTry) { - QShaderVersion ver(v, QShaderVersion::GlslEs); - source = bakedShader.shader({ QShader::GlslShader, ver, shaderStage.shaderVariant() }).shader(); - if (!source.isEmpty()) { - sourceVer = v; - break; - } - } - } else { - if (rhiD->caps.ctxMajor > 4 || (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor >= 6)) { - versionsToTry << 460 << 450 << 440 << 430 << 420 << 410 << 400 << 330 << 150; - } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 5) { - versionsToTry << 450 << 440 << 430 << 420 << 410 << 400 << 330 << 150; - } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 4) { - versionsToTry << 440 << 430 << 420 << 410 << 400 << 330 << 150; - } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 3) { - versionsToTry << 430 << 420 << 410 << 400 << 330 << 150; - } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 2) { - versionsToTry << 420 << 410 << 400 << 330 << 150; - } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 1) { - versionsToTry << 410 << 400 << 330 << 150; - } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 0) { - versionsToTry << 400 << 330 << 150; - } else if (rhiD->caps.ctxMajor == 3 && rhiD->caps.ctxMinor == 3) { - versionsToTry << 330 << 150; - } else if (rhiD->caps.ctxMajor == 3 && rhiD->caps.ctxMinor == 2) { - versionsToTry << 150; - } - if (!rhiD->caps.coreProfile) - versionsToTry << 120; - for (int v : versionsToTry) { - source = bakedShader.shader({ QShader::GlslShader, v, shaderStage.shaderVariant() }).shader(); - if (!source.isEmpty()) { - sourceVer = v; - break; - } - } + if (isVertex) { + if (!rhiD->compileShader(program, shaderStage, &vsDesc, nullptr)) + return false; + } else if (isFragment) { + if (!rhiD->compileShader(program, shaderStage, &fsDesc, nullptr)) + return false; } - if (source.isEmpty()) { - qWarning() << "No GLSL shader code found (versions tried: " << versionsToTry - << ") in baked shader" << bakedShader; - return false; - } - - const char *srcStr = source.constData(); - const GLint srcLength = source.count(); - rhiD->f->glShaderSource(shader, 1, &srcStr, &srcLength); - rhiD->f->glCompileShader(shader); - GLint compiled = 0; - rhiD->f->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - GLint infoLogLength = 0; - rhiD->f->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); - QByteArray log; - if (infoLogLength > 1) { - GLsizei length = 0; - log.resize(infoLogLength); - rhiD->f->glGetShaderInfoLog(shader, infoLogLength, &length, log.data()); - } - qWarning("Failed to compile shader: %s\nSource was:\n%s", log.constData(), source.constData()); - return false; - } - - rhiD->f->glAttachShader(program, shader); - rhiD->f->glDeleteShader(shader); - - if (isVertex) - vsDesc = bakedShader.description(); - else - fsDesc = bakedShader.description(); } - // not very useful atm since we assume the qsb-generated GLSL shaders never use uniform blocks - canUseUniformBuffers = rhiD->caps.uniformBuffers && sourceVer >= 140; - for (auto inVar : vsDesc.inputVariables()) { const QByteArray name = inVar.name.toUtf8(); rhiD->f->glBindAttribLocation(program, inVar.location, name.constData()); } - rhiD->f->glLinkProgram(program); - GLint linked = 0; - rhiD->f->glGetProgramiv(program, GL_LINK_STATUS, &linked); - if (!linked) { - GLint infoLogLength = 0; - rhiD->f->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); - QByteArray log; - if (infoLogLength > 1) { - GLsizei length = 0; - log.resize(infoLogLength); - rhiD->f->glGetProgramInfoLog(program, infoLogLength, &length, log.data()); - } - qWarning("Failed to link shader program: %s", log.constData()); + if (!rhiD->linkProgram(program)) return false; - } - - auto lookupUniforms = [this, rhiD](const QShaderDescription::UniformBlock &ub) { - const QByteArray prefix = ub.structName.toUtf8() + '.'; - for (const QShaderDescription::BlockVariable &blockMember : ub.members) { - // ### no array support for now - Uniform uniform; - uniform.type = blockMember.type; - const QByteArray name = prefix + blockMember.name.toUtf8(); - uniform.glslLocation = rhiD->f->glGetUniformLocation(program, name.constData()); - if (uniform.glslLocation >= 0) { - uniform.binding = ub.binding; - uniform.offset = blockMember.offset; - uniform.size = blockMember.size; - uniforms.append(uniform); - } - } - }; for (const QShaderDescription::UniformBlock &ub : vsDesc.uniformBlocks()) - lookupUniforms(ub); + rhiD->gatherUniforms(program, ub, &uniforms); for (const QShaderDescription::UniformBlock &ub : fsDesc.uniformBlocks()) - lookupUniforms(ub); - - auto lookupSamplers = [this, rhiD](const QShaderDescription::InOutVariable &v) { - Sampler sampler; - const QByteArray name = v.name.toUtf8(); - sampler.glslLocation = rhiD->f->glGetUniformLocation(program, name.constData()); - if (sampler.glslLocation >= 0) { - sampler.binding = v.binding; - samplers.append(sampler); - } - }; + rhiD->gatherUniforms(program, ub, &uniforms); for (const QShaderDescription::InOutVariable &v : vsDesc.combinedImageSamplers()) - lookupSamplers(v); + rhiD->gatherSamplers(program, v, &samplers); for (const QShaderDescription::InOutVariable &v : fsDesc.combinedImageSamplers()) - lookupSamplers(v); + rhiD->gatherSamplers(program, v, &samplers); generation += 1; rhiD->registerResource(this); @@ -3073,11 +3545,52 @@ QGles2ComputePipeline::~QGles2ComputePipeline() void QGles2ComputePipeline::release() { + if (!program) + return; + + QRhiGles2::DeferredReleaseEntry e; + e.type = QRhiGles2::DeferredReleaseEntry::Pipeline; + + e.pipeline.program = program; + + program = 0; + uniforms.clear(); + samplers.clear(); + + QRHI_RES_RHI(QRhiGles2); + rhiD->releaseQueue.append(e); + + rhiD->unregisterResource(this); } bool QGles2ComputePipeline::build() { - return false; + QRHI_RES_RHI(QRhiGles2); + + if (program) + release(); + + if (!rhiD->ensureContext()) + return false; + + program = rhiD->f->glCreateProgram(); + QShaderDescription csDesc; + + if (!rhiD->compileShader(program, m_shaderStage, &csDesc, nullptr)) + return false; + if (!rhiD->linkProgram(program)) + return false; + + for (const QShaderDescription::UniformBlock &ub : csDesc.uniformBlocks()) + rhiD->gatherUniforms(program, ub, &uniforms); + for (const QShaderDescription::InOutVariable &v : csDesc.combinedImageSamplers()) + rhiD->gatherSamplers(program, v, &samplers); + + // storage images and buffers need no special steps here + + generation += 1; + rhiD->registerResource(this); + return true; } QGles2CommandBuffer::QGles2CommandBuffer(QRhiImplementation *rhi) diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index d6682977ff2..88a6144b42e 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -66,8 +66,22 @@ struct QGles2Buffer : public QRhiBuffer bool build() override; GLuint buffer = 0; - GLenum target; + GLenum targetForDataOps; QByteArray ubuf; + enum Access { + AccessNone, + AccessVertex, + AccessIndex, + AccessUniform, + AccessStorageRead, + AccessStorageWrite, + AccessStorageReadWrite, + AccessUpdate + }; + struct UsageState { + Access access; + }; + UsageState usageState; friend class QRhiGles2; }; @@ -127,12 +141,27 @@ struct QGles2Texture : public QRhiTexture bool owns = true; GLenum target; GLenum glintformat; + GLenum glsizedintformat; GLenum glformat; GLenum gltype; QGles2SamplerData samplerState; bool specified = false; int mipLevelCount = 0; QRhiGles2TextureNativeHandles nativeHandlesStruct; + enum Access { + AccessNone, + AccessSample, + AccessFramebuffer, + AccessStorageRead, + AccessStorageWrite, + AccessStorageReadWrite, + AccessUpdate, + AccessRead + }; + struct UsageState { + Access access; + }; + UsageState usageState; uint generation = 0; friend class QRhiGles2; @@ -213,6 +242,25 @@ struct QGles2ShaderResourceBindings : public QRhiShaderResourceBindings friend class QRhiGles2; }; +struct QGles2UniformDescription +{ + QShaderDescription::VariableType type; + int glslLocation; + int binding; + uint offset; + int size; +}; + +Q_DECLARE_TYPEINFO(QGles2UniformDescription, Q_MOVABLE_TYPE); + +struct QGles2SamplerDescription +{ + int glslLocation; + int binding; +}; + +Q_DECLARE_TYPEINFO(QGles2SamplerDescription, Q_MOVABLE_TYPE); + struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline { QGles2GraphicsPipeline(QRhiImplementation *rhi); @@ -222,38 +270,24 @@ struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline GLuint program = 0; GLenum drawMode = GL_TRIANGLES; - QShaderDescription vsDesc; - QShaderDescription fsDesc; - bool canUseUniformBuffers = false; - - struct Uniform { - QShaderDescription::VariableType type; - int glslLocation; - int binding; - uint offset; - int size; - }; - QVector uniforms; - - struct Sampler { - int glslLocation; - int binding; - }; - QVector samplers; - + QVector uniforms; + QVector samplers; uint generation = 0; friend class QRhiGles2; }; -Q_DECLARE_TYPEINFO(QGles2GraphicsPipeline::Uniform, Q_MOVABLE_TYPE); -Q_DECLARE_TYPEINFO(QGles2GraphicsPipeline::Sampler, Q_MOVABLE_TYPE); - struct QGles2ComputePipeline : public QRhiComputePipeline { QGles2ComputePipeline(QRhiImplementation *rhi); ~QGles2ComputePipeline(); void release() override; bool build() override; + + GLuint program = 0; + QVector uniforms; + QVector samplers; + uint generation = 0; + friend class QRhiGles2; }; struct QGles2CommandBuffer : public QRhiCommandBuffer @@ -286,7 +320,11 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer CompressedImage, CompressedSubImage, BlitFromRenderbuffer, - GenMip + GenMip, + BindComputePipeline, + Dispatch, + BarriersForPass, + Barrier }; Cmd cmd; @@ -339,7 +377,8 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer QRhiGraphicsPipeline *ps; } bindGraphicsPipeline; struct { - QRhiGraphicsPipeline *ps; + QRhiGraphicsPipeline *maybeGraphicsPs; + QRhiComputePipeline *maybeComputePs; QRhiShaderResourceBindings *srb; int dynamicOffsetCount; uint dynamicOffsetPairs[MAX_UBUF_BINDINGS * 2]; // binding, offsetInConstants @@ -436,6 +475,20 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer GLenum target; GLuint texture; } genMip; + struct { + QRhiComputePipeline *ps; + } bindComputePipeline; + struct { + GLuint x; + GLuint y; + GLuint z; + } dispatch; + struct { + int trackerIndex; + } barriersForPass; + struct { + GLbitfield barriers; + } barrier; } args; }; @@ -446,11 +499,16 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer }; QVector commands; + QVarLengthArray passResTrackers; + int currentPassResTrackerIndex; + PassType recordingPass; QRhiRenderTarget *currentTarget; - QRhiGraphicsPipeline *currentPipeline; + QRhiGraphicsPipeline *currentGraphicsPipeline; + QRhiComputePipeline *currentComputePipeline; uint currentPipelineGeneration; - QRhiShaderResourceBindings *currentSrb; + QRhiShaderResourceBindings *currentGraphicsSrb; + QRhiShaderResourceBindings *currentComputeSrb; uint currentSrbGeneration; QVector dataRetainPool; @@ -467,6 +525,12 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer } void resetCommands() { commands.clear(); + // beginExternal() can lead to calling resetCommands() inside a pass, + // hence the condition + if (recordingPass == NoPass) { + passResTrackers.clear(); + currentPassResTrackerIndex = -1; + } dataRetainPool.clear(); imageRetainPool.clear(); } @@ -477,9 +541,11 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer resetCachedState(); } void resetCachedState() { - currentPipeline = nullptr; + currentGraphicsPipeline = nullptr; + currentComputePipeline = nullptr; currentPipelineGeneration = 0; - currentSrb = nullptr; + currentGraphicsSrb = nullptr; + currentComputeSrb = nullptr; currentSrbGeneration = 0; } }; @@ -606,17 +672,35 @@ public: bool ensureContext(QSurface *surface = nullptr) const; void executeDeferredReleases(); QRhi::FrameOpResult flushCommandBuffer(); + void trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access); + void trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access); void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc); void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); + void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker, + QGles2Buffer *bufD, + QRhiPassResourceTracker::BufferAccess access, + QRhiPassResourceTracker::BufferStage stage); + void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker, + QGles2Texture *texD, + QRhiPassResourceTracker::TextureAccess access, + QRhiPassResourceTracker::TextureStage stage); void executeCommandBuffer(QRhiCommandBuffer *cb); void executeBindGraphicsPipeline(QRhiGraphicsPipeline *ps); - void bindShaderResources(QRhiGraphicsPipeline *ps, QRhiShaderResourceBindings *srb, + void bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs, + QRhiShaderResourceBindings *srb, const uint *dynOfsPairs, int dynOfsCount); QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD, bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr); int effectiveSampleCount(int sampleCount) const; QSize safeTextureSize(const QSize &size) const; + bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, + QShaderDescription *desc, int *glslVersionUsed); + bool linkProgram(GLuint program); + void gatherUniforms(GLuint program, const QShaderDescription::UniformBlock &ub, + QVector *dst); + void gatherSamplers(GLuint program, const QShaderDescription::InOutVariable &v, + QVector *dst); QOpenGLContext *ctx = nullptr; bool importedContext = false; @@ -652,7 +736,8 @@ public: depth24(false), rgba8Format(false), instancing(false), - baseVertex(false) + baseVertex(false), + compute(false) { } int ctxMajor; int ctxMinor; @@ -682,6 +767,7 @@ public: uint rgba8Format : 1; uint instancing : 1; uint baseVertex : 1; + uint compute : 1; } caps; QGles2SwapChain *currentSwapChain = nullptr; QVector supportedCompressedFormats; diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index fa537a504b3..ffb2283ae7e 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -57,7 +57,8 @@ QT_BEGIN_NAMESPACE Textures are Private (device local) and a host visible staging buffer is used to upload data to them. Does not rely on strong objects refs from command buffers but does rely on the automatic resource tracking of the - command encoders. + command encoders. Assumes that an autorelease pool (ideally per frame) is + available on the thread on which QRhi is used. */ #if __has_feature(objc_arc) @@ -352,7 +353,7 @@ bool QRhiMetal::create(QRhi::Flags flags) else d->dev = MTLCreateSystemDefaultDevice(); - qDebug("Metal device: %s", qPrintable(QString::fromNSString([d->dev name]))); + qCDebug(QRHI_LOG_INFO, "Metal device: %s", qPrintable(QString::fromNSString([d->dev name]))); if (importedCmdQueue) [d->cmdQueue retain]; @@ -1214,10 +1215,12 @@ QRhi::FrameOpResult QRhiMetal::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame Q_ASSERT(currentSwapChain == swapChainD); const bool needsPresent = !flags.testFlag(QRhi::SkipPresent); - if (needsPresent) { + if (needsPresent) [swapChainD->cbWrapper.d->cb presentDrawable: swapChainD->d->curDrawable]; - swapChainD->d->curDrawable = nil; - } + + // Must not hold on to the drawable, regardless of needsPresent. + // (internally it is autoreleased or something, it seems) + swapChainD->d->curDrawable = nil; __block int thisFrameSlot = currentFrameSlot; [swapChainD->cbWrapper.d->cb addCompletedHandler: ^(id) { @@ -3535,7 +3538,7 @@ bool QMetalSwapChain::buildOrResize() rtWrapper.d->colorAttCount = 1; rtWrapper.d->dsAttCount = ds ? 1 : 0; - qDebug("got CAMetalLayer, size %dx%d", pixelSize.width(), pixelSize.height()); + qCDebug(QRHI_LOG_INFO, "got CAMetalLayer, size %dx%d", pixelSize.width(), pixelSize.height()); if (samples > 1) { MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init]; diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 7c4eeaf226a..61a1595a504 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -360,14 +360,14 @@ bool QRhiVulkan::create(QRhi::Flags flags) requestedPhysDevIndex = qEnvironmentVariableIntValue("QT_VK_PHYSICAL_DEVICE_INDEX"); for (uint32_t i = 0; i < physDevCount; ++i) { f->vkGetPhysicalDeviceProperties(physDevs[i], &physDevProperties); - qDebug("Physical device %d: '%s' %d.%d.%d", i, - physDevProperties.deviceName, - VK_VERSION_MAJOR(physDevProperties.driverVersion), - VK_VERSION_MINOR(physDevProperties.driverVersion), - VK_VERSION_PATCH(physDevProperties.driverVersion)); + qCDebug(QRHI_LOG_INFO, "Physical device %d: '%s' %d.%d.%d", i, + physDevProperties.deviceName, + VK_VERSION_MAJOR(physDevProperties.driverVersion), + VK_VERSION_MINOR(physDevProperties.driverVersion), + VK_VERSION_PATCH(physDevProperties.driverVersion)); if (physDevIndex < 0 && (requestedPhysDevIndex < 0 || requestedPhysDevIndex == int(i))) { physDevIndex = i; - qDebug(" using this physical device"); + qCDebug(QRHI_LOG_INFO, " using this physical device"); } } if (physDevIndex < 0) { @@ -386,7 +386,8 @@ bool QRhiVulkan::create(QRhi::Flags flags) gfxQueueFamilyIdx = -1; int computelessGfxQueueCandidateIdx = -1; for (int i = 0; i < queueFamilyProps.count(); ++i) { - qDebug("queue family %d: flags=0x%x count=%d", i, queueFamilyProps[i].queueFlags, queueFamilyProps[i].queueCount); + qCDebug(QRHI_LOG_INFO, "queue family %d: flags=0x%x count=%d", + i, queueFamilyProps[i].queueFlags, queueFamilyProps[i].queueCount); if (gfxQueueFamilyIdx == -1 && (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && (!maybeWindow || inst->supportsPresent(physDev, i, maybeWindow))) @@ -422,7 +423,7 @@ bool QRhiVulkan::create(QRhi::Flags flags) f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, nullptr); QVector devExts(devExtCount); f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, devExts.data()); - qDebug("%d device extensions available", devExts.count()); + qCDebug(QRHI_LOG_INFO, "%d device extensions available", devExts.count()); QVector requestedDevExts; requestedDevExts.append("VK_KHR_swapchain"); @@ -1244,9 +1245,9 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain) // with VK_ERROR_NATIVE_WINDOW_IN_USE_KHR if the old swapchain is provided) const bool reuseExisting = swapChainD->sc && swapChainD->lastConnectedSurface == swapChainD->surface; - qDebug("Creating %s swapchain of %u buffers, size %dx%d, presentation mode %d", - reuseExisting ? "recycled" : "new", - reqBufferCount, swapChainD->pixelSize.width(), swapChainD->pixelSize.height(), presentMode); + qCDebug(QRHI_LOG_INFO, "Creating %s swapchain of %u buffers, size %dx%d, presentation mode %d", + reuseExisting ? "recycled" : "new", + reqBufferCount, swapChainD->pixelSize.width(), swapChainD->pixelSize.height(), presentMode); VkSwapchainCreateInfoKHR swapChainInfo; memset(&swapChainInfo, 0, sizeof(swapChainInfo)); @@ -1290,7 +1291,7 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain) return false; } if (actualSwapChainBufferCount != reqBufferCount) - qDebug("Actual swapchain buffer count is %u", actualSwapChainBufferCount); + qCDebug(QRHI_LOG_INFO, "Actual swapchain buffer count is %u", actualSwapChainBufferCount); swapChainD->bufferCount = actualSwapChainBufferCount; VkImage swapChainImages[QVkSwapChain::MAX_BUFFER_COUNT]; @@ -1661,6 +1662,10 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram } } + // Do platform-specific WM notification. F.ex. essential on X11 in + // order to prevent glitches on resizing the window. + inst->presentQueued(swapChainD->window); + // mark the current swapchain buffer as unused from our side frame.imageAcquired = false; // and move on to the next buffer @@ -3660,34 +3665,6 @@ void QRhiVulkan::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline psD->lastActiveFrameSlot = currentFrameSlot; } -QRhiPassResourceTracker::BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages) -{ - // pick the earlier stage (as this is going to be dstAccessMask) - if (stages.testFlag(QRhiShaderResourceBinding::VertexStage)) - return QRhiPassResourceTracker::BufVertexStage; - if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage)) - return QRhiPassResourceTracker::BufFragmentStage; - if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage)) - return QRhiPassResourceTracker::BufComputeStage; - - Q_UNREACHABLE(); - return QRhiPassResourceTracker::BufVertexStage; -} - -QRhiPassResourceTracker::TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages) -{ - // pick the earlier stage (as this is going to be dstAccessMask) - if (stages.testFlag(QRhiShaderResourceBinding::VertexStage)) - return QRhiPassResourceTracker::TexVertexStage; - if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage)) - return QRhiPassResourceTracker::TexFragmentStage; - if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage)) - return QRhiPassResourceTracker::TexComputeStage; - - Q_UNREACHABLE(); - return QRhiPassResourceTracker::TexVertexStage; -} - void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, int dynamicOffsetCount, const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) @@ -3743,7 +3720,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin bufD->lastActiveFrameSlot = currentFrameSlot; trackedRegisterBuffer(&passResTracker, bufD, bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0, QRhiPassResourceTracker::BufUniformRead, - toPassTrackerBufferStage(b->stage)); + QRhiPassResourceTracker::toPassTrackerBufferStage(b->stage)); // Check both the "local" id (the generation counter) and the // global id. The latter is relevant when a newly allocated @@ -3764,7 +3741,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin samplerD->lastActiveFrameSlot = currentFrameSlot; trackedRegisterTexture(&passResTracker, texD, QRhiPassResourceTracker::TexSample, - toPassTrackerTextureStage(b->stage)); + QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage)); if (texD->generation != bd.stex.texGeneration || texD->m_id != bd.stex.texId @@ -3797,7 +3774,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin access = QRhiPassResourceTracker::TexStorageLoadStore; trackedRegisterTexture(&passResTracker, texD, access, - toPassTrackerTextureStage(b->stage)); + QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage)); if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) { rewriteDescSet = true; @@ -3828,7 +3805,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin access = QRhiPassResourceTracker::BufStorageLoadStore; trackedRegisterBuffer(&passResTracker, bufD, bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0, access, - toPassTrackerBufferStage(b->stage)); + QRhiPassResourceTracker::toPassTrackerBufferStage(b->stage)); if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) { rewriteDescSet = true; diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp index 17824a5ba12..d8a971c7b75 100644 --- a/src/gui/text/qdistancefield.cpp +++ b/src/gui/text/qdistancefield.cpp @@ -899,9 +899,6 @@ QDistanceField::QDistanceField(int width, int height) { } -QDistanceField &QDistanceField::operator=(const QDistanceField &) - = default; - QDistanceField::QDistanceField(const QRawFont &font, glyph_t glyph, bool doubleResolution) { setGlyph(font, glyph, doubleResolution); diff --git a/src/gui/text/qdistancefield_p.h b/src/gui/text/qdistancefield_p.h index d6d8edd85d2..823bfaf1c67 100644 --- a/src/gui/text/qdistancefield_p.h +++ b/src/gui/text/qdistancefield_p.h @@ -94,7 +94,6 @@ public: QDistanceField(const QRawFont &font, glyph_t glyph, bool doubleResolution = false); QDistanceField(QFontEngine *fontEngine, glyph_t glyph, bool doubleResolution = false); QDistanceField(const QPainterPath &path, glyph_t glyph, bool doubleResolution = false); - QDistanceField &operator=(const QDistanceField &other); bool isNull() const; diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 537d4bcefd8..4198df6e43f 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -899,7 +899,7 @@ QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition return rgbMask; } -QImage QFontEngine::bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform&) +QImage QFontEngine::bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform&, const QColor &) { Q_UNUSED(subPixelPosition); @@ -1075,7 +1075,10 @@ void QFontEngine::setGlyphCache(const void *context, QFontEngineGlyphCache *cach } -QFontEngineGlyphCache *QFontEngine::glyphCache(const void *context, GlyphFormat format, const QTransform &transform) const +QFontEngineGlyphCache *QFontEngine::glyphCache(const void *context, + GlyphFormat format, + const QTransform &transform, + const QColor &color) const { const QHash::const_iterator caches = m_glyphCaches.constFind(context); if (caches == m_glyphCaches.cend()) @@ -1083,8 +1086,11 @@ QFontEngineGlyphCache *QFontEngine::glyphCache(const void *context, GlyphFormat for (auto &e : *caches) { QFontEngineGlyphCache *cache = e.cache.data(); - if (format == cache->glyphFormat() && qtransform_equals_no_translate(cache->m_transform, transform)) + if (format == cache->glyphFormat() + && (format != Format_ARGB || color == cache->color()) + && qtransform_equals_no_translate(cache->m_transform, transform)) { return cache; + } } return nullptr; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 8dcfd7d66cd..e20b52cb652 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -189,7 +189,7 @@ public: virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t); virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); - virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); + virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color = QColor()); virtual QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, GlyphFormat neededFormat, const QTransform &t = QTransform(), @@ -251,7 +251,7 @@ public: void clearGlyphCache(const void *key); void setGlyphCache(const void *key, QFontEngineGlyphCache *data); - QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const; + QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform, const QColor &color = QColor()) const; static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize); static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode); diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h index fd5db1ecf5c..532be10a83f 100644 --- a/src/gui/text/qfontengineglyphcache_p.h +++ b/src/gui/text/qfontengineglyphcache_p.h @@ -65,7 +65,10 @@ QT_BEGIN_NAMESPACE class Q_GUI_EXPORT QFontEngineGlyphCache: public QSharedData { public: - QFontEngineGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) : m_format(format), m_transform(matrix) + QFontEngineGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix, const QColor &color = QColor()) + : m_format(format) + , m_transform(matrix) + , m_color(color) { Q_ASSERT(m_format != QFontEngine::Format_None); } @@ -74,9 +77,11 @@ public: QFontEngine::GlyphFormat glyphFormat() const { return m_format; } const QTransform &transform() const { return m_transform; } + const QColor &color() const { return m_color; } QFontEngine::GlyphFormat m_format; QTransform m_transform; + QColor m_color; }; typedef QHash > GlyphPointerHash; typedef QHash > GlyphIntHash; diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index 1302bd66bb1..b845889c3d1 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1322,7 +1322,7 @@ QTextList *QTextBlock::textList() const QTextBlockUserData *QTextBlock::userData() const { if (!p || !n) - return 0; + return nullptr; const QTextBlockData *b = p->blockMap().fragment(n); return b->userData; diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index ee0ff4c6ef0..99214c49601 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -290,6 +290,7 @@ void QDesktopServices::unsetUrlHandler(const QString &scheme) setUrlHandler(scheme, 0, 0); } +#if QT_DEPRECATED_SINCE(5, 0) /*! \enum QDesktopServices::StandardLocation \since 4.4 @@ -344,6 +345,7 @@ void QDesktopServices::unsetUrlHandler(const QString &scheme) \obsolete Use QStandardPaths::displayName() */ +#endif extern Q_CORE_EXPORT QString qt_applicationName_noFallback(); diff --git a/src/network/.prev_CMakeLists.txt b/src/network/.prev_CMakeLists.txt index e5756e291d2..6d43386d744 100644 --- a/src/network/.prev_CMakeLists.txt +++ b/src/network/.prev_CMakeLists.txt @@ -108,9 +108,7 @@ extend_target(Network CONDITION QT_FEATURE_settings access/qhstsstore.cpp access/qhstsstore_p.h ) -extend_target(Network CONDITION APPLE_OSX - SOURCES - kernel/qnetworkproxy_mac.cpp +extend_target(Network CONDITION APPLE LIBRARIES ${FWCoreFoundation} ${FWSecurity} @@ -219,7 +217,7 @@ extend_target(Network CONDITION QT_FEATURE_dnslookup AND WINRT kernel/qdnslookup_winrt.cpp ) -extend_target(Network CONDITION APPLE_OSX AND NOT APPLE_UIKIT +extend_target(Network CONDITION APPLE AND NOT APPLE_UIKIT LIBRARIES ${FWCoreServices} ${FWSystemConfiguration} @@ -232,7 +230,12 @@ extend_target(Network CONDITION APPLE_IOS OR APPLE_OSX ${FWSystemConfiguration} ) -extend_target(Network CONDITION NOT APPLE_IOS AND NOT APPLE_OSX +extend_target(Network CONDITION QT_FEATURE_netlistmgr AND NOT APPLE_IOS AND NOT APPLE_OSX + SOURCES + kernel/qnetconmonitor_win.cpp +) + +extend_target(Network CONDITION NOT APPLE_IOS AND NOT APPLE_OSX AND NOT QT_FEATURE_netlistmgr SOURCES kernel/qnetconmonitor_stub.cpp ) @@ -247,6 +250,11 @@ extend_target(Network CONDITION APPLE_UIKIT kernel/qnetworkinterface_uikit_p.h ) +extend_target(Network CONDITION APPLE_OSX + SOURCES + kernel/qnetworkproxy_mac.cpp +) + extend_target(Network CONDITION QT_FEATURE_libproxy AND NOT APPLE_OSX AND (UNIX OR WINRT) SOURCES kernel/qnetworkproxy_libproxy.cpp diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 3148c007043..85ee368df50 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -108,9 +108,7 @@ extend_target(Network CONDITION QT_FEATURE_settings access/qhstsstore.cpp access/qhstsstore_p.h ) -extend_target(Network CONDITION APPLE_OSX - SOURCES - kernel/qnetworkproxy_mac.cpp +extend_target(Network CONDITION APPLE LIBRARIES ${FWCoreFoundation} ${FWSecurity} @@ -220,7 +218,7 @@ extend_target(Network CONDITION QT_FEATURE_dnslookup AND WINRT kernel/qdnslookup_winrt.cpp ) -extend_target(Network CONDITION APPLE_OSX AND NOT APPLE_UIKIT +extend_target(Network CONDITION APPLE AND NOT APPLE_UIKIT LIBRARIES ${FWCoreServices} ${FWSystemConfiguration} @@ -233,7 +231,12 @@ extend_target(Network CONDITION APPLE_IOS OR APPLE_OSX ${FWSystemConfiguration} ) -extend_target(Network CONDITION NOT APPLE_IOS AND NOT APPLE_OSX +extend_target(Network CONDITION QT_FEATURE_netlistmgr AND NOT APPLE_IOS AND NOT APPLE_OSX + SOURCES + kernel/qnetconmonitor_win.cpp +) + +extend_target(Network CONDITION NOT APPLE_IOS AND NOT APPLE_OSX AND NOT QT_FEATURE_netlistmgr SOURCES kernel/qnetconmonitor_stub.cpp ) @@ -248,6 +251,11 @@ extend_target(Network CONDITION APPLE_UIKIT kernel/qnetworkinterface_uikit_p.h ) +extend_target(Network CONDITION APPLE_OSX + SOURCES + kernel/qnetworkproxy_mac.cpp +) + extend_target(Network CONDITION QT_FEATURE_libproxy AND NOT APPLE_OSX AND (UNIX OR WINRT) SOURCES kernel/qnetworkproxy_libproxy.cpp diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index 93afcf0ee12..0ece5b7179a 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -170,7 +170,6 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan encoder(HPack::FieldLookupTable::DefaultSize, true) { Q_ASSERT(channel && m_connection); - continuedFrames.reserve(20); const ProtocolParameters params(m_connection->http2Parameters()); @@ -328,10 +327,32 @@ bool QHttp2ProtocolHandler::sendRequest() return false; } + // Process 'fake' (created by QNetworkAccessManager::connectToHostEncrypted()) + // requests first: + auto &requests = m_channel->spdyRequestsToSend; + for (auto it = requests.begin(), endIt = requests.end(); it != endIt;) { + const auto &pair = *it; + const QString scheme(pair.first.url().scheme()); + if (scheme == QLatin1String("preconnect-http") + || scheme == QLatin1String("preconnect-https")) { + m_connection->preConnectFinished(); + emit pair.second->finished(); + it = requests.erase(it); + if (!requests.size()) { + // Normally, after a connection was established and H2 + // was negotiated, we send a client preface. connectToHostEncrypted + // though is not meant to send any data, it's just a 'preconnect'. + // Thus we return early: + return true; + } + } else { + ++it; + } + } + if (!prefaceSent && !sendClientPreface()) return false; - auto &requests = m_channel->spdyRequestsToSend; if (!requests.size()) return true; diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 6fb4710d77c..acc551a7c92 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -128,7 +128,8 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy, const QString &p QString result; QUrl copy = url; QString scheme = copy.scheme(); - bool isEncrypted = scheme == QLatin1String("https"); + bool isEncrypted = scheme == QLatin1String("https") + || scheme == QLatin1String("preconnect-https"); copy.setPort(copy.port(isEncrypted ? 443 : 80)); if (scheme == QLatin1String("preconnect-http")) { copy.setScheme(QLatin1String("http")); @@ -296,17 +297,29 @@ void QHttpThreadDelegate::startRequest() connectionType = QHttpNetworkConnection::ConnectionTypeHTTP2Direct; } + const bool isH2 = httpRequest.isHTTP2Allowed() || httpRequest.isHTTP2Direct(); + if (isH2) { +#if QT_CONFIG(ssl) + if (ssl) { + if (!httpRequest.isHTTP2Direct()) { + QList protocols; + protocols << QSslConfiguration::ALPNProtocolHTTP2 + << QSslConfiguration::NextProtocolHttp1_1; + incomingSslConfiguration->setAllowedNextProtocols(protocols); + } + urlCopy.setScheme(QStringLiteral("h2s")); + } else +#endif // QT_CONFIG(ssl) + { + urlCopy.setScheme(QStringLiteral("h2")); + } + } + #ifndef QT_NO_SSL if (ssl && !incomingSslConfiguration.data()) incomingSslConfiguration.reset(new QSslConfiguration); - if (httpRequest.isHTTP2Allowed() && ssl) { - // With HTTP2Direct we do not try any protocol negotiation. - QList protocols; - protocols << QSslConfiguration::ALPNProtocolHTTP2 - << QSslConfiguration::NextProtocolHttp1_1; - incomingSslConfiguration->setAllowedNextProtocols(protocols); - } else if (httpRequest.isSPDYAllowed() && ssl) { + if (!isH2 && httpRequest.isSPDYAllowed() && ssl) { connectionType = QHttpNetworkConnection::ConnectionTypeSPDY; urlCopy.setScheme(QStringLiteral("spdy")); // to differentiate SPDY requests from HTTPS requests QList nextProtocols; @@ -323,12 +336,11 @@ void QHttpThreadDelegate::startRequest() cacheKey = makeCacheKey(urlCopy, &cacheProxy, httpRequest.peerVerifyName()); else #endif - cacheKey = makeCacheKey(urlCopy, 0, httpRequest.peerVerifyName()); - + cacheKey = makeCacheKey(urlCopy, nullptr, httpRequest.peerVerifyName()); // the http object is actually a QHttpNetworkConnection httpConnection = static_cast(connections.localData()->requestEntryNow(cacheKey)); - if (httpConnection == 0) { + if (!httpConnection) { // no entry in cache; create an object // the http object is actually a QHttpNetworkConnection #ifdef QT_NO_BEARERMANAGEMENT @@ -358,7 +370,7 @@ void QHttpThreadDelegate::startRequest() connections.localData()->addEntry(cacheKey, httpConnection); } else { if (httpRequest.withCredentials()) { - QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedCredentials(httpRequest.url(), 0); + QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedCredentials(httpRequest.url(), nullptr); if (!credential.user.isEmpty() && !credential.password.isEmpty()) { QAuthenticator auth; auth.setUser(credential.user); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index a2996e35335..29192ae7b0e 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -493,9 +493,9 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) connect(&d->statusMonitor, SIGNAL(onlineStateChanged(bool)), SLOT(_q_onlineStateChanged(bool))); #ifdef QT_NO_BEARERMANAGEMENT - d->networkAccessible = d->statusMonitor.isNetworkAccesible(); + d->networkAccessible = d->statusMonitor.isNetworkAccessible(); #else - d->networkAccessible = d->statusMonitor.isNetworkAccesible() ? Accessible : NotAccessible; + d->networkAccessible = d->statusMonitor.isNetworkAccessible() ? Accessible : NotAccessible; } else { // if a session is required, we track online state through // the QNetworkSession's signals if a request is already made. @@ -1236,10 +1236,11 @@ void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quin if (sslConfiguration != QSslConfiguration::defaultConfiguration()) request.setSslConfiguration(sslConfiguration); - // There is no way to enable SPDY via a request, so we need to check - // the ssl configuration whether SPDY is allowed here. - if (sslConfiguration.allowedNextProtocols().contains( - QSslConfiguration::NextProtocolSpdy3_0)) + // There is no way to enable SPDY/HTTP2 via a request, so we need to check + // the ssl configuration whether SPDY/HTTP2 is allowed here. + if (sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::ALPNProtocolHTTP2)) + request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); + else if (sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::NextProtocolSpdy3_0)) request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); request.setPeerVerifyName(peerName); @@ -1565,8 +1566,8 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera QNetworkReplyImpl *reply = new QNetworkReplyImpl(this); #ifndef QT_NO_BEARERMANAGEMENT // NETMONTODO: network reply impl must be augmented to use the same monitoring - // capabilities as http network reply impl does. - if (!isLocalFile && !d->statusMonitor.isEnabled()) { + // capabilities as http network reply impl does. Once it does: uncomment the condition below + if (!isLocalFile /*&& !d->statusMonitor.isEnabled()*/) { connect(this, SIGNAL(networkSessionConnected()), reply, SLOT(_q_networkSessionConnected())); } diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp index ee91dc20b33..53784407d88 100644 --- a/src/network/access/qnetworkreplywasmimpl.cpp +++ b/src/network/access/qnetworkreplywasmimpl.cpp @@ -135,8 +135,10 @@ static void q_loadCallback(val event) if (readyState == 4) { // done reply->setReplyAttributes(xhr["data-handler"].as(), status, statusText); - if (!responseString.isEmpty()) - reply->dataReceived(responseString.toUtf8(), responseString.size()); + if (!responseString.isEmpty()) { + QByteArray responseStringArray = responseString.toUtf8(); + reply->dataReceived(responseStringArray, responseStringArray.size()); + } } } if (status >= 400 && !statusText.isEmpty()) diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index ba36c75419b..37f64c3f520 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -467,6 +467,17 @@ public: QString peerVerifyName; }; +/*! + Constructs a QNetworkRequest object with no URL to be requested. + Use setUrl() to set one. + + \sa url(), setUrl() +*/ +QNetworkRequest::QNetworkRequest() + : d(new QNetworkRequestPrivate) +{ +} + /*! Constructs a QNetworkRequest object with \a url as the URL to be requested. @@ -474,7 +485,7 @@ public: \sa url(), setUrl() */ QNetworkRequest::QNetworkRequest(const QUrl &url) - : d(new QNetworkRequestPrivate) + : QNetworkRequest() { d->url = url; } @@ -1344,7 +1355,7 @@ QDateTime QNetworkHeadersPrivate::fromHttpDate(const QByteArray &value) QByteArray QNetworkHeadersPrivate::toHttpDate(const QDateTime &dt) { - return QLocale::c().toString(dt, QStringViewLiteral("ddd, dd MMM yyyy hh:mm:ss 'GMT'")) + return QLocale::c().toString(dt, u"ddd, dd MMM yyyy hh:mm:ss 'GMT'") .toLatin1(); } diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index 846ead1592c..8ad4ab41c0e 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -128,7 +128,8 @@ public: }; - explicit QNetworkRequest(const QUrl &url = QUrl()); + QNetworkRequest(); + explicit QNetworkRequest(const QUrl &url); QNetworkRequest(const QNetworkRequest &other); ~QNetworkRequest(); QNetworkRequest &operator=(QNetworkRequest &&other) noexcept { swap(other); return *this; } diff --git a/src/network/access/qspdyprotocolhandler.cpp b/src/network/access/qspdyprotocolhandler.cpp index 403c01e974a..f845235bf79 100644 --- a/src/network/access/qspdyprotocolhandler.cpp +++ b/src/network/access/qspdyprotocolhandler.cpp @@ -305,7 +305,7 @@ bool QSpdyProtocolHandler::sendRequest() currentReply->setSpdyWasUsed(true); qint32 streamID = generateNextStreamID(); - currentReply->setProperty("SPDYStreamID", streamID); + m_streamIDs.insert(currentReply, streamID); currentReply->setRequest(currentRequest); currentReply->d_func()->connection = m_connection; @@ -322,7 +322,7 @@ bool QSpdyProtocolHandler::sendRequest() void QSpdyProtocolHandler::_q_replyDestroyed(QObject* reply) { - qint32 streamID = reply->property("SPDYStreamID").toInt(); + qint32 streamID = m_streamIDs.take(reply); if (m_inFlightStreams.remove(streamID)) sendRST_STREAM(streamID, RST_STREAM_CANCEL); } @@ -624,10 +624,12 @@ void QSpdyProtocolHandler::sendSYN_STREAM(const HttpMessagePair &messagePair, // hack: set the stream ID on the device directly, so when we get // the signal for uploading we know which stream we are sending on - request.uploadByteDevice()->setProperty("SPDYStreamID", streamID); + m_streamIDs.insert(request.uploadByteDevice(), streamID); QObject::connect(request.uploadByteDevice(), SIGNAL(readyRead()), this, SLOT(_q_uploadDataReadyRead()), Qt::QueuedConnection); + QObject::connect(request.uploadByteDevice(), SIGNAL(destroyed(QObject*)), this, + SLOT(_q_uploadDataDestroyed(QObject *))); } QByteArray namesAndValues = composeHeader(request); @@ -663,6 +665,11 @@ void QSpdyProtocolHandler::sendSYN_STREAM(const HttpMessagePair &messagePair, uploadData(streamID); } +void QSpdyProtocolHandler::_q_uploadDataDestroyed(QObject *uploadData) +{ + m_streamIDs.remove(uploadData); +} + void QSpdyProtocolHandler::sendRST_STREAM(qint32 streamID, RST_STREAM_STATUS_CODE statusCode) { char wireData[8]; @@ -756,7 +763,7 @@ void QSpdyProtocolHandler::_q_uploadDataReadyRead() { QNonContiguousByteDevice *device = qobject_cast(sender()); Q_ASSERT(device); - qint32 streamID = device->property("SPDYStreamID").toInt(); + qint32 streamID = m_streamIDs.value(device); Q_ASSERT(streamID > 0); uploadData(streamID); } diff --git a/src/network/access/qspdyprotocolhandler_p.h b/src/network/access/qspdyprotocolhandler_p.h index dd93a9aba2a..14e2ff388ad 100644 --- a/src/network/access/qspdyprotocolhandler_p.h +++ b/src/network/access/qspdyprotocolhandler_p.h @@ -110,6 +110,7 @@ public: private slots: void _q_uploadDataReadyRead(); void _q_replyDestroyed(QObject*); + void _q_uploadDataDestroyed(QObject *); private: @@ -216,6 +217,7 @@ private: bool m_waitingForCompleteStream; z_stream m_deflateStream; z_stream m_inflateStream; + QHash m_streamIDs; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::DataFrameFlags) diff --git a/src/network/bearer/qsharednetworksession.cpp b/src/network/bearer/qsharednetworksession.cpp index af543f77e33..b3e9892f4b1 100644 --- a/src/network/bearer/qsharednetworksession.cpp +++ b/src/network/bearer/qsharednetworksession.cpp @@ -64,9 +64,23 @@ struct DeleteLater { } }; +template +static void maybe_prune_expired(Container &c) +{ + if (c.size() > 16) { + for (auto it = c.cbegin(), end = c.cend(); it != end; /*erasing*/) { + if (!it->second.lock()) + it = c.erase(it); + else + ++it; + } + } +} + QSharedPointer QSharedNetworkSessionManager::getSession(const QNetworkConfiguration &config) { QSharedNetworkSessionManager *m = sharedNetworkSessionManager(); + maybe_prune_expired(m->sessions); auto &entry = m->sessions[config]; //if already have a session, return it if (auto p = entry.toStrongRef()) diff --git a/src/network/configure.cmake b/src/network/configure.cmake index c7d300acb0a..2dd5460b9d9 100644 --- a/src/network/configure.cmake +++ b/src/network/configure.cmake @@ -182,6 +182,29 @@ gss_ctx_id_t ctx; "# FIXME: qmake: LIBS += -lgssapi_krb5 ) +# netlistmgr +qt_config_compile_test(netlistmgr + LABEL "Network List Manager" +" +#include +#include + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + /* BEGIN TEST: */ +using namespace Microsoft::WRL; +ComPtr networkListManager; +ComPtr connectionPoint; +ComPtr connectionPointContainer; +networkListManager.As(&connectionPointContainer); +connectionPointContainer->FindConnectionPoint(IID_INetworkConnectionEvents, &connectionPoint); + /* END TEST: */ + return 0; +} +"# FIXME: qmake: LIBS += -lOle32 +) + #### Features @@ -352,3 +375,9 @@ qt_feature("sspi" PUBLIC CONDITION WIN32 AND NOT WINRT ) qt_feature_definition("sspi" "QT_NO_SSPI" NEGATE VALUE "1") +qt_feature("netlistmgr" PRIVATE + SECTION "Networking" + LABEL "Network List Manager" + PURPOSE "Use Network List Manager to keep track of network connectivity" + CONDITION WIN32 AND TEST_netlistmgr +) diff --git a/src/network/configure.json b/src/network/configure.json index 7225a6251d2..f80f38f1438 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -208,6 +208,22 @@ "main": ["gss_ctx_id_t ctx;"], "qmake": "LIBS += -lgssapi_krb5" } + }, + "netlistmgr": { + "label": "Network List Manager", + "type": "compile", + "test": { + "include": [ "netlistmgr.h", "wrl/client.h" ], + "main": [ + "using namespace Microsoft::WRL;", + "ComPtr networkListManager;", + "ComPtr connectionPoint;", + "ComPtr connectionPointContainer;", + "networkListManager.As(&connectionPointContainer);", + "connectionPointContainer->FindConnectionPoint(IID_INetworkConnectionEvents, &connectionPoint);" + ], + "qmake": "LIBS += -lOle32" + } } }, @@ -397,6 +413,13 @@ "section": "Networking", "condition": "config.win32 && !config.winrt", "output": [ "publicFeature", "feature" ] + }, + "netlistmgr": { + "label": "Network List Manager", + "purpose": "Use Network List Manager to keep track of network connectivity", + "section": "Networking", + "condition": "config.win32 && tests.netlistmgr", + "output": [ "privateFeature" ] } }, diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index 0e4cef5e74f..a55648dbc7f 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -77,6 +77,8 @@ macos | ios { kernel/qnetconmonitor_darwin.mm LIBS_PRIVATE += -framework SystemConfiguration +} else:qtConfig(netlistmgr) { + SOURCES += kernel/qnetconmonitor_win.cpp } else { SOURCES += kernel/qnetconmonitor_stub.cpp } diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 25ff8733078..487cac6d903 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -85,13 +86,6 @@ private: QString m_toBeLookedUp; }; -// ### C++11: remove once we can use std::any_of() -template -bool any_of(InputIt first, InputIt last, UnaryPredicate p) -{ - return std::find_if(first, last, p) != last; -} - template std::pair separate_if(InputIt first, InputIt last, OutputIt1 dest1, OutputIt2 dest2, UnaryPredicate p) { @@ -118,11 +112,39 @@ int get_signal_index() return signal_index + QMetaObjectPrivate::signalOffset(senderMetaObject); } -void emit_results_ready(const QHostInfo &hostInfo, const QObject *receiver, - QtPrivate::QSlotObjectBase *slotObj) +} + +/* + The calling thread is likely the one that executes the lookup via + QHostInfoRunnable. Unless we operate with a queued connection already, + posts the QHostInfo to a dedicated QHostInfoResult object that lives in + the same thread as the user-provided receiver, or (if there is none) in + the thread that made the call to lookupHost. That QHostInfoResult object + then calls the user code in the correct thread. + + The 'result' object deletes itself (via deleteLater) when the metacall + event is received. +*/ +void QHostInfoResult::postResultsReady(const QHostInfo &info) { + // queued connection will take care of dispatching to right thread + if (!slotObj) { + emitResultsReady(info); + return; + } static const int signal_index = get_signal_index(); + + // we used to have a context object, but it's already destroyed + if (withContextObject && !receiver) + return; + + /* QHostInfoResult c'tor moves the result object to the thread of receiver. + If we don't have a receiver, then the result object will not live in a + thread that runs an event loop - so move it to this' thread, which is the thread + that initiated the lookup, and required to have a running event loop. */ auto result = new QHostInfoResult(receiver, slotObj); + if (!receiver) + result->moveToThread(thread()); Q_CHECK_PTR(result); const int nargs = 2; auto types = reinterpret_cast(malloc(nargs * sizeof(int))); @@ -132,15 +154,13 @@ void emit_results_ready(const QHostInfo &hostInfo, const QObject *receiver, auto args = reinterpret_cast(malloc(nargs * sizeof(void *))); Q_CHECK_PTR(args); args[0] = 0; - args[1] = QMetaType::create(types[1], &hostInfo); + args[1] = QMetaType::create(types[1], &info); Q_CHECK_PTR(args[1]); auto metaCallEvent = new QMetaCallEvent(slotObj, nullptr, signal_index, nargs, types, args); Q_CHECK_PTR(metaCallEvent); qApp->postEvent(result, metaCallEvent); } -} - /*! \class QHostInfo \brief The QHostInfo class provides static functions for host name lookups. @@ -328,6 +348,10 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, ready, the \a functor is called with a QHostInfo argument. The QHostInfo object can then be inspected to get the results of the lookup. + + The \a functor will be run in the thread that makes the call to lookupHost; + that thread must have a running Qt event loop. + \note There is no guarantee on the order the signals will be emitted if you start multiple requests with lookupHost(). @@ -398,7 +422,7 @@ QHostInfo QHostInfo::fromName(const QString &name) #endif QHostInfo hostInfo = QHostInfoAgent::fromName(name); - QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); + QHostInfoLookupManager* manager = theHostInfoLookupManager(); manager->cache.put(name, hostInfo); return hostInfo; } @@ -411,7 +435,7 @@ QHostInfo QHostInfoPrivate::fromName(const QString &name, QSharedPointercache.put(name, hostInfo); return hostInfo; } @@ -600,8 +624,9 @@ QHostInfo QHostInfoAgent::lookup(const QString &hostName) \sa lookupId() */ QHostInfo::QHostInfo(int id) - : d(new QHostInfoPrivate) + : d_ptr(new QHostInfoPrivate) { + Q_D(QHostInfo); d->lookupId = id; } @@ -609,17 +634,30 @@ QHostInfo::QHostInfo(int id) Constructs a copy of \a other. */ QHostInfo::QHostInfo(const QHostInfo &other) - : d(new QHostInfoPrivate(*other.d.data())) + : d_ptr(new QHostInfoPrivate(*other.d_ptr)) { } +/*! + Move-constucts a new QHostInfo from \a other. + + \note The moved-from object \a other is placed in a + partially-formed state, in which the only valid operations are + destruction and assignment of a new value. + + \since 5.14 +*/ + /*! Assigns the data of the \a other object to this host info object, and returns a reference to it. */ QHostInfo &QHostInfo::operator=(const QHostInfo &other) { - *d.data() = *other.d.data(); + if (d_ptr) + *d_ptr = *other.d_ptr; + else + d_ptr = new QHostInfoPrivate(*other.d_ptr); return *this; } @@ -628,6 +666,7 @@ QHostInfo &QHostInfo::operator=(const QHostInfo &other) */ QHostInfo::~QHostInfo() { + delete d_ptr; } /*! @@ -642,6 +681,7 @@ QHostInfo::~QHostInfo() */ QList QHostInfo::addresses() const { + Q_D(const QHostInfo); return d->addrs; } @@ -652,6 +692,7 @@ QList QHostInfo::addresses() const */ void QHostInfo::setAddresses(const QList &addresses) { + Q_D(QHostInfo); d->addrs = addresses; } @@ -662,6 +703,7 @@ void QHostInfo::setAddresses(const QList &addresses) */ QString QHostInfo::hostName() const { + Q_D(const QHostInfo); return d->hostName; } @@ -672,6 +714,7 @@ QString QHostInfo::hostName() const */ void QHostInfo::setHostName(const QString &hostName) { + Q_D(QHostInfo); d->hostName = hostName; } @@ -683,6 +726,7 @@ void QHostInfo::setHostName(const QString &hostName) */ QHostInfo::HostInfoError QHostInfo::error() const { + Q_D(const QHostInfo); return d->err; } @@ -693,6 +737,7 @@ QHostInfo::HostInfoError QHostInfo::error() const */ void QHostInfo::setError(HostInfoError error) { + Q_D(QHostInfo); d->err = error; } @@ -703,6 +748,7 @@ void QHostInfo::setError(HostInfoError error) */ int QHostInfo::lookupId() const { + Q_D(const QHostInfo); return d->lookupId; } @@ -713,6 +759,7 @@ int QHostInfo::lookupId() const */ void QHostInfo::setLookupId(int id) { + Q_D(QHostInfo); d->lookupId = id; } @@ -724,6 +771,7 @@ void QHostInfo::setLookupId(int id) */ QString QHostInfo::errorString() const { + Q_D(const QHostInfo); return d->errorStr; } @@ -735,6 +783,7 @@ QString QHostInfo::errorString() const */ void QHostInfo::setErrorString(const QString &str) { + Q_D(QHostInfo); d->errorStr = str; } @@ -791,7 +840,8 @@ int QHostInfo::lookupHostImpl(const QString &name, QHostInfo hostInfo(id); hostInfo.setError(QHostInfo::HostNotFound); hostInfo.setErrorString(QCoreApplication::translate("QHostInfo", "No host name given")); - emit_results_ready(hostInfo, receiver, slotObj); + QHostInfoResult result(receiver, slotObj); + result.postResultsReady(hostInfo); return id; } @@ -805,7 +855,8 @@ int QHostInfo::lookupHostImpl(const QString &name, QHostInfo info = manager->cache.get(name, &valid); if (valid) { info.setLookupId(id); - emit_results_ready(info, receiver, slotObj); + QHostInfoResult result(receiver, slotObj); + result.postResultsReady(info); return id; } } @@ -833,11 +884,10 @@ QHostInfoRunnable::QHostInfoRunnable(const QString &hn, int i, const QObject *re void QHostInfoRunnable::run() { QHostInfoLookupManager *manager = theHostInfoLookupManager(); + const auto sg = qScopeGuard([&] { manager->lookupFinished(this); }); // check aborted - if (manager->wasAborted(id)) { - manager->lookupFinished(this); + if (manager->wasAborted(id)) return; - } QHostInfo hostInfo; @@ -859,14 +909,12 @@ void QHostInfoRunnable::run() } // check aborted again - if (manager->wasAborted(id)) { - manager->lookupFinished(this); + if (manager->wasAborted(id)) return; - } // signal emission hostInfo.setLookupId(id); - resultEmitter.emitResultsReady(hostInfo); + resultEmitter.postResultsReady(hostInfo); #if QT_CONFIG(thread) // now also iterate through the postponed ones @@ -879,30 +927,31 @@ void QHostInfoRunnable::run() QHostInfoRunnable* postponed = *it; // we can now emit hostInfo.setLookupId(postponed->id); - postponed->resultEmitter.emitResultsReady(hostInfo); + postponed->resultEmitter.postResultsReady(hostInfo); delete postponed; } manager->postponedLookups.erase(partitionBegin, partitionEnd); } #endif - manager->lookupFinished(this); - // thread goes back to QThreadPool } QHostInfoLookupManager::QHostInfoLookupManager() : wasDeleted(false) { - moveToThread(QCoreApplicationPrivate::mainThread()); #if QT_CONFIG(thread) - connect(QCoreApplication::instance(), SIGNAL(destroyed()), SLOT(waitForThreadPoolDone()), Qt::DirectConnection); + QObject::connect(QCoreApplication::instance(), &QObject::destroyed, + &threadPool, [&](QObject *) { threadPool.waitForDone(); }, + Qt::DirectConnection); threadPool.setMaxThreadCount(20); // do up to 20 DNS lookups in parallel #endif } QHostInfoLookupManager::~QHostInfoLookupManager() { + QMutexLocker locker(&mutex); wasDeleted = true; + locker.unlock(); // don't qDeleteAll currentLookups, the QThreadPool has ownership clear(); @@ -928,7 +977,8 @@ void QHostInfoLookupManager::clear() cache.clear(); } -void QHostInfoLookupManager::work() +// assumes mutex is locked by caller +void QHostInfoLookupManager::rescheduleWithMutexHeld() { if (wasDeleted) return; @@ -937,8 +987,6 @@ void QHostInfoLookupManager::work() // - launch new lookups via the thread pool // - make sure only one lookup per host/IP is in progress - QMutexLocker locker(&mutex); - if (!finishedLookups.isEmpty()) { // remove ID from aborted if it is in there for (int i = 0; i < finishedLookups.length(); i++) { @@ -950,7 +998,7 @@ void QHostInfoLookupManager::work() #if QT_CONFIG(thread) auto isAlreadyRunning = [this](QHostInfoRunnable *lookup) { - return any_of(currentLookups.cbegin(), currentLookups.cend(), ToBeLookedUpEquals(lookup->toBeLookedUp)); + return std::any_of(currentLookups.cbegin(), currentLookups.cend(), ToBeLookedUpEquals(lookup->toBeLookedUp)); }; // Transfer any postponed lookups that aren't currently running to the scheduled list, keeping already-running lookups: @@ -990,22 +1038,23 @@ void QHostInfoLookupManager::work() // called by QHostInfo void QHostInfoLookupManager::scheduleLookup(QHostInfoRunnable *r) { + QMutexLocker locker(&this->mutex); + if (wasDeleted) return; - QMutexLocker locker(&this->mutex); scheduledLookups.enqueue(r); - work(); + rescheduleWithMutexHeld(); } // called by QHostInfo void QHostInfoLookupManager::abortLookup(int id) { + QMutexLocker locker(&this->mutex); + if (wasDeleted) return; - QMutexLocker locker(&this->mutex); - #if QT_CONFIG(thread) // is postponed? delete and return for (int i = 0; i < postponedLookups.length(); i++) { @@ -1031,25 +1080,27 @@ void QHostInfoLookupManager::abortLookup(int id) // called from QHostInfoRunnable bool QHostInfoLookupManager::wasAborted(int id) { + QMutexLocker locker(&this->mutex); + if (wasDeleted) return true; - QMutexLocker locker(&this->mutex); return abortedLookups.contains(id); } // called from QHostInfoRunnable void QHostInfoLookupManager::lookupFinished(QHostInfoRunnable *r) { + QMutexLocker locker(&this->mutex); + if (wasDeleted) return; - QMutexLocker locker(&this->mutex); #if QT_CONFIG(thread) currentLookups.removeOne(r); #endif finishedLookups.append(r); - work(); + rescheduleWithMutexHeld(); } // This function returns immediately when we had a result in the cache, else it will later emit a signal @@ -1059,7 +1110,7 @@ QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *id = -1; // check cache - QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); + QHostInfoLookupManager* manager = theHostInfoLookupManager(); if (manager && manager->cache.isEnabled()) { QHostInfo info = manager->cache.get(name, valid); if (*valid) { @@ -1076,7 +1127,7 @@ QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char void qt_qhostinfo_clear_cache() { - QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); + QHostInfoLookupManager* manager = theHostInfoLookupManager(); if (manager) { manager->clear(); } @@ -1085,7 +1136,7 @@ void qt_qhostinfo_clear_cache() #ifdef QT_BUILD_INTERNAL void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e) { - QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); + QHostInfoLookupManager* manager = theHostInfoLookupManager(); if (manager) { manager->cache.setEnabled(e); } @@ -1093,7 +1144,7 @@ void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e) void qt_qhostinfo_cache_inject(const QString &hostname, const QHostInfo &resolution) { - QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); + QHostInfoLookupManager* manager = theHostInfoLookupManager(); if (!manager || !manager->cache.isEnabled()) return; @@ -1106,23 +1157,10 @@ void qt_qhostinfo_cache_inject(const QString &hostname, const QHostInfo &resolut QHostInfoCache::QHostInfoCache() : max_age(60), enabled(true), cache(128) { #ifdef QT_QHOSTINFO_CACHE_DISABLED_BY_DEFAULT - enabled = false; + enabled.store(false, std::memory_order_relaxed); #endif } -bool QHostInfoCache::isEnabled() -{ - return enabled; -} - -// this function is currently only used for the auto tests -// and not usable by public API -void QHostInfoCache::setEnabled(bool e) -{ - enabled = e; -} - - QHostInfo QHostInfoCache::get(const QString &name, bool *valid) { QMutexLocker locker(&this->mutex); @@ -1162,9 +1200,4 @@ void QHostInfoCache::clear() cache.clear(); } -QAbstractHostInfoLookupManager* QAbstractHostInfoLookupManager::globalInstance() -{ - return theHostInfoLookupManager(); -} - QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h index dc31cc08e43..cda286b4231 100644 --- a/src/network/kernel/qhostinfo.h +++ b/src/network/kernel/qhostinfo.h @@ -62,11 +62,12 @@ public: explicit QHostInfo(int lookupId = -1); QHostInfo(const QHostInfo &d); + QHostInfo(QHostInfo &&other) noexcept : d_ptr(qExchange(other.d_ptr, nullptr)) {} QHostInfo &operator=(const QHostInfo &d); QHostInfo &operator=(QHostInfo &&other) noexcept { swap(other); return *this; } ~QHostInfo(); - void swap(QHostInfo &other) noexcept { qSwap(d, other.d); } + void swap(QHostInfo &other) noexcept { qSwap(d_ptr, other.d_ptr); } QString hostName() const; void setHostName(const QString &name); @@ -147,7 +148,8 @@ public: #endif // Q_QDOC private: - QScopedPointer d; + QHostInfoPrivate *d_ptr; + Q_DECLARE_PRIVATE(QHostInfo) static int lookupHostImpl(const QString &name, const QObject *receiver, diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 7df3f5414c3..9a4657234ec 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -73,6 +73,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -83,12 +84,14 @@ class QHostInfoResult : public QObject QPointer receiver = nullptr; QtPrivate::QSlotObjectBase *slotObj = nullptr; + const bool withContextObject = false; public: QHostInfoResult() = default; QHostInfoResult(const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj) : receiver(receiver), - slotObj(slotObj) + slotObj(slotObj), + withContextObject(slotObj && receiver) { connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); @@ -96,10 +99,15 @@ public: moveToThread(receiver->thread()); } + void postResultsReady(const QHostInfo &info); + public Q_SLOTS: inline void emitResultsReady(const QHostInfo &info) { if (slotObj) { + // we used to have a context object, but it's already destroyed + if (withContextObject && !receiver) + return; QHostInfo copy = info; void *args[2] = { nullptr, reinterpret_cast(©) }; slotObj->call(const_cast(receiver.data()), args); @@ -177,10 +185,12 @@ public: void put(const QString &name, const QHostInfo &info); void clear(); - bool isEnabled(); - void setEnabled(bool e); + bool isEnabled() { return enabled.load(std::memory_order_relaxed); } + // this function is currently only used for the auto tests + // and not usable by public API + void setEnabled(bool e) { enabled.store(e, std::memory_order_relaxed); } private: - bool enabled; + std::atomic enabled; struct QHostInfoCacheElement { QHostInfo info; QElapsedTimer age; @@ -205,31 +215,13 @@ public: }; -class QAbstractHostInfoLookupManager : public QObject +class QHostInfoLookupManager { - Q_OBJECT - -public: - ~QAbstractHostInfoLookupManager() {} - virtual void clear() = 0; - - QHostInfoCache cache; - -protected: - QAbstractHostInfoLookupManager() {} - static QAbstractHostInfoLookupManager* globalInstance(); - -}; - -class QHostInfoLookupManager : public QAbstractHostInfoLookupManager -{ - Q_OBJECT public: QHostInfoLookupManager(); ~QHostInfoLookupManager(); - void clear() override; - void work(); + void clear(); // called from QHostInfo void scheduleLookup(QHostInfoRunnable *r); @@ -239,6 +231,8 @@ public: void lookupFinished(QHostInfoRunnable *r); bool wasAborted(int id); + QHostInfoCache cache; + friend class QHostInfoRunnable; protected: #if QT_CONFIG(thread) @@ -252,14 +246,12 @@ protected: #if QT_CONFIG(thread) QThreadPool threadPool; #endif - QRecursiveMutex mutex; + QMutex mutex; bool wasDeleted; -private slots: -#if QT_CONFIG(thread) - void waitForThreadPoolDone() { threadPool.waitForDone(); } -#endif +private: + void rescheduleWithMutexHeld(); }; QT_END_NAMESPACE diff --git a/src/network/kernel/qnetconmonitor_darwin.mm b/src/network/kernel/qnetconmonitor_darwin.mm index a64cd6e5307..f6daf9ed50c 100644 --- a/src/network/kernel/qnetconmonitor_darwin.mm +++ b/src/network/kernel/qnetconmonitor_darwin.mm @@ -376,7 +376,7 @@ bool QNetworkStatusMonitor::isMonitoring() const return d->ipv4Probe.isMonitoring() || d->ipv6Probe.isMonitoring(); } -bool QNetworkStatusMonitor::isNetworkAccesible() +bool QNetworkStatusMonitor::isNetworkAccessible() { // This function is to be executed on the thread that created // and uses 'this'. diff --git a/src/network/kernel/qnetconmonitor_p.h b/src/network/kernel/qnetconmonitor_p.h index 74ee56d422e..282bac50816 100644 --- a/src/network/kernel/qnetconmonitor_p.h +++ b/src/network/kernel/qnetconmonitor_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE class QNetworkConnectionMonitorPrivate; -class QNetworkConnectionMonitor : public QObject +class Q_AUTOTEST_EXPORT QNetworkConnectionMonitor : public QObject { Q_OBJECT @@ -91,7 +91,7 @@ private: }; class QNetworkStatusMonitorPrivate; -class QNetworkStatusMonitor : public QObject +class Q_AUTOTEST_EXPORT QNetworkStatusMonitor : public QObject { Q_OBJECT @@ -99,7 +99,7 @@ public: QNetworkStatusMonitor(); ~QNetworkStatusMonitor(); - bool isNetworkAccesible(); + bool isNetworkAccessible(); bool start(); void stop(); diff --git a/src/network/kernel/qnetconmonitor_stub.cpp b/src/network/kernel/qnetconmonitor_stub.cpp index 7f3a0c44c60..1ad4e9ba5a9 100644 --- a/src/network/kernel/qnetconmonitor_stub.cpp +++ b/src/network/kernel/qnetconmonitor_stub.cpp @@ -123,7 +123,7 @@ bool QNetworkStatusMonitor::isMonitoring() const return false; } -bool QNetworkStatusMonitor::isNetworkAccesible() +bool QNetworkStatusMonitor::isNetworkAccessible() { return false; } diff --git a/src/network/kernel/qnetconmonitor_win.cpp b/src/network/kernel/qnetconmonitor_win.cpp new file mode 100644 index 00000000000..b5435081699 --- /dev/null +++ b/src/network/kernel/qnetconmonitor_win.cpp @@ -0,0 +1,710 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnetconmonitor_p.h" + +#include "private/qobject_p.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +using namespace Microsoft::WRL; + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcNetMon, "qt.network.monitor"); + +namespace { +QString errorStringFromHResult(HRESULT hr) +{ + _com_error error(hr); + return QString::fromWCharArray(error.ErrorMessage()); +} + +template +bool QueryInterfaceImpl(IUnknown *from, REFIID riid, void **ppvObject) +{ + if (riid == __uuidof(T)) { + *ppvObject = static_cast(from); + from->AddRef(); + return true; + } + return false; +} + +QNetworkInterface getInterfaceFromHostAddress(const QHostAddress &local) +{ + QList interfaces = QNetworkInterface::allInterfaces(); + auto it = std::find_if( + interfaces.cbegin(), interfaces.cend(), [&local](const QNetworkInterface &iface) { + const auto &entries = iface.addressEntries(); + return std::any_of(entries.cbegin(), entries.cend(), + [&local](const QNetworkAddressEntry &entry) { + return entry.ip().isEqual(local, + QHostAddress::TolerantConversion); + }); + }); + if (it == interfaces.cend()) { + qCWarning(lcNetMon, "Could not find the interface for the local address."); + return {}; + } + return *it; +} +} // anonymous namespace + +class QNetworkConnectionEvents final : public INetworkConnectionEvents +{ +public: + QNetworkConnectionEvents(QNetworkConnectionMonitorPrivate *monitor); + ~QNetworkConnectionEvents(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override; + + ULONG STDMETHODCALLTYPE AddRef() override { return ++ref; } + ULONG STDMETHODCALLTYPE Release() override + { + if (--ref == 0) { + delete this; + return 0; + } + return ref; + } + + HRESULT STDMETHODCALLTYPE + NetworkConnectionConnectivityChanged(GUID connectionId, NLM_CONNECTIVITY connectivity) override; + HRESULT STDMETHODCALLTYPE NetworkConnectionPropertyChanged( + GUID connectionId, NLM_CONNECTION_PROPERTY_CHANGE flags) override; + + Q_REQUIRED_RESULT + bool setTarget(const QNetworkInterface &iface); + Q_REQUIRED_RESULT + bool startMonitoring(); + Q_REQUIRED_RESULT + bool stopMonitoring(); + +private: + ComPtr getNetworkConnectionFromAdapterGuid(QUuid guid); + + QUuid currentConnectionId{}; + + ComPtr networkListManager; + ComPtr connectionPoint; + + QNetworkConnectionMonitorPrivate *monitor = nullptr; + + QAtomicInteger ref = 1; // start at 1 for our own initial reference + DWORD cookie = 0; +}; + +class QNetworkConnectionMonitorPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QNetworkConnectionMonitor); + +public: + QNetworkConnectionMonitorPrivate(); + ~QNetworkConnectionMonitorPrivate(); + + Q_REQUIRED_RESULT + bool setTargets(const QHostAddress &local, const QHostAddress &remote); + Q_REQUIRED_RESULT + bool startMonitoring(); + void stopMonitoring(); + + void setConnectivity(NLM_CONNECTIVITY newConnectivity); + +private: + ComPtr connectionEvents; + // We can assume we have access to internet/subnet when this class is created because + // connection has already been established to the peer: + NLM_CONNECTIVITY connectivity = + NLM_CONNECTIVITY(NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET + | NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_SUBNET); + + bool sameSubnet = false; + bool monitoring = false; + bool comInitFailed = false; + bool remoteIsIPv6 = false; +}; + +QNetworkConnectionEvents::QNetworkConnectionEvents(QNetworkConnectionMonitorPrivate *monitor) + : monitor(monitor) +{ + auto hr = CoCreateInstance(CLSID_NetworkListManager, nullptr, CLSCTX_INPROC_SERVER, + IID_INetworkListManager, &networkListManager); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Could not get a NetworkListManager instance:" + << errorStringFromHResult(hr); + return; + } + + ComPtr connectionPointContainer; + hr = networkListManager.As(&connectionPointContainer); + if (SUCCEEDED(hr)) { + hr = connectionPointContainer->FindConnectionPoint(IID_INetworkConnectionEvents, + &connectionPoint); + } + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to get connection point for network events:" + << errorStringFromHResult(hr); + } +} + +QNetworkConnectionEvents::~QNetworkConnectionEvents() +{ + Q_ASSERT(ref == 0); +} + +ComPtr QNetworkConnectionEvents::getNetworkConnectionFromAdapterGuid(QUuid guid) +{ + ComPtr connections; + auto hr = networkListManager->GetNetworkConnections(connections.GetAddressOf()); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to enumerate network connections:" + << errorStringFromHResult(hr); + return nullptr; + } + ComPtr connection = nullptr; + do { + hr = connections->Next(1, connection.GetAddressOf(), nullptr); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to get next network connection in enumeration:" + << errorStringFromHResult(hr); + break; + } + if (connection) { + GUID adapterId; + hr = connection->GetAdapterId(&adapterId); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to get adapter ID from network connection:" + << errorStringFromHResult(hr); + continue; + } + if (guid == adapterId) + return connection; + } + } while (connection); + return nullptr; +} + +HRESULT STDMETHODCALLTYPE QNetworkConnectionEvents::QueryInterface(REFIID riid, void **ppvObject) +{ + if (!ppvObject) + return E_INVALIDARG; + + return QueryInterfaceImpl(this, riid, ppvObject) + || QueryInterfaceImpl(this, riid, ppvObject) + ? S_OK + : E_NOINTERFACE; +} + +HRESULT STDMETHODCALLTYPE QNetworkConnectionEvents::NetworkConnectionConnectivityChanged( + GUID connectionId, NLM_CONNECTIVITY newConnectivity) +{ + // This function is run on a different thread than 'monitor' is created on, so we need to run + // it on that thread + QMetaObject::invokeMethod(monitor->q_ptr, + [this, connectionId, newConnectivity, monitor = this->monitor]() { + if (connectionId == currentConnectionId) + monitor->setConnectivity(newConnectivity); + }, + Qt::QueuedConnection); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QNetworkConnectionEvents::NetworkConnectionPropertyChanged( + GUID connectionId, NLM_CONNECTION_PROPERTY_CHANGE flags) +{ + Q_UNUSED(connectionId); + Q_UNUSED(flags); + return E_NOTIMPL; +} + +bool QNetworkConnectionEvents::setTarget(const QNetworkInterface &iface) +{ + // Unset this in case it's already set to something + currentConnectionId = QUuid{}; + + NET_LUID luid; + if (ConvertInterfaceIndexToLuid(iface.index(), &luid) != NO_ERROR) { + qCWarning(lcNetMon, "Could not get the LUID for the interface."); + return false; + } + GUID guid; + if (ConvertInterfaceLuidToGuid(&luid, &guid) != NO_ERROR) { + qCWarning(lcNetMon, "Could not get the GUID for the interface."); + return false; + } + ComPtr connection = getNetworkConnectionFromAdapterGuid(guid); + if (!connection) { + qCWarning(lcNetMon, "Could not get the INetworkConnection instance for the adapter GUID."); + return false; + } + auto hr = connection->GetConnectionId(&guid); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to get the connection's GUID:" << errorStringFromHResult(hr); + return false; + } + currentConnectionId = guid; + + return true; +} + +bool QNetworkConnectionEvents::startMonitoring() +{ + if (currentConnectionId.isNull()) { + qCWarning(lcNetMon, "Can not start monitoring, set targets first"); + return false; + } + if (!connectionPoint) { + qCWarning(lcNetMon, + "We don't have the connection point, cannot start listening to events!"); + return false; + } + + auto hr = connectionPoint->Advise(this, &cookie); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to subscribe to network connectivity events:" + << errorStringFromHResult(hr); + return false; + } + return true; +} + +bool QNetworkConnectionEvents::stopMonitoring() +{ + auto hr = connectionPoint->Unadvise(cookie); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to unsubscribe from network connection events:" + << errorStringFromHResult(hr); + return false; + } + cookie = 0; + currentConnectionId = QUuid{}; + return true; +} + +QNetworkConnectionMonitorPrivate::QNetworkConnectionMonitorPrivate() +{ + auto hr = CoInitialize(nullptr); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to initialize COM:" << errorStringFromHResult(hr); + comInitFailed = true; + return; + } + + connectionEvents = new QNetworkConnectionEvents(this); +} + +QNetworkConnectionMonitorPrivate::~QNetworkConnectionMonitorPrivate() +{ + if (comInitFailed) + return; + connectionEvents.Reset(); + CoUninitialize(); +} + +bool QNetworkConnectionMonitorPrivate::setTargets(const QHostAddress &local, + const QHostAddress &remote) +{ + if (comInitFailed) + return false; + + QNetworkInterface iface = getInterfaceFromHostAddress(local); + if (!iface.isValid()) + return false; + const auto &addressEntries = iface.addressEntries(); + auto it = std::find_if( + addressEntries.cbegin(), addressEntries.cend(), + [&local](const QNetworkAddressEntry &entry) { return entry.ip() == local; }); + if (Q_UNLIKELY(it == addressEntries.cend())) { + qCWarning(lcNetMon, "The address entry we were working with disappeared"); + return false; + } + sameSubnet = remote.isInSubnet(local, it->prefixLength()); + remoteIsIPv6 = remote.protocol() == QAbstractSocket::IPv6Protocol; + + return connectionEvents->setTarget(iface); +} + +void QNetworkConnectionMonitorPrivate::setConnectivity(NLM_CONNECTIVITY newConnectivity) +{ + Q_Q(QNetworkConnectionMonitor); + const bool reachable = q->isReachable(); + connectivity = newConnectivity; + const bool newReachable = q->isReachable(); + if (reachable != newReachable) + emit q->reachabilityChanged(newReachable); +} + +bool QNetworkConnectionMonitorPrivate::startMonitoring() +{ + Q_ASSERT(connectionEvents); + Q_ASSERT(!monitoring); + if (connectionEvents->startMonitoring()) + monitoring = true; + return monitoring; +} + +void QNetworkConnectionMonitorPrivate::stopMonitoring() +{ + Q_ASSERT(connectionEvents); + Q_ASSERT(monitoring); + if (connectionEvents->stopMonitoring()) + monitoring = false; +} + +QNetworkConnectionMonitor::QNetworkConnectionMonitor() + : QObject(*new QNetworkConnectionMonitorPrivate) +{ +} + +QNetworkConnectionMonitor::QNetworkConnectionMonitor(const QHostAddress &local, + const QHostAddress &remote) + : QObject(*new QNetworkConnectionMonitorPrivate) +{ + setTargets(local, remote); +} + +QNetworkConnectionMonitor::~QNetworkConnectionMonitor() = default; + +bool QNetworkConnectionMonitor::setTargets(const QHostAddress &local, const QHostAddress &remote) +{ + if (isMonitoring()) { + qCWarning(lcNetMon, "Monitor is already active, call stopMonitoring() first"); + return false; + } + if (local.isNull()) { + qCWarning(lcNetMon, "Invalid (null) local address, cannot create a reachability target"); + return false; + } + // Silently return false for loopback addresses instead of printing warnings later + if (remote.isLoopback()) + return false; + + return d_func()->setTargets(local, remote); +} + +bool QNetworkConnectionMonitor::startMonitoring() +{ + Q_D(QNetworkConnectionMonitor); + if (isMonitoring()) { + qCWarning(lcNetMon, "Monitor is already active, call stopMonitoring() first"); + return false; + } + return d->startMonitoring(); +} + +bool QNetworkConnectionMonitor::isMonitoring() const +{ + return d_func()->monitoring; +} + +void QNetworkConnectionMonitor::stopMonitoring() +{ + Q_D(QNetworkConnectionMonitor); + if (!isMonitoring()) { + qCWarning(lcNetMon, "stopMonitoring was called when not monitoring!"); + return; + } + d->stopMonitoring(); +} + +bool QNetworkConnectionMonitor::isReachable() +{ + Q_D(QNetworkConnectionMonitor); + NLM_CONNECTIVITY required = d->sameSubnet + ? (d->remoteIsIPv6 ? NLM_CONNECTIVITY_IPV6_SUBNET : NLM_CONNECTIVITY_IPV4_SUBNET) + : (d->remoteIsIPv6 ? NLM_CONNECTIVITY_IPV6_INTERNET : NLM_CONNECTIVITY_IPV4_INTERNET); + return d_func()->connectivity & required; +} + +class QNetworkListManagerEvents final : public INetworkListManagerEvents +{ +public: + QNetworkListManagerEvents(QNetworkStatusMonitorPrivate *monitor); + ~QNetworkListManagerEvents(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override; + + ULONG STDMETHODCALLTYPE AddRef() override { return ++ref; } + ULONG STDMETHODCALLTYPE Release() override + { + if (--ref == 0) { + delete this; + return 0; + } + return ref; + } + + HRESULT STDMETHODCALLTYPE ConnectivityChanged(NLM_CONNECTIVITY newConnectivity) override; + + Q_REQUIRED_RESULT + bool start(); + Q_REQUIRED_RESULT + bool stop(); + +private: + ComPtr networkListManager = nullptr; + ComPtr connectionPoint = nullptr; + + QNetworkStatusMonitorPrivate *monitor = nullptr; + + QAtomicInteger ref = 1; // start at 1 for our own initial reference + DWORD cookie = 0; +}; + +class QNetworkStatusMonitorPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QNetworkStatusMonitor); + +public: + QNetworkStatusMonitorPrivate(); + ~QNetworkStatusMonitorPrivate(); + + Q_REQUIRED_RESULT + bool start(); + void stop(); + + void setConnectivity(NLM_CONNECTIVITY newConnectivity); + +private: + friend class QNetworkListManagerEvents; + + ComPtr managerEvents; + NLM_CONNECTIVITY connectivity = NLM_CONNECTIVITY_DISCONNECTED; + + bool monitoring = false; + bool comInitFailed = false; +}; + +QNetworkListManagerEvents::QNetworkListManagerEvents(QNetworkStatusMonitorPrivate *monitor) + : monitor(monitor) +{ + auto hr = CoCreateInstance(CLSID_NetworkListManager, nullptr, CLSCTX_INPROC_SERVER, + IID_INetworkListManager, &networkListManager); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Could not get a NetworkListManager instance:" + << errorStringFromHResult(hr); + return; + } + + // Set initial connectivity + hr = networkListManager->GetConnectivity(&monitor->connectivity); + if (FAILED(hr)) + qCWarning(lcNetMon) << "Could not get connectivity:" << errorStringFromHResult(hr); + + ComPtr connectionPointContainer; + hr = networkListManager.As(&connectionPointContainer); + if (SUCCEEDED(hr)) { + hr = connectionPointContainer->FindConnectionPoint(IID_INetworkListManagerEvents, + &connectionPoint); + } + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to get connection point for network list manager events:" + << errorStringFromHResult(hr); + } +} + +QNetworkListManagerEvents::~QNetworkListManagerEvents() +{ + Q_ASSERT(ref == 0); +} + +HRESULT STDMETHODCALLTYPE QNetworkListManagerEvents::QueryInterface(REFIID riid, void **ppvObject) +{ + if (!ppvObject) + return E_INVALIDARG; + + return QueryInterfaceImpl(this, riid, ppvObject) + || QueryInterfaceImpl(this, riid, ppvObject) + ? S_OK + : E_NOINTERFACE; +} + +HRESULT STDMETHODCALLTYPE +QNetworkListManagerEvents::ConnectivityChanged(NLM_CONNECTIVITY newConnectivity) +{ + // This function is run on a different thread than 'monitor' is created on, so we need to run + // it on that thread + QMetaObject::invokeMethod(monitor->q_ptr, + [newConnectivity, monitor = this->monitor]() { + monitor->setConnectivity(newConnectivity); + }, + Qt::QueuedConnection); + return S_OK; +} + +bool QNetworkListManagerEvents::start() +{ + if (!connectionPoint) { + qCWarning(lcNetMon, "Initialization failed, can't start!"); + return false; + } + auto hr = connectionPoint->Advise(this, &cookie); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to subscribe to network connectivity events:" + << errorStringFromHResult(hr); + return false; + } + return true; +} + +bool QNetworkListManagerEvents::stop() +{ + Q_ASSERT(connectionPoint); + auto hr = connectionPoint->Unadvise(cookie); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to unsubscribe from network connectivity events:" + << errorStringFromHResult(hr); + return false; + } + cookie = 0; + return true; +} + +QNetworkStatusMonitorPrivate::QNetworkStatusMonitorPrivate() +{ + auto hr = CoInitialize(nullptr); + if (FAILED(hr)) { + qCWarning(lcNetMon) << "Failed to initialize COM:" << errorStringFromHResult(hr); + comInitFailed = true; + return; + } + managerEvents = new QNetworkListManagerEvents(this); +} + +QNetworkStatusMonitorPrivate::~QNetworkStatusMonitorPrivate() +{ + if (comInitFailed) + return; + if (monitoring) + stop(); + managerEvents.Reset(); + CoUninitialize(); +} + +void QNetworkStatusMonitorPrivate::setConnectivity(NLM_CONNECTIVITY newConnectivity) +{ + Q_Q(QNetworkStatusMonitor); + + const bool oldAccessibility = q->isNetworkAccessible(); + connectivity = newConnectivity; + const bool accessibility = q->isNetworkAccessible(); + if (oldAccessibility != accessibility) + emit q->onlineStateChanged(accessibility); +} + +bool QNetworkStatusMonitorPrivate::start() +{ + if (comInitFailed) + return false; + Q_ASSERT(managerEvents); + Q_ASSERT(!monitoring); + if (managerEvents->start()) + monitoring = true; + return monitoring; +} + +void QNetworkStatusMonitorPrivate::stop() +{ + Q_ASSERT(managerEvents); + Q_ASSERT(monitoring); + if (managerEvents->stop()) + monitoring = false; +} + +QNetworkStatusMonitor::QNetworkStatusMonitor() : QObject(*new QNetworkStatusMonitorPrivate) {} + +QNetworkStatusMonitor::~QNetworkStatusMonitor() {} + +bool QNetworkStatusMonitor::start() +{ + if (isMonitoring()) { + qCWarning(lcNetMon, "Monitor is already active, call stopMonitoring() first"); + return false; + } + + return d_func()->start(); +} + +void QNetworkStatusMonitor::stop() +{ + if (!isMonitoring()) { + qCWarning(lcNetMon, "stopMonitoring was called when not monitoring!"); + return; + } + + d_func()->stop(); +} + +bool QNetworkStatusMonitor::isMonitoring() const +{ + return d_func()->monitoring; +} + +bool QNetworkStatusMonitor::isNetworkAccessible() +{ + return d_func()->connectivity + & (NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET + | NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_SUBNET); +} + +bool QNetworkStatusMonitor::isEnabled() +{ + return true; +} + +void QNetworkStatusMonitor::reachabilityChanged(bool online) +{ + Q_UNUSED(online); + Q_UNREACHABLE(); +} + +QT_END_NAMESPACE diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 6be1e9443e8..2244955c55a 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -627,7 +627,7 @@ void QHttpSocketEngine::slotSocketReadNotification() // from http spec is also allowed. if (proxyConnectionHeader.isEmpty()) proxyConnectionHeader = d->reply->headerField("Connection"); - if (proxyConnectionHeader.compare("close", Qt::CaseSensitive) == 0) { + if (proxyConnectionHeader.compare("close", Qt::CaseInsensitive) == 0) { willClose = true; } else if (proxyConnectionHeader.compare("keep-alive", Qt::CaseInsensitive) == 0) { willClose = false; diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 24c17124dca..3ca586e2478 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -1000,8 +1000,11 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS // parse the ancillary data struct cmsghdr *cmsgptr; + QT_WARNING_PUSH + QT_WARNING_DISABLE_CLANG("-Wsign-compare") for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { + QT_WARNING_POP if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in6_pktinfo))) { in6_pktinfo *info = reinterpret_cast(CMSG_DATA(cmsgptr)); diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index b429b3c3658..9edabd7822f 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -623,6 +623,53 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() } +static void setErrorFromWSAError(int error, QNativeSocketEnginePrivate *d) +{ + Q_ASSERT(d); + switch (error) { + case WSAEISCONN: + d->socketState = QAbstractSocket::ConnectedState; + break; + case WSAEHOSTUNREACH: + d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::HostUnreachableErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + break; + case WSAEADDRNOTAVAIL: + d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::AddressNotAvailableErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + break; + case WSAEINPROGRESS: + d->setError(QAbstractSocket::UnfinishedSocketOperationError, QNativeSocketEnginePrivate::InvalidSocketErrorString); + d->socketState = QAbstractSocket::ConnectingState; + break; + case WSAEADDRINUSE: + d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::AddressInuseErrorString); + break; + case WSAECONNREFUSED: + d->setError(QAbstractSocket::ConnectionRefusedError, QNativeSocketEnginePrivate::ConnectionRefusedErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + break; + case WSAETIMEDOUT: + d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::ConnectionTimeOutErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + break; + case WSAEACCES: + d->setError(QAbstractSocket::SocketAccessError, QNativeSocketEnginePrivate::AccessErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + break; + case WSAENETUNREACH: + d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::NetworkUnreachableErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + break; + case WSAEINVAL: + case WSAEALREADY: + d->setError(QAbstractSocket::UnfinishedSocketOperationError, QNativeSocketEnginePrivate::InvalidSocketErrorString); + break; + default: + break; + } +} + bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quint16 port) { @@ -651,9 +698,6 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin case WSANOTINITIALISED: //### break; - case WSAEISCONN: - socketState = QAbstractSocket::ConnectedState; - break; case WSAEWOULDBLOCK: { // If WSAConnect returns WSAEWOULDBLOCK on the second // connection attempt, we have to check SO_ERROR's @@ -668,82 +712,33 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin do { if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) { if (value != NOERROR) { + WS_ERROR_DEBUG(value); + errorDetected = true; // MSDN says getsockopt with SO_ERROR clears the error, but it's not actually cleared // and this can affect all subsequent WSAConnect attempts, so clear it now. const int val = NO_ERROR; ::setsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, reinterpret_cast(&val), sizeof val); - } - - if (value == WSAECONNREFUSED) { - setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); - socketState = QAbstractSocket::UnconnectedState; - errorDetected = true; - break; - } - if (value == WSAETIMEDOUT) { - setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); - socketState = QAbstractSocket::UnconnectedState; - errorDetected = true; - break; - } - if (value == WSAEHOSTUNREACH) { - setError(QAbstractSocket::NetworkError, HostUnreachableErrorString); - socketState = QAbstractSocket::UnconnectedState; - errorDetected = true; - break; - } - if (value == WSAEADDRNOTAVAIL) { - setError(QAbstractSocket::NetworkError, AddressNotAvailableErrorString); - socketState = QAbstractSocket::UnconnectedState; - errorDetected = true; - break; - } - if (value == NOERROR) { + } else { // When we get WSAEWOULDBLOCK the outcome was not known, so a // NOERROR might indicate that the result of the operation // is still unknown. We try again to increase the chance that we did // get the correct result. tryAgain = !tryAgain; } + setErrorFromWSAError(value, this); } tries++; } while (tryAgain && (tries < 2)); if (errorDetected) break; + // fall through to unfinished operation error handling + err = WSAEINPROGRESS; Q_FALLTHROUGH(); } - case WSAEINPROGRESS: - setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString); - socketState = QAbstractSocket::ConnectingState; - break; - case WSAEADDRINUSE: - setError(QAbstractSocket::NetworkError, AddressInuseErrorString); - break; - case WSAECONNREFUSED: - setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); - socketState = QAbstractSocket::UnconnectedState; - break; - case WSAETIMEDOUT: - setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); - break; - case WSAEACCES: - setError(QAbstractSocket::SocketAccessError, AccessErrorString); - socketState = QAbstractSocket::UnconnectedState; - break; - case WSAEHOSTUNREACH: - setError(QAbstractSocket::NetworkError, HostUnreachableErrorString); - socketState = QAbstractSocket::UnconnectedState; - break; - case WSAENETUNREACH: - setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString); - socketState = QAbstractSocket::UnconnectedState; - break; - case WSAEINVAL: - case WSAEALREADY: - setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString); - break; + default: + setErrorFromWSAError(err, this); break; } if (socketState != QAbstractSocket::ConnectedState) { diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp index 806c6426e49..6f1fb26add2 100644 --- a/src/network/ssl/qsslcertificate_openssl.cpp +++ b/src/network/ssl/qsslcertificate_openssl.cpp @@ -45,12 +45,19 @@ #include "qsslcertificateextension_p.h" #include +#include -#if QT_CONFIG(thread) -#include -#endif QT_BEGIN_NAMESPACE +Q_CONSTEXPR int MutexPoolSize = 17; +static QBasicMutex mutexPool[MutexPoolSize]; +namespace QMutexPool { + static QBasicMutex *globalInstanceGet(const void *addr) + { + return mutexPool + (quintptr(addr) % MutexPoolSize); + } +} + // forward declaration static QMultiMap _q_mapFromX509Name(X509_NAME *name); diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 487e975db69..1725937bc28 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -215,7 +215,7 @@ void QSecureTransportContext::reset(SSLContextRef newContext) context = newContext; } -Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_securetransport_mutex, (QMutex::Recursive)) +Q_GLOBAL_STATIC(QRecursiveMutex, qt_securetransport_mutex) //#define QSSLSOCKET_DEBUG diff --git a/src/network/ssl/qsslsocket_openssl11.cpp b/src/network/ssl/qsslsocket_openssl11.cpp index cc2d6ea2d9e..28be4f2e792 100644 --- a/src/network/ssl/qsslsocket_openssl11.cpp +++ b/src/network/ssl/qsslsocket_openssl11.cpp @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE -Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_opensslInitMutex, (QMutex::Recursive)) +Q_GLOBAL_STATIC(QRecursiveMutex, qt_opensslInitMutex) void QSslSocketPrivate::deinitialize() { diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 2eb9763e906..1fcfdf9f169 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -63,13 +63,11 @@ # include #endif #include -#if QT_CONFIG(thread) -#include -#endif #include #if defined(Q_OS_UNIX) #include #endif +#include #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) #include #endif @@ -599,8 +597,8 @@ DEFINEFUNC2(PKCS12 *, d2i_PKCS12_bio, BIO *bio, bio, PKCS12 **pkcs12, pkcs12, re DEFINEFUNC(void, PKCS12_free, PKCS12 *pkcs12, pkcs12, return, DUMMYARG) #define RESOLVEFUNC(func) \ - if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func))) \ - && !(_q_##func = _q_PTR_##func(libs.second->resolve(#func)))) \ + if (!(_q_##func = _q_PTR_##func(libs.ssl->resolve(#func))) \ + && !(_q_##func = _q_PTR_##func(libs.crypto->resolve(#func)))) \ qsslSocketCannotResolveSymbolWarning(#func); #if !defined QT_LINKED_OPENSSL @@ -736,34 +734,31 @@ static QStringList findAllLibCrypto() # endif #ifdef Q_OS_WIN -static bool tryToLoadOpenSslWin32Library(QLatin1String ssleay32LibName, QLatin1String libeay32LibName, QPair &pair) + +struct LoadedOpenSsl { + std::unique_ptr ssl, crypto; +}; + +static bool tryToLoadOpenSslWin32Library(QLatin1String ssleay32LibName, QLatin1String libeay32LibName, LoadedOpenSsl &result) { - pair.first = 0; - pair.second = 0; - - QSystemLibrary *ssleay32 = new QSystemLibrary(ssleay32LibName); + auto ssleay32 = qt_make_unique(ssleay32LibName); if (!ssleay32->load(false)) { - delete ssleay32; return FALSE; } - QSystemLibrary *libeay32 = new QSystemLibrary(libeay32LibName); + auto libeay32 = qt_make_unique(libeay32LibName); if (!libeay32->load(false)) { - delete ssleay32; - delete libeay32; return FALSE; } - pair.first = ssleay32; - pair.second = libeay32; + result.ssl = std::move(ssleay32); + result.crypto = std::move(libeay32); return TRUE; } -static QPair loadOpenSslWin32() +static LoadedOpenSsl loadOpenSsl() { - QPair pair; - pair.first = 0; - pair.second = 0; + LoadedOpenSsl result; #if QT_CONFIG(opensslv11) // With OpenSSL 1.1 the names have changed to libssl-1_1(-x64) and libcrypto-1_1(-x64), for builds using @@ -776,7 +771,7 @@ static QPair loadOpenSslWin32() #endif // !Q_PROCESSOR_x86_64 tryToLoadOpenSslWin32Library(QLatin1String("libssl-1_1" QT_SSL_SUFFIX), - QLatin1String("libcrypto-1_1" QT_SSL_SUFFIX), pair); + QLatin1String("libcrypto-1_1" QT_SSL_SUFFIX), result); #undef QT_SSL_SUFFIX @@ -785,28 +780,30 @@ static QPair loadOpenSslWin32() // When OpenSSL is built using MSVC then the libraries are named 'ssleay32.dll' and 'libeay32'dll'. // When OpenSSL is built using GCC then different library names are used (depending on the OpenSSL version) // The oldest version of a GCC-based OpenSSL which can be detected by the code below is 0.9.8g (released in 2007) - if (!tryToLoadOpenSslWin32Library(QLatin1String("ssleay32"), QLatin1String("libeay32"), pair)) { - if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-10"), QLatin1String("libcrypto-10"), pair)) { - if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-8"), QLatin1String("libcrypto-8"), pair)) { - tryToLoadOpenSslWin32Library(QLatin1String("libssl-7"), QLatin1String("libcrypto-7"), pair); + if (!tryToLoadOpenSslWin32Library(QLatin1String("ssleay32"), QLatin1String("libeay32"), result)) { + if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-10"), QLatin1String("libcrypto-10"), result)) { + if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-8"), QLatin1String("libcrypto-8"), result)) { + tryToLoadOpenSslWin32Library(QLatin1String("libssl-7"), QLatin1String("libcrypto-7"), result); } } } #endif // !QT_CONFIG(opensslv11) - return pair; + return result; } #else -static QPair loadOpenSsl() +struct LoadedOpenSsl { + std::unique_ptr ssl, crypto; +}; + +static LoadedOpenSsl loadOpenSsl() { - QPair pair; + LoadedOpenSsl result = {qt_make_unique(), qt_make_unique()}; # if defined(Q_OS_UNIX) - QLibrary *&libssl = pair.first; - QLibrary *&libcrypto = pair.second; - libssl = new QLibrary; - libcrypto = new QLibrary; + QLibrary * const libssl = result.ssl.get(); + QLibrary * const libcrypto = result.crypto.get(); // Try to find the libssl library on the system. // @@ -850,7 +847,7 @@ static QPair loadOpenSsl() libcrypto->setFileNameAndVersion(QLatin1String("crypto"), QLatin1String(SHLIB_VERSION_NUMBER)); if (libcrypto->load() && libssl->load()) { // libssl.so. and libcrypto.so. found - return pair; + return result; } else { libssl->unload(); libcrypto->unload(); @@ -869,7 +866,7 @@ static QPair loadOpenSsl() libssl->setFileNameAndVersion(QLatin1String("ssl"), fallbackSoname); libcrypto->setFileNameAndVersion(QLatin1String("crypto"), fallbackSoname); if (libcrypto->load() && libssl->load()) { - return pair; + return result; } else { libssl->unload(); libcrypto->unload(); @@ -885,11 +882,28 @@ static QPair loadOpenSsl() // macOS's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third // attempt, _after_ /Contents/Frameworks has been searched. // iOS does not ship a system libssl.dylib, libcrypto.dylib in the first place. +# if defined(Q_OS_ANDROID) + // OpenSSL 1.1.x must be suffixed otherwise it will use the system libcrypto.so libssl.so which on API-21 are OpenSSL 1.0 not 1.1 + auto openSSLSuffix = [](const QByteArray &defaultSuffix = {}) { + auto suffix = qgetenv("ANDROID_OPENSSL_SUFFIX"); + if (suffix.isEmpty()) + return defaultSuffix; + return suffix; + }; +# if QT_CONFIG(opensslv11) + static QString suffix = QString::fromLatin1(openSSLSuffix("_1_1")); +# else + static QString suffix = QString::fromLatin1(openSSLSuffix()); +# endif + libssl->setFileNameAndVersion(QLatin1String("ssl") + suffix, -1); + libcrypto->setFileNameAndVersion(QLatin1String("crypto") + suffix, -1); +# else libssl->setFileNameAndVersion(QLatin1String("ssl"), -1); libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1); +# endif if (libcrypto->load() && libssl->load()) { // libssl.so.0 and libcrypto.so.0 found - return pair; + return result; } else { libssl->unload(); libcrypto->unload(); @@ -914,7 +928,7 @@ static QPair loadOpenSsl() if (libssl->load()) { // libssl.so.x and libcrypto.so.x found - return pair; + return result; } else { libssl->unload(); } @@ -924,41 +938,33 @@ static QPair loadOpenSsl() } // failed to load anything - delete libssl; - delete libcrypto; - libssl = libcrypto = 0; - return pair; + result = {}; + return result; # else // not implemented for this platform yet - return pair; + return result; # endif } #endif +static QBasicMutex symbolResolveMutex; +static QBasicAtomicInt symbolsResolved = Q_BASIC_ATOMIC_INITIALIZER(false); +static bool triedToResolveSymbols = false; + bool q_resolveOpenSslSymbols() { - static bool symbolsResolved = false; - static bool triedToResolveSymbols = false; -#if QT_CONFIG(thread) -#if QT_CONFIG(opensslv11) - QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_OPENSSL_init_ssl)); -#else - QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_SSL_library_init)); -#endif -#endif - if (symbolsResolved) + if (symbolsResolved.loadAcquire()) + return true; + QMutexLocker locker(&symbolResolveMutex); + if (symbolsResolved.loadRelaxed()) return true; if (triedToResolveSymbols) return false; triedToResolveSymbols = true; -#ifdef Q_OS_WIN - QPair libs = loadOpenSslWin32(); -#else - QPair libs = loadOpenSsl(); -#endif - if (!libs.first || !libs.second) + LoadedOpenSsl libs = loadOpenSsl(); + if (!libs.ssl || !libs.crypto) // failed to load them return false; @@ -1007,8 +1013,6 @@ bool q_resolveOpenSslSymbols() if (!_q_OpenSSL_version) { // Apparently, we were built with OpenSSL 1.1 enabled but are now using // a wrong library. - delete libs.first; - delete libs.second; qCWarning(lcSsl, "Incompatible version of OpenSSL"); return false; } @@ -1130,8 +1134,6 @@ bool q_resolveOpenSslSymbols() // OpenSSL 1.1 has deprecated and removed SSLeay. We consider a failure to // resolve this symbol as a failure to resolve symbols. // The right operand of '||' above is ... a bit of paranoia. - delete libs.first; - delete libs.second; qCWarning(lcSsl, "Incompatible version of OpenSSL"); return false; } @@ -1402,9 +1404,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(d2i_PKCS12_bio) RESOLVEFUNC(PKCS12_free) - symbolsResolved = true; - delete libs.first; - delete libs.second; + symbolsResolved.storeRelease(true); return true; } #endif // QT_CONFIG(library) diff --git a/src/network/ssl/qsslsocket_schannel.cpp b/src/network/ssl/qsslsocket_schannel.cpp index 1314b432a4b..c254659a33f 100644 --- a/src/network/ssl/qsslsocket_schannel.cpp +++ b/src/network/ssl/qsslsocket_schannel.cpp @@ -431,7 +431,7 @@ QByteArray createAlpnString(const QByteArrayList &nextAllowedProtocols) bool QSslSocketPrivate::s_loadRootCertsOnDemand = true; bool QSslSocketPrivate::s_loadedCiphersAndCerts = false; -Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_schannel_mutex, (QMutex::Recursive)) +Q_GLOBAL_STATIC(QRecursiveMutex, qt_schannel_mutex) void QSslSocketPrivate::ensureInitialized() { diff --git a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h index 31a79dbc6c9..c3d30702102 100644 --- a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h +++ b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h @@ -131,12 +131,6 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer); #endif -#ifndef EGL_EXT_stream_acquire_mode -#define EGL_EXT_stream_acquire_mode 1 -#define EGL_CONSUMER_AUTO_ACQUIRE_EXT 0x332B -#define EGL_RESOURCE_BUSY_EXT 0x3353 -#endif - #ifndef EGL_EXT_platform_device #define EGL_PLATFORM_DEVICE_EXT 0x313F #endif @@ -162,11 +156,6 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC) (EGLDi typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); #endif -#ifndef EGL_NV_output_drm_flip_event -#define EGL_NV_output_drm_flip_event 1 -#define EGL_DRM_FLIP_EVENT_DATA_NV 0x333E -#endif - QT_BEGIN_NAMESPACE class QEGLStreamConvenience diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index e28b40c2401..7abf2957820 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -927,66 +927,38 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef antialias = antialiasingEnabled - 1; } - // try to find a match for fid - const QFontEngine::FaceId fid = engine->faceId(); - FcPattern *pattern = FcPatternCreate(); - FcPattern *match = nullptr; - - // try a trivial match by filename - FC_FILE is highest priority, so if it matches, FcFontMatch - // will just find the file (fine) and spend a millisecond or so doing unnecessary work (bad). - if (!fid.filename.isEmpty() && QFile::exists(QString::fromUtf8(fid.filename))) { - FcBlanks *blanks = FcConfigGetBlanks(nullptr); - int count = 0; - FcPattern *fileMatch = FcFreeTypeQuery((const FcChar8 *)fid.filename.data(), fid.index, - blanks, &count); - if (fileMatch) { - // Apply Fontconfig configuration - FcFreeTypeQuery only returns information stored in - // the font file, we also want to respect system and user settings. - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - match = FcFontRenderPrepare(0, pattern, fileMatch); - FcPatternDestroy(fileMatch); - } - } - - if (!match) { - FcValue value; - - // Fontconfig rules might process this information for arbitrary purposes, so add it, - // even though we already know that it doesn't match an existing file. - if (!fid.filename.isEmpty()) { - value.type = FcTypeString; - value.u.s = (const FcChar8 *)fid.filename.data(); - FcPatternAdd(pattern, FC_FILE, value, true); - - value.type = FcTypeInteger; - value.u.i = fid.index; - FcPatternAdd(pattern, FC_INDEX, value, true); - } - - const QByteArray cs = fontDef.family.toUtf8(); - value.type = FcTypeString; - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAdd(pattern, FC_FAMILY, value, true); - - if (fontDef.pixelSize > 0.1) { - value.type = FcTypeDouble; - value.u.d = fontDef.pixelSize; - FcPatternAdd(pattern, FC_PIXEL_SIZE, value, true); - } - - FcResult result; - - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - match = FcFontMatch(0, pattern, &result); - } - QFontEngine::GlyphFormat format; + // try and get the pattern + FcPattern *pattern = FcPatternCreate(); + + FcValue value; + value.type = FcTypeString; + QByteArray cs = fontDef.family.toUtf8(); + value.u.s = (const FcChar8 *)cs.data(); + FcPatternAdd(pattern,FC_FAMILY,value,true); + + QFontEngine::FaceId fid = engine->faceId(); + + if (!fid.filename.isEmpty()) { + value.u.s = (const FcChar8 *)fid.filename.data(); + FcPatternAdd(pattern,FC_FILE,value,true); + + value.type = FcTypeInteger; + value.u.i = fid.index; + FcPatternAdd(pattern,FC_INDEX,value,true); + } + + if (fontDef.pixelSize > 0.1) + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize); + + FcResult result; + + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + + FcPattern *match = FcFontMatch(0, pattern, &result); if (match) { - engine->setDefaultHintStyle(defaultHintStyleFromMatch( - (QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf)); + engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf)); FcBool fc_autohint; if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch) diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp index 8d0a20f7b9f..b608e7f4832 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp @@ -1929,8 +1929,10 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, co return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t); } -QImage QFontEngineFT::bitmapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t) +QImage QFontEngineFT::bitmapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t, const QColor &color) { + Q_UNUSED(color); + Glyph *glyph = loadGlyphFor(g, subPixelPosition, defaultFormat, t); if (glyph == nullptr) return QImage(); diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h index 2765db29469..b636c42e63e 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h @@ -236,7 +236,7 @@ private: QImage alphaMapForGlyph(glyph_t, QFixed) override; QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override; QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override; - QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override; + QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override; glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 25e7c6df72b..072dd1a28a8 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -747,7 +747,7 @@ qreal QCoreTextFontEngine::fontSmoothingGamma() return 2.0; } -QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix) +QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, const QColor &color) { glyph_metrics_t br = alphaMapBoundingBox(glyph, subPixelPosition, matrix, glyphFormat); @@ -827,6 +827,8 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition CTFontDrawGlyphs(ctfont, &cgGlyph, &CGPointZero, 1, ctx); } } else { + CGContextSetRGBFillColor(ctx, color.redF(), color.greenF(), color.blueF(), color.alphaF()); + // CGContextSetTextMatrix does not work with color glyphs, so we use // the CTM instead. This means we must translate the CTM as well, to // set the glyph position, instead of using CGContextSetTextPosition. @@ -884,12 +886,12 @@ QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPo return imageForGlyph(glyph, subPixelPosition, x); } -QImage QCoreTextFontEngine::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) +QImage QCoreTextFontEngine::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t, const QColor &color) { if (t.type() > QTransform::TxScale) - return QFontEngine::bitmapForGlyph(glyph, subPixelPosition, t); + return QFontEngine::bitmapForGlyph(glyph, subPixelPosition, t, color); - return imageForGlyph(glyph, subPixelPosition, t); + return imageForGlyph(glyph, subPixelPosition, t, color); } void QCoreTextFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 4064507058e..51d839688d5 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -110,7 +110,7 @@ public: QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override; QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override; glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) override; - QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override; + QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override; QFixed emSquareSize() const override; void doKerning(QGlyphLayout *g, ShaperFlags flags) const override; @@ -137,7 +137,7 @@ public: protected: QCoreTextFontEngine(const QFontDef &def); void init(); - QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &m); + QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &m, const QColor &color = QColor()); void loadAdvancesForGlyphs(QVarLengthArray &cgGlyphs, QGlyphLayout *glyphs) const; bool hasColorGlyphs() const; bool shouldAntialias() const; diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp index 60a5896e7b9..a4490a66643 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp @@ -650,7 +650,8 @@ bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, - const QTransform &originalTransform) + const QTransform &originalTransform, + const QColor &color) { UINT16 glyphIndex = t; FLOAT glyphAdvance = 0; @@ -735,6 +736,7 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, #if defined(QT_USE_DIRECTWRITE2) BOOL ok = true; + if (SUCCEEDED(hr)) { while (SUCCEEDED(hr) && ok) { const DWRITE_COLOR_GLYPH_RUN *colorGlyphRun = 0; @@ -759,10 +761,18 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, break; } - float r = qBound(0.0f, colorGlyphRun->runColor.r, 1.0f); - float g = qBound(0.0f, colorGlyphRun->runColor.g, 1.0f); - float b = qBound(0.0f, colorGlyphRun->runColor.b, 1.0f); - float a = qBound(0.0f, colorGlyphRun->runColor.a, 1.0f); + float r, g, b, a; + if (colorGlyphRun->paletteIndex == 0xFFFF) { + r = float(color.redF()); + g = float(color.greenF()); + b = float(color.blueF()); + a = float(color.alphaF()); + } else { + r = qBound(0.0f, colorGlyphRun->runColor.r, 1.0f); + g = qBound(0.0f, colorGlyphRun->runColor.g, 1.0f); + b = qBound(0.0f, colorGlyphRun->runColor.b, 1.0f); + a = qBound(0.0f, colorGlyphRun->runColor.a, 1.0f); + } if (!qFuzzyIsNull(a)) { renderGlyphRun(&image, @@ -784,11 +794,21 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, } else #endif { + float r, g, b, a; + if (glyphFormat == QFontEngine::Format_ARGB) { + r = float(color.redF()); + g = float(color.greenF()); + b = float(color.blueF()); + a = float(color.alphaF()); + } else { + r = g = b = a = 0.0; + } + renderGlyphRun(&image, - 0.0, - 0.0, - 0.0, - 1.0, + r, + g, + b, + a, glyphAnalysis, boundingRect); } @@ -1001,9 +1021,9 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph } } -QImage QWindowsFontEngineDirectWrite::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) +QImage QWindowsFontEngineDirectWrite::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t, const QColor &color) { - return imageForGlyph(glyph, subPixelPosition, glyphMargin(QFontEngine::Format_A32), t); + return imageForGlyph(glyph, subPixelPosition, glyphMargin(QFontEngine::Format_A32), t, color); } QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h index 3eaf8cf3d81..c8c6b83bf90 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h @@ -112,7 +112,7 @@ public: QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) override; QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override; QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) override; - QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override; + QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override; QFontEngine *cloneWithSize(qreal pixelSize) const override; Qt::HANDLE handle() const override; @@ -126,7 +126,7 @@ public: void setUniqueFamilyName(const QString &newName) { m_uniqueFamilyName = newName; } private: - QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform); + QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform, const QColor &color = QColor()); void collectMetrics(); void renderGlyphRun(QImage *destination, float r, float g, float b, float a, IDWriteGlyphRunAnalysis *glyphAnalysis, const QRect &boundingRect); static QString filenameFromFontFile(IDWriteFontFile *fontFile); diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp index bff4a2522c9..3555763b899 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp @@ -231,7 +231,7 @@ void QEvdevKeyboardHandler::processKeyEvent(int nativecode, int unicode, int qtc QWindowSystemInterface::handleExtendedKeyEvent(0, (isPress ? QEvent::KeyPress : QEvent::KeyRelease), qtcode, modifiers, nativecode + 8, 0, int(modifiers), - (unicode != 0xffff ) ? QString(unicode) : QString(), autoRepeat); + (unicode != 0xffff ) ? QString(QChar(unicode)) : QString(), autoRepeat); } QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint16 keycode, bool pressed, bool autorepeat) diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp index 0c192949052..daa52d690e9 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp @@ -96,7 +96,7 @@ QEvdevMouseManager::QEvdevMouseManager(const QString &key, const QString &specif } QInputDeviceManager *manager = QGuiApplicationPrivate::inputDeviceManager(); - connect(manager, &QInputDeviceManager::cursorPositionChangeRequested, [=](const QPoint &pos) { + connect(manager, &QInputDeviceManager::cursorPositionChangeRequested, [this](const QPoint &pos) { m_x = pos.x(); m_y = pos.y(); clampPosition(); diff --git a/src/platformsupport/input/libinput/qlibinputhandler.cpp b/src/platformsupport/input/libinput/qlibinputhandler.cpp index bb81890a67f..95dfb46d163 100644 --- a/src/platformsupport/input/libinput/qlibinputhandler.cpp +++ b/src/platformsupport/input/libinput/qlibinputhandler.cpp @@ -115,7 +115,7 @@ QLibInputHandler::QLibInputHandler(const QString &key, const QString &spec) m_touch.reset(new QLibInputTouch); QInputDeviceManager *manager = QGuiApplicationPrivate::inputDeviceManager(); - connect(manager, &QInputDeviceManager::cursorPositionChangeRequested, [=](const QPoint &pos) { + connect(manager, &QInputDeviceManager::cursorPositionChangeRequested, [this](const QPoint &pos) { m_pointer->setPos(pos); }); diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp index 8cc7a539b55..1ba32895f8e 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp +++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp @@ -66,6 +66,8 @@ enum OutputConfiguration { int QKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector) { + int candidate = -1; + for (int i = 0; i < connector->count_encoders; i++) { drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoders[i]); if (!encoder) { @@ -73,19 +75,30 @@ int QKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr co continue; } + quint32 encoderId = encoder->encoder_id; + quint32 crtcId = encoder->crtc_id; quint32 possibleCrtcs = encoder->possible_crtcs; drmModeFreeEncoder(encoder); for (int j = 0; j < resources->count_crtcs; j++) { bool isPossible = possibleCrtcs & (1 << j); bool isAvailable = !(m_crtc_allocator & (1 << j)); + // Preserve the existing CRTC -> encoder -> connector routing if + // any. It makes the initialization faster, and may be better + // since we have a very dumb picking algorithm. + bool isBestChoice = (!connector->encoder_id || + (connector->encoder_id == encoderId && + resources->crtcs[j] == crtcId)); - if (isPossible && isAvailable) + if (isPossible && isAvailable && isBestChoice) { return j; + } else if (isPossible && isAvailable) { + candidate = j; + } } } - return -1; + return candidate; } static const char * const connector_type_names[] = { // must match DRM_MODE_CONNECTOR_* diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp index 1aef1a24d2b..a6029b691c1 100644 --- a/src/plugins/imageformats/gif/qgifhandler.cpp +++ b/src/plugins/imageformats/gif/qgifhandler.cpp @@ -1215,9 +1215,11 @@ int QGifHandler::currentImageNumber() const return frameNumber; } +#if QT_DEPRECATED_SINCE(5, 13) QByteArray QGifHandler::name() const { return "gif"; } +#endif QT_END_NAMESPACE diff --git a/src/plugins/imageformats/gif/qgifhandler_p.h b/src/plugins/imageformats/gif/qgifhandler_p.h index b004ee610d1..c6592043ce2 100644 --- a/src/plugins/imageformats/gif/qgifhandler_p.h +++ b/src/plugins/imageformats/gif/qgifhandler_p.h @@ -73,7 +73,9 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; +#if QT_DEPRECATED_SINCE(5, 13) QByteArray name() const override; +#endif static bool canRead(QIODevice *device); diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index 4908850cc50..c8e31dceac7 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -818,6 +818,7 @@ bool QtIcoHandler::write(const QImage &image) return ICOReader::write(device, imgs); } +#if QT_DEPRECATED_SINCE(5, 13) /*! * Return the common identifier of the format. * For ICO format this will return "ico". @@ -826,7 +827,7 @@ QByteArray QtIcoHandler::name() const { return "ico"; } - +#endif /*! \reimp diff --git a/src/plugins/imageformats/ico/qicohandler.h b/src/plugins/imageformats/ico/qicohandler.h index 435f0361135..328dfce47eb 100644 --- a/src/plugins/imageformats/ico/qicohandler.h +++ b/src/plugins/imageformats/ico/qicohandler.h @@ -54,7 +54,9 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; +#if QT_DEPRECATED_SINCE(5, 13) QByteArray name() const override; +#endif int imageCount() const override; bool jumpToImage(int imageNumber) override; diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp index 9d5ccc8a3d8..0fb21df1d3b 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp +++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp @@ -1136,9 +1136,11 @@ void QJpegHandler::setOption(ImageOption option, const QVariant &value) } } +#if QT_DEPRECATED_SINCE(5, 13) QByteArray QJpegHandler::name() const { return "jpeg"; } +#endif QT_END_NAMESPACE diff --git a/src/plugins/imageformats/jpeg/qjpeghandler_p.h b/src/plugins/imageformats/jpeg/qjpeghandler_p.h index d832bf82f3c..fafa930c111 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler_p.h +++ b/src/plugins/imageformats/jpeg/qjpeghandler_p.h @@ -68,7 +68,9 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; +#if QT_DEPRECATED_SINCE(5, 13) QByteArray name() const override; +#endif static bool canRead(QIODevice *device); diff --git a/src/plugins/platforms/cocoa/.prev_CMakeLists.txt b/src/plugins/platforms/cocoa/.prev_CMakeLists.txt index a8ee50e7153..b8ab5af395a 100644 --- a/src/plugins/platforms/cocoa/.prev_CMakeLists.txt +++ b/src/plugins/platforms/cocoa/.prev_CMakeLists.txt @@ -37,6 +37,7 @@ add_qt_plugin(qcocoa qcocoasystemtrayicon.h qcocoasystemtrayicon.mm qcocoatheme.h qcocoatheme.mm qcocoawindow.h qcocoawindow.mm + qcocoawindowmanager.h qcocoawindowmanager.mm qiosurfacegraphicsbuffer.h qiosurfacegraphicsbuffer.mm qmacclipboard.h qmacclipboard.mm qmultitouch_mac.mm qmultitouch_mac_p.h @@ -71,14 +72,21 @@ add_qt_plugin(qcocoa ) # Resources: -add_qt_resource(qcocoa "qcocoaresources" PREFIX "/qt-project.org/mac/cursors" FILES - images/sizeallcursor.png - images/spincursor.png - images/waitcursor.png) +set(qcocoaresources_resource_files + "images/sizeallcursor.png" + "images/spincursor.png" + "images/waitcursor.png" +) + +add_qt_resource(qcocoa "qcocoaresources" + PREFIX + "/qt-project.org/mac/cursors" + FILES + ${qcocoaresources_resource_files} +) #### Keys ignored in scope 1:.:.:cocoa.pro:: -# CONFIG = "no_app_extension_api_only" # OTHER_FILES = "cocoa.json" # PLUGIN_CLASS_NAME = "QCocoaIntegrationPlugin" # PLUGIN_TYPE = "platforms" @@ -118,17 +126,17 @@ extend_target(qcocoa CONDITION TARGET Qt::Widgets #### Keys ignored in scope 5:.:.:cocoa.pro:TARGET Qt::Widgets: # QT_FOR_CONFIG = "widgets" -extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_colordialog) +extend_target(qcocoa CONDITION QT_FEATURE_colordialog AND TARGET Qt::Widgets SOURCES qcocoacolordialoghelper.h qcocoacolordialoghelper.mm ) -extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_filedialog) +extend_target(qcocoa CONDITION QT_FEATURE_filedialog AND TARGET Qt::Widgets SOURCES qcocoafiledialoghelper.h qcocoafiledialoghelper.mm ) -extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_fontdialog) +extend_target(qcocoa CONDITION QT_FEATURE_fontdialog AND TARGET Qt::Widgets SOURCES qcocoafontdialoghelper.h qcocoafontdialoghelper.mm ) diff --git a/src/plugins/platforms/cocoa/CMakeLists.txt b/src/plugins/platforms/cocoa/CMakeLists.txt index 9b546990bad..6bf09762245 100644 --- a/src/plugins/platforms/cocoa/CMakeLists.txt +++ b/src/plugins/platforms/cocoa/CMakeLists.txt @@ -41,6 +41,7 @@ add_qt_plugin(qcocoa qcocoasystemtrayicon.h qcocoasystemtrayicon.mm qcocoatheme.h qcocoatheme.mm qcocoawindow.h qcocoawindow.mm + qcocoawindowmanager.h qcocoawindowmanager.mm qiosurfacegraphicsbuffer.h qiosurfacegraphicsbuffer.mm qmacclipboard.h qmacclipboard.mm qmultitouch_mac.mm qmultitouch_mac_p.h @@ -75,14 +76,21 @@ add_qt_plugin(qcocoa ) # Resources: -add_qt_resource(qcocoa "qcocoaresources" PREFIX "/qt-project.org/mac/cursors" FILES - images/sizeallcursor.png - images/spincursor.png - images/waitcursor.png) +set(qcocoaresources_resource_files + "images/sizeallcursor.png" + "images/spincursor.png" + "images/waitcursor.png" +) + +add_qt_resource(qcocoa "qcocoaresources" + PREFIX + "/qt-project.org/mac/cursors" + FILES + ${qcocoaresources_resource_files} +) #### Keys ignored in scope 1:.:.:cocoa.pro:: -# CONFIG = "no_app_extension_api_only" # OTHER_FILES = "cocoa.json" # PLUGIN_CLASS_NAME = "QCocoaIntegrationPlugin" # PLUGIN_TYPE = "platforms" @@ -122,17 +130,17 @@ extend_target(qcocoa CONDITION TARGET Qt::Widgets #### Keys ignored in scope 5:.:.:cocoa.pro:TARGET Qt::Widgets: # QT_FOR_CONFIG = "widgets" -extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_colordialog) +extend_target(qcocoa CONDITION QT_FEATURE_colordialog AND TARGET Qt::Widgets SOURCES qcocoacolordialoghelper.h qcocoacolordialoghelper.mm ) -extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_filedialog) +extend_target(qcocoa CONDITION QT_FEATURE_filedialog AND TARGET Qt::Widgets SOURCES qcocoafiledialoghelper.h qcocoafiledialoghelper.mm ) -extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_fontdialog) +extend_target(qcocoa CONDITION QT_FEATURE_fontdialog AND TARGET Qt::Widgets SOURCES qcocoafontdialoghelper.h qcocoafontdialoghelper.mm ) diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 083b7c16552..02e00039ae3 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -6,6 +6,7 @@ SOURCES += main.mm \ qcocoatheme.mm \ qcocoabackingstore.mm \ qcocoawindow.mm \ + qcocoawindowmanager.mm \ qnsview.mm \ qnswindow.mm \ qnswindowdelegate.mm \ @@ -41,6 +42,7 @@ HEADERS += qcocoaintegration.h \ qcocoatheme.h \ qcocoabackingstore.h \ qcocoawindow.h \ + qcocoawindowmanager.h \ qnsview.h \ qnswindow.h \ qnswindowdelegate.h \ diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index 2398e6351e6..9be6814ae74 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -49,7 +49,14 @@ QT_BEGIN_NAMESPACE -class QNSWindowBackingStore : public QRasterBackingStore +class QCocoaBackingStore : public QRasterBackingStore +{ +protected: + QCocoaBackingStore(QWindow *window); + QCFType colorSpace() const; +}; + +class QNSWindowBackingStore : public QCocoaBackingStore { public: QNSWindowBackingStore(QWindow *window); @@ -64,7 +71,7 @@ private: void redrawRoundedBottomCorners(CGRect) const; }; -class QCALayerBackingStore : public QPlatformBackingStore +class QCALayerBackingStore : public QCocoaBackingStore { public: QCALayerBackingStore(QWindow *window); diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 01b4894324d..6015257f4e8 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -48,11 +48,24 @@ QT_BEGIN_NAMESPACE -QNSWindowBackingStore::QNSWindowBackingStore(QWindow *window) +QCocoaBackingStore::QCocoaBackingStore(QWindow *window) : QRasterBackingStore(window) { } +QCFType QCocoaBackingStore::colorSpace() const +{ + NSView *view = static_cast(window()->handle())->view(); + return QCFType::constructFromGet(view.window.colorSpace.CGColorSpace); +} + +// ---------------------------------------------------------------------------- + +QNSWindowBackingStore::QNSWindowBackingStore(QWindow *window) + : QCocoaBackingStore(window) +{ +} + QNSWindowBackingStore::~QNSWindowBackingStore() { } @@ -175,11 +188,10 @@ void QNSWindowBackingStore::flush(QWindow *window, const QRegion ®ion, const Q_ASSERT_X(graphicsContext, "QCocoaBackingStore", "Focusing the view should give us a current graphics context"); - // Prevent potentially costly color conversion by assigning the display color space - // to the backingstore image. This does not copy the underlying image data. - CGColorSpaceRef displayColorSpace = view.window.screen.colorSpace.CGColorSpace; + // Tag backingstore image with color space based on the window. + // Note: This does not copy the underlying image data. QCFType cgImage = CGImageCreateCopyWithColorSpace( - QCFType(m_image.toCGImage()), displayColorSpace); + QCFType(m_image.toCGImage()), colorSpace()); // Create temporary image to use for blitting, without copying image data NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize] autorelease]; @@ -293,7 +305,7 @@ void QNSWindowBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const // ---------------------------------------------------------------------------- QCALayerBackingStore::QCALayerBackingStore(QWindow *window) - : QPlatformBackingStore(window) + : QCocoaBackingStore(window) { qCDebug(lcQpaBackingStore) << "Creating QCALayerBackingStore for" << window; m_buffers.resize(1); @@ -432,11 +444,7 @@ bool QCALayerBackingStore::recreateBackBufferIfNeeded() << "based on requested" << m_requestedSize << "and dpr =" << devicePixelRatio; static auto pixelFormat = QImage::toPixelFormat(QImage::Format_ARGB32_Premultiplied); - - NSView *view = static_cast(window()->handle())->view(); - auto colorSpace = QCFType::constructFromGet(view.window.screen.colorSpace.CGColorSpace); - - m_buffers.back().reset(new GraphicsBuffer(requestedBufferSize, devicePixelRatio, pixelFormat, colorSpace)); + m_buffers.back().reset(new GraphicsBuffer(requestedBufferSize, devicePixelRatio, pixelFormat, colorSpace())); return true; } diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h index c1041ac2da2..bb309c07130 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.h +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h @@ -56,6 +56,8 @@ public: QCocoaGLContext(QOpenGLContext *context); ~QCocoaGLContext(); + void initialize() override; + bool makeCurrent(QPlatformSurface *surface) override; void swapBuffers(QPlatformSurface *surface) override; void doneCurrent() override; diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 0f8fec0548b..7b124ea5178 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -40,6 +40,8 @@ #include "qcocoaglcontext.h" #include "qcocoawindow.h" #include "qcocoahelpers.h" +#include "qcocoascreen.h" + #include #include #include @@ -53,32 +55,19 @@ static inline QByteArray getGlString(GLenum param) return QByteArray(); } -@implementation NSOpenGLPixelFormat (QtHelpers) -- (GLint)qt_getAttribute:(NSOpenGLPixelFormatAttribute)attribute -{ - int value = 0; - [self getValues:&value forAttribute:attribute forVirtualScreen:0]; - return value; -} -@end - -@implementation NSOpenGLContext (QtHelpers) -- (GLint)qt_getParameter:(NSOpenGLContextParameter)parameter -{ - int value = 0; - [self getValues:&value forParameter:parameter]; - return value; -} -@end - QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaOpenGLContext, "qt.qpa.openglcontext", QtWarningMsg); QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context) - : QPlatformOpenGLContext(), m_format(context->format()) + : QPlatformOpenGLContext() + , m_format(context->format()) { - QVariant nativeHandle = context->nativeHandle(); +} + +void QCocoaGLContext::initialize() +{ + QVariant nativeHandle = context()->nativeHandle(); if (!nativeHandle.isNull()) { if (!nativeHandle.canConvert()) { qCWarning(lcQpaOpenGLContext, "QOpenGLContext native handle must be a QCocoaNativeContext"); @@ -95,7 +84,7 @@ QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context) // Note: We have no way of knowing whether the NSOpenGLContext was created with the // share context as reported by the QOpenGLContext, but we just have to trust that // it was. It's okey, as the only thing we're using it for is to report isShared(). - if (QPlatformOpenGLContext *shareContext = context->shareHandle()) + if (QPlatformOpenGLContext *shareContext = context()->shareHandle()) m_shareContext = static_cast(shareContext)->nativeContext(); updateSurfaceFormat(); @@ -110,7 +99,7 @@ QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context) if (m_format.renderableType() != QSurfaceFormat::OpenGL) return; - if (QPlatformOpenGLContext *shareContext = context->shareHandle()) { + if (QPlatformOpenGLContext *shareContext = context()->shareHandle()) { m_shareContext = static_cast(shareContext)->nativeContext(); // Allow sharing between 3.2 Core and 4.1 Core profile versions in @@ -150,6 +139,9 @@ QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context) return; } + // The native handle should reflect the underlying context, even if we created it + context()->setNativeHandle(QVariant::fromValue(m_context)); + // --------------------- Set NSOpenGLContext properties --------------------- const GLint interval = m_format.swapInterval() >= 0 ? m_format.swapInterval() : 1; @@ -285,7 +277,32 @@ void QCocoaGLContext::updateSurfaceFormat() NSOpenGLPixelFormat *pixelFormat = m_context.pixelFormat; - int colorSize = [pixelFormat qt_getAttribute:NSOpenGLPFAColorSize]; + GLint virtualScreen = [&, this]() { + auto *platformScreen = static_cast(context()->screen()->handle()); + auto displayId = platformScreen->nativeScreen().qt_displayId; + auto requestedDisplay = CGDisplayIDToOpenGLDisplayMask(displayId); + for (int i = 0; i < pixelFormat.numberOfVirtualScreens; ++i) { + GLint supportedDisplays; + [pixelFormat getValues:&supportedDisplays forAttribute:NSOpenGLPFAScreenMask forVirtualScreen:i]; + // Note: The mask returned for NSOpenGLPFAScreenMask is a bit mask of + // physical displays that the renderer can drive, while the one returned + // from CGDisplayIDToOpenGLDisplayMask has a single bit set, representing + // that particular display. + if (requestedDisplay & supportedDisplays) + return i; + } + qCWarning(lcQpaOpenGLContext) << "Could not find virtual screen for" + << platformScreen << "with displayId" << displayId; + return 0; + }(); + + auto pixelFormatAttribute = [&](NSOpenGLPixelFormatAttribute attribute) { + int value = 0; + [pixelFormat getValues:&value forAttribute:attribute forVirtualScreen:virtualScreen]; + return value; + }; + + int colorSize = pixelFormatAttribute(NSOpenGLPFAColorSize); colorSize /= 4; // The attribute includes the alpha component m_format.setRedBufferSize(colorSize); m_format.setGreenBufferSize(colorSize); @@ -297,22 +314,28 @@ void QCocoaGLContext::updateSurfaceFormat() // size, as that will make the user believe the alpha channel can be used for // something useful, when in reality it can't, due to the surface being opaque. if (m_format.alphaBufferSize() > 0) - m_format.setAlphaBufferSize([pixelFormat qt_getAttribute:NSOpenGLPFAAlphaSize]); + m_format.setAlphaBufferSize(pixelFormatAttribute(NSOpenGLPFAAlphaSize)); - m_format.setDepthBufferSize([pixelFormat qt_getAttribute:NSOpenGLPFADepthSize]); - m_format.setStencilBufferSize([pixelFormat qt_getAttribute:NSOpenGLPFAStencilSize]); - m_format.setSamples([pixelFormat qt_getAttribute:NSOpenGLPFASamples]); + m_format.setDepthBufferSize(pixelFormatAttribute(NSOpenGLPFADepthSize)); + m_format.setStencilBufferSize(pixelFormatAttribute(NSOpenGLPFAStencilSize)); + m_format.setSamples(pixelFormatAttribute(NSOpenGLPFASamples)); - if ([pixelFormat qt_getAttribute:NSOpenGLPFATripleBuffer]) + if (pixelFormatAttribute(NSOpenGLPFATripleBuffer)) m_format.setSwapBehavior(QSurfaceFormat::TripleBuffer); - else if ([pixelFormat qt_getAttribute:NSOpenGLPFADoubleBuffer]) + else if (pixelFormatAttribute(NSOpenGLPFADoubleBuffer)) m_format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); else m_format.setSwapBehavior(QSurfaceFormat::SingleBuffer); // ------------------- Query the context ------------------- - m_format.setSwapInterval([m_context qt_getParameter:NSOpenGLCPSwapInterval]); + auto glContextParameter = [&](NSOpenGLContextParameter parameter) { + int value = 0; + [m_context getValues:&value forParameter:parameter]; + return value; + }; + + m_format.setSwapInterval(glContextParameter(NSOpenGLCPSwapInterval)); if (oldContext) [oldContext makeCurrentContext]; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 08e7447a758..9a2f19c2f2a 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -215,25 +215,6 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &QCocoaIntegration::focusWindowChanged); - - static auto splashScreenHider = QMacKeyValueObserver(NSApp, @"modalWindow", []{ - const QWindowList allWindows = QGuiApplication::topLevelWindows(); - for (QWindow *window : allWindows) { - if ((window->flags() & Qt::SplashScreen) == Qt::SplashScreen) { - QCocoaWindow *platformWindow = static_cast(window->handle()); - NSWindow *splashWindow = platformWindow->view().window; - if (!splashWindow) - continue; - if (NSApp.modalWindow) { - NSInteger originalLevel = splashWindow.level; - splashWindow.level = NSNormalWindowLevel; - window->setProperty("_q_levelBeforeModalSession", (qlonglong)originalLevel); - } else if (NSInteger originalLevel = window->property("_q_levelBeforeModalSession").toLongLong()) { - splashWindow.level = originalLevel; - } - } - } - }); } QCocoaIntegration::~QCocoaIntegration() @@ -331,9 +312,7 @@ QPlatformOffscreenSurface *QCocoaIntegration::createPlatformOffscreenSurface(QOf #ifndef QT_NO_OPENGL QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { - QCocoaGLContext *glContext = new QCocoaGLContext(context); - context->setNativeHandle(QVariant::fromValue(glContext->nativeContext())); - return glContext; + return new QCocoaGLContext(context); } #endif diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index de5cf858544..db64702b8da 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -118,11 +118,13 @@ class QSystemTrayIconSys public: QSystemTrayIconSys(QCocoaSystemTrayIcon *sys) { item = [[QNSStatusItem alloc] initWithSysTray:sys]; - [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:item]; + NSUserNotificationCenter.defaultUserNotificationCenter.delegate = item; } ~QSystemTrayIconSys() { [[[item item] view] setHidden: YES]; - [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil]; + NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter; + if (center.delegate == item) + center.delegate = nil; [item release]; } QNSStatusItem *item; @@ -264,7 +266,6 @@ bool QCocoaSystemTrayIcon::supportsMessages() const void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &message, const QIcon& icon, MessageIcon, int) { - Q_UNUSED(icon); if (!m_sys) return; @@ -272,7 +273,16 @@ void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &mess notification.title = [NSString stringWithUTF8String:title.toUtf8().data()]; notification.informativeText = [NSString stringWithUTF8String:message.toUtf8().data()]; - [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification]; + if (!icon.isNull()) { + auto *nsimage = qt_mac_create_nsimage(icon); + [nsimage setTemplate:icon.isMask()]; + notification.contentImage = [nsimage autorelease]; + } + + NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter; + center.delegate = m_sys->item; + [center deliverNotification:notification]; + [notification release]; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 363a026e71c..8f3c1927457 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -454,13 +454,35 @@ NSInteger QCocoaWindow::windowLevel(Qt::WindowFlags flags) if (type == Qt::ToolTip) windowLevel = NSScreenSaverWindowLevel; - // Any "special" window should be in at least the same level as its parent. - if (type != Qt::Window) { - const QWindow * const transientParent = window()->transientParent(); - const QCocoaWindow * const transientParentWindow = transientParent ? - static_cast(transientParent->handle()) : nullptr; - if (transientParentWindow) - windowLevel = qMax([transientParentWindow->nativeWindow() level], windowLevel); + auto *transientParent = window()->transientParent(); + if (transientParent && transientParent->handle()) { + // We try to keep windows in at least the same window level as + // their transient parent. Unfortunately this only works when the + // window is created. If the window level changes after that, as + // a result of a call to setWindowFlags, or by changing the level + // of the native window, we will not pick this up, and the window + // will be left behind (or in a different window level than) its + // parent. We could KVO-observe the window level of our transient + // parent, but that requires us to know when the parent goes away + // so that we can unregister the observation before the parent is + // dealloced, something we can't do for generic NSWindows. Another + // way would be to override [NSWindow setLevel:] and notify child + // windows about the change, but that doesn't work for foreign + // windows, which can still be transient parents via fromWinId(). + // One area where this problem is apparent is when AppKit tweaks + // the window level of modal windows during application activation + // and deactivation. Since we don't pick up on these window level + // changes in a generic way, we need to add logic explicitly to + // re-evaluate the window level after AppKit has done its tweaks. + + auto *transientCocoaWindow = static_cast(transientParent->handle()); + auto *nsWindow = transientCocoaWindow->nativeWindow(); + + // We only upgrade the window level for "special" windows, to work + // around Qt Designer parenting the designer windows to the widget + // palette window (QTBUG-31779). This should be fixed in designer. + if (type != Qt::Window) + windowLevel = qMax(windowLevel, nsWindow.level); } return windowLevel; @@ -1626,6 +1648,9 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel) [nsWindow setDepthLimit:NSWindowDepthTwentyfourBitRGB]; } + if (format().colorSpace() == QSurfaceFormat::sRGBColorSpace) + nsWindow.colorSpace = NSColorSpace.sRGBColorSpace; + return nsWindow; } diff --git a/src/corelib/thread/qmutexpool_p.h b/src/plugins/platforms/cocoa/qcocoawindowmanager.h similarity index 60% rename from src/corelib/thread/qmutexpool_p.h rename to src/plugins/platforms/cocoa/qcocoawindowmanager.h index 00710199b88..54f17eeccd7 100644 --- a/src/corelib/thread/qmutexpool_p.h +++ b/src/plugins/platforms/cocoa/qcocoawindowmanager.h @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** -** This file is part of the QtCore module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage @@ -37,52 +37,27 @@ ** ****************************************************************************/ -#ifndef QMUTEXPOOL_P_H -#define QMUTEXPOOL_P_H +#ifndef QCOCOAWINDOWMANAGER_H +#define QCOCOAWINDOWMANAGER_H -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// +#include -#include -#include "QtCore/qatomic.h" -#include "QtCore/qmutex.h" -#include "QtCore/qvarlengtharray.h" - -QT_REQUIRE_CONFIG(thread); +#include QT_BEGIN_NAMESPACE -class Q_CORE_EXPORT QMutexPool +class QCocoaWindowManager { public: - explicit QMutexPool(QMutex::RecursionMode recursionMode = QMutex::NonRecursive, int size = 131); - ~QMutexPool(); - - inline QMutex *get(const void *address) { - int index = uint(quintptr(address)) % mutexes.count(); - QMutex *m = mutexes[index].loadAcquire(); - if (m) - return m; - else - return createMutex(index); - } - static QMutexPool *instance(); - static QMutex *globalInstanceGet(const void *address); + static QCocoaWindowManager *instance(); private: - QMutex *createMutex(int index); - QVarLengthArray, 131> mutexes; - QMutex::RecursionMode recursionMode; + QCocoaWindowManager(); + void initialize(); + + void modalSessionChanged(); }; QT_END_NAMESPACE -#endif // QMUTEXPOOL_P_H +#endif // QCOCOAWINDOWMANAGER_H diff --git a/src/plugins/platforms/cocoa/qcocoawindowmanager.mm b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm new file mode 100644 index 00000000000..879bfaa546e --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcocoawindowmanager.h" +#include "qcocoawindow.h" + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +QCocoaWindowManager *QCocoaWindowManager::instance() +{ + static auto *instance = new QCocoaWindowManager; + return instance; +} + +QCocoaWindowManager::QCocoaWindowManager() +{ + if (NSApp) { + initialize(); + } else { + static auto applicationDidFinishLaunching(QMacNotificationObserver(nil, + NSApplicationDidFinishLaunchingNotification, [this] { initialize(); })); + } +} + +void QCocoaWindowManager::initialize() +{ + Q_ASSERT(NSApp); + + // Whenever the modalWindow property of NSApplication changes we have a new + // modal session running. Observing the app modal window instead of our own + // event dispatcher sessions allows us to track session started by native + // APIs as well. We need to check the initial state as well, in case there + // is already a modal session running. + static auto modalSessionObserver(QMacKeyValueObserver( + NSApp, @"modalWindow", [this] { modalSessionChanged(); }, + NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew)); +} + +void QCocoaWindowManager::modalSessionChanged() +{ + // Make sure that no window is overlapping the modal window. This can + // happen for e.g. splash screens, which have the NSPopUpMenuWindowLevel. + for (auto *window : QGuiApplication::topLevelWindows()) { + auto *platformWindow = static_cast(window->handle()); + if (!platformWindow) + continue; + + auto naturalWindowLevel = platformWindow->windowLevel(window->flags()); + if (naturalWindowLevel > NSModalPanelWindowLevel) { + NSWindow *nativeWindow = platformWindow->nativeWindow(); + if (NSApp.modalWindow) { + // Lower window to that of the modal windows, but no less + nativeWindow.level = NSModalPanelWindowLevel; + [nativeWindow orderBack:nil]; + } else { + // Restore window's natural window level, whatever that was + nativeWindow.level = naturalWindowLevel; + } + } + } +} + +static void initializeWindowManager() { Q_UNUSED(QCocoaWindowManager::instance()); } +Q_CONSTRUCTOR_FUNCTION(initializeWindowManager) + +QT_END_NAMESPACE + diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index f2f29b26ee1..58ad53a6e12 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -522,16 +522,16 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice->supportedDuplexModes().contains(mode)) break; switch (mode) { - case QPrinter::DuplexNone: + case QPrint::DuplexNone: PMSetDuplex(d->settings(), kPMDuplexNone); break; - case QPrinter::DuplexAuto: + case QPrint::DuplexAuto: PMSetDuplex(d->settings(), d->m_pageLayout.orientation() == QPageLayout::Landscape ? kPMDuplexTumble : kPMDuplexNoTumble); break; - case QPrinter::DuplexLongSide: + case QPrint::DuplexLongSide: PMSetDuplex(d->settings(), kPMDuplexNoTumble); break; - case QPrinter::DuplexShortSide: + case QPrint::DuplexShortSide: PMSetDuplex(d->settings(), kPMDuplexTumble); break; default: diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp index 2c6b4245b71..3e78196227c 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -114,20 +114,16 @@ public: : QEglFSWindow(w) , m_integration(integration) , m_egl_stream(EGL_NO_STREAM_KHR) - , m_framePending(false) { } ~QEglFSKmsEglDeviceWindow() { destroy(); } void invalidateSurface() override; void resetSurface() override; - void flip(); - static void pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); const QEglFSKmsEglDeviceIntegration *m_integration; EGLStreamKHR m_egl_stream; EGLint m_latency; - bool m_framePending; }; void QEglFSKmsEglDeviceWindow::invalidateSurface() @@ -148,9 +144,6 @@ void QEglFSKmsEglDeviceWindow::resetSurface() streamAttribs[streamAttribCount++] = EGL_STREAM_FIFO_LENGTH_KHR; streamAttribs[streamAttribCount++] = fifoLength; } - - streamAttribs[streamAttribCount++] = EGL_CONSUMER_AUTO_ACQUIRE_EXT; - streamAttribs[streamAttribCount++] = EGL_FALSE; streamAttribs[streamAttribCount++] = EGL_NONE; m_egl_stream = m_integration->m_funcs->create_stream(display, streamAttribs); @@ -248,49 +241,6 @@ void QEglFSKmsEglDeviceWindow::resetSurface() qCDebug(qLcEglfsKmsDebug, "Created stream producer surface %p", m_surface); } -void QEglFSKmsEglDeviceWindow::flip() -{ - EGLDisplay display = screen()->display(); - - EGLAttrib acquire_attribs[3] = { EGL_NONE }; - - acquire_attribs[0] = EGL_DRM_FLIP_EVENT_DATA_NV; - acquire_attribs[1] = (EGLAttrib)this; - acquire_attribs[2] = EGL_NONE; - - if (m_egl_stream != EGL_NO_STREAM_KHR) - if (!m_integration->m_funcs->acquire_stream_attrib_nv(display, m_egl_stream, acquire_attribs)) - qWarning("eglStreamConsumerAcquireAttribNV failed: eglError: %x", eglGetError()); - - m_framePending = true; - - while (m_framePending) { - drmEventContext drmEvent; - memset(&drmEvent, 0, sizeof(drmEvent)); - drmEvent.version = 3; - drmEvent.vblank_handler = nullptr; - drmEvent.page_flip_handler = pageFlipHandler; - drmHandleEvent(m_integration->m_device->fd(), &drmEvent); - } -} - -void QEglFSKmsEglDeviceWindow::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) -{ - Q_UNUSED(fd); - Q_UNUSED(sequence); - Q_UNUSED(tv_sec); - Q_UNUSED(tv_usec); - - QEglFSKmsEglDeviceWindow *window = static_cast(user_data); - window->m_framePending = false; -} - -void QEglFSKmsEglDeviceIntegration::presentBuffer(QPlatformSurface *surface) -{ - QEglFSKmsEglDeviceWindow *eglWindow = static_cast(surface); - eglWindow->flip(); -} - QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const { QEglFSKmsEglDeviceWindow *eglWindow = new QEglFSKmsEglDeviceWindow(window, this); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h index a5697ec8313..5819d82ebf1 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h @@ -62,8 +62,6 @@ public: bool supportsPBuffers() const override; QEglFSWindow *createWindow(QWindow *window) const override; - void presentBuffer(QPlatformSurface *surface) override; - EGLDeviceEXT eglDevice() const { return m_egl_device; } protected: diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index 6d211667bee..a810880c439 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -681,7 +681,7 @@ void QWasmCompositor::frame() QWasmWindow *someWindow = nullptr; - foreach (QWasmWindow *window, m_windowStack) { + for (QWasmWindow *window : qAsConst(m_windowStack)) { if (window->window()->surfaceClass() == QSurface::Window && qt_window_private(static_cast(window->window()))->receivedExpose) { someWindow = window; @@ -715,7 +715,7 @@ void QWasmCompositor::frame() m_blitter->bind(); m_blitter->setRedBlueSwizzle(true); - foreach (QWasmWindow *window, m_windowStack) { + for (QWasmWindow *window : qAsConst(m_windowStack)) { QWasmCompositedWindow &compositedWindow = m_compositedWindows[window]; if (!compositedWindow.visible) diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp index 3895646b893..ad94ba9c772 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp @@ -138,16 +138,16 @@ static constexpr const auto KeyTbl = qMakeArray( Emkb2Qt< Qt::Key_Minus, '-' >, Emkb2Qt< Qt::Key_Period, '.' >, Emkb2Qt< Qt::Key_Slash, '/' >, - Emkb2Qt< Qt::Key_0, '0' >, - Emkb2Qt< Qt::Key_1, '1' >, - Emkb2Qt< Qt::Key_2, '2' >, - Emkb2Qt< Qt::Key_3, '3' >, - Emkb2Qt< Qt::Key_4, '4' >, - Emkb2Qt< Qt::Key_5, '5' >, - Emkb2Qt< Qt::Key_6, '6' >, - Emkb2Qt< Qt::Key_7, '7' >, - Emkb2Qt< Qt::Key_8, '8' >, - Emkb2Qt< Qt::Key_9, '9' >, + Emkb2Qt< Qt::Key_0, 'D','i','g','i','t','0' >, + Emkb2Qt< Qt::Key_1, 'D','i','g','i','t','1' >, + Emkb2Qt< Qt::Key_2, 'D','i','g','i','t','2' >, + Emkb2Qt< Qt::Key_3, 'D','i','g','i','t','3' >, + Emkb2Qt< Qt::Key_4, 'D','i','g','i','t','4' >, + Emkb2Qt< Qt::Key_5, 'D','i','g','i','t','5' >, + Emkb2Qt< Qt::Key_6, 'D','i','g','i','t','6' >, + Emkb2Qt< Qt::Key_7, 'D','i','g','i','t','7' >, + Emkb2Qt< Qt::Key_8, 'D','i','g','i','t','8' >, + Emkb2Qt< Qt::Key_9, 'D','i','g','i','t','9' >, Emkb2Qt< Qt::Key_Semicolon, ';' >, Emkb2Qt< Qt::Key_Equal, '=' >, Emkb2Qt< Qt::Key_A, 'K','e','y','A' >, @@ -432,7 +432,8 @@ Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent { Qt::Key qtKey = Qt::Key_unknown; - if (qstrncmp(emscriptKey->code, "Key", 3) == 0 || qstrncmp(emscriptKey->code, "Numpad", 6) == 0) { + if (qstrncmp(emscriptKey->code, "Key", 3) == 0 || qstrncmp(emscriptKey->code, "Numpad", 6) == 0 || + qstrncmp(emscriptKey->code, "Digit", 5) == 0) { emkb2qt_t searchKey{emscriptKey->code, 0}; // search emcsripten code auto it1 = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey); @@ -779,6 +780,60 @@ quint64 QWasmEventTranslator::getTimestamp() return QDeadlineTimer::current().deadlineNSecs() / 1000; } +struct KeyMapping { Qt::Key from, to; }; + +constexpr KeyMapping tildeKeyTable[] = { // ~ + { Qt::Key_A, Qt::Key_Atilde }, + { Qt::Key_N, Qt::Key_Ntilde }, + { Qt::Key_O, Qt::Key_Otilde }, +}; +constexpr KeyMapping graveKeyTable[] = { // ` + { Qt::Key_A, Qt::Key_Agrave }, + { Qt::Key_E, Qt::Key_Egrave }, + { Qt::Key_I, Qt::Key_Igrave }, + { Qt::Key_O, Qt::Key_Ograve }, + { Qt::Key_U, Qt::Key_Ugrave }, +}; +constexpr KeyMapping acuteKeyTable[] = { // ' + { Qt::Key_A, Qt::Key_Aacute }, + { Qt::Key_E, Qt::Key_Eacute }, + { Qt::Key_I, Qt::Key_Iacute }, + { Qt::Key_O, Qt::Key_Oacute }, + { Qt::Key_U, Qt::Key_Uacute }, + { Qt::Key_Y, Qt::Key_Yacute }, +}; +constexpr KeyMapping diaeresisKeyTable[] = { // umlaut ¨ + { Qt::Key_A, Qt::Key_Adiaeresis }, + { Qt::Key_E, Qt::Key_Ediaeresis }, + { Qt::Key_I, Qt::Key_Idiaeresis }, + { Qt::Key_O, Qt::Key_Odiaeresis }, + { Qt::Key_U, Qt::Key_Udiaeresis }, + { Qt::Key_Y, Qt::Key_ydiaeresis }, +}; +constexpr KeyMapping circumflexKeyTable[] = { // ^ + { Qt::Key_A, Qt::Key_Acircumflex }, + { Qt::Key_E, Qt::Key_Ecircumflex }, + { Qt::Key_I, Qt::Key_Icircumflex }, + { Qt::Key_O, Qt::Key_Ocircumflex }, + { Qt::Key_U, Qt::Key_Ucircumflex }, +}; + +static Qt::Key find_impl(const KeyMapping *first, const KeyMapping *last, Qt::Key key) noexcept +{ + while (first != last) { + if (first->from == key) + return first->to; + ++first; + } + return Qt::Key_unknown; +} + +template +static Qt::Key find(const KeyMapping (&map)[N], Qt::Key key) noexcept +{ + return find_impl(map, map + N, key); +} + Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey) { Qt::Key wasmKey = Qt::Key_unknown; @@ -788,31 +843,30 @@ Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBa #else case Qt::Key_O: // ´ Key_Dead_Grave #endif - wasmKey = graveKeyTable.value(accentBaseKey); + wasmKey = find(graveKeyTable, accentBaseKey); break; case Qt::Key_E: // ´ Key_Dead_Acute - wasmKey = acuteKeyTable.value(accentBaseKey); + wasmKey = find(acuteKeyTable, accentBaseKey); break; case Qt::Key_AsciiTilde: case Qt::Key_N:// Key_Dead_Tilde - wasmKey = tildeKeyTable.value(accentBaseKey); + wasmKey = find(tildeKeyTable, accentBaseKey); break; #ifndef Q_OS_MACOS case Qt::Key_QuoteLeft: #endif case Qt::Key_U:// ¨ Key_Dead_Diaeresis - wasmKey = diaeresisKeyTable.value(accentBaseKey); + wasmKey = find(diaeresisKeyTable, accentBaseKey); break; case Qt::Key_I:// macOS Key_Dead_Circumflex case Qt::Key_6:// linux case Qt::Key_Apostrophe:// linux - wasmKey = circumflexKeyTable.value(accentBaseKey); - break; + wasmKey = find(circumflexKeyTable, accentBaseKey); break; default: break; - }; + }; return wasmKey; } diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h index 1655b7226a2..568ae007321 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.h +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h @@ -77,42 +77,6 @@ private: Qt::Key translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey); - QHash tildeKeyTable { // ~ - { Qt::Key_A, Qt::Key_Atilde}, - { Qt::Key_N, Qt::Key_Ntilde}, - { Qt::Key_O, Qt::Key_Otilde} - }; - QHash graveKeyTable { // ` - { Qt::Key_A, Qt::Key_Agrave}, - { Qt::Key_E, Qt::Key_Egrave}, - { Qt::Key_I, Qt::Key_Igrave}, - { Qt::Key_O, Qt::Key_Ograve}, - { Qt::Key_U, Qt::Key_Ugrave} - }; - QHash acuteKeyTable { // ' - { Qt::Key_A, Qt::Key_Aacute}, - { Qt::Key_E, Qt::Key_Eacute}, - { Qt::Key_I, Qt::Key_Iacute}, - { Qt::Key_O, Qt::Key_Oacute}, - { Qt::Key_U, Qt::Key_Uacute}, - { Qt::Key_Y, Qt::Key_Yacute} - }; - QHash diaeresisKeyTable { // umlaut ¨ - { Qt::Key_A, Qt::Key_Adiaeresis}, - { Qt::Key_E, Qt::Key_Ediaeresis}, - { Qt::Key_I, Qt::Key_Idiaeresis}, - { Qt::Key_O, Qt::Key_Odiaeresis}, - { Qt::Key_U, Qt::Key_Udiaeresis}, - { Qt::Key_Y, Qt::Key_ydiaeresis} - }; - QHash circumflexKeyTable { // ^ - { Qt::Key_A, Qt::Key_Acircumflex}, - { Qt::Key_E, Qt::Key_Ecircumflex}, - { Qt::Key_I, Qt::Key_Icircumflex}, - { Qt::Key_O, Qt::Key_Ocircumflex}, - { Qt::Key_U, Qt::Key_Ucircumflex} - }; - QMap pressedTouchIds; private: diff --git a/src/plugins/platforms/wasm/qwasmfontdatabase.cpp b/src/plugins/platforms/wasm/qwasmfontdatabase.cpp index dc6bb5847e7..53e875ead6c 100644 --- a/src/plugins/platforms/wasm/qwasmfontdatabase.cpp +++ b/src/plugins/platforms/wasm/qwasmfontdatabase.cpp @@ -38,10 +38,13 @@ void QWasmFontDatabase::populateFontDatabase() // Load font file from resources. Currently // all fonts needs to be bundled with the nexe // as Qt resources. - QStringList fontFileNames = QStringList() << QStringLiteral(":/fonts/DejaVuSansMono.ttf") - << QStringLiteral(":/fonts/Vera.ttf") - << QStringLiteral(":/fonts/DejaVuSans.ttf"); - foreach (const QString &fontFileName, fontFileNames) { + + const QString fontFileNames[] = { + QStringLiteral(":/fonts/DejaVuSansMono.ttf"), + QStringLiteral(":/fonts/Vera.ttf"), + QStringLiteral(":/fonts/DejaVuSans.ttf"), + }; + for (const QString &fontFileName : fontFileNames) { QFile theFont(fontFileName); if (!theFont.open(QIODevice::ReadOnly)) break; diff --git a/src/plugins/platforms/wasm/wasm.pro b/src/plugins/platforms/wasm/wasm.pro index c28df8f893e..f8c81755257 100644 --- a/src/plugins/platforms/wasm/wasm.pro +++ b/src/plugins/platforms/wasm/wasm.pro @@ -7,6 +7,8 @@ QT += \ # Avoid X11 header collision, use generic EGL native types DEFINES += QT_EGL_NO_X11 +DEFINES += QT_NO_FOREACH + SOURCES = \ main.cpp \ qwasmintegration.cpp \ diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index e681dbb0cb4..d5258ca6a31 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -279,7 +280,13 @@ void QWindowsInputContext::showInputPanel() // with Windows 10 if the Windows IME is (re)enabled _after_ the caret is shown. if (m_caretCreated) { cursorRectChanged(); - ShowCaret(platformWindow->handle()); + // We only call ShowCaret() on Windows 10 as in earlier versions the caret + // would actually be visible (QTBUG-74492) and the workaround for the + // Surface seems unnecessary there anyway. But leave it hidden for IME. + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10) + ShowCaret(platformWindow->handle()); + else + HideCaret(platformWindow->handle()); setWindowsImeEnabled(platformWindow, false); setWindowsImeEnabled(platformWindow, true); } diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 4b54051e0c6..4f0f8467494 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -1301,7 +1301,23 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg, || code == Qt::Key_Control || code == Qt::Key_Meta || code == Qt::Key_Alt)) { - // Someone ate the key down event + + // Workaround for QTBUG-77153: + // The Surface Pen eraser button generates Meta+F18/19/20 keystrokes, + // but when it is not touching the screen the Fn Down is eaten and only + // a Fn Up with the previous state as "not pressed" is generated, which + // would be ignored. We detect this case and synthesize the expected events. + if ((msg.lParam & 0x40000000) == 0 && + Qt::KeyboardModifier(state) == Qt::NoModifier && + ((code == Qt::Key_F18) || (code == Qt::Key_F19) || (code == Qt::Key_F20))) { + QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code, + Qt::MetaModifier, scancode, + quint32(msg.wParam), MetaLeft); + QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, code, + Qt::NoModifier, scancode, + quint32(msg.wParam), 0); + result = true; + } } else { if (!code) code = asciiToKeycode(rec->ascii ? char(rec->ascii) : char(msg.wParam), state); diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index b3d961db72d..cffd8427a2c 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -80,13 +80,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q *result = 0; const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam); - POINTER_INPUT_TYPE pointerType; - if (!QWindowsContext::user32dll.getPointerType(pointerId, &pointerType)) { + if (!QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType)) { qWarning() << "GetPointerType() failed:" << qt_error_string(); return false; } - switch (pointerType) { + switch (m_pointerType) { case QT_PT_POINTER: case QT_PT_MOUSE: case QT_PT_TOUCHPAD: { @@ -684,7 +683,7 @@ bool QWindowsPointerHandler::translateMouseWheelEvent(QWindow *window, QPoint localPos = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos); - QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers); + QWindowSystemInterface::handleWheelEvent(receiver, localPos, globalPos, QPoint(), angleDelta, keyModifiers); return true; } @@ -734,7 +733,11 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, } Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; - if (isMouseEventSynthesizedFromPenOrTouch()) { + // Following the logic of the old mouse handler, only events synthesized + // for touch screen are marked as such. On some systems, using the bit 7 of + // the extra msg info for checking if synthesized for touch does not work, + // so we use the pointer type of the last pointer message. + if (isMouseEventSynthesizedFromPenOrTouch() && m_pointerType == QT_PT_TOUCH) { if (QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch) return false; source = Qt::MouseEventSynthesizedBySystem; diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h index 068e804007d..8874db27e33 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.h +++ b/src/plugins/platforms/windows/qwindowspointerhandler.h @@ -82,6 +82,7 @@ private: bool m_needsEnterOnPointerUpdate = false; QEvent::Type m_lastEventType = QEvent::None; Qt::MouseButton m_lastEventButton = Qt::NoButton; + DWORD m_pointerType = 0; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index d919d972116..282c0b107e7 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -303,23 +303,28 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData) m_data.hMonitor = newData.hMonitor; } - if (m_data.geometry != newData.geometry || m_data.availableGeometry != newData.availableGeometry) { - m_data.geometry = newData.geometry; - m_data.availableGeometry = newData.availableGeometry; - QWindowSystemInterface::handleScreenGeometryChange(screen(), - newData.geometry, newData.availableGeometry); - } - if (!qFuzzyCompare(m_data.dpi.first, newData.dpi.first) - || !qFuzzyCompare(m_data.dpi.second, newData.dpi.second)) { - m_data.dpi = newData.dpi; + // QGuiApplicationPrivate::processScreenGeometryChange() checks and emits + // DPI and orientation as well, so, assign new values and emit DPI first. + const bool geometryChanged = m_data.geometry != newData.geometry + || m_data.availableGeometry != newData.availableGeometry; + const bool dpiChanged = !qFuzzyCompare(m_data.dpi.first, newData.dpi.first) + || !qFuzzyCompare(m_data.dpi.second, newData.dpi.second); + const bool orientationChanged = m_data.orientation != newData.orientation; + m_data.dpi = newData.dpi; + m_data.orientation = newData.orientation; + m_data.geometry = newData.geometry; + m_data.availableGeometry = newData.availableGeometry; + + if (dpiChanged) { QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), newData.dpi.first, newData.dpi.second); } - if (m_data.orientation != newData.orientation) { - m_data.orientation = newData.orientation; - QWindowSystemInterface::handleScreenOrientationChange(screen(), - newData.orientation); + if (orientationChanged) + QWindowSystemInterface::handleScreenOrientationChange(screen(), newData.orientation); + if (geometryChanged) { + QWindowSystemInterface::handleScreenGeometryChange(screen(), + newData.geometry, newData.availableGeometry); } } diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp index 3014b30c382..962e4ab938a 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp +++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -196,7 +197,19 @@ bool QWinRTFileEngine::open(QIODevice::OpenMode openMode) hr = QWinRTFunctions::await(op, d->stream.GetAddressOf()); RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::OpenError, false); - d->openMode = openMode; + const ProcessOpenModeResult res = processOpenModeFlags(openMode); + if (!res.ok) { + setError(QFileDevice::OpenError, res.error); + return false; + } + d->openMode = res.openMode; + if (d->openMode & QIODevice::Truncate) { + if (!setSize(0)) { + close(); + setError(QFileDevice::OpenError, QLatin1String("Could not truncate file")); + return false; + } + } return SUCCEEDED(hr); } @@ -257,6 +270,29 @@ qint64 QWinRTFileEngine::size() const return qint64(size); } +bool QWinRTFileEngine::setSize(qint64 size) +{ + Q_D(QWinRTFileEngine); + if (!d->stream) { + setError(QFileDevice::ResizeError, QLatin1String("File must be open to be resized")); + return false; + } + + if (size < 0) { + setError(QFileDevice::ResizeError, QLatin1String("File size cannot be negative")); + return false; + } + + HRESULT hr = d->stream->put_Size(static_cast(size)); + RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ResizeError, false); + if (!flush()) { + setError(QFileDevice::ResizeError, QLatin1String("Could not flush file")); + return false; + } + + return true; +} + qint64 QWinRTFileEngine::pos() const { Q_D(const QWinRTFileEngine); diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.h b/src/plugins/platforms/winrt/qwinrtfileengine.h index 4485917c9e5..453565a95a5 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.h +++ b/src/plugins/platforms/winrt/qwinrtfileengine.h @@ -79,6 +79,7 @@ public: bool close() override; bool flush() override; qint64 size() const override; + bool setSize(qint64 size) override; qint64 pos() const override; bool seek(qint64 pos) override; bool remove() override; diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 0d77889a36b..86ab7651c67 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -669,12 +669,6 @@ QDpi QWinRTScreen::logicalDpi() const return QDpi(d->logicalDpi, d->logicalDpi); } -qreal QWinRTScreen::pixelDensity() const -{ - Q_D(const QWinRTScreen); - return qMax(1, qRound(d->logicalDpi / 96)); -} - qreal QWinRTScreen::scaleFactor() const { Q_D(const QWinRTScreen); diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index 63c254940df..6b57780fa12 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -96,7 +96,6 @@ public: QImage::Format format() const override; QSizeF physicalSize() const override; QDpi logicalDpi() const override; - qreal pixelDensity() const override; qreal scaleFactor() const; QPlatformCursor *cursor() const override; Qt::KeyboardModifiers keyboardModifiers() const; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index d27a288feb1..cac6345b662 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -132,7 +132,9 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra if (!m_startupId.isNull()) qunsetenv("DESKTOP_STARTUP_ID"); + const int focusInDelay = 100; m_focusInTimer.setSingleShot(true); + m_focusInTimer.setInterval(focusInDelay); m_focusInTimer.callOnTimeout([]() { // No FocusIn events for us, proceed with FocusOut normally. QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason); diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp index 82a36c0727e..759ee3cc957 100644 --- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp +++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp @@ -226,11 +226,13 @@ void QXcbEventQueue::run() }; while (!m_closeConnectionDetected && (event = xcb_wait_for_event(connection))) { + m_newEventsMutex.lock(); enqueueEvent(event); while (!m_closeConnectionDetected && (event = xcb_poll_for_queued_event(connection))) enqueueEvent(event); m_newEventsCondition.wakeOne(); + m_newEventsMutex.unlock(); wakeUpDispatcher(); } @@ -350,9 +352,12 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData, void QXcbEventQueue::waitForNewEvents(unsigned long time) { - m_newEventsMutex.lock(); + QMutexLocker locker(&m_newEventsMutex); + QXcbEventNode *tailBeforeFlush = m_flushedTail; + flushBufferedEvents(); + if (tailBeforeFlush != m_flushedTail) + return; m_newEventsCondition.wait(&m_newEventsMutex, time); - m_newEventsMutex.unlock(); } void QXcbEventQueue::sendCloseConnectionEvent() const diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 396b47001de..1d1a4eea1ce 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -848,7 +848,7 @@ void QXcbWindow::doFocusOut() connection()->setFocusWindow(nullptr); relayFocusToModalWindow(); // Do not set the active window to nullptr if there is a FocusIn coming. - connection()->focusInTimer().start(400); + connection()->focusInTimer().start(); } struct QtMotifWmHints { diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp index bf9424897dd..0bae45382d7 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql.cpp +++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp @@ -1506,7 +1506,7 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const // this is safe since postgresql stores only the UTC value and not the timezone offset (only used // while parsing), so we have correct behavior in both case of with timezone and without tz r = QStringLiteral("TIMESTAMP WITH TIME ZONE ") + QLatin1Char('\'') + - QLocale::c().toString(field.value().toDateTime().toUTC(), QStringViewLiteral("yyyy-MM-ddThh:mm:ss.zzz")) + + QLocale::c().toString(field.value().toDateTime().toUTC(), u"yyyy-MM-ddThh:mm:ss.zzz") + QLatin1Char('Z') + QLatin1Char('\''); } else { r = nullStr(); @@ -1518,7 +1518,7 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const case QVariant::Time: #if QT_CONFIG(datestring) if (field.value().toTime().isValid()) { - r = QLatin1Char('\'') + field.value().toTime().toString(QStringViewLiteral("hh:mm:ss.zzz")) + QLatin1Char('\''); + r = QLatin1Char('\'') + field.value().toTime().toString(u"hh:mm:ss.zzz") + QLatin1Char('\''); } else #endif { diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp index f1a003ddcda..001bd673fc1 100644 --- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp +++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp @@ -531,7 +531,7 @@ bool QSQLiteResult::exec() } case QVariant::Time: { const QTime time = value.toTime(); - const QString str = time.toString(QStringViewLiteral("hh:mm:ss.zzz")); + const QString str = time.toString(u"hh:mm:ss.zzz"); res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(), str.size() * sizeof(ushort), SQLITE_TRANSIENT); break; diff --git a/src/plugins/sqldrivers/tds/qsql_tds.cpp b/src/plugins/sqldrivers/tds/qsql_tds.cpp index 603372230d1..9c8d242028d 100644 --- a/src/plugins/sqldrivers/tds/qsql_tds.cpp +++ b/src/plugins/sqldrivers/tds/qsql_tds.cpp @@ -813,7 +813,7 @@ QString QTDSDriver::formatValue(const QSqlField &field, r = QLatin1String("NULL"); else if (field.type() == QVariant::DateTime) { if (field.value().toDateTime().isValid()){ - r = field.value().toDateTime().toString(QStringViewLiteral("yyyyMMdd hh:mm:ss")); + r = field.value().toDateTime().toString(u"yyyyMMdd hh:mm:ss"); r.prepend(QLatin1String("'")); r.append(QLatin1String("'")); } else diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 85bf71be3f0..968ca68619e 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -75,6 +75,8 @@ #include #endif +#include + QT_USE_NAMESPACE static QWindow *qt_getWindow(const QWidget *widget) @@ -456,6 +458,37 @@ static bool setupSlider(NSSlider *slider, const QStyleOptionSlider *sl) return true; } +static void fixStaleGeometry(NSSlider *slider) +{ + // If it's later fixed in AppKit, this function is not needed. + // On macOS Mojave we suddenly have NSSliderCell with a cached + // (and stale) geometry, thus its -drawKnob, -drawBarInside:flipped:, + // -drawTickMarks fail to render the slider properly. Setting the number + // of tickmarks triggers an update in geometry. + + Q_ASSERT(slider); + + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSMojave) + return; + + NSSliderCell *cell = slider.cell; + const NSRect barRect = [cell barRectFlipped:NO]; + const NSSize sliderSize = slider.frame.size; + CGFloat difference = 0.; + if (slider.vertical) + difference = std::abs(sliderSize.height - barRect.size.height); + else + difference = std::abs(sliderSize.width - barRect.size.width); + + if (difference > 6.) { + // Stale ... + const auto nOfTicks = slider.numberOfTickMarks; + // Non-zero, different from nOfTicks to force update + slider.numberOfTickMarks = nOfTicks + 10; + slider.numberOfTickMarks = nOfTicks; + } +} + static bool isInMacUnifiedToolbarArea(QWindow *window, int windowY) { QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); @@ -2083,10 +2116,9 @@ void QMacStyle::unpolish(QWidget* w) #if QT_CONFIG(menu) qobject_cast(w) && #endif - !w->testAttribute(Qt::WA_SetPalette)) { - QPalette pal = qApp->palette(w); - w->setPalette(pal); - w->setAttribute(Qt::WA_SetPalette, false); + !w->testAttribute(Qt::WA_SetPalette)) + { + w->setPalette(QPalette()); w->setWindowOpacity(1.0); } @@ -2102,9 +2134,9 @@ void QMacStyle::unpolish(QWidget* w) #if QT_CONFIG(tabbar) if (qobject_cast(w)) { if (!w->testAttribute(Qt::WA_SetFont)) - w->setFont(qApp->font(w)); + w->setFont(QFont()); if (!w->testAttribute(Qt::WA_SetPalette)) - w->setPalette(qApp->palette(w)); + w->setPalette(QPalette()); } #endif @@ -5241,9 +5273,20 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex } 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); + + // Since the GC is flipped, upsideDown means *not* inverted when vertical. + const bool verticalFlip = !isHorizontal && !sl->upsideDown; // FIXME: && !isSierraOrLater + + if (isHorizontal) { + if (sl->upsideDown) { + CGContextTranslateCTM(ctx, rect.size.width, rect.origin.y); + CGContextScaleCTM(ctx, -1, 1); + } else { + CGContextTranslateCTM(ctx, 0, rect.origin.y); + } + } else if (verticalFlip) { + CGContextTranslateCTM(ctx, rect.origin.x, rect.size.height); + CGContextScaleCTM(ctx, 1, -1); } if (hasDoubleTicks) { @@ -5254,9 +5297,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex CGContextTranslateCTM(ctx, 1, 0); } - // Since the GC is flipped, upsideDown means *not* inverted when vertical. - const bool verticalFlip = !isHorizontal && !sl->upsideDown; // FIXME: && !isSierraOrLater - #if 0 // FIXME: Sadly, this part doesn't work. It seems to somehow polute the // NSSlider's internal state and, when we need to use the "else" part, @@ -5276,6 +5316,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex #endif { [slider calcSize]; + if (!hasDoubleTicks) + fixStaleGeometry(slider); NSSliderCell *cell = slider.cell; const int numberOfTickMarks = slider.numberOfTickMarks; @@ -5285,10 +5327,10 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex const CGRect barRect = [cell barRectFlipped:hasTicks]; if (drawBar) { + [cell drawBarInside:barRect flipped:!verticalFlip]; // This ain't HIG kosher: force unfilled bar look. if (hasDoubleTicks) slider.numberOfTickMarks = numberOfTickMarks; - [cell drawBarInside:barRect flipped:!verticalFlip]; } if (hasTicks && drawTicks) { @@ -5318,9 +5360,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex // This ain't HIG kosher: force round knob look. if (hasDoubleTicks) slider.numberOfTickMarks = 0; - // Draw the knob in the symmetrical position instead of flipping. - if (verticalFlip) - slider.intValue = slider.maxValue - slider.intValue + slider.minValue; [cell drawKnob]; } } diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp index 5236b8c8fa4..2fc46219602 100644 --- a/src/printsupport/kernel/qcups.cpp +++ b/src/printsupport/kernel/qcups.cpp @@ -106,7 +106,7 @@ static inline QString jobHoldToString(const QCUPSSupport::JobHoldUntil jobHold, if (holdUntilTime < localDateTime.time()) localDateTime = localDateTime.addDays(1); localDateTime.setTime(holdUntilTime); - return localDateTime.toUTC().time().toString(QStringViewLiteral("HH:mm")); + return localDateTime.toUTC().time().toString(u"HH:mm"); } // else fall through: Q_FALLTHROUGH(); diff --git a/src/src.pro b/src/src.pro index 9ccc1e8f65e..832a3b6d82f 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,8 +1,10 @@ TEMPLATE = subdirs -QT_FOR_CONFIG += core-private gui-private +QT_FOR_CONFIG += core-private gui-private printsupport + include($$OUT_PWD/corelib/qtcore-config.pri) include($$OUT_PWD/gui/qtgui-config.pri) +include($$OUT_PWD/printsupport/qtprintsupport-config.pri) force_bootstrap|!qtConfig(commandlineparser): \ CONFIG += force_dbus_bootstrap @@ -225,11 +227,13 @@ qtConfig(gui) { src_testlib.depends += src_gui # if QtGui is enabled, QtTest requires QtGui's headers qtConfig(widgets) { SUBDIRS += src_tools_uic src_widgets - !android-embedded: SUBDIRS += src_printsupport TOOLS += src_tools_uic src_plugins.depends += src_widgets - !android-embedded: src_plugins.depends += src_printsupport src_testlib.depends += src_widgets # if QtWidgets is enabled, QtTest requires QtWidgets's headers + qtConfig(printer) { + SUBDIRS += src_printsupport + src_plugins.depends += src_printsupport + } qtConfig(opengl) { SUBDIRS += src_opengl src_plugins.depends += src_opengl diff --git a/src/testlib/qabstracttestlogger.cpp b/src/testlib/qabstracttestlogger.cpp index 2b54cd410bd..ff05dd88c7e 100644 --- a/src/testlib/qabstracttestlogger.cpp +++ b/src/testlib/qabstracttestlogger.cpp @@ -87,7 +87,7 @@ QAbstractTestLogger::~QAbstractTestLogger() if (stream != stdout) { fclose(stream); } - stream = 0; + stream = nullptr; } void QAbstractTestLogger::filterUnprintable(char *str) const diff --git a/src/testlib/qabstracttestlogger_p.h b/src/testlib/qabstracttestlogger_p.h index 9bb1d1e80ca..e5a1404c16a 100644 --- a/src/testlib/qabstracttestlogger_p.h +++ b/src/testlib/qabstracttestlogger_p.h @@ -117,8 +117,7 @@ struct QTestCharBuffer { enum { InitialSize = 512 }; - inline QTestCharBuffer() - : _size(InitialSize), buf(staticBuf) + inline QTestCharBuffer() : buf(staticBuf) { staticBuf[0] = '\0'; } @@ -170,7 +169,7 @@ struct QTestCharBuffer } private: - int _size; + int _size = InitialSize; char* buf; char staticBuf[InitialSize]; }; diff --git a/src/testlib/qbenchmark.cpp b/src/testlib/qbenchmark.cpp index cbc009c9932..aafdc64831c 100644 --- a/src/testlib/qbenchmark.cpp +++ b/src/testlib/qbenchmark.cpp @@ -51,14 +51,6 @@ QT_BEGIN_NAMESPACE QBenchmarkGlobalData *QBenchmarkGlobalData::current; QBenchmarkGlobalData::QBenchmarkGlobalData() - : measurer(0) - , walltimeMinimum(-1) - , iterationCount(-1) - , medianIterationCount(-1) - , createChart(false) - , verboseOutput(false) - , minimumTotal(-1) - , mode_(WallTime) { setMode(mode_); } @@ -74,14 +66,13 @@ void QBenchmarkGlobalData::setMode(Mode mode) { mode_ = mode; - if (measurer) - delete measurer; + delete measurer; measurer = createMeasurer(); } QBenchmarkMeasurerBase * QBenchmarkGlobalData::createMeasurer() { - QBenchmarkMeasurerBase *measurer = 0; + QBenchmarkMeasurerBase *measurer = nullptr; if (0) { #if QT_CONFIG(valgrind) } else if (mode_ == CallgrindChildProcess || mode_ == CallgrindParentProcess) { @@ -106,24 +97,18 @@ QBenchmarkMeasurerBase * QBenchmarkGlobalData::createMeasurer() int QBenchmarkGlobalData::adjustMedianIterationCount() { - if (medianIterationCount != -1) { - return medianIterationCount; - } else { - return measurer->adjustMedianCount(1); - } + return medianIterationCount != -1 + ? medianIterationCount : measurer->adjustMedianCount(1); } QBenchmarkTestMethodData *QBenchmarkTestMethodData::current; -QBenchmarkTestMethodData::QBenchmarkTestMethodData() -:resultAccepted(false), runOnce(false), iterationCount(-1) -{ -} +QBenchmarkTestMethodData::QBenchmarkTestMethodData() = default; QBenchmarkTestMethodData::~QBenchmarkTestMethodData() { - QBenchmarkTestMethodData::current = 0; + QBenchmarkTestMethodData::current = nullptr; } void QBenchmarkTestMethodData::beginDataRun() diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h index 49868ac23aa..93b5becb2b4 100644 --- a/src/testlib/qbenchmark_p.h +++ b/src/testlib/qbenchmark_p.h @@ -81,7 +81,7 @@ struct QBenchmarkContext QString slotName; QString tag; // from _data() function - int checkpointIndex; + int checkpointIndex = -1; QString toString() const { @@ -89,7 +89,7 @@ struct QBenchmarkContext .arg(slotName, tag, QString::number(checkpointIndex)); } - QBenchmarkContext() : checkpointIndex(-1) {} + QBenchmarkContext() = default; }; Q_DECLARE_TYPEINFO(QBenchmarkContext, Q_MOVABLE_TYPE); @@ -97,19 +97,13 @@ class QBenchmarkResult { public: QBenchmarkContext context; - qreal value; - int iterations; - QTest::QBenchmarkMetric metric; - bool setByMacro; - bool valid; + qreal value = -1; + int iterations = -1; + QTest::QBenchmarkMetric metric = QTest::FramesPerSecond; + bool setByMacro = true; + bool valid = false; - QBenchmarkResult() - : value(-1) - , iterations(-1) - , metric(QTest::FramesPerSecond) - , setByMacro(true) - , valid(false) - { } + QBenchmarkResult() = default; QBenchmarkResult( const QBenchmarkContext &context, const qreal value, const int iterations, @@ -147,17 +141,17 @@ public: QBenchmarkMeasurerBase *createMeasurer(); int adjustMedianIterationCount(); - QBenchmarkMeasurerBase *measurer; + QBenchmarkMeasurerBase *measurer = nullptr; QBenchmarkContext context; - int walltimeMinimum; - int iterationCount; - int medianIterationCount; - bool createChart; - bool verboseOutput; + int walltimeMinimum = -1; + int iterationCount = -1; + int medianIterationCount = -1; + bool createChart = false; + bool verboseOutput = false; QString callgrindOutFileBase; - int minimumTotal; + int minimumTotal = -1; private: - Mode mode_; + Mode mode_ = WallTime; }; /* @@ -184,9 +178,9 @@ public: void setResult(qreal value, QTest::QBenchmarkMetric metric, bool setByMacro = true); QBenchmarkResult result; - bool resultAccepted; - bool runOnce; - int iterationCount; + bool resultAccepted = false; + bool runOnce = false; + int iterationCount = -1; }; // low-level API: diff --git a/src/testlib/qbenchmarkevent.cpp b/src/testlib/qbenchmarkevent.cpp index a8270219e46..bcae9325cde 100644 --- a/src/testlib/qbenchmarkevent.cpp +++ b/src/testlib/qbenchmarkevent.cpp @@ -44,14 +44,9 @@ QT_BEGIN_NAMESPACE -QBenchmarkEvent::QBenchmarkEvent() - : eventCounter(0) -{ -} +QBenchmarkEvent::QBenchmarkEvent() = default; -QBenchmarkEvent::~QBenchmarkEvent() -{ -} +QBenchmarkEvent::~QBenchmarkEvent() = default; void QBenchmarkEvent::start() { diff --git a/src/testlib/qbenchmarkevent_p.h b/src/testlib/qbenchmarkevent_p.h index 0f47aa475c9..9fe3daa33b4 100644 --- a/src/testlib/qbenchmarkevent_p.h +++ b/src/testlib/qbenchmarkevent_p.h @@ -76,7 +76,7 @@ public: #else bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override; #endif - qint64 eventCounter; + qint64 eventCounter = 0; }; QT_END_NAMESPACE diff --git a/src/testlib/qbenchmarkmeasurement_p.h b/src/testlib/qbenchmarkmeasurement_p.h index 8dbfd4b6180..1e2b82c25d6 100644 --- a/src/testlib/qbenchmarkmeasurement_p.h +++ b/src/testlib/qbenchmarkmeasurement_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE class QBenchmarkMeasurerBase { public: - virtual ~QBenchmarkMeasurerBase() {} + virtual ~QBenchmarkMeasurerBase() = default; virtual void init() {} virtual void start() = 0; virtual qint64 checkpoint() = 0; @@ -66,7 +66,7 @@ public: virtual bool isMeasurementAccepted(qint64 measurement) = 0; virtual int adjustIterationCount(int suggestion) = 0; virtual int adjustMedianCount(int suggestion) = 0; - virtual bool repeatCount() { return 1; } + virtual bool repeatCount() { return true; } virtual bool needsWarmupIteration() { return false; } virtual QTest::QBenchmarkMetric metricType() = 0; }; diff --git a/src/testlib/qbenchmarkperfevents.cpp b/src/testlib/qbenchmarkperfevents.cpp index 91f0792338e..e8c6969d4af 100644 --- a/src/testlib/qbenchmarkperfevents.cpp +++ b/src/testlib/qbenchmarkperfevents.cpp @@ -147,7 +147,7 @@ bool QBenchmarkPerfEventsMeasurer::isAvailable() { // this generates an EFAULT because attr == NULL if perf_event_open is available // if the kernel is too old, it generates ENOSYS - return perf_event_open(0, 0, 0, 0, 0) == -1 && errno != ENOSYS; + return perf_event_open(nullptr, 0, 0, 0, 0) == -1 && errno != ENOSYS; } /* Event list structure @@ -500,10 +500,7 @@ void QBenchmarkPerfEventsMeasurer::listCounters() "Attributes can be combined, for example: -perfcounter branch-mispredicts:kh\n"); } -QBenchmarkPerfEventsMeasurer::QBenchmarkPerfEventsMeasurer() - : fd(-1) -{ -} +QBenchmarkPerfEventsMeasurer::QBenchmarkPerfEventsMeasurer() = default; QBenchmarkPerfEventsMeasurer::~QBenchmarkPerfEventsMeasurer() { diff --git a/src/testlib/qbenchmarkperfevents_p.h b/src/testlib/qbenchmarkperfevents_p.h index 86ba5565494..3f27161ef50 100644 --- a/src/testlib/qbenchmarkperfevents_p.h +++ b/src/testlib/qbenchmarkperfevents_p.h @@ -60,23 +60,23 @@ class QBenchmarkPerfEventsMeasurer : public QBenchmarkMeasurerBase public: QBenchmarkPerfEventsMeasurer(); ~QBenchmarkPerfEventsMeasurer(); - virtual void init() override; - virtual void start() override; - virtual qint64 checkpoint() override; - virtual qint64 stop() override; - virtual bool isMeasurementAccepted(qint64 measurement) override; - virtual int adjustIterationCount(int suggestion) override; - virtual int adjustMedianCount(int suggestion) override; - virtual bool repeatCount() override { return 1; } - virtual bool needsWarmupIteration() override { return true; } - virtual QTest::QBenchmarkMetric metricType() override; + void init() override; + void start() override; + qint64 checkpoint() override; + qint64 stop() override; + bool isMeasurementAccepted(qint64 measurement) override; + int adjustIterationCount(int suggestion) override; + int adjustMedianCount(int suggestion) override; + bool repeatCount() override { return true; } + bool needsWarmupIteration() override { return true; } + QTest::QBenchmarkMetric metricType() override; static bool isAvailable(); static QTest::QBenchmarkMetric metricForEvent(quint32 type, quint64 event_id); static void setCounter(const char *name); static void listCounters(); private: - int fd; + int fd = -1; qint64 readValue(); }; diff --git a/src/testlib/qbenchmarkvalgrind.cpp b/src/testlib/qbenchmarkvalgrind.cpp index 0dac8043386..44888c4d30e 100644 --- a/src/testlib/qbenchmarkvalgrind.cpp +++ b/src/testlib/qbenchmarkvalgrind.cpp @@ -168,7 +168,7 @@ QString QBenchmarkValgrindUtils::outFileBase(qint64 pid) // Returns \c true upon success, otherwise false. bool QBenchmarkValgrindUtils::runCallgrindSubProcess(const QStringList &origAppArgs, int &exitCode) { - const QString execFile(origAppArgs.at(0)); + const QString &execFile = origAppArgs.at(0); QStringList args; args << QLatin1String("--tool=callgrind") << QLatin1String("--instr-atstart=yes") << QLatin1String("--quiet") @@ -177,7 +177,7 @@ bool QBenchmarkValgrindUtils::runCallgrindSubProcess(const QStringList &origAppA // pass on original arguments that make sense (e.g. avoid wasting time producing output // that will be ignored anyway) ... for (int i = 1; i < origAppArgs.size(); ++i) { - const QString arg(origAppArgs.at(i)); + const QString &arg = origAppArgs.at(i); if (arg == QLatin1String("-callgrind")) continue; args << arg; // ok to pass on diff --git a/src/testlib/qcsvbenchmarklogger.cpp b/src/testlib/qcsvbenchmarklogger.cpp index ee7270b6344..f410ec6e3da 100644 --- a/src/testlib/qcsvbenchmarklogger.cpp +++ b/src/testlib/qcsvbenchmarklogger.cpp @@ -46,9 +46,7 @@ QCsvBenchmarkLogger::QCsvBenchmarkLogger(const char *filename) { } -QCsvBenchmarkLogger::~QCsvBenchmarkLogger() -{ -} +QCsvBenchmarkLogger::~QCsvBenchmarkLogger() = default; void QCsvBenchmarkLogger::startLogging() { diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp index ed53dcdde8d..c2e0bebaa0d 100644 --- a/src/testlib/qplaintestlogger.cpp +++ b/src/testlib/qplaintestlogger.cpp @@ -316,9 +316,7 @@ QPlainTestLogger::QPlainTestLogger(const char *filename) { } -QPlainTestLogger::~QPlainTestLogger() -{ -} +QPlainTestLogger::~QPlainTestLogger() = default; void QPlainTestLogger::startLogging() { diff --git a/src/testlib/qsignaldumper.cpp b/src/testlib/qsignaldumper.cpp index d0b6d0dd3ff..70f4d5e63db 100644 --- a/src/testlib/qsignaldumper.cpp +++ b/src/testlib/qsignaldumper.cpp @@ -56,7 +56,7 @@ namespace QTest inline static void qPrintMessage(const QByteArray &ba) { - QTestLog::info(ba.constData(), 0, 0); + QTestLog::info(ba.constData(), nullptr, 0); } Q_GLOBAL_STATIC(QList, ignoreClasses) @@ -169,7 +169,7 @@ static void qSignalDumperCallbackEndSignal(QObject *caller, int /*signal_index*/ void QSignalDumper::startDump() { static QSignalSpyCallbackSet set = { QTest::qSignalDumperCallback, - QTest::qSignalDumperCallbackSlot, QTest::qSignalDumperCallbackEndSignal, 0 }; + QTest::qSignalDumperCallbackSlot, QTest::qSignalDumperCallbackEndSignal, nullptr }; qt_register_signal_spy_callbacks(&set); } diff --git a/src/testlib/qtaptestlogger.cpp b/src/testlib/qtaptestlogger.cpp index 476761e602b..5b5a3c48756 100644 --- a/src/testlib/qtaptestlogger.cpp +++ b/src/testlib/qtaptestlogger.cpp @@ -55,9 +55,7 @@ QTapTestLogger::QTapTestLogger(const char *filename) { } -QTapTestLogger::~QTapTestLogger() -{ -} +QTapTestLogger::~QTapTestLogger() = default; void QTapTestLogger::startLogging() { diff --git a/src/testlib/qteamcitylogger.cpp b/src/testlib/qteamcitylogger.cpp index 88c83d12699..8a771434542 100644 --- a/src/testlib/qteamcitylogger.cpp +++ b/src/testlib/qteamcitylogger.cpp @@ -103,9 +103,7 @@ QTeamCityLogger::QTeamCityLogger(const char *filename) { } -QTeamCityLogger::~QTeamCityLogger() -{ -} +QTeamCityLogger::~QTeamCityLogger() = default; void QTeamCityLogger::startLogging() { @@ -224,9 +222,7 @@ QString QTeamCityLogger::tcEscapedString(const QString &str) const { QString formattedString; - for (int i = 0; i < str.length(); i++) { - QChar ch = str.at(i); - + for (QChar ch : str) { switch (ch.toLatin1()) { case '\n': formattedString.append(QLatin1String("|n")); diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index 7affdcb8b49..cdf0800371e 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -91,25 +92,35 @@ template<> inline char *toString(const QByteArray &ba) return QTest::toPrettyCString(ba.constData(), ba.length()); } +template<> inline char *toString(const QBitArray &ba) +{ + qsizetype size = ba.size(); + char *str = static_cast(malloc(size + 1)); + for (qsizetype i = 0; i < size; ++i) + str[i] = "01"[ba.testBit(i)]; + str[size] = '\0'; + return str; +} + #if QT_CONFIG(datestring) template<> inline char *toString(const QTime &time) { return time.isValid() - ? qstrdup(qPrintable(time.toString(QStringViewLiteral("hh:mm:ss.zzz")))) + ? qstrdup(qPrintable(time.toString(u"hh:mm:ss.zzz"))) : qstrdup("Invalid QTime"); } template<> inline char *toString(const QDate &date) { return date.isValid() - ? qstrdup(qPrintable(date.toString(QStringViewLiteral("yyyy/MM/dd")))) + ? qstrdup(qPrintable(date.toString(u"yyyy/MM/dd"))) : qstrdup("Invalid QDate"); } template<> inline char *toString(const QDateTime &dateTime) { return dateTime.isValid() - ? qstrdup(qPrintable(dateTime.toString(QStringViewLiteral("yyyy/MM/dd hh:mm:ss.zzz[t]")))) + ? qstrdup(qPrintable(dateTime.toString(u"yyyy/MM/dd hh:mm:ss.zzz[t]"))) : qstrdup("Invalid QDateTime"); } #endif // datestring diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h index e5101e6955e..d1efde54b1c 100644 --- a/src/testlib/qtest_gui.h +++ b/src/testlib/qtest_gui.h @@ -162,6 +162,14 @@ inline bool qCompare(QImage const &t1, QImage const &t2, } if (t1Null && t2Null) return compare_helper(true, nullptr, nullptr, nullptr, actual, expected, file, line); + if (!qFuzzyCompare(t1.devicePixelRatioF(), t2.devicePixelRatioF())) { + qsnprintf(msg, 1024, "Compared QImages differ in device pixel ratio.\n" + " Actual (%s): %g\n" + " Expected (%s): %g", + actual, t1.devicePixelRatioF(), + expected, t2.devicePixelRatioF()); + return compare_helper(false, msg, nullptr, nullptr, actual, expected, file, line); + } if (t1.width() != t2.width() || t1.height() != t2.height()) { qsnprintf(msg, 1024, "Compared QImages differ in size.\n" " Actual (%s): %dx%d\n" @@ -196,6 +204,14 @@ inline bool qCompare(QPixmap const &t1, QPixmap const &t2, const char *actual, c } if (t1Null && t2Null) return compare_helper(true, nullptr, nullptr, nullptr, actual, expected, file, line); + if (!qFuzzyCompare(t1.devicePixelRatioF(), t2.devicePixelRatioF())) { + qsnprintf(msg, 1024, "Compared QPixmaps differ in device pixel ratio.\n" + " Actual (%s): %g\n" + " Expected (%s): %g", + actual, t1.devicePixelRatioF(), + expected, t2.devicePixelRatioF()); + return compare_helper(false, msg, nullptr, nullptr, actual, expected, file, line); + } if (t1.width() != t2.width() || t1.height() != t2.height()) { qsnprintf(msg, 1024, "Compared QPixmaps differ in size.\n" " Actual (%s): %dx%d\n" diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index 15f01c4af03..91258e9ec45 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -169,12 +169,14 @@ static QSet keywords() #endif ; +#if QT_CONFIG(properties) QCoreApplication *app = QCoreApplication::instance(); if (app) { const QVariant platformName = app->property("platformName"); if (platformName.isValid()) set << platformName.toByteArray(); } +#endif return set; } @@ -218,11 +220,10 @@ static bool checkCondition(const QByteArray &condition) static const QSet matchedConditions = activeConditions(); QList conds = condition.split(' '); - for (int i = 0; i < conds.size(); ++i) { - QByteArray c = conds.at(i); + for (QByteArray c : conds) { bool result = c.startsWith('!'); if (result) - c = c.mid(1); + c.remove(0, 1); result ^= matchedConditions.contains(c); if (!result) @@ -232,7 +233,7 @@ static bool checkCondition(const QByteArray &condition) } static bool ignoreAll = false; -static std::set *ignoredTests = 0; +static std::set *ignoredTests = nullptr; namespace QTestPrivate { diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index cfd3598072d..839f5564309 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -289,7 +289,7 @@ namespace QTest { class WatchDog; -static QObject *currentTestObject = 0; +static QObject *currentTestObject = nullptr; static QString mainSourcePath; #if defined(Q_OS_MACOS) @@ -423,7 +423,7 @@ Q_TESTLIB_EXPORT bool printAvailableFunctions = false; Q_TESTLIB_EXPORT QStringList testFunctions; Q_TESTLIB_EXPORT QStringList testTags; -static void qPrintTestSlots(FILE *stream, const char *filter = 0) +static void qPrintTestSlots(FILE *stream, const char *filter = nullptr) { for (int i = 0; i < QTest::currentTestObject->metaObject()->methodCount(); ++i) { QMetaMethod sl = QTest::currentTestObject->metaObject()->method(i); @@ -516,7 +516,7 @@ static int qToInt(const char *str) Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool qml) { int logFormat = -1; // Not set - const char *logFilename = 0; + const char *logFilename = nullptr; QTest::testFunctions.clear(); QTest::testTags.clear(); @@ -897,7 +897,7 @@ struct QTestDataSetter } ~QTestDataSetter() { - QTestResult::setCurrentTestData(0); + QTestResult::setCurrentTestData(nullptr); } }; @@ -974,11 +974,11 @@ void TestMethods::invokeTestOnData(int index) const if (i == -1) { QTestLog::info(qPrintable( QString::fromLatin1("warmup stage result : %1") - .arg(QBenchmarkTestMethodData::current->result.value)), 0, 0); + .arg(QBenchmarkTestMethodData::current->result.value)), nullptr, 0); } else { QTestLog::info(qPrintable( QString::fromLatin1("accumulation stage result: %1") - .arg(QBenchmarkTestMethodData::current->result.value)), 0, 0); + .arg(QBenchmarkTestMethodData::current->result.value)), nullptr, 0); } } } @@ -1040,7 +1040,7 @@ public: void run() override { QMutexLocker locker(&mutex); waitCondition.wakeAll(); - while (1) { + while (true) { int t = timeout.loadRelaxed(); if (!t) break; @@ -1115,7 +1115,7 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co if (data && !dataCount) { // Let empty data tag through. if (!*data) - data = 0; + data = nullptr; else { fprintf(stderr, "Unknown testdata for function %s(): '%s'\n", name.constData(), data); fprintf(stderr, "Function has no testdata.\n"); @@ -1130,10 +1130,9 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) { foundFunction = true; - QTestPrivate::checkBlackLists(name.constData(), dataCount ? table.testData(curDataIndex)->dataTag() : 0); + QTestPrivate::checkBlackLists(name.constData(), dataCount ? table.testData(curDataIndex)->dataTag() : nullptr); - QTestDataSetter s(curDataIndex >= dataCount ? static_cast(0) - : table.testData(curDataIndex)); + QTestDataSetter s(curDataIndex >= dataCount ? nullptr : table.testData(curDataIndex)); QTestPrivate::qtestMouseButtons = Qt::NoButton; if (watchDog) @@ -1156,14 +1155,14 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co return false; } - QTestResult::setCurrentGlobalTestData(0); + QTestResult::setCurrentGlobalTestData(nullptr); ++curGlobalDataIndex; } while (curGlobalDataIndex < globalDataCount); QTestResult::finishedCurrentTestFunction(); QTestResult::setSkipCurrentTest(false); QTestResult::setBlacklistCurrentTest(false); - QTestResult::setCurrentTestData(0); + QTestResult::setCurrentTestData(nullptr); return true; } @@ -1241,7 +1240,7 @@ char *toHexRepresentation(const char *ba, int length) * */ const int maxLen = 50; const int len = qMin(maxLen, length); - char *result = 0; + char *result = nullptr; if (length > maxLen) { const int size = len * 3 + 4; @@ -1274,10 +1273,8 @@ char *toHexRepresentation(const char *ba, int length) ++o; if (i == len) break; - else { - result[o] = ' '; - ++o; - } + result[o] = ' '; + ++o; } return result; @@ -1497,7 +1494,7 @@ void TestMethods::invokeTests(QObject *testObject) const QTestResult::finishedCurrentTestDataCleanup(); } QTestResult::finishedCurrentTestFunction(); - QTestResult::setCurrentTestFunction(0); + QTestResult::setCurrentTestFunction(nullptr); } #if defined(Q_OS_UNIX) @@ -1567,7 +1564,7 @@ FatalSignalHandler::FatalSignalHandler() stack.ss_flags = 0; stack.ss_size = sizeof alternate_stack; stack.ss_sp = alternate_stack; - sigaltstack(&stack, 0); + sigaltstack(&stack, nullptr); act.sa_flags |= SA_ONSTACK; #endif @@ -1586,7 +1583,7 @@ FatalSignalHandler::FatalSignalHandler() oldact.sa_flags & SA_SIGINFO || #endif oldact.sa_handler != SIG_DFL) { - sigaction(fatalSignals[i], &oldact, 0); + sigaction(fatalSignals[i], &oldact, nullptr); } else { sigaddset(&handledSignals, fatalSignals[i]); @@ -1611,7 +1608,7 @@ FatalSignalHandler::~FatalSignalHandler() // If someone overwrote it in the mean time, put it back if (oldact.sa_handler != FatalSignalHandler::signal) - sigaction(i, &oldact, 0); + sigaction(i, &oldact, nullptr); } } @@ -1927,7 +1924,7 @@ int QTest::qRun() QTestResult::addFailure("Caught unhandled exception", __FILE__, __LINE__); if (QTestResult::currentTestFunction()) { QTestResult::finishedCurrentTestFunction(); - QTestResult::setCurrentTestFunction(0); + QTestResult::setCurrentTestFunction(nullptr); } QTestLog::stopLogging(); @@ -1936,7 +1933,7 @@ int QTest::qRun() IOPMAssertionRelease(powerID); } #endif - currentTestObject = 0; + currentTestObject = nullptr; // Rethrow exception to make debugging easier. throw; @@ -1957,13 +1954,13 @@ int QTest::qRun() */ void QTest::qCleanup() { - currentTestObject = 0; + currentTestObject = nullptr; QTestTable::clearGlobalTestTable(); QTestLog::stopLogging(); delete QBenchmarkGlobalData::current; - QBenchmarkGlobalData::current = 0; + QBenchmarkGlobalData::current = nullptr; QSignalDumper::endDump(); @@ -2566,9 +2563,9 @@ bool QTest::qCompare(qfloat16 const &t1, qfloat16 const &t2, const char *actual, bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line) { - return compare_helper(floatingCompare(t1, t2), - "Compared floats are not the same (fuzzy compare)", - toString(t1), toString(t2), actual, expected, file, line); + return QTestResult::compare(floatingCompare(t1, t2), + "Compared floats are not the same (fuzzy compare)", + t1, t2, actual, expected, file, line); } /*! \fn bool QTest::qCompare(const double &t1, const double &t2, const char *actual, const char *expected, const char *file, int line) @@ -2577,11 +2574,86 @@ 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(floatingCompare(t1, t2), - "Compared doubles are not the same (fuzzy compare)", - toString(t1), toString(t2), actual, expected, file, line); + return QTestResult::compare(floatingCompare(t1, t2), + "Compared doubles are not the same (fuzzy compare)", + t1, t2, actual, expected, file, line); } +/*! \fn bool QTest::qCompare(int t1, int t2, const char *actual, const char *expected, const char *file, int line) + \internal + \since 5.14 + */ +bool QTest::qCompare(int t1, int t2, const char *actual, const char *expected, + const char *file, int line) +{ + return QTestResult::compare(t1 == t2, + "Compared values are not the same", + t1, t2, actual, expected, file, line); +} + +/*! \fn bool QTest::qCompare(unsigned t1, unsigned t2, const char *actual, const char *expected, const char *file, int line) + \internal + \since 5.14 + */ +bool QTest::qCompare(unsigned t1, unsigned t2, const char *actual, const char *expected, + const char *file, int line) +{ + return QTestResult::compare(t1 == t2, + "Compared values are not the same", + t1, t2, actual, expected, file, line); +} + +/*! \fn bool QTest::qCompare(QStringView t1, QStringView t2, const char *actual, const char *expected, const char *file, int line) + \internal + \since 5.14 + */ +bool QTest::qCompare(QStringView t1, QStringView t2, const char *actual, const char *expected, + const char *file, int line) +{ + return QTestResult::compare(t1 == t2, + "Compared values are not the same", + t1, t2, actual, expected, file, line); +} + +/*! \fn bool QTest::qCompare(QStringView t1, const QLatin1String &t2, const char *actual, const char *expected, const char *file, int line) + \internal + \since 5.14 + */ +bool QTest::qCompare(QStringView t1, const QLatin1String &t2, const char *actual, const char *expected, + const char *file, int line) +{ + return QTestResult::compare(t1 == t2, + "Compared values are not the same", + t1, t2, actual, expected, file, line); +} + +/*! \fn bool QTest::qCompare(const QLatin1String &t1, QStringView t2, const char *actual, const char *expected, const char *file, int line) + \internal + \since 5.14 + */ +bool QTest::qCompare(const QLatin1String &t1, QStringView t2, const char *actual, const char *expected, + const char *file, int line) +{ + return QTestResult::compare(t1 == t2, + "Compared values are not the same", + t1, t2, actual, expected, file, line); +} + +/*! \fn bool QTest::qCompare(const QString &t1, const QString &t2, const char *actual, const char *expected, const char *file, int line) + \internal + \since 5.14 + */ + +/*! \fn bool QTest::qCompare(const QString &t1, const QLatin1String &t2, const char *actual, const char *expected, const char *file, int line) + \internal + \since 5.14 + */ + +/*! \fn bool QTest::qCompare(const QLatin1String &t1, const QString &t2, const char *actual, const char *expected, const char *file, int line) + \internal + \since 5.14 + */ + /*! \fn bool QTest::qCompare(const double &t1, const float &t2, const char *actual, const char *expected, const char *file, int line) \internal */ @@ -2719,7 +2791,7 @@ template <> Q_TESTLIB_EXPORT char *QTest::toString(const char &t) char *QTest::toString(const char *str) { if (!str) - return 0; + return nullptr; char *msg = new char[strlen(str) + 1]; return qstrcpy(msg, str); } diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h index c0ddb93bd03..1667bc254b4 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -368,6 +368,40 @@ namespace QTest Q_TESTLIB_EXPORT bool qCompare(double const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line); + Q_TESTLIB_EXPORT bool qCompare(int t1, int t2, const char *actual, const char *expected, + const char *file, int line); + + Q_TESTLIB_EXPORT bool qCompare(unsigned t1, unsigned t2, const char *actual, const char *expected, + const char *file, int line); + + Q_TESTLIB_EXPORT bool qCompare(QStringView t1, QStringView t2, + const char *actual, const char *expected, + const char *file, int line); + Q_TESTLIB_EXPORT bool qCompare(QStringView t1, const QLatin1String &t2, + const char *actual, const char *expected, + const char *file, int line); + Q_TESTLIB_EXPORT bool qCompare(const QLatin1String &t1, QStringView t2, + const char *actual, const char *expected, + const char *file, int line); + inline bool qCompare(const QString &t1, const QString &t2, + const char *actual, const char *expected, + const char *file, int line) + { + return qCompare(QStringView(t1), QStringView(t2), actual, expected, file, line); + } + inline bool qCompare(const QString &t1, const QLatin1String &t2, + const char *actual, const char *expected, + const char *file, int line) + { + return qCompare(QStringView(t1), t2, actual, expected, file, line); + } + inline bool qCompare(const QLatin1String &t1, const QString &t2, + const char *actual, const char *expected, + const char *file, int line) + { + return qCompare(t1, QStringView(t2), actual, expected, file, line); + } + inline bool compare_ptr_helper(const volatile void *t1, const volatile void *t2, const char *actual, const char *expected, const char *file, int line) { diff --git a/src/testlib/qtestcoreelement_p.h b/src/testlib/qtestcoreelement_p.h index 84406fed857..a101ab5ea31 100644 --- a/src/testlib/qtestcoreelement_p.h +++ b/src/testlib/qtestcoreelement_p.h @@ -74,13 +74,13 @@ class QTestCoreElement: public QTestCoreList QTest::LogElementType elementType() const; private: - QTestElementAttribute *listOfAttributes; + QTestElementAttribute *listOfAttributes = nullptr; QTest::LogElementType type; }; template QTestCoreElement::QTestCoreElement(int t) - :listOfAttributes(nullptr), type(QTest::LogElementType(t)) + : type(QTest::LogElementType(t)) { } diff --git a/src/testlib/qtestdata.cpp b/src/testlib/qtestdata.cpp index a8ee130a7de..3a1c6d7e7be 100644 --- a/src/testlib/qtestdata.cpp +++ b/src/testlib/qtestdata.cpp @@ -51,12 +51,10 @@ QT_BEGIN_NAMESPACE class QTestDataPrivate { public: - QTestDataPrivate() : tag(0), parent(0), data(0), dataCount(0) {} - - char *tag; - QTestTable *parent; - void **data; - int dataCount; + char *tag = nullptr; + QTestTable *parent = nullptr; + void **data = nullptr; + int dataCount = 0; }; QTestData::QTestData(const char *tag, QTestTable *parent) diff --git a/src/testlib/qtestelement.cpp b/src/testlib/qtestelement.cpp index 622e5344f38..b4682959173 100644 --- a/src/testlib/qtestelement.cpp +++ b/src/testlib/qtestelement.cpp @@ -43,8 +43,6 @@ QT_BEGIN_NAMESPACE QTestElement::QTestElement(int type) : QTestCoreElement(type) - , listOfChildren(0) - , parent(0) { } diff --git a/src/testlib/qtestelement_p.h b/src/testlib/qtestelement_p.h index dacbe6c1063..a6b2791a420 100644 --- a/src/testlib/qtestelement_p.h +++ b/src/testlib/qtestelement_p.h @@ -69,8 +69,8 @@ class QTestElement: public QTestCoreElement void setParent(const QTestElement *p); private: - QTestElement *listOfChildren; - const QTestElement * parent; + QTestElement *listOfChildren = nullptr; + const QTestElement * parent = nullptr; }; diff --git a/src/testlib/qtestelementattribute.cpp b/src/testlib/qtestelementattribute.cpp index 9d752bf26a4..e194ee50f75 100644 --- a/src/testlib/qtestelementattribute.cpp +++ b/src/testlib/qtestelementattribute.cpp @@ -104,11 +104,7 @@ QT_BEGIN_NAMESPACE \value LET_SystemError */ -QTestElementAttribute::QTestElementAttribute() - :attributeValue(0), - attributeIndex(QTest::AI_Undefined) -{ -} +QTestElementAttribute::QTestElementAttribute() = default; QTestElementAttribute::~QTestElementAttribute() { @@ -145,7 +141,7 @@ const char *QTestElementAttribute::name() const if (attributeIndex != QTest::AI_Undefined) return AttributeNames[attributeIndex]; - return 0; + return nullptr; } QTest::AttributeIndex QTestElementAttribute::index() const @@ -168,7 +164,7 @@ bool QTestElementAttribute::setPair(QTest::AttributeIndex index, const char *val attributeIndex = index; attributeValue = qstrdup(value); - return attributeValue != 0; + return attributeValue != nullptr; } QT_END_NAMESPACE diff --git a/src/testlib/qtestelementattribute_p.h b/src/testlib/qtestelementattribute_p.h index cb4dbb5f16a..f3815b72d1f 100644 --- a/src/testlib/qtestelementattribute_p.h +++ b/src/testlib/qtestelementattribute_p.h @@ -106,8 +106,8 @@ class QTestElementAttribute: public QTestCoreList bool setPair(QTest::AttributeIndex attributeIndex, const char *value); private: - char *attributeValue; - QTest::AttributeIndex attributeIndex; + char *attributeValue = nullptr; + QTest::AttributeIndex attributeIndex = QTest::AI_Undefined; }; QT_END_NAMESPACE diff --git a/src/testlib/qtesteventloop.h b/src/testlib/qtesteventloop.h index a77b47cd7f1..b194e24c3a5 100644 --- a/src/testlib/qtesteventloop.h +++ b/src/testlib/qtesteventloop.h @@ -56,8 +56,7 @@ class Q_TESTLIB_EXPORT QTestEventLoop : public QObject Q_OBJECT public: - inline QTestEventLoop(QObject *aParent = nullptr) - : QObject(aParent), inLoop(false), _timeout(false), timerId(-1), loop(nullptr) {} + using QObject::QObject; inline void enterLoopMSecs(int ms); inline void enterLoop(int secs) { enterLoopMSecs(secs * 1000); } @@ -84,10 +83,10 @@ protected: private: Q_DECL_UNUSED_MEMBER bool inLoop; // ### Qt 6: remove - bool _timeout; - int timerId; + bool _timeout = false; + int timerId = -1; - QEventLoop *loop; + QEventLoop *loop = nullptr; }; inline void QTestEventLoop::enterLoopMSecs(int ms) diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 14543c3cde4..f3ebf343c51 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -111,7 +111,7 @@ namespace QTest { struct IgnoreResultList { inline IgnoreResultList(QtMsgType tp, const QVariant &patternIn) - : type(tp), pattern(patternIn), next(0) {} + : type(tp), pattern(patternIn) {} static inline void clearList(IgnoreResultList *&list) { @@ -163,10 +163,10 @@ namespace QTest { QtMsgType type; QVariant pattern; - IgnoreResultList *next; + IgnoreResultList *next = nullptr; }; - static IgnoreResultList *ignoreResultList = 0; + static IgnoreResultList *ignoreResultList = nullptr; static QVector loggers; static bool loggerUsingStdout = false; @@ -181,7 +181,7 @@ namespace QTest { { if (!ignoreResultList) return false; - IgnoreResultList *last = 0; + IgnoreResultList *last = nullptr; IgnoreResultList *list = ignoreResultList; while (list) { if (list->matches(type, message)) { @@ -191,7 +191,7 @@ namespace QTest { else if (list->next) ignoreResultList = list->next; else - ignoreResultList = 0; + ignoreResultList = nullptr; delete list; return true; @@ -438,11 +438,11 @@ void QTestLog::stopLogging() void QTestLog::addLogger(LogMode mode, const char *filename) { if (filename && strcmp(filename, "-") == 0) - filename = 0; + filename = nullptr; if (!filename) QTest::loggerUsingStdout = true; - QAbstractTestLogger *logger = 0; + QAbstractTestLogger *logger = nullptr; switch (mode) { case QTestLog::Plain: logger = new QPlainTestLogger(filename); diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index e63e89a78ed..fff36f290d4 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -66,6 +66,10 @@ class QTestData; class Q_TESTLIB_EXPORT QTestLog { public: + QTestLog() = delete; + ~QTestLog() = delete; + Q_DISABLE_COPY_MOVE(QTestLog) + enum LogMode { Plain = 0, XML, LightXML, XunitXML, CSV, TeamCity, TAP #if defined(QT_USE_APPLE_UNIFIED_LOGGING) @@ -135,9 +139,6 @@ public: static qreal msecsFunctionTime() { return QTestLog::nsecsFunctionTime() / 1000000.; } private: - QTestLog(); - ~QTestLog(); - static bool printAvailableTags; }; diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp index a7a4807e065..88028aac6e3 100644 --- a/src/testlib/qtestresult.cpp +++ b/src/testlib/qtestresult.cpp @@ -39,42 +39,45 @@ #include #include +#include #include +#include // toString() specializations for QStringView #include +#include #include #include #include #include -static const char *currentAppName = 0; +static const char *currentAppName = nullptr; QT_BEGIN_NAMESPACE namespace QTest { - static QTestData *currentTestData = 0; - static QTestData *currentGlobalTestData = 0; - static const char *currentTestFunc = 0; - static const char *currentTestObjectName = 0; + static QTestData *currentTestData = nullptr; + static QTestData *currentGlobalTestData = nullptr; + static const char *currentTestFunc = nullptr; + static const char *currentTestObjectName = nullptr; static bool failed = false; static bool skipCurrentTest = false; static bool blacklistCurrentTest = false; - static const char *expectFailComment = 0; + static const char *expectFailComment = nullptr; static int expectFailMode = 0; } void QTestResult::reset() { - QTest::currentTestData = 0; - QTest::currentGlobalTestData = 0; - QTest::currentTestFunc = 0; - QTest::currentTestObjectName = 0; + QTest::currentTestData = nullptr; + QTest::currentGlobalTestData = nullptr; + QTest::currentTestFunc = nullptr; + QTest::currentTestObjectName = nullptr; QTest::failed = false; - QTest::expectFailComment = 0; + QTest::expectFailComment = nullptr; QTest::expectFailMode = 0; QTest::blacklistCurrentTest = false; @@ -126,18 +129,18 @@ static void clearExpectFail() { QTest::expectFailMode = 0; delete [] const_cast(QTest::expectFailComment); - QTest::expectFailComment = 0; + QTest::expectFailComment = nullptr; } void QTestResult::finishedCurrentTestData() { if (QTest::expectFailMode) - addFailure("QEXPECT_FAIL was called without any subsequent verification statements", 0, 0); + addFailure("QEXPECT_FAIL was called without any subsequent verification statements", nullptr, 0); clearExpectFail(); if (!QTest::failed && QTestLog::unhandledIgnoreMessages()) { QTestLog::printUnhandledIgnoreMessages(); - addFailure("Not all expected messages were received", 0, 0); + addFailure("Not all expected messages were received", nullptr, 0); } QTestLog::clearIgnoreMessages(); } @@ -157,7 +160,7 @@ void QTestResult::finishedCurrentTestDataCleanup() void QTestResult::finishedCurrentTestFunction() { - QTest::currentTestFunc = 0; + QTest::currentTestFunc = nullptr; QTest::failed = false; QTestLog::leaveTestFunction(); @@ -170,14 +173,12 @@ const char *QTestResult::currentTestFunction() const char *QTestResult::currentDataTag() { - return QTest::currentTestData ? QTest::currentTestData->dataTag() - : static_cast(0); + return QTest::currentTestData ? QTest::currentTestData->dataTag() : nullptr; } const char *QTestResult::currentGlobalDataTag() { - return QTest::currentGlobalTestData ? QTest::currentGlobalTestData->dataTag() - : static_cast(0); + return QTest::currentGlobalTestData ? QTest::currentGlobalTestData->dataTag() : nullptr; } static bool isExpectFailData(const char *dataIndex) @@ -265,17 +266,54 @@ bool QTestResult::verify(bool statement, const char *statementStr, return checkStatement(statement, msg, file, line); } -bool QTestResult::compare(bool success, const char *failureMsg, - char *val1, char *val2, - const char *actual, const char *expected, - const char *file, int line) +// Format failures using the toString() template +template +void formatFailMessage(char *msg, size_t maxMsgLen, + const char *failureMsg, + const Actual &val1, const Expected &val2, + const char *actual, const char *expected) { - QTEST_ASSERT(expected); - QTEST_ASSERT(actual); + auto val1S = QTest::toString(val1); + auto val2S = QTest::toString(val2); + size_t len1 = mbstowcs(nullptr, actual, maxMsgLen); // Last parameter is not ignored on QNX + size_t len2 = mbstowcs(nullptr, expected, maxMsgLen); // (result is never larger than this). + qsnprintf(msg, maxMsgLen, "%s\n Actual (%s)%*s %s\n Expected (%s)%*s %s", + failureMsg, + actual, qMax(len1, len2) - len1 + 1, ":", val1S ? val1S : "", + expected, qMax(len1, len2) - len2 + 1, ":", val2S ? val2S : ""); + + delete [] val1S; + delete [] val2S; +} + +// Overload to format failures for "const char *" - no need to strdup(). +void formatFailMessage(char *msg, size_t maxMsgLen, + const char *failureMsg, + const char *val1, const char *val2, + const char *actual, const char *expected) +{ + size_t len1 = mbstowcs(nullptr, actual, maxMsgLen); // Last parameter is not ignored on QNX + size_t len2 = mbstowcs(nullptr, expected, maxMsgLen); // (result is never larger than this). + qsnprintf(msg, maxMsgLen, "%s\n Actual (%s)%*s %s\n Expected (%s)%*s %s", + failureMsg, + actual, qMax(len1, len2) - len1 + 1, ":", val1 ? val1 : "", + expected, qMax(len1, len2) - len2 + 1, ":", val2 ? val2 : ""); +} + +template +static bool compareHelper(bool success, const char *failureMsg, + const Actual &val1, const Expected &val2, + const char *actual, const char *expected, + const char *file, int line, + bool hasValues = true) +{ const size_t maxMsgLen = 1024; char msg[maxMsgLen] = {'\0'}; + QTEST_ASSERT(expected); + QTEST_ASSERT(actual); + if (QTestLog::verboseLevel() >= 2) { qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected); QTestLog::info(msg, file, line); @@ -289,20 +327,92 @@ bool QTestResult::compare(bool success, const char *failureMsg, qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s) returned TRUE unexpectedly.", actual, expected); } - } else if (val1 || val2) { - size_t len1 = mbstowcs(NULL, actual, maxMsgLen); // Last parameter is not ignored on QNX - size_t len2 = mbstowcs(NULL, expected, maxMsgLen); // (result is never larger than this). - qsnprintf(msg, maxMsgLen, "%s\n Actual (%s)%*s %s\n Expected (%s)%*s %s", - failureMsg, - actual, qMax(len1, len2) - len1 + 1, ":", val1 ? val1 : "", - expected, qMax(len1, len2) - len2 + 1, ":", val2 ? val2 : ""); - } else - qsnprintf(msg, maxMsgLen, "%s", failureMsg); + return checkStatement(success, msg, file, line); + } + + if (!hasValues) { + qsnprintf(msg, maxMsgLen, "%s", failureMsg); + return checkStatement(success, msg, file, line); + } + + formatFailMessage(msg, maxMsgLen, failureMsg, val1, val2, actual, expected); + + return checkStatement(success, msg, file, line); +} + +bool QTestResult::compare(bool success, const char *failureMsg, + char *val1, char *val2, + const char *actual, const char *expected, + const char *file, int line) +{ + const bool result = compareHelper(success, failureMsg, + val1 != nullptr ? val1 : "", + val2 != nullptr ? val2 : "", + actual, expected, file, line, + val1 != nullptr && val2 != nullptr); + + // Our caller got these from QTest::toString() delete [] val1; delete [] val2; - return checkStatement(success, msg, file, line); + return result; +} + +bool QTestResult::compare(bool success, const char *failureMsg, + double val1, double val2, + const char *actual, const char *expected, + const char *file, int line) +{ + return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line); +} + +bool QTestResult::compare(bool success, const char *failureMsg, + float val1, float val2, + const char *actual, const char *expected, + const char *file, int line) +{ + return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line); +} + +bool QTestResult::compare(bool success, const char *failureMsg, + int val1, int val2, + const char *actual, const char *expected, + const char *file, int line) +{ + return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line); +} + +bool QTestResult::compare(bool success, const char *failureMsg, + unsigned val1, unsigned val2, + const char *actual, const char *expected, + const char *file, int line) +{ + return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line); +} + +bool QTestResult::compare(bool success, const char *failureMsg, + QStringView val1, QStringView val2, + const char *actual, const char *expected, + const char *file, int line) +{ + return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line); +} + +bool QTestResult::compare(bool success, const char *failureMsg, + QStringView val1, const QLatin1String &val2, + const char *actual, const char *expected, + const char *file, int line) +{ + return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line); +} + +bool QTestResult::compare(bool success, const char *failureMsg, + const QLatin1String & val1, QStringView val2, + const char *actual, const char *expected, + const char *file, int line) +{ + return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line); } void QTestResult::addFailure(const char *message, const char *file, int line) diff --git a/src/testlib/qtestresult_p.h b/src/testlib/qtestresult_p.h index 4df75b2805f..38a3024a0f2 100644 --- a/src/testlib/qtestresult_p.h +++ b/src/testlib/qtestresult_p.h @@ -55,6 +55,9 @@ QT_BEGIN_NAMESPACE +class QLatin1String; +class QStringView; + class QTestResultPrivate; class QTestData; @@ -79,7 +82,34 @@ public: char *val1, char *val2, const char *actual, const char *expected, const char *file, int line); - + static bool compare(bool success, const char *failureMsg, + double val1, double val2, + const char *actual, const char *expected, + const char *file, int line); + static bool compare(bool success, const char *failureMsg, + float val1, float val2, + const char *actual, const char *expected, + const char *file, int line); + static bool compare(bool success, const char *failureMsg, + int val1, int val2, + const char *actual, const char *expected, + const char *file, int line); + static bool compare(bool success, const char *failureMsg, + unsigned val1, unsigned val2, + const char *actual, const char *expected, + const char *file, int line); + static bool compare(bool success, const char *failureMsg, + QStringView val1, QStringView val2, + const char *actual, const char *expected, + const char *file, int line); + static bool compare(bool success, const char *failureMsg, + const QLatin1String &val1, QStringView val2, + const char *actual, const char *expected, + const char *file, int line); + static bool compare(bool success, const char *failureMsg, + QStringView val1, const QLatin1String &val2, + const char *actual, const char *expected, + const char *file, int line); static void setCurrentGlobalTestData(QTestData *data); static void setCurrentTestData(QTestData *data); static void setCurrentTestFunction(const char *func); diff --git a/src/testlib/qtesttable.cpp b/src/testlib/qtesttable.cpp index 20e0702d443..85dff170173 100644 --- a/src/testlib/qtesttable.cpp +++ b/src/testlib/qtesttable.cpp @@ -58,11 +58,11 @@ public: } struct Element { - Element() : name(nullptr), type(0) {} + Element() = default; Element(const char *n, int t) : name(n), type(t) {} - const char *name; - int type; + const char *name = nullptr; + int type = 0; }; using ElementList = std::vector; @@ -78,8 +78,8 @@ public: static QTestTable *gTable; }; -QTestTable *QTestTablePrivate::currentTestTable = 0; -QTestTable *QTestTablePrivate::gTable = 0; +QTestTable *QTestTablePrivate::currentTestTable = nullptr; +QTestTable *QTestTablePrivate::gTable = nullptr; void QTestTable::addColumn(int type, const char *name) { @@ -119,7 +119,7 @@ QTestTable::QTestTable() QTestTable::~QTestTable() { - QTestTablePrivate::currentTestTable = 0; + QTestTablePrivate::currentTestTable = nullptr; delete d; } @@ -172,7 +172,7 @@ QTestTable *QTestTable::globalTestTable() void QTestTable::clearGlobalTestTable() { delete QTestTablePrivate::gTable; - QTestTablePrivate::gTable = 0; + QTestTablePrivate::gTable = nullptr; } QTestTable *QTestTable::currentTestTable() diff --git a/src/testlib/qtestxunitstreamer.cpp b/src/testlib/qtestxunitstreamer.cpp index fe9a6e21ccf..bdbdfa9610e 100644 --- a/src/testlib/qtestxunitstreamer.cpp +++ b/src/testlib/qtestxunitstreamer.cpp @@ -54,8 +54,7 @@ QTestXunitStreamer::QTestXunitStreamer(QXunitTestLogger *logger) QTEST_ASSERT(testLogger); } -QTestXunitStreamer::~QTestXunitStreamer() -{} +QTestXunitStreamer::~QTestXunitStreamer() = default; void QTestXunitStreamer::indentForElement(const QTestElement* element, char* buf, int size) { @@ -129,7 +128,7 @@ void QTestXunitStreamer::formatAttributes(const QTestElement* element, const QTe return; } - char const* key = 0; + char const* key = nullptr; if (attrindex == QTest::AI_Description) key = "message"; else if (attrindex != QTest::AI_File && attrindex != QTest::AI_Line) diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp index c47042c3a00..763cea327b2 100644 --- a/src/testlib/qxmltestlogger.cpp +++ b/src/testlib/qxmltestlogger.cpp @@ -107,9 +107,7 @@ QXmlTestLogger::QXmlTestLogger(XmlMode mode, const char *filename) { } -QXmlTestLogger::~QXmlTestLogger() -{ -} +QXmlTestLogger::~QXmlTestLogger() = default; void QXmlTestLogger::startLogging() { @@ -182,23 +180,20 @@ inline static bool isEmpty(const char *str) static const char *incidentFormatString(bool noDescription, bool noTag) { if (noDescription) { - if (noTag) - return "\n"; - else - return "\n" + return noTag + ? "\n" + : "\n" " \n" "\n"; - } else { - if (noTag) - return "\n" - " \n" - "\n"; - else - return "\n" - " \n" - " \n" - "\n"; } + return noTag + ? "\n" + " \n" + "\n" + : "\n" + " \n" + " \n" + "\n"; } static const char *benchmarkResultFormatString() diff --git a/src/testlib/qxunittestlogger.cpp b/src/testlib/qxunittestlogger.cpp index 336edb59942..b3cac9cb825 100644 --- a/src/testlib/qxunittestlogger.cpp +++ b/src/testlib/qxunittestlogger.cpp @@ -59,13 +59,6 @@ QT_BEGIN_NAMESPACE QXunitTestLogger::QXunitTestLogger(const char *filename) : QAbstractTestLogger(filename) - , listOfTestcases(0) - , currentLogElement(0) - , errorLogElement(0) - , logFormatter(0) - , testCounter(0) - , failureCounter(0) - , errorCounter(0) { } @@ -155,7 +148,7 @@ void QXunitTestLogger::leaveTestFunction() void QXunitTestLogger::addIncident(IncidentTypes type, const char *description, const char *file, int line) { - const char *typeBuf = 0; + const char *typeBuf = nullptr; char buf[100]; switch (type) { @@ -299,7 +292,7 @@ void QXunitTestLogger::addTag(QTestElement* element) void QXunitTestLogger::addMessage(MessageTypes type, const QString &message, const char *file, int line) { QTestElement *errorElement = new QTestElement(QTest::LET_Error); - const char *typeBuf = 0; + const char *typeBuf = nullptr; switch (type) { case QAbstractTestLogger::Warn: diff --git a/src/testlib/qxunittestlogger_p.h b/src/testlib/qxunittestlogger_p.h index 48f07ddcf24..518ba098f48 100644 --- a/src/testlib/qxunittestlogger_p.h +++ b/src/testlib/qxunittestlogger_p.h @@ -79,14 +79,14 @@ class QXunitTestLogger : public QAbstractTestLogger const char *file = nullptr, int line = 0) override; private: - QTestElement *listOfTestcases; - QTestElement *currentLogElement; - QTestElement *errorLogElement; - QTestXunitStreamer *logFormatter; + QTestElement *listOfTestcases = nullptr; + QTestElement *currentLogElement = nullptr; + QTestElement *errorLogElement = nullptr; + QTestXunitStreamer *logFormatter = nullptr; - int testCounter; - int failureCounter; - int errorCounter; + int testCounter = 0; + int failureCounter = 0; + int errorCounter = 0; }; QT_END_NAMESPACE diff --git a/src/tools/bootstrap/.prev_CMakeLists.txt b/src/tools/bootstrap/.prev_CMakeLists.txt index 464a19d32ee..64493410ac7 100644 --- a/src/tools/bootstrap/.prev_CMakeLists.txt +++ b/src/tools/bootstrap/.prev_CMakeLists.txt @@ -64,32 +64,32 @@ add_qt_module(Bootstrap ../../corelib/serialization/qtextstream.cpp ../../corelib/serialization/qxmlstream.cpp ../../corelib/serialization/qxmlutils.cpp + ../../corelib/text/qbytearray.cpp + ../../corelib/text/qbytearraymatcher.cpp + ../../corelib/text/qlocale.cpp + ../../corelib/text/qlocale_tools.cpp + ../../corelib/text/qregexp.cpp + ../../corelib/text/qstring.cpp + ../../corelib/text/qstring_compat.cpp + ../../corelib/text/qstringbuilder.cpp + ../../corelib/text/qstringlist.cpp + ../../corelib/text/qstringview.cpp + ../../corelib/text/qvsnprintf.cpp ../../corelib/time/qdatetime.cpp ../../corelib/tools/qarraydata.cpp ../../corelib/tools/qbitarray.cpp - ../../corelib/tools/qbytearray.cpp - ../../corelib/tools/qbytearraymatcher.cpp ../../corelib/tools/qcommandlineoption.cpp ../../corelib/tools/qcommandlineparser.cpp ../../corelib/tools/qcryptographichash.cpp ../../corelib/tools/qhash.cpp ../../corelib/tools/qline.cpp ../../corelib/tools/qlist.cpp - ../../corelib/tools/qlocale.cpp - ../../corelib/tools/qlocale_tools.cpp ../../corelib/tools/qmap.cpp ../../corelib/tools/qpoint.cpp ../../corelib/tools/qrect.cpp - ../../corelib/tools/qregexp.cpp ../../corelib/tools/qringbuffer.cpp ../../corelib/tools/qsize.cpp - ../../corelib/tools/qstring.cpp - ../../corelib/tools/qstring_compat.cpp - ../../corelib/tools/qstringbuilder.cpp - ../../corelib/tools/qstringlist.cpp - ../../corelib/tools/qstringview.cpp ../../corelib/tools/qversionnumber.cpp - ../../corelib/tools/qvsnprintf.cpp ../../xml/dom/qdom.cpp ../../xml/sax/qxml.cpp DEFINES @@ -104,7 +104,6 @@ add_qt_module(Bootstrap ) #### Keys ignored in scope 1:.:.:bootstrap.pro:: -# CONFIG = "minimal_syncqt" "internal_module" "force_bootstrap" "gc_binaries" # INSTALLS = "lib" # MODULE_CONFIG = "gc_binaries" # MODULE_INCNAME = "QtCore" "QtXml" @@ -148,24 +147,25 @@ extend_target(Bootstrap CONDITION WIN32 user32 ) -extend_target(Bootstrap CONDITION APPLE_OSX +extend_target(Bootstrap CONDITION APPLE SOURCES ../../corelib/global/qoperatingsystemversion_darwin.mm - ../../corelib/io/qfilesystemengine_unix.cpp - ../../corelib/io/qfilesystemiterator_unix.cpp - ../../corelib/io/qfsfileengine_unix.cpp - ../../corelib/io/qstandardpaths_mac.mm ../../corelib/kernel/qcore_foundation.mm ../../corelib/kernel/qcore_mac.cpp ../../corelib/kernel/qcore_mac_objc.mm ../../corelib/kernel/qcoreapplication_mac.cpp - LIBRARIES - ${FWCoreServices} PUBLIC_LIBRARIES ${FWFoundation} ) -extend_target(Bootstrap CONDITION APPLE_OSX AND APPLE_UIKIT +extend_target(Bootstrap CONDITION APPLE_OSX + SOURCES + ../../corelib/io/qstandardpaths_mac.mm + LIBRARIES + ${FWCoreServices} +) + +extend_target(Bootstrap CONDITION APPLE_UIKIT LIBRARIES ${FWUIKit} ) @@ -201,9 +201,6 @@ extend_target(Bootstrap CONDITION NOT cross_compile ZLIB::ZLIB ) -#### Keys ignored in scope 12:.:.:bootstrap.pro:else: -# CONFIG = "no_core_dep" - extend_target(Bootstrap CONDITION WIN32 AND mingw PUBLIC_LIBRARIES uuid diff --git a/src/tools/bootstrap/CMakeLists.txt b/src/tools/bootstrap/CMakeLists.txt index 1d25e2e6e4e..6659cd140a4 100644 --- a/src/tools/bootstrap/CMakeLists.txt +++ b/src/tools/bootstrap/CMakeLists.txt @@ -62,32 +62,32 @@ extend_target(Bootstrap ../../corelib/serialization/qtextstream.cpp ../../corelib/serialization/qxmlstream.cpp ../../corelib/serialization/qxmlutils.cpp + ../../corelib/text/qbytearray.cpp + ../../corelib/text/qbytearraymatcher.cpp + ../../corelib/text/qlocale.cpp + ../../corelib/text/qlocale_tools.cpp + ../../corelib/text/qregexp.cpp + ../../corelib/text/qstring.cpp + ../../corelib/text/qstring_compat.cpp + ../../corelib/text/qstringbuilder.cpp + ../../corelib/text/qstringlist.cpp + ../../corelib/text/qstringview.cpp + ../../corelib/text/qvsnprintf.cpp ../../corelib/time/qdatetime.cpp ../../corelib/tools/qarraydata.cpp ../../corelib/tools/qbitarray.cpp - ../../corelib/tools/qbytearray.cpp - ../../corelib/tools/qbytearraymatcher.cpp ../../corelib/tools/qcommandlineoption.cpp ../../corelib/tools/qcommandlineparser.cpp ../../corelib/tools/qcryptographichash.cpp ../../corelib/tools/qhash.cpp ../../corelib/tools/qline.cpp ../../corelib/tools/qlist.cpp - ../../corelib/tools/qlocale.cpp - ../../corelib/tools/qlocale_tools.cpp ../../corelib/tools/qmap.cpp ../../corelib/tools/qpoint.cpp ../../corelib/tools/qrect.cpp - ../../corelib/tools/qregexp.cpp ../../corelib/tools/qringbuffer.cpp ../../corelib/tools/qsize.cpp - ../../corelib/tools/qstring.cpp - ../../corelib/tools/qstring_compat.cpp - ../../corelib/tools/qstringbuilder.cpp - ../../corelib/tools/qstringlist.cpp - ../../corelib/tools/qstringview.cpp ../../corelib/tools/qversionnumber.cpp - ../../corelib/tools/qvsnprintf.cpp ../../xml/dom/qdom.cpp ../../xml/sax/qxml.cpp PUBLIC_DEFINES # special case @@ -109,7 +109,6 @@ extend_target(Bootstrap ) #### Keys ignored in scope 1:.:.:bootstrap.pro:: -# CONFIG = "minimal_syncqt" "internal_module" "force_bootstrap" "gc_binaries" # INSTALLS = "lib" # MODULE_CONFIG = "gc_binaries" # MODULE_INCNAME = "QtCore" "QtXml" @@ -153,24 +152,25 @@ extend_target(Bootstrap CONDITION WIN32 user32 ) -extend_target(Bootstrap CONDITION APPLE_OSX +extend_target(Bootstrap CONDITION APPLE SOURCES ../../corelib/global/qoperatingsystemversion_darwin.mm - ../../corelib/io/qfilesystemengine_unix.cpp - ../../corelib/io/qfilesystemiterator_unix.cpp - ../../corelib/io/qfsfileengine_unix.cpp - ../../corelib/io/qstandardpaths_mac.mm ../../corelib/kernel/qcore_foundation.mm ../../corelib/kernel/qcore_mac.cpp ../../corelib/kernel/qcore_mac_objc.mm ../../corelib/kernel/qcoreapplication_mac.cpp - LIBRARIES - ${FWCoreServices} PUBLIC_LIBRARIES ${FWFoundation} ) -extend_target(Bootstrap CONDITION APPLE_OSX AND APPLE_UIKIT +extend_target(Bootstrap CONDITION APPLE_OSX + SOURCES + ../../corelib/io/qstandardpaths_mac.mm + LIBRARIES + ${FWCoreServices} +) + +extend_target(Bootstrap CONDITION APPLE_UIKIT LIBRARIES ${FWUIKit} ) @@ -184,9 +184,6 @@ extend_target(Bootstrap CONDITION UNIX AND NOT APPLE_OSX # extend_target(Bootstrap CONDITION cross_compile [...]) # extend_target(Bootstrap CONDITION NOT cross_compile [...]) -#### Keys ignored in scope 12:.:.:bootstrap.pro:else: -# CONFIG = "no_core_dep" - extend_target(Bootstrap CONDITION WIN32 AND mingw PUBLIC_LIBRARIES uuid diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 757460393e9..32e36cefa06 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -74,32 +74,32 @@ SOURCES += \ ../../corelib/serialization/qtextstream.cpp \ ../../corelib/serialization/qxmlutils.cpp \ ../../corelib/serialization/qxmlstream.cpp \ + ../../corelib/text/qbytearray.cpp \ + ../../corelib/text/qbytearraymatcher.cpp \ + ../../corelib/text/qlocale.cpp \ + ../../corelib/text/qlocale_tools.cpp \ + ../../corelib/text/qregexp.cpp \ + ../../corelib/text/qstring.cpp \ + ../../corelib/text/qstringbuilder.cpp \ + ../../corelib/text/qstring_compat.cpp \ + ../../corelib/text/qstringlist.cpp \ + ../../corelib/text/qstringview.cpp \ + ../../corelib/text/qvsnprintf.cpp \ ../../corelib/time/qdatetime.cpp \ - ../../corelib/tools/qbitarray.cpp \ - ../../corelib/tools/qbytearray.cpp \ ../../corelib/tools/qarraydata.cpp \ - ../../corelib/tools/qbytearraymatcher.cpp \ + ../../corelib/tools/qbitarray.cpp \ ../../corelib/tools/qcommandlineparser.cpp \ ../../corelib/tools/qcommandlineoption.cpp \ ../../corelib/tools/qcryptographichash.cpp \ ../../corelib/tools/qhash.cpp \ ../../corelib/tools/qlist.cpp \ - ../../corelib/tools/qlocale.cpp \ - ../../corelib/tools/qlocale_tools.cpp \ ../../corelib/tools/qmap.cpp \ - ../../corelib/tools/qregexp.cpp \ ../../corelib/tools/qringbuffer.cpp \ ../../corelib/tools/qpoint.cpp \ ../../corelib/tools/qrect.cpp \ ../../corelib/tools/qsize.cpp \ ../../corelib/tools/qline.cpp \ - ../../corelib/tools/qstring.cpp \ - ../../corelib/tools/qstringbuilder.cpp \ - ../../corelib/tools/qstring_compat.cpp \ - ../../corelib/tools/qstringlist.cpp \ - ../../corelib/tools/qstringview.cpp \ ../../corelib/tools/qversionnumber.cpp \ - ../../corelib/tools/qvsnprintf.cpp \ ../../xml/dom/qdom.cpp \ ../../xml/sax/qxml.cpp @@ -126,10 +126,7 @@ win32:SOURCES += ../../corelib/global/qoperatingsystemversion_win.cpp \ mac { SOURCES += \ ../../corelib/kernel/qcoreapplication_mac.cpp \ - ../../corelib/kernel/qcore_mac.cpp \ - ../../corelib/io/qfilesystemengine_unix.cpp \ - ../../corelib/io/qfilesystemiterator_unix.cpp \ - ../../corelib/io/qfsfileengine_unix.cpp + ../../corelib/kernel/qcore_mac.cpp OBJECTIVE_SOURCES += \ ../../corelib/global/qoperatingsystemversion_darwin.mm \ diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 41d0bbf2a14..6a74e739e6d 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -518,10 +518,15 @@ void Generator::generateCode() } } +// +// Generate meta object link to parent meta objects +// + if (!extraList.isEmpty()) { - fprintf(out, "static const QMetaObject * const qt_meta_extradata_%s[] = {\n ", qualifiedClassNameIdentifier.constData()); + fprintf(out, "static const QMetaObject::SuperData qt_meta_extradata_%s[] = {\n", + qualifiedClassNameIdentifier.constData()); for (int i = 0; i < extraList.count(); ++i) { - fprintf(out, " &%s::staticMetaObject,\n", extraList.at(i).constData()); + fprintf(out, " QMetaObject::SuperData::link<%s::staticMetaObject>(),\n", extraList.at(i).constData()); } fprintf(out, " nullptr\n};\n\n"); } @@ -537,7 +542,7 @@ void Generator::generateCode() if (isQObject) fprintf(out, " nullptr,\n"); else if (cdef->superclassList.size() && (!cdef->hasQGadget || knownGadgets.contains(purestSuperClass))) - fprintf(out, " &%s::staticMetaObject,\n", purestSuperClass.constData()); + fprintf(out, " QMetaObject::SuperData::link<%s::staticMetaObject>(),\n", purestSuperClass.constData()); else fprintf(out, " nullptr,\n"); fprintf(out, " qt_meta_stringdata_%s.data,\n" diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index d16c859eedf..fd5f8c9017c 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -547,10 +547,11 @@ void WriteInitialization::acceptUI(DomUI *node) m_output << m_option.indent << language::endFunctionDefinition("setupUi"); if (!m_mainFormUsedInRetranslateUi && language::language() == Language::Cpp) { + // Mark varName as unused to avoid compiler warnings. m_refreshInitialization += m_indent; - m_refreshInitialization += QLatin1String("Q_UNUSED("); + m_refreshInitialization += QLatin1String("(void)"); m_refreshInitialization += varName ; - m_refreshInitialization += QLatin1String(");\n"); + m_refreshInitialization += QLatin1String(";\n"); } m_output << m_option.indent diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp index 716c833fc91..ca74ee4b12c 100644 --- a/src/widgets/accessible/simplewidgets.cpp +++ b/src/widgets/accessible/simplewidgets.cpp @@ -779,8 +779,7 @@ int QAccessibleLineEdit::cursorPosition() const QRect QAccessibleLineEdit::characterRect(int offset) const { int x = lineEdit()->d_func()->control->cursorToX(offset); - int y; - lineEdit()->getTextMargins(0, &y, 0, 0); + int y = lineEdit()->textMargins().top(); QFontMetrics fm(lineEdit()->font()); const QString ch = text(offset, offset + 1); if (ch.isEmpty()) diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 82c341b47c2..fc002905364 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -1745,7 +1745,7 @@ void QColorDialogPrivate::initWidgets() q->connect(custom, SIGNAL(selected(int,int)), SLOT(_q_newCustom(int,int))); q->connect(custom, SIGNAL(currentChanged(int,int)), SLOT(_q_nextCustom(int,int))); - q->connect(custom, &QWellArray::colorChanged, [=] (int index, QRgb color) { + q->connect(custom, &QWellArray::colorChanged, [this] (int index, QRgb color) { QColorDialogOptions::setCustomColor(index, color); if (custom) custom->update(); diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 2f45635298a..c85b56d4f5e 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -44,6 +44,7 @@ #include "qfiledialog.h" #include "qfiledialog_p.h" +#include #include #include #include @@ -4035,7 +4036,7 @@ bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) { return true; case Qt::Key_Back: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) return false; #endif case Qt::Key_Left: diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp index f39ae2b53e5..9ab75e0b0af 100644 --- a/src/widgets/dialogs/qfileinfogatherer.cpp +++ b/src/widgets/dialogs/qfileinfogatherer.cpp @@ -79,14 +79,8 @@ static QString translateDriveName(const QFileInfo &drive) Creates thread */ QFileInfoGatherer::QFileInfoGatherer(QObject *parent) - : QThread(parent), abort(false), -#if QT_CONFIG(filesystemwatcher) - watcher(0), -#endif -#ifdef Q_OS_WIN - m_resolveSymlinks(true), -#endif - m_iconProvider(&defaultProvider) + : QThread(parent) + , m_iconProvider(&defaultProvider) { #if QT_CONFIG(filesystemwatcher) watcher = new QFileSystemWatcher(this); diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h index 795f60249f5..829c620c1ec 100644 --- a/src/widgets/dialogs/qfileinfogatherer_p.h +++ b/src/widgets/dialogs/qfileinfogatherer_p.h @@ -210,13 +210,13 @@ private: QAtomicInt abort; #if QT_CONFIG(filesystemwatcher) - QFileSystemWatcher *watcher; -#endif -#ifdef Q_OS_WIN - bool m_resolveSymlinks; // not accessed by run() + QFileSystemWatcher *watcher = nullptr; #endif QFileIconProvider *m_iconProvider; // not accessed by run() QFileIconProvider defaultProvider; +#ifdef Q_OS_WIN + bool m_resolveSymlinks = true; // not accessed by run() +#endif }; QT_END_NAMESPACE diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index b521f50f407..820fc6e2201 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -227,11 +227,9 @@ bool QFileSystemModel::remove(const QModelIndex &aindex) /*! Constructs a file system model with the given \a parent. */ -QFileSystemModel::QFileSystemModel(QObject *parent) - : QAbstractItemModel(*new QFileSystemModelPrivate, parent) +QFileSystemModel::QFileSystemModel(QObject *parent) : + QFileSystemModel(*new QFileSystemModelPrivate, parent) { - Q_D(QFileSystemModel); - d->init(); } /*! @@ -247,9 +245,7 @@ QFileSystemModel::QFileSystemModel(QFileSystemModelPrivate &dd, QObject *parent) /*! Destroys this file system model. */ -QFileSystemModel::~QFileSystemModel() -{ -} +QFileSystemModel::~QFileSystemModel() = default; /*! \reimp @@ -1945,6 +1941,9 @@ QStringList QFileSystemModelPrivate::unwatchPathsAt(const QModelIndex &index) void QFileSystemModelPrivate::init() { Q_Q(QFileSystemModel); + + delayedSortTimer.setSingleShot(true); + qRegisterMetaType > >(); #if QT_CONFIG(filesystemwatcher) q->connect(&fileInfoGatherer, SIGNAL(newListOfFiles(QString,QStringList)), diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h index d8f9f2b076f..844e417e2d3 100644 --- a/src/widgets/dialogs/qfilesystemmodel_p.h +++ b/src/widgets/dialogs/qfilesystemmodel_p.h @@ -99,13 +99,13 @@ public: class QFileSystemNode { public: + Q_DISABLE_COPY_MOVE(QFileSystemNode) + explicit QFileSystemNode(const QString &filename = QString(), QFileSystemNode *p = nullptr) - : fileName(filename), populatedChildren(false), isVisible(false), dirtyChildrenIndex(-1), parent(p), info(nullptr) {} + : fileName(filename), parent(p) {} ~QFileSystemNode() { qDeleteAll(children); delete info; - info = nullptr; - parent = nullptr; } QString fileName; @@ -204,31 +204,16 @@ public: } } - bool populatedChildren; - bool isVisible; QHash children; QList visibleChildren; - int dirtyChildrenIndex; + QExtendedInformation *info = nullptr; QFileSystemNode *parent; - - - QExtendedInformation *info; - + int dirtyChildrenIndex = -1; + bool populatedChildren = false; + bool isVisible = false; }; - QFileSystemModelPrivate() : - forceSort(true), - sortColumn(0), - sortOrder(Qt::AscendingOrder), - readOnly(true), - setRootPath(false), - filters(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs), - nameFilterDisables(true), // false on windows, true on mac and unix - disableRecursiveSort(false) - { - delayedSortTimer.setSingleShot(true); - } - + QFileSystemModelPrivate() = default; void init(); /* \internal @@ -303,18 +288,7 @@ public: QFileInfoGatherer fileInfoGatherer; #endif // filesystemwatcher QTimer delayedSortTimer; - bool forceSort; - int sortColumn; - Qt::SortOrder sortOrder; - bool readOnly; - bool setRootPath; - QDir::Filters filters; QHash bypassFilters; - bool nameFilterDisables; - //This flag is an optimization for the QFileDialog - //It enable a sort which is not recursive, it means - //we sort only what we see. - bool disableRecursiveSort; #if QT_CONFIG(regularexpression) QStringList nameFilters; #endif @@ -322,7 +296,6 @@ public: QFileSystemNode root; - QBasicTimer fetchingTimer; struct Fetching { QString dir; QString file; @@ -330,6 +303,18 @@ public: }; QVector toFetch; + QBasicTimer fetchingTimer; + + QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs; + int sortColumn = 0; + Qt::SortOrder sortOrder = Qt::AscendingOrder; + bool forceSort = true; + bool readOnly = true; + bool setRootPath = false; + bool nameFilterDisables = true; // false on windows, true on mac and unix + // This flag is an optimization for QFileDialog. It enables a sort which is + // not recursive, meaning we sort only what we see. + bool disableRecursiveSort = false; }; Q_DECLARE_TYPEINFO(QFileSystemModelPrivate::Fetching, Q_MOVABLE_TYPE); diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp index cd296ca0202..7e3592e034c 100644 --- a/src/widgets/dialogs/qfontdialog.cpp +++ b/src/widgets/dialogs/qfontdialog.cpp @@ -163,7 +163,7 @@ QFontDialog::QFontDialog(QWidget *parent) \since 4.5 Constructs a standard font dialog with the given \a parent and specified - \a initial color. + \a initial font. */ QFontDialog::QFontDialog(const QFont &initial, QWidget *parent) : QFontDialog(parent) diff --git a/src/widgets/doc/macOS/AppKit/AppKit.h b/src/widgets/doc/macOS/AppKit/AppKit.h new file mode 100644 index 00000000000..29e2004423e --- /dev/null +++ b/src/widgets/doc/macOS/AppKit/AppKit.h @@ -0,0 +1 @@ +// Dummy header used in documentation build diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf index 6e04372a8b6..548224bf612 100644 --- a/src/widgets/doc/qtwidgets.qdocconf +++ b/src/widgets/doc/qtwidgets.qdocconf @@ -5,6 +5,9 @@ project = QtWidgets description = Qt Widgets Reference Documentation version = $QT_VERSION +# dummy macOS headers for generating docs under non-mac platforms +includepaths += -I./macOS + examplesinstallpath = widgets qhp.projects = QtWidgets diff --git a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc index e507d66451d..65569a9cd22 100644 --- a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc +++ b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc @@ -220,7 +220,7 @@ When you make your own widget class, you should also communicate its layout properties. If the widget uses one of Qt's layouts, this is already taken - care of. If the widget does not have any child widgets, or uses manual + care of. If the widget does not have any child widgets, or uses a manual layout, you can change the behavior of the widget using any or all of the following mechanisms: diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index 65708fa1ca6..ca30c72db5f 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -449,8 +449,8 @@ \value ItemSendsGeometryChanges The item enables itemChange() notifications for ItemPositionChange, ItemPositionHasChanged, - ItemMatrixChange, ItemTransformChange, ItemTransformHasChanged, - ItemRotationChange, ItemRotationHasChanged, ItemScaleChange, ItemScaleHasChanged, + ItemTransformChange, ItemTransformHasChanged, ItemRotationChange, + ItemRotationHasChanged, ItemScaleChange, ItemScaleHasChanged, ItemTransformOriginPointChange, and ItemTransformOriginPointHasChanged. For performance reasons, these notifications are disabled by default. You must enable this flag to receive notifications for position and transform diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp index f1b01fbb4dd..2b6712075f4 100644 --- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp +++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp @@ -697,9 +697,7 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto if (!newWidget->testAttribute(Qt::WA_Resized)) newWidget->adjustSize(); - int left, top, right, bottom; - newWidget->getContentsMargins(&left, &top, &right, &bottom); - q->setContentsMargins(left, top, right, bottom); + q->setContentsMargins(newWidget->contentsMargins()); q->setWindowTitle(newWidget->windowTitle()); // size policies and constraints.. @@ -1293,8 +1291,15 @@ void QGraphicsProxyWidget::wheelEvent(QGraphicsSceneWheelEvent *event) pos = d->mapToReceiver(pos, receiver); // Send mouse event. - QWheelEvent wheelEvent(pos.toPoint(), event->screenPos(), event->delta(), - event->buttons(), event->modifiers(), event->orientation()); + QPoint angleDelta; + if (event->orientation() == Qt::Horizontal) + angleDelta.setX(event->delta()); + else + angleDelta.setY(event->delta()); + // pixelDelta, inverted, scrollPhase and source from the original QWheelEvent + // were not preserved in the QGraphicsSceneWheelEvent unfortunately + QWheelEvent wheelEvent(pos, event->screenPos(), QPoint(), angleDelta, + event->buttons(), event->modifiers(), Qt::NoScrollPhase, false); QPointer focusWidget = d->widget->focusWidget(); extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); qt_sendSpontaneousEvent(receiver, &wheelEvent); diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 2cdbdc20720..313939e6380 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -2805,7 +2805,7 @@ QGraphicsPolygonItem *QGraphicsScene::addPolygon(const QPolygonF &polygon, Note that the item's geometry is provided in item coordinates, and its position is initialized to (0, 0). For example, if a QRect(50, 50, 100, 100) is added, its top-left corner will be at (50, 50) relative to the - origin in the items coordinate system. + origin in the item's coordinate system. If the item is visible (i.e., QGraphicsItem::isVisible() returns \c true), QGraphicsScene will emit changed() once control goes back to the event diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp index 3ec9668cde2..7f142187209 100644 --- a/src/widgets/graphicsview/qgraphicsview.cpp +++ b/src/widgets/graphicsview/qgraphicsview.cpp @@ -691,7 +691,7 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event) } // Find the topmost item under the mouse with a cursor. foreach (QGraphicsItem *item, scene->d_func()->cachedItemsUnderMouse) { - if (item->hasCursor()) { + if (item->isEnabled() && item->hasCursor()) { _q_setViewportCursor(item->cursor()); return; } @@ -808,7 +808,7 @@ void QGraphicsViewPrivate::_q_unsetViewportCursor() Q_Q(QGraphicsView); const auto items = q->items(lastMouseEvent.pos()); for (QGraphicsItem *item : items) { - if (item->hasCursor()) { + if (item->isEnabled() && item->hasCursor()) { _q_setViewportCursor(item->cursor()); return; } @@ -3426,12 +3426,13 @@ void QGraphicsView::wheelEvent(QWheelEvent *event) QGraphicsSceneWheelEvent wheelEvent(QEvent::GraphicsSceneWheel); wheelEvent.setWidget(viewport()); - wheelEvent.setScenePos(mapToScene(event->pos())); - wheelEvent.setScreenPos(event->globalPos()); + wheelEvent.setScenePos(mapToScene(event->position().toPoint())); + wheelEvent.setScreenPos(event->globalPosition().toPoint()); wheelEvent.setButtons(event->buttons()); wheelEvent.setModifiers(event->modifiers()); - wheelEvent.setDelta(event->delta()); - wheelEvent.setOrientation(event->orientation()); + const bool horizontal = qAbs(event->angleDelta().x()) > qAbs(event->angleDelta().y()); + wheelEvent.setDelta(horizontal ? event->angleDelta().x() : event->angleDelta().y()); + wheelEvent.setOrientation(horizontal ? Qt::Horizontal : Qt::Vertical); wheelEvent.setAccepted(false); QCoreApplication::sendEvent(d->scene, &wheelEvent); event->setAccepted(wheelEvent.isAccepted()); diff --git a/src/widgets/graphicsview/qgraphicswidget_p.cpp b/src/widgets/graphicsview/qgraphicswidget_p.cpp index cc08b1c5661..fd47f444ea9 100644 --- a/src/widgets/graphicsview/qgraphicswidget_p.cpp +++ b/src/widgets/graphicsview/qgraphicswidget_p.cpp @@ -110,8 +110,6 @@ QGraphicsWidgetPrivate::QGraphicsWidgetPrivate() QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate() { - // Remove any lazily allocated data - delete windowData; } /*! @@ -147,7 +145,7 @@ void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const void QGraphicsWidgetPrivate::ensureWindowData() { if (!windowData) - windowData = new WindowData; + windowData = qt_make_unique(); } void QGraphicsWidgetPrivate::setPalette_helper(const QPalette &palette) diff --git a/src/widgets/graphicsview/qgraphicswidget_p.h b/src/widgets/graphicsview/qgraphicswidget_p.h index 5e0fdb693b7..e4cc2c3016e 100644 --- a/src/widgets/graphicsview/qgraphicswidget_p.h +++ b/src/widgets/graphicsview/qgraphicswidget_p.h @@ -190,7 +190,8 @@ public: , buttonMouseOver(false) , buttonSunken(false) {} - } *windowData; + }; + std::unique_ptr windowData; void ensureWindowData(); bool setWindowFrameMargins; diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index 6ff0fe8132d..d4c83cb82c3 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #ifndef QT_NO_ACCESSIBILITY @@ -343,7 +344,7 @@ void QAbstractItemViewPrivate::_q_scrollerStateChanged() \value SingleSelection When the user selects an item, any already-selected item becomes unselected. It is possible for the user to deselect the selected - item. + item by pressing the Ctrl key when clicking the selected item. \value ContiguousSelection When the user selects an item in the usual way, the selection is cleared and the new item selected. However, if the user @@ -2290,7 +2291,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) #ifdef QT_KEYPAD_NAVIGATION switch (event->key()) { case Qt::Key_Select: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (!hasEditFocus()) { setEditFocus(true); return; @@ -2298,7 +2299,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) } break; case Qt::Key_Back: - if (QApplication::keypadNavigationEnabled() && hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && hasEditFocus()) { setEditFocus(false); } else { event->ignore(); @@ -2309,7 +2310,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) // Let's ignore vertical navigation events, only if there is no other widget // what can take the focus in vertical direction. This means widget can handle navigation events // even the widget don't have edit focus, and there is no other widget in requested direction. - if(QApplication::keypadNavigationEnabled() && !hasEditFocus() + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus() && QWidgetPrivate::canKeypadNavigate(Qt::Vertical)) { event->ignore(); return; @@ -2318,14 +2319,14 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) case Qt::Key_Left: case Qt::Key_Right: // Similar logic as in up and down events - if(QApplication::keypadNavigationEnabled() && !hasEditFocus() + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus() && (QWidgetPrivate::canKeypadNavigate(Qt::Horizontal) || QWidgetPrivate::inTabWidget(this))) { event->ignore(); return; } break; default: - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) { event->ignore(); return; } @@ -2413,7 +2414,8 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) case Qt::Key_Down: case Qt::Key_Up: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && QWidgetPrivate::canKeypadNavigate(Qt::Vertical)) { + if (QApplicationPrivate::keypadNavigationEnabled() + && QWidgetPrivate::canKeypadNavigate(Qt::Vertical)) { event->accept(); // don't change focus break; } diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index be80843b073..c4766a74bdb 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -189,7 +189,7 @@ static const int maxSizeSection = 1048575; // since section size is in a bitfiel The following values are obsolete: \value Custom Use Fixed instead. - \sa setResizeMode(), setSectionResizeMode(), stretchLastSection, minimumSectionSize + \sa setSectionResizeMode(), stretchLastSection, minimumSectionSize */ /*! @@ -880,7 +880,7 @@ void QHeaderView::swapSections(int first, int second) size equal to zero is however not recommended. In that situation hideSection should be used instead. - \sa sectionResized(), resizeMode(), sectionSize(), hideSection() + \sa sectionResized(), sectionSize(), hideSection() */ void QHeaderView::resizeSection(int logical, int size) @@ -960,7 +960,7 @@ void QHeaderView::resizeSection(int logical, int size) Resizes the sections according to the given \a mode, ignoring the current resize mode. - \sa resizeMode(), sectionResized() + \sa sectionResized() */ void QHeaderView::resizeSections(QHeaderView::ResizeMode mode) @@ -1139,16 +1139,6 @@ void QHeaderView::setSectionsMovable(bool movable) d->movableSections = movable; } -// ### Qt 6 - remove this obsolete function -/*! - \obsolete - \fn void QHeaderView::setMovable(bool movable) - - Use setSectionsMovable instead. - - \sa setSectionsMovable() -*/ - /*! \since 5.0 @@ -1167,16 +1157,6 @@ bool QHeaderView::sectionsMovable() const return d->movableSections; } -// ### Qt 6 - remove this obsolete function -/*! - \obsolete - \fn bool QHeaderView::isMovable() const - - Use sectionsMovable instead. - - \sa sectionsMovable() -*/ - /*! \property QHeaderView::firstSectionMovable \brief Whether the first column can be moved by the user @@ -1223,16 +1203,6 @@ void QHeaderView::setSectionsClickable(bool clickable) d->clickableSections = clickable; } -// ### Qt 6 - remove this obsolete function -/*! - \obsolete - \fn void QHeaderView::setClickable(bool clickable) - - Use setSectionsClickable instead. - - \sa setSectionsClickable() -*/ - /*! \since 5.0 @@ -1249,16 +1219,6 @@ bool QHeaderView::sectionsClickable() const return d->clickableSections; } -// ### Qt 6 - remove this obsolete function -/*! - \obsolete - \fn bool QHeaderView::isClickable() const - - Use sectionsClickable instead. - - \sa sectionsClickable() -*/ - void QHeaderView::setHighlightSections(bool highlight) { Q_D(QHeaderView); @@ -1277,7 +1237,7 @@ bool QHeaderView::highlightSections() const Sets the constraints on how the header can be resized to those described by the given \a mode. - \sa resizeMode(), length(), sectionResized() + \sa length(), sectionResized() */ void QHeaderView::setSectionResizeMode(ResizeMode mode) @@ -1327,26 +1287,6 @@ void QHeaderView::setSectionResizeMode(int logicalIndex, ResizeMode mode) d->doDelayedResizeSections(); // section sizes may change as a result of the new mode } -// ### Qt 6 - remove this obsolete function -/*! - \overload - \obsolete - \fn void QHeaderView::setResizeMode(int logicalIndex, ResizeMode mode) - - Use setSectionResizeMode instead. - - \sa setSectionResizeMode() -*/ - -/*! - \obsolete - \fn void QHeaderView::setResizeMode(ResizeMode mode) - - Use setSectionResizeMode instead. - - \sa setSectionResizeMode() -*/ - /*! \since 5.0 @@ -1407,16 +1347,6 @@ int QHeaderView::resizeContentsPrecision() const return d->resizeContentsPrecision; } -// ### Qt 6 - remove this obsolete function -/*! - \obsolete - \fn QHeaderView::ResizeMode QHeaderView::resizeMode(int logicalIndex) const - - Use sectionResizeMode instead. - - \sa sectionResizeMode() -*/ - /*! \since 4.1 @@ -1424,7 +1354,7 @@ int QHeaderView::resizeContentsPrecision() const views, this can be used to see if the headerview needs to resize the sections when the view's geometry changes. - \sa stretchLastSection, resizeMode() + \sa stretchLastSection */ int QHeaderView::stretchSectionCount() const diff --git a/src/widgets/itemviews/qitemeditorfactory.cpp b/src/widgets/itemviews/qitemeditorfactory.cpp index 2d49dd4421d..8ed2ee5f281 100644 --- a/src/widgets/itemviews/qitemeditorfactory.cpp +++ b/src/widgets/itemviews/qitemeditorfactory.cpp @@ -570,11 +570,9 @@ void QExpandingLineEdit::changeEvent(QEvent *e) void QExpandingLineEdit::updateMinimumWidth() { - int left, right; - getTextMargins(&left, 0, &right, 0); - int width = left + right + 4 /*horizontalMargin in qlineedit.cpp*/; - getContentsMargins(&left, 0, &right, 0); - width += left + right; + const QMargins tm = textMargins(); + const QMargins cm = contentsMargins(); + const int width = tm.left() + tm.right() + cm.left() + cm.right() + 4 /*horizontalMargin in qlineedit.cpp*/; QStyleOptionFrame opt; initStyleOption(&opt); diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 25facd1484a..04cddf29268 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -54,6 +54,7 @@ #if QT_CONFIG(rubberband) #include #endif +#include #include #include #include @@ -810,14 +811,14 @@ void QListView::mouseReleaseEvent(QMouseEvent *e) void QListView::wheelEvent(QWheelEvent *e) { Q_D(QListView); - if (e->orientation() == Qt::Vertical) { + if (qAbs(e->angleDelta().y()) > qAbs(e->angleDelta().x())) { if (e->angleDelta().x() == 0 - && ((d->flow == TopToBottom && d->wrap) || (d->flow == LeftToRight && !d->wrap)) - && d->vbar->minimum() == 0 && d->vbar->maximum() == 0) { + && ((d->flow == TopToBottom && d->wrap) || (d->flow == LeftToRight && !d->wrap)) + && d->vbar->minimum() == 0 && d->vbar->maximum() == 0) { QPoint pixelDelta(e->pixelDelta().y(), e->pixelDelta().x()); QPoint angleDelta(e->angleDelta().y(), e->angleDelta().x()); - QWheelEvent hwe(e->pos(), e->globalPos(), pixelDelta, angleDelta, e->delta(), - Qt::Horizontal, e->buttons(), e->modifiers(), e->phase(), e->source(), e->inverted()); + QWheelEvent hwe(e->position(), e->globalPosition(), pixelDelta, angleDelta, + e->buttons(), e->modifiers(), e->phase(), e->inverted(), e->source()); if (e->spontaneous()) qt_sendSpontaneousEvent(d->hbar, &hwe); else @@ -1185,7 +1186,7 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie rect.translate(0, -rect.height()); if (rect.bottom() <= 0) { #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { int row = d->batchStartRow() - 1; while (row >= 0 && d->isHiddenOrDisabled(row)) --row; @@ -1214,7 +1215,7 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie rect.translate(0, rect.height()); if (rect.top() >= contents.height()) { #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { int rowCount = d->model->rowCount(d->root); int row = 0; while (row < rowCount && d->isHiddenOrDisabled(row)) @@ -1895,7 +1896,7 @@ bool QListViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QMo void QListViewPrivate::removeCurrentAndDisabled(QVector *indexes, const QModelIndex ¤t) const { - auto isCurrentOrDisabled = [=](const QModelIndex &index) { + auto isCurrentOrDisabled = [this, current](const QModelIndex &index) { return !isIndexEnabled(index) || index == current; }; indexes->erase(std::remove_if(indexes->begin(), indexes->end(), diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp index 37bb370e73c..e7dcfac4037 100644 --- a/src/widgets/itemviews/qlistwidget.cpp +++ b/src/widgets/itemviews/qlistwidget.cpp @@ -930,12 +930,14 @@ QDataStream &operator>>(QDataStream &in, QListWidgetItem &item) \sa Qt::AlignmentFlag */ +#if QT_DEPRECATED_SINCE(5, 13) /*! \fn QColor QListWidgetItem::backgroundColor() const \obsolete This function is deprecated. Use background() instead. */ +#endif /*! \fn QBrush QListWidgetItem::background() const @@ -946,6 +948,7 @@ QDataStream &operator>>(QDataStream &in, QListWidgetItem &item) \sa setBackground(), foreground() */ +#if QT_DEPRECATED_SINCE(5, 13) /*! \fn QColor QListWidgetItem::textColor() const \obsolete @@ -954,6 +957,7 @@ QDataStream &operator>>(QDataStream &in, QListWidgetItem &item) This function is deprecated. Use foreground() instead. */ +#endif /*! \fn QBrush QListWidgetItem::foreground() const @@ -1119,12 +1123,14 @@ void QListWidgetItem::setFlags(Qt::ItemFlags aflags) \sa background(), setForeground() */ +#if QT_DEPRECATED_SINCE(5, 13) /*! \fn void QListWidgetItem::setTextColor(const QColor &color) \obsolete This function is deprecated. Use setForeground() instead. */ +#endif /*! \fn void QListWidgetItem::setForeground(const QBrush &brush) diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 8860ef208dd..e706af1a42c 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -51,6 +51,7 @@ #if QT_CONFIG(abstractbutton) #include #endif +#include #include #include #include @@ -1710,7 +1711,7 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi case MoveUp: { int originalRow = visualRow; #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && visualRow == 0) + if (QApplicationPrivate::keypadNavigationEnabled() && visualRow == 0) visualRow = d->visualRow(model()->rowCount() - 1) + 1; // FIXME? visualRow = bottom + 1; #endif @@ -1739,7 +1740,7 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height())); } #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && visualRow >= bottom) + if (QApplicationPrivate::keypadNavigationEnabled() && visualRow >= bottom) visualRow = -1; #endif int r = d->logicalRow(visualRow); diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp index 0fb9e283851..a25a5828815 100644 --- a/src/widgets/itemviews/qtablewidget.cpp +++ b/src/widgets/itemviews/qtablewidget.cpp @@ -1251,6 +1251,7 @@ void QTableWidgetItem::setFlags(Qt::ItemFlags aflags) \sa font(), setText(), setForeground() */ +#if QT_DEPRECATED_SINCE(5, 13) /*! \fn QColor QTableWidgetItem::backgroundColor() const \obsolete @@ -1264,6 +1265,7 @@ void QTableWidgetItem::setFlags(Qt::ItemFlags aflags) This function is deprecated. Use setBackground() instead. */ +#endif /*! \fn QBrush QTableWidgetItem::background() const @@ -1283,6 +1285,7 @@ void QTableWidgetItem::setFlags(Qt::ItemFlags aflags) \sa setForeground() */ +#if QT_DEPRECATED_SINCE(5, 13) /*! \fn QColor QTableWidgetItem::textColor() const \obsolete @@ -1296,6 +1299,7 @@ void QTableWidgetItem::setFlags(Qt::ItemFlags aflags) This function is deprecated. Use setForeground() instead. */ +#endif /*! \fn QBrush QTableWidgetItem::foreground() const diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 55b10d13c1b..23a530821f0 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -55,6 +55,7 @@ #include #endif +#include #include #include @@ -2214,14 +2215,14 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie case MoveNext: case MoveDown: #ifdef QT_KEYPAD_NAVIGATION - if (vi == d->viewItems.count()-1 && QApplication::keypadNavigationEnabled()) + if (vi == d->viewItems.count()-1 && QApplicationPrivate::keypadNavigationEnabled()) return d->model->index(0, current.column(), d->root); #endif return d->modelIndex(d->below(vi), current.column()); case MovePrevious: case MoveUp: #ifdef QT_KEYPAD_NAVIGATION - if (vi == 0 && QApplication::keypadNavigationEnabled()) + if (vi == 0 && QApplicationPrivate::keypadNavigationEnabled()) return d->modelIndex(d->viewItems.count() - 1, current.column()); #endif return d->modelIndex(d->above(vi), current.column()); diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp index d2dc91b18cd..d285ad6d28c 100644 --- a/src/widgets/itemviews/qtreewidget.cpp +++ b/src/widgets/itemviews/qtreewidget.cpp @@ -1251,6 +1251,7 @@ bool QTreeWidgetItem::isFirstColumnSpanned() const \sa font(), setText(), setForeground() */ +#if QT_DEPRECATED_SINCE(5, 13) /*! \fn QColor QTreeWidgetItem::backgroundColor(int column) const \obsolete @@ -1264,6 +1265,7 @@ bool QTreeWidgetItem::isFirstColumnSpanned() const This function is deprecated. Use setBackground() instead. */ +#endif /*! \fn QBrush QTreeWidgetItem::background(int column) const @@ -1284,6 +1286,7 @@ bool QTreeWidgetItem::isFirstColumnSpanned() const \sa setForeground() */ +#if QT_DEPRECATED_SINCE(5, 13) /*! \fn QColor QTreeWidgetItem::textColor(int column) const \obsolete @@ -1297,6 +1300,7 @@ bool QTreeWidgetItem::isFirstColumnSpanned() const This function is deprecated. Use setForeground() instead. */ +#endif /*! \fn QBrush QTreeWidgetItem::foreground(int column) const diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index c922aeccebf..94b14ecb4f5 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -236,9 +236,6 @@ void QApplicationPrivate::createEventDispatcher() encapsulated in a QStyle object. This can be changed at runtime with setStyle(). - \li It specifies how the application is to allocate colors. See - setColorSpec() for details. - \li It provides localization of strings that are visible to the user via translate(). @@ -298,11 +295,6 @@ void QApplicationPrivate::createEventDispatcher() \li style(), setStyle(). - \row - \li Color usage - \li colorSpec(), - setColorSpec(). - \row \li Text handling \li installTranslator(), @@ -337,6 +329,7 @@ void QApplicationPrivate::createEventDispatcher() \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings */ +#if QT_DEPRECATED_SINCE(5, 8) // ### fixme: Qt 6: Remove ColorSpec and accessors. /*! \enum QApplication::ColorSpec @@ -350,15 +343,7 @@ void QApplicationPrivate::createEventDispatcher() See setColorSpec() for full details. */ - -/*! - \fn QApplication::setGraphicsSystem(const QString &) - \obsolete - - This call has no effect. - - Use the QPA framework instead. -*/ +#endif /*! \fn QWidget *QApplication::topLevelAt(const QPoint &point) @@ -1956,15 +1941,8 @@ bool QApplication::event(QEvent *e) return QGuiApplication::event(e); } -/*! - \fn void QApplication::syncX() - Was used to synchronize with the X server in 4.x, here for source compatibility. - \internal - \obsolete -*/ - // ### FIXME: topLevelWindows does not contain QWidgets without a parent -// until create_sys is called. So we have to override the +// until QWidgetPrivate::create is called. So we have to override the // QGuiApplication::notifyLayoutDirectionChange // to do the right thing. void QApplicationPrivate::notifyLayoutDirectionChange() @@ -3240,13 +3218,18 @@ bool QApplication::notify(QObject *receiver, QEvent *e) if (spontaneous && phase == Qt::ScrollBegin) QApplicationPrivate::wheel_widget = nullptr; - const QPoint &relpos = wheel->pos(); + QPoint relpos = wheel->position().toPoint(); if (spontaneous && (phase == Qt::NoScrollPhase || phase == Qt::ScrollUpdate)) QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); +#if QT_DEPRECATED_SINCE(5, 14) QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), wheel->modifiers(), phase, wheel->source(), wheel->inverted()); +#else + QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(), + wheel->modifiers(), phase, wheel->inverted(), wheel->source()); +#endif we.setTimestamp(wheel->timestamp()); bool eventAccepted; do { @@ -3281,9 +3264,14 @@ bool QApplication::notify(QObject *receiver, QEvent *e) // is set. Since it accepted the wheel event previously, we continue // sending those events until we get a ScrollEnd, which signifies // the end of the natural scrolling sequence. - const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos()); + const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPosition().toPoint()); +#if QT_DEPRECATED_SINCE(5, 0) QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), wheel->modifiers(), wheel->phase(), wheel->source()); +#else + QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(), + wheel->modifiers(), wheel->phase(), wheel->inverted(), wheel->source()); +#endif we.setTimestamp(wheel->timestamp()); we.spont = true; we.ignore(); @@ -3833,8 +3821,6 @@ void QApplicationPrivate::openPopup(QWidget *popup) This feature is available in Qt for Embedded Linux only. \since 4.6 - - \sa keypadNavigationEnabled() */ void QApplication::setNavigationMode(Qt::NavigationMode mode) { @@ -3847,8 +3833,6 @@ void QApplication::setNavigationMode(Qt::NavigationMode mode) This feature is available in Qt for Embedded Linux only. \since 4.6 - - \sa keypadNavigationEnabled() */ Qt::NavigationMode QApplication::navigationMode() { @@ -3983,15 +3967,6 @@ int QApplication::doubleClickInterval() return QGuiApplication::styleHints()->mouseDoubleClickInterval(); } -/*! - \fn QApplication::keyboardInputDirection() - \since 4.2 - \deprecated - - Returns the current keyboard input direction. Replaced with QInputMethod::inputDirection() - \sa QInputMethod::inputDirection() -*/ - /*! \property QApplication::keyboardInputInterval \brief the time limit in milliseconds that distinguishes a key press @@ -4129,14 +4104,6 @@ void QApplication::beep() \sa QCoreApplication::instance(), qGuiApp */ -/*! - \fn QLocale QApplication::keyboardInputLocale() - \since 4.2 - \obsolete - - Returns the current keyboard input locale. Replaced with QInputMethod::locale() -*/ - bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event) { return QGuiApplication::sendSpontaneousEvent(receiver, event); diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 98eb9b73c6e..36c0ba87393 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -136,6 +136,13 @@ public: static QWidget *tryModalHelper_sys(QWidget *top); bool canQuit(); #endif +#ifdef QT_KEYPAD_NAVIGATION + static bool keypadNavigationEnabled() + { + return navigationMode == Qt::NavigationModeKeypadTabOrder || + navigationMode == Qt::NavigationModeKeypadDirectional; + } +#endif bool notify_helper(QObject *receiver, QEvent * e); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 89b0e56297e..cdea0a570c5 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -393,7 +393,7 @@ QPointer QWidgetPrivate::editingWidget; This feature is only available in Qt for Embedded Linux. - \sa setEditFocus(), QApplication::keypadNavigationEnabled() + \sa setEditFocus(), QApplication::navigationMode() */ bool QWidget::hasEditFocus() const { @@ -413,7 +413,7 @@ bool QWidget::hasEditFocus() const This feature is only available in Qt for Embedded Linux. - \sa hasEditFocus(), QApplication::keypadNavigationEnabled() + \sa hasEditFocus(), QApplication::navigationMode() */ void QWidget::setEditFocus(bool on) { @@ -1193,7 +1193,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) q->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea); q->setAttribute(Qt::WA_WState_Hidden); - //give potential windows a bigger "pre-initial" size; create_sys() will give them a new size later + //give potential windows a bigger "pre-initial" size; create() will give them a new size later data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480); focus_next = focus_prev = q; @@ -1287,27 +1287,19 @@ QScreen *QWidgetPrivate::associatedScreen() const /*! Creates a new widget window. - The parameter \a window is ignored in Qt 5. Please use - QWindow::fromWinId() to create a QWindow wrapping a foreign - window and pass it to QWidget::createWindowContainer() instead. - - Initializes the window (sets the geometry etc.) if \a - initializeWindow is true. If \a initializeWindow is false, no - initialization is performed. This parameter only makes sense if \a - window is a valid window. - - Destroys the old window if \a destroyOldWindow is true. If \a - destroyOldWindow is false, you are responsible for destroying the - window yourself (using platform native code). - - The QWidget constructor calls create(0,true,true) to create a - window for this widget. + The parameters \a window, \a initializeWindow, and \a destroyOldWindow + are ignored in Qt 5. Please use QWindow::fromWinId() to create a + QWindow wrapping a foreign window and pass it to + QWidget::createWindowContainer() instead. \sa createWindowContainer(), QWindow::fromWinId() */ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) { + Q_UNUSED(initializeWindow); + Q_UNUSED(destroyOldWindow); + Q_D(QWidget); if (Q_UNLIKELY(window)) qWarning("QWidget::create(): Parameter 'window' does not have any effect."); @@ -1367,7 +1359,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) d->updateIsOpaque(); setAttribute(Qt::WA_WState_Created); // set created flag - d->create_sys(window, initializeWindow, destroyOldWindow); + d->create(); // a real toplevel window needs a backing store if (isWindow() && windowType() != Qt::Desktop) { @@ -1431,14 +1423,10 @@ void q_createNativeChildrenAndSetParent(const QWidget *parentWidget) } -void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow) +void QWidgetPrivate::create() { Q_Q(QWidget); - Q_UNUSED(window); - Q_UNUSED(initializeWindow); - Q_UNUSED(destroyOldWindow); - if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow()) return; // we only care about real toplevels @@ -6469,8 +6457,18 @@ void QWidget::setFocusProxy(QWidget * w) } } + QWidget *oldDeepestFocusProxy = d_func()->deepestFocusProxy(); + if (!oldDeepestFocusProxy) + oldDeepestFocusProxy = this; + const bool changingAppFocusWidget = (QApplicationPrivate::focus_widget == oldDeepestFocusProxy); + d->createExtra(); d->extra->focus_proxy = w; + + if (changingAppFocusWidget) { + QWidget *newDeepestFocusProxy = d_func()->deepestFocusProxy(); + QApplicationPrivate::focus_widget = newDeepestFocusProxy ? newDeepestFocusProxy : this; + } } @@ -7474,6 +7472,17 @@ QByteArray QWidget::saveGeometry() const return array; } +static void checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry, + int frameHeight) +{ + if (!restoredGeometry->intersects(availableGeometry)) { + restoredGeometry->moveBottom(qMin(restoredGeometry->bottom(), availableGeometry.bottom())); + restoredGeometry->moveLeft(qMax(restoredGeometry->left(), availableGeometry.left())); + restoredGeometry->moveRight(qMin(restoredGeometry->right(), availableGeometry.right())); + } + restoredGeometry->moveTop(qMax(restoredGeometry->top(), availableGeometry.top() + frameHeight)); +} + /*! \since 4.2 @@ -7528,7 +7537,7 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) quint8 fullScreen; qint32 restoredScreenWidth = 0; - stream >> restoredFrameGeometry + stream >> restoredFrameGeometry // Only used for sanity checks in version 0 >> restoredNormalGeometry >> restoredScreenNumber >> maximized @@ -7558,8 +7567,6 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) } const int frameHeight = 20; - if (!restoredFrameGeometry.isValid()) - restoredFrameGeometry = QRect(QPoint(0,0), sizeHint()); if (!restoredNormalGeometry.isValid()) restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint()); @@ -7579,23 +7586,11 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) // - (Mac only) The window is higher than the available geometry. It must // be possible to bring the size grip on screen by moving the window. #if 0 // Used to be included in Qt4 for Q_WS_MAC - restoredFrameGeometry.setHeight(qMin(restoredFrameGeometry.height(), availableGeometry.height())); restoredNormalGeometry.setHeight(qMin(restoredNormalGeometry.height(), availableGeometry.height() - frameHeight)); #endif - if (!restoredFrameGeometry.intersects(availableGeometry)) { - restoredFrameGeometry.moveBottom(qMin(restoredFrameGeometry.bottom(), availableGeometry.bottom())); - restoredFrameGeometry.moveLeft(qMax(restoredFrameGeometry.left(), availableGeometry.left())); - restoredFrameGeometry.moveRight(qMin(restoredFrameGeometry.right(), availableGeometry.right())); - } - restoredFrameGeometry.moveTop(qMax(restoredFrameGeometry.top(), availableGeometry.top())); - - if (!restoredNormalGeometry.intersects(availableGeometry)) { - restoredNormalGeometry.moveBottom(qMin(restoredNormalGeometry.bottom(), availableGeometry.bottom())); - restoredNormalGeometry.moveLeft(qMax(restoredNormalGeometry.left(), availableGeometry.left())); - restoredNormalGeometry.moveRight(qMin(restoredNormalGeometry.right(), availableGeometry.right())); - } - restoredNormalGeometry.moveTop(qMax(restoredNormalGeometry.top(), availableGeometry.top() + frameHeight)); + checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight); + checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight); if (maximized || fullScreen) { // set geometry before setting the window state to make @@ -7649,7 +7644,7 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) Changing the margins will trigger a resizeEvent(). - \sa contentsRect(), getContentsMargins() + \sa contentsRect(), contentsMargins() */ void QWidget::setContentsMargins(int left, int top, int right, int bottom) { @@ -7679,7 +7674,7 @@ void QWidget::setContentsMargins(int left, int top, int right, int bottom) Changing the margins will trigger a resizeEvent(). - \sa contentsRect(), getContentsMargins() + \sa contentsRect(), contentsMargins() */ void QWidget::setContentsMargins(const QMargins &margins) { @@ -7708,7 +7703,11 @@ void QWidgetPrivate::updateContentsRect() QCoreApplication::sendEvent(q, &e); } +#if QT_DEPRECATED_SINCE(5, 14) /*! + \obsolete + Use contentsMargins(). + Returns the widget's contents margins for \a left, \a top, \a right, and \a bottom. @@ -7726,6 +7725,7 @@ void QWidget::getContentsMargins(int *left, int *top, int *right, int *bottom) c if (bottom) *bottom = m.bottom(); } +#endif // FIXME: Move to qmargins.h for next minor Qt release QMargins operator|(const QMargins &m1, const QMargins &m2) @@ -7739,7 +7739,7 @@ QMargins operator|(const QMargins &m1, const QMargins &m2) \brief The contentsMargins function returns the widget's contents margins. - \sa getContentsMargins(), setContentsMargins(), contentsRect() + \sa setContentsMargins(), contentsRect() */ QMargins QWidget::contentsMargins() const { @@ -7752,7 +7752,7 @@ QMargins QWidget::contentsMargins() const /*! Returns the area inside the widget's margins. - \sa setContentsMargins(), getContentsMargins() + \sa setContentsMargins(), contentsMargins() */ QRect QWidget::contentsRect() const { @@ -9408,12 +9408,6 @@ bool QWidget::event(QEvent *event) d->renderToTextureReallyDirty = 1; #endif break; - case QEvent::PlatformSurface: { - auto surfaceEvent = static_cast(event); - if (surfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) - d->setWinId(0); - break; - } #ifndef QT_NO_PROPERTIES case QEvent::DynamicPropertyChange: { const QByteArray &propName = static_cast(event)->propertyName(); @@ -11392,7 +11386,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) // windowModality property and then reshown. } if (testAttribute(Qt::WA_WState_Created)) { - // don't call setModal_sys() before create_sys() + // don't call setModal_sys() before create() d->setModal_sys(); } break; diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h index e47deb5d0d3..0777bed65ce 100644 --- a/src/widgets/kernel/qwidget.h +++ b/src/widgets/kernel/qwidget.h @@ -524,7 +524,10 @@ public: void setContentsMargins(int left, int top, int right, int bottom); void setContentsMargins(const QMargins &margins); +#if QT_DEPRECATED_SINCE(5, 14) + QT_DEPRECATED_X("use contentsMargins()") void getContentsMargins(int *left, int *top, int *right, int *bottom) const; +#endif QMargins contentsMargins() const; QRect contentsRect() const; diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 99ec38e0504..7cb9a3895a0 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -360,7 +360,7 @@ public: void update(T t); void init(QWidget *desktopWidget, Qt::WindowFlags f); - void create_sys(WId window, bool initializeWindow, bool destroyOldWindow); + void create(); void createRecursively(); void createWinId(); diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index ba100838292..5537ff497a7 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -828,14 +828,14 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event) return; QWidget *rootWidget = m_widget; - QPoint pos = event->pos(); + QPoint pos = event->position().toPoint(); // Use proper popup window for wheel event. Some QPA sends the wheel // event to the root menu, so redirect it to the proper popup window. QWidget *activePopupWidget = QApplication::activePopupWidget(); if (activePopupWidget && activePopupWidget != m_widget) { rootWidget = activePopupWidget; - pos = rootWidget->mapFromGlobal(event->globalPos()); + pos = rootWidget->mapFromGlobal(event->globalPosition().toPoint()); } // which child should have it? @@ -846,7 +846,12 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event) QPoint mapped = widget->mapFrom(rootWidget, pos); +#if QT_DEPRECATED_SINCE(5, 0) QWheelEvent translated(mapped, event->globalPos(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted()); +#else + QWheelEvent translated(QPointF(mapped), event->globalPosition(), event->pixelDelta(), event->angleDelta(), + event->buttons(), event->modifiers(), event->phase(), event->inverted(), event->source()); +#endif translated.setTimestamp(event->timestamp()); QGuiApplication::forwardEvent(widget, &translated, event); } diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 34cc3c93dbf..e21ff4bec81 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -469,7 +469,14 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, case PE_FrameGroupBox: { QPixmap pixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_groupbox.png")); - int topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin; + int topMargin = 0; + auto control = dynamic_cast(widget); + if (control && !control->isCheckable() && control->title().isEmpty()) { + // Shrinking the topMargin if Not checkable AND title is empty + topMargin = groupBoxTopMargin; + } else { + topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin; + } QRect frame = option->rect.adjusted(0, topMargin, 0, 0); qDrawBorderPixmap(painter, frame, QMargins(6, 6, 6, 6), pixmap); break; diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index ee0418b5b87..7b69eff30c0 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -161,6 +161,7 @@ #include "QtWidgets/qapplication.h" #include "QtGui/qevent.h" #include "QtWidgets/qdesktopwidget.h" +#include #include #if QT_CONFIG(lineedit) #include "QtWidgets/qlineedit.h" @@ -1416,7 +1417,7 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e) // widget lost focus, hide the popup if (d->widget && (!d->widget->hasFocus() #ifdef QT_KEYPAD_NAVIGATION - || (QApplication::keypadNavigationEnabled() && !d->widget->hasEditFocus()) + || (QApplicationPrivate::keypadNavigationEnabled() && !d->widget->hasEditFocus()) #endif )) d->popup->hide(); @@ -1434,7 +1435,7 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e) switch (key) { #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Select: - if (!QApplication::keypadNavigationEnabled()) + if (!QApplicationPrivate::keypadNavigationEnabled()) break; #endif case Qt::Key_Return: @@ -1464,7 +1465,7 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e) #ifdef QT_KEYPAD_NAVIGATION case QEvent::KeyRelease: { QKeyEvent *ke = static_cast(e); - if (QApplication::keypadNavigationEnabled() && ke->key() == Qt::Key_Back) { + if (QApplicationPrivate::keypadNavigationEnabled() && ke->key() == Qt::Key_Back) { // Send the event to the 'widget'. This is what we did for KeyPress, so we need // to do the same for KeyRelease, in case the widget's KeyPress event set // up something (such as a timer) that is relying on also receiving the @@ -1481,7 +1482,7 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e) case QEvent::MouseButtonPress: { #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { // if we've clicked in the widget (or its descendant), let it handle the click QWidget *source = qobject_cast(o); if (source) { diff --git a/src/widgets/widgets/qabstractbutton.cpp b/src/widgets/widgets/qabstractbutton.cpp index f30a3bc7b81..d956d2ba238 100644 --- a/src/widgets/widgets/qabstractbutton.cpp +++ b/src/widgets/widgets/qabstractbutton.cpp @@ -44,6 +44,7 @@ #endif #if QT_CONFIG(buttongroup) #include "qbuttongroup.h" +#include "private/qapplication_p.h" #include "private/qbuttongroup_p.h" #endif #include "qabstractbutton_p.h" @@ -319,7 +320,7 @@ void QAbstractButtonPrivate::moveFocus(int key) if (exclusive #ifdef QT_KEYPAD_NAVIGATION - && !QApplication::keypadNavigationEnabled() + && !QApplicationPrivate::keypadNavigationEnabled() #endif && candidate && fb->d_func()->checked @@ -1063,7 +1064,7 @@ void QAbstractButton::keyPressEvent(QKeyEvent *e) case Qt::Key_Right: case Qt::Key_Down: { #ifdef QT_KEYPAD_NAVIGATION - if ((QApplication::keypadNavigationEnabled() + if ((QApplicationPrivate::keypadNavigationEnabled() && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)) || (!QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional || (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down))) { @@ -1159,7 +1160,7 @@ void QAbstractButton::focusInEvent(QFocusEvent *e) { Q_D(QAbstractButton); #ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled()) + if (!QApplicationPrivate::keypadNavigationEnabled()) #endif d->fixFocusPolicy(); QWidget::focusInEvent(e); diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index b9e0d3280fa..55b2dcd6621 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -1324,7 +1324,7 @@ void QAbstractScrollArea::mouseMoveEvent(QMouseEvent *e) void QAbstractScrollArea::wheelEvent(QWheelEvent *e) { Q_D(QAbstractScrollArea); - if (e->orientation() == Qt::Horizontal) + if (qAbs(e->angleDelta().x()) > qAbs(e->angleDelta().y())) QCoreApplication::sendEvent(d->hbar, e); else QCoreApplication::sendEvent(d->vbar, e); @@ -1362,7 +1362,7 @@ void QAbstractScrollArea::keyPressEvent(QKeyEvent * e) #endif } else { #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) { e->ignore(); return; } @@ -1376,7 +1376,7 @@ void QAbstractScrollArea::keyPressEvent(QKeyEvent * e) break; case Qt::Key_Left: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && hasEditFocus() + if (QApplicationPrivate::keypadNavigationEnabled() && hasEditFocus() && (!d->hbar->isVisible() || d->hbar->value() == d->hbar->minimum())) { //if we aren't using the hbar or we are already at the leftmost point ignore e->ignore(); @@ -1389,7 +1389,7 @@ void QAbstractScrollArea::keyPressEvent(QKeyEvent * e) break; case Qt::Key_Right: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && hasEditFocus() + if (QApplicationPrivate::keypadNavigationEnabled() && hasEditFocus() && (!d->hbar->isVisible() || d->hbar->value() == d->hbar->maximum())) { //if we aren't using the hbar or we are already at the rightmost point ignore e->ignore(); diff --git a/src/widgets/widgets/qabstractslider.cpp b/src/widgets/widgets/qabstractslider.cpp index 2172ebc99cf..129d540f509 100644 --- a/src/widgets/widgets/qabstractslider.cpp +++ b/src/widgets/widgets/qabstractslider.cpp @@ -47,6 +47,8 @@ #endif #include +#include + QT_BEGIN_NAMESPACE /*! @@ -764,10 +766,11 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e) { Q_D(QAbstractSlider); e->ignore(); - int delta = e->delta(); + bool vertical = bool(e->angleDelta().y()); + int delta = vertical ? e->angleDelta().y() : e->angleDelta().x(); if (e->inverted()) delta = -delta; - if (d->scrollByDelta(e->orientation(), e->modifiers(), delta)) + if (d->scrollByDelta(vertical ? Qt::Vertical : Qt::Horizontal, e->modifiers(), delta)) e->accept(); } @@ -815,13 +818,13 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) switch (ev->key()) { #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Select: - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) setEditFocus(!hasEditFocus()); else ev->ignore(); break; case Qt::Key_Back: - if (QApplication::keypadNavigationEnabled() && hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && hasEditFocus()) { setValue(d->origValue); setEditFocus(false); } else @@ -834,7 +837,7 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) // In QApplication::KeypadNavigationDirectional, we want to change the slider // value if there is no left/right navigation possible and if this slider is not // inside a tab widget. - if (QApplication::keypadNavigationEnabled() + if (QApplicationPrivate::keypadNavigationEnabled() && (!hasEditFocus() && QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder || d->orientation == Qt::Vertical || !hasEditFocus() @@ -842,7 +845,7 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) ev->ignore(); return; } - if (QApplication::keypadNavigationEnabled() && d->orientation == Qt::Vertical) + if (QApplicationPrivate::keypadNavigationEnabled() && d->orientation == Qt::Vertical) action = d->invertedControls ? SliderSingleStepSub : SliderSingleStepAdd; else #endif @@ -854,7 +857,7 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) case Qt::Key_Right: #ifdef QT_KEYPAD_NAVIGATION // Same logic as in Qt::Key_Left - if (QApplication::keypadNavigationEnabled() + if (QApplicationPrivate::keypadNavigationEnabled() && (!hasEditFocus() && QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder || d->orientation == Qt::Vertical || !hasEditFocus() @@ -862,7 +865,7 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) ev->ignore(); return; } - if (QApplication::keypadNavigationEnabled() && d->orientation == Qt::Vertical) + if (QApplicationPrivate::keypadNavigationEnabled() && d->orientation == Qt::Vertical) action = d->invertedControls ? SliderSingleStepAdd : SliderSingleStepSub; else #endif @@ -875,7 +878,7 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) #ifdef QT_KEYPAD_NAVIGATION // In QApplication::KeypadNavigationDirectional, we want to change the slider // value if there is no up/down navigation possible. - if (QApplication::keypadNavigationEnabled() + if (QApplicationPrivate::keypadNavigationEnabled() && (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder || d->orientation == Qt::Horizontal || !hasEditFocus() && QWidgetPrivate::canKeypadNavigate(Qt::Vertical))) { @@ -888,7 +891,7 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) case Qt::Key_Down: #ifdef QT_KEYPAD_NAVIGATION // Same logic as in Qt::Key_Up - if (QApplication::keypadNavigationEnabled() + if (QApplicationPrivate::keypadNavigationEnabled() && (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder || d->orientation == Qt::Horizontal || !hasEditFocus() && QWidgetPrivate::canKeypadNavigate(Qt::Vertical))) { diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index e6e9939a10a..f5708788b89 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -39,6 +39,7 @@ #include #include +#include #if QT_CONFIG(datetimeparser) #include #endif @@ -803,7 +804,7 @@ bool QAbstractSpinBox::event(QEvent *event) #ifdef QT_KEYPAD_NAVIGATION case QEvent::EnterEditFocus: case QEvent::LeaveEditFocus: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { const bool b = d->edit->event(event); d->edit->setSelection(d->edit->displayText().size() - d->suffix.size(),0); if (event->type() == QEvent::LeaveEditFocus) @@ -1025,7 +1026,7 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event) case Qt::Key_Up: case Qt::Key_Down: { #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { // Reserve up/down for nav - use left/right for edit. if (!hasEditFocus() && (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down)) { @@ -1061,13 +1062,13 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event) #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Left: case Qt::Key_Right: - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) { event->ignore(); return; } break; case Qt::Key_Back: - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) { event->ignore(); return; } @@ -1085,7 +1086,7 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event) #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Select: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { // Toggles between left/right moving cursor and inc/dec. setEditFocus(!hasEditFocus()); } @@ -1221,7 +1222,7 @@ void QAbstractSpinBox::focusOutEvent(QFocusEvent *event) #ifdef QT_KEYPAD_NAVIGATION // editingFinished() is already emitted on LeaveEditFocus - if (!QApplication::keypadNavigationEnabled()) + if (!QApplicationPrivate::keypadNavigationEnabled()) #endif emit editingFinished(); } diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp index 510b34cb183..78706b1854e 100644 --- a/src/widgets/widgets/qcalendarwidget.cpp +++ b/src/widgets/widgets/qcalendarwidget.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -1384,14 +1385,14 @@ void QCalendarView::keyPressEvent(QKeyEvent *event) { #ifdef QT_KEYPAD_NAVIGATION if (event->key() == Qt::Key_Select) { - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (!hasEditFocus()) { setEditFocus(true); return; } } } else if (event->key() == Qt::Key_Back) { - if (QApplication::keypadNavigationEnabled() && hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && hasEditFocus()) { if (qobject_cast(model())) { emit changeDate(origDate, true); //changes selection back to origDate, but doesn't activate setEditFocus(false); @@ -1418,7 +1419,7 @@ void QCalendarView::keyPressEvent(QKeyEvent *event) #if QT_CONFIG(wheelevent) void QCalendarView::wheelEvent(QWheelEvent *event) { - const int numDegrees = event->delta() / 8; + const int numDegrees = event->angleDelta().y() / 8; const int numSteps = numDegrees / 15; const QModelIndex index = currentIndex(); QDate currentDate = static_cast(model())->dateForCell(index.row(), index.column()); diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 0b52747b6a9..8b54d61e8e8 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -223,7 +223,7 @@ void QComboBoxPrivate::_q_completerActivated(const QModelIndex &index) } # ifdef QT_KEYPAD_NAVIGATION - if ( QApplication::keypadNavigationEnabled() + if ( QApplicationPrivate::keypadNavigationEnabled() && q->isEditable() && q->completer() && q->completer()->completionMode() == QCompleter::UnfilteredPopupCompletion ) { @@ -896,11 +896,6 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const \fn void QComboBox::currentIndexChanged(const QString &text) \since 4.1 - \obsolete - - Use currentTextChanged(const QString &) or currentIndexChanged(int) - instead. - This signal is sent whenever the currentIndex in the combobox changes either through user interaction or programmatically. The item's \a text is passed. @@ -1539,7 +1534,7 @@ void QComboBox::setAutoCompletion(bool enable) Q_D(QComboBox); #ifdef QT_KEYPAD_NAVIGATION - if (Q_UNLIKELY(QApplication::keypadNavigationEnabled() && !enable && isEditable())) + if (Q_UNLIKELY(QApplicationPrivate::keypadNavigationEnabled() && !enable && isEditable())) qWarning("QComboBox::setAutoCompletion: auto completion is mandatory when combo box editable"); #endif @@ -1886,7 +1881,7 @@ void QComboBox::setLineEdit(QLineEdit *edit) setAutoCompletion(d->autoCompletion); #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { // Editable combo boxes will have a completer that is set to UnfilteredPopupCompletion. // This means that when the user enters edit mode they are immediately presented with a // list of possible completions. @@ -2628,7 +2623,7 @@ bool QComboBoxPrivate::showNativePopup() /*! Displays the list of items in the combobox. If the list is empty - then the no items will be shown. + then no items will be shown. If you reimplement this function to show a custom pop-up, make sure you call hidePopup() to reset the internal state. @@ -2658,7 +2653,7 @@ void QComboBox::showPopup() #ifdef QT_KEYPAD_NAVIGATION #if QT_CONFIG(completer) - if (QApplication::keypadNavigationEnabled() && d->completer) { + if (QApplicationPrivate::keypadNavigationEnabled() && d->completer) { // editable combo box is line edit plus completer setEditFocus(true); d->completer->complete(); // show popup @@ -2719,15 +2714,14 @@ void QComboBox::showPopup() int heightMargin = container->topMargin() + container->bottomMargin(); // add the frame of the container - int marginTop, marginBottom; - container->getContentsMargins(0, &marginTop, 0, &marginBottom); - heightMargin += marginTop + marginBottom; + const QMargins cm = container->contentsMargins(); + heightMargin += cm.top() + cm.bottom(); //add the frame of the view - view()->getContentsMargins(0, &marginTop, 0, &marginBottom); - marginTop += static_cast(QObjectPrivate::get(view()))->top; - marginBottom += static_cast(QObjectPrivate::get(view()))->bottom; - heightMargin += marginTop + marginBottom; + const QMargins vm = view()->contentsMargins(); + heightMargin += vm.top() + vm.bottom(); + heightMargin += static_cast(QObjectPrivate::get(view()))->top; + heightMargin += static_cast(QObjectPrivate::get(view()))->bottom; listRect.setHeight(listRect.height() + heightMargin); } @@ -2864,7 +2858,7 @@ void QComboBox::showPopup() container->update(); #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) view()->setEditFocus(true); #endif if (startTimer) { @@ -2936,7 +2930,7 @@ void QComboBox::hidePopup() d->container->hide(); } #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && isEditable() && hasFocus()) + if (QApplicationPrivate::keypadNavigationEnabled() && isEditable() && hasFocus()) setEditFocus(true); #endif d->_q_resetButton(); @@ -3195,7 +3189,7 @@ void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e) } } else { #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && sc == QStyle::SC_ComboBoxEditField && lineEdit) { + if (QApplicationPrivate::keypadNavigationEnabled() && sc == QStyle::SC_ComboBoxEditField && lineEdit) { lineEdit->event(e); //so lineedit can move cursor, etc return; } @@ -3244,7 +3238,7 @@ void QComboBox::keyPressEvent(QKeyEvent *e) Q_FALLTHROUGH(); case Qt::Key_PageUp: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) e->ignore(); else #endif @@ -3259,7 +3253,7 @@ void QComboBox::keyPressEvent(QKeyEvent *e) Q_FALLTHROUGH(); case Qt::Key_PageDown: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) e->ignore(); else #endif @@ -3293,7 +3287,7 @@ void QComboBox::keyPressEvent(QKeyEvent *e) break; #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Select: - if (QApplication::keypadNavigationEnabled() + if (QApplicationPrivate::keypadNavigationEnabled() && (!hasEditFocus() || !d->lineEdit)) { showPopup(); return; @@ -3301,11 +3295,11 @@ void QComboBox::keyPressEvent(QKeyEvent *e) break; case Qt::Key_Left: case Qt::Key_Right: - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) e->ignore(); break; case Qt::Key_Back: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (!hasEditFocus() || !d->lineEdit) e->ignore(); } else { @@ -3383,12 +3377,13 @@ void QComboBox::wheelEvent(QWheelEvent *e) !d->viewContainer()->isVisible()) { const int rowCount = count(); int newIndex = currentIndex(); + int delta = e->angleDelta().y(); - if (e->delta() > 0) { + if (delta > 0) { newIndex--; while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled)) newIndex--; - } else if (e->delta() < 0) { + } else if (delta < 0) { newIndex++; while (newIndex < rowCount && !(d->model->index(newIndex, d->modelColumn, d->root).flags() & Qt::ItemIsEnabled)) newIndex++; diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h index 3b48b151a1a..286772c0919 100644 --- a/src/widgets/widgets/qcombobox.h +++ b/src/widgets/widgets/qcombobox.h @@ -227,11 +227,8 @@ Q_SIGNALS: void highlighted(int index); void textHighlighted(const QString &); void currentIndexChanged(int index); - void currentTextChanged(const QString &); -#if QT_DEPRECATED_SINCE(5, 13) - QT_DEPRECATED_VERSION_X(5, 13, "Use currentTextChanged() instead") void currentIndexChanged(const QString &); -#endif + void currentTextChanged(const QString &); #if QT_DEPRECATED_SINCE(5, 15) QT_DEPRECATED_VERSION_X(5, 15, "Use textActivated() instead") void activated(const QString &); diff --git a/src/widgets/widgets/qcommandlinkbutton.cpp b/src/widgets/widgets/qcommandlinkbutton.cpp index 68dfefb3b7b..2b9258fd91f 100644 --- a/src/widgets/widgets/qcommandlinkbutton.cpp +++ b/src/widgets/widgets/qcommandlinkbutton.cpp @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE \ingroup basicwidgets \inmodule QtWidgets - The command link is a new control that was introduced by Windows Vista. It's + The command link is a new control that was introduced by Windows Vista. Its intended use is similar to that of a radio button in that it is used to choose between a set of mutually exclusive options. Command link buttons should not be used by themselves but rather as an alternative to radio buttons in diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index 45c72e24d45..3c92d4be0ea 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -37,6 +37,7 @@ ** ****************************************************************************/ +#include #include #include #include @@ -642,7 +643,7 @@ QDateTimeEdit::Section QDateTimeEdit::currentSection() const { Q_D(const QDateTimeEdit); #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && d->focusOnButton) + if (QApplicationPrivate::keypadNavigationEnabled() && d->focusOnButton) return NoSection; #endif return QDateTimeEditPrivate::convertToPublic(d->sectionType(d->currentSectionIndex)); @@ -1055,7 +1056,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event) switch (event->key()) { #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_NumberSign: //shortcut to popup calendar - if (QApplication::keypadNavigationEnabled() && d->calendarPopupEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled() && d->calendarPopupEnabled()) { d->initCalendarPopup(); d->positionCalendarPopup(); d->monthCalendar->show(); @@ -1063,7 +1064,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event) } break; case Qt::Key_Select: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (hasEditFocus()) { if (d->focusOnButton) { d->initCalendarPopup(); @@ -1095,7 +1096,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event) return; default: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && !hasEditFocus() + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus() && !event->text().isEmpty() && event->text().at(0).isLetterOrNumber()) { setEditFocus(true); @@ -1117,8 +1118,8 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event) if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right) { if ( #ifdef QT_KEYPAD_NAVIGATION - QApplication::keypadNavigationEnabled() && !hasEditFocus() - || !QApplication::keypadNavigationEnabled() && + QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus() + || !QApplicationPrivate::keypadNavigationEnabled() && #endif !(event->modifiers() & Qt::ControlModifier)) { select = false; @@ -1127,7 +1128,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event) #if 0 // Used to be included in Qt4 for Q_WS_MAC else #ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled()) + if (!QApplicationPrivate::keypadNavigationEnabled()) #endif { select = (event->modifiers() & Qt::ShiftModifier); @@ -1147,7 +1148,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event) && (event->key() != Qt::Key_Tab || !(event->modifiers() & Qt::ShiftModifier)); #ifdef QT_KEYPAD_NAVIGATION int newSection = d->nextPrevSection(d->currentSectionIndex, forward); - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (d->focusOnButton) { newSection = forward ? 0 : d->sectionNodes.size() - 1; d->focusOnButton = false; @@ -1290,7 +1291,7 @@ void QDateTimeEdit::stepBy(int steps) Q_D(QDateTimeEdit); #ifdef QT_KEYPAD_NAVIGATION // with keypad navigation and not editFocus, left right change the date/time by a fixed amount. - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) { // if date based, shift by day. else shift by 15min if (d->sections & DateSections_Mask) { setDateTime(dateTime().addDays(steps)); @@ -1417,7 +1418,7 @@ QDateTimeEdit::StepEnabled QDateTimeEdit::stepEnabled() const QAbstractSpinBox::StepEnabled ret = 0; #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) { if (d->wrapping) return StepEnabled(StepUpEnabled | StepDownEnabled); // 3 cases. date, time, datetime. each case look @@ -1702,7 +1703,7 @@ void QDateTimeEditPrivate::updateEdit() if (!specialValue() #ifdef QT_KEYPAD_NAVIGATION - && !(QApplication::keypadNavigationEnabled() && !edit->hasEditFocus()) + && !(QApplicationPrivate::keypadNavigationEnabled() && !edit->hasEditFocus()) #endif ) { int cursor = sectionPos(currentSectionIndex); @@ -1731,7 +1732,7 @@ void QDateTimeEditPrivate::setSelected(int sectionIndex, bool forward) { if (specialValue() #ifdef QT_KEYPAD_NAVIGATION - || (QApplication::keypadNavigationEnabled() && !edit->hasEditFocus()) + || (QApplicationPrivate::keypadNavigationEnabled() && !edit->hasEditFocus()) #endif ) { edit->selectAll(); @@ -2426,7 +2427,7 @@ void QDateTimeEditPrivate::init(const QVariant &var) break; } #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) q->setCalendarPopup(true); #endif q->setInputMethodHints(Qt::ImhPreferNumbers); @@ -2602,7 +2603,7 @@ QCalendarWidget *QCalendarPopup::verifyCalendarInstance() QCalendarWidget *cw = new QCalendarWidget(this); cw->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader); #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) cw->setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames); #endif setCalendarWidget(cw); diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 68e3de05bc9..7f482a6a4e9 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -293,7 +293,7 @@ QLineEdit::~QLineEdit() /*! \property QLineEdit::text - \brief the line edit's text + \brief the line edit's text. Setting this property clears the selection, clears the undo/redo history, moves the cursor to the end of the line and resets the @@ -322,7 +322,7 @@ void QLineEdit::setText(const QString& text) \since 4.7 \property QLineEdit::placeholderText - \brief the line edit's placeholder text + \brief the line edit's placeholder text. Setting this property makes the line edit display a grayed-out placeholder text as long as the line edit is empty. @@ -354,7 +354,7 @@ void QLineEdit::setPlaceholderText(const QString& placeholderText) /*! \property QLineEdit::displayText - \brief the displayed text + \brief the displayed text. If \l echoMode is \l Normal this returns the same as text(); if \l EchoMode is \l Password or \l PasswordEchoOnEdit it returns a string of @@ -375,7 +375,7 @@ QString QLineEdit::displayText() const /*! \property QLineEdit::maxLength - \brief the maximum permitted length of the text + \brief the maximum permitted length of the text. If the text is too long, it is truncated at the limit. @@ -405,7 +405,7 @@ void QLineEdit::setMaxLength(int maxLength) /*! \property QLineEdit::frame - \brief whether the line edit draws itself with a frame + \brief whether the line edit draws itself with a frame. If enabled (the default) the line edit draws itself inside a frame, otherwise the line edit draws itself without any frame. @@ -544,7 +544,7 @@ void QLineEdit::setFrame(bool enable) /*! \property QLineEdit::echoMode - \brief the line edit's echo mode + \brief the line edit's echo mode. The echo mode determines how the text entered in the line edit is displayed (or echoed) to the user. @@ -684,11 +684,12 @@ QSize QLineEdit::sizeHint() const ensurePolished(); QFontMetrics fm(font()); const int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this); - int h = qMax(fm.height(), iconSize - 2) + 2 * QLineEditPrivate::verticalMargin - + d->topTextMargin + d->bottomTextMargin + const QMargins tm = d->effectiveTextMargins(); + int h = qMax(fm.height(), qMax(14, iconSize - 2)) + 2 * QLineEditPrivate::verticalMargin + + tm.top() + tm.bottom() + d->topmargin + d->bottommargin; int w = fm.horizontalAdvance(QLatin1Char('x')) * 17 + 2 * QLineEditPrivate::horizontalMargin - + d->effectiveLeftTextMargin() + d->effectiveRightTextMargin() + + tm.left() + tm.right() + d->leftmargin + d->rightmargin; // "some" QStyleOptionFrame opt; initStyleOption(&opt); @@ -708,11 +709,12 @@ QSize QLineEdit::minimumSizeHint() const Q_D(const QLineEdit); ensurePolished(); QFontMetrics fm = fontMetrics(); + const QMargins tm = d->effectiveTextMargins(); int h = fm.height() + qMax(2 * QLineEditPrivate::verticalMargin, fm.leading()) - + d->topTextMargin + d->bottomTextMargin + + tm.top() + tm.bottom() + d->topmargin + d->bottommargin; int w = fm.maxWidth() - + d->effectiveLeftTextMargin() + d->effectiveRightTextMargin() + + tm.left() + tm.right() + d->leftmargin + d->rightmargin; QStyleOptionFrame opt; initStyleOption(&opt); @@ -723,7 +725,7 @@ QSize QLineEdit::minimumSizeHint() const /*! \property QLineEdit::cursorPosition - \brief the current cursor position for this line edit + \brief the current cursor position for this line edit. Setting the cursor position causes a repaint when appropriate. @@ -756,7 +758,7 @@ int QLineEdit::cursorPositionAt(const QPoint &pos) /*! \property QLineEdit::alignment - \brief the alignment of the line edit + \brief the alignment of the line edit. Both horizontal and vertical alignment is allowed here, Qt::AlignJustify will map to Qt::AlignLeft. @@ -894,7 +896,7 @@ void QLineEdit::end(bool mark) /*! \property QLineEdit::modified - \brief whether the line edit's contents has been modified by the user + \brief whether the line edit's contents has been modified by the user. The modified flag is never read by QLineEdit; it has a default value of false and is changed to true whenever the user changes the line @@ -924,7 +926,7 @@ void QLineEdit::setModified(bool modified) /*! \property QLineEdit::hasSelectedText - \brief whether there is any text selected + \brief whether there is any text selected. hasSelectedText() returns \c true if some or all of the text has been selected by the user; otherwise returns \c false. @@ -943,7 +945,7 @@ bool QLineEdit::hasSelectedText() const /*! \property QLineEdit::selectedText - \brief the selected text + \brief the selected text. If there is no selected text this property's value is an empty string. @@ -1030,7 +1032,7 @@ void QLineEdit::setSelection(int start, int length) /*! \property QLineEdit::undoAvailable - \brief whether undo is available + \brief whether undo is available. Undo becomes available once the user has modified the text in the line edit. @@ -1045,7 +1047,7 @@ bool QLineEdit::isUndoAvailable() const /*! \property QLineEdit::redoAvailable - \brief whether redo is available + \brief whether redo is available. Redo becomes available once the user has performed one or more undo operations on text in the line edit. @@ -1062,7 +1064,7 @@ bool QLineEdit::isRedoAvailable() const /*! \property QLineEdit::dragEnabled \brief whether the lineedit starts a drag if the user presses and - moves the mouse on some selected text + moves the mouse on some selected text. Dragging is disabled by default. */ @@ -1081,7 +1083,7 @@ void QLineEdit::setDragEnabled(bool b) /*! \property QLineEdit::cursorMoveStyle - \brief the movement style of cursor in this line edit + \brief the movement style of cursor in this line edit. \since 4.8 When this property is set to Qt::VisualMoveStyle, the line edit will use visual @@ -1127,17 +1129,11 @@ bool QLineEdit::hasAcceptableInput() const sizes \a left, \a top, \a right, and \a bottom. \since 4.5 - See also getTextMargins(). + See also textMargins(). */ void QLineEdit::setTextMargins(int left, int top, int right, int bottom) { - Q_D(QLineEdit); - d->leftTextMargin = left; - d->topTextMargin = top; - d->rightTextMargin = right; - d->bottomTextMargin = bottom; - updateGeometry(); - update(); + setTextMargins({left, top, right, bottom}); } /*! @@ -1148,10 +1144,17 @@ void QLineEdit::setTextMargins(int left, int top, int right, int bottom) */ void QLineEdit::setTextMargins(const QMargins &margins) { - setTextMargins(margins.left(), margins.top(), margins.right(), margins.bottom()); + Q_D(QLineEdit); + d->textMargins = margins; + updateGeometry(); + update(); } +#if QT_DEPRECATED_SINCE(5, 14) /*! + \obsolete + Use textMargins() + Returns the widget's text margins for \a left, \a top, \a right, and \a bottom. \since 4.5 @@ -1159,16 +1162,17 @@ void QLineEdit::setTextMargins(const QMargins &margins) */ void QLineEdit::getTextMargins(int *left, int *top, int *right, int *bottom) const { - Q_D(const QLineEdit); + QMargins m = textMargins(); if (left) - *left = d->leftTextMargin; + *left = m.left(); if (top) - *top = d->topTextMargin; + *top = m.top(); if (right) - *right = d->rightTextMargin; + *right = m.right(); if (bottom) - *bottom = d->bottomTextMargin; + *bottom = m.bottom(); } +#endif /*! \since 4.6 @@ -1179,12 +1183,12 @@ void QLineEdit::getTextMargins(int *left, int *top, int *right, int *bottom) con QMargins QLineEdit::textMargins() const { Q_D(const QLineEdit); - return QMargins(d->leftTextMargin, d->topTextMargin, d->rightTextMargin, d->bottomTextMargin); + return d->textMargins; } /*! \property QLineEdit::inputMask - \brief The validation input mask + \brief The validation input mask. If no mask is set, inputMask() returns an empty string. @@ -1481,7 +1485,7 @@ bool QLineEdit::event(QEvent * e) d->initMouseYThreshold(); } #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (e->type() == QEvent::EnterEditFocus) { end(false); d->setCursorVisible(true); @@ -1513,7 +1517,7 @@ void QLineEdit::mousePressEvent(QMouseEvent* e) if (e->button() == Qt::RightButton) return; #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + if (QApplication::QApplicationPrivate() && !hasEditFocus()) { setEditFocus(true); // Get the completion list to pop up. if (d->control->completer()) @@ -1722,7 +1726,7 @@ void QLineEdit::keyPressEvent(QKeyEvent *event) bool select = false; switch (event->key()) { case Qt::Key_Select: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (hasEditFocus()) { setEditFocus(false); if (d->control->completer() && d->control->completer()->popup()->isVisible()) @@ -1733,13 +1737,13 @@ void QLineEdit::keyPressEvent(QKeyEvent *event) break; case Qt::Key_Back: case Qt::Key_No: - if (!QApplication::keypadNavigationEnabled() || !hasEditFocus()) { + if (!QApplicationPrivate::keypadNavigationEnabled() || !hasEditFocus()) { event->ignore(); return; } break; default: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (!hasEditFocus() && !(event->modifiers() & Qt::ControlModifier)) { if (!event->text().isEmpty() && event->text().at(0).isPrint() && !isReadOnly()) @@ -1754,7 +1758,7 @@ void QLineEdit::keyPressEvent(QKeyEvent *event) - if (QApplication::keypadNavigationEnabled() && !select && !hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && !select && !hasEditFocus()) { setEditFocus(true); if (event->key() == Qt::Key_Select) return; // Just start. No action. @@ -1801,7 +1805,7 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) // Focus in if currently in navigation focus on the widget // Only focus in on preedits, to allow input methods to // commit text as they focus out without interfering with focus - if (QApplication::keypadNavigationEnabled() + if (QApplicationPrivate::keypadNavigationEnabled() && hasFocus() && !hasEditFocus() && !e->preeditString().isEmpty()) setEditFocus(true); @@ -1874,7 +1878,7 @@ void QLineEdit::focusInEvent(QFocusEvent *e) d->clickCausedFocus = 1; } #ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && ( e->reason() == Qt::PopupFocusReason))) { + if (!QApplicationPrivate::keypadNavigationEnabled() || (hasEditFocus() && ( e->reason() == Qt::PopupFocusReason))) { #endif d->control->setBlinkingCursorEnabled(true); QStyleOptionFrame opt; @@ -1918,7 +1922,7 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) d->control->setBlinkingCursorEnabled(false); #ifdef QT_KEYPAD_NAVIGATION // editingFinished() is already emitted on LeaveEditFocus - if (!QApplication::keypadNavigationEnabled()) + if (!QApplicationPrivate::keypadNavigationEnabled()) #endif if (reason != Qt::PopupFocusReason || !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) { @@ -1950,10 +1954,7 @@ void QLineEdit::paintEvent(QPaintEvent *) initStyleOption(&panel); style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this); QRect r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); - r.setX(r.x() + d->effectiveLeftTextMargin()); - r.setY(r.y() + d->topTextMargin); - r.setRight(r.right() - d->effectiveRightTextMargin()); - r.setBottom(r.bottom() - d->bottomTextMargin); + r = r.marginsRemoved(d->effectiveTextMargins()); p.setClipRect(r); QFontMetrics fm = fontMetrics(); @@ -2041,7 +2042,7 @@ void QLineEdit::paintEvent(QPaintEvent *) int flags = QWidgetLineControl::DrawText; #ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || hasEditFocus()) + if (!QApplicationPrivate::keypadNavigationEnabled() || hasEditFocus()) #endif if (d->control->hasSelectedText() || (d->cursorVisible && !d->control->inputMask().isEmpty() && !d->control->isReadOnly())){ flags |= QWidgetLineControl::DrawSelections; diff --git a/src/widgets/widgets/qlineedit.h b/src/widgets/widgets/qlineedit.h index de82927f74b..1cf1f244492 100644 --- a/src/widgets/widgets/qlineedit.h +++ b/src/widgets/widgets/qlineedit.h @@ -172,7 +172,10 @@ public: void setTextMargins(int left, int top, int right, int bottom); void setTextMargins(const QMargins &margins); +#if QT_DEPRECATED_SINCE(5, 14) + QT_DEPRECATED_X("use textMargins()") void getTextMargins(int *left, int *top, int *right, int *bottom) const; +#endif QMargins textMargins() const; #if QT_CONFIG(action) diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 7d580e50a51..d2b5f87906e 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -254,10 +254,7 @@ QRect QLineEditPrivate::adjustedContentsRect() const QStyleOptionFrame opt; q->initStyleOption(&opt); QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q); - r.setX(r.x() + effectiveLeftTextMargin()); - r.setY(r.y() + topTextMargin); - r.setRight(r.right() - effectiveRightTextMargin()); - r.setBottom(r.bottom() - bottomTextMargin); + r = r.marginsRemoved(effectiveTextMargins()); return r; } @@ -672,14 +669,12 @@ static int effectiveTextMargin(int defaultMargin, const QLineEditPrivate::SideWi return e.widget->isVisibleTo(e.widget->parentWidget()); })); } -int QLineEditPrivate::effectiveLeftTextMargin() const +QMargins QLineEditPrivate::effectiveTextMargins() const { - return effectiveTextMargin(leftTextMargin, leftSideWidgetList(), sideWidgetParameters()); -} - -int QLineEditPrivate::effectiveRightTextMargin() const -{ - return effectiveTextMargin(rightTextMargin, rightSideWidgetList(), sideWidgetParameters()); + return {effectiveTextMargin(textMargins.left(), leftSideWidgetList(), sideWidgetParameters()), + textMargins.top(), + effectiveTextMargin(textMargins.right(), rightSideWidgetList(), sideWidgetParameters()), + textMargins.bottom()}; } diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h index 3f98aab901f..a11fea6bbe4 100644 --- a/src/widgets/widgets/qlineedit_p.h +++ b/src/widgets/widgets/qlineedit_p.h @@ -67,6 +67,7 @@ #endif #include "QtCore/qpointer.h" #include "QtCore/qmimedata.h" +#include #include "private/qwidgetlinecontrol_p.h" @@ -153,7 +154,7 @@ public: : control(0), frame(1), contextMenuEnabled(1), cursorVisible(0), dragEnabled(0), clickCausedFocus(0), edited(0), hscroll(0), vscroll(0), alignment(Qt::AlignLeading | Qt::AlignVCenter), - leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0), + textMargins{0, 0, 0, 0}, lastTextSize(0), mouseYThreshold(0) { } @@ -233,10 +234,7 @@ public: void _q_textChanged(const QString &); void _q_clearButtonClicked(); - int leftTextMargin; // use effectiveLeftTextMargin() in case of icon. - int topTextMargin; - int rightTextMargin; // use effectiveRightTextMargin() in case of icon. - int bottomTextMargin; + QMargins textMargins; // use effectiveTextMargins() in case of icon. QString placeholderText; @@ -252,8 +250,7 @@ public: inline const SideWidgetEntryList &rightSideWidgetList() const { return q_func()->layoutDirection() == Qt::LeftToRight ? trailingSideWidgets : leadingSideWidgets; } - int effectiveLeftTextMargin() const; - int effectiveRightTextMargin() const; + QMargins effectiveTextMargins() const; private: struct SideWidgetLocation { diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 72653b377d1..e38490dabdf 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -142,9 +142,7 @@ public: #endif if (style() != p->style()) setStyle(p->style()); - int leftMargin, topMargin, rightMargin, bottomMargin; - p->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); - setContentsMargins(leftMargin, topMargin, rightMargin, bottomMargin); + setContentsMargins(p->contentsMargins()); setLayoutDirection(p->layoutDirection()); //QObject::connect(this, SIGNAL(triggered(QAction*)), this, SLOT(onTrigger(QAction*))); //QObject::connect(this, SIGNAL(hovered(QAction*)), this, SLOT(onHovered(QAction*))); @@ -200,7 +198,7 @@ void QMenuPrivate::init() q->setAttribute(Qt::WA_X11NetWmWindowTypePopupMenu); defaultMenuAction = menuAction = new QAction(q); menuAction->d_func()->menu = q; - QObject::connect(menuAction, &QAction::changed, [=] { + QObject::connect(menuAction, &QAction::changed, [this] { if (!tornPopup.isNull()) tornPopup->updateWindowTitle(); }); @@ -2392,7 +2390,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction) } #ifdef QT_KEYPAD_NAVIGATION - if (!atAction && QApplication::keypadNavigationEnabled()) { + if (!atAction && QApplicationPrivate::keypadNavigationEnabled()) { // Try to have one item activated if (d->defaultAction && d->defaultAction->isEnabled()) { atAction = d->defaultAction; @@ -2847,8 +2845,8 @@ void QMenu::paintEvent(QPaintEvent *e) void QMenu::wheelEvent(QWheelEvent *e) { Q_D(QMenu); - if (d->scroll && rect().contains(e->pos())) - d->scrollMenu(e->delta() > 0 ? + if (d->scroll && rect().contains(e->position().toPoint())) + d->scrollMenu(e->angleDelta().y() > 0 ? QMenuPrivate::QMenuScroller::ScrollUp : QMenuPrivate::QMenuScroller::ScrollDown); } #endif diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index 397304ec440..88437974304 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -54,6 +54,7 @@ #endif #include #include +#include "private/qapplication_p.h" #include "private/qtextdocumentlayout_p.h" #include "private/qabstracttextdocumentlayout_p.h" #include "qtextdocument.h" @@ -1573,7 +1574,7 @@ bool QPlainTextEdit::event(QEvent *e) } #ifdef QT_KEYPAD_NAVIGATION else if (e->type() == QEvent::EnterEditFocus || e->type() == QEvent::LeaveEditFocus) { - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) d->sendControlEvent(e); } #endif @@ -1691,7 +1692,7 @@ void QPlainTextEdit::keyPressEvent(QKeyEvent *e) #ifdef QT_KEYPAD_NAVIGATION switch (e->key()) { case Qt::Key_Select: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (!(d->control->textInteractionFlags() & Qt::LinksAccessibleByKeyboard)) setEditFocus(!hasEditFocus()); else { @@ -1709,14 +1710,14 @@ void QPlainTextEdit::keyPressEvent(QKeyEvent *e) break; case Qt::Key_Back: case Qt::Key_No: - if (!QApplication::keypadNavigationEnabled() - || (QApplication::keypadNavigationEnabled() && !hasEditFocus())) { + if (!QApplicationPrivate::keypadNavigationEnabled() + || (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus())) { e->ignore(); return; } break; default: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (!hasEditFocus() && !(e->modifiers() & Qt::ControlModifier)) { if (e->text()[0].isPrint()) { setEditFocus(true); @@ -1792,7 +1793,7 @@ void QPlainTextEdit::keyPressEvent(QKeyEvent *e) switch (e->key()) { case Qt::Key_Up: case Qt::Key_Down: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { // Cursor position didn't change, so we want to leave // these keys to change focus. e->ignore(); @@ -1801,7 +1802,7 @@ void QPlainTextEdit::keyPressEvent(QKeyEvent *e) break; case Qt::Key_Left: case Qt::Key_Right: - if (QApplication::keypadNavigationEnabled() + if (QApplicationPrivate::keypadNavigationEnabled() && QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { // Same as for Key_Up and Key_Down. e->ignore(); @@ -1810,7 +1811,7 @@ void QPlainTextEdit::keyPressEvent(QKeyEvent *e) break; case Qt::Key_Back: if (!e->isAutoRepeat()) { - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (document()->isEmpty()) { setEditFocus(false); e->accept(); @@ -1836,7 +1837,7 @@ void QPlainTextEdit::keyReleaseEvent(QKeyEvent *e) { #ifdef QT_KEYPAD_NAVIGATION Q_D(QPlainTextEdit); - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (!e->isAutoRepeat() && e->key() == Qt::Key_Back && d->deleteAllTimer.isActive()) { d->deleteAllTimer.stop(); @@ -2080,7 +2081,7 @@ void QPlainTextEdit::mousePressEvent(QMouseEvent *e) { Q_D(QPlainTextEdit); #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) setEditFocus(true); #endif d->sendControlEvent(e); @@ -2212,7 +2213,7 @@ void QPlainTextEdit::inputMethodEvent(QInputMethodEvent *e) Q_D(QPlainTextEdit); #ifdef QT_KEYPAD_NAVIGATION if (d->control->textInteractionFlags() & Qt::TextEditable - && QApplication::keypadNavigationEnabled() + && QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) { setEditFocus(true); selectAll(); // so text is replaced rather than appended to diff --git a/src/widgets/widgets/qscrollarea.cpp b/src/widgets/widgets/qscrollarea.cpp index 9994344d79f..68aa545082c 100644 --- a/src/widgets/widgets/qscrollarea.cpp +++ b/src/widgets/widgets/qscrollarea.cpp @@ -46,6 +46,7 @@ #include "qapplication.h" #include "qvariant.h" #include "qdebug.h" +#include "private/qapplication_p.h" #include "private/qlayoutengine_p.h" QT_BEGIN_NAMESPACE @@ -300,7 +301,7 @@ bool QScrollArea::event(QEvent *e) d->updateScrollBars(); } #ifdef QT_KEYPAD_NAVIGATION - else if (QApplication::keypadNavigationEnabled()) { + else if (QApplicationPrivate::keypadNavigationEnabled()) { if (e->type() == QEvent::Show) QApplication::instance()->installEventFilter(this); else if (e->type() == QEvent::Hide) @@ -319,7 +320,7 @@ bool QScrollArea::eventFilter(QObject *o, QEvent *e) Q_D(QScrollArea); #ifdef QT_KEYPAD_NAVIGATION if (d->widget && o != d->widget && e->type() == QEvent::FocusIn - && QApplication::keypadNavigationEnabled()) { + && QApplicationPrivate::keypadNavigationEnabled()) { if (o->isWidgetType()) ensureWidgetVisible(static_cast(o)); } diff --git a/src/widgets/widgets/qscrollbar.cpp b/src/widgets/widgets/qscrollbar.cpp index b4168268a0b..08d771a27a6 100644 --- a/src/widgets/widgets/qscrollbar.cpp +++ b/src/widgets/widgets/qscrollbar.cpp @@ -497,16 +497,14 @@ bool QScrollBar::event(QEvent *event) void QScrollBar::wheelEvent(QWheelEvent *event) { event->ignore(); - int delta = event->delta(); // scrollbar is a special case - in vertical mode it reaches minimum // value in the upper position, however QSlider's minimum value is on - // the bottom. So we need to invert a value, but since the scrollbar is - // inverted by default, we need to inverse the delta value for the + // the bottom. So we need to invert the value, but since the scrollbar is + // inverted by default, we need to invert the delta value only for the // horizontal orientation. - if (event->orientation() == Qt::Horizontal) - delta = -delta; + int delta = (orientation() == Qt::Horizontal ? -event->angleDelta().x() : event->angleDelta().y()); Q_D(QScrollBar); - if (d->scrollByDelta(event->orientation(), event->modifiers(), delta)) + if (d->scrollByDelta(orientation(), event->modifiers(), delta)) event->accept(); if (event->phase() == Qt::ScrollBegin) diff --git a/src/widgets/widgets/qslider.cpp b/src/widgets/widgets/qslider.cpp index 47d3b2fb811..161e4ba27a6 100644 --- a/src/widgets/widgets/qslider.cpp +++ b/src/widgets/widgets/qslider.cpp @@ -46,6 +46,7 @@ #include "qpainter.h" #include "qstyle.h" #include "qstyleoption.h" +#include "private/qapplication_p.h" #include "private/qabstractslider_p.h" #include "qdebug.h" @@ -360,7 +361,7 @@ void QSlider::mousePressEvent(QMouseEvent *ev) return; } #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) setEditFocus(true); #endif ev->accept(); diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp index 08533040a72..e7a4889996c 100644 --- a/src/widgets/widgets/qsplitter.cpp +++ b/src/widgets/widgets/qsplitter.cpp @@ -771,14 +771,13 @@ void QSplitterPrivate::setGeo(QSplitterLayoutStruct *sls, int p, int s, bool all if (!sls->handle->isHidden()) { QSplitterHandle *h = sls->handle; QSize hs = h->sizeHint(); - int left, top, right, bottom; - h->getContentsMargins(&left, &top, &right, &bottom); + const QMargins m = h->contentsMargins(); if (orient==Qt::Horizontal) { if (q->isRightToLeft()) p = contents.width() - p + hs.width(); - h->setGeometry(p-hs.width() - left, contents.y(), hs.width() + left + right, contents.height()); + h->setGeometry(p-hs.width() - m.left(), contents.y(), hs.width() + m.left() + m.right(), contents.height()); } else { - h->setGeometry(contents.x(), p-hs.height() - top, contents.width(), hs.height() + top + bottom); + h->setGeometry(contents.x(), p-hs.height() - m.top(), contents.width(), hs.height() + m.top() + m.bottom()); } } } diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index f6f56c12d18..18fda11ddf2 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -65,6 +65,7 @@ #endif #include "qdebug.h" +#include "private/qapplication_p.h" #include "private/qtabbar_p.h" #if 0 // Used to be included in Qt4 for Q_WS_MAC @@ -415,7 +416,7 @@ void QTabBarPrivate::init() QObject::connect(rightB, SIGNAL(clicked()), q, SLOT(_q_scrollTabs())); rightB->hide(); #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { leftB->setFocusPolicy(Qt::NoFocus); rightB->setFocusPolicy(Qt::NoFocus); q->setFocusPolicy(Qt::NoFocus); @@ -2210,7 +2211,9 @@ void QTabBar::wheelEvent(QWheelEvent *event) { #ifndef Q_OS_MAC Q_D(QTabBar); - int offset = event->delta() > 0 ? -1 : 1; + int delta = (qAbs(event->angleDelta().x()) > qAbs(event->angleDelta().y()) ? + event->angleDelta().x() : event->angleDelta().y()); + int offset = delta > 0 ? -1 : 1; d->setCurrentNextEnabledIndex(offset); QWidget::wheelEvent(event); #else diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp index 547b8a82f91..4d7b39ae019 100644 --- a/src/widgets/widgets/qtabwidget.cpp +++ b/src/widgets/widgets/qtabwidget.cpp @@ -39,6 +39,7 @@ #include "qtabwidget.h" +#include "private/qapplication_p.h" #include "private/qwidget_p.h" #include "private/qtabbar_p.h" #include "qapplication.h" @@ -241,7 +242,7 @@ void QTabWidgetPrivate::init() q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::TabWidget)); #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) q->setFocusPolicy(Qt::NoFocus); else #endif @@ -1108,14 +1109,14 @@ void QTabWidget::keyPressEvent(QKeyEvent *e) if (((e->key() == Qt::Key_Tab || e->key() == Qt::Key_Backtab) && count() > 1 && e->modifiers() & Qt::ControlModifier) #ifdef QT_KEYPAD_NAVIGATION - || QApplication::keypadNavigationEnabled() && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right) && count() > 1 + || QApplicationPrivate::keypadNavigationEnabled() && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right) && count() > 1 #endif ) { int pageCount = d->tabs->count(); int page = currentIndex(); int dx = (e->key() == Qt::Key_Backtab || e->modifiers() & Qt::ShiftModifier) ? -1 : 1; #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)) + if (QApplicationPrivate::keypadNavigationEnabled() && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)) dx = e->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1; #endif for (int pass = 0; pass < pageCount; ++pass) { diff --git a/src/widgets/widgets/qtextbrowser.cpp b/src/widgets/widgets/qtextbrowser.cpp index 7a77f86de2c..3e493903151 100644 --- a/src/widgets/widgets/qtextbrowser.cpp +++ b/src/widgets/widgets/qtextbrowser.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -1016,7 +1017,7 @@ void QTextBrowser::keyPressEvent(QKeyEvent *ev) Q_D(QTextBrowser); switch (ev->key()) { case Qt::Key_Select: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (!hasEditFocus()) { setEditFocus(true); return; @@ -1031,7 +1032,7 @@ void QTextBrowser::keyPressEvent(QKeyEvent *ev) } break; case Qt::Key_Back: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (hasEditFocus()) { setEditFocus(false); ev->accept(); @@ -1041,7 +1042,7 @@ void QTextBrowser::keyPressEvent(QKeyEvent *ev) QTextEdit::keyPressEvent(ev); return; default: - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) { ev->ignore(); return; } diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 8599573e5a9..bd9e5f8159c 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -1116,7 +1117,7 @@ bool QTextEdit::event(QEvent *e) #endif // QT_NO_CONTEXTMENU #ifdef QT_KEYPAD_NAVIGATION if (e->type() == QEvent::EnterEditFocus || e->type() == QEvent::LeaveEditFocus) { - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) d->sendControlEvent(e); } #endif @@ -1301,7 +1302,7 @@ void QTextEdit::keyPressEvent(QKeyEvent *e) #ifdef QT_KEYPAD_NAVIGATION switch (e->key()) { case Qt::Key_Select: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { // code assumes linksaccessible + editable isn't meaningful if (d->control->textInteractionFlags() & Qt::TextEditable) { setEditFocus(!hasEditFocus()); @@ -1322,14 +1323,14 @@ void QTextEdit::keyPressEvent(QKeyEvent *e) break; case Qt::Key_Back: case Qt::Key_No: - if (!QApplication::keypadNavigationEnabled() - || (QApplication::keypadNavigationEnabled() && !hasEditFocus())) { + if (!QApplicationPrivate::keypadNavigationEnabled() + || (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus())) { e->ignore(); return; } break; default: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (!hasEditFocus() && !(e->modifiers() & Qt::ControlModifier)) { if (e->text()[0].isPrint()) setEditFocus(true); @@ -1418,7 +1419,7 @@ void QTextEdit::keyPressEvent(QKeyEvent *e) switch (e->key()) { case Qt::Key_Up: case Qt::Key_Down: - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { // Cursor position didn't change, so we want to leave // these keys to change focus. e->ignore(); @@ -1427,7 +1428,7 @@ void QTextEdit::keyPressEvent(QKeyEvent *e) break; case Qt::Key_Back: if (!e->isAutoRepeat()) { - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (document()->isEmpty() || !(d->control->textInteractionFlags() & Qt::TextEditable)) { setEditFocus(false); e->accept(); @@ -1453,7 +1454,7 @@ void QTextEdit::keyReleaseEvent(QKeyEvent *e) { #ifdef QT_KEYPAD_NAVIGATION Q_D(QTextEdit); - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (!e->isAutoRepeat() && e->key() == Qt::Key_Back && d->deleteAllTimer.isActive()) { d->deleteAllTimer.stop(); @@ -1665,7 +1666,7 @@ void QTextEdit::mousePressEvent(QMouseEvent *e) { Q_D(QTextEdit); #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) + if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) setEditFocus(true); #endif d->sendControlEvent(e); @@ -1796,7 +1797,7 @@ void QTextEdit::inputMethodEvent(QInputMethodEvent *e) Q_D(QTextEdit); #ifdef QT_KEYPAD_NAVIGATION if (d->control->textInteractionFlags() & Qt::TextEditable - && QApplication::keypadNavigationEnabled() + && QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) setEditFocus(true); #endif diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp index fcaafbc5818..d1a0f5ea78e 100644 --- a/src/widgets/widgets/qtoolbar.cpp +++ b/src/widgets/widgets/qtoolbar.cpp @@ -53,7 +53,6 @@ #if QT_CONFIG(rubberband) #include #endif -#include #include #include #include diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index 56dba1dd32f..46bc29eed71 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -54,6 +54,7 @@ #endif #include "qapplication.h" +#include "private/qapplication_p.h" #if QT_CONFIG(graphicsview) #include "qgraphicssceneevent.h" #endif @@ -1662,7 +1663,7 @@ void QWidgetLineControl::processKeyEvent(QKeyEvent* event) case Qt::Key_F4: #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Select: - if (!QApplication::keypadNavigationEnabled()) + if (!QApplicationPrivate::keypadNavigationEnabled()) break; #endif if (!m_completer->currentCompletion().isEmpty() && hasSelectedText() @@ -1912,7 +1913,7 @@ void QWidgetLineControl::processKeyEvent(QKeyEvent* event) break; #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Back: - if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat() + if (QApplicationPrivate::keypadNavigationEnabled() && !event->isAutoRepeat() && !isReadOnly()) { if (text().length() == 0) { setText(m_cancelText); diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 70e1c148a1e..fdbaf29dd81 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -55,6 +55,7 @@ #endif #include #include +#include "private/qapplication_p.h" #include "private/qtextdocumentlayout_p.h" #include "private/qabstracttextdocumentlayout_p.h" #include "qtextdocument.h" @@ -294,7 +295,7 @@ bool QWidgetTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) bool isNavigationEvent = e->key() == Qt::Key_Up || e->key() == Qt::Key_Down; #ifdef QT_KEYPAD_NAVIGATION - ignoreNavigationEvents = ignoreNavigationEvents || QApplication::keypadNavigationEnabled(); + ignoreNavigationEvents = ignoreNavigationEvents || QApplicationPrivate::keypadNavigationEnabled(); isNavigationEvent = isNavigationEvent || (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)); @@ -1159,7 +1160,7 @@ void QWidgetTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget #ifdef QT_KEYPAD_NAVIGATION case QEvent::EnterEditFocus: case QEvent::LeaveEditFocus: - if (QApplication::keypadNavigationEnabled()) + if (QApplicationPrivate::keypadNavigationEnabled()) d->editFocusEvent(e); break; #endif @@ -2218,7 +2219,7 @@ void QWidgetTextControlPrivate::focusEvent(QFocusEvent *e) emit q->updateRequest(q->selectionRect()); if (e->gotFocus()) { #ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || (hasEditFocus && (e->reason() == Qt::PopupFocusReason))) { + if (!QApplicationPrivate::keypadNavigationEnabled() || (hasEditFocus && (e->reason() == Qt::PopupFocusReason))) { #endif cursorOn = (interactionFlags & (Qt::TextSelectableByKeyboard | Qt::TextEditable)); if (interactionFlags & Qt::TextEditable) { @@ -2259,7 +2260,7 @@ void QWidgetTextControlPrivate::editFocusEvent(QEvent *e) { Q_Q(QWidgetTextControl); - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keypadNavigationEnabled()) { if (e->type() == QEvent::EnterEditFocus && interactionFlags & Qt::TextEditable) { const QTextCursor oldSelection = cursor; const int oldCursorPos = cursor.position(); @@ -3280,7 +3281,7 @@ QAbstractTextDocumentLayout::PaintContext QWidgetTextControl::getPaintContext(QW if (!d->dndFeedbackCursor.isNull()) ctx.cursorPosition = d->dndFeedbackCursor.position(); #ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || d->hasEditFocus) + if (!QApplicationPrivate::keypadNavigationEnabled() || d->hasEditFocus) #endif if (d->cursor.hasSelection()) { QAbstractTextDocumentLayout::Selection selection; diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index 1c45118fb12..1993073cce2 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -1161,12 +1161,12 @@ QChar QXmlInputSource::next() d->nextReturnedEndOfData = false; fetchData(); if (d->pos >= d->length) { - return EndOfDocument; + return QChar(EndOfDocument); } return next(); } d->nextReturnedEndOfData = true; - return EndOfData; + return QChar(EndOfData); } // QXmlInputSource has no way to signal encoding errors. The best we can do @@ -1174,7 +1174,7 @@ QChar QXmlInputSource::next() // will then just call this function again to get the next char. QChar c = d->unicode[d->pos++]; if (c.unicode() == EndOfData) - c = EndOfDocument; + c = QChar(EndOfDocument); return c; } @@ -1313,8 +1313,8 @@ static QString extractEncodingDecl(const QString &text, bool *needMoreText) return QString(); while (pos < endPos) { - ushort uc = text.at(pos).unicode(); - if (uc == '\'' || uc == '"') + QChar uc = text.at(pos); + if (uc == u'\'' || uc == u'"') break; ++pos; } @@ -1325,8 +1325,8 @@ static QString extractEncodingDecl(const QString &text, bool *needMoreText) QString encoding; ++pos; while (pos < endPos) { - ushort uc = text.at(pos).unicode(); - if (uc == '\'' || uc == '"') + QChar uc = text.at(pos); + if (uc == u'\'' || uc == u'"') break; encoding.append(uc); ++pos; @@ -7800,7 +7800,7 @@ void QXmlSimpleReaderPrivate::next() c = inputSource->next(); // If we are not incremental parsing, we just skip over EndOfData chars to give the // parser an uninterrupted stream of document chars. - if (c == QXmlInputSource::EndOfData && parseStack == nullptr) + if (c == QChar(QXmlInputSource::EndOfData) && parseStack == nullptr) c = inputSource->next(); if (uc == '\n') { lineNr++; @@ -7877,7 +7877,7 @@ void QXmlSimpleReaderPrivate::init(const QXmlInputSource *i) */ void QXmlSimpleReaderPrivate::initData() { - c = QXmlInputSource::EndOfData; + c = QChar(QXmlInputSource::EndOfData); xmlRefStack.clear(); next(); } @@ -7925,7 +7925,7 @@ void QXmlSimpleReaderPrivate::unexpectedEof(ParseFunction where, int state) if (parseStack == nullptr) { reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF)); } else { - if (c == QXmlInputSource::EndOfDocument) { + if (c == QChar(QXmlInputSource::EndOfDocument)) { reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF)); } else { pushParseState(where, state); diff --git a/tests/auto/concurrent/qtconcurrentfilter/CMakeLists.txt b/tests/auto/concurrent/qtconcurrentfilter/CMakeLists.txt index e4e6884728b..df8d278ee04 100644 --- a/tests/auto/concurrent/qtconcurrentfilter/CMakeLists.txt +++ b/tests/auto/concurrent/qtconcurrentfilter/CMakeLists.txt @@ -5,10 +5,12 @@ ##################################################################### add_qt_test(tst_qtconcurrentfilter + GUI SOURCES tst_qtconcurrentfilter.cpp DEFINES + # -QT_NO_LINKED_LIST # special case remove until figured out how to deal with this QT_STRICT_ITERATORS - LIBRARIES + PUBLIC_LIBRARIES Qt::Concurrent ) diff --git a/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro b/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro index f3684faa611..15345d40db7 100644 --- a/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro +++ b/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro @@ -3,3 +3,4 @@ TARGET = tst_qtconcurrentfilter QT = core testlib concurrent SOURCES = tst_qtconcurrentfilter.cpp DEFINES += QT_STRICT_ITERATORS +DEFINES -= QT_NO_LINKED_LIST diff --git a/tests/auto/concurrent/qtconcurrentmap/CMakeLists.txt b/tests/auto/concurrent/qtconcurrentmap/CMakeLists.txt index 2158aa7d754..1dce177058f 100644 --- a/tests/auto/concurrent/qtconcurrentmap/CMakeLists.txt +++ b/tests/auto/concurrent/qtconcurrentmap/CMakeLists.txt @@ -5,16 +5,15 @@ ##################################################################### add_qt_test(tst_qtconcurrentmap + GUI SOURCES tst_qtconcurrentmap.cpp DEFINES + # -QT_NO_LINKED_LIST # special case remove until we figure this out QT_STRICT_ITERATORS - LIBRARIES + PUBLIC_LIBRARIES Qt::Concurrent ) ## Scopes: ##################################################################### -# -#extend_target(tst_qtconcurrentmap CONDITION contains(QT_CONFIG, c++1z) -#) diff --git a/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro b/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro index fd8fd0a74a9..717d103e449 100644 --- a/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro +++ b/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro @@ -3,6 +3,7 @@ TARGET = tst_qtconcurrentmap QT = core testlib concurrent SOURCES = tst_qtconcurrentmap.cpp DEFINES += QT_STRICT_ITERATORS +DEFINES -= QT_NO_LINKED_LIST # Force C++17 if available contains(QT_CONFIG, c++1z): CONFIG += c++1z diff --git a/tests/auto/corelib/.prev_CMakeLists.txt b/tests/auto/corelib/.prev_CMakeLists.txt index 906e496da92..1029b146540 100644 --- a/tests/auto/corelib/.prev_CMakeLists.txt +++ b/tests/auto/corelib/.prev_CMakeLists.txt @@ -11,6 +11,7 @@ if(NOT APPLE_UIKIT) add_subdirectory(plugin) add_subdirectory(serialization) add_subdirectory(statemachine) + add_subdirectory(text) add_subdirectory(thread) add_subdirectory(time) add_subdirectory(tools) diff --git a/tests/auto/corelib/CMakeLists.txt b/tests/auto/corelib/CMakeLists.txt index cb1228a1a00..d9137d49e33 100644 --- a/tests/auto/corelib/CMakeLists.txt +++ b/tests/auto/corelib/CMakeLists.txt @@ -11,6 +11,7 @@ if(NOT APPLE_UIKIT) # add_subdirectory(plugin) # special case missing project add_subdirectory(serialization) add_subdirectory(statemachine) + add_subdirectory(text) add_subdirectory(thread) add_subdirectory(time) add_subdirectory(tools) diff --git a/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST b/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST index b5b37b44988..3e42a737dfd 100644 --- a/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST +++ b/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST @@ -1,3 +1,2 @@ [deleteChildrenWithRunningGroup] -osx-10.12 osx-10.13 diff --git a/tests/auto/corelib/animation/qpauseanimation/BLACKLIST b/tests/auto/corelib/animation/qpauseanimation/BLACKLIST index e223ec82e26..53372ce9aeb 100644 --- a/tests/auto/corelib/animation/qpauseanimation/BLACKLIST +++ b/tests/auto/corelib/animation/qpauseanimation/BLACKLIST @@ -1,6 +1,9 @@ [pauseAndPropertyAnimations] -* +osx-10.12 +osx-10.14 +osx-10.13 [multipleSequentialGroups] -osx -[noTimerUpdates] -osx +osx-10.12 +osx-10.14 +osx-10.13 + diff --git a/tests/auto/corelib/animation/qpropertyanimation/BLACKLIST b/tests/auto/corelib/animation/qpropertyanimation/BLACKLIST deleted file mode 100644 index a8719b241a0..00000000000 --- a/tests/auto/corelib/animation/qpropertyanimation/BLACKLIST +++ /dev/null @@ -1,6 +0,0 @@ -[statesAndSignals:normal animation] -windows -[startBackwardWithoutEndValue] -windows -[startWithoutStartValue] -osx diff --git a/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST b/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST index 4c999ff88f5..e516c0e8260 100644 --- a/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST +++ b/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST @@ -1,8 +1,6 @@ -[startGroupWithRunningChild] -windows [finishWithUncontrolledAnimation] -windows -osx-10.12 +windows-10 msvc-2015 osx-10.13 [groupWithZeroDurationAnimations] -osx +osx-10.13 + diff --git a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp index 6cadebfd7f6..78b6449a690 100644 --- a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp +++ b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp @@ -263,7 +263,7 @@ void tst_QTextCodec::fromUnicode() If the encoding is a superset of ASCII, test that the byte array is correct (no off by one, no trailing '\0'). */ - QByteArray result = codec->fromUnicode(QStringViewLiteral("abc")); + QByteArray result = codec->fromUnicode(u"abc"); if (result.startsWith('a')) { QCOMPARE(result.size(), 3); QCOMPARE(result, QByteArray("abc")); diff --git a/tests/auto/corelib/corelib.pro b/tests/auto/corelib/corelib.pro index 1d76e1549be..d696e174aaa 100644 --- a/tests/auto/corelib/corelib.pro +++ b/tests/auto/corelib/corelib.pro @@ -13,6 +13,7 @@ SUBDIRS = \ plugin \ serialization \ statemachine \ + text \ thread \ time \ tools diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp index e4b783ad6f8..84e5ccce492 100644 --- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp +++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp @@ -50,8 +50,8 @@ private slots: void installMessageHandler(); #if QT_DEPRECATED_SINCE(5, 0) void installMsgHandler(); -#endif void installBothHandler(); +#endif #ifdef QT_BUILD_INTERNAL void cleanupFuncinfo_data(); @@ -163,7 +163,6 @@ void tst_qmessagehandler::installMsgHandler() QtMsgHandler myHandler = qInstallMsgHandler(oldHandler); QCOMPARE((void*)myHandler, (void*)customMsgHandler); } -#endif void tst_qmessagehandler::installBothHandler() { @@ -178,6 +177,7 @@ void tst_qmessagehandler::installBothHandler() QCOMPARE(s_function, Q_FUNC_INFO); QCOMPARE(s_line, line); } +#endif # define ADD(x) QTest::newRow(x) << Q_FUNC_INFO << x; diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index a818c6c09dc..584e66a7db1 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -506,7 +506,7 @@ void tst_QDebug::qDebugQStringView() const { QLatin1String file, function; int line = 0; - const QStringView inView = QStringViewLiteral("input"); + const QStringView inView = u"input"; MessageHandlerSetter mhs(myMessageHandler); { qDebug() << inView; } diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index 2aebc67dcf9..52e7ebadb17 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -1268,6 +1268,7 @@ tst_QDir::cleanPath_data() QTest::newRow("drive-above-root") << "A:/.." << "A:/.."; QTest::newRow("unc-server-up") << "//server/path/.." << "//server"; QTest::newRow("unc-server-above-root") << "//server/.." << "//server/.."; + QTest::newRow("longpath") << "\\\\?\\d:\\" << "d:/"; #else QTest::newRow("data15") << "//c:/foo" << "/c:/foo"; #endif // non-windows @@ -1745,6 +1746,7 @@ void tst_QDir::nativeSeparators() QCOMPARE(QDir::toNativeSeparators(QLatin1String("\\")), QString("\\")); QCOMPARE(QDir::fromNativeSeparators(QLatin1String("/")), QString("/")); QCOMPARE(QDir::fromNativeSeparators(QLatin1String("\\")), QString("/")); + QCOMPARE(QDir::fromNativeSeparators(QLatin1String("\\\\?\\C:\\")), QString("C:/")); #else QCOMPARE(QDir::toNativeSeparators(QLatin1String("/")), QString("/")); QCOMPARE(QDir::toNativeSeparators(QLatin1String("\\")), QString("\\")); diff --git a/tests/auto/corelib/io/qfile/.prev_CMakeLists.txt b/tests/auto/corelib/io/qfile/.prev_CMakeLists.txt index 57824a82c75..7b5c5bab8c1 100644 --- a/tests/auto/corelib/io/qfile/.prev_CMakeLists.txt +++ b/tests/auto/corelib/io/qfile/.prev_CMakeLists.txt @@ -30,23 +30,35 @@ add_qt_test(tst_qfile ) # Resources: +set(qfile_resource_files + "resources/" +) + add_qt_resource(tst_qfile "qfile" PREFIX "/tst_qfileinfo/" FILES - "resources/" + ${qfile_resource_files} ) +set(rename-fallback_resource_files + "rename-fallback.qrc" +) + add_qt_resource(tst_qfile "rename-fallback" PREFIX "/" FILES - "rename-fallback.qrc" + ${rename-fallback_resource_files} ) +set(copy-fallback_resource_files + "copy-fallback.qrc" +) + add_qt_resource(tst_qfile "copy-fallback" PREFIX "/" FILES - "copy-fallback.qrc" + ${copy-fallback_resource_files} ) diff --git a/tests/auto/corelib/io/qfile/BLACKLIST b/tests/auto/corelib/io/qfile/BLACKLIST deleted file mode 100644 index 8366667166c..00000000000 --- a/tests/auto/corelib/io/qfile/BLACKLIST +++ /dev/null @@ -1,7 +0,0 @@ -# QTBUG-48455 -[readLineStdin] -msvc-2015 ci -msvc-2017 ci -[readLineStdin_lineByLine] -msvc-2015 ci -msvc-2017 ci diff --git a/tests/auto/corelib/io/qfile/CMakeLists.txt b/tests/auto/corelib/io/qfile/CMakeLists.txt index d4fd6e48cf0..70c471858cb 100644 --- a/tests/auto/corelib/io/qfile/CMakeLists.txt +++ b/tests/auto/corelib/io/qfile/CMakeLists.txt @@ -5,7 +5,7 @@ ##################################################################### # Collect test data -list(APPEND test_data "BLACKLIST") +# list(APPEND test_data "BLACKLIST") # special case remove list(APPEND test_data "dosfile.txt") list(APPEND test_data "noendofline.txt") list(APPEND test_data "testfile.txt") @@ -30,23 +30,35 @@ add_qt_test(tst_qfile ) # Resources: +set(qfile_resource_files + "resources/" +) + add_qt_resource(tst_qfile "qfile" PREFIX "/tst_qfileinfo/" FILES - "resources/" + ${qfile_resource_files} ) +set(rename-fallback_resource_files + "rename-fallback.qrc" +) + add_qt_resource(tst_qfile "rename-fallback" PREFIX "/" FILES - "rename-fallback.qrc" + ${rename-fallback_resource_files} ) +set(copy-fallback_resource_files + "copy-fallback.qrc" +) + add_qt_resource(tst_qfile "copy-fallback" PREFIX "/" FILES - "copy-fallback.qrc" + ${copy-fallback_resource_files} ) diff --git a/tests/auto/corelib/io/qfilesystemwatcher/BLACKLIST b/tests/auto/corelib/io/qfilesystemwatcher/BLACKLIST index 90b714758a3..9b210b0d5f1 100644 --- a/tests/auto/corelib/io/qfilesystemwatcher/BLACKLIST +++ b/tests/auto/corelib/io/qfilesystemwatcher/BLACKLIST @@ -1,6 +1,9 @@ # QTBUG-33574 QTBUG-30943 [signalsEmittedAfterFileMoved] -windows +windows-10 msvc-2017 +windows-10 msvc-2019 +windows-10 msvc-2015 +windows-7sp1 [watchFileAndItsDirectory:native backend-testfile] osx windows diff --git a/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp b/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp index 569c610e24e..b05c89a8bb1 100644 --- a/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp +++ b/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp @@ -65,7 +65,7 @@ void tst_QNoDebug::noDebugOutput() const void tst_QNoDebug::streaming() const { QDateTime dt(QDate(1,2,3),QTime(4,5,6)); - const QByteArray debugString = dt.toString(QStringViewLiteral("yyyy-MM-dd HH:mm:ss.zzz t")).toLatin1(); + const QByteArray debugString = dt.toString(u"yyyy-MM-dd HH:mm:ss.zzz t").toLatin1(); const QByteArray message = "QDateTime(" + debugString + " Qt::LocalTime)"; QTest::ignoreMessage(QtWarningMsg, message.constData()); qWarning() << dt; diff --git a/tests/auto/corelib/io/qprocess/BLACKLIST b/tests/auto/corelib/io/qprocess/BLACKLIST index b355bb0f75e..aa9fdab64d3 100644 --- a/tests/auto/corelib/io/qprocess/BLACKLIST +++ b/tests/auto/corelib/io/qprocess/BLACKLIST @@ -2,8 +2,6 @@ redhatenterpriselinuxworkstation-6.6 # QTBUG-48455 [fileWriterProcess] -msvc-2015 ci -msvc-2017 ci -[softExitInSlots] -# QTBUG-66903 -windows +windows-10 msvc-2015 +windows-10 msvc-2017 + diff --git a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp index df1dbebbf24..44c8c4b681d 100644 --- a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp +++ b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2018 Intel Corporation. +** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2019 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -563,15 +563,15 @@ void tst_QResourceEngine::setLocale() // default constructed QResource gets the default locale QResource resource; resource.setFileName("aliasdir/aliasdir.txt"); - QVERIFY(!resource.isCompressed()); + QCOMPARE(resource.compressionAlgorithm(), QResource::NoCompression); // change the default locale and make sure it doesn't affect the resource QLocale::setDefault(QLocale("de_CH")); - QVERIFY(!resource.isCompressed()); + QCOMPARE(resource.compressionAlgorithm(), QResource::NoCompression); // then explicitly set the locale on qresource resource.setLocale(QLocale("de_CH")); - QVERIFY(resource.isCompressed()); + QVERIFY(resource.compressionAlgorithm() != QResource::NoCompression); // the reset the default locale back QLocale::setDefault(QLocale::system()); diff --git a/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp b/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp index 96970421d3e..f1327933c42 100644 --- a/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp +++ b/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp @@ -72,6 +72,7 @@ public slots: private slots: void transactionalWrite(); + void retryTransactionalWrite(); void textStreamManualFlush(); void textStreamAutoFlush(); void saveTwice(); @@ -129,6 +130,39 @@ void tst_QSaveFile::transactionalWrite() QCOMPARE(QFile::permissions(targetFile), QFile::permissions(otherFile)); } +// QTBUG-77007: Simulate the case of an application with a loop prompting +// to retry saving on failure. Create a read-only file first (Unix only) +void tst_QSaveFile::retryTransactionalWrite() +{ +#ifndef Q_OS_UNIX + QSKIP("This test is Unix only"); +#endif + QTemporaryDir dir; + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); + + QString targetFile = dir.path() + QLatin1String("/outfile"); + const QString readOnlyName = targetFile + QLatin1String(".ro"); + { + QFile readOnlyFile(readOnlyName); + QVERIFY2(readOnlyFile.open(QIODevice::WriteOnly), msgCannotOpen(readOnlyFile).constData()); + readOnlyFile.write("Hello"); + readOnlyFile.close(); + auto permissions = readOnlyFile.permissions(); + permissions &= ~(QFileDevice::WriteOwner | QFileDevice::WriteGroup | QFileDevice::WriteUser); + QVERIFY(readOnlyFile.setPermissions(permissions)); + } + + QSaveFile file(readOnlyName); + QVERIFY(!file.open(QIODevice::WriteOnly)); + + file.setFileName(targetFile); + QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData()); + QVERIFY(file.isOpen()); + QCOMPARE(file.write("Hello"), Q_INT64_C(5)); + QCOMPARE(file.error(), QFile::NoError); + QVERIFY(file.commit()); +} + void tst_QSaveFile::saveTwice() { // Check that we can reuse a QSaveFile object diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index a71a68e4576..289590a2338 100644 --- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp +++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp @@ -1366,7 +1366,9 @@ void tst_QSettings::testVariantTypes() if (format >= QSettings::InvalidFormat) { testVal("keysequence", QKeySequence(Qt::ControlModifier + Qt::Key_F1), QKeySequence, KeySequence); } else { - testVal("keysequence", QKeySequence(Qt::ControlModifier + Qt::Key_F1), QString, String); + testVal("keysequence", + QKeySequence(Qt::ControlModifier + Qt::Key_F1).toString(QKeySequence::NativeText), + QString, String); } #undef testVal diff --git a/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST b/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST index 4dd71ca9f43..4c9fe53c14e 100644 --- a/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST +++ b/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST @@ -1,4 +1,4 @@ [elapsed] -windows -osx-10.12 +windows-10 msvc-2015 osx-10.13 +windows-10 msvc-2017 diff --git a/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST b/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST deleted file mode 100644 index 06588188d4b..00000000000 --- a/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST +++ /dev/null @@ -1,6 +0,0 @@ -[sendPostedEvents] -windows -[registerTimer] -windows -winrt -osx diff --git a/tests/auto/corelib/kernel/qeventloop/BLACKLIST b/tests/auto/corelib/kernel/qeventloop/BLACKLIST deleted file mode 100644 index 6ea6314b0a5..00000000000 --- a/tests/auto/corelib/kernel/qeventloop/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[testQuitLock] -windows diff --git a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp index 56623773a26..9fe7d637270 100644 --- a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp +++ b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp @@ -1322,8 +1322,8 @@ bool tst_QMetaObjectBuilder::sameMetaObject return false; } - const QMetaObject * const *objects1 = meta1->d.relatedMetaObjects; - const QMetaObject * const *objects2 = meta2->d.relatedMetaObjects; + const auto *objects1 = meta1->d.relatedMetaObjects; + const auto *objects2 = meta2->d.relatedMetaObjects; if (objects1 && !objects2) return false; if (objects2 && !objects1) @@ -1391,7 +1391,7 @@ private: }; QMetaObject TestObject::staticMetaObject = { - { 0, 0, 0, 0, 0, 0 } + { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr } }; TestObject::TestObject(QObject *parent) diff --git a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro index 56b8c071c34..4856b138c3c 100644 --- a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro +++ b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro @@ -5,6 +5,7 @@ INCLUDEPATH += $$PWD/../../../other/qvariant_common SOURCES = tst_qmetatype.cpp TESTDATA=./typeFlags.bin DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +DEFINES -= QT_NO_LINKED_LIST msvc|winrt { # Prevents "fatal error C1128: number of sections exceeded object file format limit". diff --git a/tests/auto/corelib/kernel/qobject/BLACKLIST b/tests/auto/corelib/kernel/qobject/BLACKLIST deleted file mode 100644 index 0887a73b4c9..00000000000 --- a/tests/auto/corelib/kernel/qobject/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[moveToThread] -windows diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 1778bf24bcf..a805bfb7473 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -1401,6 +1401,7 @@ struct CustomType CustomType(const CustomType &other): i1(other.i1), i2(other.i2), i3(other.i3) { ++instanceCount; playWithObjects(); } ~CustomType() { --instanceCount; playWithObjects(); } + CustomType &operator=(const CustomType &) = default; int i1, i2, i3; int value() { return i1 + i2 + i3; } diff --git a/tests/auto/corelib/kernel/qsocketnotifier/BLACKLIST b/tests/auto/corelib/kernel/qsocketnotifier/BLACKLIST index e68bf84268a..f3b7fc97b1e 100644 --- a/tests/auto/corelib/kernel/qsocketnotifier/BLACKLIST +++ b/tests/auto/corelib/kernel/qsocketnotifier/BLACKLIST @@ -1,3 +1,4 @@ [unexpectedDisconnection] -windows -osx +osx-10.12 +windows-10 msvc-2015 +windows-7sp1 diff --git a/tests/auto/corelib/kernel/qtimer/BLACKLIST b/tests/auto/corelib/kernel/qtimer/BLACKLIST index 16cbab45871..dc8b8987e5a 100644 --- a/tests/auto/corelib/kernel/qtimer/BLACKLIST +++ b/tests/auto/corelib/kernel/qtimer/BLACKLIST @@ -1,5 +1,9 @@ [remainingTime] -windows -osx +osx-10.12 +osx-10.14 +osx-10.13 +windows-10 msvc-2017 [basic_chrono] -osx +osx-10.14 +osx-10.13 + diff --git a/tests/auto/corelib/kernel/qvariant/CMakeLists.txt b/tests/auto/corelib/kernel/qvariant/CMakeLists.txt index b611bece638..dbf9e0b119b 100644 --- a/tests/auto/corelib/kernel/qvariant/CMakeLists.txt +++ b/tests/auto/corelib/kernel/qvariant/CMakeLists.txt @@ -9,6 +9,7 @@ add_qt_test(tst_qvariant SOURCES tst_qvariant.cpp DEFINES + # -QT_NO_LINKED_LIST # special case remove until we fix this QT_DISABLE_DEPRECATED_BEFORE=0 INCLUDE_DIRECTORIES ../../../other/qvariant_common @@ -17,23 +18,18 @@ add_qt_test(tst_qvariant ) # Resources: +set(qvariant_resource_files + "stream/qt4.9/" + "stream/qt5.0/" +) + add_qt_resource(tst_qvariant "qvariant" PREFIX "/" FILES - stream/qt4.9/ - stream/qt5.0/ + ${qvariant_resource_files} ) -#### Keys ignored in scope 1:.:.:qvariant.pro:: -# CONFIG = "testcase" - ## Scopes: ##################################################################### - -#### Keys ignored in scope 2:.:.:qvariant.pro:qtConfig(c++14): -# CONFIG = "c++14" - -#### Keys ignored in scope 3:.:.:qvariant.pro:qtConfig(c++1z): -# CONFIG = "c++1z" diff --git a/tests/auto/corelib/kernel/qvariant/qvariant.pro b/tests/auto/corelib/kernel/qvariant/qvariant.pro index a620be00919..0b5280df86f 100644 --- a/tests/auto/corelib/kernel/qvariant/qvariant.pro +++ b/tests/auto/corelib/kernel/qvariant/qvariant.pro @@ -5,6 +5,7 @@ INCLUDEPATH += $$PWD/../../../other/qvariant_common SOURCES = tst_qvariant.cpp RESOURCES += qvariant.qrc DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +DEFINES -= QT_NO_LINKED_LIST qtConfig(c++14): CONFIG += c++14 qtConfig(c++1z): CONFIG += c++1z !qtConfig(doubleconversion):!qtConfig(system-doubleconversion) { diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 5d06f6e8c8f..074cb070925 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -379,11 +379,13 @@ void tst_QVariant::isNull() QString str1; QVariant var1( str1 ); QVERIFY( var1.isNull() ); +#if QT_DEPRECATED_SINCE(5, 9) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED QVariant var2( QString::null ); QT_WARNING_POP QVERIFY( var2.isNull() ); +#endif QVariant var3( QString( "blah" ) ); QVERIFY( !var3.isNull() ); diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp index 1cbe0cae480..57aa67c1428 100644 --- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp +++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp @@ -436,6 +436,8 @@ void tst_QtJson::testObjectSimple() object.insert("boolean", true); QCOMPARE(object.value("boolean").toBool(), true); QCOMPARE(object.value(QLatin1String("boolean")).toBool(), true); + QJsonObject object2 = object; + QJsonObject object3 = object; QStringList keys = object.keys(); QVERIFY2(keys.contains("number"), "key number not found"); @@ -461,6 +463,40 @@ void tst_QtJson::testObjectSimple() object.insert("string", QString::fromLatin1("foo")); QVERIFY2(object.value(QLatin1String("string")).toString() != before, "value should have been updated"); + // same tests again but with QStringView keys + object2.insert(QStringView(u"value"), value); + QCOMPARE(object2.value("value"), value); + + size = object2.size(); + object2.remove(QStringView(u"boolean")); + QCOMPARE(object2.size(), size - 1); + QVERIFY2(!object2.contains(QStringView(u"boolean")), "key boolean should have been removed"); + + taken = object2.take(QStringView(u"value")); + QCOMPARE(taken, value); + QVERIFY2(!object2.contains("value"), "key value should have been removed"); + + before = object2.value("string").toString(); + object2.insert(QStringView(u"string"), QString::fromLatin1("foo")); + QVERIFY2(object2.value(QStringView(u"string")).toString() != before, "value should have been updated"); + + // same tests again but with QLatin1String keys + object3.insert(QLatin1String("value"), value); + QCOMPARE(object3.value("value"), value); + + size = object3.size(); + object3.remove(QLatin1String("boolean")); + QCOMPARE(object3.size(), size - 1); + QVERIFY2(!object3.contains("boolean"), "key boolean should have been removed"); + + taken = object3.take(QLatin1String("value")); + QCOMPARE(taken, value); + QVERIFY2(!object3.contains("value"), "key value should have been removed"); + + before = object3.value("string").toString(); + object3.insert(QLatin1String("string"), QString::fromLatin1("foo")); + QVERIFY2(object3.value(QLatin1String("string")).toString() != before, "value should have been updated"); + size = object.size(); QJsonObject subobject; subobject.insert("number", 42); @@ -1096,6 +1132,8 @@ void tst_QtJson::undefinedValues() QJsonObject object; object.insert("Key", QJsonValue(QJsonValue::Undefined)); QCOMPARE(object.size(), 0); + object["Key"] = QJsonValue(QJsonValue::Undefined); + QCOMPARE(object.size(), 0); object.insert("Key", QLatin1String("Value")); QCOMPARE(object.size(), 1); @@ -2698,6 +2736,8 @@ void tst_QtJson::longStrings() // test around 15 and 16 bit boundaries, as these are limits // in the data structures (for Latin1String in qjson_p.h) QString s(0x7ff0, 'a'); + QByteArray ba(0x7ff0, 'a'); + ba.append(0x8010 - 0x7ff0, 'c'); for (int i = 0x7ff0; i < 0x8010; i++) { s.append(QLatin1Char('c')); @@ -2714,9 +2754,21 @@ void tst_QtJson::longStrings() /* ... and a QByteArray from the QJsonDocument */ QByteArray a2 = d2.toJson(); QCOMPARE(a1, a2); + + // Test long keys + QJsonObject o1, o2; + o1[s] = 42; + o2[QLatin1String(ba.data(), i + 1)] = 42; + d1.setObject(o1); + d2.setObject(o2); + a1 = d1.toJson(); + a2 = d2.toJson(); + QCOMPARE(a1, a2); } s = QString(0xfff0, 'a'); + ba = QByteArray(0xfff0, 'a'); + ba.append(0x10010 - 0xfff0, 'c'); for (int i = 0xfff0; i < 0x10010; i++) { s.append(QLatin1Char('c')); @@ -2733,6 +2785,16 @@ void tst_QtJson::longStrings() /* ... and a QByteArray from the QJsonDocument */ QByteArray a2 = d2.toJson(); QCOMPARE(a1, a2); + + // Test long keys + QJsonObject o1, o2; + o1[s] = 42; + o2[QLatin1String(ba.data(), i + 1)] = 42; + d1.setObject(o1); + d2.setObject(o2); + a1 = d1.toJson(); + a2 = d2.toJson(); + QCOMPARE(a1, a2); } } diff --git a/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp b/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp index 3dd4b5114c5..28d29168fb6 100644 --- a/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp +++ b/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp @@ -80,6 +80,11 @@ private Q_SLOTS: void addData_singleElement(); void addData_complex_data() { arrays_data(); } void addData_complex(); + + void duplicatedData_data() { arrays_data(); } + void duplicatedData(); + void extraData_data() { arrays_data(); } + void extraData(); }; #define FOR_CBOR_TYPE(F) \ @@ -480,6 +485,28 @@ static QString parseOne(QCborStreamReader &reader) return result; } +static QString parse(QCborStreamReader &reader, const QByteArray &data) +{ + qint64 oldPos = 0; + if (QIODevice *dev = reader.device()) + oldPos = dev->pos(); + + QString r = parseOne(reader); + if (r.isEmpty()) + return r; + + if (reader.currentOffset() - oldPos != data.size()) + r = QString("Number of parsed bytes (%1) not expected (%2)") + .arg(reader.currentOffset()).arg(data.size()); + if (QIODevice *dev = reader.device()) { + if (dev->pos() - oldPos != data.size()) + r = QString("QIODevice not advanced (%1) as expected (%2)") + .arg(dev->pos()).arg(data.size()); + } + + return r; +} + bool parseNonRecursive(QString &result, bool &printingStringChunks, QCborStreamReader &reader) { while (reader.lastError() == QCborError::NoError) { @@ -612,13 +639,13 @@ void tst_QCborStreamReader::fixed() } QVERIFY(reader.isValid()); QCOMPARE(reader.lastError(), QCborError::NoError); - QCOMPARE(parseOne(reader), expected); + QCOMPARE(parse(reader, data), expected); // verify that we can re-read reader.reset(); QVERIFY(reader.isValid()); QCOMPARE(reader.lastError(), QCborError::NoError); - QCOMPARE(parseOne(reader), expected); + QCOMPARE(parse(reader, data), expected); } void tst_QCborStreamReader::strings_data() @@ -721,7 +748,7 @@ void tst_QCborStreamReader::emptyContainers() QCOMPARE(reader.lastError(), QCborError::NoError); if (reader.isLengthKnown()) QCOMPARE(reader.length(), 0U); - QCOMPARE(parseOne(reader), expected); + QCOMPARE(parse(reader, data), expected); // verify that we can re-read reader.reset(); @@ -729,7 +756,7 @@ void tst_QCborStreamReader::emptyContainers() QCOMPARE(reader.lastError(), QCborError::NoError); if (reader.isLengthKnown()) QCOMPARE(reader.length(), 0U); - QCOMPARE(parseOne(reader), expected); + QCOMPARE(parse(reader, data), expected); } void tst_QCborStreamReader::arrays_data() @@ -758,7 +785,7 @@ static void checkContainer(int len, const QByteArray &data, const QString &expec QVERIFY(reader.isLengthKnown()); QCOMPARE(reader.length(), uint(len)); } - QCOMPARE(parseOne(reader), expected); + QCOMPARE(parse(reader, data), expected); // verify that we can re-read reader.reset(); @@ -768,7 +795,7 @@ static void checkContainer(int len, const QByteArray &data, const QString &expec QVERIFY(reader.isLengthKnown()); QCOMPARE(reader.length(), uint(len)); } - QCOMPARE(parseOne(reader), expected); + QCOMPARE(parse(reader, data), expected); } void tst_QCborStreamReader::arrays() @@ -892,7 +919,7 @@ void tst_QCborStreamReader::validation() buffer.open(QIODevice::ReadOnly); reader.setDevice(&buffer); } - parseOne(reader); + parse(reader, data); QVERIFY(reader.lastError() != QCborError::NoError); // next() should fail @@ -997,7 +1024,7 @@ void tst_QCborStreamReader::addData_singleElement() reader.addData(data.constData() + i, 1); } - parseOne(reader); + parse(reader, data); QCOMPARE(reader.lastError(), QCborError::EndOfFile); } @@ -1009,7 +1036,7 @@ void tst_QCborStreamReader::addData_singleElement() reader.addData(data.right(1)); } QCOMPARE(reader.lastError(), QCborError::NoError); - QCOMPARE(parseOne(reader), expected); + QCOMPARE(parse(reader, data), expected); } void tst_QCborStreamReader::addData_complex() @@ -1085,6 +1112,69 @@ void tst_QCborStreamReader::addData_complex() "{1, [" + expected + ", " + expected + "]}"); } +void tst_QCborStreamReader::duplicatedData() +{ + QFETCH_GLOBAL(bool, useDevice); + QFETCH(QByteArray, data); + QFETCH(QString, expected); + removeIndicators(expected); + + // double the data up + QByteArray doubledata = data + data; + + QBuffer buffer(&doubledata); + QCborStreamReader reader(doubledata); + if (useDevice) { + buffer.open(QIODevice::ReadOnly); + reader.setDevice(&buffer); + } + QVERIFY(reader.isValid()); + QCOMPARE(reader.lastError(), QCborError::NoError); + QCOMPARE(parse(reader, data), expected); // yes, data + + QVERIFY(reader.currentOffset() < doubledata.size()); + if (useDevice) { + reader.setDevice(&buffer); + QVERIFY(reader.isValid()); + QCOMPARE(reader.lastError(), QCborError::NoError); + QCOMPARE(parse(reader, data), expected); + QCOMPARE(buffer.pos(), doubledata.size()); + } else { + // there's no reader.setData() + } +} + +void tst_QCborStreamReader::extraData() +{ + QFETCH_GLOBAL(bool, useDevice); + QFETCH(QByteArray, data); + QFETCH(QString, expected); + removeIndicators(expected); + + QByteArray extension(9, '\0'); + + // stress test everything with extra bytes (just one byte changing; + // TinyCBOR used to have a bug where the next byte got sometimes read) + for (int c = '\0'; c < 0x100; ++c) { + extension[0] = c; + QByteArray extendeddata = data + extension; + + QBuffer buffer(&extendeddata); + QCborStreamReader reader(extendeddata); + if (useDevice) { + buffer.open(QIODevice::ReadOnly); + reader.setDevice(&buffer); + } + QVERIFY(reader.isValid()); + QCOMPARE(reader.lastError(), QCborError::NoError); + QCOMPARE(parse(reader, data), expected); // yes, data + + // if we were a parser, we could parse the next payload + if (useDevice) + QCOMPARE(buffer.readAll(), extension); + } +} + QTEST_MAIN(tst_QCborStreamReader) diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index f69ce4120d4..6fa82ea6817 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -91,8 +91,14 @@ private slots: void toCbor_data(); void toCbor(); + void toCborStreamWriter_data() { toCbor_data(); } + void toCborStreamWriter(); void fromCbor_data(); void fromCbor(); + void fromCborStreamReaderByteArray_data() { fromCbor_data(); } + void fromCborStreamReaderByteArray(); + void fromCborStreamReaderIODevice_data() { fromCbor_data(); } + void fromCborStreamReaderIODevice(); void validation_data(); void validation(); void toDiagnosticNotation_data(); @@ -1454,6 +1460,22 @@ void tst_QCborValue::toCbor() "\xa1\x01\xd9\xd9\xf7" + result); } +void tst_QCborValue::toCborStreamWriter() +{ + QFETCH(QCborValue, v); + QFETCH(QByteArray, result); + QFETCH(QCborValue::EncodingOptions, options); + + QByteArray output; + QBuffer buffer(&output); + buffer.open(QIODevice::WriteOnly); + QCborStreamWriter writer(&buffer); + + v.toCbor(writer, options); + QCOMPARE(buffer.pos(), result.size()); + QCOMPARE(output, result); +} + void tst_QCborValue::fromCbor_data() { addCommonCborData(); @@ -1484,20 +1506,11 @@ void tst_QCborValue::fromCbor_data() << raw("\xd8\x25\x51" "\1\2\3\4""\4\3\2\0""\0\0\0\0""\0\0\0\1""\2"); } -void tst_QCborValue::fromCbor() +void fromCbor_common(void (*doCheck)(const QCborValue &, const QByteArray &)) { QFETCH(QCborValue, v); QFETCH(QByteArray, result); - auto doCheck = [](const QCborValue &v, const QByteArray &result) { - QCborParserError error; - QCborValue decoded = QCborValue::fromCbor(result, &error); - QVERIFY2(error.error == QCborError(), qPrintable(error.errorString())); - QCOMPARE(error.offset, result.size()); - QVERIFY(decoded == v); - QVERIFY(v == decoded); - }; - doCheck(v, result); if (QTest::currentTestFailed()) return; @@ -1548,6 +1561,52 @@ void tst_QCborValue::fromCbor() return; } +void tst_QCborValue::fromCbor() +{ + auto doCheck = [](const QCborValue &v, const QByteArray &result) { + QCborParserError error; + QCborValue decoded = QCborValue::fromCbor(result, &error); + QVERIFY2(error.error == QCborError(), qPrintable(error.errorString())); + QCOMPARE(error.offset, result.size()); + QVERIFY(decoded == v); + QVERIFY(v == decoded); + }; + + fromCbor_common(doCheck); +} + +void tst_QCborValue::fromCborStreamReaderByteArray() +{ + auto doCheck = [](const QCborValue &expected, const QByteArray &data) { + QCborStreamReader reader(data); + QCborValue decoded = QCborValue::fromCbor(reader); + QCOMPARE(reader.lastError(), QCborError()); + QCOMPARE(reader.currentOffset(), data.size()); + QVERIFY(decoded == expected); + QVERIFY(expected == decoded); + }; + + fromCbor_common(doCheck); +} + +void tst_QCborValue::fromCborStreamReaderIODevice() +{ + auto doCheck = [](const QCborValue &expected, const QByteArray &data) { + QBuffer buffer; + buffer.setData(data); + buffer.open(QIODevice::ReadOnly); + QCborStreamReader reader(&buffer); + QCborValue decoded = QCborValue::fromCbor(reader); + QCOMPARE(reader.lastError(), QCborError()); + QCOMPARE(reader.currentOffset(), data.size()); + QVERIFY(decoded == expected); + QVERIFY(expected == decoded); + QCOMPARE(buffer.pos(), reader.currentOffset()); + }; + + fromCbor_common(doCheck); +} + void tst_QCborValue::validation_data() { addValidationColumns(); diff --git a/tests/auto/corelib/serialization/qdatastream/qdatastream.pro b/tests/auto/corelib/serialization/qdatastream/qdatastream.pro index 25f8b889a0a..469d689f3fb 100644 --- a/tests/auto/corelib/serialization/qdatastream/qdatastream.pro +++ b/tests/auto/corelib/serialization/qdatastream/qdatastream.pro @@ -3,6 +3,8 @@ TARGET = tst_qdatastream QT += testlib SOURCES = tst_qdatastream.cpp +DEFINES -= QT_NO_LINKED_LIST + TESTDATA += datastream.q42 android:!android-embedded { diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp index b8778e4e985..8197c386c5c 100644 --- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp +++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp @@ -2391,10 +2391,10 @@ void tst_QDataStream::setVersion() if (vers == 1) { for (int grp = 0; grp < (int)QPalette::NColorGroups; ++grp) { - QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::Foreground) - == inPal1.color((QPalette::ColorGroup)grp, QPalette::Foreground)); - QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::Background) - == inPal1.color((QPalette::ColorGroup)grp, QPalette::Background)); + QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::WindowText) + == inPal1.color((QPalette::ColorGroup)grp, QPalette::WindowText)); + QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::Window) + == inPal1.color((QPalette::ColorGroup)grp, QPalette::Window)); QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::Light) == inPal1.color((QPalette::ColorGroup)grp, QPalette::Light)); QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::Dark) diff --git a/tests/auto/corelib/serialization/qtextstream/BLACKLIST b/tests/auto/corelib/serialization/qtextstream/BLACKLIST index b54b53cd740..b8c1b742f45 100644 --- a/tests/auto/corelib/serialization/qtextstream/BLACKLIST +++ b/tests/auto/corelib/serialization/qtextstream/BLACKLIST @@ -1,3 +1,4 @@ [stillOpenWhenAtEnd] -windows +windows-10 msvc-2017 winrt +windows-7sp1 diff --git a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp index 32306e80035..6381ce5ed0b 100644 --- a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp +++ b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp @@ -2586,7 +2586,7 @@ void tst_QTextStream::stringview_write_operator_ToDevice() QBuffer buf; buf.open(QBuffer::WriteOnly); QTextStream stream(&buf); - const QStringView expected = QStringViewLiteral("expectedStringView"); + const QStringView expected = u"expectedStringView"; stream << expected; stream.flush(); QCOMPARE(buf.buffer().constData(), "expectedStringView"); diff --git a/tests/auto/corelib/text/CMakeLists.txt b/tests/auto/corelib/text/CMakeLists.txt new file mode 100644 index 00000000000..dd51385aa6a --- /dev/null +++ b/tests/auto/corelib/text/CMakeLists.txt @@ -0,0 +1,22 @@ +# Generated from text.pro. + +# add_subdirectory(qbytearray) # special case not ported +add_subdirectory(qbytearraylist) +# add_subdirectory(qbytearraymatcher) # special case not ported +add_subdirectory(qbytedatabuffer) +# add_subdirectory(qchar) # special case not ported +# add_subdirectory(qcollator) # special case not ported +# add_subdirectory(qlatin1string) # special case not ported +# add_subdirectory(qlocale) # special case not ported +add_subdirectory(qregexp) +add_subdirectory(qregularexpression) +# add_subdirectory(qstring) # special case not ported +add_subdirectory(qstring_no_cast_from_bytearray) +# add_subdirectory(qstringapisymmetry) # special case not ported +# add_subdirectory(qstringbuilder) # special case not ported +add_subdirectory(qstringiterator) +add_subdirectory(qstringlist) +add_subdirectory(qstringmatcher) +add_subdirectory(qstringref) +# add_subdirectory(qstringview) # special case not ported +# add_subdirectory(qtextboundaryfinder) # special case not ported diff --git a/tests/auto/corelib/tools/qbytearray/.gitattributes b/tests/auto/corelib/text/qbytearray/.gitattributes similarity index 100% rename from tests/auto/corelib/tools/qbytearray/.gitattributes rename to tests/auto/corelib/text/qbytearray/.gitattributes diff --git a/tests/auto/corelib/tools/qbytearray/.gitignore b/tests/auto/corelib/text/qbytearray/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qbytearray/.gitignore rename to tests/auto/corelib/text/qbytearray/.gitignore diff --git a/tests/auto/corelib/tools/qbytearray/android_testdata.qrc b/tests/auto/corelib/text/qbytearray/android_testdata.qrc similarity index 100% rename from tests/auto/corelib/tools/qbytearray/android_testdata.qrc rename to tests/auto/corelib/text/qbytearray/android_testdata.qrc diff --git a/tests/auto/corelib/tools/qbytearray/qbytearray.pro b/tests/auto/corelib/text/qbytearray/qbytearray.pro similarity index 100% rename from tests/auto/corelib/tools/qbytearray/qbytearray.pro rename to tests/auto/corelib/text/qbytearray/qbytearray.pro diff --git a/tests/auto/corelib/tools/qbytearray/rfc3252.txt b/tests/auto/corelib/text/qbytearray/rfc3252.txt similarity index 100% rename from tests/auto/corelib/tools/qbytearray/rfc3252.txt rename to tests/auto/corelib/text/qbytearray/rfc3252.txt diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp similarity index 100% rename from tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp rename to tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray_mac.mm b/tests/auto/corelib/text/qbytearray/tst_qbytearray_mac.mm similarity index 100% rename from tests/auto/corelib/tools/qbytearray/tst_qbytearray_mac.mm rename to tests/auto/corelib/text/qbytearray/tst_qbytearray_mac.mm diff --git a/tests/auto/corelib/text/qbytearraylist/CMakeLists.txt b/tests/auto/corelib/text/qbytearraylist/CMakeLists.txt new file mode 100644 index 00000000000..99ce43d0a7b --- /dev/null +++ b/tests/auto/corelib/text/qbytearraylist/CMakeLists.txt @@ -0,0 +1,11 @@ +# Generated from qbytearraylist.pro. + +##################################################################### +## tst_qbytearraylist Test: +##################################################################### + +add_qt_test(tst_qbytearraylist + GUI + SOURCES + tst_qbytearraylist.cpp +) diff --git a/tests/auto/corelib/tools/qbytearraylist/qbytearraylist.pro b/tests/auto/corelib/text/qbytearraylist/qbytearraylist.pro similarity index 100% rename from tests/auto/corelib/tools/qbytearraylist/qbytearraylist.pro rename to tests/auto/corelib/text/qbytearraylist/qbytearraylist.pro diff --git a/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp b/tests/auto/corelib/text/qbytearraylist/tst_qbytearraylist.cpp similarity index 100% rename from tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp rename to tests/auto/corelib/text/qbytearraylist/tst_qbytearraylist.cpp diff --git a/tests/auto/corelib/tools/qbytearraymatcher/qbytearraymatcher.pro b/tests/auto/corelib/text/qbytearraymatcher/qbytearraymatcher.pro similarity index 100% rename from tests/auto/corelib/tools/qbytearraymatcher/qbytearraymatcher.pro rename to tests/auto/corelib/text/qbytearraymatcher/qbytearraymatcher.pro diff --git a/tests/auto/corelib/tools/qbytearraymatcher/tst_qbytearraymatcher.cpp b/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp similarity index 100% rename from tests/auto/corelib/tools/qbytearraymatcher/tst_qbytearraymatcher.cpp rename to tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp diff --git a/tests/auto/corelib/tools/qbytedatabuffer/.gitignore b/tests/auto/corelib/text/qbytedatabuffer/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qbytedatabuffer/.gitignore rename to tests/auto/corelib/text/qbytedatabuffer/.gitignore diff --git a/tests/auto/corelib/tools/qbytedatabuffer/CMakeLists.txt b/tests/auto/corelib/text/qbytedatabuffer/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qbytedatabuffer/CMakeLists.txt rename to tests/auto/corelib/text/qbytedatabuffer/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qbytedatabuffer/qbytedatabuffer.pro b/tests/auto/corelib/text/qbytedatabuffer/qbytedatabuffer.pro similarity index 100% rename from tests/auto/corelib/tools/qbytedatabuffer/qbytedatabuffer.pro rename to tests/auto/corelib/text/qbytedatabuffer/qbytedatabuffer.pro diff --git a/tests/auto/corelib/tools/qbytedatabuffer/tst_qbytedatabuffer.cpp b/tests/auto/corelib/text/qbytedatabuffer/tst_qbytedatabuffer.cpp similarity index 100% rename from tests/auto/corelib/tools/qbytedatabuffer/tst_qbytedatabuffer.cpp rename to tests/auto/corelib/text/qbytedatabuffer/tst_qbytedatabuffer.cpp diff --git a/tests/auto/corelib/tools/qchar/.gitignore b/tests/auto/corelib/text/qchar/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qchar/.gitignore rename to tests/auto/corelib/text/qchar/.gitignore diff --git a/tests/auto/corelib/tools/qchar/data/NormalizationTest.txt b/tests/auto/corelib/text/qchar/data/NormalizationTest.txt similarity index 100% rename from tests/auto/corelib/tools/qchar/data/NormalizationTest.txt rename to tests/auto/corelib/text/qchar/data/NormalizationTest.txt diff --git a/tests/auto/corelib/tools/qchar/qchar.pro b/tests/auto/corelib/text/qchar/qchar.pro similarity index 100% rename from tests/auto/corelib/tools/qchar/qchar.pro rename to tests/auto/corelib/text/qchar/qchar.pro diff --git a/tests/auto/corelib/tools/qchar/testdata.qrc b/tests/auto/corelib/text/qchar/testdata.qrc similarity index 100% rename from tests/auto/corelib/tools/qchar/testdata.qrc rename to tests/auto/corelib/text/qchar/testdata.qrc diff --git a/tests/auto/corelib/tools/qchar/tst_qchar.cpp b/tests/auto/corelib/text/qchar/tst_qchar.cpp similarity index 100% rename from tests/auto/corelib/tools/qchar/tst_qchar.cpp rename to tests/auto/corelib/text/qchar/tst_qchar.cpp diff --git a/tests/auto/corelib/tools/qcollator/qcollator.pro b/tests/auto/corelib/text/qcollator/qcollator.pro similarity index 100% rename from tests/auto/corelib/tools/qcollator/qcollator.pro rename to tests/auto/corelib/text/qcollator/qcollator.pro diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/text/qcollator/tst_qcollator.cpp similarity index 100% rename from tests/auto/corelib/tools/qcollator/tst_qcollator.cpp rename to tests/auto/corelib/text/qcollator/tst_qcollator.cpp diff --git a/tests/auto/corelib/tools/qlatin1string/.gitignore b/tests/auto/corelib/text/qlatin1string/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qlatin1string/.gitignore rename to tests/auto/corelib/text/qlatin1string/.gitignore diff --git a/tests/auto/corelib/tools/qlatin1string/qlatin1string.pro b/tests/auto/corelib/text/qlatin1string/qlatin1string.pro similarity index 100% rename from tests/auto/corelib/tools/qlatin1string/qlatin1string.pro rename to tests/auto/corelib/text/qlatin1string/qlatin1string.pro diff --git a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp b/tests/auto/corelib/text/qlatin1string/tst_qlatin1string.cpp similarity index 100% rename from tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp rename to tests/auto/corelib/text/qlatin1string/tst_qlatin1string.cpp diff --git a/tests/auto/corelib/tools/qlocale/.gitignore b/tests/auto/corelib/text/qlocale/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qlocale/.gitignore rename to tests/auto/corelib/text/qlocale/.gitignore diff --git a/tests/auto/corelib/tools/qlocale/qlocale.pro b/tests/auto/corelib/text/qlocale/qlocale.pro similarity index 100% rename from tests/auto/corelib/tools/qlocale/qlocale.pro rename to tests/auto/corelib/text/qlocale/qlocale.pro diff --git a/tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.cpp b/tests/auto/corelib/text/qlocale/syslocaleapp/syslocaleapp.cpp similarity index 100% rename from tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.cpp rename to tests/auto/corelib/text/qlocale/syslocaleapp/syslocaleapp.cpp diff --git a/tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.pro b/tests/auto/corelib/text/qlocale/syslocaleapp/syslocaleapp.pro similarity index 100% rename from tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.pro rename to tests/auto/corelib/text/qlocale/syslocaleapp/syslocaleapp.pro diff --git a/tests/auto/corelib/tools/qlocale/test/test.pro b/tests/auto/corelib/text/qlocale/test/test.pro similarity index 100% rename from tests/auto/corelib/tools/qlocale/test/test.pro rename to tests/auto/corelib/text/qlocale/test/test.pro diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp similarity index 99% rename from tests/auto/corelib/tools/qlocale/tst_qlocale.cpp rename to tests/auto/corelib/text/qlocale/tst_qlocale.cpp index ec8f2fc047a..676c66df3ec 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp @@ -1459,8 +1459,8 @@ void tst_QLocale::dayOfWeek() QCOMPARE(QLocale::c().toString(date, "ddd"), shortName); QCOMPARE(QLocale::c().toString(date, "dddd"), longName); - QCOMPARE(QLocale::c().toString(date, QStringViewLiteral("ddd")), shortName); - QCOMPARE(QLocale::c().toString(date, QStringViewLiteral("dddd")), longName); + QCOMPARE(QLocale::c().toString(date, u"ddd"), shortName); + QCOMPARE(QLocale::c().toString(date, u"dddd"), longName); } void tst_QLocale::formatDate_data() diff --git a/tests/auto/corelib/tools/qregexp/.gitignore b/tests/auto/corelib/text/qregexp/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qregexp/.gitignore rename to tests/auto/corelib/text/qregexp/.gitignore diff --git a/tests/auto/corelib/tools/qregexp/CMakeLists.txt b/tests/auto/corelib/text/qregexp/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qregexp/CMakeLists.txt rename to tests/auto/corelib/text/qregexp/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qregexp/qregexp.pro b/tests/auto/corelib/text/qregexp/qregexp.pro similarity index 100% rename from tests/auto/corelib/tools/qregexp/qregexp.pro rename to tests/auto/corelib/text/qregexp/qregexp.pro diff --git a/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp b/tests/auto/corelib/text/qregexp/tst_qregexp.cpp similarity index 100% rename from tests/auto/corelib/tools/qregexp/tst_qregexp.cpp rename to tests/auto/corelib/text/qregexp/tst_qregexp.cpp diff --git a/tests/auto/corelib/tools/qregularexpression/.gitignore b/tests/auto/corelib/text/qregularexpression/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qregularexpression/.gitignore rename to tests/auto/corelib/text/qregularexpression/.gitignore diff --git a/tests/auto/corelib/tools/qregularexpression/CMakeLists.txt b/tests/auto/corelib/text/qregularexpression/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qregularexpression/CMakeLists.txt rename to tests/auto/corelib/text/qregularexpression/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro b/tests/auto/corelib/text/qregularexpression/qregularexpression.pro similarity index 100% rename from tests/auto/corelib/tools/qregularexpression/qregularexpression.pro rename to tests/auto/corelib/text/qregularexpression/qregularexpression.pro diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp similarity index 100% rename from tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp rename to tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp diff --git a/tests/auto/corelib/tools/qstring/.gitignore b/tests/auto/corelib/text/qstring/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qstring/.gitignore rename to tests/auto/corelib/text/qstring/.gitignore diff --git a/tests/auto/corelib/tools/qstring/double_data.h b/tests/auto/corelib/text/qstring/double_data.h similarity index 100% rename from tests/auto/corelib/tools/qstring/double_data.h rename to tests/auto/corelib/text/qstring/double_data.h diff --git a/tests/auto/corelib/tools/qstring/qstring.pro b/tests/auto/corelib/text/qstring/qstring.pro similarity index 100% rename from tests/auto/corelib/tools/qstring/qstring.pro rename to tests/auto/corelib/text/qstring/qstring.pro diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp similarity index 99% rename from tests/auto/corelib/tools/qstring/tst_qstring.cpp rename to tests/auto/corelib/text/qstring/tst_qstring.cpp index e4aa00f500b..cce3e601cdf 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -4763,7 +4763,7 @@ void tst_QString::arg() QCOMPARE( s4.arg("foo"), QLatin1String("[foo]") ); QCOMPARE( s5.arg(QLatin1String("foo")), QLatin1String("[foo]") ); - QCOMPARE( s6.arg(QStringViewLiteral("foo")), QLatin1String("[foo]") ); + QCOMPARE( s6.arg(u"foo"), QLatin1String("[foo]") ); QCOMPARE( s7.arg("foo"), QLatin1String("[foo]") ); QCOMPARE( s8.arg("foo"), QLatin1String("[foo %1]") ); QCOMPARE( s8.arg("foo").arg("bar"), QLatin1String("[foo bar]") ); @@ -4825,10 +4825,10 @@ void tst_QString::arg() QCOMPARE( QString("%1").arg("hello", -10), QLatin1String("hello ") ); QCOMPARE( QString("%1").arg(QLatin1String("hello"), -5), QLatin1String("hello") ); - QCOMPARE( QString("%1").arg(QStringViewLiteral("hello"), -2), QLatin1String("hello") ); + QCOMPARE( QString("%1").arg(u"hello", -2), QLatin1String("hello") ); QCOMPARE( QString("%1").arg("hello", 0), QLatin1String("hello") ); QCOMPARE( QString("%1").arg(QLatin1String("hello"), 2), QLatin1String("hello") ); - QCOMPARE( QString("%1").arg(QStringViewLiteral("hello"), 5), QLatin1String("hello") ); + QCOMPARE( QString("%1").arg(u"hello", 5), QLatin1String("hello") ); QCOMPARE( QString("%1").arg("hello", 10), QLatin1String(" hello") ); QCOMPARE( QString("%1%1").arg("hello"), QLatin1String("hellohello") ); QCOMPARE( QString("%2%1").arg("hello"), QLatin1String("%2hello") ); diff --git a/tests/auto/corelib/tools/qstring/tst_qstring_mac.mm b/tests/auto/corelib/text/qstring/tst_qstring_mac.mm similarity index 100% rename from tests/auto/corelib/tools/qstring/tst_qstring_mac.mm rename to tests/auto/corelib/text/qstring/tst_qstring_mac.mm diff --git a/tests/auto/corelib/tools/qstring_no_cast_from_bytearray/CMakeLists.txt b/tests/auto/corelib/text/qstring_no_cast_from_bytearray/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qstring_no_cast_from_bytearray/CMakeLists.txt rename to tests/auto/corelib/text/qstring_no_cast_from_bytearray/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qstring_no_cast_from_bytearray/qstring_no_cast_from_bytearray.pro b/tests/auto/corelib/text/qstring_no_cast_from_bytearray/qstring_no_cast_from_bytearray.pro similarity index 100% rename from tests/auto/corelib/tools/qstring_no_cast_from_bytearray/qstring_no_cast_from_bytearray.pro rename to tests/auto/corelib/text/qstring_no_cast_from_bytearray/qstring_no_cast_from_bytearray.pro diff --git a/tests/auto/corelib/tools/qstring_no_cast_from_bytearray/tst_qstring_no_cast_from_bytearray.cpp b/tests/auto/corelib/text/qstring_no_cast_from_bytearray/tst_qstring_no_cast_from_bytearray.cpp similarity index 100% rename from tests/auto/corelib/tools/qstring_no_cast_from_bytearray/tst_qstring_no_cast_from_bytearray.cpp rename to tests/auto/corelib/text/qstring_no_cast_from_bytearray/tst_qstring_no_cast_from_bytearray.cpp diff --git a/tests/auto/corelib/tools/qstringapisymmetry/.gitignore b/tests/auto/corelib/text/qstringapisymmetry/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qstringapisymmetry/.gitignore rename to tests/auto/corelib/text/qstringapisymmetry/.gitignore diff --git a/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro b/tests/auto/corelib/text/qstringapisymmetry/qstringapisymmetry.pro similarity index 100% rename from tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro rename to tests/auto/corelib/text/qstringapisymmetry/qstringapisymmetry.pro diff --git a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp similarity index 100% rename from tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp rename to tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder.pro b/tests/auto/corelib/text/qstringbuilder/qstringbuilder.pro similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder.pro rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder.pro diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/CMakeLists.txt b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/CMakeLists.txt rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder1/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/qstringbuilder1.pro b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/qstringbuilder1.pro similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/qstringbuilder1.pro rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder1/qstringbuilder1.pro diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/tst_qstringbuilder1.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/tst_qstringbuilder1.cpp similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/tst_qstringbuilder1.cpp rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder1/tst_qstringbuilder1.cpp diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/CMakeLists.txt b/tests/auto/corelib/text/qstringbuilder/qstringbuilder2/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/CMakeLists.txt rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder2/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/qstringbuilder2.pro b/tests/auto/corelib/text/qstringbuilder/qstringbuilder2/qstringbuilder2.pro similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/qstringbuilder2.pro rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder2/qstringbuilder2.pro diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/tst_qstringbuilder2.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder2/tst_qstringbuilder2.cpp similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/tst_qstringbuilder2.cpp rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder2/tst_qstringbuilder2.cpp diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/CMakeLists.txt b/tests/auto/corelib/text/qstringbuilder/qstringbuilder3/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/CMakeLists.txt rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder3/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/qstringbuilder3.pro b/tests/auto/corelib/text/qstringbuilder/qstringbuilder3/qstringbuilder3.pro similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/qstringbuilder3.pro rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder3/qstringbuilder3.pro diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/tst_qstringbuilder3.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder3/tst_qstringbuilder3.cpp similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/tst_qstringbuilder3.cpp rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder3/tst_qstringbuilder3.cpp diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/CMakeLists.txt b/tests/auto/corelib/text/qstringbuilder/qstringbuilder4/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/CMakeLists.txt rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder4/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/qstringbuilder4.pro b/tests/auto/corelib/text/qstringbuilder/qstringbuilder4/qstringbuilder4.pro similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/qstringbuilder4.pro rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder4/qstringbuilder4.pro diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/tst_qstringbuilder4.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder4/tst_qstringbuilder4.cpp similarity index 100% rename from tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/tst_qstringbuilder4.cpp rename to tests/auto/corelib/text/qstringbuilder/qstringbuilder4/tst_qstringbuilder4.cpp diff --git a/tests/auto/corelib/tools/qstringiterator/CMakeLists.txt b/tests/auto/corelib/text/qstringiterator/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qstringiterator/CMakeLists.txt rename to tests/auto/corelib/text/qstringiterator/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qstringiterator/qstringiterator.pro b/tests/auto/corelib/text/qstringiterator/qstringiterator.pro similarity index 100% rename from tests/auto/corelib/tools/qstringiterator/qstringiterator.pro rename to tests/auto/corelib/text/qstringiterator/qstringiterator.pro diff --git a/tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp b/tests/auto/corelib/text/qstringiterator/tst_qstringiterator.cpp similarity index 100% rename from tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp rename to tests/auto/corelib/text/qstringiterator/tst_qstringiterator.cpp diff --git a/tests/auto/corelib/tools/qstringlist/.gitignore b/tests/auto/corelib/text/qstringlist/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qstringlist/.gitignore rename to tests/auto/corelib/text/qstringlist/.gitignore diff --git a/tests/auto/corelib/tools/qstringlist/CMakeLists.txt b/tests/auto/corelib/text/qstringlist/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qstringlist/CMakeLists.txt rename to tests/auto/corelib/text/qstringlist/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qstringlist/qstringlist.pro b/tests/auto/corelib/text/qstringlist/qstringlist.pro similarity index 100% rename from tests/auto/corelib/tools/qstringlist/qstringlist.pro rename to tests/auto/corelib/text/qstringlist/qstringlist.pro diff --git a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp b/tests/auto/corelib/text/qstringlist/tst_qstringlist.cpp similarity index 100% rename from tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp rename to tests/auto/corelib/text/qstringlist/tst_qstringlist.cpp diff --git a/tests/auto/corelib/tools/qstringmatcher/.gitignore b/tests/auto/corelib/text/qstringmatcher/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qstringmatcher/.gitignore rename to tests/auto/corelib/text/qstringmatcher/.gitignore diff --git a/tests/auto/corelib/tools/qstringmatcher/CMakeLists.txt b/tests/auto/corelib/text/qstringmatcher/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qstringmatcher/CMakeLists.txt rename to tests/auto/corelib/text/qstringmatcher/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qstringmatcher/qstringmatcher.pro b/tests/auto/corelib/text/qstringmatcher/qstringmatcher.pro similarity index 100% rename from tests/auto/corelib/tools/qstringmatcher/qstringmatcher.pro rename to tests/auto/corelib/text/qstringmatcher/qstringmatcher.pro diff --git a/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp b/tests/auto/corelib/text/qstringmatcher/tst_qstringmatcher.cpp similarity index 100% rename from tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp rename to tests/auto/corelib/text/qstringmatcher/tst_qstringmatcher.cpp diff --git a/tests/auto/corelib/tools/qstringref/CMakeLists.txt b/tests/auto/corelib/text/qstringref/CMakeLists.txt similarity index 100% rename from tests/auto/corelib/tools/qstringref/CMakeLists.txt rename to tests/auto/corelib/text/qstringref/CMakeLists.txt diff --git a/tests/auto/corelib/tools/qstringref/qstringref.pro b/tests/auto/corelib/text/qstringref/qstringref.pro similarity index 100% rename from tests/auto/corelib/tools/qstringref/qstringref.pro rename to tests/auto/corelib/text/qstringref/qstringref.pro diff --git a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp b/tests/auto/corelib/text/qstringref/tst_qstringref.cpp similarity index 100% rename from tests/auto/corelib/tools/qstringref/tst_qstringref.cpp rename to tests/auto/corelib/text/qstringref/tst_qstringref.cpp diff --git a/tests/auto/corelib/tools/qstringview/.gitignore b/tests/auto/corelib/text/qstringview/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qstringview/.gitignore rename to tests/auto/corelib/text/qstringview/.gitignore diff --git a/tests/auto/corelib/tools/qstringview/qstringview.pro b/tests/auto/corelib/text/qstringview/qstringview.pro similarity index 100% rename from tests/auto/corelib/tools/qstringview/qstringview.pro rename to tests/auto/corelib/text/qstringview/qstringview.pro diff --git a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp similarity index 98% rename from tests/auto/corelib/tools/qstringview/tst_qstringview.cpp rename to tests/auto/corelib/text/qstringview/tst_qstringview.cpp index 794f39708a4..5d95f43d6ae 100644 --- a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp +++ b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp @@ -251,7 +251,7 @@ void tst_QStringView::constExpr() const Q_STATIC_ASSERT(sv2.empty()); } { - constexpr QStringView sv = QStringViewLiteral(""); + constexpr QStringView sv = u""; Q_STATIC_ASSERT(sv.size() == 0); Q_STATIC_ASSERT(!sv.isNull()); Q_STATIC_ASSERT(sv.empty()); @@ -263,7 +263,7 @@ void tst_QStringView::constExpr() const Q_STATIC_ASSERT(sv2.empty()); } { - constexpr QStringView sv = QStringViewLiteral("Hello"); + constexpr QStringView sv = u"Hello"; Q_STATIC_ASSERT(sv.size() == 5); Q_STATIC_ASSERT(!sv.empty()); Q_STATIC_ASSERT(!sv.isEmpty()); @@ -465,7 +465,7 @@ void tst_QStringView::arg() const #undef CHECK2 #undef CHECK1 - QCOMPARE(QStringViewLiteral(" %2 %2 %1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, u'C'), " \r \r c C "); + QCOMPARE(QStringView(u" %2 %2 %1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, u'C'), " \r \r c C "); } void tst_QStringView::fromQString() const @@ -662,9 +662,9 @@ void tst_QStringView::conversion_tests(String string) const void tst_QStringView::comparison() { - const QStringView aa = QStringViewLiteral("aa"); - const QStringView upperAa = QStringViewLiteral("AA"); - const QStringView bb = QStringViewLiteral("bb"); + const QStringView aa = u"aa"; + const QStringView upperAa = u"AA"; + const QStringView bb = u"bb"; QVERIFY(aa == aa); QVERIFY(aa != bb); diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/.gitignore b/tests/auto/corelib/text/qtextboundaryfinder/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qtextboundaryfinder/.gitignore rename to tests/auto/corelib/text/qtextboundaryfinder/.gitignore diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/data/GraphemeBreakTest.txt b/tests/auto/corelib/text/qtextboundaryfinder/data/GraphemeBreakTest.txt similarity index 100% rename from tests/auto/corelib/tools/qtextboundaryfinder/data/GraphemeBreakTest.txt rename to tests/auto/corelib/text/qtextboundaryfinder/data/GraphemeBreakTest.txt diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/data/LineBreakTest.txt b/tests/auto/corelib/text/qtextboundaryfinder/data/LineBreakTest.txt similarity index 100% rename from tests/auto/corelib/tools/qtextboundaryfinder/data/LineBreakTest.txt rename to tests/auto/corelib/text/qtextboundaryfinder/data/LineBreakTest.txt diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/data/SentenceBreakTest.txt b/tests/auto/corelib/text/qtextboundaryfinder/data/SentenceBreakTest.txt similarity index 100% rename from tests/auto/corelib/tools/qtextboundaryfinder/data/SentenceBreakTest.txt rename to tests/auto/corelib/text/qtextboundaryfinder/data/SentenceBreakTest.txt diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/data/WordBreakTest.txt b/tests/auto/corelib/text/qtextboundaryfinder/data/WordBreakTest.txt similarity index 100% rename from tests/auto/corelib/tools/qtextboundaryfinder/data/WordBreakTest.txt rename to tests/auto/corelib/text/qtextboundaryfinder/data/WordBreakTest.txt diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/qtextboundaryfinder.pro b/tests/auto/corelib/text/qtextboundaryfinder/qtextboundaryfinder.pro similarity index 100% rename from tests/auto/corelib/tools/qtextboundaryfinder/qtextboundaryfinder.pro rename to tests/auto/corelib/text/qtextboundaryfinder/qtextboundaryfinder.pro diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/testdata.qrc b/tests/auto/corelib/text/qtextboundaryfinder/testdata.qrc similarity index 100% rename from tests/auto/corelib/tools/qtextboundaryfinder/testdata.qrc rename to tests/auto/corelib/text/qtextboundaryfinder/testdata.qrc diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp b/tests/auto/corelib/text/qtextboundaryfinder/tst_qtextboundaryfinder.cpp similarity index 100% rename from tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp rename to tests/auto/corelib/text/qtextboundaryfinder/tst_qtextboundaryfinder.cpp diff --git a/tests/auto/corelib/text/text.pro b/tests/auto/corelib/text/text.pro new file mode 100644 index 00000000000..09d58bd74cd --- /dev/null +++ b/tests/auto/corelib/text/text.pro @@ -0,0 +1,23 @@ +TEMPLATE = subdirs + +SUBDIRS = \ + qbytearray \ + qbytearraylist \ + qbytearraymatcher \ + qbytedatabuffer \ + qchar \ + qcollator \ + qlatin1string \ + qlocale \ + qregexp \ + qregularexpression \ + qstring \ + qstring_no_cast_from_bytearray \ + qstringapisymmetry \ + qstringbuilder \ + qstringiterator \ + qstringlist \ + qstringmatcher \ + qstringref \ + qstringview \ + qtextboundaryfinder diff --git a/tests/auto/corelib/thread/qsemaphore/BLACKLIST b/tests/auto/corelib/thread/qsemaphore/BLACKLIST index 0786f504173..f61f4c1a3b9 100644 --- a/tests/auto/corelib/thread/qsemaphore/BLACKLIST +++ b/tests/auto/corelib/thread/qsemaphore/BLACKLIST @@ -1,3 +1,6 @@ +[tryAcquireWithTimeout] +osx-10.12 +osx-10.13 [tryAcquireWithTimeout:0.2s] windows osx-10.12 diff --git a/tests/auto/corelib/thread/qthread/BLACKLIST b/tests/auto/corelib/thread/qthread/BLACKLIST index ccf530362cb..87538a1048b 100644 --- a/tests/auto/corelib/thread/qthread/BLACKLIST +++ b/tests/auto/corelib/thread/qthread/BLACKLIST @@ -1,4 +1,7 @@ [wait3_slowDestructor] -windows +windows-10 msvc-2015 +windows-7sp1 +windows-10 msvc-2017 [sleep] -windows ci +windows-7sp1 + diff --git a/tests/auto/corelib/thread/qthreadpool/BLACKLIST b/tests/auto/corelib/thread/qthreadpool/BLACKLIST index fc497316877..e4f2fcd822a 100644 --- a/tests/auto/corelib/thread/qthreadpool/BLACKLIST +++ b/tests/auto/corelib/thread/qthreadpool/BLACKLIST @@ -1,3 +1,7 @@ [expiryTimeoutRace] -osx -linux +rhel-7.6 +opensuse-leap +osx-10.13 +ubuntu-18.04 +osx-10.12 +opensuse-42.3 diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index 112c36952c3..60e8d8cba22 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -92,7 +92,9 @@ private slots: void priorityStart(); void waitForDone(); void clear(); +#if QT_DEPRECATED_SINCE(5, 9) void cancel(); +#endif void tryTake(); void waitForDoneTimeout(); void destroyingWaitsForTasksToFinish(); @@ -963,6 +965,7 @@ void tst_QThreadPool::clear() QCOMPARE(count.loadRelaxed(), threadPool.maxThreadCount()); } +#if QT_DEPRECATED_SINCE(5, 9) void tst_QThreadPool::cancel() { QSemaphore sem(0); @@ -1034,6 +1037,7 @@ void tst_QThreadPool::cancel() delete runnables[0]; //if the pool deletes them then we'll get double-free crash delete runnables[runs-1]; } +#endif void tst_QThreadPool::tryTake() { diff --git a/tests/auto/corelib/thread/qwaitcondition/BLACKLIST b/tests/auto/corelib/thread/qwaitcondition/BLACKLIST deleted file mode 100644 index 3ff336576b3..00000000000 --- a/tests/auto/corelib/thread/qwaitcondition/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[wakeOne] -windows diff --git a/tests/auto/corelib/time/qdatetime/BLACKLIST b/tests/auto/corelib/time/qdatetime/BLACKLIST deleted file mode 100644 index 3a42ee066b6..00000000000 --- a/tests/auto/corelib/time/qdatetime/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[timeZoneAbbreviation] -osx diff --git a/tests/auto/corelib/tools/CMakeLists.txt b/tests/auto/corelib/tools/CMakeLists.txt index 2a9d149aa88..17588e3daab 100644 --- a/tests/auto/corelib/tools/CMakeLists.txt +++ b/tests/auto/corelib/tools/CMakeLists.txt @@ -1,45 +1,50 @@ +# Generated from tools.pro. + +# add_subdirectory(collections) # special case not ported +# add_subdirectory(containerapisymmetry) # special case not ported add_subdirectory(qalgorithms) add_subdirectory(qarraydata) +# add_subdirectory(qarraydata_strictiterators) # special case not ported add_subdirectory(qbitarray) -add_subdirectory(qbytearraylist) -add_subdirectory(qbytedatabuffer) add_subdirectory(qcache) add_subdirectory(qcommandlineparser) add_subdirectory(qcontiguouscache) +# add_subdirectory(qcryptographichash) # special case not ported add_subdirectory(qeasingcurve) add_subdirectory(qexplicitlyshareddatapointer) +# add_subdirectory(qfreelist) # special case not ported add_subdirectory(qhash) +# add_subdirectory(qhash_strictiterators) # special case not ported add_subdirectory(qhashfunctions) +# add_subdirectory(qline) # special case not ported add_subdirectory(qlinkedlist) add_subdirectory(qlist) +# add_subdirectory(qlist_strictiterators) # special case not ported add_subdirectory(qmakearray) add_subdirectory(qmap) +# add_subdirectory(qmap_strictiterators) # special case not ported add_subdirectory(qmargins) add_subdirectory(qmessageauthenticationcode) +# add_subdirectory(qoffsetstringarray) # special case not ported add_subdirectory(qpair) add_subdirectory(qpoint) add_subdirectory(qpointf) add_subdirectory(qqueue) add_subdirectory(qrect) -add_subdirectory(qregexp) -add_subdirectory(qregularexpression) add_subdirectory(qringbuffer) add_subdirectory(qscopedpointer) add_subdirectory(qscopedvaluerollback) add_subdirectory(qscopeguard) add_subdirectory(qset) +# add_subdirectory(qsharedpointer) # special case not ported add_subdirectory(qsize) add_subdirectory(qsizef) add_subdirectory(qstl) -add_subdirectory(qstring_no_cast_from_bytearray) -add_subdirectory(qstringbuilder/qstringbuilder1) -add_subdirectory(qstringbuilder/qstringbuilder2) -add_subdirectory(qstringbuilder/qstringbuilder3) -add_subdirectory(qstringbuilder/qstringbuilder4) -add_subdirectory(qstringiterator) -add_subdirectory(qstringlist) -add_subdirectory(qstringmatcher) -add_subdirectory(qstringref) add_subdirectory(qtimeline) add_subdirectory(qvarlengtharray) - +# add_subdirectory(qvector) # special case not ported +# add_subdirectory(qvector_strictiterators) # special case not ported +# add_subdirectory(qversionnumber) # special case not ported +if(APPLE) + # add_subdirectory(qmacautoreleasepool) # special case not ported +endif() diff --git a/tests/auto/corelib/tools/collections/BLACKLIST b/tests/auto/corelib/tools/collections/BLACKLIST new file mode 100644 index 00000000000..c6e289aadbe --- /dev/null +++ b/tests/auto/corelib/tools/collections/BLACKLIST @@ -0,0 +1,2 @@ +[insert_remove_loop] +msvc-2019 diff --git a/tests/auto/corelib/tools/collections/collections.pro b/tests/auto/corelib/tools/collections/collections.pro index b074fa93380..e0f9f0a0ea1 100644 --- a/tests/auto/corelib/tools/collections/collections.pro +++ b/tests/auto/corelib/tools/collections/collections.pro @@ -4,5 +4,6 @@ SOURCES += tst_collections.cpp QT = core testlib # This test does not work with strict iterators +DEFINES -= QT_NO_LINKED_LIST DEFINES -= QT_STRICT_ITERATORS DEFINES -= QT_NO_JAVA_STYLE_ITERATORS diff --git a/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro b/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro index 30dc8026ef1..e46d51761ef 100644 --- a/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro +++ b/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro @@ -5,3 +5,4 @@ QT = core testlib # This test does not work with strict iterators DEFINES -= QT_STRICT_ITERATORS +DEFINES -= QT_NO_LINKED_LIST diff --git a/tests/auto/corelib/tools/qbytearraylist/CMakeLists.txt b/tests/auto/corelib/tools/qbytearraylist/CMakeLists.txt deleted file mode 100644 index f7b8314dbdc..00000000000 --- a/tests/auto/corelib/tools/qbytearraylist/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_qt_test(tst_qbytearraylist SOURCES tst_qbytearraylist.cpp) diff --git a/tests/auto/corelib/tools/qline/tst_qline.cpp b/tests/auto/corelib/tools/qline/tst_qline.cpp index 0418daf640c..31aa5b4e0ce 100644 --- a/tests/auto/corelib/tools/qline/tst_qline.cpp +++ b/tests/auto/corelib/tools/qline/tst_qline.cpp @@ -207,7 +207,10 @@ void tst_QLine::testIntersection() QPointF ip; - QLineF::IntersectionType itype = a.intersect(b, &ip); + QLineF::IntersectionType itype = a.intersects(b, &ip); +#if QT_DEPRECATED_SINCE(5, 14) + QCOMPARE(a.intersect(b, &ip), itype); +#endif QCOMPARE(int(itype), type); if (type != QLineF::NoIntersection) { diff --git a/tests/auto/corelib/tools/qlinkedlist/CMakeLists.txt b/tests/auto/corelib/tools/qlinkedlist/CMakeLists.txt index aad00ab21ed..a2f7ec5e2e0 100644 --- a/tests/auto/corelib/tools/qlinkedlist/CMakeLists.txt +++ b/tests/auto/corelib/tools/qlinkedlist/CMakeLists.txt @@ -1 +1,13 @@ -add_qt_test(tst_qlinkedlist SOURCES tst_qlinkedlist.cpp) +# Generated from qlinkedlist.pro. + +##################################################################### +## tst_qlinkedlist Test: +##################################################################### + +add_qt_test(tst_qlinkedlist + GUI + SOURCES + tst_qlinkedlist.cpp + #DEFINES # special case remove + #-QT_NO_LINKED_LIST # special case remove until fixed +) diff --git a/tests/auto/corelib/tools/qlinkedlist/qlinkedlist.pro b/tests/auto/corelib/tools/qlinkedlist/qlinkedlist.pro index 80630f78ad2..378c574eb0e 100644 --- a/tests/auto/corelib/tools/qlinkedlist/qlinkedlist.pro +++ b/tests/auto/corelib/tools/qlinkedlist/qlinkedlist.pro @@ -2,3 +2,4 @@ CONFIG += testcase TARGET = tst_qlinkedlist QT = core testlib SOURCES = tst_qlinkedlist.cpp +DEFINES -= QT_NO_LINKED_LIST diff --git a/tests/auto/corelib/tools/qlocale/BLACKLIST b/tests/auto/corelib/tools/qlocale/BLACKLIST deleted file mode 100644 index 3eac7c10ed7..00000000000 --- a/tests/auto/corelib/tools/qlocale/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[formatTimeZone] -osx diff --git a/tests/auto/corelib/tools/qtimeline/BLACKLIST b/tests/auto/corelib/tools/qtimeline/BLACKLIST index 5611969b4de..b60cab31fa3 100644 --- a/tests/auto/corelib/tools/qtimeline/BLACKLIST +++ b/tests/auto/corelib/tools/qtimeline/BLACKLIST @@ -1,9 +1,9 @@ [interpolation] -windows osx-10.12 +windows-10 msvc-2015 osx-10.13 -[duration] -windows +windows-7sp1 [frameRate] osx-10.12 osx-10.13 + diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index 070c25368b3..3d90644aa37 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -64,21 +64,21 @@ private: void initializeList(); }; -int fooCtor = 0; -int fooDtor = 0; - -struct Foo +struct Tracker { - int *p; + static int count; + Tracker() { ++count; } + Tracker(const Tracker &) { ++count; } + Tracker(Tracker &&) { ++count; } - Foo() { p = new int; ++fooCtor; } - Foo(const Foo &/*other*/) { p = new int; ++fooCtor; } + Tracker &operator=(const Tracker &) = default; + Tracker &operator=(Tracker &&) = default; - void operator=(const Foo & /* other */) { } - - ~Foo() { delete p; ++fooDtor; } + ~Tracker() { --count; } }; +int Tracker::count = 0; + void tst_QVarLengthArray::append() { QVarLengthArray v; @@ -130,6 +130,23 @@ void tst_QVarLengthArray::removeLast() v.removeLast(); QCOMPARE(v.size(), 2); } + + { + Tracker t; + QCOMPARE(Tracker::count, 1); + QVarLengthArray v; + v.append(t); + v.append({}); + QCOMPARE(Tracker::count, 3); + v.removeLast(); + QCOMPARE(Tracker::count, 2); + v.append(t); + v.append({}); + QCOMPARE(Tracker::count, 4); + v.removeLast(); + QCOMPARE(Tracker::count, 3); + } + QCOMPARE(Tracker::count, 0); } void tst_QVarLengthArray::oldTests() diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index 32561304722..05b5579d648 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -253,6 +253,7 @@ private slots: void fillInt() const; void fillMovable() const; void fillCustom() const; + void fillDetaches() const; void first() const; void fromListInt() const; void fromListMovable() const; @@ -1310,6 +1311,16 @@ void tst_QVector::fillCustom() const QCOMPARE(instancesCount, Custom::counter.loadAcquire()); } +void tst_QVector::fillDetaches() const +{ + QVector test = { 1, 2, 3 }; + QVector copy = test; + copy.fill(42); + + QCOMPARE(test, QVector({1, 2, 3})); + QCOMPARE(copy, QVector({42, 42, 42})); +} + void tst_QVector::first() const { QVector myvec; diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro index 243e7e96f52..49b2a1f075d 100644 --- a/tests/auto/corelib/tools/tools.pro +++ b/tests/auto/corelib/tools/tools.pro @@ -6,13 +6,7 @@ SUBDIRS=\ qarraydata \ qarraydata_strictiterators \ qbitarray \ - qbytearray \ - qbytearraylist \ - qbytearraymatcher \ - qbytedatabuffer \ qcache \ - qchar \ - qcollator \ qcommandlineparser \ qcontiguouscache \ qcryptographichash \ @@ -22,12 +16,10 @@ SUBDIRS=\ qhash \ qhash_strictiterators \ qhashfunctions \ - qlatin1string \ qline \ qlinkedlist \ qlist \ qlist_strictiterators \ - qlocale \ qmakearray \ qmap \ qmap_strictiterators \ @@ -39,8 +31,6 @@ SUBDIRS=\ qpointf \ qqueue \ qrect \ - qregexp \ - qregularexpression \ qringbuffer \ qscopedpointer \ qscopedvaluerollback \ @@ -50,16 +40,6 @@ SUBDIRS=\ qsize \ qsizef \ qstl \ - qstring \ - qstring_no_cast_from_bytearray \ - qstringapisymmetry \ - qstringbuilder \ - qstringiterator \ - qstringlist \ - qstringmatcher \ - qstringref \ - qstringview \ - qtextboundaryfinder \ qtimeline \ qvarlengtharray \ qvector \ diff --git a/tests/auto/dbus/qdbusabstractadaptor/qdbusabstractadaptor/BLACKLIST b/tests/auto/dbus/qdbusabstractadaptor/qdbusabstractadaptor/BLACKLIST new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/auto/dbus/qdbusconnection_spyhook/BLACKLIST b/tests/auto/dbus/qdbusconnection_spyhook/BLACKLIST new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp b/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp index 2dbb078ae0c..fe121750812 100644 --- a/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp +++ b/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp @@ -164,7 +164,7 @@ void tst_QIcoImageFormat::imageCount_data() QTest::newRow("16px,32px - 16 colors") << "valid/TIMER01.ICO" << 2; QTest::newRow("16px16c, 32px32c, 32px256c 1") << "valid/WORLD.ico" << 3; QTest::newRow("16px16c, 32px32c, 32px256c 2") << "valid/WORLDH.ico" << 3; - QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << 0; + QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << -1; QTest::newRow("includes 32BPP w/alpha") << "valid/semitransparent.ico" << 9; QTest::newRow("PNG compression") << "valid/Qt.ico" << 4; QTest::newRow("CUR file") << "valid/yellow.cur" << 1; @@ -177,7 +177,6 @@ void tst_QIcoImageFormat::imageCount() QImageReader reader(m_IconPath + QLatin1Char('/') + fileName); QCOMPARE(reader.imageCount(), count); - } void tst_QIcoImageFormat::jumpToNextImage_data() @@ -218,7 +217,7 @@ void tst_QIcoImageFormat::loopCount_data() QTest::addColumn("count"); QTest::newRow("floppy (16px,32px - 16 colors)") << "valid/35FLOPPY.ICO" << 0; - QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << 0; + QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << -1; } void tst_QIcoImageFormat::loopCount() @@ -228,6 +227,7 @@ void tst_QIcoImageFormat::loopCount() QImageReader reader(m_IconPath + QLatin1Char('/') + fileName); QCOMPARE(reader.loopCount(), count); + QCOMPARE(reader.canRead(), count < 0 ? false : true); } void tst_QIcoImageFormat::nextImageDelay_data() @@ -256,7 +256,7 @@ void tst_QIcoImageFormat::nextImageDelay() QImageReader reader(m_IconPath + QLatin1Char('/') + fileName); if (count == -1) { - QCOMPARE(reader.nextImageDelay(), 0); + QCOMPARE(reader.nextImageDelay(), -1); } else { int i; for (i = 0; i < count; i++) { diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index d17a1717289..8b42b139a38 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -158,6 +159,9 @@ private slots: void saveFormat_data(); void saveFormat(); + void saveColorSpace_data(); + void saveColorSpace(); + void readText_data(); void readText(); @@ -1883,6 +1887,33 @@ void tst_QImageReader::saveFormat() QCOMPARE(stored, converted); } +void tst_QImageReader::saveColorSpace_data() +{ + QTest::addColumn("colorspaceId"); + + QTest::newRow("Undefined") << QColorSpace::Undefined; + QTest::newRow("sRGB") << QColorSpace::SRgb; + QTest::newRow("sRGB(linear)") << QColorSpace::SRgbLinear; + QTest::newRow("AdobeRGB") << QColorSpace::AdobeRgb; + QTest::newRow("DisplayP3") << QColorSpace::DisplayP3; + QTest::newRow("ProPhotoRgb") << QColorSpace::ProPhotoRgb; +} + +void tst_QImageReader::saveColorSpace() +{ + QFETCH(QColorSpace::ColorSpaceId, colorspaceId); + + QImage orig(":/images/kollada.png"); + + orig.setColorSpace(colorspaceId); + QBuffer buf; + buf.open(QIODevice::WriteOnly); + QVERIFY(orig.save(&buf, "png")); + buf.close(); + QImage stored = QImage::fromData(buf.buffer(), "png"); + + QCOMPARE(stored, orig); +} void tst_QImageReader::readText_data() { diff --git a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp index 158530428d2..3158883ef59 100644 --- a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp +++ b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp @@ -104,18 +104,28 @@ void tst_QPixmapCache::cacheLimit() void tst_QPixmapCache::setCacheLimit() { + QPixmap res; QPixmap *p1 = new QPixmap(2, 3); QPixmapCache::insert("P1", *p1); +#if QT_DEPRECATED_SINCE(5, 13) QVERIFY(QPixmapCache::find("P1") != 0); +#endif + QVERIFY(QPixmapCache::find("P1", &res)); delete p1; QPixmapCache::setCacheLimit(0); +#if QT_DEPRECATED_SINCE(5, 13) QVERIFY(!QPixmapCache::find("P1")); +#endif + QVERIFY(!QPixmapCache::find("P1", &res)); p1 = new QPixmap(2, 3); QPixmapCache::setCacheLimit(1000); QPixmapCache::insert("P1", *p1); +#if QT_DEPRECATED_SINCE(5, 13) QVERIFY(QPixmapCache::find("P1") != 0); +#endif + QVERIFY(QPixmapCache::find("P1", &res)); delete p1; @@ -200,6 +210,7 @@ void tst_QPixmapCache::find() QVERIFY(QPixmapCache::insert("P1", p1)); QPixmap p2; +#if QT_DEPRECATED_SINCE(5, 13) QVERIFY(QPixmapCache::find("P1", p2)); QCOMPARE(p2.width(), 10); QCOMPARE(p2.height(), 10); @@ -209,6 +220,12 @@ void tst_QPixmapCache::find() QPixmap *p3 = QPixmapCache::find("P1"); QVERIFY(p3); QCOMPARE(p1, *p3); +#endif + + QVERIFY(QPixmapCache::find("P1", &p2)); + QCOMPARE(p2.width(), 10); + QCOMPARE(p2.height(), 10); + QCOMPARE(p1, p2); //The int part of the API QPixmapCache::Key key = QPixmapCache::insert(p1); @@ -261,6 +278,7 @@ void tst_QPixmapCache::insert() } int num = 0; +#if QT_DEPRECATED_SINCE(5, 13) for (int k = 0; k < numberOfKeys; ++k) { if (QPixmapCache::find(QString::number(k))) ++num; @@ -268,6 +286,16 @@ void tst_QPixmapCache::insert() if (QPixmapCache::find("0")) ++num; + num = 0; +#endif + QPixmap res; + for (int k = 0; k < numberOfKeys; ++k) { + if (QPixmapCache::find(QString::number(k), &res)) + ++num; + } + + if (QPixmapCache::find("0", &res)) + ++num; QVERIFY(num <= estimatedNum); QPixmap p3; @@ -340,17 +368,17 @@ void tst_QPixmapCache::remove() p1.fill(Qt::yellow); QPixmap p2; - QVERIFY(QPixmapCache::find("red", p2)); + QVERIFY(QPixmapCache::find("red", &p2)); QVERIFY(p1.toImage() != p2.toImage()); QVERIFY(p1.toImage() == p1.toImage()); // sanity check QPixmapCache::remove("red"); - QVERIFY(!QPixmapCache::find("red")); + QVERIFY(!QPixmapCache::find("red", &p2)); QPixmapCache::remove("red"); - QVERIFY(!QPixmapCache::find("red")); + QVERIFY(!QPixmapCache::find("red", &p2)); QPixmapCache::remove("green"); - QVERIFY(!QPixmapCache::find("green")); + QVERIFY(!QPixmapCache::find("green", &p2)); //The int part of the API QPixmapCache::clear(); @@ -392,7 +420,7 @@ void tst_QPixmapCache::remove() key = QPixmapCache::insert(p1); QPixmapCache::remove(key); QVERIFY(QPixmapCache::find(key, &p1) == 0); - QVERIFY(QPixmapCache::find("red") != 0); + QVERIFY(QPixmapCache::find("red", &p1) != 0); } void tst_QPixmapCache::clear() @@ -408,14 +436,14 @@ void tst_QPixmapCache::clear() const int numberOfKeys = estimatedNum + 1000; for (int i = 0; i < numberOfKeys; ++i) - QVERIFY(QPixmapCache::find("x" + QString::number(i)) == 0); + QVERIFY(!QPixmapCache::find("x" + QString::number(i), &p1)); for (int j = 0; j < numberOfKeys; ++j) QPixmapCache::insert(QString::number(j), p1); int num = 0; for (int k = 0; k < numberOfKeys; ++k) { - if (QPixmapCache::find(QString::number(k), p1)) + if (QPixmapCache::find(QString::number(k), &p1)) ++num; } QVERIFY(num > 0); @@ -423,7 +451,7 @@ void tst_QPixmapCache::clear() QPixmapCache::clear(); for (int k = 0; k < numberOfKeys; ++k) - QVERIFY(!QPixmapCache::find(QString::number(k))); + QVERIFY(!QPixmapCache::find(QString::number(k), &p1)); //The int part of the API QPixmap p2(10, 10); diff --git a/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp b/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp index 68852f5a3f2..d67b17fd43b 100644 --- a/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp +++ b/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp @@ -68,10 +68,17 @@ void tst_QDrag::getSetCheck() QCOMPARE((QMimeData *)0, obj1.mimeData()); // delete var1; // No delete, since QDrag takes ownership - Qt::DropAction result = obj1.start(); + Qt::DropAction result = obj1.exec(); + QCOMPARE(result, Qt::IgnoreAction); + result = obj1.exec(Qt::MoveAction | Qt::LinkAction); + QCOMPARE(result, Qt::IgnoreAction); + +#if QT_DEPRECATED_SINCE(5, 13) + result = obj1.start(); QCOMPARE(result, Qt::IgnoreAction); result = obj1.start(Qt::MoveAction | Qt::LinkAction); QCOMPARE(result, Qt::IgnoreAction); +#endif } QTEST_MAIN(tst_QDrag) diff --git a/tests/auto/gui/kernel/qguiapplication/BLACKLIST b/tests/auto/gui/kernel/qguiapplication/BLACKLIST index 9a670237b7e..e6ffe78ae35 100644 --- a/tests/auto/gui/kernel/qguiapplication/BLACKLIST +++ b/tests/auto/gui/kernel/qguiapplication/BLACKLIST @@ -1,4 +1,3 @@ [focusObject] -opensuse -opensuse-leap -ubuntu +ubuntu-16.04 +opensuse-42.3 diff --git a/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST b/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST index b1590a5ccf3..d2c51922a87 100644 --- a/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST +++ b/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST @@ -1,5 +1,3 @@ -[sendPostedEvents] -windows [registerTimer] -windows winrt + diff --git a/tests/auto/gui/kernel/qguieventloop/BLACKLIST b/tests/auto/gui/kernel/qguieventloop/BLACKLIST deleted file mode 100644 index 03acb2f5b0d..00000000000 --- a/tests/auto/gui/kernel/qguieventloop/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[testQuitLock] -osx-10.12 diff --git a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp index b2572188b93..3ce65a67858 100644 --- a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp +++ b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp @@ -191,7 +191,7 @@ template<> struct TestValueFactory { static QTextLength *create() { return new QTextLength(QTextLength::PercentageLength, 50); } }; template<> struct TestValueFactory { - static QTextFormat *create() { return new QTextFormat(QTextFormat::TableFormat); } + static QTextFormat *create() { return new QTextFormat(QTextFormat::FrameFormat); } }; template<> struct TestValueFactory { static QMatrix *create() { return new QMatrix(10, 20, 30, 40, 50, 60); } diff --git a/tests/auto/gui/kernel/qguitimer/BLACKLIST b/tests/auto/gui/kernel/qguitimer/BLACKLIST new file mode 100644 index 00000000000..6ab715b9221 --- /dev/null +++ b/tests/auto/gui/kernel/qguitimer/BLACKLIST @@ -0,0 +1,8 @@ +[basic_chrono] +osx-10.13 +[remainingTime] +osx-10.12 +windows-10 msvc-2015 +osx-10.14 +osx-10.13 + diff --git a/tests/auto/gui/kernel/qtouchevent/BLACKLIST b/tests/auto/gui/kernel/qtouchevent/BLACKLIST index 8e78d7e41f5..dcda77bce79 100644 --- a/tests/auto/gui/kernel/qtouchevent/BLACKLIST +++ b/tests/auto/gui/kernel/qtouchevent/BLACKLIST @@ -1,6 +1,2 @@ -[basicRawEventTranslation] -linux [multiPointRawEventTranslationOnTouchScreen] -linux -[multiPointRawEventTranslationOnTouchPad] -linux +ubuntu-16.04 diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index 1820499a536..1bb3917948b 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -1,3 +1,7 @@ +[positioning] +opensuse-leap +ubuntu-16.04 +opensuse-42.3 [positioning:default] linux osx-10.12 ci @@ -6,38 +10,25 @@ winrt osx-10.12 ci [modalWithChildWindow] ubuntu-16.04 -# QTBUG-66851 -opensuse opensuse-leap +# QTBUG-66851 # QTBUG-69160 -android +opensuse-42.3 [setVisible] # QTBUG-69154 android [modalWindowEnterEventOnHide_QTBUG35109] ubuntu-16.04 -osx ci +osx-10.11 +osx-10.13 +osx-10.14 +osx-10.12 [spuriousMouseMove] -windows ci # QTBUG-69162 -android -[modalDialogClosingOneOfTwoModal] -osx -[modalWindowModallity] -osx -# QTBUG-69163 -android -[visibility] -osx-10.12 ci - +windows-10 msvc-2015 +windows-10 msvc-2017 [testInputEvents] rhel-7.4 -[isActive] -# QTBUG-67768 -ubuntu -# QTBUG-69157 -android - [exposeEventOnShrink_QTBUG54040] # QTBUG-69155 android diff --git a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp index 96d983c8f74..e19f76d8307 100644 --- a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp +++ b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp @@ -2861,8 +2861,10 @@ void tst_QMatrixNxN::convertGeneric() QMatrix4x4 m4(m1); QVERIFY(isSame(m4, unique4x4)); +#if QT_DEPRECATED_SINCE(5, 0) QMatrix4x4 m5 = qGenericMatrixToMatrix4x4(m1); QVERIFY(isSame(m5, unique4x4)); +#endif static float const conv4x4[12] = { 1.0f, 2.0f, 3.0f, 4.0f, @@ -2874,8 +2876,10 @@ void tst_QMatrixNxN::convertGeneric() QMatrix4x3 m10 = m9.toGenericMatrix<4, 3>(); QVERIFY(isSame(m10, conv4x4)); +#if QT_DEPRECATED_SINCE(5, 0) QMatrix4x3 m11 = qGenericMatrixFromMatrix4x4<4, 3>(m9); QVERIFY(isSame(m11, conv4x4)); +#endif } // Copy of "flagBits" in qmatrix4x4.h. diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp index 097dd111d3e..8041fb5439a 100644 --- a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp +++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp @@ -778,7 +778,10 @@ void tst_QQuaternion::conjugate() QQuaternion v1(w1, x1, y1, z1); QQuaternion v2(w1, -x1, -y1, -z1); +#if QT_DEPRECATED_SINCE(5, 5) QCOMPARE(v1.conjugate(), v2); +#endif + QCOMPARE(v1.conjugated(), v2); } // Test quaternion creation from an axis and an angle. diff --git a/tests/auto/gui/painting/qcolorspace/resources/HP_ZR30w.icc b/tests/auto/gui/painting/qcolorspace/resources/HP_ZR30w.icc new file mode 100644 index 00000000000..b3f860714c5 Binary files /dev/null and b/tests/auto/gui/painting/qcolorspace/resources/HP_ZR30w.icc differ diff --git a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp index 7a88eb18b29..bc1a45013ca 100644 --- a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp +++ b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp @@ -36,7 +36,7 @@ #include Q_DECLARE_METATYPE(QColorSpace::ColorSpaceId) -Q_DECLARE_METATYPE(QColorSpace::Gamut) +Q_DECLARE_METATYPE(QColorSpace::Primaries) Q_DECLARE_METATYPE(QColorSpace::TransferFunction) class tst_QColorSpace : public QObject @@ -53,6 +53,7 @@ private slots: void toIccProfile_data(); void toIccProfile(); + void fromIccProfile_data(); void fromIccProfile(); void imageConversion_data(); @@ -60,11 +61,14 @@ private slots: void loadImage(); - void gamut(); + void primaries(); void primariesXyz(); void primaries2_data(); void primaries2(); void invalidPrimaries(); + + void changeTransferFunction(); + void changePrimaries(); }; tst_QColorSpace::tst_QColorSpace() @@ -74,33 +78,33 @@ tst_QColorSpace::tst_QColorSpace() void tst_QColorSpace::namedColorSpaces_data() { QTest::addColumn("colorSpaceId"); - QTest::addColumn("gamutId"); + QTest::addColumn("primariesId"); QTest::addColumn("transferFunctionId"); QTest::newRow("sRGB") << QColorSpace::SRgb - << QColorSpace::Gamut::SRgb + << QColorSpace::Primaries::SRgb << QColorSpace::TransferFunction::SRgb; QTest::newRow("sRGB Linear") << QColorSpace::SRgbLinear - << QColorSpace::Gamut::SRgb + << QColorSpace::Primaries::SRgb << QColorSpace::TransferFunction::Linear; QTest::newRow("Adobe RGB") << QColorSpace::AdobeRgb - << QColorSpace::Gamut::AdobeRgb + << QColorSpace::Primaries::AdobeRgb << QColorSpace::TransferFunction::Gamma; QTest::newRow("Display-P3") << QColorSpace::DisplayP3 - << QColorSpace::Gamut::DciP3D65 + << QColorSpace::Primaries::DciP3D65 << QColorSpace::TransferFunction::SRgb; QTest::newRow("ProPhoto RGB") << QColorSpace::ProPhotoRgb - << QColorSpace::Gamut::ProPhotoRgb + << QColorSpace::Primaries::ProPhotoRgb << QColorSpace::TransferFunction::ProPhotoRgb; QTest::newRow("BT.2020") << QColorSpace::Bt2020 - << QColorSpace::Gamut::Bt2020 + << QColorSpace::Primaries::Bt2020 << QColorSpace::TransferFunction::Bt2020; } void tst_QColorSpace::namedColorSpaces() { QFETCH(QColorSpace::ColorSpaceId, colorSpaceId); - QFETCH(QColorSpace::Gamut, gamutId); + QFETCH(QColorSpace::Primaries, primariesId); QFETCH(QColorSpace::TransferFunction, transferFunctionId); QColorSpace colorSpace = colorSpaceId; @@ -108,7 +112,7 @@ void tst_QColorSpace::namedColorSpaces() QVERIFY(colorSpace.isValid()); QCOMPARE(colorSpace.colorSpaceId(), colorSpaceId); - QCOMPARE(colorSpace.gamut(), gamutId); + QCOMPARE(colorSpace.primaries(), primariesId); QCOMPARE(colorSpace.transferFunction(), transferFunctionId); } @@ -121,10 +125,10 @@ void tst_QColorSpace::toIccProfile_data() void tst_QColorSpace::toIccProfile() { QFETCH(QColorSpace::ColorSpaceId, colorSpaceId); - QFETCH(QColorSpace::Gamut, gamutId); + QFETCH(QColorSpace::Primaries, primariesId); QFETCH(QColorSpace::TransferFunction, transferFunctionId); - Q_UNUSED(gamutId); + Q_UNUSED(primariesId); Q_UNUSED(transferFunctionId); QColorSpace colorSpace = colorSpaceId; @@ -142,21 +146,38 @@ void tst_QColorSpace::toIccProfile() QCOMPARE(iccProfile2, iccProfile); } +void tst_QColorSpace::fromIccProfile_data() +{ + QTest::addColumn("testProfile"); + QTest::addColumn("colorSpaceId"); + QTest::addColumn("transferFunction"); + QTest::addColumn("description"); + + QString prefix = QFINDTESTDATA("resources/"); + // Read the official sRGB ICCv2 profile: + QTest::newRow("sRGB2014 (ICCv2)") << prefix + "sRGB2014.icc" << QColorSpace::SRgb + << QColorSpace::TransferFunction::SRgb << QString("sRGB2014"); + // My monitor's profile: + QTest::newRow("HP ZR30w (ICCv4)") << prefix + "HP_ZR30w.icc" << QColorSpace::Unknown + << QColorSpace::TransferFunction::Gamma << QString("HP Z30i"); +} + void tst_QColorSpace::fromIccProfile() { - // Read the official sRGB ICCv2 profile: - QString prefix = QFINDTESTDATA("resources/"); - QFile file(prefix + "sRGB2014.icc"); + QFETCH(QString, testProfile); + QFETCH(QColorSpace::ColorSpaceId, colorSpaceId); + QFETCH(QColorSpace::TransferFunction, transferFunction); + QFETCH(QString, description); + + QFile file(testProfile); file.open(QIODevice::ReadOnly); QByteArray iccProfile = file.readAll(); - QColorSpace stdSRgb = QColorSpace::fromIccProfile(iccProfile); - QVERIFY(stdSRgb.isValid()); + QColorSpace fileColorSpace = QColorSpace::fromIccProfile(iccProfile); + QVERIFY(fileColorSpace.isValid()); - QCOMPARE(stdSRgb.gamut(), QColorSpace::Gamut::SRgb); - QCOMPARE(stdSRgb.transferFunction(), QColorSpace::TransferFunction::SRgb); - QCOMPARE(stdSRgb.colorSpaceId(), QColorSpace::SRgb); - - QCOMPARE(stdSRgb, QColorSpace(QColorSpace::SRgb)); + QCOMPARE(fileColorSpace.colorSpaceId(), colorSpaceId); + QCOMPARE(fileColorSpace.transferFunction(), transferFunction); + QCOMPARE(QColorSpacePrivate::get(fileColorSpace)->description, description); } void tst_QColorSpace::imageConversion_data() @@ -262,7 +283,7 @@ void tst_QColorSpace::loadImage() QVERIFY(maxBlue2 > maxBlue); } -void tst_QColorSpace::gamut() +void tst_QColorSpace::primaries() { QColor black = QColor::fromRgbF(0.0, 0.0, 0.0); QColor white = QColor::fromRgbF(1.0, 1.0, 1.0); @@ -304,30 +325,30 @@ void tst_QColorSpace::primariesXyz() QColorSpace bt2020 = QColorSpace::Bt2020; // Check if our calculated matrices, match the precalculated ones. - QCOMPARE(sRgb.d_func()->toXyz, QColorMatrix::toXyzFromSRgb()); - QCOMPARE(adobeRgb.d_func()->toXyz, QColorMatrix::toXyzFromAdobeRgb()); - QCOMPARE(displayP3.d_func()->toXyz, QColorMatrix::toXyzFromDciP3D65()); - QCOMPARE(proPhotoRgb.d_func()->toXyz, QColorMatrix::toXyzFromProPhotoRgb()); - QCOMPARE(bt2020.d_func()->toXyz, QColorMatrix::toXyzFromBt2020()); + QCOMPARE(QColorSpacePrivate::get(sRgb)->toXyz, QColorMatrix::toXyzFromSRgb()); + QCOMPARE(QColorSpacePrivate::get(adobeRgb)->toXyz, QColorMatrix::toXyzFromAdobeRgb()); + QCOMPARE(QColorSpacePrivate::get(displayP3)->toXyz, QColorMatrix::toXyzFromDciP3D65()); + QCOMPARE(QColorSpacePrivate::get(proPhotoRgb)->toXyz, QColorMatrix::toXyzFromProPhotoRgb()); + QCOMPARE(QColorSpacePrivate::get(bt2020)->toXyz, QColorMatrix::toXyzFromBt2020()); } void tst_QColorSpace::primaries2_data() { - QTest::addColumn("gamut"); + QTest::addColumn("primariesId"); - QTest::newRow("sRGB") << QColorSpace::Gamut::SRgb; - QTest::newRow("DCI-P3 (D65)") << QColorSpace::Gamut::DciP3D65; - QTest::newRow("Adobe RGB (1998)") << QColorSpace::Gamut::AdobeRgb; - QTest::newRow("ProPhoto RGB") << QColorSpace::Gamut::ProPhotoRgb; - QTest::newRow("BT.2020") << QColorSpace::Gamut::Bt2020; + QTest::newRow("sRGB") << QColorSpace::Primaries::SRgb; + QTest::newRow("DCI-P3 (D65)") << QColorSpace::Primaries::DciP3D65; + QTest::newRow("Adobe RGB (1998)") << QColorSpace::Primaries::AdobeRgb; + QTest::newRow("ProPhoto RGB") << QColorSpace::Primaries::ProPhotoRgb; + QTest::newRow("BT.2020") << QColorSpace::Primaries::Bt2020; } void tst_QColorSpace::primaries2() { - QFETCH(QColorSpace::Gamut, gamut); - QColorSpacePrimaries primaries(gamut); + QFETCH(QColorSpace::Primaries, primariesId); + QColorSpacePrimaries primaries(primariesId); - QColorSpace original(gamut, QColorSpace::TransferFunction::Linear); + QColorSpace original(primariesId, QColorSpace::TransferFunction::Linear); QColorSpace custom1(primaries.whitePoint, primaries.redPoint, primaries.greenPoint, primaries.bluePoint, QColorSpace::TransferFunction::Linear); QCOMPARE(original, custom1); @@ -357,5 +378,49 @@ void tst_QColorSpace::invalidPrimaries() QCOMPARE(custom.colorSpaceId(), QColorSpace::Undefined); } +void tst_QColorSpace::changeTransferFunction() +{ + QColorSpace sRgb = QColorSpace::SRgb; + + QColorSpace sRgbLinear = sRgb.withTransferFunction(QColorSpace::TransferFunction::Linear); + QCOMPARE(sRgbLinear.transferFunction(), QColorSpace::TransferFunction::Linear); + QCOMPARE(sRgbLinear.gamma(), 1.0f); + QCOMPARE(sRgbLinear.primaries(), QColorSpace::Primaries::SRgb); + QCOMPARE(sRgbLinear.colorSpaceId(), QColorSpace::SRgbLinear); + QCOMPARE(sRgbLinear, QColorSpace(QColorSpace::SRgbLinear)); + QVERIFY(sRgbLinear != sRgb); + QCOMPARE(sRgbLinear.withTransferFunction(QColorSpace::TransferFunction::SRgb), sRgb); + + QColorSpace aRgb = QColorSpace::AdobeRgb; + aRgb.setTransferFunction(QColorSpace::TransferFunction::SRgb); + QCOMPARE(aRgb.transferFunction(), QColorSpace::TransferFunction::SRgb); + QCOMPARE(aRgb.primaries(), QColorSpace::Primaries::AdobeRgb); + QCOMPARE(aRgb.colorSpaceId(), QColorSpace::Unknown); + QVERIFY(aRgb != QColorSpace(QColorSpace::AdobeRgb)); + QVERIFY(aRgb != sRgb); + QCOMPARE(aRgb.withTransferFunction(QColorSpace::TransferFunction::Gamma, 2.2f), + QColorSpace(QColorSpace::AdobeRgb)); + QVERIFY(aRgb != QColorSpace(QColorSpace::AdobeRgb)); + aRgb.setTransferFunction(QColorSpace::TransferFunction::Gamma, 2.2f); + QVERIFY(aRgb == QColorSpace(QColorSpace::AdobeRgb)); + + QColorSpace undefined; + QCOMPARE(undefined.withTransferFunction(QColorSpace::TransferFunction::Linear), undefined); + undefined.setTransferFunction(QColorSpace::TransferFunction::SRgb); + QCOMPARE(undefined, QColorSpace()); +} + +void tst_QColorSpace::changePrimaries() +{ + QColorSpace cs = QColorSpace::SRgb; + cs.setPrimaries(QColorSpace::Primaries::DciP3D65); + QVERIFY(cs.isValid()); + QCOMPARE(cs, QColorSpace(QColorSpace::DisplayP3)); + cs.setTransferFunction(QColorSpace::TransferFunction::Linear); + cs.setPrimaries(QPointF(0.3127, 0.3290), QPointF(0.640, 0.330), + QPointF(0.3000, 0.6000), QPointF(0.150, 0.060)); + QCOMPARE(cs, QColorSpace(QColorSpace::SRgbLinear)); +} + QTEST_MAIN(tst_QColorSpace) #include "tst_qcolorspace.moc" diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 2b53169a45d..0efeb9b356f 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -123,14 +123,18 @@ private slots: void drawPath2(); void drawPath3(); +#if QT_DEPRECATED_SINCE(5, 13) void drawRoundRect_data() { fillData(); } void drawRoundRect(); +#endif + void drawRoundedRect_data() { fillData(); } + void drawRoundedRect(); void qimageFormats_data(); void qimageFormats(); void textOnTransparentImage(); -#ifndef QT_NO_WIDGETS +#if !defined(QT_NO_WIDGETS) && QT_DEPRECATED_SINCE(5, 13) void initFrom(); #endif @@ -679,12 +683,14 @@ static QRect getPaintedSize(const QPixmap &pm, const QColor &background) } #ifndef QT_NO_WIDGETS + +#if QT_DEPRECATED_SINCE(5, 13) void tst_QPainter::initFrom() { QWidget *widget = new QWidget(); QPalette pal = widget->palette(); - pal.setColor(QPalette::Foreground, QColor(255, 0, 0)); - pal.setBrush(QPalette::Background, QColor(0, 255, 0)); + pal.setColor(QPalette::WindowText, QColor(255, 0, 0)); + pal.setBrush(QPalette::Window, QColor(0, 255, 0)); widget->setPalette(pal); widget->show(); @@ -698,11 +704,12 @@ void tst_QPainter::initFrom() p.initFrom(widget); QCOMPARE(p.font(), font); - QCOMPARE(p.pen().color(), pal.color(QPalette::Foreground)); + QCOMPARE(p.pen().color(), pal.color(QPalette::WindowText)); QCOMPARE(p.background(), pal.window()); delete widget; } +#endif void tst_QPainter::drawBorderPixmap() { @@ -1546,6 +1553,7 @@ void tst_QPainter::drawClippedEllipse() } +#if QT_DEPRECATED_SINCE(5, 13) void tst_QPainter::drawRoundRect() { QFETCH(QRect, rect); @@ -1580,6 +1588,42 @@ void tst_QPainter::drawRoundRect() QCOMPARE(painted.height(), rect.height() + increment); } } +#endif + +void tst_QPainter::drawRoundedRect() +{ + QFETCH(QRect, rect); + QFETCH(bool, usePen); + +#ifdef Q_OS_DARWIN + if (QTest::currentDataTag() == QByteArray("rect(6, 12, 3, 14) with pen") || + QTest::currentDataTag() == QByteArray("rect(6, 17, 3, 25) with pen") || + QTest::currentDataTag() == QByteArray("rect(10, 6, 10, 3) with pen") || + QTest::currentDataTag() == QByteArray("rect(10, 12, 10, 14) with pen") || + QTest::currentDataTag() == QByteArray("rect(13, 45, 17, 80) with pen") || + QTest::currentDataTag() == QByteArray("rect(13, 50, 17, 91) with pen") || + QTest::currentDataTag() == QByteArray("rect(17, 6, 24, 3) with pen") || + QTest::currentDataTag() == QByteArray("rect(24, 12, 38, 14) with pen")) + QSKIP("The Mac paint engine is off-by-one on certain rect sizes"); +#endif + QPixmap pixmap(rect.x() + rect.width() + 10, + rect.y() + rect.height() + 10); + { + pixmap.fill(Qt::white); + QPainter p(&pixmap); + p.setRenderHint(QPainter::Qt4CompatiblePainting); + p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen)); + p.setBrush(Qt::black); + p.drawRoundedRect(rect, 25, 25, Qt::RelativeSize); + p.end(); + + int increment = usePen ? 1 : 0; + + const QRect painted = getPaintedSize(pixmap, Qt::white); + QCOMPARE(painted.width(), rect.width() + increment); + QCOMPARE(painted.height(), rect.height() + increment); + } +} void tst_QPainter::qimageFormats_data() { @@ -1662,9 +1706,13 @@ void tst_QPainter::combinedMatrix() p.translate(0.5, 0.5); + QTransform ct = p.combinedTransform(); +#if QT_DEPRECATED_SINCE(5, 13) QMatrix cm = p.combinedMatrix(); + QCOMPARE(cm, ct.toAffine()); +#endif - QPointF pt = QPointF(0, 0) * cm; + QPointF pt = QPointF(0, 0) * ct.toAffine(); QCOMPARE(pt.x(), 48.0); QCOMPARE(pt.y(), 16.0); @@ -1979,7 +2027,7 @@ void tst_QPainter::clippedFillPath_data() << pen2; path = QPainterPath(); - path.addRoundRect(QRect(15, 15, 50, 50), 20); + path.addRoundedRect(QRect(15, 15, 50, 50), 20, Qt::RelativeSize); QTest::newRow("round rect 0") << QSize(100, 100) << path << QRect(15, 15, 49, 49) << QBrush(Qt::NoBrush) @@ -4088,14 +4136,18 @@ void tst_QPainter::inactivePainter() p.setClipRegion(region); p.setClipping(true); +#if QT_DEPRECATED_SINCE(5, 13) p.combinedMatrix(); +#endif p.combinedTransform(); p.compositionMode(); p.setCompositionMode(QPainter::CompositionMode_Plus); p.device(); +#if QT_DEPRECATED_SINCE(5, 13) p.deviceMatrix(); +#endif p.deviceTransform(); p.font(); @@ -4119,7 +4171,9 @@ void tst_QPainter::inactivePainter() p.setRenderHint(QPainter::Antialiasing, true); p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false); +#if QT_DEPRECATED_SINCE(5, 13) p.resetMatrix(); +#endif p.resetTransform(); p.rotate(1); p.scale(2, 2); @@ -4135,8 +4189,10 @@ void tst_QPainter::inactivePainter() p.window(); p.setWindow(QRect(10, 10, 620, 460)); +#if QT_DEPRECATED_SINCE(5, 13) p.worldMatrix(); p.setWorldMatrix(QMatrix().translate(43, 21), true); +#endif p.setWorldMatrixEnabled(true); p.transform(); diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp index c90348e91a6..67cf9a321af 100644 --- a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp +++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp @@ -161,10 +161,18 @@ void tst_QPainterPath::clear() p1.clear(); QCOMPARE(p1, p2); + p1.lineTo(50, 50); + QPainterPath p3; + QCOMPARE(p1.elementCount(), 2); + p3.lineTo(50, 50); + QCOMPARE(p1, p3); + QCOMPARE(p1.fillRule(), Qt::OddEvenFill); p1.setFillRule(Qt::WindingFill); + QVERIFY(p1 != p3); p1.clear(); - QCOMPARE(p1.fillRule(), Qt::WindingFill); + QCOMPARE(p1.fillRule(), Qt::OddEvenFill); + QCOMPARE(p1, p2); } void tst_QPainterPath::reserveAndCapacity() diff --git a/tests/auto/gui/painting/qpathclipper/paths.cpp b/tests/auto/gui/painting/qpathclipper/paths.cpp index 077527e1a0b..1328befd1b4 100644 --- a/tests/auto/gui/painting/qpathclipper/paths.cpp +++ b/tests/auto/gui/painting/qpathclipper/paths.cpp @@ -578,7 +578,7 @@ QPainterPath Paths::node() m_rect.setHeight(100); QPainterPath shape; - shape.addRoundRect(m_rect, 25); + shape.addRoundedRect(m_rect, 25, Qt::RelativeSize); const int conWidth = 10; const int xOffset = 7; diff --git a/tests/auto/gui/qopengl/BLACKLIST b/tests/auto/gui/qopengl/BLACKLIST index a036106c57f..10e0520bd95 100644 --- a/tests/auto/gui/qopengl/BLACKLIST +++ b/tests/auto/gui/qopengl/BLACKLIST @@ -1,10 +1,2 @@ -[fboRendering] -windows -[QTBUG15621_triangulatingStrokerDivZero] -windows -[imageFormatPainting] -windows -[openGLPaintDevice] -windows [wglContextWrap] windows diff --git a/tests/auto/gui/text/qfont/BLACKLIST b/tests/auto/gui/text/qfont/BLACKLIST deleted file mode 100644 index 42cb8408f42..00000000000 --- a/tests/auto/gui/text/qfont/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[defaultFamily] -b2qt diff --git a/tests/auto/gui/text/qfont/tst_qfont.cpp b/tests/auto/gui/text/qfont/tst_qfont.cpp index 901284e131b..96f3b1c1d76 100644 --- a/tests/auto/gui/text/qfont/tst_qfont.cpp +++ b/tests/auto/gui/text/qfont/tst_qfont.cpp @@ -58,7 +58,9 @@ private slots: void insertAndRemoveSubstitutions(); void serialize_data(); void serialize(); +#if QT_DEPRECATED_SINCE(5, 13) void lastResortFont(); +#endif void styleName(); void defaultFamily_data(); void defaultFamily(); @@ -484,6 +486,7 @@ void tst_QFont::serialize() } } +#if QT_DEPRECATED_SINCE(5, 13) // QFont::lastResortFont() may abort with qFatal() on QWS/QPA // if absolutely no font is found. Just as ducumented for QFont::lastResortFont(). // This happens on our CI machines which run QWS autotests. @@ -494,6 +497,7 @@ void tst_QFont::lastResortFont() QFont font; QVERIFY(!font.lastResortFont().isEmpty()); } +#endif void tst_QFont::styleName() { diff --git a/tests/auto/gui/text/qglyphrun/BLACKLIST b/tests/auto/gui/text/qglyphrun/BLACKLIST index d8dbdabb4ba..57f32c683d4 100644 --- a/tests/auto/gui/text/qglyphrun/BLACKLIST +++ b/tests/auto/gui/text/qglyphrun/BLACKLIST @@ -1,4 +1,3 @@ [mixedScripts] ubuntu-18.04 b2qt -windows diff --git a/tests/auto/gui/text/qtextdocumentlayout/BLACKLIST b/tests/auto/gui/text/qtextdocumentlayout/BLACKLIST index b13b2497d3d..5c81e74aa0e 100644 --- a/tests/auto/gui/text/qtextdocumentlayout/BLACKLIST +++ b/tests/auto/gui/text/qtextdocumentlayout/BLACKLIST @@ -1,2 +1,4 @@ [imageAtRightAlignedTab] -linux +rhel-6.6 +rhel-7.4 +rhel-7.6 diff --git a/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST b/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST index fc9e5a9efe8..0ce46130ce0 100644 --- a/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST +++ b/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST @@ -1,3 +1,2 @@ [rewriteDocument] -winrt # QTBUG-54623 - +winrt diff --git a/tests/auto/gui/text/qtexttable/qtexttable.pro b/tests/auto/gui/text/qtexttable/qtexttable.pro index 2faadfcb0d2..73e94d5735c 100644 --- a/tests/auto/gui/text/qtexttable/qtexttable.pro +++ b/tests/auto/gui/text/qtexttable/qtexttable.pro @@ -1,6 +1,6 @@ CONFIG += testcase TARGET = tst_qtexttable -QT += testlib +QT += testlib gui-private qtHaveModule(widgets): QT += widgets SOURCES += tst_qtexttable.cpp diff --git a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp index 22f00c677d2..f21b969aa76 100644 --- a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp +++ b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp @@ -44,6 +44,7 @@ #include #include #endif +#include typedef QList IntList; @@ -91,7 +92,7 @@ private slots: void QTBUG11282_insertBeforeMergedEnding(); #endif void QTBUG22011_insertBeforeRowSpan(); -#ifndef QT_NO_PRINTER +#if !defined(QT_NO_PRINTER) && defined(QT_BUILD_INTERNAL) void QTBUG31330_renderBackground(); #endif @@ -1025,7 +1026,7 @@ void tst_QTextTable::QTBUG22011_insertBeforeRowSpan() QCOMPARE(table->columns(), 6); } -#ifndef QT_NO_PRINTER +#if !defined(QT_NO_PRINTER) && defined(QT_BUILD_INTERNAL) namespace { class QTBUG31330_PaintDevice : public QPagedPaintDevice { @@ -1065,11 +1066,46 @@ public: {} }; + class QDummyPagedPaintDevicePrivate : public QPagedPaintDevicePrivate + { + bool setPageLayout(const QPageLayout &newPageLayout) override + { + m_pageLayout = newPageLayout; + return m_pageLayout.isEquivalentTo(newPageLayout); + } + + bool setPageSize(const QPageSize &pageSize) override + { + m_pageLayout.setPageSize(pageSize); + return m_pageLayout.pageSize().isEquivalentTo(pageSize); + } + + bool setPageOrientation(QPageLayout::Orientation orientation) override + { + m_pageLayout.setOrientation(orientation); + return m_pageLayout.orientation() == orientation; + } + + bool setPageMargins(const QMarginsF &margins, QPageLayout::Unit units) override + { + m_pageLayout.setUnits(units); + m_pageLayout.setMargins(margins); + return m_pageLayout.margins() == margins && m_pageLayout.units() == units; + } + + QPageLayout pageLayout() const override + { + return m_pageLayout; + } + + QPageLayout m_pageLayout; + }; + int pages; QPaintEngine* engine; QTBUG31330_PaintDevice(QPaintEngine* engine) - : pages(1), engine(engine) + : QPagedPaintDevice(new QDummyPagedPaintDevicePrivate), pages(1), engine(engine) { QPageLayout layout = pageLayout(); layout.setUnits(QPageLayout::Point); diff --git a/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp b/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp index add23d46cfa..4d95345de90 100644 --- a/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp +++ b/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp @@ -39,7 +39,9 @@ class tst_qdesktopservices : public QObject private slots: void openUrl(); void handlers(); +#if QT_DEPRECATED_SINCE(5, 0) void testDataLocation(); +#endif }; void tst_qdesktopservices::openUrl() @@ -89,6 +91,7 @@ void tst_qdesktopservices::handlers() #define Q_XDG_PLATFORM #endif +#if QT_DEPRECATED_SINCE(5, 0) void tst_qdesktopservices::testDataLocation() { // This is the one point where QDesktopServices and QStandardPaths differ. @@ -115,6 +118,7 @@ void tst_qdesktopservices::testDataLocation() #endif } } +#endif QTEST_MAIN(tst_qdesktopservices) diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index e24370fc87e..bf3d9364467 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -46,6 +46,7 @@ #endif // NO_SSL #include +#include #include #include "emulationdetector.h" @@ -71,6 +72,8 @@ class tst_Http2 : public QObject public: tst_Http2(); ~tst_Http2(); +public slots: + void init(); private slots: // Tests: void singleRequest_data(); @@ -82,6 +85,8 @@ private slots: void goaway_data(); void goaway(); void earlyResponse(); + void connectToHost_data(); + void connectToHost(); protected slots: // Slots to listen to our in-process server: @@ -115,7 +120,7 @@ private: quint16 serverPort = 0; QThread *workerThread = nullptr; - QNetworkAccessManager manager; + std::unique_ptr manager; QTestEventLoop eventLoop; @@ -129,6 +134,10 @@ private: static const Http2::RawSettings defaultServerSettings; }; +#define STOP_ON_FAILURE \ + if (QTest::currentTestFailed()) \ + return; + const Http2::RawSettings tst_Http2::defaultServerSettings{{Http2::Settings::MAX_CONCURRENT_STREAMS_ID, 100}}; namespace { @@ -174,6 +183,11 @@ tst_Http2::~tst_Http2() } } +void tst_Http2::init() +{ + manager.reset(new QNetworkAccessManager); +} + void tst_Http2::singleRequest_data() { QTest::addColumn("h2Attribute"); @@ -228,13 +242,14 @@ void tst_Http2::singleRequest() QFETCH(const QNetworkRequest::Attribute, h2Attribute); request.setAttribute(h2Attribute, QVariant(true)); - auto reply = manager.get(request); + auto reply = manager->get(request); connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); // Since we're using self-signed certificates, // ignore SSL errors: reply->ignoreSslErrors(); runEventLoop(); + STOP_ON_FAILURE QVERIFY(nRequests == 0); QVERIFY(prefaceOK); @@ -270,6 +285,7 @@ void tst_Http2::multipleRequests() sendRequest(i, priorities[QRandomGenerator::global()->bounded(3)]); runEventLoop(); + STOP_ON_FAILURE QVERIFY(nRequests == 0); QVERIFY(prefaceOK); @@ -299,7 +315,7 @@ void tst_Http2::flowControlClientSide() params.maxSessionReceiveWindowSize = Http2::defaultSessionWindowSize * 5; params.settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID] = Http2::defaultSessionWindowSize; // Inform our manager about non-default settings: - manager.setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params)); + manager->setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params)); const Http2::RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, quint32(3)}}; ServerPtr srv(newServer(serverSettings, defaultConnectionType(), params)); @@ -317,6 +333,7 @@ void tst_Http2::flowControlClientSide() sendRequest(i); runEventLoop(120000); + STOP_ON_FAILURE QVERIFY(nRequests == 0); QVERIFY(prefaceOK); @@ -357,6 +374,7 @@ void tst_Http2::flowControlServerSide() sendRequest(i, QNetworkRequest::NormalPriority, payload); runEventLoop(120000); + STOP_ON_FAILURE QVERIFY(nRequests == 0); QVERIFY(prefaceOK); @@ -377,7 +395,7 @@ void tst_Http2::pushPromise() Http2::ProtocolParameters params; // Defaults are good, except ENABLE_PUSH: params.settingsFrameData[Settings::ENABLE_PUSH_ID] = 1; - manager.setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params)); + manager->setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params)); ServerPtr srv(newServer(defaultServerSettings, defaultConnectionType(), params)); srv->enablePushPromise(true, QByteArray("/script.js")); @@ -393,12 +411,13 @@ void tst_Http2::pushPromise() QNetworkRequest request(url); request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true)); - auto reply = manager.get(request); + auto reply = manager->get(request); connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); // Since we're using self-signed certificates, ignore SSL errors: reply->ignoreSslErrors(); runEventLoop(); + STOP_ON_FAILURE QVERIFY(nRequests == 0); QVERIFY(prefaceOK); @@ -416,7 +435,7 @@ void tst_Http2::pushPromise() url.setPath("/script.js"); QNetworkRequest promisedRequest(url); promisedRequest.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true)); - reply = manager.get(promisedRequest); + reply = manager->get(promisedRequest); connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); reply->ignoreSslErrors(); @@ -467,7 +486,7 @@ void tst_Http2::goaway() url.setPath(QString("/%1").arg(i)); QNetworkRequest request(url); request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true)); - replies[i] = manager.get(request); + replies[i] = manager->get(request); QCOMPARE(replies[i]->error(), QNetworkReply::NoError); void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = &QNetworkReply::error; @@ -477,6 +496,7 @@ void tst_Http2::goaway() } runEventLoop(5000 + responseTimeoutMS); + STOP_ON_FAILURE // No request processed, no 'replyFinished' slot calls: QCOMPARE(nRequests, 0); @@ -520,12 +540,134 @@ void tst_Http2::earlyResponse() sendRequest(1, QNetworkRequest::NormalPriority, {1000000, Qt::Uninitialized}); runEventLoop(); + STOP_ON_FAILURE QVERIFY(nRequests == 0); QVERIFY(prefaceOK); QVERIFY(serverGotSettingsACK); } +void tst_Http2::connectToHost_data() +{ + // The attribute to set on a new request: + QTest::addColumn("requestAttribute"); + // The corresponding (to the attribute above) connection type the + // server will use: + QTest::addColumn("connectionType"); + +#if QT_CONFIG(ssl) + QTest::addRow("encrypted-h2-direct") << QNetworkRequest::Http2DirectAttribute << H2Type::h2Direct; + if (!clearTextHTTP2) + QTest::addRow("encrypted-h2-ALPN") << QNetworkRequest::HTTP2AllowedAttribute << H2Type::h2Alpn; +#endif // QT_CONFIG(ssl) + // This works for all configurations, tests 'preconnect-http' scheme: + // h2 with protocol upgrade is not working for now (the logic is a bit + // complicated there ...). + QTest::addRow("h2-direct") << QNetworkRequest::Http2DirectAttribute << H2Type::h2cDirect; +} + +void tst_Http2::connectToHost() +{ + // QNetworkAccessManager::connectToHostEncrypted() and connectToHost() + // creates a special request with 'preconnect-https' or 'preconnect-http' + // schemes. At the level of the protocol handler we are supposed to report + // these requests as finished and wait for the real requests. This test will + // connect to a server with the first reply 'finished' signal meaning we + // indeed connected. At this point we check that a client preface was not + // sent yet, and no response received. Then we send the second (the real) + // request and do our usual checks. Since our server closes its listening + // socket on the first incoming connection (would not accept a new one), + // the successful completion of the second requests also means we were able + // to find a cached connection and re-use it. + + QFETCH(const QNetworkRequest::Attribute, requestAttribute); + QFETCH(const H2Type, connectionType); + + clearHTTP2State(); + + serverPort = 0; + nRequests = 2; + + ServerPtr targetServer(newServer(defaultServerSettings, connectionType)); + +#if QT_CONFIG(ssl) + Q_ASSERT(!clearTextHTTP2 || connectionType != H2Type::h2Alpn); +#else + Q_ASSERT(connectionType == H2Type::h2c || connectionType == H2Type::h2cDirect); + Q_ASSERT(targetServer->isClearText()); +#endif // QT_CONFIG(ssl) + + QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection); + runEventLoop(); + + QVERIFY(serverPort != 0); + + auto url = requestUrl(connectionType); + url.setPath("/index.html"); + + QNetworkReply *reply = nullptr; + // Here some mess with how we create this first reply: +#if QT_CONFIG(ssl) + if (!targetServer->isClearText()) { + // Let's emulate what QNetworkAccessManager::connectToHostEncrypted() does. + // Alas, we cannot use it directly, since it does not return the reply and + // also does not know the difference between H2 with ALPN or direct. + auto copyUrl = url; + copyUrl.setScheme(QLatin1String("preconnect-https")); + QNetworkRequest request(copyUrl); + request.setAttribute(requestAttribute, true); + reply = manager->get(request); + // Since we're using self-signed certificates, ignore SSL errors: + reply->ignoreSslErrors(); + } else +#endif // QT_CONFIG(ssl) + { + // Emulating what QNetworkAccessManager::connectToHost() does with + // additional information that it cannot provide (the attribute). + auto copyUrl = url; + copyUrl.setScheme(QLatin1String("preconnect-http")); + QNetworkRequest request(copyUrl); + request.setAttribute(requestAttribute, true); + reply = manager->get(request); + } + + connect(reply, &QNetworkReply::finished, [this, reply]() { + --nRequests; + eventLoop.exitLoop(); + QCOMPARE(reply->error(), QNetworkReply::NoError); + QVERIFY(reply->isFinished()); + // Nothing must be sent yet: + QVERIFY(!prefaceOK); + QVERIFY(!serverGotSettingsACK); + // Nothing received back: + QVERIFY(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).isNull()); + QCOMPARE(reply->readAll().size(), 0); + }); + + runEventLoop(); + STOP_ON_FAILURE + + QCOMPARE(nRequests, 1); + + QNetworkRequest request(url); + request.setAttribute(requestAttribute, QVariant(true)); + reply = manager->get(request); + connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); + // Note, unlike the first request, when the connection is ecnrytped, we + // do not ignore TLS errors on this reply - we should re-use existing + // connection, there TLS errors were already ignored. + + runEventLoop(); + STOP_ON_FAILURE + + QVERIFY(nRequests == 0); + QVERIFY(prefaceOK); + QVERIFY(serverGotSettingsACK); + + QCOMPARE(reply->error(), QNetworkReply::NoError); + QVERIFY(reply->isFinished()); +} + void tst_Http2::serverStarted(quint16 port) { serverPort = port; @@ -537,7 +679,7 @@ void tst_Http2::clearHTTP2State() windowUpdates = 0; prefaceOK = false; serverGotSettingsACK = false; - manager.setProperty(Http2::http2ParametersPropertyName, QVariant()); + manager->setProperty(Http2::http2ParametersPropertyName, QVariant()); } void tst_Http2::runEventLoop(int ms) @@ -590,9 +732,9 @@ void tst_Http2::sendRequest(int streamNumber, QNetworkReply *reply = nullptr; if (payload.size()) - reply = manager.post(request, payload); + reply = manager->post(request, payload); else - reply = manager.get(request); + reply = manager->get(request); reply->ignoreSslErrors(); connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); @@ -684,14 +826,29 @@ void tst_Http2::replyFinished() QVERIFY(nRequests); if (const auto reply = qobject_cast(sender())) { + if (reply->error() != QNetworkReply::NoError) + stopEventLoop(); + QCOMPARE(reply->error(), QNetworkReply::NoError); + const QVariant http2Used(reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute)); + if (!http2Used.isValid() || !http2Used.toBool()) + stopEventLoop(); + QVERIFY(http2Used.isValid()); QVERIFY(http2Used.toBool()); + const QVariant spdyUsed(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute)); + if (!spdyUsed.isValid() || spdyUsed.toBool()) + stopEventLoop(); + QVERIFY(spdyUsed.isValid()); QVERIFY(!spdyUsed.toBool()); + const QVariant code(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute)); + if (!code.isValid() || !code.canConvert() || code.value() != 200) + stopEventLoop(); + QVERIFY(code.isValid()); QVERIFY(code.canConvert()); QCOMPARE(code.value(), 200); @@ -709,6 +866,8 @@ void tst_Http2::replyFinishedWithError() if (const auto reply = qobject_cast(sender())) { // For now this is a 'generic' code, it just verifies some error was // reported without testing its type. + if (reply->error() == QNetworkReply::NoError) + stopEventLoop(); QVERIFY(reply->error() != QNetworkReply::NoError); } diff --git a/tests/auto/network/access/qabstractnetworkcache/BLACKLIST b/tests/auto/network/access/qabstractnetworkcache/BLACKLIST index 2ad52f8b31f..12f45f0e129 100644 --- a/tests/auto/network/access/qabstractnetworkcache/BLACKLIST +++ b/tests/auto/network/access/qabstractnetworkcache/BLACKLIST @@ -1,2 +1,2 @@ [cacheControl] -windows +windows-10 msvc-2015 diff --git a/tests/auto/network/access/qftp/BLACKLIST b/tests/auto/network/access/qftp/BLACKLIST index 96d9274653b..463030a0892 100644 --- a/tests/auto/network/access/qftp/BLACKLIST +++ b/tests/auto/network/access/qftp/BLACKLIST @@ -6,5 +6,16 @@ redhatenterpriselinuxworkstation-6.6 [activeMode:WithoutProxyWithSession] redhatenterpriselinuxworkstation-6.6 +[list] +ubuntu-16.04 +opensuse-leap +osx-10.11 +windows-7sp1 +ubuntu-18.04 +osx-10.14 +b2qt +osx-10.12 +windows-10 msvc-2015 +opensuse-42.3 [list:epsvNotSupported] * diff --git a/tests/auto/network/access/qftp/tst_qftp.cpp b/tests/auto/network/access/qftp/tst_qftp.cpp index a04c2ae01d3..2068738a67a 100644 --- a/tests/auto/network/access/qftp/tst_qftp.cpp +++ b/tests/auto/network/access/qftp/tst_qftp.cpp @@ -134,8 +134,8 @@ private: bool fileExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &file, const QString &cdDir = QString() ); bool dirExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &cdDir, const QString &dirToCreate ); - void renameInit( bool &isSuccess, const QString &host, const QString &user, const QString &password, const QString &createFile ); - void renameCleanup( bool &isSuccess, const QString &host, const QString &user, const QString &password, const QString &fileToDelete ); + void renameInit( const QString &host, const QString &user, const QString &password, const QString &createFile ); + void renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete ); QFtp *ftp; #ifndef QT_NO_BEARERMANAGEMENT @@ -336,11 +336,7 @@ static QByteArray msgTimedOut(const QString &host, quint16 port = 0) result += ':'; result += QByteArray::number(port); } - - if (host == QtNetworkSettings::ftpServerName()) - return "(QTBUG-75549) Flaky results: " % result; - else - return result; + return result; } void tst_QFtp::connectToHost() @@ -355,7 +351,7 @@ void tst_QFtp::connectToHost() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); QTEST( connectToHost_state, "state" ); @@ -438,7 +434,7 @@ void tst_QFtp::login() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); ResMapIt it = resultMap.find( QFtp::Login ); QVERIFY( it != resultMap.end() ); @@ -486,7 +482,7 @@ void tst_QFtp::close() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); QCOMPARE( close_state, (int)QFtp::Unconnected ); @@ -554,7 +550,7 @@ void tst_QFtp::list() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); ResMapIt it = resultMap.find( QFtp::List ); QVERIFY( it != resultMap.end() ); @@ -615,7 +611,7 @@ void tst_QFtp::cd() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) { - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); } ResMapIt it = resultMap.find( QFtp::Cd ); @@ -692,7 +688,7 @@ void tst_QFtp::get() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); ResMapIt it = resultMap.find( QFtp::Get ); QVERIFY( it != resultMap.end() ); @@ -819,7 +815,7 @@ void tst_QFtp::put() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); it = resultMap.find( QFtp::Put ); QVERIFY( it != resultMap.end() ); @@ -852,7 +848,7 @@ void tst_QFtp::put() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); QCOMPARE( done_success, 1 ); QTEST( buf.buffer(), "fileData" ); @@ -870,7 +866,7 @@ void tst_QFtp::put() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); it = resultMap.find( QFtp::Remove ); QVERIFY( it != resultMap.end() ); @@ -934,7 +930,7 @@ void tst_QFtp::mkdir() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); ResMapIt it = resultMap.find( QFtp::Mkdir ); QVERIFY( it != resultMap.end() ); @@ -959,7 +955,7 @@ void tst_QFtp::mkdir() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); it = resultMap.find( QFtp::Mkdir ); QVERIFY( it != resultMap.end() ); @@ -979,7 +975,7 @@ void tst_QFtp::mkdir() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); it = resultMap.find( QFtp::Rmdir ); QVERIFY( it != resultMap.end() ); @@ -1077,9 +1073,8 @@ void tst_QFtp::rename_data() << 0; } -void tst_QFtp::renameInit( bool &isSuccess, const QString &host, const QString &user, const QString &password, const QString &createFile ) +void tst_QFtp::renameInit( const QString &host, const QString &user, const QString &password, const QString &createFile ) { - isSuccess = false; if ( !createFile.isNull() ) { // upload the file init(); @@ -1093,7 +1088,7 @@ void tst_QFtp::renameInit( bool &isSuccess, const QString &host, const QString & delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host) ); + QFAIL( msgTimedOut(host) ); ResMapIt it = resultMap.find( QFtp::Put ); QVERIFY( it != resultMap.end() ); @@ -1101,12 +1096,10 @@ void tst_QFtp::renameInit( bool &isSuccess, const QString &host, const QString & QVERIFY( fileExists( host, 21, user, password, createFile ) ); } - isSuccess = true; } -void tst_QFtp::renameCleanup( bool &isSuccess, const QString &host, const QString &user, const QString &password, const QString &fileToDelete ) +void tst_QFtp::renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete ) { - isSuccess = false; if ( !fileToDelete.isNull() ) { // cleanup (i.e. remove the file) init(); @@ -1120,7 +1113,7 @@ void tst_QFtp::renameCleanup( bool &isSuccess, const QString &host, const QStrin delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host) ); + QFAIL( msgTimedOut(host) ); ResMapIt it = resultMap.find( QFtp::Remove ); QVERIFY( it != resultMap.end() ); @@ -1128,7 +1121,6 @@ void tst_QFtp::renameCleanup( bool &isSuccess, const QString &host, const QStrin QVERIFY( !fileExists( host, 21, user, password, fileToDelete ) ); } - isSuccess = true; } void tst_QFtp::rename() @@ -1151,10 +1143,7 @@ void tst_QFtp::rename() if(renamedFile.contains('%')) renamedFile = renamedFile.arg(uniqueExtension); - bool isSuccess = true; - renameInit(isSuccess, host, user, password, createFile); - if (!isSuccess) - QSKIP("(QTBUG-75549) abort test when there is an error in helper functions"); + renameInit( host, user, password, createFile ); init(); ftp = newFtp(); @@ -1169,7 +1158,7 @@ void tst_QFtp::rename() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host) ); + QFAIL( msgTimedOut(host) ); ResMapIt it = resultMap.find( QFtp::Rename ); QVERIFY( it != resultMap.end() ); @@ -1184,9 +1173,7 @@ void tst_QFtp::rename() QVERIFY( !fileExists( host, 21, user, password, renamedFile ) ); } - renameCleanup(isSuccess, host, user, password, renamedFile); - if (!isSuccess) - QSKIP("(QTBUG-75549) abort test when there is an error in helper functions"); + renameCleanup( host, user, password, renamedFile ); } /* @@ -1360,7 +1347,7 @@ void tst_QFtp::commandSequence() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host) ); + QFAIL( msgTimedOut(host) ); QTEST( commandSequence_success, "success" ); } @@ -1415,7 +1402,7 @@ void tst_QFtp::abort() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); ResMapIt it = resultMap.find( cmd ); QVERIFY( it != resultMap.end() ); @@ -1453,7 +1440,7 @@ void tst_QFtp::abort() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); it = resultMap.find( QFtp::Remove ); QVERIFY( it != resultMap.end() ); @@ -1491,11 +1478,8 @@ void tst_QFtp::bytesAvailable() addCommand( QFtp::Close, ftp->close() ); QTestEventLoop::instance().enterLoop( 40 ); - if ( QTestEventLoop::instance().timeout() ) { - delete ftp; - ftp = 0; - QSKIP( msgTimedOut(host) ); - } + if ( QTestEventLoop::instance().timeout() ) + QFAIL( msgTimedOut(host) ); ResMapIt it = resultMap.find( QFtp::Get ); QVERIFY( it != resultMap.end() ); @@ -1588,7 +1572,7 @@ void tst_QFtp::proxy() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) { - QSKIP( msgTimedOut(host, port) ); + QFAIL( msgTimedOut(host, port) ); } ResMapIt it = resultMap.find( QFtp::Cd ); @@ -1623,7 +1607,7 @@ void tst_QFtp::binaryAscii() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(QtNetworkSettings::ftpServerName()) ); + QFAIL( msgTimedOut(QtNetworkSettings::ftpServerName()) ); ResMapIt it = resultMap.find(QFtp::Put); QVERIFY(it != resultMap.end()); @@ -1645,7 +1629,7 @@ void tst_QFtp::binaryAscii() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(QtNetworkSettings::ftpServerName()) ); + QFAIL( msgTimedOut(QtNetworkSettings::ftpServerName()) ); ResMapIt it2 = resultMap.find(QFtp::Get); QVERIFY(it2 != resultMap.end()); @@ -1668,7 +1652,7 @@ void tst_QFtp::binaryAscii() delete ftp; ftp = 0; if ( QTestEventLoop::instance().timeout() ) - QSKIP( msgTimedOut(QtNetworkSettings::ftpServerName()) ); + QFAIL( msgTimedOut(QtNetworkSettings::ftpServerName()) ); it = resultMap.find( QFtp::Remove ); QVERIFY( it != resultMap.end() ); @@ -2100,7 +2084,7 @@ void tst_QFtp::doneSignal() connect(&ftp, SIGNAL(done(bool)), &(QTestEventLoop::instance()), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(61); if (QTestEventLoop::instance().timeout()) - QSKIP( msgTimedOut(QtNetworkSettings::ftpServerName()) ); + QFAIL("Network operation timed out"); QCOMPARE(spy.count(), 1); QCOMPARE(spy.first().first().toBool(), false); diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST index 4d29a830e9c..f9bbdd96c33 100644 --- a/tests/auto/network/access/qnetworkreply/BLACKLIST +++ b/tests/auto/network/access/qnetworkreply/BLACKLIST @@ -1,47 +1,249 @@ # See qtbase/src/testlib/qtestblacklist.cpp for format -osx [authenticationCacheAfterCancel] -windows +windows-10 msvc-2017 +windows-10 msvc-2015 +osx-10.13 +windows-7sp1 [httpAbort] -* +ubuntu-16.04 +rhel-7.6 +[backgroundRequestInterruption] +ubuntu-16.04 +opensuse-leap +ubuntu-18.04 +b2qt +osx-10.12 +windows-10 msvc-2015 +opensuse-42.3 [backgroundRequestInterruption:ftp, bg, nobg] * +[getErrors] +osx-10.13 +# QTBUG-71953 [getErrors:ftp-host] linux # QTBUG-71953 +[getFromHttp] +rhel-6.6 +ubuntu-16.04 +rhel-7.6 +opensuse-leap +osx-10.11 +osx-10.13 +windows-7sp1 +ubuntu-18.04 +osx-10.14 +rhel-7.4 +b2qt +windows-10 msvc-2017 +osx-10.12 +windows-10 msvc-2015 +opensuse-42.3 [getFromHttp:success-external] * [getFromHttpIntoBuffer] -windows +osx-10.12 +osx-10.13 [getFromHttpIntoBuffer2] -windows +windows-10 msvc-2015 +windows-10 msvc-2017 [headFromHttp] -windows +osx-10.13 +windows-10 msvc-2017 [ioGetFromHttpWithSocksProxy] -windows +osx-10.12 [ioPostToHttpFromSocket] -windows # QTBUG-66247 +osx-10.13 +windows-7sp1 +windows-10 msvc-2017 +osx-10.12 +windows-10 msvc-2015 [ioHttpRedirect] -windows +windows-10 msvc-2015 # QTBUG-66602 +windows-10 msvc-2017 [ioHttpRedirectMultipartPost] -* +ubuntu-16.04 +rhel-7.6 # QTBUG-66247 +opensuse-leap +osx-10.13 +ubuntu-18.04 +rhel-7.4 +b2qt +osx-10.12 +windows-10 msvc-2015 +opensuse-42.3 [ioHttpRedirectPolicy] -* +ubuntu-16.04 +opensuse-leap +windows-7sp1 +ubuntu-18.04 +b2qt +windows-10 msvc-2017 +windows-10 msvc-2015 +opensuse-42.3 [ioHttpRedirectPostPut] -linux -windows +osx-10.12 +windows-10 msvc-2015 [putToFtp] -windows ci -[putToFtpWithInvalidCredentials] -windows ci +windows-10 msvc-2017 [putWithServerClosingConnectionImmediately] -windows +osx-10.11 +osx-10.13 +windows-7sp1 +windows-10 msvc-2017 +osx-10.12 +windows-10 msvc-2015 [qtbug28035browserDoesNotLoadQtProjectOrgCorrectly] -windows -[getFromUnreachableIp] -windows msvc-2017 -[ioHttpRedirectErrors:too-many-redirects] -rhel-6.6 ci +windows-10 msvc-2015 +windows-7sp1 +[authenticationWithDifferentRealm] +osx-10.13 +[backgroundRequest] +osx-10.12 +[connectToIPv6Address] +osx-10.12 +[deleteFromHttp] +osx-10.12 +[downloadProgress] +osx-10.12 +[emitErrorForAllReplies] +osx-10.12 +[encrypted] +osx-10.13 +[ftpAuthentication] +osx-10.13 +[httpCanReadLine] +osx-10.12 +osx-10.13 +[httpRecursiveCreation] +osx-10.12 +osx-10.13 +[httpWithNoCredentialUsage] +osx-10.12 +[ignoreSslErrorsList] +osx-10.12 +osx-10.13 +[ignoreSslErrorsListWithSlot] +osx-10.12 +osx-10.13 +[ioGetFromBuiltinHttp] +osx-10.12 +osx-10.11 +osx-10.14 +osx-10.13 +[ioGetFromHttp] +osx-10.12 +[ioGetFromHttpWithAuth] +osx-10.12 +osx-10.13 +[ioGetFromHttpWithAuthSynchronous] +osx-10.12 +[ioGetFromHttpWithProxyAuth] +osx-10.12 +[ioGetFromHttpWithReuseParallel] +osx-10.12 +osx-10.13 +[ioGetFromHttpWithReuseSequential] +osx-10.12 +osx-10.13 +[ioGetFromHttpsWithIgnoreSslErrors] +osx-10.12 +[ioGetFromHttpsWithSslErrors] +osx-10.12 +[ioGetFromHttpsWithSslHandshakeError] +osx-10.12 +[ioGetWithManyProxies] +osx-10.12 +[ioPostToHttpFromFile] +osx-10.13 +[ioPostToHttpFromMiddleOfFileFiveBytes] +osx-10.13 +[ioPostToHttpFromMiddleOfFileToEnd] +osx-10.13 +[ioPostToHttpFromMiddleOfQBufferFiveBytes] +osx-10.13 +[ioPostToHttpFromSocketSynchronous] +osx-10.12 +osx-10.13 +[ioPostToHttpNoBufferFlag] +osx-10.13 +[ioPostToHttpUploadProgress] +osx-10.12 +osx-10.11 +osx-10.13 +[ioPutToHttpFromFile] +osx-10.13 +[lastModifiedHeaderForHttp] +osx-10.12 +osx-10.13 +[multipartSkipIndices] +osx-10.12 +osx-10.13 +[nestedEventLoops] +osx-10.12 +osx-10.13 +[pipelining] +osx-10.13 +[postToHttp] +osx-10.12 +osx-10.13 +[postToHttpMultipart] +osx-10.12 +osx-10.13 +[postToHttpSynchronous] +osx-10.12 +osx-10.13 +[postToHttps] +osx-10.12 +osx-10.13 +[postToHttpsMultipart] +osx-10.12 +osx-10.13 +[postToHttpsSynchronous] +osx-10.12 +osx-10.13 +[putGetDeleteGetFromHttp] +osx-10.12 +[putToHttp] +osx-10.12 +osx-10.13 +[putToHttpSynchronous] +osx-10.12 +osx-10.13 +[putToHttps] +osx-10.12 +osx-10.13 +[putToHttpsSynchronous] +osx-10.12 +osx-10.13 +[putWithRateLimiting] +osx-10.12 +osx-10.13 +[qtbug13431replyThrottling] +osx-10.12 +[receiveCookiesFromHttp] +osx-10.12 +osx-10.13 +[receiveCookiesFromHttpSynchronous] +osx-10.12 +osx-10.13 +[sendCookies] +osx-10.12 +osx-10.13 +[sendCookiesSynchronous] +osx-10.12 +osx-10.13 +[sendCustomRequestToHttp] +osx-10.12 +[sslConfiguration] +osx-10.12 +osx-10.13 +[synchronousRequest] +osx-10.12 +osx-10.13 +[backgroundRequestConnectInBackground] +osx-10.12 +osx-10.13 diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 1afd8af7b04..418e1caf687 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -6426,7 +6426,8 @@ void tst_QNetworkReply::abortOnEncrypted() QSKIP("Server fails to listen. Skipping since QTcpServer is covered in another test."); server.connect(&server, &SslServer::newEncryptedConnection, [&server]() { - connect(server.socket, &QTcpSocket::readyRead, server.socket, []() { + // MSVC 201X C4573-misunderstands connect() or QObject::connect(), so use server.connect(): + server.connect(server.socket, &QTcpSocket::readyRead, server.socket, []() { // This slot must not be invoked! QVERIFY(false); }); @@ -6474,8 +6475,8 @@ void tst_QNetworkReply::sslSessionSharing_data() void tst_QNetworkReply::sslSessionSharing() { -#ifdef QT_SECURETRANSPORT - QSKIP("Not implemented with SecureTransport"); +#if QT_CONFIG(schannel) || defined(QT_SECURETRANSPORT) + QSKIP("Not implemented with SecureTransport/Schannel"); #endif QString urlString("https://" + QtNetworkSettings::httpServerName()); @@ -6542,8 +6543,8 @@ void tst_QNetworkReply::sslSessionSharingFromPersistentSession_data() void tst_QNetworkReply::sslSessionSharingFromPersistentSession() { -#ifdef QT_SECURETRANSPORT - QSKIP("Not implemented with SecureTransport"); +#if QT_CONFIG(schannel) || defined(QT_SECURETRANSPORT) + QSKIP("Not implemented with SecureTransport/Schannel"); #endif QString urlString("https://" + QtNetworkSettings::httpServerName()); @@ -8200,6 +8201,9 @@ void tst_QNetworkReply::backgroundRequestInterruption_data() void tst_QNetworkReply::backgroundRequestInterruption() { #ifndef QT_NO_BEARERMANAGEMENT + if (QNetworkStatusMonitor::isEnabled() && QByteArray(QTest::currentDataTag()).startsWith("http")) + QSKIP("This test (currently) doesn't make any sense when QNetworkStatusMonitor is enabled"); + QFETCH(QUrl, url); QFETCH(bool, background); QFETCH(QNetworkReply::NetworkError, error); diff --git a/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp b/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp index 7a3def410a4..6637be0174e 100644 --- a/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp +++ b/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp @@ -41,6 +41,7 @@ class tst_QNetworkRequest: public QObject private slots: void ctor_data(); void ctor(); + void implicitDefaultCtor(); void setUrl_data(); void setUrl(); void setRawHeader_data(); @@ -78,6 +79,12 @@ void tst_QNetworkRequest::ctor() } } +void tst_QNetworkRequest::implicitDefaultCtor() +{ + QNetworkRequest r = {}; + Q_UNUSED(r); +} + void tst_QNetworkRequest::setUrl_data() { ctor_data(); diff --git a/tests/auto/network/access/spdy/BLACKLIST b/tests/auto/network/access/spdy/BLACKLIST index b13eae10008..ce2f7f383f6 100644 --- a/tests/auto/network/access/spdy/BLACKLIST +++ b/tests/auto/network/access/spdy/BLACKLIST @@ -1,4 +1,10 @@ [download] -linux +opensuse-leap +ubuntu-18.04 +ubuntu-16.04 +b2qt [upload] -linux +opensuse-leap +ubuntu-18.04 +b2qt + diff --git a/tests/auto/network/kernel/qdnslookup/BLACKLIST b/tests/auto/network/kernel/qdnslookup/BLACKLIST index edf6436384b..4461d8b5f7d 100644 --- a/tests/auto/network/kernel/qdnslookup/BLACKLIST +++ b/tests/auto/network/kernel/qdnslookup/BLACKLIST @@ -1,2 +1,12 @@ [lookup] -ci +rhel-7.6 +opensuse-leap +osx-10.13 +windows-7sp1 +ubuntu-18.04 +rhel-7.4 +b2qt +windows-10 msvc-2017 +osx-10.12 +windows-10 msvc-2015 +opensuse-42.3 diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp index 224e4d61a9f..48f05a46043 100644 --- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp +++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp @@ -375,11 +375,14 @@ QT_WARNING_DISABLE_DEPRECATED void tst_QHostAddress::assignment() { QHostAddress address; + +#if QT_DEPRECATED_SINCE(5, 8) address = "127.0.0.1"; QCOMPARE(address, QHostAddress("127.0.0.1")); address = "::1"; QCOMPARE(address, QHostAddress("::1")); +#endif // WinRT does not support sockaddr_in #ifndef Q_OS_WINRT diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp index da6e02210be..a603b2d879c 100644 --- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp @@ -92,6 +92,7 @@ private slots: void lookupIPv6(); void lookupConnectToFunctionPointer_data(); void lookupConnectToFunctionPointer(); + void lookupConnectToFunctionPointerDeleted(); void lookupConnectToLambda_data(); void lookupConnectToLambda(); void reverseLookup_data(); @@ -358,6 +359,17 @@ void tst_QHostInfo::lookupConnectToFunctionPointer() QCOMPARE(tmp.join(' '), expected.join(' ')); } +void tst_QHostInfo::lookupConnectToFunctionPointerDeleted() +{ + { + QObject contextObject; + QHostInfo::lookupHost("localhost", &contextObject, [](const QHostInfo){ + QFAIL("This should never be called!"); + }); + } + QTestEventLoop::instance().enterLoop(3); +} + void tst_QHostInfo::lookupConnectToLambda_data() { lookupIPv4_data(); @@ -464,7 +476,9 @@ void tst_QHostInfo::reverseLookup_data() QTest::newRow("dns.google") << QString("8.8.8.8") << reverseLookupHelper("8.8.8.8") << 0 << false; QTest::newRow("one.one.one.one") << QString("1.1.1.1") << reverseLookupHelper("1.1.1.1") << 0 << false; - QTest::newRow("bogus-name") << QString("1::2::3::4") << QStringList() << 1 << true; + QTest::newRow("dns.google IPv6") << QString("2001:4860:4860::8888") << reverseLookupHelper("2001:4860:4860::8888") << 0 << true; + QTest::newRow("cloudflare IPv6") << QString("2606:4700:4700::1111") << reverseLookupHelper("2606:4700:4700::1111") << 0 << true; + QTest::newRow("bogus-name IPv6") << QString("1::2::3::4") << QStringList() << 1 << true; } void tst_QHostInfo::reverseLookup() @@ -705,6 +719,7 @@ void tst_QHostInfo::cache() void tst_QHostInfo::resultsReady(const QHostInfo &hi) { + QVERIFY(QThread::currentThread() == thread()); lookupDone = true; lookupResults = hi; lookupsDoneCounter++; diff --git a/tests/auto/network/socket/platformsocketengine/BLACKLIST b/tests/auto/network/socket/platformsocketengine/BLACKLIST index 154c5cc5b22..f1f88d26d17 100644 --- a/tests/auto/network/socket/platformsocketengine/BLACKLIST +++ b/tests/auto/network/socket/platformsocketengine/BLACKLIST @@ -1,8 +1,11 @@ [tcpLoopbackPerformance] -windows +windows-10 msvc-2015 +windows-7sp1 [receiveUrgentData] -windows +windows-10 msvc-2015 +windows-7sp1 [serverTest] -windows +windows-10 msvc-2015 +windows-7sp1 [tcpLoopbackPerformance] windows diff --git a/tests/auto/network/socket/qhttpsocketengine/BLACKLIST b/tests/auto/network/socket/qhttpsocketengine/BLACKLIST index 991d01dd00b..ceb3b7862e5 100644 --- a/tests/auto/network/socket/qhttpsocketengine/BLACKLIST +++ b/tests/auto/network/socket/qhttpsocketengine/BLACKLIST @@ -1,6 +1,5 @@ -[passwordAuth] -windows [downloadBigFile] -windows +windows-10 msvc-2015 +windows-7sp1 [ensureEofTriggersNotification] windows diff --git a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST index 8af3cea8dcd..f769aafbdd7 100644 --- a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST +++ b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST @@ -1,11 +1,12 @@ [udpTest] * [passwordAuth] -* +ubuntu-18.04 # QTBUG-74162 [passwordAuth2] -* -[serverTest] -windows +osx-10.12 +ubuntu-18.04 [downloadBigFile] -windows +windows-10 msvc-2015 +windows-7sp1 + diff --git a/tests/auto/network/socket/qtcpserver/BLACKLIST b/tests/auto/network/socket/qtcpserver/BLACKLIST index f8b61808cc5..ad0edf0af13 100644 --- a/tests/auto/network/socket/qtcpserver/BLACKLIST +++ b/tests/auto/network/socket/qtcpserver/BLACKLIST @@ -1,13 +1,24 @@ -windows -[linkLocal] -linux +[listenWhileListening] +windows-10 msvc-2015 [listenWhileListening:WithSocks5Proxy] linux windows +[ipv6Server] +windows-10 msvc-2015 +windows-7sp1 +windows-10 msvc-2017 [ipv6Server:WithoutProxy] windows osx -[clientServerLoop:WithSocks5Proxy] -linux -[crashTests:WithSocks5Proxy] -linux +[addressReusable] +windows-10 msvc-2015 +[eagainBlockingAccept] +windows-10 msvc-2015 +windows-7sp1 +windows-10 msvc-2017 +[proxyFactory] +windows-7sp1 +[serverAddress] +windows-10 msvc-2017 +windows-10 msvc-2015 +windows-7sp1 diff --git a/tests/auto/network/socket/qtcpsocket/BLACKLIST b/tests/auto/network/socket/qtcpsocket/BLACKLIST index d724897b74b..8c2f8d26388 100644 --- a/tests/auto/network/socket/qtcpsocket/BLACKLIST +++ b/tests/auto/network/socket/qtcpsocket/BLACKLIST @@ -1,13 +1,14 @@ -[bindThenResolveHost:first-fail] -windows +[bind] +windows-10 msvc-2015 +windows-7sp1 [bind:[::]] windows [bind:[::]:randomport] windows -[invalidProxy:socks5-on-http] -windows +[timeoutConnect] +windows-10 msvc-2015 +# QTBUG-66247 [timeoutConnect:ip] windows # QTBUG-66247 -[taskQtBug5799ConnectionErrorEventLoop] -windows + diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 7733b0a62b6..75b9b232599 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -164,9 +164,8 @@ private slots: void waitForReadyReadInASlot(); void remoteCloseError(); void nestedEventLoopInErrorSlot(); -#ifndef Q_OS_WIN - void connectToLocalHostNoService(); -#endif + void connectToHostError_data(); + void connectToHostError(); void waitForConnectedInHostLookupSlot(); void waitForConnectedInHostLookupSlot2(); void readyReadSignalsAfterWaitForReadyRead(); @@ -2066,18 +2065,38 @@ void tst_QTcpSocket::nestedEventLoopInErrorSlot() } //---------------------------------------------------------------------------------- -#ifndef Q_OS_WIN -void tst_QTcpSocket::connectToLocalHostNoService() + +void tst_QTcpSocket::connectToHostError_data() +{ + QTest::addColumn("host"); + QTest::addColumn("port"); + QTest::addColumn("expectedError"); + + QTest::newRow("localhost no service") << QStringLiteral("localhost") << 31415 << QAbstractSocket::ConnectionRefusedError; + QTest::newRow("unreachable") << QStringLiteral("0.0.0.1") << 65000 << QAbstractSocket::NetworkError; +} + + +void tst_QTcpSocket::connectToHostError() { - // This test was created after we received a report that claimed - // QTcpSocket would crash if trying to connect to "localhost" on a random - // port with no service listening. QTcpSocket *socket = newSocket(); - socket->connectToHost("localhost", 31415); // no service running here, one suspects + + QAbstractSocket::SocketError error = QAbstractSocket::UnknownSocketError; + + QFETCH(QString, host); + QFETCH(int, port); + QFETCH(QAbstractSocket::SocketError, expectedError); + + connect(socket, QOverload::of(&QAbstractSocket::error),[&](QAbstractSocket::SocketError socketError){ + error = socketError; + }); + socket->connectToHost(host, port); // no service running here, one suspects QTRY_COMPARE(socket->state(), QTcpSocket::UnconnectedState); + if (error != expectedError && error == QAbstractSocket::ConnectionRefusedError) + QEXPECT_FAIL("unreachable", "CI firewall interfers with this test", Continue); + QCOMPARE(error, expectedError); delete socket; } -#endif //---------------------------------------------------------------------------------- void tst_QTcpSocket::waitForConnectedInHostLookupSlot() diff --git a/tests/auto/network/socket/qudpsocket/BLACKLIST b/tests/auto/network/socket/qudpsocket/BLACKLIST index 0d56f6c8270..9b5aa8a3fc3 100644 --- a/tests/auto/network/socket/qudpsocket/BLACKLIST +++ b/tests/auto/network/socket/qudpsocket/BLACKLIST @@ -1,26 +1,16 @@ [writeDatagramToNonExistingPeer] -windows -osx -[asyncReadDatagram] -osx +windows-10 msvc-2017 +windows-10 msvc-2015 +windows-7sp1 [multicastLeaveAfterClose] -osx -[readyRead] -osx +osx-10.12 +osx-10.11 [readyReadForEmptyDatagram] -osx +opensuse-leap +ubuntu-16.04 [echo] -linux -osx +opensuse-42.3 [ipv6Loop] -osx -[loop] -osx -[broadcasting] -osx -[zeroLengthDatagram] -osx -[linkLocalIPv6] -linux +osx-10.12 [readyReadForEmptyDatagram] linux diff --git a/tests/auto/network/socket/qudpsocket/clientserver/main.cpp b/tests/auto/network/socket/qudpsocket/clientserver/main.cpp index cc3e90671aa..8172cd4f6f6 100644 --- a/tests/auto/network/socket/qudpsocket/clientserver/main.cpp +++ b/tests/auto/network/socket/qudpsocket/clientserver/main.cpp @@ -54,7 +54,7 @@ public: printf("ok\n"); break; case UnconnectedClient: - peerAddress = host; + peerAddress = QHostAddress(host); peerPort = port; if (bind(QHostAddress::Any, port + 1, ShareAddress | ReuseAddressHint)) { startTimer(250); diff --git a/tests/auto/network/ssl/qsslcertificate/BLACKLIST b/tests/auto/network/ssl/qsslcertificate/BLACKLIST index 25509a5ca8f..9494ee22783 100644 --- a/tests/auto/network/ssl/qsslcertificate/BLACKLIST +++ b/tests/auto/network/ssl/qsslcertificate/BLACKLIST @@ -1,3 +1,13 @@ # OpenSSL version is too new. Rich will fix :) [subjectAndIssuerAttributes] -* +ubuntu-16.04 +rhel-7.6 +opensuse-leap +windows-7sp1 +ubuntu-18.04 +rhel-7.4 +b2qt +windows-10 msvc-2017 +windows-10 msvc-2015 +opensuse-42.3 + diff --git a/tests/auto/network/ssl/qsslkey/BLACKLIST b/tests/auto/network/ssl/qsslkey/BLACKLIST index f9bc0af6ded..e9723001f5d 100644 --- a/tests/auto/network/ssl/qsslkey/BLACKLIST +++ b/tests/auto/network/ssl/qsslkey/BLACKLIST @@ -1,2 +1,16 @@ -redhatenterpriselinuxworkstation -rhel +[constructor] +rhel-6.6 +rhel-7.4 +rhel-7.6 +[length] +rhel-6.6 +rhel-7.4 +rhel-7.6 +[toEncryptedPemOrDer] +rhel-6.6 +rhel-7.4 +rhel-7.6 +[toPemOrDer] +rhel-6.6 +rhel-7.4 +rhel-7.6 diff --git a/tests/auto/network/ssl/qsslsocket/BLACKLIST b/tests/auto/network/ssl/qsslsocket/BLACKLIST index 3ecd3d9dbb8..36143691c9d 100644 --- a/tests/auto/network/ssl/qsslsocket/BLACKLIST +++ b/tests/auto/network/ssl/qsslsocket/BLACKLIST @@ -1,23 +1,15 @@ [abortOnSslErrors] -windows +windows-10 msvc-2015 [deprecatedProtocols] windows -[disabledProtocols] -windows -[protocol] -windows -[qtbug18498_peek] -windows -[setReadBufferSize] -windows [spontaneousWrite] -windows +windows-7sp1 [sslErrors] -windows +windows-7sp1 [connectToHostEncrypted] osx-10.13 [setSslConfiguration] -windows -osx-10.13 +windows-10 msvc-2015 +windows-7sp1 [connectToHostEncryptedWithVerificationPeerName] osx-10.13 diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index 4035dfbf5f1..4e023203626 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -546,6 +546,7 @@ void tst_QSslSocket::constructing() // verify that changing the default config doesn't affect this socket // (on Unix, the ca certs might be empty, depending on whether we load // them on demand or not, so set them explicitly) +#if QT_DEPRECATED_SINCE(5, 5) socket.setCaCertificates(QSslSocket::systemCaCertificates()); QSslSocket::setDefaultCaCertificates(QList()); QSslSocket::setDefaultCiphers(QList()); @@ -556,6 +557,25 @@ void tst_QSslSocket::constructing() QVERIFY(QSslConfiguration::defaultConfiguration().caCertificates().isEmpty()); QVERIFY(QSslConfiguration::defaultConfiguration().ciphers().isEmpty()); + QSslConfiguration::setDefaultConfiguration(savedDefault); +#endif + + auto sslConfig = socket.sslConfiguration(); + sslConfig.setCaCertificates(QSslConfiguration::systemCaCertificates()); + socket.setSslConfiguration(sslConfig); + + auto defaultConfig = QSslConfiguration::defaultConfiguration(); + defaultConfig.setCaCertificates(QList()); + defaultConfig.setCiphers(QList()); + QSslConfiguration::setDefaultConfiguration(defaultConfig); + + QVERIFY(!socket.sslConfiguration().caCertificates().isEmpty()); + QVERIFY(!socket.sslConfiguration().ciphers().isEmpty()); + + // verify the default as well: + QVERIFY(QSslConfiguration::defaultConfiguration().caCertificates().isEmpty()); + QVERIFY(QSslConfiguration::defaultConfiguration().ciphers().isEmpty()); + QSslConfiguration::setDefaultConfiguration(savedDefault); } @@ -756,18 +776,41 @@ void tst_QSslSocket::ciphers() { if (!QSslSocket::supportsSsl()) return; +#if QT_DEPRECATED_SINCE(5, 5) + { + QSslSocket socket; + QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers()); + socket.setCiphers(QList()); + QVERIFY(socket.ciphers().isEmpty()); + socket.setCiphers(socket.defaultCiphers()); + QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers()); + socket.setCiphers(socket.defaultCiphers()); + QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers()); + // Task 164356 + socket.setCiphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); + } +#endif QSslSocket socket; - QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers()); - socket.setCiphers(QList()); - QVERIFY(socket.ciphers().isEmpty()); - socket.setCiphers(socket.defaultCiphers()); - QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers()); - socket.setCiphers(socket.defaultCiphers()); - QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers()); + QCOMPARE(socket.sslConfiguration().ciphers(), QSslConfiguration::defaultConfiguration().ciphers()); + + auto sslConfig = socket.sslConfiguration(); + sslConfig.setCiphers(QList()); + socket.setSslConfiguration(sslConfig); + QVERIFY(socket.sslConfiguration().ciphers().isEmpty()); + + sslConfig.setCiphers(QSslConfiguration::defaultConfiguration().ciphers()); + socket.setSslConfiguration(sslConfig); + QCOMPARE(socket.sslConfiguration().ciphers(), QSslConfiguration::defaultConfiguration().ciphers()); + + sslConfig.setCiphers(QSslConfiguration::defaultConfiguration().ciphers()); + socket.setSslConfiguration(sslConfig); + QCOMPARE(socket.sslConfiguration().ciphers(), QSslConfiguration::defaultConfiguration().ciphers()); // Task 164356 - socket.setCiphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); + sslConfig.setCiphers({QSslCipher("ALL"), QSslCipher("!ADH"), QSslCipher("!LOW"), + QSslCipher("!EXP"), QSslCipher("!MD5"), QSslCipher("@STRENGTH")}); + socket.setSslConfiguration(sslConfig); } void tst_QSslSocket::connectToHostEncrypted() @@ -858,11 +901,14 @@ void tst_QSslSocket::sessionCipher() QSKIP("Skipping flaky test - See QTBUG-29941"); QVERIFY(!socket->sessionCipher().isNull()); - qDebug() << "Supported Ciphers:" << QSslSocket::supportedCiphers(); - qDebug() << "Default Ciphers:" << QSslSocket::defaultCiphers(); + qDebug() << "Supported Ciphers:" << QSslConfiguration::supportedCiphers(); + qDebug() << "Default Ciphers:" << QSslConfiguration::defaultConfiguration().ciphers(); qDebug() << "Session Cipher:" << socket->sessionCipher(); +#if QT_DEPRECATED_SINCE(5, 5) QVERIFY(QSslSocket::supportedCiphers().contains(socket->sessionCipher())); +#endif + QVERIFY(QSslConfiguration::supportedCiphers().contains(socket->sessionCipher())); socket->disconnectFromHost(); QVERIFY(socket->waitForDisconnected()); } @@ -886,7 +932,11 @@ void tst_QSslSocket::localCertificate() QSslSocketPtr socket = newSocket(); QList localCert = QSslCertificate::fromPath(httpServerCertChainPath()); - socket->setCaCertificates(localCert); + + auto sslConfig = socket->sslConfiguration(); + sslConfig.setCaCertificates(localCert); + socket->setSslConfiguration(sslConfig); + socket->setLocalCertificate(testDataDir + "certs/fluke.cert"); socket->setPrivateKey(testDataDir + "certs/fluke.key"); @@ -990,7 +1040,11 @@ void tst_QSslSocket::privateKeyOpaque() QSslSocketPtr socket = newSocket(); QList localCert = QSslCertificate::fromPath(httpServerCertChainPath()); - socket->setCaCertificates(localCert); + + auto sslConfig = socket->sslConfiguration(); + sslConfig.setCaCertificates(localCert); + socket->setSslConfiguration(sslConfig); + socket->setLocalCertificate(testDataDir + "certs/fluke.cert"); socket->setPrivateKey(QSslKey(reinterpret_cast(pkey))); @@ -1011,7 +1065,10 @@ void tst_QSslSocket::protocol() this->socket = socket.data(); QList certs = QSslCertificate::fromPath(httpServerCertChainPath()); - socket->setCaCertificates(certs); + auto sslConfig = socket->sslConfiguration(); + sslConfig.setCaCertificates(certs); + socket->setSslConfiguration(sslConfig); + #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND connect(socket, SIGNAL(sslErrors(QList)), this, SLOT(untrustedWorkaroundSlot(QList))); @@ -1159,7 +1216,7 @@ public: QString m_keyFile; QString m_certFile; QString m_interFile; - QString ciphers; + QList ciphers; signals: void socketError(QAbstractSocket::SocketError); @@ -1209,7 +1266,9 @@ protected: } if (!ciphers.isEmpty()) { - socket->setCiphers(ciphers); + auto sslConfig = socket->sslConfiguration(); + sslConfig.setCiphers(ciphers); + socket->setSslConfiguration(sslConfig); } QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState)); @@ -1359,7 +1418,7 @@ void tst_QSslSocket::serverCipherPreferences() // First using the default (server preference) { SslServer server; - server.ciphers = QString("AES128-SHA:AES256-SHA"); + server.ciphers = {QSslCipher("AES128-SHA"), QSslCipher("AES256-SHA")}; QVERIFY(server.listen()); QEventLoop loop; @@ -1367,7 +1426,10 @@ void tst_QSslSocket::serverCipherPreferences() QSslSocket client; socket = &client; - socket->setCiphers("AES256-SHA:AES128-SHA"); + + auto sslConfig = socket->sslConfiguration(); + sslConfig.setCiphers({QSslCipher("AES256-SHA"), QSslCipher("AES128-SHA")}); + socket->setSslConfiguration(sslConfig); // upon SSL wrong version error, error will be triggered, not sslErrors connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit())); @@ -1388,7 +1450,7 @@ void tst_QSslSocket::serverCipherPreferences() QSslConfiguration config = QSslConfiguration::defaultConfiguration(); config.setSslOption(QSsl::SslOptionDisableServerCipherPreference, true); server.config = config; - server.ciphers = QString("AES128-SHA:AES256-SHA"); + server.ciphers = {QSslCipher("AES128-SHA"), QSslCipher("AES256-SHA")}; QVERIFY(server.listen()); QEventLoop loop; @@ -1396,7 +1458,10 @@ void tst_QSslSocket::serverCipherPreferences() QSslSocket client; socket = &client; - socket->setCiphers("AES256-SHA:AES128-SHA"); + + auto sslConfig = socket->sslConfiguration(); + sslConfig.setCiphers({QSslCipher("AES256-SHA"), QSslCipher("AES128-SHA")}); + socket->setSslConfiguration(sslConfig); // upon SSL wrong version error, error will be triggered, not sslErrors connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit())); @@ -1420,12 +1485,30 @@ void tst_QSslSocket::setCaCertificates() if (!QSslSocket::supportsSsl()) return; +#if QT_DEPRECATED_SINCE(5, 5) + { + QSslSocket socket; + QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); + socket.setCaCertificates(QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem")); + QCOMPARE(socket.caCertificates().size(), 1); + socket.setCaCertificates(socket.defaultCaCertificates()); + QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); + } +#endif QSslSocket socket; - QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); - socket.setCaCertificates(QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem")); - QCOMPARE(socket.caCertificates().size(), 1); - socket.setCaCertificates(socket.defaultCaCertificates()); - QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); + QCOMPARE(socket.sslConfiguration().caCertificates(), + QSslConfiguration::defaultConfiguration().caCertificates()); + + auto sslConfig = socket.sslConfiguration(); + sslConfig.setCaCertificates( + QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem")); + socket.setSslConfiguration(sslConfig); + QCOMPARE(socket.sslConfiguration().caCertificates().size(), 1); + + sslConfig.setCaCertificates(QSslConfiguration::defaultConfiguration().caCertificates()); + socket.setSslConfiguration(sslConfig); + QCOMPARE(socket.sslConfiguration().caCertificates(), + QSslConfiguration::defaultConfiguration().caCertificates()); } void tst_QSslSocket::setLocalCertificate() @@ -1638,19 +1721,43 @@ void tst_QSslSocket::addDefaultCaCertificate() if (!QSslSocket::supportsSsl()) return; +#if QT_DEPRECATED_SINCE(5, 5) + { + // Reset the global CA chain + QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates()); + + QList flukeCerts = QSslCertificate::fromPath(httpServerCertChainPath()); + QCOMPARE(flukeCerts.size(), 1); + QList globalCerts = QSslSocket::defaultCaCertificates(); + QVERIFY(!globalCerts.contains(flukeCerts.first())); + QSslSocket::addDefaultCaCertificate(flukeCerts.first()); + QCOMPARE(QSslSocket::defaultCaCertificates().size(), globalCerts.size() + 1); + QVERIFY(QSslSocket::defaultCaCertificates().contains(flukeCerts.first())); + + // Restore the global CA chain + QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates()); + } +#endif + // Reset the global CA chain - QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates()); + auto sslConfig = QSslConfiguration::defaultConfiguration(); + sslConfig.setCaCertificates(QSslConfiguration::systemCaCertificates()); + QSslConfiguration::setDefaultConfiguration(sslConfig); QList flukeCerts = QSslCertificate::fromPath(httpServerCertChainPath()); QCOMPARE(flukeCerts.size(), 1); - QList globalCerts = QSslSocket::defaultCaCertificates(); + QList globalCerts = QSslConfiguration::defaultConfiguration().caCertificates(); QVERIFY(!globalCerts.contains(flukeCerts.first())); QSslSocket::addDefaultCaCertificate(flukeCerts.first()); - QCOMPARE(QSslSocket::defaultCaCertificates().size(), globalCerts.size() + 1); - QVERIFY(QSslSocket::defaultCaCertificates().contains(flukeCerts.first())); + QCOMPARE(QSslConfiguration::defaultConfiguration().caCertificates().size(), + globalCerts.size() + 1); + QVERIFY(QSslConfiguration::defaultConfiguration().caCertificates() + .contains(flukeCerts.first())); // Restore the global CA chain - QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates()); + sslConfig = QSslConfiguration::defaultConfiguration(); + sslConfig.setCaCertificates(QSslConfiguration::systemCaCertificates()); + QSslConfiguration::setDefaultConfiguration(sslConfig); } void tst_QSslSocket::addDefaultCaCertificates() @@ -1666,9 +1773,16 @@ void tst_QSslSocket::defaultCaCertificates() if (!QSslSocket::supportsSsl()) return; - QList certs = QSslSocket::defaultCaCertificates(); +#if QT_DEPRECATED_SINCE(5, 5) + { + QList certs = QSslSocket::defaultCaCertificates(); + QVERIFY(certs.size() > 1); + QCOMPARE(certs, QSslSocket::systemCaCertificates()); + } +#endif + QList certs = QSslConfiguration::defaultConfiguration().caCertificates(); QVERIFY(certs.size() > 1); - QCOMPARE(certs, QSslSocket::systemCaCertificates()); + QCOMPARE(certs, QSslConfiguration::systemCaCertificates()); } void tst_QSslSocket::defaultCiphers() @@ -1676,12 +1790,22 @@ void tst_QSslSocket::defaultCiphers() if (!QSslSocket::supportsSsl()) return; - QList ciphers = QSslSocket::defaultCiphers(); +#if QT_DEPRECATED_SINCE(5, 5) + { + QList ciphers = QSslSocket::defaultCiphers(); + QVERIFY(ciphers.size() > 1); + + QSslSocket socket; + QCOMPARE(socket.defaultCiphers(), ciphers); + QCOMPARE(socket.ciphers(), ciphers); + } +#endif + QList ciphers = QSslConfiguration::defaultConfiguration().ciphers(); QVERIFY(ciphers.size() > 1); QSslSocket socket; - QCOMPARE(socket.defaultCiphers(), ciphers); - QCOMPARE(socket.ciphers(), ciphers); + QCOMPARE(socket.sslConfiguration().defaultConfiguration().ciphers(), ciphers); + QCOMPARE(socket.sslConfiguration().ciphers(), ciphers); } void tst_QSslSocket::resetDefaultCiphers() @@ -1701,11 +1825,21 @@ void tst_QSslSocket::supportedCiphers() if (!QSslSocket::supportsSsl()) return; - QList ciphers = QSslSocket::supportedCiphers(); +#if QT_DEPRECATED_SINCE(5, 5) + { + QList ciphers = QSslSocket::supportedCiphers(); + QVERIFY(ciphers.size() > 1); + + QSslSocket socket; + QCOMPARE(socket.supportedCiphers(), ciphers); + } +#endif + + QList ciphers = QSslConfiguration::supportedCiphers(); QVERIFY(ciphers.size() > 1); QSslSocket socket; - QCOMPARE(socket.supportedCiphers(), ciphers); + QCOMPARE(socket.sslConfiguration().supportedCiphers(), ciphers); } void tst_QSslSocket::systemCaCertificates() @@ -1713,9 +1847,16 @@ void tst_QSslSocket::systemCaCertificates() if (!QSslSocket::supportsSsl()) return; - QList certs = QSslSocket::systemCaCertificates(); +#if QT_DEPRECATED_SINCE(5, 5) + { + QList certs = QSslSocket::systemCaCertificates(); + QVERIFY(certs.size() > 1); + QCOMPARE(certs, QSslSocket::defaultCaCertificates()); + } +#endif + QList certs = QSslConfiguration::systemCaCertificates(); QVERIFY(certs.size() > 1); - QCOMPARE(certs, QSslSocket::defaultCaCertificates()); + QCOMPARE(certs, QSslConfiguration::defaultConfiguration().systemCaCertificates()); } void tst_QSslSocket::wildcardCertificateNames() @@ -2755,7 +2896,6 @@ void tst_QSslSocket::encryptWithoutConnecting() void tst_QSslSocket::resume_data() { - QSKIP("Temporary skip while updating certificates"); QTest::addColumn("ignoreErrorsAfterPause"); QTest::addColumn >("errorsToIgnore"); QTest::addColumn("expectSuccess"); @@ -2780,7 +2920,9 @@ void tst_QSslSocket::resume() { // make sure the server certificate is not in the list of accepted certificates, // we want to trigger the sslErrors signal - QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates()); + auto sslConfig = QSslConfiguration::defaultConfiguration(); + sslConfig.setCaCertificates(QSslConfiguration::systemCaCertificates()); + QSslConfiguration::setDefaultConfiguration(sslConfig); QFETCH(bool, ignoreErrorsAfterPause); QFETCH(QList, errorsToIgnore); @@ -3100,7 +3242,7 @@ void tst_QSslSocket::dhServer() return; SslServer server; - server.ciphers = QLatin1String("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA"); + server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")}; QVERIFY(server.listen()); QEventLoop loop; @@ -3129,7 +3271,7 @@ void tst_QSslSocket::dhServerCustomParamsNull() return; SslServer server; - server.ciphers = QLatin1String("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA"); + server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")}; QSslConfiguration cfg = server.config; cfg.setDiffieHellmanParameters(QSslDiffieHellmanParameters()); @@ -3165,7 +3307,7 @@ void tst_QSslSocket::dhServerCustomParams() return; SslServer server; - server.ciphers = QLatin1String("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA"); + server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")}; QSslConfiguration cfg = server.config; @@ -3214,7 +3356,7 @@ void tst_QSslSocket::ecdhServer() return; SslServer server; - server.ciphers = QLatin1String("ECDHE-RSA-AES128-SHA"); + server.ciphers = {QSslCipher("ECDHE-RSA-AES128-SHA")}; QVERIFY(server.listen()); QEventLoop loop; @@ -3584,7 +3726,7 @@ public: bool ignoreSslErrors; QSslSocket::PeerVerifyMode peerVerifyMode; QSsl::SslProtocol protocol; - QString ciphers; + QList ciphers; PskProvider m_pskProvider; protected: @@ -3598,7 +3740,9 @@ protected: connect(socket, SIGNAL(sslErrors(QList)), this, SLOT(ignoreErrorSlot())); if (!ciphers.isEmpty()) { - socket->setCiphers(ciphers); + auto sslConfig = socket->sslConfiguration(); + sslConfig.setCiphers(ciphers); + socket->setSslConfiguration(sslConfig); } QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState)); @@ -3640,7 +3784,7 @@ void tst_QSslSocket::simplePskConnect() QSKIP("No SSL support"); bool pskCipherFound = false; - const QList supportedCiphers = QSslSocket::supportedCiphers(); + const QList supportedCiphers = QSslConfiguration::supportedCiphers(); for (const QSslCipher &cipher : supportedCiphers) { if (cipher.name() == PSK_CIPHER_WITHOUT_AUTH) { pskCipherFound = true; @@ -3692,7 +3836,9 @@ void tst_QSslSocket::simplePskConnect() connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(exitLoop())); // force a PSK cipher w/o auth - socket.setCiphers(PSK_CIPHER_WITHOUT_AUTH); + auto sslConfig = socket.sslConfiguration(); + sslConfig.setCiphers({QSslCipher(PSK_CIPHER_WITHOUT_AUTH)}); + socket.setSslConfiguration(sslConfig); PskProvider provider; @@ -3961,7 +4107,9 @@ void tst_QSslSocket::pskServer() connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(exitLoop())); // force a PSK cipher w/o auth - socket.setCiphers(PSK_CIPHER_WITHOUT_AUTH); + auto sslConfig = socket.sslConfiguration(); + sslConfig.setCiphers({QSslCipher(PSK_CIPHER_WITHOUT_AUTH)}); + socket.setSslConfiguration(sslConfig); PskProvider provider; provider.setIdentity(PSK_CLIENT_IDENTITY); diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp index 4199c0f465e..3b28e7a8033 100644 --- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp +++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp @@ -211,10 +211,23 @@ void tst_QSslSocket_onDemandCertificates_member::onDemandRootCertLoadingMemberMe { const QString host("www.qt.io"); +#if QT_DEPRECATED_SINCE(5, 5) + { + // not using any root certs -> should not work + QSslSocketPtr socket2 = newSocket(); + this->socket = socket2.data(); + socket2->setCaCertificates(QList()); + socket2->connectToHostEncrypted(host, 443); + QVERIFY(!waitForEncrypted(socket2.data())); + } +#endif + // not using any root certs -> should not work QSslSocketPtr socket2 = newSocket(); this->socket = socket2.data(); - socket2->setCaCertificates(QList()); + auto sslConfig = socket2->sslConfiguration(); + sslConfig.setCaCertificates(QList()); + socket2->setSslConfiguration(sslConfig); socket2->connectToHostEncrypted(host, 443); QVERIFY(!waitForEncrypted(socket2.data())); @@ -224,10 +237,23 @@ void tst_QSslSocket_onDemandCertificates_member::onDemandRootCertLoadingMemberMe socket->connectToHostEncrypted(host, 443); QVERIFY2(waitForEncrypted(socket.data()), qPrintable(socket->errorString())); +#if QT_DEPRECATED_SINCE(5, 5) + { + // not using any root certs again -> should not work + QSslSocketPtr socket3 = newSocket(); + this->socket = socket3.data(); + socket3->setCaCertificates(QList()); + socket3->connectToHostEncrypted(host, 443); + QVERIFY(!waitForEncrypted(socket3.data())); + } +#endif + // not using any root certs again -> should not work QSslSocketPtr socket3 = newSocket(); this->socket = socket3.data(); - socket3->setCaCertificates(QList()); + sslConfig = socket3->sslConfiguration(); + sslConfig.setCaCertificates(QList()); + socket3->setSslConfiguration(sslConfig); socket3->connectToHostEncrypted(host, 443); QVERIFY(!waitForEncrypted(socket3.data())); diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp index 671a21b1c25..a441d13619f 100644 --- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp +++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp @@ -178,6 +178,7 @@ void tst_QSslSocket_onDemandCertificates_static::onDemandRootCertLoadingStaticMe { QString host("www.qt.io"); +#if QT_DEPRECATED_SINCE(5, 5) // not using any root certs -> should not work QSslSocket::setDefaultCaCertificates(QList()); QSslSocketPtr socket = newSocket(); @@ -200,6 +201,7 @@ void tst_QSslSocket_onDemandCertificates_static::onDemandRootCertLoadingStaticMe QVERIFY(!socket3->waitForEncrypted()); QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates()); +#endif // setting empty default configuration -> should not work QSslConfiguration conf; diff --git a/tests/auto/opengl/qgl/BLACKLIST b/tests/auto/opengl/qgl/BLACKLIST index d3165a51e5e..ec75ea16eb7 100644 --- a/tests/auto/opengl/qgl/BLACKLIST +++ b/tests/auto/opengl/qgl/BLACKLIST @@ -1,25 +1,8 @@ -[glWidgetRendering] -windows -winrt -[glFBORendering] -windows -winrt -[multipleFBOInterleavedRendering] -windows -winrt -[glPBufferRendering] -windows -winrt -[replaceClipping] -windows -winrt -[clipTest] -windows -winrt [graphicsViewClipping] -windows -winrt -linux ci -[glFBOUseInGLWidget] -windows -winrt +ubuntu-16.04 +rhel-7.6 +opensuse-leap +ubuntu-18.04 +rhel-7.4 +opensuse-42.3 + diff --git a/tests/auto/other/gestures/BLACKLIST b/tests/auto/other/gestures/BLACKLIST index c465ff316e1..2af5d403590 100644 --- a/tests/auto/other/gestures/BLACKLIST +++ b/tests/auto/other/gestures/BLACKLIST @@ -3,17 +3,25 @@ rhel-7.4 rhel-7.6 ubuntu-18.04 [customGesture] -# QTBUG-67254 -ubuntu -opensuse opensuse-leap +# QTBUG-67254 +opensuse-42.3 [graphicsItemGesture] ubuntu-18.04 +rhel-7.4 +rhel-7.6 [graphicsItemTreeGesture] ubuntu-18.04 [graphicsView] ubuntu-18.04 +rhel-7.4 +rhel-7.6 [explicitGraphicsObjectTarget] ubuntu-18.04 +rhel-7.4 +rhel-7.6 [autoCancelGestures2] ubuntu-18.04 +rhel-7.4 +rhel-7.6 + diff --git a/tests/auto/other/lancelot/paintcommands.cpp b/tests/auto/other/lancelot/paintcommands.cpp index 8a2934049ee..dc71253f3ed 100644 --- a/tests/auto/other/lancelot/paintcommands.cpp +++ b/tests/auto/other/lancelot/paintcommands.cpp @@ -1202,7 +1202,7 @@ void PaintCommands::command_drawRoundRect(QRegularExpressionMatch re) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED - m_painter->drawRoundRect(x, y, w, h, xs, ys); + m_painter->drawRoundedRect(x, y, w, h, xs, ys, Qt::RelativeSize); QT_WARNING_POP } diff --git a/tests/auto/other/networkselftest/BLACKLIST b/tests/auto/other/networkselftest/BLACKLIST index 4a958b43a5e..948081eb78a 100644 --- a/tests/auto/other/networkselftest/BLACKLIST +++ b/tests/auto/other/networkselftest/BLACKLIST @@ -1,4 +1,6 @@ # QTBUG-27571 [ftpProxyServer] -windows 32bit -windows 64bit +windows-10 msvc-2017 +windows-10 msvc-2015 +windows-7sp1 + diff --git a/tests/auto/other/qaccessibilitymac/BLACKLIST b/tests/auto/other/qaccessibilitymac/BLACKLIST deleted file mode 100644 index f53fa7e853c..00000000000 --- a/tests/auto/other/qaccessibilitymac/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[hierarchyTest] -osx-10.12 ci diff --git a/tests/auto/other/qfocusevent/BLACKLIST b/tests/auto/other/qfocusevent/BLACKLIST index 0b034725873..5af8be91a03 100644 --- a/tests/auto/other/qfocusevent/BLACKLIST +++ b/tests/auto/other/qfocusevent/BLACKLIST @@ -1,6 +1,3 @@ -[checkReason_Shortcut] -osx-10.12 ci [checkReason_ActiveWindow] -osx-10.12 ci winrt diff --git a/tests/auto/other/qnetworkaccessmanager_and_qprogressdialog/BLACKLIST b/tests/auto/other/qnetworkaccessmanager_and_qprogressdialog/BLACKLIST index aea819fc2eb..65a939cdcbc 100644 --- a/tests/auto/other/qnetworkaccessmanager_and_qprogressdialog/BLACKLIST +++ b/tests/auto/other/qnetworkaccessmanager_and_qprogressdialog/BLACKLIST @@ -1,2 +1,5 @@ +[downloadCheck] +windows-10 msvc-2015 +windows-10 msvc-2017 [downloadCheck:with-zeroCopy] windows diff --git a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp index d1b4ed8bcd5..81b49a3a87f 100644 --- a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp +++ b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp @@ -302,10 +302,12 @@ void tst_QPrinterInfo::testConstructors() QCOMPARE(copy1.minimumPhysicalPageSize(), printers.at(i).minimumPhysicalPageSize()); QCOMPARE(copy1.maximumPhysicalPageSize(), printers.at(i).maximumPhysicalPageSize()); QCOMPARE(copy1.supportedPageSizes(), printers.at(i).supportedPageSizes()); +#if QT_DEPRECATED_SINCE(5, 3) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED QCOMPARE(copy1.supportedSizesWithNames(), printers.at(i).supportedSizesWithNames()); QT_WARNING_POP +#endif QCOMPARE(copy1.supportedResolutions(), printers.at(i).supportedResolutions()); QCOMPARE(copy1.defaultDuplexMode(), printers.at(i).defaultDuplexMode()); QCOMPARE(copy1.supportedDuplexModes(), printers.at(i).supportedDuplexModes()); @@ -326,10 +328,12 @@ QT_WARNING_POP QCOMPARE(copy2.minimumPhysicalPageSize(), printers.at(i).minimumPhysicalPageSize()); QCOMPARE(copy2.maximumPhysicalPageSize(), printers.at(i).maximumPhysicalPageSize()); QCOMPARE(copy2.supportedPageSizes(), printers.at(i).supportedPageSizes()); +#if QT_DEPRECATED_SINCE(5, 3) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED QCOMPARE(copy2.supportedSizesWithNames(), printers.at(i).supportedSizesWithNames()); QT_WARNING_POP +#endif QCOMPARE(copy2.supportedResolutions(), printers.at(i).supportedResolutions()); QCOMPARE(copy2.defaultDuplexMode(), printers.at(i).defaultDuplexMode()); QCOMPARE(copy2.supportedDuplexModes(), printers.at(i).supportedDuplexModes()); diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h index 55875359ff1..174db2863ef 100644 --- a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h +++ b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h @@ -34,7 +34,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -511,13 +512,13 @@ public: QSqlQuery q( "SELECT banner FROM v$version", db ); q.next(); - QRegExp vers( "([0-9]+)\\.[0-9\\.]+[0-9]" ); - - if ( vers.indexIn( q.value( 0 ).toString() ) ) { + QRegularExpression vers("([0-9]+)\\.[0-9\\.]+[0-9]"); + QRegularExpressionMatch match = vers.match(q.value(0).toString()); + if (match.hasMatch()) { bool ok; - ver = vers.cap( 1 ).toInt( &ok ); + ver = match.captured(1).toInt(&ok); - if ( !ok ) + if (!ok) ver = -1; } diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp index f309231b107..c59250e36e6 100644 --- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -228,7 +228,7 @@ struct FieldDef { QString fieldName() const { QString rt = typeName; - rt.replace(QRegExp("\\s"), QString("_")); + rt.replace(QRegularExpression("\\s"), QString("_")); int i = rt.indexOf(QLatin1Char('(')); if (i == -1) i = rt.length(); diff --git a/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp b/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp index be0285537e8..871ac24be40 100644 --- a/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp +++ b/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp @@ -42,7 +42,9 @@ public: virtual ~tst_QSqlError(); private slots: +#if QT_DEPRECATED_SINCE(5, 1) void getSetCheck(); +#endif void construction(); void moveOperator(); void operators(); @@ -57,6 +59,7 @@ tst_QSqlError::~tst_QSqlError() { } +#if QT_DEPRECATED_SINCE(5, 1) // Testing get/set functions void tst_QSqlError::getSetCheck() { @@ -83,14 +86,28 @@ void tst_QSqlError::getSetCheck() obj1.setNumber(INT_MAX); QCOMPARE(INT_MAX, obj1.number()); } +#endif void tst_QSqlError::construction() { - QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, 123); +#if QT_DEPRECATED_SINCE(5, 3) + { + QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, 123); + QCOMPARE(obj1.driverText(), QString("drivertext")); + QCOMPARE(obj1.databaseText(), QString("databasetext")); + QCOMPARE(obj1.type(), QSqlError::UnknownError); + QCOMPARE(obj1.number(), 123); + QCOMPARE(obj1.nativeErrorCode(), QStringLiteral("123")); + QVERIFY(obj1.isValid()); + } +#endif + QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, QStringLiteral("123")); QCOMPARE(obj1.driverText(), QString("drivertext")); QCOMPARE(obj1.databaseText(), QString("databasetext")); QCOMPARE(obj1.type(), QSqlError::UnknownError); +#if QT_DEPRECATED_SINCE(5, 3) QCOMPARE(obj1.number(), 123); +#endif QCOMPARE(obj1.nativeErrorCode(), QStringLiteral("123")); QVERIFY(obj1.isValid()); @@ -98,7 +115,9 @@ void tst_QSqlError::construction() QCOMPARE(obj2.driverText(), obj1.driverText()); QCOMPARE(obj2.databaseText(), obj1.databaseText()); QCOMPARE(obj2.type(), obj1.type()); +#if QT_DEPRECATED_SINCE(5, 3) QCOMPARE(obj2.number(), obj1.number()); +#endif QCOMPARE(obj2.nativeErrorCode(), obj1.nativeErrorCode()); QVERIFY(obj2.isValid()); @@ -106,7 +125,9 @@ void tst_QSqlError::construction() QCOMPARE(obj3.driverText(), obj2.driverText()); QCOMPARE(obj3.databaseText(), obj2.databaseText()); QCOMPARE(obj3.type(), obj2.type()); +#if QT_DEPRECATED_SINCE(5, 3) QCOMPARE(obj3.number(), obj2.number()); +#endif QCOMPARE(obj3.nativeErrorCode(), obj2.nativeErrorCode()); QVERIFY(obj3.isValid()); @@ -116,7 +137,9 @@ void tst_QSqlError::construction() QCOMPARE(obj4.databaseText(), QString()); QCOMPARE(obj4.text(), QString()); QCOMPARE(obj4.type(), QSqlError::NoError); +#if QT_DEPRECATED_SINCE(5, 3) QCOMPARE(obj4.number(), -1); +#endif QCOMPARE(obj4.nativeErrorCode(), QString()); QSqlError obj5(QStringLiteral("drivertext"), QStringLiteral("databasetext"), @@ -124,7 +147,9 @@ void tst_QSqlError::construction() QCOMPARE(obj5.driverText(), QString("drivertext")); QCOMPARE(obj5.databaseText(), QString("databasetext")); QCOMPARE(obj5.type(), QSqlError::UnknownError); +#if QT_DEPRECATED_SINCE(5, 3) QCOMPARE(obj5.number(), 123); +#endif QCOMPARE(obj5.nativeErrorCode(), QStringLiteral("123")); QVERIFY(obj5.isValid()); @@ -133,17 +158,31 @@ void tst_QSqlError::construction() QCOMPARE(obj6.driverText(), QString("drivertext")); QCOMPARE(obj6.databaseText(), QString("databasetext")); QCOMPARE(obj6.type(), QSqlError::UnknownError); +#if QT_DEPRECATED_SINCE(5, 3) QCOMPARE(obj6.number(), 0); +#endif QCOMPARE(obj6.nativeErrorCode(), QStringLiteral("Err123")); QVERIFY(obj6.isValid()); - // Default constructed object as constructed before Qt 5.3 - QSqlError obj7(QString(), QString(), QSqlError::NoError, -1); +#if QT_DEPRECATED_SINCE(5, 3) + { + // Default constructed object as constructed before Qt 5.3 + QSqlError obj7(QString(), QString(), QSqlError::NoError, -1); + QVERIFY(!obj7.isValid()); + QCOMPARE(obj7.driverText(), QString()); + QCOMPARE(obj7.databaseText(), QString()); + QCOMPARE(obj7.type(), QSqlError::NoError); + QCOMPARE(obj7.number(), -1); + QCOMPARE(obj7.nativeErrorCode(), QString()); + } +#endif + + // Default constructed object + QSqlError obj7; QVERIFY(!obj7.isValid()); QCOMPARE(obj7.driverText(), QString()); QCOMPARE(obj7.databaseText(), QString()); QCOMPARE(obj7.type(), QSqlError::NoError); - QCOMPARE(obj7.number(), -1); QCOMPARE(obj7.nativeErrorCode(), QString()); // Move constructor @@ -151,32 +190,32 @@ void tst_QSqlError::construction() QCOMPARE(obj8.driverText(), obj2.driverText()); QCOMPARE(obj8.databaseText(), obj2.databaseText()); QCOMPARE(obj8.type(), obj2.type()); +#if QT_DEPRECATED_SINCE(5, 3) QCOMPARE(obj8.number(), obj2.number()); +#endif QCOMPARE(obj8.nativeErrorCode(), obj2.nativeErrorCode()); QVERIFY(obj8.isValid()); } void tst_QSqlError::moveOperator() { - QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, 123), obj2; + QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, QStringLiteral("123")), obj2; obj2 = std::move(obj1); QCOMPARE(obj2.driverText(), QString("drivertext")); QCOMPARE(obj2.databaseText(), QString("databasetext")); QCOMPARE(obj2.type(), QSqlError::UnknownError); +#if QT_DEPRECATED_SINCE(5, 3) QCOMPARE(obj2.number(), 123); +#endif QCOMPARE(obj2.nativeErrorCode(), QStringLiteral("123")); QVERIFY(obj2.isValid()); } void tst_QSqlError::operators() { - QSqlError error1; - QSqlError error2; - QSqlError error3; - - error1.setType(QSqlError::NoError); - error2.setType(QSqlError::NoError); - error3.setType(QSqlError::UnknownError); + QSqlError error1(QString(), QString(), QSqlError::NoError); + QSqlError error2(QString(), QString(), QSqlError::NoError); + QSqlError error3(QString(), QString(), QSqlError::UnknownError); QCOMPARE(error1, error2); QVERIFY(error1 != error3); diff --git a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp index 467c53088ec..fb01b19d16d 100644 --- a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp +++ b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp @@ -466,6 +466,8 @@ void tst_Cmptest::compareQPixmaps_data() const QPixmap pixmap1(xpmPixmapData1); const QPixmap pixmap2(xpmPixmapData2); const QPixmap pixmap3(xpmPixmapData3); + QPixmap pixmapWrongDpr = pixmap1.scaled(2, 2); + pixmapWrongDpr.setDevicePixelRatio(2); QTest::newRow("both null") << QPixmap() << QPixmap(); QTest::newRow("one null") << QPixmap() << pixmap1; @@ -473,6 +475,7 @@ void tst_Cmptest::compareQPixmaps_data() QTest::newRow("equal") << pixmap1 << pixmap1; QTest::newRow("different size") << pixmap1 << pixmap3; QTest::newRow("different pixels") << pixmap1 << pixmap2; + QTest::newRow("different dpr") << pixmap1 << pixmapWrongDpr; } void tst_Cmptest::compareQPixmaps() @@ -492,6 +495,8 @@ void tst_Cmptest::compareQImages_data() const QImage image2(QPixmap(xpmPixmapData2).toImage()); const QImage image1Indexed = image1.convertToFormat(QImage::Format_Indexed8); const QImage image3(QPixmap(xpmPixmapData3).toImage()); + QImage imageWrongDpr = image1.scaled(2, 2); + imageWrongDpr.setDevicePixelRatio(2); QTest::newRow("both null") << QImage() << QImage(); QTest::newRow("one null") << QImage() << image1; @@ -500,6 +505,7 @@ void tst_Cmptest::compareQImages_data() QTest::newRow("different size") << image1 << image3; QTest::newRow("different format") << image1 << image1Indexed; QTest::newRow("different pixels") << image1 << image2; + QTest::newRow("different dpr") << image1 << imageWrongDpr; } void tst_Cmptest::compareQImages() diff --git a/tests/auto/testlib/selftests/expected_cmptest.lightxml b/tests/auto/testlib/selftests/expected_cmptest.lightxml index 58b5a5e530b..f1089335859 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.lightxml +++ b/tests/auto/testlib/selftests/expected_cmptest.lightxml @@ -208,6 +208,12 @@ + + + + @@ -245,6 +251,12 @@ + + + + diff --git a/tests/auto/testlib/selftests/expected_cmptest.tap b/tests/auto/testlib/selftests/expected_cmptest.tap index 238db2fc2b6..dc9cb5c9507 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.tap +++ b/tests/auto/testlib/selftests/expected_cmptest.tap @@ -245,9 +245,9 @@ not ok 32 - compareQPixmaps(one null) found: 1 (opA).isNull() expected: 0 (opB).isNull() actual: 1 (opA).isNull() - at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483) + at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:486) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 483 + line: 486 ... not ok 33 - compareQPixmaps(other null) --- @@ -257,9 +257,9 @@ not ok 33 - compareQPixmaps(other null) found: 0 (opA).isNull() expected: 1 (opB).isNull() actual: 0 (opA).isNull() - at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483) + at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:486) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 483 + line: 486 ... ok 34 - compareQPixmaps(equal) not ok 35 - compareQPixmaps(different size) @@ -270,19 +270,31 @@ not ok 35 - compareQPixmaps(different size) found: 11x20 (opA) expected: 20x20 (opB) actual: 11x20 (opA) - at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483) + at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:486) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 483 + line: 486 ... not ok 36 - compareQPixmaps(different pixels) --- # Compared values are not the same - at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483) + at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:486) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 483 + line: 486 ... -ok 37 - compareQImages(both null) -not ok 38 - compareQImages(one null) +not ok 37 - compareQPixmaps(different dpr) + --- + type: QCOMPARE + message: Compared QPixmaps differ in device pixel ratio. + wanted: 2 (opB) + found: 1 (opA) + expected: 2 (opB) + actual: 1 (opA) + at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:486) + file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp + line: 486 + ... +ok 38 - compareQImages(both null) +not ok 39 - compareQImages(one null) --- type: QCOMPARE message: Compared QImages differ. @@ -290,11 +302,11 @@ not ok 38 - compareQImages(one null) found: 1 (opA).isNull() expected: 0 (opB).isNull() actual: 1 (opA).isNull() - at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510) + at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 510 + line: 516 ... -not ok 39 - compareQImages(other null) +not ok 40 - compareQImages(other null) --- type: QCOMPARE message: Compared QImages differ. @@ -302,12 +314,12 @@ not ok 39 - compareQImages(other null) found: 0 (opA).isNull() expected: 1 (opB).isNull() actual: 0 (opA).isNull() - at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510) + at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 510 + line: 516 ... -ok 40 - compareQImages(equal) -not ok 41 - compareQImages(different size) +ok 41 - compareQImages(equal) +not ok 42 - compareQImages(different size) --- type: QCOMPARE message: Compared QImages differ in size. @@ -315,11 +327,11 @@ not ok 41 - compareQImages(different size) found: 11x20 (opA) expected: 20x20 (opB) actual: 11x20 (opA) - at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510) + at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 510 + line: 516 ... -not ok 42 - compareQImages(different format) +not ok 43 - compareQImages(different format) --- type: QCOMPARE message: Compared QImages differ in format. @@ -327,19 +339,31 @@ not ok 42 - compareQImages(different format) found: 6 (opA) expected: 3 (opB) actual: 6 (opA) - at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510) + at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 510 + line: 516 ... -not ok 43 - compareQImages(different pixels) +not ok 44 - compareQImages(different pixels) --- # Compared values are not the same - at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510) + at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 510 + line: 516 ... -ok 44 - compareQRegion(equal-empty) -not ok 45 - compareQRegion(1-empty) +not ok 45 - compareQImages(different dpr) + --- + type: QCOMPARE + message: Compared QImages differ in device pixel ratio. + wanted: 2 (opB) + found: 1 (opA) + expected: 2 (opB) + actual: 1 (opA) + at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516) + file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp + line: 516 + ... +ok 46 - compareQRegion(equal-empty) +not ok 47 - compareQRegion(1-empty) --- type: QCOMPARE message: Compared values are not the same @@ -347,12 +371,12 @@ not ok 45 - compareQRegion(1-empty) found: QRegion(200x50+10+10) (rA) expected: QRegion(null) (rB) actual: QRegion(200x50+10+10) (rA) - at: tst_Cmptest::compareQRegion() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:533) + at: tst_Cmptest::compareQRegion() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:539) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 533 + line: 539 ... -ok 46 - compareQRegion(equal) -not ok 47 - compareQRegion(different lists) +ok 48 - compareQRegion(equal) +not ok 49 - compareQRegion(different lists) --- type: QCOMPARE message: Compared values are not the same @@ -360,11 +384,11 @@ not ok 47 - compareQRegion(different lists) found: QRegion(200x50+10+10) (rA) expected: QRegion(2 rectangles, 50x200+100+200, 200x50+10+10) (rB) actual: QRegion(200x50+10+10) (rA) - at: tst_Cmptest::compareQRegion() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:533) + at: tst_Cmptest::compareQRegion() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:539) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 533 + line: 539 ... -not ok 48 - compareQVector2D() +not ok 50 - compareQVector2D() --- type: QCOMPARE message: Compared values are not the same @@ -372,11 +396,11 @@ not ok 48 - compareQVector2D() found: QVector2D(1, 2) (v2a) expected: QVector2D(1, 3) (v2b) actual: QVector2D(1, 2) (v2a) - at: tst_Cmptest::compareQVector2D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:542) + at: tst_Cmptest::compareQVector2D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:548) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 542 + line: 548 ... -not ok 49 - compareQVector3D() +not ok 51 - compareQVector3D() --- type: QCOMPARE message: Compared values are not the same @@ -384,11 +408,11 @@ not ok 49 - compareQVector3D() found: QVector3D(1, 2, 3) (v3a) expected: QVector3D(1, 3, 3) (v3b) actual: QVector3D(1, 2, 3) (v3a) - at: tst_Cmptest::compareQVector3D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:551) + at: tst_Cmptest::compareQVector3D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:557) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 551 + line: 557 ... -not ok 50 - compareQVector4D() +not ok 52 - compareQVector4D() --- type: QCOMPARE message: Compared values are not the same @@ -396,11 +420,11 @@ not ok 50 - compareQVector4D() found: QVector4D(1, 2, 3, 4) (v4a) expected: QVector4D(1, 3, 3, 4) (v4b) actual: QVector4D(1, 2, 3, 4) (v4a) - at: tst_Cmptest::compareQVector4D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:560) + at: tst_Cmptest::compareQVector4D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:566) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 560 + line: 566 ... -not ok 51 - verify() +not ok 53 - verify() --- type: QVERIFY message: Verification failed @@ -408,35 +432,11 @@ not ok 51 - verify() found: false (opaqueFunc() < 2) expected: true (opaqueFunc() < 2) actual: false (opaqueFunc() < 2) - at: tst_Cmptest::verify() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:572) - file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 572 - ... -not ok 52 - verify2() - --- - type: QVERIFY - message: 42 - wanted: true (opaqueFunc() < 2) - found: false (opaqueFunc() < 2) - expected: true (opaqueFunc() < 2) - actual: false (opaqueFunc() < 2) - at: tst_Cmptest::verify2() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:578) + at: tst_Cmptest::verify() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:578) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp line: 578 ... -not ok 53 - tryVerify() - --- - type: QVERIFY - message: Verification failed - wanted: true (opaqueFunc() < 2) - found: false (opaqueFunc() < 2) - expected: true (opaqueFunc() < 2) - actual: false (opaqueFunc() < 2) - at: tst_Cmptest::tryVerify() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:584) - file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp - line: 584 - ... -not ok 54 - tryVerify2() +not ok 54 - verify2() --- type: QVERIFY message: 42 @@ -444,13 +444,37 @@ not ok 54 - tryVerify2() found: false (opaqueFunc() < 2) expected: true (opaqueFunc() < 2) actual: false (opaqueFunc() < 2) - at: tst_Cmptest::tryVerify2() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:590) + at: tst_Cmptest::verify2() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:584) + file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp + line: 584 + ... +not ok 55 - tryVerify() + --- + type: QVERIFY + message: Verification failed + wanted: true (opaqueFunc() < 2) + found: false (opaqueFunc() < 2) + expected: true (opaqueFunc() < 2) + actual: false (opaqueFunc() < 2) + at: tst_Cmptest::tryVerify() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:590) file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp line: 590 ... -ok 55 - verifyExplicitOperatorBool() -ok 56 - cleanupTestCase() -1..56 -# tests 56 +not ok 56 - tryVerify2() + --- + type: QVERIFY + message: 42 + wanted: true (opaqueFunc() < 2) + found: false (opaqueFunc() < 2) + expected: true (opaqueFunc() < 2) + actual: false (opaqueFunc() < 2) + at: tst_Cmptest::tryVerify2() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:596) + file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp + line: 596 + ... +ok 57 - verifyExplicitOperatorBool() +ok 58 - cleanupTestCase() +1..58 +# tests 58 # pass 18 -# fail 38 +# fail 40 diff --git a/tests/auto/testlib/selftests/expected_cmptest.teamcity b/tests/auto/testlib/selftests/expected_cmptest.teamcity index 422d0cbfdfd..426fddb20f1 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.teamcity +++ b/tests/auto/testlib/selftests/expected_cmptest.teamcity @@ -95,6 +95,9 @@ ##teamcity[testStarted name='compareQPixmaps(different pixels)' flowId='tst_Cmptest'] ##teamcity[testFailed name='compareQPixmaps(different pixels)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared values are not the same' flowId='tst_Cmptest'] ##teamcity[testFinished name='compareQPixmaps(different pixels)' flowId='tst_Cmptest'] +##teamcity[testStarted name='compareQPixmaps(different dpr)' flowId='tst_Cmptest'] +##teamcity[testFailed name='compareQPixmaps(different dpr)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared QPixmaps differ in device pixel ratio.|n Actual (opA): 1|n Expected (opB): 2' flowId='tst_Cmptest'] +##teamcity[testFinished name='compareQPixmaps(different dpr)' flowId='tst_Cmptest'] ##teamcity[testStarted name='compareQImages(both null)' flowId='tst_Cmptest'] ##teamcity[testFinished name='compareQImages(both null)' flowId='tst_Cmptest'] ##teamcity[testStarted name='compareQImages(one null)' flowId='tst_Cmptest'] @@ -114,6 +117,9 @@ ##teamcity[testStarted name='compareQImages(different pixels)' flowId='tst_Cmptest'] ##teamcity[testFailed name='compareQImages(different pixels)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared values are not the same' flowId='tst_Cmptest'] ##teamcity[testFinished name='compareQImages(different pixels)' flowId='tst_Cmptest'] +##teamcity[testStarted name='compareQImages(different dpr)' flowId='tst_Cmptest'] +##teamcity[testFailed name='compareQImages(different dpr)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared QImages differ in device pixel ratio.|n Actual (opA): 1|n Expected (opB): 2' flowId='tst_Cmptest'] +##teamcity[testFinished name='compareQImages(different dpr)' flowId='tst_Cmptest'] ##teamcity[testStarted name='compareQRegion(equal-empty)' flowId='tst_Cmptest'] ##teamcity[testFinished name='compareQRegion(equal-empty)' flowId='tst_Cmptest'] ##teamcity[testStarted name='compareQRegion(1-empty)' flowId='tst_Cmptest'] diff --git a/tests/auto/testlib/selftests/expected_cmptest.txt b/tests/auto/testlib/selftests/expected_cmptest.txt index e1aa81c1a16..08877ef74d0 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.txt +++ b/tests/auto/testlib/selftests/expected_cmptest.txt @@ -104,6 +104,10 @@ FAIL! : tst_Cmptest::compareQPixmaps(different size) Compared QPixmaps differ i Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)] FAIL! : tst_Cmptest::compareQPixmaps(different pixels) Compared values are not the same Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)] +FAIL! : tst_Cmptest::compareQPixmaps(different dpr) Compared QPixmaps differ in device pixel ratio. + Actual (opA): 1 + Expected (opB): 2 + Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)] PASS : tst_Cmptest::compareQImages(both null) FAIL! : tst_Cmptest::compareQImages(one null) Compared QImages differ. Actual (opA).isNull(): 1 @@ -124,6 +128,10 @@ FAIL! : tst_Cmptest::compareQImages(different format) Compared QImages differ i Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)] FAIL! : tst_Cmptest::compareQImages(different pixels) Compared values are not the same Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)] +FAIL! : tst_Cmptest::compareQImages(different dpr) Compared QImages differ in device pixel ratio. + Actual (opA): 1 + Expected (opB): 2 + Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)] PASS : tst_Cmptest::compareQRegion(equal-empty) FAIL! : tst_Cmptest::compareQRegion(1-empty) Compared values are not the same Actual (rA): QRegion(200x50+10+10) @@ -156,5 +164,5 @@ FAIL! : tst_Cmptest::tryVerify2() 'opaqueFunc() < 2' returned FALSE. (42) Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)] PASS : tst_Cmptest::verifyExplicitOperatorBool() PASS : tst_Cmptest::cleanupTestCase() -Totals: 18 passed, 38 failed, 0 skipped, 0 blacklisted, 0ms +Totals: 18 passed, 40 failed, 0 skipped, 0 blacklisted, 0ms ********* Finished testing of tst_Cmptest ********* diff --git a/tests/auto/testlib/selftests/expected_cmptest.xml b/tests/auto/testlib/selftests/expected_cmptest.xml index 1c5a17631a6..daf2560f1b4 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.xml +++ b/tests/auto/testlib/selftests/expected_cmptest.xml @@ -210,6 +210,12 @@ + + + + @@ -247,6 +253,12 @@ + + + + diff --git a/tests/auto/testlib/selftests/expected_cmptest.xunitxml b/tests/auto/testlib/selftests/expected_cmptest.xunitxml index 99823d1c1c2..397db4c3e41 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.xunitxml +++ b/tests/auto/testlib/selftests/expected_cmptest.xunitxml @@ -1,5 +1,5 @@ - + @@ -98,6 +98,9 @@ Actual (opA): 11x20 Expected (opB): 20x20" result="fail"/> + + setText(QCoreApplication::translate("QFileDialog", "Files of type:", nullptr)); - Q_UNUSED(QFileDialog); + (void)QFileDialog; } // retranslateUi }; diff --git a/tests/auto/widgets/dialogs/qdialog/BLACKLIST b/tests/auto/widgets/dialogs/qdialog/BLACKLIST index dd6a8bfff9d..72e3dff6dd5 100644 --- a/tests/auto/widgets/dialogs/qdialog/BLACKLIST +++ b/tests/auto/widgets/dialogs/qdialog/BLACKLIST @@ -1,4 +1,4 @@ [snapToDefaultButton] -osx +osx-10.14 [showFullScreen] osx-10.13 ci diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp index c840dabc1a1..a494d7119a4 100644 --- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp +++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp @@ -52,7 +52,9 @@ class DummyDialog : public QDialog { public: DummyDialog(): QDialog() {} +#if QT_DEPRECATED_SINCE(5, 13) using QDialog::showExtension; +#endif }; class tst_QDialog : public QObject @@ -64,8 +66,10 @@ public: private slots: void cleanup(); void getSetCheck(); +#if QT_DEPRECATED_SINCE(5, 13) void showExtension_data(); void showExtension(); +#endif void defaultButtons(); void showMaximized(); void showMinimized(); @@ -76,6 +80,9 @@ private slots: void deleteInExec(); #if QT_CONFIG(sizegrip) void showSizeGrip(); +#if QT_DEPRECATED_SINCE(5, 13) + void showSizeGrip_deprecated(); +#endif #endif void setVisible(); void reject(); @@ -89,6 +96,7 @@ private slots: void tst_QDialog::getSetCheck() { QDialog obj1; +#if QT_DEPRECATED_SINCE(5, 13) // QWidget* QDialog::extension() // void QDialog::setExtension(QWidget*) QWidget *var1 = new QWidget; @@ -97,6 +105,7 @@ void tst_QDialog::getSetCheck() obj1.setExtension((QWidget *)0); QCOMPARE((QWidget *)0, obj1.extension()); // No delete var1, since setExtension takes ownership +#endif // int QDialog::result() // void QDialog::setResult(int) @@ -146,6 +155,7 @@ void tst_QDialog::cleanup() QVERIFY(QApplication::topLevelWidgets().isEmpty()); } +#if QT_DEPRECATED_SINCE(5, 13) void tst_QDialog::showExtension_data() { QTest::addColumn("dlgSize"); @@ -197,6 +207,7 @@ void tst_QDialog::showExtension() testWidget.setExtension( 0 ); } +#endif void tst_QDialog::defaultButtons() { @@ -422,8 +433,36 @@ void tst_QDialog::deleteInExec() } #if QT_CONFIG(sizegrip) + // From Task 124269 void tst_QDialog::showSizeGrip() +{ + QDialog dialog(nullptr); + dialog.show(); + QWidget *ext = new QWidget(&dialog); + QVERIFY(!dialog.isSizeGripEnabled()); + + dialog.setSizeGripEnabled(true); + QPointer sizeGrip = dialog.findChild(); + QVERIFY(sizeGrip); + QVERIFY(sizeGrip->isVisible()); + QVERIFY(dialog.isSizeGripEnabled()); + + dialog.setSizeGripEnabled(false); + QVERIFY(!dialog.isSizeGripEnabled()); + + dialog.setSizeGripEnabled(true); + sizeGrip = dialog.findChild(); + QVERIFY(sizeGrip); + QVERIFY(sizeGrip->isVisible()); + sizeGrip->hide(); + dialog.hide(); + dialog.show(); + QVERIFY(!sizeGrip->isVisible()); +} + +#if QT_DEPRECATED_SINCE(5, 13) +void tst_QDialog::showSizeGrip_deprecated() { QDialog dialog(0); dialog.show(); @@ -476,7 +515,9 @@ void tst_QDialog::showSizeGrip() dialog.show(); QVERIFY(!sizeGrip->isVisible()); } -#endif +#endif // QT_DEPRECATED_SINCE(5, 13) + +#endif // QT_CONFIG(sizegrip) void tst_QDialog::setVisible() { diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp index f7482bae45a..2131e45f29a 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp @@ -800,7 +800,10 @@ void tst_QFiledialog::isReadOnly() QAction* renameAction = fd.findChild("qt_rename_action"); QAction* deleteAction = fd.findChild("qt_delete_action"); +#if QT_DEPRECATED_SINCE(5, 13) QCOMPARE(fd.isReadOnly(), false); +#endif + QCOMPARE(fd.testOption(QFileDialog::ReadOnly), false); // This is dependent upon the file/dir, find cross platform way to test //fd.setDirectory(QDir::home()); diff --git a/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST b/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST index e0887d8ad18..875855b59e4 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST +++ b/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST @@ -1,2 +1,4 @@ [QTBUG4419_lineEditSelectAll] -osx +osx-10.12 +osx-10.14 +osx-10.13 diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp index 869418371ce..40eff1e4c37 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp @@ -378,24 +378,24 @@ void tst_QFileDialog2::task143519_deleteAndRenameActionBehavior() // defaults QVERIFY(openContextMenu(fd)); QCOMPARE(fd.selectedFiles(), QStringList(ctx.file.fileName())); - QCOMPARE(rm->isEnabled(), !fd.isReadOnly()); - QCOMPARE(mv->isEnabled(), !fd.isReadOnly()); + QCOMPARE(rm->isEnabled(), !fd.testOption(QFileDialog::ReadOnly)); + QCOMPARE(mv->isEnabled(), !fd.testOption(QFileDialog::ReadOnly)); // change to non-defaults: - fd.setReadOnly(!fd.isReadOnly()); + fd.setOption(QFileDialog::ReadOnly, !fd.testOption(QFileDialog::ReadOnly)); QVERIFY(openContextMenu(fd)); QCOMPARE(fd.selectedFiles().size(), 1); - QCOMPARE(rm->isEnabled(), !fd.isReadOnly()); - QCOMPARE(mv->isEnabled(), !fd.isReadOnly()); + QCOMPARE(rm->isEnabled(), !fd.testOption(QFileDialog::ReadOnly)); + QCOMPARE(mv->isEnabled(), !fd.testOption(QFileDialog::ReadOnly)); // and changed back to defaults: - fd.setReadOnly(!fd.isReadOnly()); + fd.setOption(QFileDialog::ReadOnly, !fd.testOption(QFileDialog::ReadOnly)); QVERIFY(openContextMenu(fd)); QCOMPARE(fd.selectedFiles().size(), 1); - QCOMPARE(rm->isEnabled(), !fd.isReadOnly()); - QCOMPARE(mv->isEnabled(), !fd.isReadOnly()); + QCOMPARE(rm->isEnabled(), !fd.testOption(QFileDialog::ReadOnly)); + QCOMPARE(mv->isEnabled(), !fd.testOption(QFileDialog::ReadOnly)); } #endif // !QT_NO_CONTEXTMENU && !QT_NO_MENU diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST b/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST index f78d23c6b13..f2f0f8d26ee 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST @@ -1,13 +1,19 @@ winrt +[sort] +winrt [sort:QFileDialog usage] ubuntu b2qt [specialFiles] -ubuntu b2qt [dirsBeforeFiles] -ubuntu +ubuntu-16.04 +rhel-7.6 +windows-10 msvc-2017 +ubuntu-18.04 b2qt -windows -rhel -suse-leap +winrt +windows-10 msvc-2015 + +[drives] +winrt diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 665a116a3ad..f8f40e8488b 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -65,18 +65,18 @@ } \ } while(0) +Q_DECLARE_METATYPE(QDir::Filters) +Q_DECLARE_METATYPE(QFileDevice::Permissions) + +Q_LOGGING_CATEGORY(lcFileSystemModel, "qt.widgets.tests.qfilesystemmodel") + class tst_QFileSystemModel : public QObject { Q_OBJECT -public: - tst_QFileSystemModel(); - -public Q_SLOTS: - void init(); - void cleanup(); - private slots: void initTestCase(); + void cleanup(); + void indexPath(); void rootPath(); @@ -128,48 +128,33 @@ private slots: void fileInfo(); protected: - bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList()); - QModelIndex prepareTestModelRoot(const QString &test_path, QSignalSpy **spy2 = nullptr, - QSignalSpy **spy3 = nullptr); + bool createFiles(QFileSystemModel *model, const QString &test_path, + const QStringList &initial_files, int existingFileCount = 0, + const QStringList &initial_dirs = QStringList()); + QModelIndex prepareTestModelRoot(QFileSystemModel *model, const QString &test_path, + QSignalSpy **spy2 = nullptr, QSignalSpy **spy3 = nullptr); private: - QFileSystemModel *model; QString flatDirTestPath; QTemporaryDir m_tempDir; }; -tst_QFileSystemModel::tst_QFileSystemModel() : model(0) -{ -} - -void tst_QFileSystemModel::init() -{ - cleanup(); - QCOMPARE(model, nullptr); - model = new QFileSystemModel; -} - void tst_QFileSystemModel::cleanup() { - delete model; - model = 0; - QString tmp = flatDirTestPath; - QDir dir(tmp); - if (dir.exists(tmp)) { - QStringList list = dir.entryList(QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot); - for (int i = 0; i < list.count(); ++i) { - QFileInfo fi(dir.path() + '/' + list.at(i)); - if (fi.exists() && fi.isFile()) { - QFile p(fi.absoluteFilePath()); - p.setPermissions(QFile::ReadUser | QFile::ReadOwner | QFile::ExeOwner | QFile::ExeUser | QFile::WriteUser | QFile::WriteOwner | QFile::WriteOther); - QFile dead(dir.path() + '/' + list.at(i)); - dead.remove(); + QDir dir(flatDirTestPath); + if (dir.exists()) { + const QDir::Filters filters = QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot; + const QFileInfoList list = dir.entryInfoList(filters); + for (const QFileInfo &fi : list) { + if (fi.isDir()) { + QVERIFY(dir.rmdir(fi.fileName())); + } else { + QFile dead(fi.absoluteFilePath()); + dead.setPermissions(QFile::ReadUser | QFile::ReadOwner | QFile::ExeOwner | QFile::ExeUser | QFile::WriteUser | QFile::WriteOwner | QFile::WriteOther); + QVERIFY(dead.remove()); } - if (fi.exists() && fi.isDir()) - QVERIFY(dir.rmdir(list.at(i))); } - list = dir.entryList(QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot); - QCOMPARE(list.count(), 0); + QVERIFY(dir.entryInfoList(filters).isEmpty()); } } @@ -182,6 +167,7 @@ void tst_QFileSystemModel::initTestCase() void tst_QFileSystemModel::indexPath() { #if !defined(Q_OS_WIN) + QScopedPointer model(new QFileSystemModel); int depth = QDir::currentPath().count('/'); model->setRootPath(QDir::currentPath()); QString backPath; @@ -195,9 +181,10 @@ void tst_QFileSystemModel::indexPath() void tst_QFileSystemModel::rootPath() { + QScopedPointer model(new QFileSystemModel); QCOMPARE(model->rootPath(), QString(QDir().path())); - QSignalSpy rootChanged(model, SIGNAL(rootPathChanged(QString))); + QSignalSpy rootChanged(model.data(), &QFileSystemModel::rootPathChanged); QModelIndex root = model->setRootPath(model->rootPath()); root = model->setRootPath("this directory shouldn't exist"); QCOMPARE(rootChanged.count(), 0); @@ -243,6 +230,7 @@ void tst_QFileSystemModel::rootPath() void tst_QFileSystemModel::readOnly() { + QScopedPointer model(new QFileSystemModel); QCOMPARE(model->isReadOnly(), true); QTemporaryFile file(flatDirTestPath + QStringLiteral("/XXXXXX.dat")); QVERIFY2(file.open(), qPrintable(file.errorString())); @@ -263,19 +251,21 @@ void tst_QFileSystemModel::readOnly() class CustomFileIconProvider : public QFileIconProvider { public: - CustomFileIconProvider() : QFileIconProvider() { - mb = qApp->style()->standardIcon(QStyle::SP_MessageBoxCritical); - dvd = qApp->style()->standardIcon(QStyle::SP_DriveDVDIcon); + CustomFileIconProvider() : QFileIconProvider() + { + auto style = QApplication::style(); + mb = style->standardIcon(QStyle::SP_MessageBoxCritical); + dvd = style->standardIcon(QStyle::SP_DriveDVDIcon); } - virtual QIcon icon(const QFileInfo &info) const + QIcon icon(const QFileInfo &info) const override { if (info.isDir()) return mb; return QFileIconProvider::icon(info); } - virtual QIcon icon(IconType type) const + QIcon icon(IconType type) const override { if (type == QFileIconProvider::Folder) return dvd; @@ -289,69 +279,67 @@ private: void tst_QFileSystemModel::iconProvider() { + QScopedPointer model(new QFileSystemModel); QVERIFY(model->iconProvider()); - QFileIconProvider *p = new QFileIconProvider(); - model->setIconProvider(p); - QCOMPARE(model->iconProvider(), p); - model->setIconProvider(0); - delete p; + QScopedPointer provider(new QFileIconProvider); + model->setIconProvider(provider.data()); + QCOMPARE(model->iconProvider(), provider.data()); + model->setIconProvider(nullptr); + provider.reset(); - QFileSystemModel *myModel = new QFileSystemModel(); + QScopedPointer myModel(new QFileSystemModel); const QStringList documentPaths = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); QVERIFY(!documentPaths.isEmpty()); - const QString documentPath = documentPaths.front(); - myModel->setRootPath(documentPath); + myModel->setRootPath(documentPaths.constFirst()); //We change the provider, icons must be updated - CustomFileIconProvider *custom = new CustomFileIconProvider(); - myModel->setIconProvider(custom); + provider.reset(new CustomFileIconProvider); + myModel->setIconProvider(provider.data()); - QPixmap mb = qApp->style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(50, 50); + QPixmap mb = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(50, 50); QCOMPARE(myModel->fileIcon(myModel->index(QDir::homePath())).pixmap(50, 50), mb); - delete myModel; - delete custom; } -bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount, const QStringList &initial_dirs) +bool tst_QFileSystemModel::createFiles(QFileSystemModel *model, const QString &test_path, + const QStringList &initial_files, int existingFileCount, + const QStringList &initial_dirs) { - //qDebug() << (model->rowCount(model->index(test_path))) << existingFileCount << initial_files; + qCDebug(lcFileSystemModel) << (model->rowCount(model->index(test_path))) << existingFileCount << initial_files; bool timedOut = false; TRY_WAIT((model->rowCount(model->index(test_path)) == existingFileCount), &timedOut); if (timedOut) return false; - for (int i = 0; i < initial_dirs.count(); ++i) { - QDir dir(test_path); - if (!dir.exists()) { - qWarning() << "error" << test_path << "doesn't exists"; - return false; - } - if(!dir.mkdir(initial_dirs.at(i))) { - qWarning() << "error" << "failed to make" << initial_dirs.at(i); - return false; - } - //qDebug() << test_path + '/' + initial_dirs.at(i) << (QFile::exists(test_path + '/' + initial_dirs.at(i))); + QDir dir(test_path); + if (!dir.exists()) { + qWarning() << "error" << test_path << "doesn't exist"; + return false; } - for (int i = 0; i < initial_files.count(); ++i) { - QFile file(test_path + '/' + initial_files.at(i)); + for (const auto &initial_dir : initial_dirs) { + if (!dir.mkdir(initial_dir)) { + qWarning() << "error" << "failed to make" << initial_dir; + return false; + } + qCDebug(lcFileSystemModel) << test_path + '/' + initial_dir << (QFile::exists(test_path + '/' + initial_dir)); + } + for (const auto &initial_file : initial_files) { + QFile file(test_path + '/' + initial_file); if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) { - qDebug() << "failed to open file" << initial_files.at(i); + qDebug() << "failed to open file" << initial_file; return false; } if (!file.resize(1024 + file.size())) { - qDebug() << "failed to resize file" << initial_files.at(i); + qDebug() << "failed to resize file" << initial_file; return false; } if (!file.flush()) { - qDebug() << "failed to flush file" << initial_files.at(i); + qDebug() << "failed to flush file" << initial_file; return false; } file.close(); #if defined(Q_OS_WIN) - if (initial_files.at(i)[0] == '.') { - QString hiddenFile = QDir::toNativeSeparators(file.fileName()); - wchar_t nativeHiddenFile[MAX_PATH]; - memset(nativeHiddenFile, 0, sizeof(nativeHiddenFile)); - hiddenFile.toWCharArray(nativeHiddenFile); + if (initial_file[0] == '.') { + const QString hiddenFile = QDir::toNativeSeparators(file.fileName()); + const auto nativeHiddenFile = reinterpret_cast(hiddenFile.utf16()); #ifndef Q_OS_WINRT DWORD currentAttributes = ::GetFileAttributes(nativeHiddenFile); #else // !Q_OS_WINRT @@ -370,13 +358,13 @@ bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringLi } } #endif - //qDebug() << test_path + '/' + initial_files.at(i) << (QFile::exists(test_path + '/' + initial_files.at(i))); + qCDebug(lcFileSystemModel) << test_path + '/' + initial_file << (QFile::exists(test_path + '/' + initial_file)); } return true; } -QModelIndex tst_QFileSystemModel::prepareTestModelRoot(const QString &test_path, QSignalSpy **spy2, - QSignalSpy **spy3) +QModelIndex tst_QFileSystemModel::prepareTestModelRoot(QFileSystemModel *model, const QString &test_path, + QSignalSpy **spy2, QSignalSpy **spy3) { if (model->rowCount(model->index(test_path)) != 0) return QModelIndex(); @@ -387,9 +375,8 @@ QModelIndex tst_QFileSystemModel::prepareTestModelRoot(const QString &test_path, *spy3 = new QSignalSpy(model, &QFileSystemModel::rowsAboutToBeInserted); QStringList files = { "b", "d", "f", "h", "j", ".a", ".c", ".e", ".g" }; - QString l = "b,d,f,h,j,.a,.c,.e,.g"; - if (!createFiles(test_path, files)) + if (!createFiles(model, test_path, files)) return QModelIndex(); QModelIndex root = model->setRootPath(test_path); @@ -406,10 +393,10 @@ QModelIndex tst_QFileSystemModel::prepareTestModelRoot(const QString &test_path, void tst_QFileSystemModel::rowCount() { - const QString tmp = flatDirTestPath; QSignalSpy *spy2 = nullptr; QSignalSpy *spy3 = nullptr; - QModelIndex root = prepareTestModelRoot(flatDirTestPath, &spy2, &spy3); + QScopedPointer model(new QFileSystemModel); + QModelIndex root = prepareTestModelRoot(model.data(), flatDirTestPath, &spy2, &spy3); QVERIFY(root.isValid()); QVERIFY(spy2 && spy2->count() > 0); @@ -419,11 +406,11 @@ void tst_QFileSystemModel::rowCount() void tst_QFileSystemModel::rowsInserted_data() { QTest::addColumn("count"); - QTest::addColumn("ascending"); + QTest::addColumn("ascending"); for (int i = 0; i < 4; ++i) { const QByteArray iB = QByteArray::number(i); - QTest::newRow(("Qt::AscendingOrder " + iB).constData()) << i << (int)Qt::AscendingOrder; - QTest::newRow(("Qt::DescendingOrder " + iB).constData()) << i << (int)Qt::DescendingOrder; + QTest::newRow(("Qt::AscendingOrder " + iB).constData()) << i << Qt::AscendingOrder; + QTest::newRow(("Qt::DescendingOrder " + iB).constData()) << i << Qt::DescendingOrder; } } @@ -436,20 +423,21 @@ static inline QString lastEntry(const QModelIndex &root) void tst_QFileSystemModel::rowsInserted() { const QString tmp = flatDirTestPath; - QModelIndex root = prepareTestModelRoot(tmp); + QScopedPointer model(new QFileSystemModel); + QModelIndex root = prepareTestModelRoot(model.data(), tmp); QVERIFY(root.isValid()); - QFETCH(int, ascending); + QFETCH(Qt::SortOrder, ascending); QFETCH(int, count); - model->sort(0, (Qt::SortOrder)ascending); + model->sort(0, ascending); - QSignalSpy spy0(model, SIGNAL(rowsInserted(QModelIndex,int,int))); - QSignalSpy spy1(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy spy0(model.data(), &QAbstractItemModel::rowsInserted); + QSignalSpy spy1(model.data(), &QAbstractItemModel::rowsAboutToBeInserted); int oldCount = model->rowCount(root); QStringList files; for (int i = 0; i < count; ++i) files.append(QLatin1Char('c') + QString::number(i)); - QVERIFY(createFiles(tmp, files, 5)); + QVERIFY(createFiles(model.data(), tmp, files, 5)); QTRY_COMPARE(model->rowCount(root), oldCount + count); int totalRowsInserted = 0; for (int i = 0; i < spy0.count(); ++i) { @@ -469,7 +457,7 @@ void tst_QFileSystemModel::rowsInserted() } if (count == 0) QCOMPARE(spy1.count(), 0); else QVERIFY(spy1.count() >= 1); - QVERIFY(createFiles(tmp, QStringList(".hidden_file"), 5 + count)); + QVERIFY(createFiles(model.data(), tmp, QStringList(".hidden_file"), 5 + count)); if (count != 0) QTRY_VERIFY(spy0.count() >= 1); @@ -489,19 +477,21 @@ void tst_QFileSystemModel::rowsRemoved_data() void tst_QFileSystemModel::rowsRemoved() { const QString tmp = flatDirTestPath; - QModelIndex root = prepareTestModelRoot(tmp); + QScopedPointer model(new QFileSystemModel); + QModelIndex root = prepareTestModelRoot(model.data(), tmp); QVERIFY(root.isValid()); QFETCH(int, count); - QFETCH(int, ascending); - model->sort(0, (Qt::SortOrder)ascending); + QFETCH(Qt::SortOrder, ascending); + model->sort(0, ascending); - QSignalSpy spy0(model, SIGNAL(rowsRemoved(QModelIndex,int,int))); - QSignalSpy spy1(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy spy0(model.data(), &QAbstractItemModel::rowsRemoved); + QSignalSpy spy1(model.data(), &QAbstractItemModel::rowsAboutToBeRemoved); int oldCount = model->rowCount(root); for (int i = count - 1; i >= 0; --i) { - //qDebug() << "removing" << model->index(i, 0, root).data().toString(); - QVERIFY(QFile::remove(tmp + '/' + model->index(i, 0, root).data().toString())); + const QString fileName = model->index(i, 0, root).data().toString(); + qCDebug(lcFileSystemModel) << "removing" << fileName; + QVERIFY(QFile::remove(tmp + QLatin1Char('/') + fileName)); } for (int i = 0 ; i < 10; ++i) { if (count != 0) { @@ -520,18 +510,23 @@ void tst_QFileSystemModel::rowsRemoved() lst.append(model->index(i, 0, root).data().toString()); if (model->rowCount(root) == oldCount - count) break; - qDebug() << "still have:" << lst << QFile::exists(tmp + '/' + QString(".a")); + qCDebug(lcFileSystemModel) << "still have:" << lst << QFile::exists(tmp + QLatin1String("/.a")); QDir tmpLister(tmp); - qDebug() << tmpLister.entryList(); + qCDebug(lcFileSystemModel) << tmpLister.entryList(); } QTRY_COMPARE(model->rowCount(root), oldCount - count); - QVERIFY(QFile::exists(tmp + '/' + QString(".a"))); - QVERIFY(QFile::remove(tmp + '/' + QString(".a"))); - QVERIFY(QFile::remove(tmp + '/' + QString(".c"))); + QVERIFY(QFile::exists(tmp + QLatin1String("/.a"))); + QVERIFY(QFile::remove(tmp + QLatin1String("/.a"))); + QVERIFY(QFile::remove(tmp + QLatin1String("/.c"))); - if (count != 0) QVERIFY(spy0.count() >= 1); else QCOMPARE(spy0.count(), 0); - if (count != 0) QVERIFY(spy1.count() >= 1); else QCOMPARE(spy1.count(), 0); + if (count != 0) { + QVERIFY(spy0.count() >= 1); + QVERIFY(spy1.count() >= 1); + } else { + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); + } } void tst_QFileSystemModel::dataChanged_data() @@ -544,18 +539,19 @@ void tst_QFileSystemModel::dataChanged() QSKIP("This can't be tested right now since we don't watch files, only directories."); const QString tmp = flatDirTestPath; - QModelIndex root = prepareTestModelRoot(tmp); + QScopedPointer model(new QFileSystemModel); + QModelIndex root = prepareTestModelRoot(model.data(), tmp); QVERIFY(root.isValid()); QFETCH(int, count); - QFETCH(int, assending); - model->sort(0, (Qt::SortOrder)assending); + QFETCH(Qt::SortOrder, ascending); + model->sort(0, ascending); - QSignalSpy spy(model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + QSignalSpy spy(model.data(), &QAbstractItemModel::dataChanged); QStringList files; for (int i = 0; i < count; ++i) files.append(model->index(i, 0, root).data().toString()); - createFiles(tmp, files); + createFiles(model.data(), tmp, files); QTest::qWait(WAITTIME); @@ -566,64 +562,68 @@ void tst_QFileSystemModel::filters_data() { QTest::addColumn("files"); QTest::addColumn("dirs"); - QTest::addColumn("dirFilters"); + QTest::addColumn("dirFilters"); QTest::addColumn("nameFilters"); QTest::addColumn("rowCount"); - QTest::newRow("no dirs") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs) << QStringList() << 2; - QTest::newRow("no dirs - dot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDot) << QStringList() << 1; - QTest::newRow("no dirs - dotdot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDotDot) << QStringList() << 1; - QTest::newRow("no dirs - dotanddotdot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 0; - QTest::newRow("one dir - dot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDot) << QStringList() << 2; - QTest::newRow("one dir - dotdot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDotDot) << QStringList() << 2; - QTest::newRow("one dir - dotanddotdot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 1; - QTest::newRow("one dir") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs) << QStringList() << 3; - QTest::newRow("no dir + hidden") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::Hidden) << QStringList() << 2; - QTest::newRow("dir+hid+files") << (QStringList() << "a" << "b" << "c") << QStringList() << - (int)(QDir::Dirs | QDir::Files | QDir::Hidden) << QStringList() << 5; - QTest::newRow("dir+file+hid-dot .A") << (QStringList() << "a" << "b" << "c") << (QStringList() << ".A") << - (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << QStringList() << 4; - QTest::newRow("dir+files+hid+dot A") << (QStringList() << "a" << "b" << "c") << (QStringList() << "AFolder") << - (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << (QStringList() << "A*") << 2; - QTest::newRow("dir+files+hid+dot+cas1") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << - (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << (QStringList() << "Z") << 1; - QTest::newRow("dir+files+hid+dot+cas2") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << - (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << (QStringList() << "a") << 1; - QTest::newRow("dir+files+hid+dot+cas+alldir") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << - (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive | QDir::AllDirs) << (QStringList() << "Z") << 1; - QTest::newRow("case sensitive") << (QStringList() << "Antiguagdb" << "Antiguamtd" - << "Antiguamtp" << "afghanistangdb" << "afghanistanmtd") - << QStringList() << (int)(QDir::Files) << QStringList() << 5; + const QStringList abcList{QLatin1String("a"), QLatin1String("b"), QLatin1String("c")}; + const QStringList zList{QLatin1String("Z")}; + + QTest::newRow("no dirs") << abcList << QStringList() << QDir::Filters(QDir::Dirs) << QStringList() << 2; + QTest::newRow("no dirs - dot") << abcList << QStringList() << (QDir::Dirs | QDir::NoDot) << QStringList() << 1; + QTest::newRow("no dirs - dotdot") << abcList << QStringList() << (QDir::Dirs | QDir::NoDotDot) << QStringList() << 1; + QTest::newRow("no dirs - dotanddotdot") << abcList << QStringList() << (QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 0; + QTest::newRow("one dir - dot") << abcList << zList << (QDir::Dirs | QDir::NoDot) << QStringList() << 2; + QTest::newRow("one dir - dotdot") << abcList << zList << (QDir::Dirs | QDir::NoDotDot) << QStringList() << 2; + QTest::newRow("one dir - dotanddotdot") << abcList << zList << (QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 1; + QTest::newRow("one dir") << abcList << zList << QDir::Filters(QDir::Dirs) << QStringList() << 3; + QTest::newRow("no dir + hidden") << abcList << QStringList() << (QDir::Dirs | QDir::Hidden) << QStringList() << 2; + QTest::newRow("dir+hid+files") << abcList << QStringList() << + (QDir::Dirs | QDir::Files | QDir::Hidden) << QStringList() << 5; + QTest::newRow("dir+file+hid-dot .A") << abcList << QStringList{QLatin1String(".A")} << + (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << QStringList() << 4; + QTest::newRow("dir+files+hid+dot A") << abcList << QStringList{QLatin1String("AFolder")} << + (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << QStringList{QLatin1String("A*")} << 2; + QTest::newRow("dir+files+hid+dot+cas1") << abcList << zList << + (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << zList << 1; + QTest::newRow("dir+files+hid+dot+cas2") << abcList << zList << + (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << QStringList{QLatin1String("a")} << 1; + QTest::newRow("dir+files+hid+dot+cas+alldir") << abcList << zList << + (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive | QDir::AllDirs) << zList << 1; + + QTest::newRow("case sensitive") << QStringList{QLatin1String("Antiguagdb"), QLatin1String("Antiguamtd"), + QLatin1String("Antiguamtp"), QLatin1String("afghanistangdb"), QLatin1String("afghanistanmtd")} + << QStringList() << QDir::Filters(QDir::Files) << QStringList() << 5; } void tst_QFileSystemModel::filters() { QString tmp = flatDirTestPath; - QVERIFY(createFiles(tmp, QStringList())); + QScopedPointer model(new QFileSystemModel); + QVERIFY(createFiles(model.data(), tmp, QStringList())); QModelIndex root = model->setRootPath(tmp); QFETCH(QStringList, files); QFETCH(QStringList, dirs); - QFETCH(int, dirFilters); + QFETCH(QDir::Filters, dirFilters); QFETCH(QStringList, nameFilters); QFETCH(int, rowCount); if (nameFilters.count() > 0) model->setNameFilters(nameFilters); model->setNameFilterDisables(false); - model->setFilter((QDir::Filters)dirFilters); + model->setFilter(dirFilters); - QVERIFY(createFiles(tmp, files, 0, dirs)); + QVERIFY(createFiles(model.data(), tmp, files, 0, dirs)); QTRY_COMPARE(model->rowCount(root), rowCount); // Make sure that we do what QDir does QDir xFactor(tmp); - QDir::Filters filters = (QDir::Filters)dirFilters; QStringList dirEntries; if (nameFilters.count() > 0) - dirEntries = xFactor.entryList(nameFilters, filters); + dirEntries = xFactor.entryList(nameFilters, dirFilters); else - dirEntries = xFactor.entryList(filters); + dirEntries = xFactor.entryList(dirFilters); QCOMPARE(dirEntries.count(), rowCount); @@ -667,12 +667,13 @@ void tst_QFileSystemModel::nameFilters() { QStringList list; list << "a" << "b" << "c"; + QScopedPointer model(new QFileSystemModel); model->setNameFilters(list); model->setNameFilterDisables(false); QCOMPARE(model->nameFilters(), list); QString tmp = flatDirTestPath; - QVERIFY(createFiles(tmp, list)); + QVERIFY(createFiles(model.data(), tmp, list)); QModelIndex root = model->setRootPath(tmp); QTRY_COMPARE(model->rowCount(root), 3); @@ -693,15 +694,17 @@ void tst_QFileSystemModel::setData_data() << QDir::temp().absolutePath() + '/' + "a" << false; */ + + const QStringList abcList{QLatin1String("a"), QLatin1String("b"), QLatin1String("c")}; QTest::newRow("in current dir") << QString() - << (QStringList() << "a" << "b" << "c") + << abcList << "a" << "d" << true; QTest::newRow("in subdir") << "s" - << (QStringList() << "a" << "b" << "c") + << abcList << "a" << "d" << true; @@ -709,7 +712,8 @@ void tst_QFileSystemModel::setData_data() void tst_QFileSystemModel::setData() { - QSignalSpy spy(model, SIGNAL(fileRenamed(QString,QString,QString))); + QScopedPointer model(new QFileSystemModel); + QSignalSpy spy(model.data(), &QFileSystemModel::fileRenamed); QFETCH(QString, subdirName); QFETCH(QStringList, files); QFETCH(QString, oldFileName); @@ -722,7 +726,7 @@ void tst_QFileSystemModel::setData() QVERIFY(dir.mkdir(subdirName)); tmp.append('/' + subdirName); } - QVERIFY(createFiles(tmp, files)); + QVERIFY(createFiles(model.data(), tmp, files)); QModelIndex tmpIdx = model->setRootPath(flatDirTestPath); if (!subdirName.isEmpty()) { tmpIdx = model->index(tmp); @@ -760,6 +764,7 @@ void tst_QFileSystemModel::sortPersistentIndex() const QFileInfo fileInfo(file.fileName()); file.close(); QTRY_VERIFY(QDir(flatDirTestPath).entryInfoList().contains(fileInfo)); + QScopedPointer model(new QFileSystemModel); QModelIndex root = model->setRootPath(flatDirTestPath); QTRY_VERIFY(model->rowCount(root) > 0); @@ -786,8 +791,9 @@ void tst_QFileSystemModel::sort() { QFETCH(bool, fileDialogMode); - MyFriendFileSystemModel *myModel = new MyFriendFileSystemModel(); - QTreeView *tree = new QTreeView(); + QScopedPointer myModel(new MyFriendFileSystemModel); + QTreeView tree; + tree.setWindowTitle(QTest::currentTestFunction()); if (fileDialogMode && EmulationDetector::isRunningArmOnX86()) QSKIP("Crashes in QEMU. QTBUG-70572"); @@ -816,24 +822,23 @@ void tst_QFileSystemModel::sort() myModel->setRootPath(""); myModel->setFilter(QDir::AllEntries | QDir::System | QDir::Hidden); - tree->setSortingEnabled(true); - tree->setModel(myModel); - tree->show(); - tree->resize(800, 800); - QVERIFY(QTest::qWaitForWindowActive(tree)); - tree->header()->setSortIndicator(1,Qt::DescendingOrder); - tree->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); + tree.setSortingEnabled(true); + tree.setModel(myModel.data()); + tree.show(); + tree.resize(800, 800); + QVERIFY(QTest::qWaitForWindowActive(&tree)); + tree.header()->setSortIndicator(1, Qt::DescendingOrder); + tree.header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); QStringList dirsToOpen; - do - { - dirsToOpen< 0 ; --i) { QString path = dirsToOpen[i]; - tree->expand(myModel->index(path, 0)); + tree.expand(myModel->index(path, 0)); } - tree->expand(myModel->index(dirPath, 0)); + tree.expand(myModel->index(dirPath, 0)); QModelIndex parent = myModel->index(dirPath, 0); QList expectedOrder; expectedOrder << tempFile2.fileName() << tempFile.fileName() << dirPath + QChar('/') + ".." << dirPath + QChar('/') + "."; @@ -859,15 +864,13 @@ void tst_QFileSystemModel::sort() QTRY_COMPARE(dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString(), expectedOrder.at(i)); } } - - delete tree; - delete myModel; } void tst_QFileSystemModel::mkdir() { QString tmp = flatDirTestPath; QString newFolderPath = QDir::toNativeSeparators(tmp + '/' + "NewFoldermkdirtest4"); + QScopedPointer model(new QFileSystemModel); QModelIndex tmpDir = model->index(tmp); QVERIFY(tmpDir.isValid()); QDir bestatic(newFolderPath); @@ -902,6 +905,7 @@ void tst_QFileSystemModel::deleteFile() qWarning() << "unable to create" << newFilePath; } newFile.close(); + QScopedPointer model(new QFileSystemModel); QModelIndex idx = model->index(newFilePath); QVERIFY(idx.isValid()); QVERIFY(model->remove(idx)); @@ -963,7 +967,8 @@ void tst_QFileSystemModel::caseSensitivity() QString tmp = flatDirTestPath; QStringList files; files << "a" << "c" << "C"; - QVERIFY(createFiles(tmp, files)); + QScopedPointer model(new QFileSystemModel); + QVERIFY(createFiles(model.data(), tmp, files)); QModelIndex root = model->index(tmp); QStringList paths; QModelIndexList indexes; @@ -1013,13 +1018,14 @@ void tst_QFileSystemModel::dirsBeforeFiles() const int itemCount = 3; for (int i = 0; i < itemCount; ++i) { - QLatin1Char c('a' + i); - dir.mkdir(c + QLatin1String("-dir")); + QLatin1Char c('a' + char(i)); + QVERIFY(dir.mkdir(c + QLatin1String("-dir"))); QFile file(flatDirTestPath + QLatin1Char('/') + c + QLatin1String("-file")); - file.open(QIODevice::ReadWrite); + QVERIFY(file.open(QIODevice::ReadWrite)); file.close(); } + QScopedPointer model(new QFileSystemModel); QModelIndex root = model->setRootPath(flatDirTestPath); // Wait for model to be notified by the file system watcher QTRY_COMPARE(model->rowCount(root), 2 * itemCount); @@ -1073,7 +1079,7 @@ static inline QByteArray permissionRowName(bool readOnly, int permission) void tst_QFileSystemModel::permissions_data() { - QTest::addColumn("permissions"); + QTest::addColumn("permissions"); QTest::addColumn("readOnly"); static const int permissions[] = { @@ -1081,22 +1087,23 @@ void tst_QFileSystemModel::permissions_data() QFile::ReadOwner, QFile::WriteOwner|QFile::ReadOwner, }; - for (size_t i = 0; i < sizeof permissions / sizeof *permissions; ++i) { - QTest::newRow(permissionRowName(false, permissions[i]).constData()) << permissions[i] << false; - QTest::newRow(permissionRowName(true, permissions[i]).constData()) << permissions[i] << true; + for (int permission : permissions) { + QTest::newRow(permissionRowName(false, permission).constData()) << QFileDevice::Permissions(permission) << false; + QTest::newRow(permissionRowName(true, permission).constData()) << QFileDevice::Permissions(permission) << true; } } void tst_QFileSystemModel::permissions() // checks QTBUG-20503 { - QFETCH(int, permissions); + QFETCH(QFileDevice::Permissions, permissions); QFETCH(bool, readOnly); const QString tmp = flatDirTestPath; const QString file = tmp + QLatin1String("/f"); - QVERIFY(createFiles(tmp, QStringList() << "f")); + QScopedPointer model(new QFileSystemModel); + QVERIFY(createFiles(model.data(), tmp, QStringList{QLatin1String("f")})); - QVERIFY(QFile::setPermissions(file, QFile::Permissions(permissions))); + QVERIFY(QFile::setPermissions(file, permissions)); const QModelIndex root = model->setRootPath(tmp); diff --git a/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST b/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST index da52809aad5..e633e7c0a3d 100644 --- a/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST +++ b/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST @@ -1,2 +1,6 @@ [defaultButton] -* +ubuntu-16.04 +rhel-7.6 +opensuse-leap +ubuntu-18.04 +rhel-7.4 diff --git a/tests/auto/widgets/dialogs/qprogressdialog/BLACKLIST b/tests/auto/widgets/dialogs/qprogressdialog/BLACKLIST index 1789f515075..2b784414cd8 100644 --- a/tests/auto/widgets/dialogs/qprogressdialog/BLACKLIST +++ b/tests/auto/widgets/dialogs/qprogressdialog/BLACKLIST @@ -1,2 +1,2 @@ [autoShow] -osx ci +osx-10.13 diff --git a/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST b/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST index 4833af527fd..64a92d18aab 100644 --- a/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST +++ b/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST @@ -1,3 +1,2 @@ [prepareGeometryChangeInvalidateCache] -opensuse -opensuse-leap +opensuse-42.3 diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp index 4f3ff15ae01..7b914512ab8 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp @@ -1811,7 +1811,8 @@ void tst_QGraphicsItem::selected_multi() { // Ctrl-move on item1 - QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier); + const QPoint item1Point = view.mapFromScene(item1->scenePos()) + QPoint(1, 0); + QMouseEvent event(QEvent::MouseMove, item1Point, view.viewport()->mapToGlobal(item1Point), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier); QApplication::sendEvent(view.viewport(), &event); QVERIFY(!item1->isSelected()); QVERIFY(!item2->isSelected()); @@ -1832,7 +1833,8 @@ void tst_QGraphicsItem::selected_multi() { // Ctrl-move on item1 - QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier); + const QPoint item1Point = view.mapFromScene(item1->scenePos()) + QPoint(1, 0); + QMouseEvent event(QEvent::MouseMove, item1Point, view.viewport()->mapToGlobal(item1Point), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier); QApplication::sendEvent(view.viewport(), &event); QVERIFY(item1->isSelected()); QVERIFY(!item2->isSelected()); @@ -4151,6 +4153,8 @@ void tst_QGraphicsItem::cursor() QGraphicsView view(&scene); view.showFullScreen(); QVERIFY(QTest::qWaitForWindowExposed(&view)); + const Qt::CursorShape viewportShape = view.viewport()->cursor().shape(); + QGraphicsRectItem *item1 = scene.addRect(QRectF(-100, 0, 50, 50)); QGraphicsRectItem *item2 = scene.addRect(QRectF(50, 0, 50, 50)); @@ -4178,41 +4182,45 @@ void tst_QGraphicsItem::cursor() item1->setCursor(Qt::IBeamCursor); item2->setCursor(Qt::PointingHandCursor); - QTest::mouseMove(&view, view.rect().center()); - - const Qt::CursorShape viewportShape = view.viewport()->cursor().shape(); + QPoint viewCenter = view.rect().center(); + QPoint item1Center = view.mapFromScene(item1->sceneBoundingRect().center()); + QPoint item2Center = view.mapFromScene(item2->sceneBoundingRect().center()); { - QTest::mouseMove(view.viewport(), QPoint(100, 50)); - QMouseEvent event(QEvent::MouseMove, QPoint(100, 50), Qt::NoButton, 0, 0); + QMouseEvent event(QEvent::MouseMove, viewCenter, view.viewport()->mapToGlobal(viewCenter), Qt::NoButton, 0, 0); QApplication::sendEvent(view.viewport(), &event); } - QTRY_COMPARE(view.viewport()->cursor().shape(), viewportShape); + QCOMPARE(view.viewport()->cursor().shape(), viewportShape); { - QTest::mouseMove(view.viewport(), view.mapFromScene(item1->sceneBoundingRect().center())); - QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->sceneBoundingRect().center()), Qt::NoButton, 0, 0); + QMouseEvent event(QEvent::MouseMove, item1Center, view.viewport()->mapToGlobal(item1Center), Qt::NoButton, 0, 0); QApplication::sendEvent(view.viewport(), &event); } - QTRY_COMPARE(view.viewport()->cursor().shape(), item1->cursor().shape()); + QCOMPARE(view.viewport()->cursor().shape(), item1->cursor().shape()); { - QTest::mouseMove(view.viewport(), view.mapFromScene(item2->sceneBoundingRect().center())); - QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item2->sceneBoundingRect().center()), Qt::NoButton, 0, 0); + QMouseEvent event(QEvent::MouseMove, item2Center, view.viewport()->mapToGlobal(item2Center), Qt::NoButton, 0, 0); QApplication::sendEvent(view.viewport(), &event); } - QTRY_COMPARE(view.viewport()->cursor().shape(), item2->cursor().shape()); + QCOMPARE(view.viewport()->cursor().shape(), item2->cursor().shape()); { - QTest::mouseMove(view.viewport(), view.rect().center()); - QMouseEvent event(QEvent::MouseMove, QPoint(100, 25), Qt::NoButton, 0, 0); + QMouseEvent event(QEvent::MouseMove, viewCenter, view.viewport()->mapToGlobal(viewCenter), Qt::NoButton, 0, 0); QApplication::sendEvent(view.viewport(), &event); } - QTRY_COMPARE(view.viewport()->cursor().shape(), viewportShape); + QCOMPARE(view.viewport()->cursor().shape(), viewportShape); + + item1->setEnabled(false); + { + QMouseEvent event(QEvent::MouseMove, item1Center, view.viewport()->mapToGlobal(item1Center), Qt::NoButton, 0, 0); + QApplication::sendEvent(view.viewport(), &event); + } + + QCOMPARE(view.viewport()->cursor().shape(), viewportShape); } #endif /* @@ -4433,12 +4441,14 @@ protected: case QGraphicsItem::ItemPositionHasChanged: break; case QGraphicsItem::ItemMatrixChange: { +#if QT_DEPRECATED_SINCE(5, 13) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED QVariant variant; variant.setValue(matrix()); oldValues << variant; QT_WARNING_POP +#endif } break; case QGraphicsItem::ItemTransformChange: { @@ -4558,6 +4568,7 @@ void tst_QGraphicsItem::itemChange() QCOMPARE(tester.oldValues.last(), QVariant(true)); QCOMPARE(tester.isEnabled(), true); } +#if QT_DEPRECATED_SINCE(5, 13) { QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED // QDesktopWidget::screen() @@ -4577,6 +4588,7 @@ QT_WARNING_DISABLE_DEPRECATED // QDesktopWidget::screen() QCOMPARE(tester.matrix(), QMatrix().rotate(90)); QT_WARNING_POP } +#endif { tester.resetTransform(); ++changeCount; @@ -5055,12 +5067,6 @@ public: void tst_QGraphicsItem::paint() { -#if defined(Q_OS_MACOS) - if (QSysInfo::productVersion() == QLatin1String("10.12")) { - QSKIP("Test is very flaky on MacOS_10_12, see QTBUG-76566"); - } -#endif - QGraphicsScene scene; PaintTester paintTester; @@ -5090,22 +5096,25 @@ void tst_QGraphicsItem::paint() PaintTester tester2; scene2.addItem(&tester2); - //First show one paint - QTRY_COMPARE(tester2.painted, 1); + //First show at least one paint + QCOMPARE(tester2.painted, 0); + QTRY_VERIFY(tester2.painted > 0); + int painted = tester2.painted; //nominal case, update call paint tester2.update(); - QTRY_COMPARE(tester2.painted, 2); + QTRY_COMPARE(tester2.painted, painted + 1); + painted = tester2.painted; //we remove the item from the scene, number of updates is still the same tester2.update(); scene2.removeItem(&tester2); - QTRY_COMPARE(tester2.painted, 2); + QTRY_COMPARE(tester2.painted, painted); //We re-add the item, the number of paint should increase scene2.addItem(&tester2); tester2.update(); - QTRY_COMPARE(tester2.painted, 3); + QTRY_COMPARE(tester2.painted, painted + 1); } class HarakiriItem : public QGraphicsRectItem @@ -11375,7 +11384,7 @@ void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2() origView.reset(); childYellow->setOpacity(0.0); - QTRY_COMPARE(origView.repaints, 1); + QTRY_VERIFY(origView.repaints > 0); view.show(); qApp->setActiveWindow(&view); @@ -11390,8 +11399,8 @@ void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2() QEXPECT_FAIL("", "Fails on WinRT. Figure out why - QTBUG-68297", Abort); #endif - QTRY_COMPARE(origView.repaints, 1); - QTRY_COMPARE(view.repaints, 1); + QTRY_VERIFY(origView.repaints > 0); + QTRY_VERIFY(view.repaints > 0); } void tst_QGraphicsItem::QT_2649_focusScope() diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index 530c3bb4645..39aa65a4789 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -463,14 +463,13 @@ void tst_QGraphicsProxyWidget::setWidget() QCOMPARE(proxy->focusPolicy(), Qt::WheelFocus); QVERIFY(proxy->acceptDrops()); QCOMPARE(proxy->acceptHoverEvents(), true); // to get widget enter events - int left, top, right, bottom; - widget->getContentsMargins(&left, &top, &right, &bottom); + const QMarginsF margins = QMarginsF{widget->contentsMargins()}; qreal rleft, rtop, rright, rbottom; proxy->getContentsMargins(&rleft, &rtop, &rright, &rbottom); - QCOMPARE((qreal)left, rleft); - QCOMPARE((qreal)top, rtop); - QCOMPARE((qreal)right, rright); - QCOMPARE((qreal)bottom, rbottom); + QCOMPARE(margins.left(), rleft); + QCOMPARE(margins.top(), rtop); + QCOMPARE(margins.right(), rright); + QCOMPARE(margins.bottom(), rbottom); } else { // proxy shouldn't mess with the widget if it can't insert it. QCOMPARE(proxy->widget(), nullptr); diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST index b8b427b3dd1..a3c9e2e421b 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST @@ -3,11 +3,5 @@ opensuse-42.3 ci [removeFullyTransparentItem] osx-10.12 [tabFocus_sceneWithNestedFocusWidgets] -opensuse -opensuse-leap -[inputMethod] -opensuse -opensuse-leap -[hoverEvents_parentChild] -ubuntu +opensuse-42.3 diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST index ee13a37212c..22fce8620b4 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST @@ -1,20 +1,24 @@ [task255529_transformationAnchorMouseAndViewportMargins] -xcb +opensuse-leap +rhel-7.4 +ubuntu-16.04 +opensuse-42.3 [cursor] -xcb +opensuse-leap +ubuntu-16.04 +opensuse-42.3 [cursor2] -xcb -windows -[rubberBandExtendSelection] -xcb -[rotated_rubberBand] -xcb +ubuntu-16.04 [sendEvent] -xcb -[forwardMousePress] -xcb +ubuntu-16.04 +opensuse-42.3 [resizeAnchor] -xcb +ubuntu-16.04 +rhel-7.6 +opensuse-leap +ubuntu-18.04 +rhel-7.4 +opensuse-42.3 [update2] opensuse-42.3 [itemsInRect_cosmeticAdjust] diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 52cc7ed1285..4709499cd64 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -2219,7 +2219,7 @@ void tst_QGraphicsView::wheelEvent() { QWheelEvent event(view.mapFromScene(widget->boundingRect().center()), view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())), - 120, 0, 0, Qt::Horizontal); + QPoint(), QPoint(120, 0), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); QApplication::sendEvent(view.viewport(), &event); QCOMPARE(scene.orientation, Qt::Horizontal); } @@ -2228,7 +2228,7 @@ void tst_QGraphicsView::wheelEvent() { QWheelEvent event(view.mapFromScene(widget->boundingRect().center()), view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())), - 120, 0, 0, Qt::Vertical); + QPoint(), QPoint(0, 120), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); QApplication::sendEvent(view.viewport(), &event); QCOMPARE(scene.orientation, Qt::Vertical); } @@ -2526,9 +2526,8 @@ void tst_QGraphicsView::viewportUpdateMode2() view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); view.setScene(&dummyScene); view.ensurePolished(); // make sure we get the right content margins - int left, top, right, bottom; - view.getContentsMargins(&left, &top, &right, &bottom); - view.resize(200 + left + right, 200 + top + bottom); + const QMargins margins = view.contentsMargins(); + view.resize(200 + margins.left() + margins.right(), 200 + margins.top() + margins.bottom()); toplevel.show(); qApp->setActiveWindow(&toplevel); QVERIFY(QTest::qWaitForWindowExposed(&toplevel)); @@ -4043,9 +4042,8 @@ void tst_QGraphicsView::update() CustomView view(0, &toplevel); view.setScene(&dummyScene); view.ensurePolished(); // must ensure polished to get content margins right - int left, top, right, bottom; - view.getContentsMargins(&left, &top, &right, &bottom); - view.resize(200 + left + right, 200 + top + bottom); + const QMargins margins = view.contentsMargins(); + view.resize(200 + margins.left() + margins.right(), 200 + margins.top() + margins.bottom()); toplevel.show(); QVERIFY(QTest::qWaitForWindowExposed(&toplevel)); diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp index 85b42e54fec..d3477be9862 100644 --- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp @@ -2905,7 +2905,7 @@ public: Q_UNUSED(widget); qreal w = rect().width(); QRectF box(0, 0, w, 2400/w); - painter->drawRoundRect(box); + painter->drawRoundedRect(box, 25, 25, Qt::RelativeSize); painter->drawLine(box.topLeft(), box.bottomRight()); painter->drawLine(box.bottomLeft(), box.topRight()); } diff --git a/tests/auto/widgets/itemviews/qcolumnview/BLACKLIST b/tests/auto/widgets/itemviews/qcolumnview/BLACKLIST deleted file mode 100644 index bda01c700c4..00000000000 --- a/tests/auto/widgets/itemviews/qcolumnview/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[scrollTo:reverse] -osx diff --git a/tests/auto/widgets/itemviews/qheaderview/BLACKLIST b/tests/auto/widgets/itemviews/qheaderview/BLACKLIST index efb813f7d22..297a6fe7b71 100644 --- a/tests/auto/widgets/itemviews/qheaderview/BLACKLIST +++ b/tests/auto/widgets/itemviews/qheaderview/BLACKLIST @@ -1,3 +1,3 @@ [stretchAndRestoreLastSection] -opensuse opensuse-leap +opensuse-42.3 diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index 0b828b8484d..3a60b3b7c64 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -2516,9 +2516,9 @@ void tst_QListView::horizontalScrollingByVerticalWheelEvents() QPoint globalPos = lv.geometry().center(); QPoint pos = lv.viewport()->geometry().center(); - QWheelEvent wheelDownEvent(pos, globalPos, QPoint(0, 0), QPoint(0, -120), -120, Qt::Vertical, 0, 0); - QWheelEvent wheelUpEvent(pos, globalPos, QPoint(0, 0), QPoint(0, 120), 120, Qt::Vertical, 0, 0); - QWheelEvent wheelLeftDownEvent(pos, globalPos, QPoint(0, 0), QPoint(120, -120), -120, Qt::Vertical, 0, 0); + QWheelEvent wheelDownEvent(pos, globalPos, QPoint(0, 0), QPoint(0, -120), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); + QWheelEvent wheelUpEvent(pos, globalPos, QPoint(0, 0), QPoint(0, 120), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); + QWheelEvent wheelLeftDownEvent(pos, globalPos, QPoint(0, 0), QPoint(120, -120), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); int hValue = lv.horizontalScrollBar()->value(); QApplication::sendEvent(lv.viewport(), &wheelDownEvent); diff --git a/tests/auto/widgets/itemviews/qtableview/BLACKLIST b/tests/auto/widgets/itemviews/qtableview/BLACKLIST index be90475a6f8..9648cef3de7 100644 --- a/tests/auto/widgets/itemviews/qtableview/BLACKLIST +++ b/tests/auto/widgets/itemviews/qtableview/BLACKLIST @@ -1,4 +1,3 @@ [moveCursorBiggerJump] osx -[columnViewportPosition] -winrt # QTBUG-72853 + diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index bf874080567..6bbb30a6dbc 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -4074,8 +4074,10 @@ void tst_QTableView::mouseWheel() view.verticalScrollBar()->setValue(10); QPoint pos = view.viewport()->geometry().center(); - QWheelEvent verticalEvent(pos, delta, 0, 0, Qt::Vertical); - QWheelEvent horizontalEvent(pos, delta, 0, 0, Qt::Horizontal); + QWheelEvent verticalEvent(pos, view.mapToGlobal(pos), QPoint(), QPoint(0, delta), + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); + QWheelEvent horizontalEvent(pos, view.mapToGlobal(pos), QPoint(), QPoint(delta, 0), + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); QApplication::sendEvent(view.viewport(), &horizontalEvent); QVERIFY(qAbs(view.horizontalScrollBar()->value() - horizontalPositon) < 15); QApplication::sendEvent(view.viewport(), &verticalEvent); @@ -4350,7 +4352,9 @@ void tst_QTableView::taskQTBUG_5237_wheelEventOnHeader() int sbValueBefore = view.verticalScrollBar()->value(); QHeaderView *header = view.verticalHeader(); QTest::mouseMove(header); - QWheelEvent wheelEvent(header->geometry().center(), -720, 0, 0); + QPoint pos = header->geometry().center(); + QWheelEvent wheelEvent(pos, header->viewport()->mapToGlobal(pos), QPoint(), QPoint(0, -720), + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); QApplication::sendEvent(header->viewport(), &wheelEvent); int sbValueAfter = view.verticalScrollBar()->value(); QVERIFY(sbValueBefore != sbValueAfter); diff --git a/tests/auto/widgets/kernel/qapplication/BLACKLIST b/tests/auto/widgets/kernel/qapplication/BLACKLIST index d7de7bf16e7..ac65a97c408 100644 --- a/tests/auto/widgets/kernel/qapplication/BLACKLIST +++ b/tests/auto/widgets/kernel/qapplication/BLACKLIST @@ -1,4 +1,4 @@ [touchEventPropagation] -# QTBUG-66745 -opensuse opensuse-leap +# QTBUG-66745 +opensuse-42.3 diff --git a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp index 8dd9d7c428f..00bde3cb256 100644 --- a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp +++ b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp @@ -194,7 +194,7 @@ void tst_QBoxLayout::setGeometry() setFrameless(&toplevel); QWidget w(&toplevel); QVBoxLayout *lay = new QVBoxLayout; - lay->setMargin(0); + lay->setContentsMargins(0, 0, 0, 0); lay->setSpacing(0); QHBoxLayout *lay2 = new QHBoxLayout; QDial *dial = new QDial; @@ -271,7 +271,7 @@ void tst_QBoxLayout::widgetSurplus() QDialog window; QScopedPointer marginEater(new MarginEatingStyle); QVBoxLayout *vbox = new QVBoxLayout(&window); - vbox->setMargin(0); + vbox->setContentsMargins(0, 0, 0, 0); vbox->setSpacing(0); QLabel *hiddenLabel = new QLabel(tr("Invisible label")); diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp index 5e0327319b1..1d63d140fb5 100644 --- a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp +++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp @@ -219,9 +219,9 @@ void tst_QGridLayout::badDistributionBug() QDialog dialog; Ui::SortDialog ui; ui.setupUi(&dialog); - ui.gridLayout->setMargin(0); + ui.gridLayout->setContentsMargins(0, 0, 0, 0); ui.gridLayout->setSpacing(0); - ui.vboxLayout->setMargin(0); + ui.vboxLayout->setContentsMargins(0, 0, 0, 0); ui.vboxLayout->setSpacing(0); ui.okButton->setFixedHeight(20); ui.moreButton->setFixedHeight(20); @@ -237,7 +237,7 @@ void tst_QGridLayout::setMinAndMaxSize() QWidget widget; setFrameless(&widget); QGridLayout layout(&widget); - layout.setMargin(0); + layout.setContentsMargins(0, 0, 0, 0); layout.setSpacing(0); layout.setSizeConstraint(QLayout::SetMinAndMaxSize); widget.show(); @@ -396,7 +396,7 @@ void tst_QGridLayout::spacingAndSpacers() QWidget widget; setFrameless(&widget); QGridLayout layout(&widget); - layout.setMargin(0); + layout.setContentsMargins(0, 0, 0, 0); layout.setSpacing(0); widget.show(); @@ -1541,7 +1541,7 @@ void tst_QGridLayout::spacerWithSpacing() QWidget window; QGridLayout layout(&window); layout.setSpacing(1); - layout.setMargin(0); + layout.setContentsMargins(0, 0, 0, 0); populate(&layout, 0, i); populate(&layout, 1, j); populate(&layout, 2, k); @@ -1651,7 +1651,7 @@ void tst_QGridLayout::taskQTBUG_52357_spacingWhenItemIsHidden() QWidget widget; setFrameless(&widget); QGridLayout layout(&widget); - layout.setMargin(0); + layout.setContentsMargins(0, 0, 0, 0); layout.setSpacing(5); QPushButton button1; layout.addWidget(&button1, 0, 0); diff --git a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp index 936f581d89f..140a367afe5 100644 --- a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp +++ b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp @@ -308,7 +308,7 @@ void tst_QLayout::controlTypes2() { QWidget main; QVBoxLayout *const layout = new QVBoxLayout(&main); - layout->setMargin(0); + layout->setContentsMargins(0, 0, 0, 0); QComboBox *combo = new QComboBox(&main); layout->addWidget(combo); QCOMPARE(layout->controlTypes(), QSizePolicy::ComboBox); @@ -319,7 +319,7 @@ void tst_QLayout::adjustSizeShouldMakeSureLayoutIsActivated() QWidget main; QVBoxLayout *const layout = new QVBoxLayout(&main); - layout->setMargin(0); + layout->setContentsMargins(0, 0, 0, 0); SizeHinterFrame *frame = new SizeHinterFrame(QSize(200, 10), QSize(200, 8)); frame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); layout->addWidget(frame); diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index 03bec4286b6..02e97e4b4e2 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -2,30 +2,34 @@ [normalGeometry] ubuntu-16.04 [saveRestoreGeometry] -xcb -b2qt -[restoreVersion1Geometry] -osx -[updateWhileMinimized] +opensuse-leap ubuntu-16.04 +b2qt +opensuse-42.3 +[restoreVersion1Geometry] +ubuntu-16.04 +[updateWhileMinimized] ubuntu-18.04 rhel-7.4 +ubuntu-16.04 rhel-7.6 -osx [focusProxyAndInputMethods] -linux -[raise] -# QTBUG-68175 -opensuse +ubuntu-16.04 +rhel-7.6 opensuse-leap -[setWindowGeometry] -osx -[windowMoveResize] -osx +ubuntu-18.04 +rhel-7.4 +opensuse-42.3 +[raise] +opensuse-leap +# QTBUG-68175 +opensuse-42.3 [childEvents] osx ci [renderInvisible] -osx +osx-10.12 +osx-10.11 +osx-10.14 [optimizedResizeMove] osx [optimizedResize_topLevel] @@ -40,12 +44,14 @@ opensuse opensuse-leap [moveInResizeEvent] ubuntu-16.04 -[moveChild:right] -osx -[activateWindow] -osx-10.12 ci [multipleToplevelFocusCheck] -linux +ubuntu-16.04 +rhel-7.6 +opensuse-leap +ubuntu-18.04 +rhel-7.4 +opensuse-42.3 [windowState] # QTBUG-75270 winrt + diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 103be88f866..bfc26318426 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -182,6 +182,8 @@ private slots: void tabOrderWithCompoundWidgets(); void tabOrderNoChange(); void tabOrderNoChange2(); + void appFocusWidgetWithFocusProxyLater(); + void appFocusWidgetWhenLosingFocusProxy(); #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) void activation(); #endif @@ -2032,6 +2034,51 @@ void tst_QWidget::tabOrderNoChange2() QCOMPARE(focusChainBackward, getFocusChain(&w, false)); } +void tst_QWidget::appFocusWidgetWithFocusProxyLater() +{ + // Given a lineedit without a focus proxy + QWidget window; + window.setWindowTitle(QTest::currentTestFunction()); + QLineEdit *lineEditFocusProxy = new QLineEdit(&window); + QLineEdit *lineEdit = new QLineEdit(&window); + lineEdit->setFocus(); + window.show(); + QApplication::setActiveWindow(&window); + QVERIFY(QTest::qWaitForWindowActive(&window)); + QCOMPARE(QApplication::focusWidget(), lineEdit); + + // When setting a focus proxy for the focus widget (like QWebEngineView does) + lineEdit->setFocusProxy(lineEditFocusProxy); + + // Then the focus widget should be updated + QCOMPARE(QApplication::focusWidget(), lineEditFocusProxy); + + // So that deleting the lineEdit and later the window, doesn't crash + delete lineEdit; + QCOMPARE(QApplication::focusWidget(), nullptr); +} + +void tst_QWidget::appFocusWidgetWhenLosingFocusProxy() +{ + // Given a lineedit with a focus proxy + QWidget window; + window.setWindowTitle(QTest::currentTestFunction()); + QLineEdit *lineEditFocusProxy = new QLineEdit(&window); + QLineEdit *lineEdit = new QLineEdit(&window); + lineEdit->setFocusProxy(lineEditFocusProxy); + lineEdit->setFocus(); + window.show(); + QApplication::setActiveWindow(&window); + QVERIFY(QTest::qWaitForWindowActive(&window)); + QCOMPARE(QApplication::focusWidget(), lineEditFocusProxy); + + // When unsetting the focus proxy + lineEdit->setFocusProxy(nullptr); + + // Then the application focus widget should be back to the lineedit + QCOMPARE(QApplication::focusWidget(), lineEdit); +} + #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) void tst_QWidget::activation() { @@ -6142,7 +6189,7 @@ void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint() { if (m_platform != QStringLiteral("xcb")) QSKIP("This test is for X11 only."); - // Same size as in QWidget::create_sys(). + // Same size as in QWidgetPrivate::create. const QSize desktopSize = QApplication::desktop()->size(); const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10); @@ -8026,7 +8073,7 @@ public: sp.setHeightForWidth(hfwLayout); QVBoxLayout *vbox = new QVBoxLayout; - vbox->setMargin(0); + vbox->setContentsMargins(0, 0, 0, 0); vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false)); setLayout(vbox); } @@ -9425,7 +9472,7 @@ void tst_QWidget::initialPosForDontShowOnScreenWidgets() const QPoint expectedPos(0, 0); QWidget widget; widget.setAttribute(Qt::WA_DontShowOnScreen); - widget.winId(); // Make sure create_sys is called. + widget.winId(); // Make sure QWidgetPrivate::create is called. QCOMPARE(widget.pos(), expectedPos); QCOMPARE(widget.geometry().topLeft(), expectedPos); } @@ -9435,7 +9482,7 @@ void tst_QWidget::initialPosForDontShowOnScreenWidgets() QWidget widget; widget.setAttribute(Qt::WA_DontShowOnScreen); widget.move(expectedPos); - widget.winId(); // Make sure create_sys is called. + widget.winId(); // Make sure QWidgetPrivate::create is called. QCOMPARE(widget.pos(), expectedPos); QCOMPARE(widget.geometry().topLeft(), expectedPos); } @@ -10073,7 +10120,7 @@ void tst_QWidget::grabMouse() w.setObjectName(QLatin1String("tst_qwidget_grabMouse")); w.setWindowTitle(w.objectName()); QLayout *layout = new QVBoxLayout(&w); - layout->setMargin(50); + layout->setContentsMargins(50, 50, 50, 50); GrabLoggerWidget *grabber = new GrabLoggerWidget(&log, &w); const QString grabberObjectName = QLatin1String("tst_qwidget_grabMouse_grabber"); grabber->setObjectName(grabberObjectName); diff --git a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST index 381cf76c46f..39d7b695f6c 100644 --- a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST @@ -4,4 +4,5 @@ opensuse-42.3 ubuntu-16.04 [setWindowState] ubuntu-18.04 -rhel +rhel-7.6 + diff --git a/tests/auto/widgets/util/qcompleter/BLACKLIST b/tests/auto/widgets/util/qcompleter/BLACKLIST index fdc424b6ac1..367270fdf27 100644 --- a/tests/auto/widgets/util/qcompleter/BLACKLIST +++ b/tests/auto/widgets/util/qcompleter/BLACKLIST @@ -1,2 +1,6 @@ [QTBUG_14292_filesystem] -linux +ubuntu-16.04 +opensuse-leap +rhel-7.4 +rhel-6.6 +opensuse-42.3 diff --git a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp index d8fbb8e041a..f77efe036a8 100644 --- a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp +++ b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp @@ -1662,8 +1662,12 @@ void tst_QAbstractSlider::wheelEvent() slider->setOrientation(sliderOrientation); Qt::KeyboardModifier k = withModifiers ? Qt::ControlModifier : Qt::NoModifier; - QWheelEvent event(slider->rect().bottomRight() + distanceFromBottomRight, WHEEL_DELTA * deltaMultiple, - Qt::NoButton, k, wheelOrientation); + + const QPoint wheelPoint = slider->rect().bottomRight() + distanceFromBottomRight; + const QPoint angleDelta(wheelOrientation == Qt::Horizontal ? WHEEL_DELTA * deltaMultiple : 0, + wheelOrientation == Qt::Vertical ? WHEEL_DELTA * deltaMultiple : 0); + QWheelEvent event(wheelPoint, slider->mapToGlobal(wheelPoint), QPoint(), angleDelta, + Qt::NoButton, k, Qt::NoScrollPhase, false); QVERIFY(applicationInstance->sendEvent(slider,&event)); #ifdef Q_OS_MAC QEXPECT_FAIL("Normal data page", "QTBUG-23679", Continue); @@ -1674,8 +1678,8 @@ void tst_QAbstractSlider::wheelEvent() slider->setSliderPosition(initialSliderPosition); k = withModifiers ? Qt::ShiftModifier : Qt::NoModifier; - event = QWheelEvent(slider->rect().bottomRight() + distanceFromBottomRight, WHEEL_DELTA * deltaMultiple, - Qt::NoButton, k, wheelOrientation); + event = QWheelEvent(wheelPoint, slider->mapToGlobal(wheelPoint), QPoint(), angleDelta, + Qt::NoButton, k, Qt::NoScrollPhase, false); QSignalSpy spy1(slider, SIGNAL(actionTriggered(int))); QSignalSpy spy2(slider, SIGNAL(valueChanged(int))); QVERIFY(applicationInstance->sendEvent(slider,&event)); @@ -1715,16 +1719,16 @@ void tst_QAbstractSlider::fineGrainedWheelEvent() slider->setSliderPosition(0); const int singleStepDelta = invertedControls ? (-WHEEL_DELTA / 3) : (WHEEL_DELTA / 3); - - QWheelEvent eventDown(slider->rect().bottomRight(), singleStepDelta / 2, - Qt::NoButton, Qt::NoModifier, Qt::Vertical); + const QPoint wheelPoint = slider->rect().bottomRight(); + QWheelEvent eventDown(wheelPoint, slider->mapToGlobal(wheelPoint), QPoint(), QPoint(0, singleStepDelta / 2), + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); QVERIFY(applicationInstance->sendEvent(slider,&eventDown)); QCOMPARE(slider->sliderPosition(), 0); QVERIFY(applicationInstance->sendEvent(slider,&eventDown)); QCOMPARE(slider->sliderPosition(), 1); - QWheelEvent eventUp(slider->rect().bottomRight(), -singleStepDelta / 2, - Qt::NoButton, Qt::NoModifier, Qt::Vertical); + QWheelEvent eventUp(wheelPoint, slider->mapToGlobal(wheelPoint), QPoint(), QPoint(0, -singleStepDelta / 2), + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); QVERIFY(applicationInstance->sendEvent(slider,&eventUp)); QCOMPARE(slider->sliderPosition(), 1); QVERIFY(applicationInstance->sendEvent(slider,&eventUp)); diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index a5767708119..4e16edaca83 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -254,12 +254,22 @@ void tst_QComboBox::getSetCheck() obj1.setMaxCount(INT_MAX); QCOMPARE(INT_MAX, obj1.maxCount()); + // QCompleter *QComboBox::completer() + // void QComboBox::setCompleter(QCompleter *) + obj1.setCompleter(nullptr); + QCOMPARE(nullptr, obj1.completer()); + QCompleter completer; + obj1.setCompleter(&completer); + QVERIFY(obj1.completer() == nullptr); // no QLineEdit is set + +#if QT_DEPRECATED_SINCE(5, 13) // bool QComboBox::autoCompletion() // void QComboBox::setAutoCompletion(bool) obj1.setAutoCompletion(false); QCOMPARE(false, obj1.autoCompletion()); obj1.setAutoCompletion(true); QCOMPARE(true, obj1.autoCompletion()); +#endif // bool QComboBox::duplicatesEnabled() // void QComboBox::setDuplicatesEnabled(bool) @@ -317,6 +327,9 @@ void tst_QComboBox::getSetCheck() QCOMPARE(var8, obj1.lineEdit()); // delete var8; // No delete, since QComboBox takes ownership + // After setting a line edit, completer() should not return nullptr anymore + QVERIFY(obj1.completer() != nullptr); + // const QValidator * QComboBox::validator() // void QComboBox::setValidator(const QValidator *) QIntValidator *var9 = new QIntValidator(0); @@ -777,7 +790,9 @@ void tst_QComboBox::virtualAutocompletion() QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); QComboBox *testWidget = topLevel.comboBox(); testWidget->clear(); +#if QT_DEPRECATED_SINCE(5, 13) testWidget->setAutoCompletion(true); +#endif testWidget->addItem("Foo"); testWidget->addItem("Bar"); testWidget->addItem("Boat"); @@ -837,7 +852,9 @@ void tst_QComboBox::autoCompletionCaseSensitivity() QCOMPARE(qApp->focusWidget(), (QWidget *)testWidget); testWidget->clear(); +#if QT_DEPRECATED_SINCE(5, 13) testWidget->setAutoCompletion(true); +#endif testWidget->addItem("Cow"); testWidget->addItem("irrelevant1"); testWidget->addItem("aww"); @@ -2102,7 +2119,9 @@ void tst_QComboBox::mouseWheel() box.setEditable(i==0?false:true); box.setCurrentIndex(startIndex); - QWheelEvent event = QWheelEvent(box.rect().bottomRight() , WHEEL_DELTA * wheelDirection, Qt::NoButton, Qt::NoModifier); + const QPoint wheelPoint = box.rect().bottomRight(); + QWheelEvent event(wheelPoint, box.mapToGlobal(wheelPoint), QPoint(), QPoint(0, WHEEL_DELTA * wheelDirection), + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); QVERIFY(applicationInstance->sendEvent(&box,&event)); QCOMPARE(box.currentIndex(), expectedIndex); @@ -2131,7 +2150,9 @@ void tst_QComboBox::popupWheelHandling() comboBox->showPopup(); QTRY_VERIFY(comboBox->view() && comboBox->view()->isVisible()); const QPoint popupPos = comboBox->view()->pos(); - QWheelEvent event(QPointF(10, 10), WHEEL_DELTA, Qt::NoButton, Qt::NoModifier); + const QPoint wheelPoint(10, 10); + QWheelEvent event(wheelPoint, scrollArea.mapToGlobal(wheelPoint), QPoint(), QPoint(0, WHEEL_DELTA), + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); QVERIFY(QCoreApplication::sendEvent(scrollArea.windowHandle(), &event)); QCoreApplication::processEvents(); QVERIFY(comboBox->view()->isVisible()); @@ -3050,7 +3071,9 @@ void tst_QComboBox::task_QTBUG_31146_popupCompletion() { QComboBox comboBox; comboBox.setEditable(true); +#if QT_DEPRECATED_SINCE(5, 13) comboBox.setAutoCompletion(true); +#endif comboBox.setInsertPolicy(QComboBox::NoInsert); comboBox.completer()->setCaseSensitivity(Qt::CaseInsensitive); comboBox.completer()->setCompletionMode(QCompleter::PopupCompletion); diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp index cd045e476cf..810f081b737 100644 --- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp @@ -3141,7 +3141,6 @@ void tst_QDateTimeEdit::wheelEvent_data() { #if QT_CONFIG(wheelevent) QTest::addColumn("angleDelta"); - QTest::addColumn("qt4Delta"); QTest::addColumn("stepModifier"); QTest::addColumn("modifiers"); QTest::addColumn("source"); @@ -3255,7 +3254,6 @@ void tst_QDateTimeEdit::wheelEvent_data() modifierName.latin1(), sourceName.latin1()) << angleDelta - << units << static_cast(stepModifier) << modifiers << source @@ -3277,7 +3275,6 @@ void tst_QDateTimeEdit::wheelEvent() { #if QT_CONFIG(wheelevent) QFETCH(QPoint, angleDelta); - QFETCH(int, qt4Delta); QFETCH(int, stepModifier); QFETCH(Qt::KeyboardModifiers, modifiers); QFETCH(Qt::MouseEventSource, source); @@ -3294,9 +3291,8 @@ void tst_QDateTimeEdit::wheelEvent() style->stepModifier = static_cast(stepModifier); edit.setStyle(style.data()); - QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta, - Qt::Vertical, Qt::NoButton, modifiers, Qt::NoScrollPhase, - source); + QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, + Qt::NoButton, modifiers, Qt::NoScrollPhase, false, source); QCOMPARE(edit.date(), startDate); for (QDate expected : expectedDates) { diff --git a/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST b/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST index c1b6c9693e0..8f5648d0f9a 100644 --- a/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST +++ b/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST @@ -1,2 +1,4 @@ [editingFinished] -* +osx-10.12 +osx-10.14 +osx-10.13 diff --git a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp index a20b5568da0..c760d9cc99b 100644 --- a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp +++ b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp @@ -1377,7 +1377,6 @@ void tst_QDoubleSpinBox::wheelEvents_data() { #if QT_CONFIG(wheelevent) QTest::addColumn("angleDelta"); - QTest::addColumn("qt4Delta"); QTest::addColumn("stepModifier"); QTest::addColumn("modifier"); QTest::addColumn("source"); @@ -1476,7 +1475,6 @@ void tst_QDoubleSpinBox::wheelEvents_data() modifierName.latin1(), sourceName.latin1()) << angleDelta - << units << static_cast(stepModifier) << modifiers << source @@ -1496,7 +1494,6 @@ void tst_QDoubleSpinBox::wheelEvents() { #if QT_CONFIG(wheelevent) QFETCH(QPoint, angleDelta); - QFETCH(int, qt4Delta); QFETCH(int, stepModifier); QFETCH(Qt::KeyboardModifiers, modifier); QFETCH(Qt::MouseEventSource, source); @@ -1512,9 +1509,8 @@ void tst_QDoubleSpinBox::wheelEvents() style->stepModifier = static_cast(stepModifier); spinBox.setStyle(style.data()); - QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta, - Qt::Vertical, Qt::NoButton, modifier, Qt::NoScrollPhase, - source); + QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, + Qt::NoButton, modifier, Qt::NoScrollPhase, false, source); for (int expected : expectedValues) { qApp->sendEvent(&spinBox, &event); QCOMPARE(spinBox.value(), expected); diff --git a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp index 34862f68104..f599ac73c6a 100644 --- a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp +++ b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp @@ -461,7 +461,7 @@ void tst_QLabel::unicodeText() QVBoxLayout *layout = new QVBoxLayout(); QLabel *label = new QLabel(text, &frame); layout->addWidget(label); - layout->setMargin(8); + layout->setContentsMargins(8, 8, 8, 8); frame.setLayout(layout); frame.show(); QVERIFY(QTest::qWaitForWindowExposed(&frame)); diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index f1bc3e8dd48..1c68a5f752e 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -3530,6 +3530,13 @@ void tst_QLineEdit::textMargin() centerOnScreen(&tlw); tlw.show(); + const QMargins margins = testWidget.textMargins(); + QCOMPARE(left, margins.left()); + QCOMPARE(top, margins.top()); + QCOMPARE(right, margins.right()); + QCOMPARE(bottom, margins.bottom()); + +#if QT_DEPRECATED_SINCE(5, 14) int l; int t; int r; @@ -3539,6 +3546,7 @@ void tst_QLineEdit::textMargin() QCOMPARE(top, t); QCOMPARE(right, r); QCOMPARE(bottom, b); +#endif QTest::mouseClick(&testWidget, Qt::LeftButton, 0, mousePressPos); QTRY_COMPARE(testWidget.cursorPosition(), cursorPosition); diff --git a/tests/auto/widgets/widgets/qmdiarea/BLACKLIST b/tests/auto/widgets/widgets/qmdiarea/BLACKLIST index b1c8d7dfded..1dd876ea973 100644 --- a/tests/auto/widgets/widgets/qmdiarea/BLACKLIST +++ b/tests/auto/widgets/widgets/qmdiarea/BLACKLIST @@ -1,7 +1,16 @@ -[updateScrollBars] -osx [tileSubWindows] -osx -xcb +ubuntu-16.04 +rhel-7.6 +opensuse-leap +osx-10.11 +osx-10.13 +ubuntu-18.04 +osx-10.14 +rhel-7.4 +osx-10.12 +opensuse-42.3 [resizeTimer] -osx +osx-10.12 +osx-10.14 +osx-10.13 + diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp index 046899ce051..b8abd78657a 100644 --- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp +++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp @@ -880,7 +880,7 @@ void tst_QMdiArea::minimumSizeHint() { QMdiArea workspace; workspace.show(); - QSize expectedSize(workspace.style()->pixelMetric(QStyle::PM_MDIMinimizedWidth), + QSize expectedSize(workspace.style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth), workspace.style()->pixelMetric(QStyle::PM_TitleBarHeight)); qApp->processEvents(); QAbstractScrollArea dummyScrollArea; diff --git a/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST b/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST deleted file mode 100644 index 26d1776b0d4..00000000000 --- a/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[setOpaqueResizeAndMove] -osx-10.12 diff --git a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp index 2b59a227b32..b8891fab953 100644 --- a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp +++ b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp @@ -613,7 +613,7 @@ void tst_QMdiSubWindow::showShaded() // Calculate mouse position for bottom right corner and simulate a // vertical resize with the mouse. - int offset = window->style()->pixelMetric(QStyle::PM_MDIFrameWidth) / 2; + int offset = window->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth) / 2; QPoint mousePosition(window->width() - qMax(offset, 2), window->height() - qMax(offset, 2)); QWidget *mouseReceiver = nullptr; #ifdef Q_OS_MAC @@ -759,7 +759,7 @@ void tst_QMdiSubWindow::setOpaqueResizeAndMove() QTRY_COMPARE(priv->resizeTimerId, -1); // Enter resize mode. - int offset = window->style()->pixelMetric(QStyle::PM_MDIFrameWidth) / 2; + int offset = window->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth) / 2; QPoint mousePosition(mouseReceiver->width() - qMax(offset, 2), mouseReceiver->height() - qMax(offset, 2)); sendMouseMove(mouseReceiver, mousePosition, Qt::NoButton); sendMousePress(mouseReceiver, mousePosition); @@ -1762,7 +1762,8 @@ void tst_QMdiSubWindow::fixedMinMaxSize() int minimizedHeight = subWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options); if (!subWindow->style()->styleHint(QStyle::SH_TitleBar_NoBorder, &options, subWindow)) minimizedHeight += 8; - int minimizedWidth = subWindow->style()->pixelMetric(QStyle::PM_MDIMinimizedWidth, &options); + int minimizedWidth = subWindow->style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth, + &options); const QSize minimizedSize = QSize(minimizedWidth, minimizedHeight); // Even though the sub window has a minimum size set, it should be possible diff --git a/tests/auto/widgets/widgets/qmenu/BLACKLIST b/tests/auto/widgets/widgets/qmenu/BLACKLIST index bac14ea2254..ad6d2f340c9 100644 --- a/tests/auto/widgets/widgets/qmenu/BLACKLIST +++ b/tests/auto/widgets/widgets/qmenu/BLACKLIST @@ -1,13 +1,13 @@ [task258920_mouseBorder] -osx -[submenuTearOffDontClose] -osx-10.12 ci +osx-10.14 +osx-10.13 [layoutDirection] +osx-10.12 +osx-10.13 # Fails when enabling synchronous expose events QTBUG-62092 -osx ci [pushButtonPopulateOnAboutToShow] -osx +osx-10.13 [tearOff] -osx +osx-10.14 [activeSubMenuPosition] winrt diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index 3bfbe754ef7..9c40c0bd577 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -610,7 +610,7 @@ void tst_QMenu::widgetActionFocus() static QMenu *getTornOffMenu() { - foreach (QWidget *w, QApplication::allWidgets()) { + for (QWidget *w : QApplication::allWidgets()) { if (w->isVisible() && w->inherits("QTornOffMenu")) return static_cast(w); } @@ -948,30 +948,28 @@ void tst_QMenu::menuSizeHint() { QMenu menu; //this is a list of arbitrary strings so that we check the geometry - QStringList list = QStringList() << "trer" << "ezrfgtgvqd" << "sdgzgzerzerzer" << "eerzertz" << "er"; - foreach (QString str, list) + for (auto str : {"trer", "ezrfgtgvqd", "sdgzgzerzerzer", "eerzertz", "er"}) menu.addAction(str); - int left, top, right, bottom; - menu.getContentsMargins(&left, &top, &right, &bottom); + const QMargins cm = menu.contentsMargins(); const int panelWidth = menu.style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, &menu); const int hmargin = menu.style()->pixelMetric(QStyle::PM_MenuHMargin, 0, &menu), vmargin = menu.style()->pixelMetric(QStyle::PM_MenuVMargin, 0, &menu); int maxWidth =0; QRect result; - foreach (QAction *action, menu.actions()) { + for (QAction *action : menu.actions()) { maxWidth = qMax(maxWidth, menu.actionGeometry(action).width()); result |= menu.actionGeometry(action); - QCOMPARE(result.x(), left + hmargin + panelWidth); - QCOMPARE(result.y(), top + vmargin + panelWidth); + QCOMPARE(result.x(), cm.left() + hmargin + panelWidth); + QCOMPARE(result.y(), cm.top() + vmargin + panelWidth); } QStyleOption opt(0); opt.rect = menu.rect(); opt.state = QStyle::State_None; - QSize resSize = QSize(result.x(), result.y()) + result.size() + QSize(hmargin + right + panelWidth, vmargin + top + panelWidth); + QSize resSize = QSize(result.x(), result.y()) + result.size() + QSize(hmargin + cm.right() + panelWidth, vmargin + cm.top() + panelWidth); resSize = menu.style()->sizeFromContents(QStyle::CT_Menu, &opt, resSize.expandedTo(QApplication::globalStrut()), &menu); @@ -1572,8 +1570,7 @@ void tst_QMenu::menuSize_Scrolling() int hmargin = style()->pixelMetric(QStyle::PM_MenuHMargin, nullptr, this); int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, this); - int leftMargin, topMargin, rightMargin, bottomMargin; - getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); + const QMargins cm = contentsMargins(); QRect lastItem = actionGeometry(actions().at(actions().length() - 1)); QSize s = size(); #ifdef Q_OS_WINRT @@ -1586,7 +1583,7 @@ void tst_QMenu::menuSize_Scrolling() return; } - QCOMPARE( s.width(), lastItem.right() + fw + hmargin + rightMargin + 1); + QCOMPARE( s.width(), lastItem.right() + fw + hmargin + cm.right() + 1); QMenu::showEvent(e); } diff --git a/tests/auto/widgets/widgets/qmenubar/BLACKLIST b/tests/auto/widgets/widgets/qmenubar/BLACKLIST index f897797f00f..c9e15e531c6 100644 --- a/tests/auto/widgets/widgets/qmenubar/BLACKLIST +++ b/tests/auto/widgets/widgets/qmenubar/BLACKLIST @@ -3,6 +3,6 @@ ubuntu-16.04 #QTBUG-66255 ubuntu-18.04 [activatedCount] -* +opensuse-42.3 [QTBUG_65488_hiddenActionTriggered] winrt diff --git a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST index b67c8354e8c..b281eca3bfe 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST +++ b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST @@ -1,5 +1,3 @@ -[clearAndGrab] -ubuntu - [stackWidgetOpaqueChildIsVisible] -windows +windows-10 msvc-2017 + diff --git a/tests/auto/widgets/widgets/qscrollbar/BLACKLIST b/tests/auto/widgets/widgets/qscrollbar/BLACKLIST deleted file mode 100644 index 277ae4d2605..00000000000 --- a/tests/auto/widgets/widgets/qscrollbar/BLACKLIST +++ /dev/null @@ -1,3 +0,0 @@ -#QTBUG-66321 -[QTBUG_42871] -macos diff --git a/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp b/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp index 278f5cdd688..339ff293f42 100644 --- a/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp +++ b/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp @@ -151,8 +151,11 @@ void tst_QScrollBar::QTBUG_27308() testWidget.setValue(testWidget.minimum()); testWidget.setEnabled(false); - QWheelEvent event(testWidget.rect().center(), - -WHEEL_DELTA, Qt::NoButton, Qt::NoModifier, testWidget.orientation()); + const QPoint wheelPoint = testWidget.rect().center(); + const QPoint angleDelta(testWidget.orientation() == Qt::Horizontal ? -WHEEL_DELTA : 0, + testWidget.orientation() == Qt::Vertical ? -WHEEL_DELTA : 0); + QWheelEvent event(wheelPoint, testWidget.mapToGlobal(wheelPoint), QPoint(), angleDelta, + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); qApp->sendEvent(&testWidget, &event); QCOMPARE(testWidget.value(), testWidget.minimum()); } diff --git a/tests/auto/widgets/widgets/qspinbox/BLACKLIST b/tests/auto/widgets/widgets/qspinbox/BLACKLIST index a38511bfb47..96a7732165e 100644 --- a/tests/auto/widgets/widgets/qspinbox/BLACKLIST +++ b/tests/auto/widgets/widgets/qspinbox/BLACKLIST @@ -1,3 +1,2 @@ [stepModifierPressAndHold] -opensuse ci # QTBUG-69492 -opensuse-leap ci +opensuse-42.3 diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp index 3dd29b02149..d75e701d1c4 100644 --- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp +++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp @@ -1331,7 +1331,6 @@ void tst_QSpinBox::wheelEvents_data() { #if QT_CONFIG(wheelevent) QTest::addColumn("angleDelta"); - QTest::addColumn("qt4Delta"); QTest::addColumn("stepModifier"); QTest::addColumn("modifier"); QTest::addColumn("source"); @@ -1430,7 +1429,6 @@ void tst_QSpinBox::wheelEvents_data() modifierName.latin1(), sourceName.latin1()) << angleDelta - << units << static_cast(stepModifier) << modifiers << source @@ -1450,7 +1448,6 @@ void tst_QSpinBox::wheelEvents() { #if QT_CONFIG(wheelevent) QFETCH(QPoint, angleDelta); - QFETCH(int, qt4Delta); QFETCH(int, stepModifier); QFETCH(Qt::KeyboardModifiers, modifier); QFETCH(Qt::MouseEventSource, source); @@ -1466,9 +1463,8 @@ void tst_QSpinBox::wheelEvents() style->stepModifier = static_cast(stepModifier); spinBox.setStyle(style.data()); - QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta, - Qt::Vertical, Qt::NoButton, modifier, Qt::NoScrollPhase, - source); + QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, + Qt::NoButton, modifier, Qt::NoScrollPhase, false, source); for (int expected : expectedValues) { qApp->sendEvent(&spinBox, &event); QCOMPARE(spinBox.value(), expected); diff --git a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp index 8b45ac20b7f..cbeb77a25e0 100644 --- a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp +++ b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp @@ -599,7 +599,7 @@ void tst_QSplitter::testShowHide() QWidget widget(&topLevel); widget.resize(400 + split->handleWidth(), 200); QVBoxLayout *lay=new QVBoxLayout(&widget); - lay->setMargin(0); + lay->setContentsMargins(0, 0, 0, 0); lay->setSpacing(0); split->addWidget(new QWidget); split->addWidget(new QWidget); diff --git a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp index cbf5196bb95..feade7d4430 100644 --- a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp +++ b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp @@ -620,7 +620,7 @@ void tst_QTabWidget::heightForWidth() QWidget *window = new QWidget; QVBoxLayout *lay = new QVBoxLayout(window); - lay->setMargin(0); + lay->setContentsMargins(0, 0, 0, 0); lay->setSpacing(0); QTabWidget *tabWid = new QTabWidget(window); QWidget *w = new QWidget; @@ -637,7 +637,7 @@ void tst_QTabWidget::heightForWidth() ); label->setWordWrap(true); lay2->addWidget(label); - lay2->setMargin(0); + lay2->setContentsMargins(0, 0, 0, 0); lay->addWidget(tabWid); int h = window->heightForWidth(160); diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp index 81682dc0273..c2cf31bfa44 100644 --- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp @@ -2669,12 +2669,14 @@ void tst_QTextEdit::wheelEvent() ed.setReadOnly(true); float defaultFontSize = ed.font().pointSizeF(); - QWheelEvent wheelUp(QPointF(), QPointF(), QPoint(), QPoint(0, 120), 120, Qt::Vertical, Qt::NoButton, Qt::ControlModifier); + QWheelEvent wheelUp(QPointF(), QPointF(), QPoint(), QPoint(0, 120), + Qt::NoButton, Qt::ControlModifier, Qt::NoScrollPhase, Qt::MouseEventNotSynthesized); ed.wheelEvent(&wheelUp); QCOMPARE(defaultFontSize + 1, ed.font().pointSizeF()); - QWheelEvent wheelHalfDown(QPointF(), QPointF(), QPoint(), QPoint(0, -60), -60, Qt::Vertical, Qt::NoButton, Qt::ControlModifier); + QWheelEvent wheelHalfDown(QPointF(), QPointF(), QPoint(), QPoint(0, -60), + Qt::NoButton, Qt::ControlModifier, Qt::NoScrollPhase, Qt::MouseEventNotSynthesized); ed.wheelEvent(&wheelHalfDown); QCOMPARE(defaultFontSize + 0.5, ed.font().pointSizeF()); diff --git a/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST b/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST index df4fda196f5..52ba36562fc 100644 --- a/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST +++ b/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST @@ -1,2 +1,2 @@ [task176137_autoRepeatOfAction] -osx ci +osx-10.13 diff --git a/tests/benchmarks/corelib/corelib.pro b/tests/benchmarks/corelib/corelib.pro index 99af4c138fa..010abd7751d 100644 --- a/tests/benchmarks/corelib/corelib.pro +++ b/tests/benchmarks/corelib/corelib.pro @@ -4,6 +4,7 @@ SUBDIRS = \ json \ mimetypes \ kernel \ + text \ thread \ time \ tools \ diff --git a/tests/benchmarks/corelib/io/qdiriterator/main.cpp b/tests/benchmarks/corelib/io/qdiriterator/main.cpp index e71daccf7db..eae752d99a3 100644 --- a/tests/benchmarks/corelib/io/qdiriterator/main.cpp +++ b/tests/benchmarks/corelib/io/qdiriterator/main.cpp @@ -78,24 +78,22 @@ void tst_qdiriterator::data() } #ifdef Q_OS_WIN -static int posix_helper(const wchar_t *dirpath) +static int posix_helper(const wchar_t *dirpath, size_t length) { int count = 0; HANDLE hSearch; WIN32_FIND_DATA fd; - const size_t origDirPathLength = wcslen(dirpath); - wchar_t appendedPath[MAX_PATH]; - wcscpy(appendedPath, dirpath); - wcscat(appendedPath, L"\\*"); + Q_ASSERT(MAX_PATH > length + 3); + wcsncpy(appendedPath, dirpath, length); + wcscpy(appendedPath + length, L"\\*"); #ifndef Q_OS_WINRT hSearch = FindFirstFile(appendedPath, &fd); #else hSearch = FindFirstFileEx(appendedPath, FindExInfoStandard, &fd, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH); #endif - appendedPath[origDirPathLength] = 0; if (hSearch == INVALID_HANDLE_VALUE) { qWarning("FindFirstFile failed"); @@ -107,10 +105,12 @@ static int posix_helper(const wchar_t *dirpath) !(fd.cFileName[0] == L'.' && fd.cFileName[1] == L'.' && fd.cFileName[2] == 0)) { if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - wcscat(appendedPath, L"\\"); - wcscat(appendedPath, fd.cFileName); - count += posix_helper(appendedPath); - appendedPath[origDirPathLength] = 0; + // newLength will "point" to where we put a * earlier, so we overwrite that. + size_t newLength = length + 1; // "+ 1" for directory separator + Q_ASSERT(newLength + wcslen(fd.cFileName) + 1 < MAX_PATH); // "+ 1" for null-terminator + wcscpy(appendedPath + newLength, fd.cFileName); + newLength += wcslen(fd.cFileName); + count += posix_helper(appendedPath, newLength); } else { ++count; @@ -164,8 +164,8 @@ void tst_qdiriterator::posix() QBENCHMARK { #ifdef Q_OS_WIN wchar_t wPath[MAX_PATH]; - path.toWCharArray(wPath); - count = posix_helper(wPath); + const int end = path.toWCharArray(wPath); + count = posix_helper(wPath, end); #else count = posix_helper(dirpath.constData()); #endif diff --git a/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp index d68264b78f7..6ee8b4e93b7 100644 --- a/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp +++ b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp @@ -218,8 +218,9 @@ void QFileSystemIteratorPrivate::pushSubDirectory(const QByteArray &path) #ifdef Q_OS_WIN wchar_t szSearchPath[MAX_PATH]; - QString::fromLatin1(path).toWCharArray(szSearchPath); - wcscat(szSearchPath, L"\\*"); + const int end = QString::fromLatin1(path + "\\*").toWCharArray(szSearchPath); + Q_ASSERT(end < MAX_PATH); + szSearchPath[end] = L'\0'; #ifndef Q_OS_WINRT HANDLE dir = FindFirstFile(szSearchPath, &m_fileSearchResult); #else diff --git a/tests/benchmarks/corelib/tools/qbytearray/main.cpp b/tests/benchmarks/corelib/text/qbytearray/main.cpp similarity index 100% rename from tests/benchmarks/corelib/tools/qbytearray/main.cpp rename to tests/benchmarks/corelib/text/qbytearray/main.cpp diff --git a/tests/benchmarks/corelib/tools/qbytearray/qbytearray.pro b/tests/benchmarks/corelib/text/qbytearray/qbytearray.pro similarity index 100% rename from tests/benchmarks/corelib/tools/qbytearray/qbytearray.pro rename to tests/benchmarks/corelib/text/qbytearray/qbytearray.pro diff --git a/tests/benchmarks/corelib/tools/qchar/main.cpp b/tests/benchmarks/corelib/text/qchar/main.cpp similarity index 100% rename from tests/benchmarks/corelib/tools/qchar/main.cpp rename to tests/benchmarks/corelib/text/qchar/main.cpp diff --git a/tests/benchmarks/corelib/tools/qchar/qchar.pro b/tests/benchmarks/corelib/text/qchar/qchar.pro similarity index 100% rename from tests/benchmarks/corelib/tools/qchar/qchar.pro rename to tests/benchmarks/corelib/text/qchar/qchar.pro diff --git a/tests/benchmarks/corelib/tools/qlocale/main.cpp b/tests/benchmarks/corelib/text/qlocale/main.cpp similarity index 100% rename from tests/benchmarks/corelib/tools/qlocale/main.cpp rename to tests/benchmarks/corelib/text/qlocale/main.cpp diff --git a/tests/benchmarks/corelib/tools/qlocale/qlocale.pro b/tests/benchmarks/corelib/text/qlocale/qlocale.pro similarity index 100% rename from tests/benchmarks/corelib/tools/qlocale/qlocale.pro rename to tests/benchmarks/corelib/text/qlocale/qlocale.pro diff --git a/tests/benchmarks/corelib/tools/qregexp/main.cpp b/tests/benchmarks/corelib/text/qregexp/main.cpp similarity index 100% rename from tests/benchmarks/corelib/tools/qregexp/main.cpp rename to tests/benchmarks/corelib/text/qregexp/main.cpp diff --git a/tests/benchmarks/corelib/tools/qregexp/qregexp.pro b/tests/benchmarks/corelib/text/qregexp/qregexp.pro similarity index 100% rename from tests/benchmarks/corelib/tools/qregexp/qregexp.pro rename to tests/benchmarks/corelib/text/qregexp/qregexp.pro diff --git a/tests/benchmarks/corelib/tools/qregexp/qregexp.qrc b/tests/benchmarks/corelib/text/qregexp/qregexp.qrc similarity index 100% rename from tests/benchmarks/corelib/tools/qregexp/qregexp.qrc rename to tests/benchmarks/corelib/text/qregexp/qregexp.qrc diff --git a/tests/benchmarks/corelib/tools/qstring/main.cpp b/tests/benchmarks/corelib/text/qstring/main.cpp similarity index 100% rename from tests/benchmarks/corelib/tools/qstring/main.cpp rename to tests/benchmarks/corelib/text/qstring/main.cpp diff --git a/tests/benchmarks/corelib/tools/qstring/qstring.pro b/tests/benchmarks/corelib/text/qstring/qstring.pro similarity index 100% rename from tests/benchmarks/corelib/tools/qstring/qstring.pro rename to tests/benchmarks/corelib/text/qstring/qstring.pro diff --git a/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp b/tests/benchmarks/corelib/text/qstringbuilder/main.cpp similarity index 100% rename from tests/benchmarks/corelib/tools/qstringbuilder/main.cpp rename to tests/benchmarks/corelib/text/qstringbuilder/main.cpp diff --git a/tests/benchmarks/corelib/tools/qstringbuilder/qstringbuilder.pro b/tests/benchmarks/corelib/text/qstringbuilder/qstringbuilder.pro similarity index 100% rename from tests/benchmarks/corelib/tools/qstringbuilder/qstringbuilder.pro rename to tests/benchmarks/corelib/text/qstringbuilder/qstringbuilder.pro diff --git a/tests/benchmarks/corelib/tools/qstringlist/.gitignore b/tests/benchmarks/corelib/text/qstringlist/.gitignore similarity index 100% rename from tests/benchmarks/corelib/tools/qstringlist/.gitignore rename to tests/benchmarks/corelib/text/qstringlist/.gitignore diff --git a/tests/benchmarks/corelib/tools/qstringlist/main.cpp b/tests/benchmarks/corelib/text/qstringlist/main.cpp similarity index 100% rename from tests/benchmarks/corelib/tools/qstringlist/main.cpp rename to tests/benchmarks/corelib/text/qstringlist/main.cpp diff --git a/tests/benchmarks/corelib/tools/qstringlist/qstringlist.pro b/tests/benchmarks/corelib/text/qstringlist/qstringlist.pro similarity index 100% rename from tests/benchmarks/corelib/tools/qstringlist/qstringlist.pro rename to tests/benchmarks/corelib/text/qstringlist/qstringlist.pro diff --git a/tests/benchmarks/corelib/text/text.pro b/tests/benchmarks/corelib/text/text.pro new file mode 100644 index 00000000000..a2397b37fe9 --- /dev/null +++ b/tests/benchmarks/corelib/text/text.pro @@ -0,0 +1,9 @@ +TEMPLATE = subdirs +SUBDIRS = \ + qbytearray \ + qchar \ + qlocale \ + qstringbuilder \ + qstringlist + +*g++*: SUBDIRS += qstring diff --git a/tests/benchmarks/corelib/tools/qhash/paths_small_data.txt b/tests/benchmarks/corelib/tools/qhash/paths_small_data.txt index d5acd288203..662285296f7 100644 --- a/tests/benchmarks/corelib/tools/qhash/paths_small_data.txt +++ b/tests/benchmarks/corelib/tools/qhash/paths_small_data.txt @@ -47,13 +47,38 @@ ./codecs/.obj/debug-shared ./.pch ./.pch/debug-shared +./text +./text/text.pro +./text/qregexp +./text/qregexp/qregexp.qrc +./text/qregexp/main.cpp +./text/qregexp/Makefile +./text/qregexp/qregexp.pro +./text/qstringbuilder +./text/qstringbuilder/main.cpp +./text/qstringbuilder/Makefile +./text/qstringbuilder/qstringbuilder.pro +./text/qstring +./text/qstring/generatelist.pl +./text/qstring/data.h +./text/qstring/qstring.pro +./text/qstring/main.cpp +./text/qstring/data.cpp +./text/qstring/Makefile +./text/qstring/utf-8.txt +./text/qstringlist +./text/qstringlist/qstringlist.pro +./text/qstringlist/main.cpp +./text/qstringlist/.gitignore +./text/qstringlist/Makefile +./text/qbytearray +./text/qbytearray/qbytearray.pro +./text/qbytearray/main.cpp +./text/qbytearray/Makefile +./text/.pch +./text/.pch/debug-shared ./tools ./tools/tools.pro -./tools/qregexp -./tools/qregexp/qregexp.qrc -./tools/qregexp/main.cpp -./tools/qregexp/Makefile -./tools/qregexp/qregexp.pro ./tools/qvector ./tools/qvector/tst_vector ./tools/qvector/.pch @@ -72,31 +97,10 @@ ./tools/qvector/qvector.pro ./tools/.pch ./tools/.pch/debug-shared -./tools/qstringbuilder -./tools/qstringbuilder/main.cpp -./tools/qstringbuilder/Makefile -./tools/qstringbuilder/qstringbuilder.pro ./tools/containers-sequential ./tools/containers-sequential/containers-sequential.pro ./tools/containers-sequential/main.cpp ./tools/containers-sequential/Makefile -./tools/qstring -./tools/qstring/generatelist.pl -./tools/qstring/data.h -./tools/qstring/qstring.pro -./tools/qstring/main.cpp -./tools/qstring/data.cpp -./tools/qstring/Makefile -./tools/qstring/utf-8.txt -./tools/qstringlist -./tools/qstringlist/qstringlist.pro -./tools/qstringlist/main.cpp -./tools/qstringlist/.gitignore -./tools/qstringlist/Makefile -./tools/qbytearray -./tools/qbytearray/qbytearray.pro -./tools/qbytearray/main.cpp -./tools/qbytearray/Makefile ./tools/containers-associative ./tools/containers-associative/containers-associative.pro ./tools/containers-associative/main.cpp diff --git a/tests/benchmarks/corelib/tools/tools.pro b/tests/benchmarks/corelib/tools/tools.pro index 33cbe00438c..b4ee0520a63 100644 --- a/tests/benchmarks/corelib/tools/tools.pro +++ b/tests/benchmarks/corelib/tools/tools.pro @@ -2,19 +2,12 @@ TEMPLATE = subdirs SUBDIRS = \ containers-associative \ containers-sequential \ - qbytearray \ qcontiguouscache \ qcryptographichash \ qlist \ - qlocale \ qmap \ qrect \ qringbuffer \ qstack \ - qstring \ - qstringbuilder \ - qstringlist \ qvector \ qalgorithms - -!*g++*: SUBDIRS -= qstring diff --git a/tests/benchmarks/gui/image/qpixmapcache/tst_qpixmapcache.cpp b/tests/benchmarks/gui/image/qpixmapcache/tst_qpixmapcache.cpp index d4be85b5add..2ded426cdd2 100644 --- a/tests/benchmarks/gui/image/qpixmapcache/tst_qpixmapcache.cpp +++ b/tests/benchmarks/gui/image/qpixmapcache/tst_qpixmapcache.cpp @@ -106,7 +106,7 @@ void tst_QPixmapCache::find() if (cacheType) { QBENCHMARK { for (int i = 0 ; i <= 10000 ; i++) - QPixmapCache::find(QString::asprintf("my-key-%d", i), p); + QPixmapCache::find(QString::asprintf("my-key-%d", i), &p); } } else { QBENCHMARK { @@ -155,7 +155,7 @@ void tst_QPixmapCache::styleUseCaseComplexKey() QPixmapCache::insert(QString::asprintf("%s-%d-%d-%d-%d-%d-%d", QString("my-progressbar-%1").arg(i).toLatin1().constData(), 5, 3, 0, 358, 100, 200), p); for (int i = 0 ; i <= 10000 ; i++) - QPixmapCache::find(QString::asprintf("%s-%d-%d-%d-%d-%d-%d", QString("my-progressbar-%1").arg(i).toLatin1().constData(), 5, 3, 0, 358, 100, 200), p); + QPixmapCache::find(QString::asprintf("%s-%d-%d-%d-%d-%d-%d", QString("my-progressbar-%1").arg(i).toLatin1().constData(), 5, 3, 0, 358, 100, 200), &p); } } else { QHash hash; diff --git a/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp b/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp index bd0889bf4a8..d26ac016b9a 100644 --- a/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp +++ b/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp @@ -305,17 +305,17 @@ void tst_LanceBench::runTestSuite(GraphicsEngine engine, QImage::Format format, 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 { + 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); QPainter p(device); pcmd.setPainter(&p); pcmd.runCommands(); diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp index b15aad04cd2..e0c5a7f6834 100644 --- a/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp +++ b/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp @@ -60,7 +60,7 @@ public: { Q_UNUSED(option); Q_UNUSED(widget); - painter->drawRoundRect(rect()); + painter->drawRoundedRect(rect(), 25, 25, Qt::RelativeSize); painter->drawLine(rect().topLeft(), rect().bottomRight()); painter->drawLine(rect().bottomLeft(), rect().topRight()); } diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp index 5c97d7f7381..caf5455a800 100644 --- a/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp +++ b/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp @@ -53,7 +53,7 @@ public: { Q_UNUSED(option); Q_UNUSED(widget); - painter->drawRoundRect(rect()); + painter->drawRoundedRect(rect(), 25, 25, Qt::RelativeSize); painter->drawLine(rect().topLeft(), rect().bottomRight()); painter->drawLine(rect().bottomLeft(), rect().topRight()); } diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp index 57ab62b1c38..2277ae0f144 100644 --- a/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp +++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp @@ -38,7 +38,7 @@ Chip::Chip(const QColor &color, int x, int y) setZValue((x + y) % 2); setFlags(ItemIsSelectable | ItemIsMovable); - setAcceptsHoverEvents(true); + setAcceptHoverEvents(true); } QRectF Chip::boundingRect() const diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp index cf82282bfeb..21eb622f15c 100644 --- a/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp +++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp @@ -57,9 +57,9 @@ void Chip::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid { Q_UNUSED(widget); - QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color; + QColor fillColor = (option->state & QStyle::State_Selected) ? color.darker(150) : color; if (option->state & QStyle::State_MouseOver) - fillColor = fillColor.light(125); + fillColor = fillColor.lighter(125); if (option->levelOfDetail < 0.2) { if (option->levelOfDetail < 0.125) { @@ -82,7 +82,7 @@ void Chip::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid pen.setWidth(width); QBrush b = painter->brush(); - painter->setBrush(QBrush(fillColor.dark(option->state & QStyle::State_Sunken ? 120 : 100))); + painter->setBrush(QBrush(fillColor.darker(option->state & QStyle::State_Sunken ? 120 : 100))); painter->drawRect(QRect(14, 14, 79, 39)); painter->setBrush(b); diff --git a/tests/libfuzzer/README b/tests/libfuzzer/README index 7327e76eff4..57140cebfb8 100644 --- a/tests/libfuzzer/README +++ b/tests/libfuzzer/README @@ -7,7 +7,7 @@ of the test and track the code execution. Should the test crash, libFuzzer will data which triggered the crash. You can then use this to debug and fix the called code. ! Please note: The purpose of fuzz testing is to find unexpected code paths. Running fuzz tests may! -! result in unforeseen bevavior, including loss of data. Consider running the tests in an isolated ! +! result in unforeseen behavior, including loss of data. Consider running the tests in an isolated ! ! environment, e.g. on a virtual machine. You have been warned. ! To run a test with libFuzzer: @@ -21,7 +21,7 @@ To run a test with libFuzzer: to add the needed code coverage instrumentation. Since speed of execution is crucial for fuzz testing, it's recommendable to also use the switches -release -static - It might also make sense to add sanitzers by passing + It might also make sense to add sanitizers by passing -sanitize <...> 4. Build Qt. 5. Build one of the tests using this Qt build. @@ -29,7 +29,7 @@ To run a test with libFuzzer: Depending on the expected input format of the tested function, you will get results faster if you: * provide a set of interesting input data by passing the path of a directory which contains - these data, each in one file. You can find such datasets in the subdirectory "testcases". + these data, each in one file. You can find such data sets in the subdirectory "testcases". * pass a so-called dictionary listing keywords of the input format using -dict= A couple of such dictionaries are provided by AFL (http://lcamtuf.coredump.cx/afl/) diff --git a/tests/libfuzzer/gui/iccparser/iccparser.pro b/tests/libfuzzer/gui/iccparser/iccparser.pro new file mode 100644 index 00000000000..bf4037eae75 --- /dev/null +++ b/tests/libfuzzer/gui/iccparser/iccparser.pro @@ -0,0 +1,3 @@ +QT += gui +SOURCES += main.cpp +LIBS += -fsanitize=fuzzer diff --git a/tests/libfuzzer/gui/iccparser/main.cpp b/tests/libfuzzer/gui/iccparser/main.cpp new file mode 100644 index 00000000000..ba4f70ef3ba --- /dev/null +++ b/tests/libfuzzer/gui/iccparser/main.cpp @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 +#include + +extern "C" int LLVMFuzzerTestOneInput(const char *data, size_t size) { + static int c = 0; + static QGuiApplication a(c, nullptr); + QColorSpace cs = QColorSpace::fromIccProfile(QByteArray(data, size)); + return 0; +} diff --git a/tests/manual/keypadnavigation/main.cpp b/tests/manual/keypadnavigation/main.cpp index 67986a9cc9e..dad43765140 100644 --- a/tests/manual/keypadnavigation/main.cpp +++ b/tests/manual/keypadnavigation/main.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include "ui_keypadnavigation.h" class KeypadNavigation : public QMainWindow @@ -48,7 +47,7 @@ public: ui->setupUi(this); const struct { - QObject *action; + QAction *action; QWidget *page; } layoutMappings[] = { {ui->m_actionLayoutVerticalSimple, ui->m_pageVerticalSimple}, @@ -58,15 +57,16 @@ public: {ui->m_actionLayoutChaos, ui->m_pageChaos}, {ui->m_actionLayoutDialogs, ui->m_pageDialogs} }; - for (int i = 0; i < int(sizeof layoutMappings / sizeof layoutMappings[0]); ++i) { - connect(layoutMappings[i].action, SIGNAL(triggered()), &m_layoutSignalMapper, SLOT(map())); - m_layoutSignalMapper.setMapping(layoutMappings[i].action, layoutMappings[i].page); + for (auto layoutMapping : layoutMappings) { + const auto page = layoutMapping.page; + connect(layoutMapping.action, &QAction::triggered, ui->m_stackWidget, + [this, page]() + { ui->m_stackWidget->setCurrentWidget(page); }); } - connect(&m_layoutSignalMapper, SIGNAL(mapped(QWidget*)), ui->m_stackWidget, SLOT(setCurrentWidget(QWidget*))); #ifdef QT_KEYPAD_NAVIGATION const struct { - QObject *action; + QAction *action; Qt::NavigationMode mode; } modeMappings[] = { {ui->m_actionModeNone, Qt::NavigationModeNone}, @@ -75,17 +75,17 @@ public: {ui->m_actionModeCursorAuto, Qt::NavigationModeCursorAuto}, {ui->m_actionModeCursorForceVisible, Qt::NavigationModeCursorForceVisible} }; - for (int i = 0; i < int(sizeof modeMappings / sizeof modeMappings[0]); ++i) { - connect(modeMappings[i].action, SIGNAL(triggered()), &m_modeSignalMapper, SLOT(map())); - m_modeSignalMapper.setMapping(modeMappings[i].action, int(modeMappings[i].mode)); + for (auto modeMapping : modeMappings) { + const auto mode = modeMapping.mode; + connect(modeMapping.action, &QAction::triggered, this, + [this, mode]() { setNavigationMode(mode); }); } - connect(&m_modeSignalMapper, SIGNAL(mapped(int)), SLOT(setNavigationMode(int))); #else // QT_KEYPAD_NAVIGATION ui->m_menuNavigation_mode->deleteLater(); #endif // QT_KEYPAD_NAVIGATION const struct { - QObject *button; + QPushButton *button; Dialog dialog; } openDialogMappings[] = { {ui->m_buttonGetOpenFileName, DialogGetOpenFileName}, @@ -97,11 +97,11 @@ public: {ui->m_buttonAboutQt, DialogAboutQt}, {ui->m_buttonGetItem, DialogGetItem} }; - for (int i = 0; i < int(sizeof openDialogMappings / sizeof openDialogMappings[0]); ++i) { - connect(openDialogMappings[i].button, SIGNAL(clicked()), &m_dialogSignalMapper, SLOT(map())); - m_dialogSignalMapper.setMapping(openDialogMappings[i].button, int(openDialogMappings[i].dialog)); + for (auto openDialogMapping : openDialogMappings) { + const auto dialog = openDialogMapping.dialog; + connect(openDialogMapping.button, &QPushButton::clicked, this, + [this, dialog]() { openDialog(dialog); }); } - connect(&m_dialogSignalMapper, SIGNAL(mapped(int)), SLOT(openDialog(int))); } ~KeypadNavigation() @@ -162,11 +162,6 @@ private: }; Ui_KeypadNavigation *ui; - QSignalMapper m_layoutSignalMapper; -#ifdef QT_KEYPAD_NAVIGATION - QSignalMapper m_modeSignalMapper; -#endif // QT_KEYPAD_NAVIGATION - QSignalMapper m_dialogSignalMapper; }; int main(int argc, char *argv[]) diff --git a/tests/manual/lance/widgets.h b/tests/manual/lance/widgets.h index 46c55f4c160..09b2c3e6679 100644 --- a/tests/manual/lance/widgets.h +++ b/tests/manual/lance/widgets.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index 63c8eb6538f..e6885463743 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -23,6 +23,7 @@ qimagereader \ qlayout \ qlocale \ qmimedatabase \ +qnetconmonitor \ qnetworkaccessmanager/qget \ qnetworkconfigurationmanager \ qnetworkconfiguration \ diff --git a/tests/manual/qgraphicslayout/flicker/window.h b/tests/manual/qgraphicslayout/flicker/window.h index 22a53585d1d..3e7bc617317 100644 --- a/tests/manual/qgraphicslayout/flicker/window.h +++ b/tests/manual/qgraphicslayout/flicker/window.h @@ -107,7 +107,7 @@ public: Q_UNUSED(option); Q_UNUSED(widget); painter->setBrush(m_brush); - painter->drawRoundRect(rect()); + painter->drawRoundedRect(rect(), Qt::RelativeSize); painter->drawLine(rect().topLeft(), rect().bottomRight()); painter->drawLine(rect().bottomLeft(), rect().topRight()); } diff --git a/tests/manual/qnetconmonitor/qnetconmonitor.pro b/tests/manual/qnetconmonitor/qnetconmonitor.pro new file mode 100644 index 00000000000..dda88c4cd7f --- /dev/null +++ b/tests/manual/qnetconmonitor/qnetconmonitor.pro @@ -0,0 +1,4 @@ +TEMPLATE = app +QT = network-private testlib +CONFIG += console +SOURCES += tst_qnetconmonitor.cpp diff --git a/tests/manual/qnetconmonitor/tst_qnetconmonitor.cpp b/tests/manual/qnetconmonitor/tst_qnetconmonitor.cpp new file mode 100644 index 00000000000..92daee3348b --- /dev/null +++ b/tests/manual/qnetconmonitor/tst_qnetconmonitor.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 +#include + +#include +#include + +#include + +void testDetectDisconnection(); +void testDetectRouteDisrupted(); + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + if (!QNetworkStatusMonitor::isEnabled()) { + qWarning("QNetworkStatusMonitor is not enabled for this platform!"); + return 0; + } + + while (true) { + + QByteArray indent(" "); + { + QTextStream writer(stdout); + writer << "Manual test for QNetwork{Status|Connection}Monitor\n" + << "The tests are grouped by what they test. Run them in any order\n" + << "- QNetworkStatusMonitor tests:\n" + << indent << "c" << indent << "Test connection and disconnection detection.\n" + << "- QNetworkConnectionMonitor tests:\n" + << indent << "r" << indent << "Test detection of disruption of route to target.\n" + << "- General\n" + << indent << "q" << indent << "Quit the test.\n" + << "> "; + } + + auto getCommand = []() { + char ch; + QTextStream reader(stdin); + reader >> ch; + return ch; + }; + + switch (getCommand()) { + case 'c': + testDetectDisconnection(); + break; + case 'r': + testDetectRouteDisrupted(); + break; + case 'q': + return 0; + } + } + Q_UNREACHABLE(); + return 0; +} + +bool ensureNetworkAccessible(QNetworkStatusMonitor &status, QTextStream &writer) +{ + if (!status.isNetworkAccessible()) { + writer << "Network currently not accessible, please make sure you have an internet " + "connection. Will wait for a connection for 20 seconds.\n"; + writer.flush(); + QDeadlineTimer timer{ 20 * 1000 }; + while (!timer.hasExpired() && !status.isNetworkAccessible()) + QCoreApplication::processEvents(); + if (!status.isNetworkAccessible()) { + writer << "Error: No network in 20 seconds, ending now!\n"; + return false; + } + writer << "Network successfully connected, thanks!\n"; + } + return true; +} + +void testDetectDisconnection() +{ + QTextStream writer(stdout); + QNetworkStatusMonitor status; + + if (!status.start()) { + writer << "Error: Failed to start"; + return; + } + + if (!ensureNetworkAccessible(status, writer)) + return; + + QSignalSpy onlineStateSpy(&status, &QNetworkStatusMonitor::onlineStateChanged); + + writer << "Please disconnect from the internet within 20 seconds\n"; + writer.flush(); + QDeadlineTimer timer{ 20 * 1000 }; + while (!timer.hasExpired() && status.isNetworkAccessible()) + QCoreApplication::processEvents(); + if (status.isNetworkAccessible()) { + writer << "Error: Still connected after 20 seconds, ending now!\n"; + return; + } + if (onlineStateSpy.count() == 0) { + writer << "Error: There was a disconnection but there was no signal emitted!\n"; + return; + } + // Get the final parameter of the final signal emission and make sure it is false. + if (onlineStateSpy.last().last().toBool()) { + writer << "Error: There was a disconnection but the latest signal emitted says we are online!\n"; + return; + } + writer << "Success, connection loss was detected!\n"; +} + +void testDetectRouteDisrupted() +{ + QTextStream writer(stdout); + + { + QNetworkStatusMonitor status; + if (!status.start()) { + writer << "Error: Failed to start"; + return; + } + if (!ensureNetworkAccessible(status, writer)) + return; + } + + QNetworkConnectionMonitor connection; + + auto readLineFromStdin = []() -> QString { + QTextStream in(stdin); + return in.readLine(); + }; + + writer << "Type your local IP address: "; + writer.flush(); + const QHostAddress local{ readLineFromStdin() }; + if (local.isNull()) { + writer << "Error: The address is invalid!\n"; + return; + } + + const QHostAddress defaultAddress{ QString::fromLatin1("1.1.1.1") }; + QHostAddress remote; + do { + writer << "Type a remote IP address [" << defaultAddress.toString() << "]: "; + writer.flush(); + QString address = readLineFromStdin(); + if (address.isEmpty()) { + remote = defaultAddress; + } else { + QHostAddress remoteTemp{ address }; + if (remoteTemp.isNull()) { + writer << "Invalid address\n"; + } else { + remote = remoteTemp; + } + } + } while (remote.isNull()); + + if (!connection.setTargets(local, remote)) { + writer << "Error: Failed to set the targets!\n"; + return; + } + if (!connection.isReachable()) { + writer << "Error: Target is not reachable!\n"; + return; + } + if (!connection.startMonitoring()) { + writer << "Error: Failed to start monitoring!\n"; + return; + } + + QSignalSpy reachabilitySpy(&connection, &QNetworkConnectionMonitor::reachabilityChanged); + + writer << "QNetworkConnectionMonitor might assume the target is initially reachable.\n" + "If it is not reachable then this test might not work correctly.\n" + "Please disrupt the connection between your machine and the target within 20 " + "seconds\n"; + writer.flush(); + reachabilitySpy.wait(20 * 1000); + if (reachabilitySpy.count() == 0) { + writer << "Error: There was a disconnection but there was no signal emitted!\n"; + return; + } + // Get the final parameter of the final signal emission and make sure it is false. + if (reachabilitySpy.last().last().toBool()) { + writer << "Error: There was a disconnection but the latest signal emitted says the target is " + "reachable!\n"; + return; + } + writer << "Success, connection disruption was detected!\n"; +} diff --git a/tests/manual/rhi/computeimage/computeimage.cpp b/tests/manual/rhi/computeimage/computeimage.cpp index 7bc05fc04f3..51bf216c5ab 100644 --- a/tests/manual/rhi/computeimage/computeimage.cpp +++ b/tests/manual/rhi/computeimage/computeimage.cpp @@ -146,7 +146,7 @@ void Window::customInit() d.ubuf->build(); d.releasePool << d.ubuf; - qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0; + qint32 flip = 0; // regardless of isYUpInFramebuffer() since the input is not flipped so the end result is good for GL too d.initialUpdates->updateDynamicBuffer(d.ubuf, 64, 4, &flip); d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None, diff --git a/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp index 8fda2b73c8c..53185bddb2c 100644 --- a/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp +++ b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp @@ -290,6 +290,10 @@ struct Renderer void Thread::run() { while (active) { +#ifdef Q_OS_DARWIN + QMacAutoReleasePool autoReleasePool; +#endif + if (pendingRender) { pendingRender = false; renderer->render(pendingRenderIsNewExpose, false); diff --git a/tests/manual/rhi/offscreen/offscreen.cpp b/tests/manual/rhi/offscreen/offscreen.cpp index 678d6ffe482..79e50d3dd40 100644 --- a/tests/manual/rhi/offscreen/offscreen.cpp +++ b/tests/manual/rhi/offscreen/offscreen.cpp @@ -307,7 +307,7 @@ int main(int argc, char **argv) opacity = qBound(0.0f, opacity, 1.0f); } - cb->beginPass(rt, { 0, 1, 0, 1 }, { 1, 0 }, u); + cb->beginPass(rt, QColor::fromRgbF(0.0f, 1.0f, 0.0f, 1.0f), { 1, 0 }, u); cb->setGraphicsPipeline(ps); cb->setViewport({ 0, 0, 1280, 720 }); cb->setShaderResources(); diff --git a/util/cmake/pro2cmake.py b/util/cmake/pro2cmake.py index f6d354f19c1..26c346eef94 100755 --- a/util/cmake/pro2cmake.py +++ b/util/cmake/pro2cmake.py @@ -311,6 +311,10 @@ def handle_function_value(group: pp.ParseResults): # Do nothing, just return a string result return str(group) + # Return the whole expression as a string. + if function_name in ['join', 'cmakeRelativePath', 'shell_quote', 'shadowed']: + return 'join({})'.format(''.join(function_args)) + raise RuntimeError('No logic to handle function "{}", please add one in handle_function_value().'.format(function_name)) class Operation: diff --git a/util/locale_database/cldr2qlocalexml.py b/util/locale_database/cldr2qlocalexml.py index 5560d8b43fa..1982e3ba27c 100755 --- a/util/locale_database/cldr2qlocalexml.py +++ b/util/locale_database/cldr2qlocalexml.py @@ -38,11 +38,11 @@ command-line argument. Save its standard output (but not error) to a file for later processing by ``./qlocalexml2cpp.py`` When you update the CLDR data, be sure to also update -src/corelib/tools/qt_attribution.json's entry for unicode-cldr. Check +src/corelib/text/qt_attribution.json's entry for unicode-cldr. Check this script's output for unknown language, country or script messages; if any can be resolved, use their entry in common/main/en.xml to append new entries to enumdata.py's lists and update documentation in -src/corelib/tools/qlocale.qdoc, adding the new entries in alphabetic +src/corelib/text/qlocale.qdoc, adding the new entries in alphabetic order. While updating the locale data, check also for updates to MS-Win's diff --git a/util/locale_database/qlocalexml2cpp.py b/util/locale_database/qlocalexml2cpp.py index 2dad2dd57aa..ea89288b4ff 100755 --- a/util/locale_database/qlocalexml2cpp.py +++ b/util/locale_database/qlocalexml2cpp.py @@ -339,7 +339,7 @@ def main(): (data_temp_file, data_temp_file_path) = tempfile.mkstemp("qlocale_data_p", dir=qtsrcdir) data_temp_file = os.fdopen(data_temp_file, "w") - qlocaledata_file = open(qtsrcdir + "/src/corelib/tools/qlocale_data_p.h", "r") + qlocaledata_file = open(qtsrcdir + "/src/corelib/text/qlocale_data_p.h", "r") s = qlocaledata_file.readline() while s and s != GENERATED_BLOCK_START: data_temp_file.write(s) @@ -735,14 +735,14 @@ def main(): data_temp_file.close() qlocaledata_file.close() - os.remove(qtsrcdir + "/src/corelib/tools/qlocale_data_p.h") - os.rename(data_temp_file_path, qtsrcdir + "/src/corelib/tools/qlocale_data_p.h") + os.remove(qtsrcdir + "/src/corelib/text/qlocale_data_p.h") + os.rename(data_temp_file_path, qtsrcdir + "/src/corelib/text/qlocale_data_p.h") # qlocale.h (qlocaleh_temp_file, qlocaleh_temp_file_path) = tempfile.mkstemp("qlocale.h", dir=qtsrcdir) qlocaleh_temp_file = os.fdopen(qlocaleh_temp_file, "w") - qlocaleh_file = open(qtsrcdir + "/src/corelib/tools/qlocale.h", "r") + qlocaleh_file = open(qtsrcdir + "/src/corelib/text/qlocale.h", "r") s = qlocaleh_file.readline() while s and s != GENERATED_BLOCK_START: qlocaleh_temp_file.write(s) @@ -808,14 +808,14 @@ def main(): qlocaleh_temp_file.close() qlocaleh_file.close() - os.remove(qtsrcdir + "/src/corelib/tools/qlocale.h") - os.rename(qlocaleh_temp_file_path, qtsrcdir + "/src/corelib/tools/qlocale.h") + os.remove(qtsrcdir + "/src/corelib/text/qlocale.h") + os.rename(qlocaleh_temp_file_path, qtsrcdir + "/src/corelib/text/qlocale.h") # qlocale.qdoc (qlocaleqdoc_temp_file, qlocaleqdoc_temp_file_path) = tempfile.mkstemp("qlocale.qdoc", dir=qtsrcdir) qlocaleqdoc_temp_file = os.fdopen(qlocaleqdoc_temp_file, "w") - qlocaleqdoc_file = open(qtsrcdir + "/src/corelib/tools/qlocale.qdoc", "r") + qlocaleqdoc_file = open(qtsrcdir + "/src/corelib/text/qlocale.qdoc", "r") s = qlocaleqdoc_file.readline() DOCSTRING = " QLocale's data is based on Common Locale Data Repository " while s: @@ -827,8 +827,8 @@ def main(): qlocaleqdoc_temp_file.close() qlocaleqdoc_file.close() - os.remove(qtsrcdir + "/src/corelib/tools/qlocale.qdoc") - os.rename(qlocaleqdoc_temp_file_path, qtsrcdir + "/src/corelib/tools/qlocale.qdoc") + os.remove(qtsrcdir + "/src/corelib/text/qlocale.qdoc") + os.rename(qlocaleqdoc_temp_file_path, qtsrcdir + "/src/corelib/text/qlocale.qdoc") if __name__ == "__main__": main() diff --git a/util/unicode/README b/util/unicode/README index e52f26175ae..87f055d42d9 100644 --- a/util/unicode/README +++ b/util/unicode/README @@ -19,7 +19,7 @@ To update: need to be expanded, for example. In some cases QChar may need additions to some of its enums. * Build with the modified code, fix any compilation issues. -* That may have updated qtbase/src/corelib/tools/qunicodetables.cpp; +* That may have updated qtbase/src/corelib/text/qunicodetables.cpp; if so the update matters; be sure to commit the changes to data/ at the same time and update tools/qt_attribution.json to match; use the UCD Revision number, rather than the Unicode standard number, as the diff --git a/util/unicode/main.cpp b/util/unicode/main.cpp index ec84667ee5f..84231c6277b 100644 --- a/util/unicode/main.cpp +++ b/util/unicode/main.cpp @@ -3096,7 +3096,7 @@ int main(int, char **) "// We mean it.\n" "//\n\n"; - QFile f("../../src/corelib/tools/qunicodetables.cpp"); + QFile f("../../src/corelib/text/qunicodetables.cpp"); f.open(QFile::WriteOnly|QFile::Truncate); f.write(header); f.write(note); @@ -3116,7 +3116,7 @@ int main(int, char **) f.write("QT_END_NAMESPACE\n"); f.close(); - f.setFileName("../../src/corelib/tools/qunicodetables_p.h"); + f.setFileName("../../src/corelib/text/qunicodetables_p.h"); f.open(QFile::WriteOnly | QFile::Truncate); f.write(header); f.write(note);