Merge remote-tracking branch 'origin/5.11' into dev

Conflicts:
	src/plugins/platforms/cocoa/qnsview.mm
	src/plugins/platforms/cocoa/qnsview_mouse.mm
	src/testlib/testlib.pro

Change-Id: Ia0ce4243418fe6a485b0f290c67bd433b3b04ff2
This commit is contained in:
Liang Qi 2018-03-28 08:12:21 +02:00
commit 794781e7cf
99 changed files with 1435 additions and 1084 deletions

View File

@ -15,7 +15,8 @@
"src/xml",
"src/widgets",
"src/printsupport",
"src/plugins/sqldrivers"
"src/plugins/sqldrivers",
"src/testlib"
],
"commandline": {

View File

@ -87,10 +87,12 @@ void PathStrokeControls::createCommonControls(QWidget* parent)
m_joinGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
QRadioButton *bevelJoin = new QRadioButton(m_joinGroup);
QRadioButton *miterJoin = new QRadioButton(m_joinGroup);
QRadioButton *svgMiterJoin = new QRadioButton(m_joinGroup);
QRadioButton *roundJoin = new QRadioButton(m_joinGroup);
m_joinGroup->setTitle(tr("Join Style"));
bevelJoin->setText(tr("Bevel"));
miterJoin->setText(tr("Miter"));
svgMiterJoin->setText(tr("SvgMiter"));
roundJoin->setText(tr("Round"));
m_styleGroup = new QGroupBox(parent);
@ -145,6 +147,7 @@ void PathStrokeControls::createCommonControls(QWidget* parent)
QVBoxLayout *joinGroupLayout = new QVBoxLayout(m_joinGroup);
joinGroupLayout->addWidget(bevelJoin);
joinGroupLayout->addWidget(miterJoin);
joinGroupLayout->addWidget(svgMiterJoin);
joinGroupLayout->addWidget(roundJoin);
QVBoxLayout *styleGroupLayout = new QVBoxLayout(m_styleGroup);
@ -167,6 +170,7 @@ void PathStrokeControls::createCommonControls(QWidget* parent)
connect(bevelJoin, SIGNAL(clicked()), m_renderer, SLOT(setBevelJoin()));
connect(miterJoin, SIGNAL(clicked()), m_renderer, SLOT(setMiterJoin()));
connect(svgMiterJoin, SIGNAL(clicked()), m_renderer, SLOT(setSvgMiterJoin()));
connect(roundJoin, SIGNAL(clicked()), m_renderer, SLOT(setRoundJoin()));
connect(curveMode, SIGNAL(clicked()), m_renderer, SLOT(setCurveMode()));

View File

@ -92,6 +92,7 @@ public slots:
void setBevelJoin() { m_joinStyle = Qt::BevelJoin; update(); }
void setMiterJoin() { m_joinStyle = Qt::MiterJoin; update(); }
void setSvgMiterJoin() { m_joinStyle = Qt::SvgMiterJoin; update(); }
void setRoundJoin() { m_joinStyle = Qt::RoundJoin; update(); }
void setCurveMode() { m_pathMode = CurveMode; update(); }

View File

@ -20,7 +20,7 @@ isEmpty(CTEST_VERSION) {
return()
}
!versionAtLeast(CMAKE_VERSION, 2.8.3) {
!versionAtLeast(CMAKE_VERSION, 3.1.0) {
message("cmake $$CMAKE_VERSION is too old for this test.")
return()
}

View File

@ -1,13 +1,7 @@
!!IF !equals(TEMPLATE, aux)
if (CMAKE_VERSION VERSION_LESS 2.8.3)
message(FATAL_ERROR \"Qt 5 requires at least CMake version 2.8.3\")
if (CMAKE_VERSION VERSION_LESS 3.1.0)
message(FATAL_ERROR \"Qt 5 $${CMAKE_MODULE_NAME} module requires at least CMake version 3.1.0\")
endif()
!!ELSE
if (CMAKE_VERSION VERSION_LESS 3.0.0)
message(FATAL_ERROR \"Qt 5 $${CMAKE_MODULE_NAME} module requires at least CMake version 3.0.0\")
endif()
!!ENDIF
!!IF !isEmpty(CMAKE_USR_MOVE_WORKAROUND)
!!IF !isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
@ -161,9 +155,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
set(_Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES \"$${CMAKE_MODULE_DEPS}\")
!!IF !isEmpty(CMAKE_INTERFACE_MODULE_DEPS)
if (NOT CMAKE_VERSION VERSION_LESS 3.0.0)
list(APPEND _Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES \"$${CMAKE_INTERFACE_MODULE_DEPS}\")
endif()
!!ENDIF
set(Qt5$${CMAKE_MODULE_NAME}_OWN_PRIVATE_INCLUDE_DIRS ${Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS})
@ -219,9 +211,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
set(_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES \"$${CMAKE_QT5_MODULE_DEPS}\")
!!IF !isEmpty(CMAKE_INTERFACE_QT5_MODULE_DEPS)
if (NOT CMAKE_VERSION VERSION_LESS 3.0.0)
list(APPEND _Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES \"$${CMAKE_INTERFACE_QT5_MODULE_DEPS}\")
endif()
!!ENDIF
!!IF !isEmpty(CMAKE_STATIC_TYPE)
@ -252,8 +242,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
endif()
endforeach()
if (_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIRS_EXIST
AND NOT CMAKE_VERSION VERSION_LESS 3.0.0 )
if (_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIRS_EXIST)
add_library(Qt5::$${CMAKE_MODULE_NAME}Private INTERFACE IMPORTED)
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME}Private PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${Qt5$${CMAKE_MODULE_NAME}_OWN_PRIVATE_INCLUDE_DIRS}

View File

@ -2913,7 +2913,8 @@
Returns the absolute path of \c path.
If \c base is not specified, uses the current directory as the base
directory.
directory. If it is a relative path, it is resolved relative to the current
directory before use.
For example, the following call returns the string
\c {"/home/johndoe/myproject/readme.txt"}:
@ -3152,9 +3153,15 @@
\section2 relative_path(filePath[, base])
Returns the path to \c filePath relative to \c base. If \c base is not
specified, it is the current project directory. This function is a wrapper
around QDir::relativeFilePath.
Returns the path to \c filePath relative to \c base.
If \c base is not specified, it is the current project
directory. If it is relative, it is resolved relative to the
current project directory before use.
If \c filePath is relative, it is first resolved against the base
directory; in that case, this function effectively acts as
$$clean_path().
See also \l{absolute_path(path[, base])}{absolute_path()},
\l{clean_path(path)}{clean_path()}.

View File

@ -103,7 +103,7 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName)
return QDir::cleanPath(fileName);
#ifdef Q_OS_WIN // Add drive to otherwise-absolute path:
if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') {
Q_ASSERT(isAbsolutePath(baseDir));
Q_ASSERT_X(isAbsolutePath(baseDir), "IoUtils::resolvePath", qUtf8Printable(baseDir));
return QDir::cleanPath(baseDir.left(2) + fileName);
}
#endif // Q_OS_WIN

View File

@ -1178,7 +1178,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
evalError(fL1S("absolute_path(path[, base]) requires one or two arguments."));
} else {
QString arg = args.at(0).toQString(m_tmp1);
QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory();
QString baseDir = args.count() > 1
? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2))
: currentDirectory();
QString rstr = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg);
ret << (rstr.isSharedWith(m_tmp1)
? args.at(0)
@ -1192,7 +1194,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
evalError(fL1S("relative_path(path[, base]) requires one or two arguments."));
} else {
QString arg = args.at(0).toQString(m_tmp1);
QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory();
QString baseDir = args.count() > 1
? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2))
: currentDirectory();
QString absArg = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg);
QString rstr = QDir(baseDir).relativeFilePath(absArg);
ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));

View File

@ -1,6 +1,6 @@
if (CMAKE_VERSION VERSION_LESS 2.8.9)
message(FATAL_ERROR \"Qt5 requires at least CMake version 2.8.9\")
if (CMAKE_VERSION VERSION_LESS 3.1.0)
message(FATAL_ERROR \"Qt5 requires at least CMake version 3.1.0\")
endif()
if (NOT Qt5_FIND_COMPONENTS)

View File

@ -78,27 +78,10 @@ set(Qt5_POSITION_INDEPENDENT_CODE True)
# Applications now need to be compiled with the -fPIC option if the Qt option
# \"reduce relocations\" is active. For backward compatibility only, Qt accepts
# the use of -fPIE for GCC 4.x versions.
if (CMAKE_VERSION VERSION_LESS 2.8.12
AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\"
OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))
set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\")
else()
set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_OPTIONS $$QMAKE_CXXFLAGS_APP)
endif()
set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_OPTIONS $$QMAKE_CXXFLAGS_APP)
# Applications using qmake or cmake >= 2.8.12 as their build system will
# adapt automatically. Applications using an older release of cmake in
# combination with GCC 5.x need to change their CMakeLists.txt to add
# Qt5Core_EXECUTABLE_COMPILE_FLAGS to CMAKE_CXX_FLAGS. In particular,
# applications using cmake >= 2.8.9 and < 2.8.11 will continue to build
# with the -fPIE option and invoke the special compatibility mode if using
# GCC 4.x.
# TODO Qt6: Remove
set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"\")
if (CMAKE_VERSION VERSION_LESS 2.8.12
AND (CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\"
AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))
set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIC\")
endif()
!!IF !isEmpty(QT_NAMESPACE)
list(APPEND Qt5Core_DEFINITIONS -DQT_NAMESPACE=$$QT_NAMESPACE)
@ -157,7 +140,7 @@ if (NOT TARGET Qt5::WinMain)
)
!!ENDIF
if (NOT CMAKE_VERSION VERSION_LESS 2.8.11 AND NOT Qt5_NO_LINK_QTMAIN)
if (NOT Qt5_NO_LINK_QTMAIN)
set(_isExe $<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>)
set(_isWin32 $<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>)
set(_isNotExcluded $<NOT:$<BOOL:$<TARGET_PROPERTY:Qt5_NO_LINK_QTMAIN>>>)

View File

@ -152,9 +152,6 @@ function(QT5_GENERATE_MOC infile outfile )
set(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}")
endif()
if ("x${ARGV2}" STREQUAL "xTARGET")
if (CMAKE_VERSION VERSION_LESS 2.8.12)
message(FATAL_ERROR "The TARGET parameter to qt5_generate_moc is only available when using CMake 2.8.12 or later.")
endif()
set(moc_target ${ARGV3})
endif()
qt5_create_moc_command(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}" "")
@ -178,9 +175,6 @@ function(QT5_WRAP_CPP outfiles )
set(moc_target ${_WRAP_CPP_TARGET})
set(moc_depends ${_WRAP_CPP_DEPENDS})
if (moc_target AND CMAKE_VERSION VERSION_LESS 2.8.12)
message(FATAL_ERROR "The TARGET parameter to qt5_wrap_cpp is only available when using CMake 2.8.12 or later.")
endif()
foreach(it ${moc_files})
get_filename_component(it ${it} ABSOLUTE)
qt5_make_output_file(${it} moc_ cpp outfile)
@ -300,54 +294,3 @@ function(QT5_ADD_RESOURCES outfiles )
endfunction()
set(_Qt5_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..")
if (NOT CMAKE_VERSION VERSION_LESS 2.8.9)
macro(qt5_use_modules _target _link_type)
if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.11)
if(CMAKE_WARN_DEPRECATED)
set(messageType WARNING)
endif()
if(CMAKE_ERROR_DEPRECATED)
set(messageType FATAL_ERROR)
endif()
if(messageType)
message(${messageType} "The qt5_use_modules macro is obsolete. Use target_link_libraries with IMPORTED targets instead.")
endif()
endif()
if (NOT TARGET ${_target})
message(FATAL_ERROR "The first argument to qt5_use_modules must be an existing target.")
endif()
if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE" )
set(_qt5_modules ${ARGN})
set(_qt5_link_type ${_link_type})
else()
set(_qt5_modules ${_link_type} ${ARGN})
endif()
if ("${_qt5_modules}" STREQUAL "")
message(FATAL_ERROR "qt5_use_modules requires at least one Qt module to use.")
endif()
foreach(_module ${_qt5_modules})
if (NOT Qt5${_module}_FOUND)
find_package(Qt5${_module} PATHS "${_Qt5_COMPONENT_PATH}" NO_DEFAULT_PATH)
if (NOT Qt5${_module}_FOUND)
message(FATAL_ERROR "Can not use \"${_module}\" module which has not yet been found.")
endif()
endif()
target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES})
set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${Qt5${_module}_INCLUDE_DIRS})
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${Qt5${_module}_COMPILE_DEFINITIONS})
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG)
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG)
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG)
if (Qt5_POSITION_INDEPENDENT_CODE
AND (CMAKE_VERSION VERSION_LESS 2.8.12
AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)))
set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE})
endif()
endforeach()
endmacro()
endif()

View File

@ -87,6 +87,7 @@
#define QT_FEATURE_journald -1
#define QT_FEATURE_futimens -1
#define QT_FEATURE_futimes -1
#define QT_FEATURE_itemmodel -1
#define QT_FEATURE_library -1
#ifdef __linux__
# define QT_FEATURE_linkat 1

View File

@ -676,8 +676,11 @@ QFile::rename(const QString &newName)
return !error;
}
close();
d->setError(QFile::RenameError,
tr("Cannot open destination file: %1").arg(out.errorString()));
} else {
d->setError(QFile::RenameError, errorString());
}
d->setError(QFile::RenameError, out.isOpen() ? errorString() : out.errorString());
}
return false;
}

View File

@ -1,20 +1,46 @@
# Qt itemmodels core module
!qtConfig(itemmodel): return()
HEADERS += \
itemmodels/qabstractitemmodel.h \
itemmodels/qabstractitemmodel_p.h \
itemmodels/qabstractproxymodel.h \
itemmodels/qabstractproxymodel_p.h \
itemmodels/qitemselectionmodel.h \
itemmodels/qitemselectionmodel_p.h \
itemmodels/qidentityproxymodel.h \
itemmodels/qsortfilterproxymodel.h \
itemmodels/qstringlistmodel.h
itemmodels/qitemselectionmodel_p.h
SOURCES += \
itemmodels/qabstractitemmodel.cpp \
itemmodels/qabstractproxymodel.cpp \
itemmodels/qitemselectionmodel.cpp \
itemmodels/qidentityproxymodel.cpp \
itemmodels/qsortfilterproxymodel.cpp \
itemmodels/qitemselectionmodel.cpp
qtConfig(proxymodel) {
HEADERS += \
itemmodels/qabstractproxymodel.h \
itemmodels/qabstractproxymodel_p.h
SOURCES += \
itemmodels/qabstractproxymodel.cpp
qtConfig(identityproxymodel) {
HEADERS += \
itemmodels/qidentityproxymodel.h
SOURCES += \
itemmodels/qidentityproxymodel.cpp
}
qtConfig(sortfilterproxymodel) {
HEADERS += \
itemmodels/qsortfilterproxymodel.h
SOURCES += \
itemmodels/qsortfilterproxymodel.cpp
}
}
qtConfig(stringlistmodel) {
HEADERS += \
itemmodels/qstringlistmodel.h
SOURCES += \
itemmodels/qstringlistmodel.cpp
}

View File

@ -45,6 +45,8 @@
#include <QtCore/qhash.h>
#include <QtCore/qvector.h>
QT_REQUIRE_CONFIG(itemmodel);
QT_BEGIN_NAMESPACE

View File

@ -60,6 +60,8 @@
QT_BEGIN_NAMESPACE
QT_REQUIRE_CONFIG(itemmodel);
class QPersistentModelIndexData
{
public:

View File

@ -38,9 +38,6 @@
****************************************************************************/
#include "qabstractproxymodel.h"
#ifndef QT_NO_PROXYMODEL
#include "qitemselectionmodel.h"
#include <private/qabstractproxymodel_p.h>
#include <QtCore/QSize>
@ -471,5 +468,3 @@ Qt::DropActions QAbstractProxyModel::supportedDropActions() const
QT_END_NAMESPACE
#include "moc_qabstractproxymodel.cpp"
#endif // QT_NO_PROXYMODEL

View File

@ -42,11 +42,10 @@
#include <QtCore/qabstractitemmodel.h>
QT_REQUIRE_CONFIG(proxymodel);
QT_BEGIN_NAMESPACE
#ifndef QT_NO_PROXYMODEL
class QAbstractProxyModelPrivate;
class QItemSelection;
@ -112,8 +111,6 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_sourceModelDestroyed())
};
#endif // QT_NO_PROXYMODEL
QT_END_NAMESPACE
#endif // QABSTRACTPROXYMODEL_H

View File

@ -54,7 +54,7 @@
#include "private/qabstractitemmodel_p.h"
#ifndef QT_NO_PROXYMODEL
QT_REQUIRE_CONFIG(proxymodel);
QT_BEGIN_NAMESPACE
@ -71,6 +71,4 @@ public:
QT_END_NAMESPACE
#endif // QT_NO_PROXYMODEL
#endif // QABSTRACTPROXYMODEL_P_H

View File

@ -38,9 +38,6 @@
****************************************************************************/
#include "qidentityproxymodel.h"
#ifndef QT_NO_IDENTITYPROXYMODEL
#include "qitemselectionmodel.h"
#include <private/qabstractproxymodel_p.h>
@ -616,5 +613,3 @@ void QIdentityProxyModelPrivate::_q_sourceRowsRemoved(const QModelIndex &parent,
QT_END_NAMESPACE
#include "moc_qidentityproxymodel.cpp"
#endif // QT_NO_IDENTITYPROXYMODEL

View File

@ -43,7 +43,7 @@
#include <QtCore/qabstractproxymodel.h>
#ifndef QT_NO_IDENTITYPROXYMODEL
QT_REQUIRE_CONFIG(identityproxymodel);
QT_BEGIN_NAMESPACE
@ -110,7 +110,5 @@ private:
QT_END_NAMESPACE
#endif // QT_NO_IDENTITYPROXYMODEL
#endif // QIDENTITYPROXYMODEL_H

View File

@ -47,6 +47,8 @@
#include <QtCore/qlist.h>
#include <QtCore/qabstractitemmodel.h>
QT_REQUIRE_CONFIG(itemmodel);
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QItemSelectionRange

View File

@ -53,6 +53,8 @@
#include "private/qobject_p.h"
QT_REQUIRE_CONFIG(itemmodel);
QT_BEGIN_NAMESPACE
class QItemSelectionModelPrivate: public QObjectPrivate

View File

@ -38,9 +38,6 @@
****************************************************************************/
#include "qsortfilterproxymodel.h"
#ifndef QT_NO_SORTFILTERPROXYMODEL
#include "qitemselectionmodel.h"
#include <qsize.h>
#include <qdebug.h>
@ -2896,5 +2893,3 @@ QItemSelection QSortFilterProxyModel::mapSelectionFromSource(const QItemSelectio
QT_END_NAMESPACE
#include "moc_qsortfilterproxymodel.cpp"
#endif // QT_NO_SORTFILTERPROXYMODEL

View File

@ -41,11 +41,10 @@
#define QSORTFILTERPROXYMODEL_H
#include <QtCore/qabstractproxymodel.h>
#ifndef QT_NO_SORTFILTERPROXYMODEL
#include <QtCore/qregexp.h>
QT_REQUIRE_CONFIG(sortfilterproxymodel);
QT_BEGIN_NAMESPACE
@ -198,6 +197,4 @@ private:
QT_END_NAMESPACE
#endif // QT_NO_SORTFILTERPROXYMODEL
#endif // QSORTFILTERPROXYMODEL_H

View File

@ -47,8 +47,6 @@
#include <algorithm>
#ifndef QT_NO_STRINGLISTMODEL
QT_BEGIN_NAMESPACE
/*!
@ -329,5 +327,3 @@ Qt::DropActions QStringListModel::supportedDropActions() const
QT_END_NAMESPACE
#include "moc_qstringlistmodel.cpp"
#endif // QT_NO_STRINGLISTMODEL

View File

@ -43,11 +43,10 @@
#include <QtCore/qabstractitemmodel.h>
#include <QtCore/qstringlist.h>
QT_REQUIRE_CONFIG(stringlistmodel);
QT_BEGIN_NAMESPACE
#ifndef QT_NO_STRINGLISTMODEL
class Q_CORE_EXPORT QStringListModel : public QAbstractListModel
{
Q_OBJECT
@ -78,8 +77,6 @@ private:
QStringList lst;
};
#endif // QT_NO_STRINGLISTMODEL
QT_END_NAMESPACE
#endif // QSTRINGLISTMODEL_H

View File

@ -61,7 +61,6 @@
# include "qbitarray.h"
# include "qurl.h"
# include "qvariant.h"
# include "qabstractitemmodel.h"
# include "qjsonvalue.h"
# include "qjsonobject.h"
# include "qjsonarray.h"
@ -69,6 +68,10 @@
# include "qbytearraylist.h"
#endif
#if QT_CONFIG(itemmodel)
# include "qabstractitemmodel.h"
#endif
#ifndef QT_NO_GEOM_VARIANT
# include "qsize.h"
# include "qpoint.h"
@ -1349,8 +1352,10 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
case QMetaType::Void:
case QMetaType::VoidStar:
case QMetaType::QObjectStar:
#if QT_CONFIG(itemmodel)
case QMetaType::QModelIndex:
case QMetaType::QPersistentModelIndex:
#endif
case QMetaType::QJsonValue:
case QMetaType::QJsonObject:
case QMetaType::QJsonArray:
@ -1573,8 +1578,10 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
case QMetaType::Void:
case QMetaType::VoidStar:
case QMetaType::QObjectStar:
#if QT_CONFIG(itemmodel)
case QMetaType::QModelIndex:
case QMetaType::QPersistentModelIndex:
#endif
case QMetaType::QJsonValue:
case QMetaType::QJsonObject:
case QMetaType::QJsonArray:

View File

@ -89,6 +89,14 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
F(VoidStar, 31, void*) \
#if QT_CONFIG(itemmodel)
#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)\
F(QModelIndex, 42, QModelIndex) \
F(QPersistentModelIndex, 50, QPersistentModelIndex)
#else
#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
#endif
#define QT_FOR_EACH_STATIC_CORE_CLASS(F)\
F(QChar, 7, QChar) \
F(QString, 10, QString) \
@ -112,13 +120,12 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QEasingCurve, 29, QEasingCurve) \
F(QUuid, 30, QUuid) \
F(QVariant, 41, QVariant) \
F(QModelIndex, 42, QModelIndex) \
F(QRegularExpression, 44, QRegularExpression) \
F(QJsonValue, 45, QJsonValue) \
F(QJsonObject, 46, QJsonObject) \
F(QJsonArray, 47, QJsonArray) \
F(QJsonDocument, 48, QJsonDocument) \
F(QPersistentModelIndex, 50, QPersistentModelIndex) \
QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
F(QObjectStar, 39, QObject*)

View File

@ -201,8 +201,6 @@ template<> struct TypeDefinition<QJsonArray> { static const bool IsAvailable = f
template<> struct TypeDefinition<QJsonDocument> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QJsonObject> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QJsonValue> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QModelIndex> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QPersistentModelIndex> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QUrl> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QByteArrayList> { static const bool IsAvailable = false; };
#endif

View File

@ -56,8 +56,10 @@
#include "qurl.h"
#include "qlocale.h"
#include "quuid.h"
#ifndef QT_BOOTSTRAPPED
#if QT_CONFIG(itemmodel)
#include "qabstractitemmodel.h"
#endif
#ifndef QT_BOOTSTRAPPED
#include "qjsonvalue.h"
#include "qjsonobject.h"
#include "qjsonarray.h"
@ -393,6 +395,8 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
return false;
}
break;
#endif // QT_BOOTSTRAPPED
#if QT_CONFIG(itemmodel)
case QVariant::ModelIndex:
switch (d->type) {
case QVariant::PersistentModelIndex:
@ -411,7 +415,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
return false;
}
break;
#endif // QT_BOOTSTRAPPED
#endif // QT_CONFIG(itemmodel)
case QVariant::String: {
QString *str = static_cast<QString *>(result);
switch (d->type) {
@ -1952,12 +1956,6 @@ QVariant::QVariant(const QRegularExpression &re)
QVariant::QVariant(const QUuid &uuid)
: d(Uuid)
{ v_construct<QUuid>(&d, uuid); }
QVariant::QVariant(const QModelIndex &modelIndex)
: d(ModelIndex)
{ v_construct<QModelIndex>(&d, modelIndex); }
QVariant::QVariant(const QPersistentModelIndex &modelIndex)
: d(PersistentModelIndex)
{ v_construct<QPersistentModelIndex>(&d, modelIndex); }
QVariant::QVariant(const QJsonValue &jsonValue)
: d(QMetaType::QJsonValue)
{ v_construct<QJsonValue>(&d, jsonValue); }
@ -1971,6 +1969,14 @@ QVariant::QVariant(const QJsonDocument &jsonDocument)
: d(QMetaType::QJsonDocument)
{ v_construct<QJsonDocument>(&d, jsonDocument); }
#endif // QT_BOOTSTRAPPED
#if QT_CONFIG(itemmodel)
QVariant::QVariant(const QModelIndex &modelIndex)
: d(ModelIndex)
{ v_construct<QModelIndex>(&d, modelIndex); }
QVariant::QVariant(const QPersistentModelIndex &modelIndex)
: d(PersistentModelIndex)
{ v_construct<QPersistentModelIndex>(&d, modelIndex); }
#endif
/*!
Returns the storage type of the value stored in the variant.
@ -2668,21 +2674,7 @@ QRegularExpression QVariant::toRegularExpression() const
}
#endif // QT_CONFIG(regularexpression)
#ifndef QT_BOOTSTRAPPED
/*!
\since 5.0
Returns the variant as a QUuid if the variant has type()
\l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString;
otherwise returns a default-constructed QUuid.
\sa canConvert(), convert()
*/
QUuid QVariant::toUuid() const
{
return qVariantToHelper<QUuid>(d, handlerManager);
}
#if QT_CONFIG(itemmodel)
/*!
\since 5.0
@ -2708,6 +2700,22 @@ QPersistentModelIndex QVariant::toPersistentModelIndex() const
{
return qVariantToHelper<QPersistentModelIndex>(d, handlerManager);
}
#endif // QT_CONFIG(itemmodel)
#ifndef QT_BOOTSTRAPPED
/*!
\since 5.0
Returns the variant as a QUuid if the variant has type()
\l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString;
otherwise returns a default-constructed QUuid.
\sa canConvert(), convert()
*/
QUuid QVariant::toUuid() const
{
return qVariantToHelper<QUuid>(d, handlerManager);
}
/*!
\since 5.0
@ -3182,9 +3190,11 @@ bool QVariant::canConvert(int targetTypeId) const
if (d.type == targetTypeId)
return true;
#if QT_CONFIG(itemmodel)
if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex)
|| (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex))
return true;
#endif
if (targetTypeId == QMetaType::QVariantList
&& (d.type == QMetaType::QVariantList

View File

@ -165,8 +165,10 @@ class Q_CORE_EXPORT QVariant
Hash = QMetaType::QVariantHash,
EasingCurve = QMetaType::QEasingCurve,
Uuid = QMetaType::QUuid,
#if QT_CONFIG(itemmodel)
ModelIndex = QMetaType::QModelIndex,
PersistentModelIndex = QMetaType::QPersistentModelIndex,
#endif
LastCoreType = QMetaType::LastCoreType,
Font = QMetaType::QFont,
@ -255,13 +257,15 @@ class Q_CORE_EXPORT QVariant
QVariant(const QUrl &url);
QVariant(const QEasingCurve &easing);
QVariant(const QUuid &uuid);
QVariant(const QModelIndex &modelIndex);
QVariant(const QPersistentModelIndex &modelIndex);
QVariant(const QJsonValue &jsonValue);
QVariant(const QJsonObject &jsonObject);
QVariant(const QJsonArray &jsonArray);
QVariant(const QJsonDocument &jsonDocument);
#endif // QT_BOOTSTRAPPED
#if QT_CONFIG(itemmodel)
QVariant(const QModelIndex &modelIndex);
QVariant(const QPersistentModelIndex &modelIndex);
#endif
QVariant& operator=(const QVariant &other);
#ifdef Q_COMPILER_RVALUE_REFS
@ -329,13 +333,15 @@ class Q_CORE_EXPORT QVariant
QUrl toUrl() const;
QEasingCurve toEasingCurve() const;
QUuid toUuid() const;
QModelIndex toModelIndex() const;
QPersistentModelIndex toPersistentModelIndex() const;
QJsonValue toJsonValue() const;
QJsonObject toJsonObject() const;
QJsonArray toJsonArray() const;
QJsonDocument toJsonDocument() const;
#endif // QT_BOOTSTRAPPED
#if QT_CONFIG(itemmodel)
QModelIndex toModelIndex() const;
QPersistentModelIndex toPersistentModelIndex() const;
#endif
#ifndef QT_NO_DATASTREAM
void load(QDataStream &ds);

View File

@ -797,6 +797,13 @@ struct BezierEase : public QEasingCurveFunction
return t3;
}
bool static inline almostZero(qreal value)
{
// 1e-3 might seem excessively fuzzy, but any smaller value will make the
// factors a, b, and c large enough to knock out the cubic solver.
return value > -1e-3 && value < 1e-3;
}
qreal static inline findTForX(const SingleCubicBezier &singleCubicBezier, qreal x)
{
const qreal p0 = singleCubicBezier.p0x;
@ -809,6 +816,32 @@ struct BezierEase : public QEasingCurveFunction
const qreal factorT1 = -3 * p0 + 3 * p1;
const qreal factorT0 = p0 - x;
// Cases for quadratic, linear and invalid equations
if (almostZero(factorT3)) {
if (almostZero(factorT2)) {
if (almostZero(factorT1))
return 0.0;
return -factorT0 / factorT1;
}
const qreal discriminant = factorT1 * factorT1 - 4.0 * factorT2 * factorT0;
if (discriminant < 0.0)
return 0.0;
if (discriminant == 0.0)
return -factorT1 / (2.0 * factorT2);
const qreal solution1 = (-factorT1 + std::sqrt(discriminant)) / (2.0 * factorT2);
if (solution1 >= 0.0 && solution1 <= 1.0)
return solution1;
const qreal solution2 = (-factorT1 - std::sqrt(discriminant)) / (2.0 * factorT2);
if (solution2 >= 0.0 && solution2 <= 1.0)
return solution2;
return 0.0;
}
const qreal a = factorT2 / factorT3;
const qreal b = factorT1 / factorT3;
const qreal c = factorT0 / factorT3;

View File

@ -176,11 +176,11 @@ public:
inline QVarLengthArray<T, Prealloc> &operator<<(const T &t)
{ append(t); return *this; }
inline QVarLengthArray<T, Prealloc> &operator<<(T &&t)
{ append(t); return *this; }
{ append(std::move(t)); return *this; }
inline QVarLengthArray<T, Prealloc> &operator+=(const T &t)
{ append(t); return *this; }
inline QVarLengthArray<T, Prealloc> &operator+=(T &&t)
{ append(t); return *this; }
{ append(std::move(t)); return *this; }
void prepend(T &&t);
void prepend(const T &t);

View File

@ -284,9 +284,9 @@ public:
inline QVector<T> &operator<<(const QVector<T> &l)
{ *this += l; return *this; }
inline QVector<T> &operator+=(T &&t)
{ append(t); return *this; }
{ append(std::move(t)); return *this; }
inline QVector<T> &operator<<(T &&t)
{ append(t); return *this; }
{ append(std::move(t)); return *this; }
QList<T> toList() const;

View File

@ -61,8 +61,7 @@ function(QT5_ADD_DBUS_INTERFACE _sources _interface _basename)
COMMAND ${Qt5DBus_QDBUSXML2CPP_EXECUTABLE} ${_params} -p ${_basename} ${_infile}
DEPENDS ${_infile} VERBATIM)
set_source_files_properties("${_impl}" PROPERTIES SKIP_AUTOMOC TRUE)
set_source_files_properties("${_header}" PROPERTIES SKIP_AUTOMOC TRUE)
set_source_files_properties("${_impl}" "${_header}" PROPERTIES SKIP_AUTOMOC TRUE)
qt5_generate_moc("${_header}" "${_moc}")
@ -147,8 +146,7 @@ function(QT5_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optio
endif()
qt5_generate_moc("${_header}" "${_moc}")
set_source_files_properties("${_impl}" PROPERTIES SKIP_AUTOMOC TRUE)
set_source_files_properties("${_header}" PROPERTIES SKIP_AUTOMOC TRUE)
set_source_files_properties("${_impl}" "${_header}" PROPERTIES SKIP_AUTOMOC TRUE)
macro_add_file_dependencies("${_impl}" "${_moc}")
list(APPEND ${_sources} "${_impl}" "${_header}" "${_moc}")

View File

@ -137,6 +137,16 @@ void qt_scale_image_16bit(uchar *destPixels, int dbpl,
// this bounds check here is required as floating point rounding above might in some cases lead to
// w/h values that are one pixel too large, falling outside of the valid image area.
const int ystart = srcy >> 16;
if (ystart >= srch && iy < 0) {
srcy += iy;
--h;
}
const int xstart = basex >> 16;
if (xstart >= (int)(sbpl/sizeof(SRC)) && ix < 0) {
basex += ix;
--w;
}
int yend = (srcy + iy * (h - 1)) >> 16;
if (yend < 0 || yend >= srch)
--h;
@ -248,6 +258,16 @@ template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl,
// this bounds check here is required as floating point rounding above might in some cases lead to
// w/h values that are one pixel too large, falling outside of the valid image area.
const int ystart = srcy >> 16;
if (ystart >= srch && iy < 0) {
srcy += iy;
--h;
}
const int xstart = basex >> 16;
if (xstart >= (int)(sbpl/sizeof(quint32)) && ix < 0) {
basex += ix;
--w;
}
int yend = (srcy + iy * (h - 1)) >> 16;
if (yend < 0 || yend >= srch)
--h;

View File

@ -558,6 +558,16 @@ void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
// this bounds check here is required as floating point rounding above might in some cases lead to
// w/h values that are one pixel too large, falling outside of the valid image area.
const int ystart = srcy >> 16;
if (ystart >= srch && iy < 0) {
srcy += iy;
--h;
}
const int xstart = basex >> 16;
if (xstart >= (int)(sbpl/sizeof(quint32)) && ix < 0) {
basex += ix;
--w;
}
int yend = (srcy + iy * (h - 1)) >> 16;
if (yend < 0 || yend >= srch)
--h;

View File

@ -698,6 +698,11 @@ void QRasterPaintEngine::setState(QPainterState *s)
{
Q_D(QRasterPaintEngine);
QPaintEngineEx::setState(s);
QRasterPaintEngineState *t = state();
if (t->clip && t->clip->enabled != t->clipEnabled) {
// Since we do not "detach" clipdata when changing only enabled state, we need to resync state here
t->clip->enabled = t->clipEnabled;
}
d->rasterBuffer->compositionMode = s->composition_mode;
}

View File

@ -1033,7 +1033,6 @@ void QPainterPath::addRect(const QRectF &r)
bool first = d_func()->elements.size() < 2;
d_func()->elements.reserve(d_func()->elements.size() + 5);
moveTo(r.x(), r.y());
Element l1 = { r.x() + r.width(), r.y(), LineToElement };
@ -1071,8 +1070,6 @@ void QPainterPath::addPolygon(const QPolygonF &polygon)
ensureData();
detach();
d_func()->elements.reserve(d_func()->elements.size() + polygon.size());
moveTo(polygon.constFirst());
for (int i=1; i<polygon.size(); ++i) {
Element elm = { polygon.at(i).x(), polygon.at(i).y(), LineToElement };
@ -1115,9 +1112,7 @@ void QPainterPath::addEllipse(const QRectF &boundingRect)
ensureData();
detach();
Q_D(QPainterPath);
bool first = d_func()->elements.size() < 2;
d->elements.reserve(d->elements.size() + 13);
QPointF pts[12];
int point_count;
@ -1294,7 +1289,6 @@ void QPainterPath::addRegion(const QRegion &region)
ensureData();
detach();
d_func()->elements.reserve(region.rectCount() * 5);
for (const QRect &rect : region)
addRect(rect);
}
@ -2463,7 +2457,6 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
Q_ASSERT(p.d_func()->elements.at(0).type == QPainterPath::MoveToElement);
p.d_func()->elements.clear();
}
p.d_func()->elements.reserve(p.d_func()->elements.size() + size);
for (int i=0; i<size; ++i) {
int type;
double x, y;

View File

@ -382,7 +382,14 @@ static void getAddresses(int sock, char *buf, QList<QNetworkInterfacePrivate *>
auto payloadPtr = reinterpret_cast<uchar *>(RTA_DATA(rta));
switch (rta->rta_type) {
case IFA_ADDRESS: // address
case IFA_ADDRESS:
// Local address (all interfaces except for point-to-point)
if (entry.ip().isNull())
entry.setIp(makeAddress(payloadPtr, payloadLen));
break;
case IFA_LOCAL:
// Override the local address (point-to-point interfaces)
entry.setIp(makeAddress(payloadPtr, payloadLen));
break;

View File

@ -87,6 +87,9 @@ typedef IAsyncOperationWithProgress<IBuffer *, UINT32> IAsyncBufferOperation;
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcNetworkSocket, "qt.network.socket");
Q_LOGGING_CATEGORY(lcNetworkSocketVerbose, "qt.network.socket.verbose");
#if _MSC_VER >= 1900
static HRESULT qt_winrt_try_create_thread_network_context(QString host, ComPtr<IThreadNetworkContext> &context)
{
@ -167,11 +170,14 @@ public:
SocketEngineWorker(QNativeSocketEnginePrivate *engine)
: enginePrivate(engine)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << engine;
}
~SocketEngineWorker()
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
if (Q_UNLIKELY(initialReadOp)) {
qCDebug(lcNetworkSocket) << Q_FUNC_INFO << "Closing initial read operation";
ComPtr<IAsyncInfo> info;
HRESULT hr = initialReadOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
@ -184,6 +190,7 @@ public:
}
if (readOp) {
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing read operation";
ComPtr<IAsyncInfo> info;
HRESULT hr = readOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
@ -196,6 +203,7 @@ public:
}
if (connectOp) {
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing connect operation";
ComPtr<IAsyncInfo> info;
HRESULT hr = connectOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
@ -210,30 +218,13 @@ public:
signals:
void connectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString);
void newDatagramsReceived(const QList<WinRtDatagram> &datagram);
void newDataReceived(const QVector<QByteArray> &data);
void newDataReceived();
void socketErrorOccured(QAbstractSocket::SocketError error);
public slots:
Q_INVOKABLE void notifyAboutNewDatagrams()
{
QMutexLocker locker(&mutex);
QList<WinRtDatagram> datagrams = pendingDatagrams;
pendingDatagrams.clear();
emit newDatagramsReceived(datagrams);
}
Q_INVOKABLE void notifyAboutNewData()
{
QMutexLocker locker(&mutex);
const QVector<QByteArray> newData = std::move(pendingData);
pendingData.clear();
emit newDataReceived(newData);
}
public:
void startReading()
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
ComPtr<IBuffer> buffer;
HRESULT hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
Q_ASSERT_SUCCEEDED(hr);
@ -249,6 +240,7 @@ public:
HRESULT onConnectOpFinished(IAsyncAction *action, AsyncStatus)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
HRESULT hr = action->GetResults();
if (FAILED(hr)) {
if (hr == HRESULT_FROM_WIN32(WSAETIMEDOUT)) {
@ -287,6 +279,7 @@ public:
HRESULT OnNewDatagramReceived(IDatagramSocket *, IDatagramSocketMessageReceivedEventArgs *args)
{
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO;
WinRtDatagram datagram;
QHostAddress returnAddress;
ComPtr<IHostName> remoteHost;
@ -311,10 +304,11 @@ public:
datagram.data.resize(length);
hr = reader->ReadBytes(length, reinterpret_cast<BYTE *>(datagram.data.data()));
RETURN_OK_IF_FAILED("Could not read datagram");
QMutexLocker locker(&mutex);
// Notify the engine about new datagrams being present at the next event loop iteration
if (pendingDatagrams.isEmpty())
QMetaObject::invokeMethod(this, "notifyAboutNewDatagrams", Qt::QueuedConnection);
if (emitDataReceived)
emit newDataReceived();
pendingDatagrams << datagram;
return S_OK;
@ -322,6 +316,7 @@ public:
HRESULT onReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
{
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO;
if (asyncInfo == initialReadOp.Get()) {
initialReadOp.Reset();
} else if (asyncInfo == readOp.Get()) {
@ -334,6 +329,7 @@ public:
// that the connection was closed. The socket cannot be closed here, as the subsequent read
// might fail then.
if (status == Error || status == Canceled) {
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Remote host closed";
emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError);
return S_OK;
}
@ -358,6 +354,7 @@ public:
// the closing of the socket won't be communicated to the caller. So only the error is set. The
// actual socket close happens inside of read.
if (!bufferLength) {
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Remote host closed";
emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError);
return S_OK;
}
@ -378,10 +375,10 @@ public:
}
QByteArray newData(reinterpret_cast<const char*>(data), qint64(bufferLength));
QMutexLocker readLocker(&mutex);
if (pendingData.isEmpty())
QMetaObject::invokeMethod(this, "notifyAboutNewData", Qt::QueuedConnection);
pendingData << newData;
emit newDataReceived();
pendingData.append(newData);
readLocker.unlock();
hr = QEventDispatcherWinRT::runOnXamlThread([buffer, this]() {
@ -433,7 +430,8 @@ private:
ComPtr<IStreamSocket> tcpSocket;
QList<WinRtDatagram> pendingDatagrams;
QVector<QByteArray> pendingData;
bool emitDataReceived = true;
QByteArray pendingData;
// Protects pendingData/pendingDatagrams which are accessed from native callbacks
QMutex mutex;
@ -487,6 +485,12 @@ static QByteArray socketDescription(const QAbstractSocketEngine *s)
" not in "#state1" or "#state2); \
return (returnValue); \
} } while (0)
#define Q_CHECK_STATES3(function, state1, state2, state3, returnValue) do { \
if (d->socketState != (state1) && d->socketState != (state2) && d->socketState != (state3)) { \
qWarning(""#function" was called" \
" not in "#state1", "#state2" or "#state3); \
return (returnValue); \
} } while (0)
#define Q_CHECK_TYPE(function, type, returnValue) do { \
if (d->socketType != (type)) { \
qWarning(#function" was called by a" \
@ -509,6 +513,7 @@ static AsyncStatus opStatus(const ComPtr<T> &op)
static qint64 writeIOStream(ComPtr<IOutputStream> stream, const char *data, qint64 len)
{
qCDebug(lcNetworkSocket) << Q_FUNC_INFO << data << len;
ComPtr<IBuffer> buffer;
HRESULT hr = g->bufferFactory->Create(len, &buffer);
Q_ASSERT_SUCCEEDED(hr);
@ -533,6 +538,7 @@ static qint64 writeIOStream(ComPtr<IOutputStream> stream, const char *data, qint
QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
: QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << parent;
qRegisterMetaType<WinRtDatagram>();
qRegisterMetaType<WinRTSocketEngine::ErrorString>();
Q_D(QNativeSocketEngine);
@ -546,20 +552,20 @@ QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::connectOpFinished,
this, &QNativeSocketEngine::handleConnectOpFinished, Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::newDatagramsReceived, this, &QNativeSocketEngine::handleNewDatagrams, Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::newDataReceived,
this, &QNativeSocketEngine::handleNewData, Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::newDataReceived, this, &QNativeSocketEngine::handleNewData, Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::socketErrorOccured,
this, &QNativeSocketEngine::handleTcpError, Qt::QueuedConnection);
}
QNativeSocketEngine::~QNativeSocketEngine()
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
close();
}
bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << type << protocol;
Q_D(QNativeSocketEngine);
if (isValid())
close();
@ -568,6 +574,28 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstract
if (!d->createNewSocket(type, protocol))
return false;
if (type == QAbstractSocket::UdpSocket) {
// Set the broadcasting flag if it's a UDP socket.
if (!setOption(BroadcastSocketOption, 1)) {
d->setError(QAbstractSocket::UnsupportedSocketOperationError,
WinRTSocketEngine::BroadcastingInitFailedErrorString);
close();
return false;
}
// Set some extra flags that are interesting to us, but accept failure
setOption(ReceivePacketInformation, 1);
setOption(ReceiveHopLimit, 1);
}
// Make sure we receive out-of-band data
if (type == QAbstractSocket::TcpSocket
&& !setOption(ReceiveOutOfBandData, 1)) {
qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data");
}
d->socketType = type;
d->socketProtocol = protocol;
return true;
@ -575,6 +603,7 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstract
bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << socketDescriptor << socketState;
Q_D(QNativeSocketEngine);
if (isValid())
@ -622,18 +651,28 @@ bool QNativeSocketEngine::isValid() const
bool QNativeSocketEngine::connectToHost(const QHostAddress &address, quint16 port)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << address << port;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::connectToHost(), false);
Q_CHECK_STATES3(QNativeSocketEngine::connectToHost(), QAbstractSocket::BoundState,
QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false);
const QString addressString = address.toString();
return connectToHostByName(addressString, port);
}
bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << name << port;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::connectToHostByName(), false);
Q_CHECK_STATES3(QNativeSocketEngine::connectToHostByName(), QAbstractSocket::BoundState,
QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false);
HRESULT hr;
#if _MSC_VER >= 1900
ComPtr<IThreadNetworkContext> networkContext;
if (!qEnvironmentVariableIsEmpty("QT_WINRT_USE_THREAD_NETWORK_CONTEXT")) {
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Creating network context";
hr = qt_winrt_try_create_thread_network_context(name, networkContext);
if (FAILED(hr)) {
setError(QAbstractSocket::ConnectionRefusedError, QLatin1String("Could not create thread network context."));
@ -668,6 +707,7 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
#if _MSC_VER >= 1900
if (networkContext != nullptr) {
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing network context";
ComPtr<IClosable> networkContextCloser;
hr = networkContext.As(&networkContextCloser);
Q_ASSERT_SUCCEEDED(hr);
@ -691,7 +731,11 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << address << port;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bind(), false);
Q_CHECK_STATE(QNativeSocketEngine::bind(), QAbstractSocket::UnconnectedState, false);
HRESULT hr;
// runOnXamlThread may only return S_OK (will assert otherwise) so no need to check its result.
// hr is set inside the lambda though. If an error occurred hr will point that out.
@ -773,10 +817,16 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
bool QNativeSocketEngine::listen()
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::listen(), false);
Q_CHECK_STATE(QNativeSocketEngine::listen(), QAbstractSocket::BoundState, false);
#if QT_CONFIG(sctp)
Q_CHECK_TYPES(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket,
QAbstractSocket::SctpSocket, false);
#else
Q_CHECK_TYPE(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket, false);
#endif
if (d->tcpListener && d->socketDescriptor != -1) {
d->socketState = QAbstractSocket::ListeningState;
@ -787,10 +837,16 @@ bool QNativeSocketEngine::listen()
int QNativeSocketEngine::accept()
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::accept(), -1);
Q_CHECK_STATE(QNativeSocketEngine::accept(), QAbstractSocket::ListeningState, -1);
#if QT_CONFIG(sctp)
Q_CHECK_TYPES(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket,
QAbstractSocket::SctpSocket, -1);
#else
Q_CHECK_TYPE(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket, -1);
#endif
if (d->socketDescriptor == -1 || d->pendingConnections.isEmpty()) {
d->setError(QAbstractSocket::TemporaryError, WinRTSocketEngine::TemporaryErrorString);
@ -810,6 +866,7 @@ int QNativeSocketEngine::accept()
void QNativeSocketEngine::close()
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
Q_D(QNativeSocketEngine);
if (d->closingDown)
@ -878,29 +935,41 @@ void QNativeSocketEngine::close()
bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
{
Q_UNUSED(groupAddress);
Q_UNUSED(iface);
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::joinMulticastGroup(), false);
Q_CHECK_STATE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false);
Q_CHECK_TYPE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false);
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << groupAddress << iface;
Q_UNIMPLEMENTED();
return false;
}
bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
{
Q_UNUSED(groupAddress);
Q_UNUSED(iface);
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::leaveMulticastGroup(), false);
Q_CHECK_STATE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false);
Q_CHECK_TYPE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false);
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << groupAddress << iface;
Q_UNIMPLEMENTED();
return false;
}
QNetworkInterface QNativeSocketEngine::multicastInterface() const
{
Q_D(const QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::multicastInterface(), QNetworkInterface());
Q_CHECK_TYPE(QNativeSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface());
Q_UNIMPLEMENTED();
return QNetworkInterface();
}
bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface)
{
Q_UNUSED(iface);
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setMulticastInterface(), false);
Q_CHECK_TYPE(QNativeSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false);
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << iface;
Q_UNIMPLEMENTED();
return false;
}
@ -908,55 +977,64 @@ bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface)
qint64 QNativeSocketEngine::bytesAvailable() const
{
Q_D(const QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1);
Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, -1);
if (d->socketType != QAbstractSocket::TcpSocket)
return -1;
return d->bytesAvailable;
QMutexLocker locker(&d->worker->mutex);
const qint64 bytesAvailable = d->worker->pendingData.length();
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << bytesAvailable;
return bytesAvailable;
}
qint64 QNativeSocketEngine::read(char *data, qint64 maxlen)
{
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << maxlen;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::read(), -1);
Q_CHECK_STATES(QNativeSocketEngine::read(), QAbstractSocket::ConnectedState, QAbstractSocket::BoundState, -1);
if (d->socketType != QAbstractSocket::TcpSocket)
return -1;
// There will be a read notification when the socket was closed by the remote host. If that
// happens and there isn't anything left in the buffer, we have to return -1 in order to signal
// the closing of the socket.
QMutexLocker mutexLocker(&d->readMutex);
if (d->pendingData.isEmpty() && d->socketState != QAbstractSocket::ConnectedState) {
QMutexLocker mutexLocker(&d->worker->mutex);
if (d->worker->pendingData.isEmpty() && d->socketState != QAbstractSocket::ConnectedState) {
close();
return -1;
}
QByteArray readData;
qint64 leftToMaxLen = maxlen;
while (leftToMaxLen > 0 && !d->pendingData.isEmpty()) {
QByteArray pendingData = d->pendingData.takeFirst();
// Do not read the whole data. Put the rest of it back into the "queue"
if (leftToMaxLen < pendingData.length()) {
readData += pendingData.left(leftToMaxLen);
pendingData = pendingData.remove(0, maxlen);
d->pendingData.prepend(pendingData);
break;
const int copyLength = qMin(maxlen, qint64(d->worker->pendingData.length()));
if (maxlen >= d->worker->pendingData.length()) {
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Reading full buffer";
readData = d->worker->pendingData;
d->worker->pendingData.clear();
d->emitReadReady = true;
} else {
readData += pendingData;
leftToMaxLen -= pendingData.length();
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Reading part of the buffer ("
<< copyLength << "of" << d->worker->pendingData.length() << "bytes";
readData = d->worker->pendingData.left(maxlen);
d->worker->pendingData.remove(0, maxlen);
if (d->notifyOnRead)
emit readReady();
}
}
const int copyLength = qMin(maxlen, qint64(readData.length()));
d->bytesAvailable -= copyLength;
mutexLocker.unlock();
memcpy(data, readData, copyLength);
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Read" << copyLength << "bytes";
return copyLength;
}
qint64 QNativeSocketEngine::write(const char *data, qint64 len)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << data << len;
Q_D(QNativeSocketEngine);
if (!isValid())
return -1;
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::write(), -1);
Q_CHECK_STATE(QNativeSocketEngine::write(), QAbstractSocket::ConnectedState, -1);
HRESULT hr = E_FAIL;
ComPtr<IOutputStream> stream;
@ -978,28 +1056,35 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len)
qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header,
PacketHeaderOptions)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << maxlen;
#ifndef QT_NO_UDPSOCKET
Q_D(QNativeSocketEngine);
QMutexLocker locker(&d->readMutex);
if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) {
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::readDatagram(), -1);
Q_CHECK_STATES(QNativeSocketEngine::readDatagram(), QAbstractSocket::BoundState,
QAbstractSocket::ConnectedState, -1);
QMutexLocker locker(&d->worker->mutex);
if (d->socketType != QAbstractSocket::UdpSocket || d->worker->pendingDatagrams.isEmpty()) {
if (header)
header->clear();
return -1;
}
WinRtDatagram datagram = d->pendingDatagrams.takeFirst();
WinRtDatagram datagram = d->worker->pendingDatagrams.takeFirst();
if (header)
*header = datagram.header;
QByteArray readOrigin;
// Do not read the whole datagram. Put the rest of it back into the "queue"
if (maxlen < datagram.data.length()) {
if (maxlen < datagram.data.length())
readOrigin = datagram.data.left(maxlen);
datagram.data = datagram.data.remove(0, maxlen);
d->pendingDatagrams.prepend(datagram);
} else {
else
readOrigin = datagram.data;
if (d->worker->pendingDatagrams.isEmpty()) {
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "That's all folks";
d->worker->emitDataReceived = true;
d->emitReadReady = true;
}
locker.unlock();
memcpy(data, readOrigin, qMin(maxlen, qint64(datagram.data.length())));
return readOrigin.length();
@ -1013,8 +1098,13 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea
qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << data << len;
#ifndef QT_NO_UDPSOCKET
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1);
Q_CHECK_STATES(QNativeSocketEngine::writeDatagram(), QAbstractSocket::BoundState,
QAbstractSocket::ConnectedState, -1);
if (d->socketType != QAbstractSocket::UdpSocket)
return -1;
@ -1051,18 +1141,25 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QI
bool QNativeSocketEngine::hasPendingDatagrams() const
{
Q_D(const QNativeSocketEngine);
QMutexLocker locker(&d->readMutex);
return d->pendingDatagrams.length() > 0;
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::hasPendingDatagrams(), false);
Q_CHECK_NOT_STATE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false);
Q_CHECK_TYPE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false);
QMutexLocker locker(&d->worker->mutex);
return d->worker->pendingDatagrams.length() > 0;
}
qint64 QNativeSocketEngine::pendingDatagramSize() const
{
Q_D(const QNativeSocketEngine);
QMutexLocker locker(&d->readMutex);
if (d->pendingDatagrams.isEmpty())
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::pendingDatagramSize(), -1);
Q_CHECK_TYPE(QNativeSocketEngine::pendingDatagramSize(), QAbstractSocket::UdpSocket, -1);
QMutexLocker locker(&d->worker->mutex);
if (d->worker->pendingDatagrams.isEmpty())
return -1;
return d->pendingDatagrams.at(0).data.length();
return d->worker->pendingDatagrams.at(0).data.length();
}
qint64 QNativeSocketEngine::bytesToWrite() const
@ -1078,6 +1175,7 @@ qint64 QNativeSocketEngine::receiveBufferSize() const
void QNativeSocketEngine::setReceiveBufferSize(qint64 bufferSize)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << bufferSize;
Q_D(QNativeSocketEngine);
d->setOption(QAbstractSocketEngine::ReceiveBufferSocketOption, bufferSize);
}
@ -1090,6 +1188,7 @@ qint64 QNativeSocketEngine::sendBufferSize() const
void QNativeSocketEngine::setSendBufferSize(qint64 bufferSize)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << bufferSize;
Q_D(QNativeSocketEngine);
d->setOption(QAbstractSocketEngine::SendBufferSocketOption, bufferSize);
}
@ -1102,12 +1201,14 @@ int QNativeSocketEngine::option(QAbstractSocketEngine::SocketOption option) cons
bool QNativeSocketEngine::setOption(QAbstractSocketEngine::SocketOption option, int value)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << option << value;
Q_D(QNativeSocketEngine);
return d->setOption(option, value);
}
bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << msecs;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForRead(), false);
Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForRead(),
@ -1124,8 +1225,8 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
return true;
// If we are a client, we are ready to read if our buffer has data
QMutexLocker locker(&d->readMutex);
if (!d->pendingData.isEmpty())
QMutexLocker locker(&d->worker->mutex);
if (!d->worker->pendingData.isEmpty())
return true;
// Nothing to do, wait for more events
@ -1142,9 +1243,13 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
{
Q_UNUSED(msecs);
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << msecs;
Q_UNUSED(timedOut);
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false);
Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForWrite(),
QAbstractSocket::UnconnectedState, false);
if (d->socketState == QAbstractSocket::ConnectingState) {
HRESULT hr = QWinRTFunctions::await(d->worker->connectOp, QWinRTFunctions::ProcessMainThreadEvents);
if (SUCCEEDED(hr)) {
@ -1157,11 +1262,14 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, bool checkRead, bool checkWrite, int msecs, bool *timedOut)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << checkRead << checkWrite << msecs;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForReadOrWrite(), false);
Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForReadOrWrite(),
QAbstractSocket::UnconnectedState, false);
Q_UNUSED(readyToRead);
Q_UNUSED(readyToWrite);
Q_UNUSED(checkRead);
Q_UNUSED(checkWrite);
Q_UNUSED(msecs);
Q_UNUSED(timedOut);
return false;
}
@ -1174,6 +1282,7 @@ bool QNativeSocketEngine::isReadNotificationEnabled() const
void QNativeSocketEngine::setReadNotificationEnabled(bool enable)
{
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable;
Q_D(QNativeSocketEngine);
d->notifyOnRead = enable;
}
@ -1186,6 +1295,7 @@ bool QNativeSocketEngine::isWriteNotificationEnabled() const
void QNativeSocketEngine::setWriteNotificationEnabled(bool enable)
{
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable;
Q_D(QNativeSocketEngine);
d->notifyOnWrite = enable;
if (enable && d->socketState == QAbstractSocket::ConnectedState) {
@ -1203,12 +1313,14 @@ bool QNativeSocketEngine::isExceptionNotificationEnabled() const
void QNativeSocketEngine::setExceptionNotificationEnabled(bool enable)
{
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable;
Q_D(QNativeSocketEngine);
d->notifyOnException = enable;
}
void QNativeSocketEngine::establishRead()
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
Q_D(QNativeSocketEngine);
HRESULT hr;
@ -1222,6 +1334,7 @@ void QNativeSocketEngine::establishRead()
void QNativeSocketEngine::handleConnectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << success << error << errorString;
Q_D(QNativeSocketEngine);
disconnect(d->worker, &SocketEngineWorker::connectOpFinished,
this, &QNativeSocketEngine::handleConnectOpFinished);
@ -1232,6 +1345,7 @@ void QNativeSocketEngine::handleConnectOpFinished(bool success, QAbstractSocket:
}
d->socketState = QAbstractSocket::ConnectedState;
d->fetchConnectionParameters();
emit connectionReady();
if (d->socketType != QAbstractSocket::TcpSocket)
@ -1246,29 +1360,24 @@ void QNativeSocketEngine::handleConnectOpFinished(bool success, QAbstractSocket:
establishRead();
}
void QNativeSocketEngine::handleNewDatagrams(const QList<WinRtDatagram> &datagrams)
void QNativeSocketEngine::handleNewData()
{
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO;
Q_D(QNativeSocketEngine);
QMutexLocker locker(&d->readMutex);
d->pendingDatagrams.append(datagrams);
if (d->notifyOnRead)
emit readReady();
}
void QNativeSocketEngine::handleNewData(const QVector<QByteArray> &data)
{
Q_D(QNativeSocketEngine);
QMutexLocker locker(&d->readMutex);
d->pendingData.append(data);
for (const QByteArray &newData : data)
d->bytesAvailable += newData.length();
locker.unlock();
if (d->notifyOnRead)
readNotification();
if (d->notifyOnRead && d->emitReadReady) {
if (d->socketType == QAbstractSocket::UdpSocket && !d->worker->emitDataReceived)
return;
qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Emitting readReady";
emit readReady();
d->worker->emitDataReceived = false;
d->emitReadReady = false;
}
}
void QNativeSocketEngine::handleTcpError(QAbstractSocket::SocketError error)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << error;
Q_D(QNativeSocketEngine);
WinRTSocketEngine::ErrorString errorString;
switch (error) {
@ -1287,6 +1396,7 @@ void QNativeSocketEngine::handleTcpError(QAbstractSocket::SocketError error)
bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << socketType << socketProtocol;
Q_UNUSED(socketProtocol);
HRESULT hr;
@ -1343,10 +1453,12 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
, sslSocket(nullptr)
, connectionToken( { -1 } )
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
}
QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
if (socketDescriptor == -1 || connectionToken.value == -1)
return;
@ -1362,6 +1474,7 @@ QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString) const
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << error << errorString;
if (hasSetSocketError) {
// Only set socket errors once for one engine; expect the
// socket to recreate its engine after an error. Note: There's
@ -1523,6 +1636,7 @@ int QNativeSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt)
bool QNativeSocketEnginePrivate::setOption(QAbstractSocketEngine::SocketOption opt, int v)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << opt << v;
ComPtr<IStreamSocketControl> control;
if (socketType == QAbstractSocket::TcpSocket) {
if (FAILED(tcpSocket()->get_Control(&control))) {
@ -1583,6 +1697,7 @@ bool QNativeSocketEnginePrivate::setOption(QAbstractSocketEngine::SocketOption o
bool QNativeSocketEnginePrivate::fetchConnectionParameters()
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
localPort = 0;
localAddress.clear();
peerPort = 0;
@ -1659,6 +1774,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener *listener, IStreamSocketListenerConnectionReceivedEventArgs *args)
{
qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
Q_Q(QNativeSocketEngine);
Q_UNUSED(listener)
IStreamSocket *socket;
@ -1670,40 +1786,6 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener
return S_OK;
}
HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args)
{
Q_Q(QNativeSocketEngine);
Q_UNUSED(socket);
WinRtDatagram datagram;
QHostAddress returnAddress;
ComPtr<IHostName> remoteHost;
HRESULT hr = args->get_RemoteAddress(&remoteHost);
RETURN_OK_IF_FAILED("Could not obtain remote host");
HString remoteHostString;
remoteHost->get_CanonicalName(remoteHostString.GetAddressOf());
RETURN_OK_IF_FAILED("Could not obtain remote host's canonical name");
returnAddress.setAddress(qt_QStringFromHString(remoteHostString));
datagram.header.senderAddress = returnAddress;
HString remotePort;
hr = args->get_RemotePort(remotePort.GetAddressOf());
RETURN_OK_IF_FAILED("Could not obtain remote port");
datagram.header.senderPort = qt_QStringFromHString(remotePort).toInt();
ComPtr<IDataReader> reader;
hr = args->GetDataReader(&reader);
RETURN_OK_IF_FAILED("Could not obtain data reader");
quint32 length;
hr = reader->get_UnconsumedBufferLength(&length);
RETURN_OK_IF_FAILED("Could not obtain unconsumed buffer length");
datagram.data.resize(length);
hr = reader->ReadBytes(length, reinterpret_cast<BYTE *>(datagram.data.data()));
RETURN_OK_IF_FAILED("Could not read datagram");
emit q->newDatagramReceived(datagram);
return S_OK;
}
QT_END_NAMESPACE
#include "qnativesocketengine_winrt.moc"

View File

@ -54,6 +54,7 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <QtCore/QEventLoop>
#include <QtCore/QBuffer>
#include <QtCore/QLoggingCategory>
#include <QtCore/QMutex>
#include <QtCore/QAtomicInteger>
#include "QtNetwork/qhostaddress.h"
@ -63,6 +64,9 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcNetworkSocket)
Q_DECLARE_LOGGING_CATEGORY(lcNetworkSocketVerbose)
namespace WinRTSocketEngine {
enum ErrorString {
NonBlockingInitFailedErrorString,
@ -178,8 +182,7 @@ private slots:
void establishRead();
void handleConnectOpFinished(bool success, QAbstractSocket::SocketError error,
WinRTSocketEngine::ErrorString errorString);
void handleNewDatagrams(const QList<WinRtDatagram> &datagram);
void handleNewData(const QVector<QByteArray> &data);
void handleNewData();
void handleTcpError(QAbstractSocket::SocketError error);
private:
@ -218,28 +221,14 @@ private:
{ return reinterpret_cast<ABI::Windows::Networking::Sockets::IDatagramSocket *>(socketDescriptor); }
Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener;
// In case of TCP readMutex protects readBytes and bytesAvailable. In case of UDP it is
// pendingDatagrams. They are written inside native callbacks (handleReadyRead and
// handleNewDatagrams/putIntoPendingDatagramsList)
mutable QMutex readMutex;
// Protected by readMutex. Written in handleReadyRead (native callback)
QAtomicInteger<int> bytesAvailable;
// Protected by readMutex. Written in handleNewData/putIntoPendingData (native callback)
QVector<QByteArray> pendingData;
// Protected by readMutex. Written in handleNewDatagrams/putIntoPendingDatagramsList
QList<WinRtDatagram> pendingDatagrams;
QList<ABI::Windows::Networking::Sockets::IStreamSocket *> pendingConnections;
QList<ABI::Windows::Networking::Sockets::IStreamSocket *> currentConnections;
QEventLoop eventLoop;
QAbstractSocket *sslSocket;
EventRegistrationToken connectionToken;
HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket,
ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args);
bool emitReadReady = true;
HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener,
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
};

View File

@ -116,14 +116,14 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
Describes the protocol of the cipher.
\value SslV3 SSLv3
\value SslV3 SSLv3. When using the WinRT backend this option will also enable TLSv1.0
\value SslV2 SSLv2
\value TlsV1_0 TLSv1.0
\value TlsV1_0OrLater TLSv1.0 and later versions. This option is not available when using the WinRT backend due to platform limitations.
\value TlsV1 Obsolete, means the same as TlsV1_0
\value TlsV1_1 TLSv1.1
\value TlsV1_1 TLSv1.1. When using the WinRT backend this option will also enable TLSv1.0.
\value TlsV1_1OrLater TLSv1.1 and later versions. This option is not available when using the WinRT backend due to platform limitations.
\value TlsV1_2 TLSv1.2
\value TlsV1_2 TLSv1.2. When using the WinRT backend this option will also enable TLSv1.0 and TLSv1.1.
\value TlsV1_2OrLater TLSv1.2 and later versions. This option is not available when using the WinRT backend due to platform limitations.
\value UnknownProtocol The cipher's protocol cannot be determined.
\value AnyProtocol The socket understands SSLv2, SSLv3, and TLSv1.0. This

View File

@ -128,10 +128,10 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
QList<QSslCertificate> systemCerts;
// SecTrustSettingsCopyCertificates is not defined on iOS.
#ifdef Q_OS_OSX
QCFType<CFArrayRef> cfCerts;
// iterate through all enum members, order:
// kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin, kSecTrustSettingsDomainSystem
for (int dom = kSecTrustSettingsDomainUser; dom <= int(kSecTrustSettingsDomainSystem); dom++) {
QCFType<CFArrayRef> cfCerts;
OSStatus status = SecTrustSettingsCopyCertificates(SecTrustSettingsDomain(dom), &cfCerts);
if (status == noErr) {
const CFIndex size = CFArrayGetCount(cfCerts);

View File

@ -238,7 +238,6 @@ void QSslSocketBackendPrivate::startClientEncryption()
case QSsl::SslV3:
protectionLevel = SocketProtectionLevel_Ssl; // Only use this value if weak cipher support is required
break;
case QSsl::SecureProtocols:
case QSsl::TlsV1SslV3:
case QSsl::TlsV1_0:
protectionLevel = SocketProtectionLevel_Tls10;
@ -257,6 +256,11 @@ void QSslSocketBackendPrivate::startClientEncryption()
setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QStringLiteral("unsupported protocol"));
return;
case QSsl::SecureProtocols:
// SocketProtectionLevel_Tls12 actually means "use TLS1.0, 1.1 or 1.2"
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketprotectionlevel
protectionLevel = SocketProtectionLevel_Tls12;
break;
default:
protectionLevel = SocketProtectionLevel_Tls12; // default to highest
protocol = QSsl::TlsV1_2;

View File

@ -493,7 +493,7 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
{
const Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
const bool frameless = (flags & Qt::FramelessWindowHint) || windowIsPopupType(type);
const bool resizeable = type != Qt::Dialog; // Dialogs: remove zoom button by disabling resize
const bool resizeable = !(flags & Qt::CustomizeWindowHint); // Remove zoom button by disabling resize
// Select base window type. Note that the value of NSBorderlessWindowMask is 0.
NSUInteger styleMask = (frameless || !resizeable) ? NSBorderlessWindowMask : NSResizableWindowMask;

View File

@ -155,8 +155,12 @@
NSPoint screenPoint;
if (theEvent) {
NSPoint windowPoint = [theEvent locationInWindow];
if (qIsNaN(windowPoint.x) || qIsNaN(windowPoint.y)) {
screenPoint = [NSEvent mouseLocation];
} else {
NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
screenPoint = screenRect.origin;
}
} else {
screenPoint = [NSEvent mouseLocation];
}

View File

@ -63,6 +63,18 @@
QT_BEGIN_NAMESPACE
#define DECLARE_DEBUG_VAR(variable) \
static bool debug_ ## variable() \
{ static bool value = qgetenv("QNX_SCREEN_DEBUG").contains(QT_STRINGIFY(variable)); return value; }
DECLARE_DEBUG_VAR(fps)
DECLARE_DEBUG_VAR(posts)
DECLARE_DEBUG_VAR(blits)
DECLARE_DEBUG_VAR(updates)
DECLARE_DEBUG_VAR(cpu_time)
DECLARE_DEBUG_VAR(gpu_time)
DECLARE_DEBUG_VAR(statistics)
#undef DECLARE_DEBUG_VAR
/*!
\class QQnxWindow
\brief The QQnxWindow is the base class of the various classes used as instances of
@ -211,6 +223,35 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
// it'll cause us not to join a group (the app will presumably join at some future time).
if (windowGroup.isValid() && windowGroup.canConvert<QByteArray>())
joinWindowGroup(windowGroup.toByteArray());
int debug = 0;
if (Q_UNLIKELY(debug_fps())) {
debug |= SCREEN_DEBUG_GRAPH_FPS;
}
if (Q_UNLIKELY(debug_posts())) {
debug |= SCREEN_DEBUG_GRAPH_POSTS;
}
if (Q_UNLIKELY(debug_blits())) {
debug |= SCREEN_DEBUG_GRAPH_BLITS;
}
if (Q_UNLIKELY(debug_updates())) {
debug |= SCREEN_DEBUG_GRAPH_UPDATES;
}
if (Q_UNLIKELY(debug_cpu_time())) {
debug |= SCREEN_DEBUG_GRAPH_CPU_TIME;
}
if (Q_UNLIKELY(debug_gpu_time())) {
debug |= SCREEN_DEBUG_GRAPH_GPU_TIME;
}
if (Q_UNLIKELY(debug_statistics())) {
debug = SCREEN_DEBUG_STATISTICS;
}
if (debug > 0) {
Q_SCREEN_CHECKERROR(screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_DEBUG, &debug),
"Could not set SCREEN_PROPERTY_DEBUG");
qWindowDebug() << "window SCREEN_PROPERTY_DEBUG= " << debug;
}
}
QQnxWindow::~QQnxWindow()

View File

@ -86,6 +86,22 @@ typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXC
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
#endif
#ifndef GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB
#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
#endif
#ifndef GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
#endif
#ifndef GLX_LOSE_CONTEXT_ON_RESET_ARB
#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
#endif
#ifndef GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV
#define GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x20F7
#endif
static Window createDummyWindow(Display *dpy, XVisualInfo *visualInfo, int screenNumber, Window rootWin)
{
Colormap cmap = XCreateColormap(dpy, rootWin, visualInfo->visual, AllocNone);
@ -179,6 +195,8 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
, m_isPBufferCurrent(false)
, m_swapInterval(-1)
, m_ownsContext(nativeHandle.isNull())
, m_getGraphicsResetStatus(0)
, m_lost(false)
{
if (nativeHandle.isNull())
init(screen, share);
@ -214,6 +232,8 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
const bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile");
const bool supportsRobustness = glxExt.contains("GLX_ARB_create_context_robustness");
const bool supportsVideoMemoryPurge = glxExt.contains("GLX_NV_robustness_video_memory_purge");
// Use glXCreateContextAttribsARB if available
// Also, GL ES context creation requires GLX_EXT_create_context_es2_profile
@ -266,6 +286,9 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
int flags = 0;
if (supportsRobustness)
flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
if (m_format.testOption(QSurfaceFormat::DebugContext))
flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
@ -279,8 +302,26 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
}
contextAttributes << None;
if (supportsRobustness && supportsVideoMemoryPurge) {
QVector<int> contextAttributesWithNvidiaReset = contextAttributes;
contextAttributesWithNvidiaReset << GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB << GLX_LOSE_CONTEXT_ON_RESET_ARB;
contextAttributesWithNvidiaReset << GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV << GL_TRUE;
contextAttributesWithNvidiaReset << None;
m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributesWithNvidiaReset.data());
if (!m_context && m_shareContext) {
// re-try without a shared glx context
m_context = glXCreateContextAttribsARB(m_display, config, 0, true, contextAttributesWithNvidiaReset.data());
if (m_context)
m_shareContext = 0;
}
}
if (m_context) {
m_getGraphicsResetStatus = reinterpret_cast<GLenum (QOPENGLF_APIENTRYP)()>(getProcAddress("glGetGraphicsResetStatusARB"));
} else {
contextAttributes << None;
m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributes.data());
if (!m_context && m_shareContext) {
// re-try without a shared glx context
@ -290,6 +331,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
}
}
}
}
// Could not create a context using glXCreateContextAttribsARB, falling back to glXCreateNewContext.
if (!m_context) {
@ -494,6 +536,12 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface)
QXcbWindow *window = static_cast<QXcbWindow *>(surface);
glxDrawable = window->xcb_window();
success = glXMakeCurrent(m_display, glxDrawable, m_context);
m_lost = false;
if (m_getGraphicsResetStatus && m_getGraphicsResetStatus() != GL_NO_ERROR) {
m_lost = true;
// Drop the surface. Will recreate on the next makeCurrent.
window->invalidateSurface();
}
} else if (surfaceClass == QSurface::Offscreen) {
m_isPBufferCurrent = true;
QGLXPbuffer *pbuffer = static_cast<QGLXPbuffer *>(surface);
@ -609,7 +657,7 @@ bool QGLXContext::isSharing() const
bool QGLXContext::isValid() const
{
return m_context != 0;
return m_context != 0 && !m_lost;
}
bool QGLXContext::m_queriedDummyContext = false;

View File

@ -89,6 +89,8 @@ private:
bool m_isPBufferCurrent;
int m_swapInterval;
bool m_ownsContext;
GLenum (APIENTRY * m_getGraphicsResetStatus)();
bool m_lost;
static bool m_queriedDummyContext;
static bool m_supportsThreading;
};

View File

@ -462,8 +462,10 @@ void QPSQLResult::cleanup()
d->result = nullptr;
while (!d->nextResultSets.isEmpty())
PQclear(d->nextResultSets.takeFirst());
if (d->stmtId != InvalidStatementId)
if (d->stmtId != InvalidStatementId) {
if (d->drv_d_func())
d->drv_d_func()->finishQuery(d->stmtId);
}
d->stmtId = InvalidStatementId;
setAt(QSql::BeforeFirstRow);
d->currentSize = -1;

View File

@ -56,6 +56,7 @@
#include <qregularexpression.h>
#endif
#include <QTimeZone>
#include <QScopedValueRollback>
#if defined Q_OS_WIN
# include <qt_windows.h>
@ -129,6 +130,7 @@ protected:
bool gotoNext(QSqlCachedResult::ValueCache& row, int idx) override;
bool reset(const QString &query) override;
bool prepare(const QString &query) override;
bool execBatch(bool arrayBind) override;
bool exec() override;
int size() override;
int numRowsAffected() override;
@ -443,6 +445,29 @@ static QString timespecToString(const QDateTime &dateTime)
}
}
bool QSQLiteResult::execBatch(bool arrayBind)
{
Q_UNUSED(arrayBind);
Q_D(QSqlResult);
QScopedValueRollback<QVector<QVariant>> valuesScope(d->values);
QVector<QVariant> values = d->values;
if (values.count() == 0)
return false;
for (int i = 0; i < values.at(0).toList().count(); ++i) {
d->values.clear();
QScopedValueRollback<QHash<QString, QVector<int>>> indexesScope(d->indexes);
QHash<QString, QVector<int>>::const_iterator it = d->indexes.constBegin();
while (it != d->indexes.constEnd()) {
bindValue(it.key(), values.at(it.value().first()).toList().at(i), QSql::In);
++it;
}
if (!exec())
return false;
}
return true;
}
bool QSQLiteResult::exec()
{
Q_D(QSQLiteResult);
@ -471,7 +496,7 @@ bool QSQLiteResult::exec()
// can end up in a case where for virtual tables it returns 0 even though it
// has parameters
if (paramCount > 1 && paramCount < values.count()) {
const auto countIndexes = [](int counter, const QList<int>& indexList) {
const auto countIndexes = [](int counter, const QVector<int> &indexList) {
return counter + indexList.length();
};
@ -485,13 +510,14 @@ bool QSQLiteResult::exec()
// placeholders. So we need to ensure the QVector has only one instance of
// each value as SQLite will do the rest for us.
QVector<QVariant> prunedValues;
QList<int> handledIndexes;
QVector<int> handledIndexes;
for (int i = 0, currentIndex = 0; i < values.size(); ++i) {
if (handledIndexes.contains(i))
continue;
const auto placeHolder = QString::fromUtf8(sqlite3_bind_parameter_name(d->stmt, currentIndex + 1));
handledIndexes << d->indexes[placeHolder];
prunedValues << values.at(d->indexes[placeHolder].first());
const auto &indexes = d->indexes.value(placeHolder);
handledIndexes << indexes;
prunedValues << values.at(indexes.first());
++currentIndex;
}
values = prunedValues;

File diff suppressed because it is too large Load Diff

View File

@ -190,6 +190,7 @@ public:
Button_PullDown, // QPushButton with menu
Button_PushButton,
Button_RadioButton,
Button_SquareButton, // Oversized QPushButton
Button_WindowClose,
Button_WindowMiniaturize,
Button_WindowZoom,
@ -206,7 +207,23 @@ public:
TextField
};
typedef QPair<CocoaControlType, QStyleHelper::WidgetSizePolicy> CocoaControl;
struct CocoaControl {
CocoaControl();
CocoaControl(CocoaControlType t, QStyleHelper::WidgetSizePolicy s);
CocoaControlType type;
QStyleHelper::WidgetSizePolicy size;
bool operator==(const CocoaControl &other) const;
QSizeF defaultFrameSize() const;
QRectF adjustedControlFrame(const QRectF &rect) const;
QMarginsF titleMargins() const;
bool getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const;
};
typedef void (^DrawRectBlock)(CGContextRef, const CGRect &);
@ -273,11 +290,13 @@ public:
void setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const;
void drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const;
void drawNSViewInRect(CocoaControl widget, NSView *view, const QRectF &rect, QPainter *p, bool isQWidget = true, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const;
void resolveCurrentNSView(QWindow *window) const;
void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const;
void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const;
void drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const;
void drawToolbarButtonArrow(const QStyleOption *opt, QPainter *p) const;
QPainterPath windowPanelPath(const QRectF &r) const;

View File

@ -122,6 +122,7 @@ static inline HDC hdcForWidgetBackingStore(const QWidget *widget)
{
if (QBackingStore *backingStore = backingStoreForWidget(widget)) {
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
if (nativeInterface)
return static_cast<HDC>(nativeInterface->nativeResourceForBackingStore(QByteArrayLiteral("getDC"), backingStore));
}
return 0;

View File

@ -690,7 +690,7 @@ void QSqlResult::bindValue(int index, const QVariant& val, QSql::ParamType param
{
Q_D(QSqlResult);
d->binds = PositionalBinding;
QList<int>& indexes = d->indexes[d->fieldSerial(index)];
QVector<int> &indexes = d->indexes[d->fieldSerial(index)];
if (!indexes.contains(index))
indexes.append(index);
if (d->values.count() <= index)
@ -717,7 +717,7 @@ void QSqlResult::bindValue(const QString& placeholder, const QVariant& val,
d->binds = NamedBinding;
// if the index has already been set when doing emulated named
// bindings - don't reset it
const QList<int> indexes = d->indexes.value(placeholder);
const QVector<int> indexes = d->indexes.value(placeholder);
for (int idx : indexes) {
if (d->values.count() <= idx)
d->values.resize(idx + 1);
@ -764,7 +764,7 @@ QVariant QSqlResult::boundValue(int index) const
QVariant QSqlResult::boundValue(const QString& placeholder) const
{
Q_D(const QSqlResult);
QList<int> indexes = d->indexes.value(placeholder);
const QVector<int> indexes = d->indexes.value(placeholder);
return d->values.value(indexes.value(0,-1));
}

View File

@ -135,7 +135,7 @@ public:
QString executedQuery;
QHash<int, QSql::ParamType> types;
QVector<QVariant> values;
typedef QHash<QString, QList<int> > IndexMap;
typedef QHash<QString, QVector<int> > IndexMap;
IndexMap indexes;
typedef QVector<QHolder> QHolderVector;

View File

@ -0,0 +1,22 @@
{
"module": "testlib",
"depends": [
"core"
],
"features": {
"itemmodeltester": {
"label": "Tester for item models",
"purpose": "Provides a utility to test item models.",
"condition": "features.itemmodel",
"output": [ "publicFeature" ]
}
},
"summary": [
{
"section": "Qt Testlib",
"entries": [ "itemmodeltester" ]
}
]
}

View File

@ -30,7 +30,7 @@
#define QABSTRACTITEMMODELTESTER_H
#include <QtCore/QObject>
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#ifdef QT_GUI_LIB
#include <QtGui/QFont>
@ -41,6 +41,8 @@
#include <QtGui/QIcon>
#endif
QT_REQUIRE_CONFIG(itemmodeltester);
QT_BEGIN_NAMESPACE
class QAbstractItemModel;

View File

@ -40,7 +40,7 @@
#ifndef QBENCHMARK_H
#define QBENCHMARK_H
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#include <QtTest/qbenchmarkmetric.h>
QT_BEGIN_NAMESPACE

View File

@ -69,7 +69,7 @@
#include <QtTest/private/qbenchmarkmeasurement_p.h>
#include <QtCore/QMap>
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#ifdef QTESTLIB_USE_VALGRIND
#include <QtTest/private/qbenchmarkvalgrind_p.h>
#endif

View File

@ -41,7 +41,7 @@
#ifndef QBENCHMARKMETRIC_H
#define QBENCHMARKMETRIC_H
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE

View File

@ -51,7 +51,7 @@
// We mean it.
//
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#include <QtTest/qbenchmarkmetric.h>
QT_BEGIN_NAMESPACE

View File

@ -41,7 +41,7 @@
#ifndef QTEST_H
#define QTEST_H
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#include <QtTest/qtestcase.h>
#include <QtTest/qtestdata.h>
#include <QtTest/qbenchmark.h>

View File

@ -54,7 +54,7 @@
#include <QtCore/qdebug.h>
#include <QtGui/qaccessible.h>
#include <QtGui/qguiapplication.h>
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#include <QtTest/qtestsystem.h>
#if QT_CONFIG(accessibility)

View File

@ -51,7 +51,7 @@
// We mean it.
//
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE

View File

@ -75,6 +75,7 @@
#include <QtTest/private/qtestutil_macos_p.h>
#endif
#include <cmath>
#include <numeric>
#include <algorithm>
@ -208,8 +209,13 @@ static void stackTrace()
if (debuggerPresent())
return;
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime());
const int msecsTotalTime = qRound(QTestLog::msecsTotalTime());
fprintf(stderr, "\n=== Received signal at function time: %dms, total time: %dms, dumping stack ===\n",
msecsFunctionTime, msecsTotalTime);
#endif
#ifdef Q_OS_LINUX
fprintf(stderr, "\n========= Received signal, dumping stack ==============\n");
char cmd[512];
qsnprintf(cmd, 512, "gdb --pid %d 2>/dev/null <<EOF\n"
"set prompt\n"
@ -221,9 +227,8 @@ static void stackTrace()
(int)getpid());
if (system(cmd) == -1)
fprintf(stderr, "calling gdb failed\n");
fprintf(stderr, "========= End of stack trace ==============\n");
fprintf(stderr, "=== End of stack trace ===\n");
#elif defined(Q_OS_OSX)
fprintf(stderr, "\n========= Received signal, dumping stack ==============\n");
char cmd[512];
qsnprintf(cmd, 512, "lldb -p %d 2>/dev/null <<EOF\n"
"bt all\n"
@ -232,7 +237,7 @@ static void stackTrace()
(int)getpid());
if (system(cmd) == -1)
fprintf(stderr, "calling lldb failed\n");
fprintf(stderr, "========= End of stack trace ==============\n");
fprintf(stderr, "=== End of stack trace ===\n");
#endif
}
@ -2445,7 +2450,16 @@ bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const
bool QTest::qCompare(double const &t1, double const &t2, const char *actual, const char *expected,
const char *file, int line)
{
return compare_helper(qFuzzyCompare(t1, t2), "Compared doubles are not the same (fuzzy compare)",
bool equal = false;
int cl1 = std::fpclassify(t1);
int cl2 = std::fpclassify(t2);
if (cl1 == FP_INFINITE)
equal = ((t1 < 0) == (t2 < 0)) && cl2 == FP_INFINITE;
else if (cl1 == FP_NAN)
equal = (cl2 == FP_NAN);
else
equal = qFuzzyCompare(t1, t2);
return compare_helper(equal, "Compared doubles are not the same (fuzzy compare)",
toString(t1), toString(t2), actual, expected, file, line);
}

View File

@ -40,7 +40,7 @@
#ifndef QTESTCASE_H
#define QTESTCASE_H
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qnamespace.h>

View File

@ -40,7 +40,7 @@
#ifndef QTESTDATA_H
#define QTESTDATA_H
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qstring.h>

View File

@ -45,7 +45,7 @@
#pragma qt_no_master_include
#endif
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#ifdef QT_GUI_LIB
#include <QtTest/qtestkeyboard.h>
#include <QtTest/qtestmouse.h>
@ -103,7 +103,10 @@ class QTestKeyClicksEvent: public QTestEvent
{
public:
inline QTestKeyClicksEvent(const QString &keys, Qt::KeyboardModifiers modifiers, int delay)
: _keys(keys), _modifiers(modifiers), _delay(delay) {}
: _keys(keys), _modifiers(modifiers), _delay(delay)
{
Q_UNUSED(_delay) // Silence -Werror,-Wunused-private-field
}
inline QTestEvent *clone() const override { return new QTestKeyClicksEvent(*this); }
#ifdef QT_WIDGETS_LIB
@ -124,7 +127,12 @@ class QTestMouseEvent: public QTestEvent
public:
inline QTestMouseEvent(QTest::MouseAction action, Qt::MouseButton button,
Qt::KeyboardModifiers modifiers, QPoint position, int delay)
: _action(action), _button(button), _modifiers(modifiers), _pos(position), _delay(delay) {}
: _action(action), _button(button), _modifiers(modifiers), _pos(position), _delay(delay)
{
Q_UNUSED(_action)
Q_UNUSED(_button)
Q_UNUSED(_delay)
}
inline QTestEvent *clone() const override { return new QTestMouseEvent(*this); }
#ifdef QT_WIDGETS_LIB
@ -147,7 +155,10 @@ private:
class QTestDelayEvent: public QTestEvent
{
public:
inline QTestDelayEvent(int msecs): _delay(msecs) {}
inline QTestDelayEvent(int msecs): _delay(msecs)
{
Q_UNUSED(_delay)
}
inline QTestEvent *clone() const override { return new QTestDelayEvent(*this); }
#ifdef QT_WIDGETS_LIB

View File

@ -40,7 +40,7 @@
#ifndef QTESTEVENTLOOP_H
#define QTESTEVENTLOOP_H
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qeventloop.h>

View File

@ -46,7 +46,7 @@
#endif
#include <QtTest/qtestassert.h>
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#include <QtTest/qtestsystem.h>
#include <QtTest/qtestspontaneevent.h>

View File

@ -51,7 +51,7 @@
// We mean it.
//
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE

View File

@ -39,7 +39,7 @@
#include <QtCore/QtGlobal>
#include <QtCore/qnamespace.h>
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE

View File

@ -45,7 +45,7 @@
#pragma qt_no_master_include
#endif
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#include <QtTest/qtestassert.h>
#include <QtTest/qtestsystem.h>
#include <QtTest/qtestspontaneevent.h>

View File

@ -51,7 +51,7 @@
// We mean it.
//
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE

View File

@ -51,7 +51,7 @@
// We mean it.
//
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE

View File

@ -45,7 +45,7 @@
#pragma qt_no_master_include
#endif
#include <QtTest/qtest_global.h>
#include <QtTest/qttestglobal.h>
#include <QtTest/qtestassert.h>
#include <QtTest/qtestsystem.h>
#include <QtTest/qtestspontaneevent.h>

View File

@ -37,14 +37,14 @@
**
****************************************************************************/
#ifndef QTEST_GLOBAL_H
#define QTEST_GLOBAL_H
#ifndef QTTESTGLOBAL_H
#define QTTESTGLOBAL_H
#include <QtCore/qglobal.h>
#include <QtTest/qttestlib-config.h>
QT_BEGIN_NAMESPACE
#if defined(QT_STATIC)
# define Q_TESTLIB_EXPORT
#else

View File

@ -12,7 +12,6 @@ unix:!embedded:QMAKE_PKGCONFIG_DESCRIPTION = Qt \
QMAKE_DOCS = $$PWD/doc/qttestlib.qdocconf
HEADERS = \
qabstractitemmodeltester.h \
qbenchmark.h \
qbenchmark_p.h \
qbenchmarkmeasurement_p.h \
@ -29,7 +28,6 @@ HEADERS = \
qtestdata.h \
qtestevent.h \
qtesteventloop.h \
qtest_global.h \
qtest_gui.h \
qtest_network.h \
qtest_widgets.h \
@ -41,10 +39,10 @@ HEADERS = \
qtesttouch.h \
qtestblacklist_p.h \
qtesthelpers_p.h \
qttestglobal.h \
qtaptestlogger_p.h
SOURCES = \
qabstractitemmodeltester.cpp \
qtestcase.cpp \
qtestlog.cpp \
qtesttable.cpp \
@ -71,6 +69,14 @@ SOURCES = \
qtestblacklist.cpp \
qtaptestlogger.cpp
qtConfig(itemmodeltester) {
HEADERS += \
qabstractitemmodeltester.h
SOURCES += \
qabstractitemmodeltester.cpp
}
DEFINES *= QT_NO_CAST_TO_ASCII \
QT_NO_CAST_FROM_ASCII \
QT_NO_FOREACH \

View File

@ -1525,7 +1525,7 @@ QTableWidgetItem &QTableWidgetItem::operator=(const QTableWidgetItem &other)
\snippet qtablewidget-resizing/mainwindow.cpp 0
\snippet qtablewidget-resizing/mainwindow.cpp 1
Items are created ouside the table (with no parent widget) and inserted
Items are created outside the table (with no parent widget) and inserted
into the table with setItem():
\snippet qtablewidget-resizing/mainwindow.cpp 2

View File

@ -242,7 +242,7 @@ public:
static HWND getHWNDForWidget(const QWidget *widget)
{
if (QWindow *window = windowForWidget(widget))
if (window->handle())
if (window->handle() && QGuiApplication::platformNativeInterface())
return static_cast<HWND> (QGuiApplication::platformNativeInterface()->
nativeResourceForWindow(QByteArrayLiteral("handle"), window));
return 0;

View File

@ -73,6 +73,9 @@
},
"QtDBus" => {
"qdbusmacros.h" => "QtDbus/qtdbusglobal.h"
},
"QtTest" => {
"qtest_global.h" => "QtTest/qttestglobal.h"
}
);

View File

@ -47,17 +47,7 @@ find_package(Qt5Core REQUIRED)
include("${_Qt5CTestMacros}")
if(NOT ${CMAKE_VERSION} VERSION_LESS 2.8.9)
# Requires INCLUDE_DIRECTORIES target property in CMake 2.8.8
# and POSITION_INDEPENDENT_CODE target property in 2.8.9
if (NOT NO_GUI)
expect_pass(test_use_modules_function)
endif()
expect_pass(test_umbrella_config)
else()
message("CMake version older than 2.8.9 (Found ${CMAKE_VERSION}). Not running test \"test_use_modules_function\" or \"test_umbrella_config\"")
endif()
expect_pass(test_umbrella_config)
expect_pass(test_wrap_cpp_and_resources)
if (NOT NO_WIDGETS)
expect_pass(test_dependent_modules)
@ -90,12 +80,8 @@ if (NOT NO_DBUS)
expect_pass(test_dbus_module)
endif()
expect_pass(test_multiple_find_package)
if (NOT WIN32 OR (WIN32 AND NOT CMAKE_VERSION VERSION_LESS 2.8.11))
# Broken on windows on earlier CMake versions.
# http://public.kitware.com/Bug/view.php?id=13392
expect_pass(test_add_resources_delayed_file)
expect_pass(test_add_binary_resources_delayed_file BINARY test_add_binary_resources_delayed_file)
endif()
expect_pass(test_add_resources_delayed_file)
expect_pass(test_add_binary_resources_delayed_file BINARY test_add_binary_resources_delayed_file)
expect_pass(test_private_includes)
expect_pass(test_private_targets)
expect_pass(test_testlib_definitions)
@ -153,7 +139,7 @@ if (QT_WITH_ANGLE OR (NOT WIN32 AND NOT APPLE AND NOT NO_EGL))
endif()
expect_pass(test_opengl_lib)
if (NOT CMAKE_VERSION VERSION_LESS 2.8.11 AND NOT NO_WIDGETS)
if (NOT NO_WIDGETS)
expect_pass(test_interface)
endif()
@ -166,4 +152,3 @@ if (NOT CMAKE_VERSION VERSION_LESS 3.8)
# /usr/bin/ld: CMakeFiles/mywidget.dir/moc_mywidget.cpp.o: previous definition here
# Reason: SKIP_* properties were added in CMake 3.8 only
expect_pass(test_QTBUG-63422)
endif()

View File

@ -1,18 +0,0 @@
cmake_minimum_required(VERSION 2.8)
project(test_use_modules_function)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(two two.cpp)
add_executable(three three.cpp)
find_package(Qt5Core)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
qt5_use_modules(two Test)
qt5_use_modules(three Gui Test)

View File

@ -1,45 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest>
#include <QWindow>
class Three : public QObject
{
Q_OBJECT
public:
Three(QObject *parent = 0)
{
QWindow *w = new QWindow;
w->show();
}
};
QTEST_MAIN(Three)
#include "three.moc"

View File

@ -1,43 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest>
class Two : public QObject
{
Q_OBJECT
public:
Two(QObject *parent = 0)
{
}
};
QTEST_MAIN(Two)
#include "two.moc"

View File

@ -4,3 +4,6 @@ redhatenterpriselinuxworkstation-6.6
[fileWriterProcess]
msvc-2015 ci
msvc-2017 ci
[softExitInSlots]
# QTBUG-66903
windows

View File

@ -146,6 +146,7 @@ public:
HANDLE eventHandle() const { return notifier.handle(); }
int numberOfTimesActivated() const { return activatedCount; }
void setEnabled(bool b) { notifier.setEnabled(b); }
bool isEnabled() const { return notifier.isEnabled(); }
signals:
void activated();
@ -239,8 +240,9 @@ void tst_QWinEventNotifier::disableNotifiersInActivatedSlot()
for (int i = 0; i < count; ++i)
events[i].reset(new EventWithNotifier);
auto isActivatedOrNull = [&events](int i) {
return !events.at(i) || events.at(i)->numberOfTimesActivated() > 0;
auto isActivatedOrDisabled = [&events](int i) {
return !events.at(i) || !events.at(i)->isEnabled()
|| events.at(i)->numberOfTimesActivated() > 0;
};
for (auto &e : events) {
@ -251,8 +253,10 @@ void tst_QWinEventNotifier::disableNotifiersInActivatedSlot()
else
events.at(i)->setEnabled(false);
}
if (std::all_of(notifiersToSignal.begin(), notifiersToSignal.end(), isActivatedOrNull))
if (std::all_of(notifiersToSignal.begin(), notifiersToSignal.end(),
isActivatedOrDisabled)) {
QTimer::singleShot(0, &QTestEventLoop::instance(), SLOT(exitLoop()));
}
});
}
for (int i : notifiersToSignal)

View File

@ -54,6 +54,7 @@ private slots:
void testCbrtDouble();
void testCbrtFloat();
void cpp11();
void quadraticEquation();
};
void tst_QEasingCurve::type()
@ -804,5 +805,74 @@ void tst_QEasingCurve::cpp11()
#endif
}
void tst_QEasingCurve::quadraticEquation() {
// We find the value for a given time by solving a cubic equation.
// ax^3 + bx^2 + cx + d = 0
// However, the solver also needs to take care of cases where a = 0,
// b = 0 or c = 0, and the equation becomes quadratic, linear or invalid.
// A naive cubic solver might divide by zero and return nan, even
// when the solution is a real number.
// This test should triggers those cases.
{
// If the control points are spaced 1/3 apart of the distance of the
// start- and endpoint, the equation becomes linear.
QEasingCurve test(QEasingCurve::BezierSpline);
const qreal p1 = 1.0 / 3.0;
const qreal p2 = 1.0 - 1.0 / 3.0;
const qreal p3 = 1.0;
test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0));
QVERIFY(qAbs(test.valueForProgress(0.25) - 0.15625) < 1e-6);
QVERIFY(qAbs(test.valueForProgress(0.5) - 0.5) < 1e-6);
QVERIFY(qAbs(test.valueForProgress(0.75) - 0.84375) < 1e-6);
}
{
// If both the start point and the first control point
// are placed a 0.0, and the second control point is
// placed at 1/3, we get a case where a = 0 and b != 0
// i.e. a quadratic equation.
QEasingCurve test(QEasingCurve::BezierSpline);
const qreal p1 = 0.0;
const qreal p2 = 1.0 / 3.0;
const qreal p3 = 1.0;
test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0));
QVERIFY(qAbs(test.valueForProgress(0.25) - 0.5) < 1e-6);
QVERIFY(qAbs(test.valueForProgress(0.5) - 0.792893) < 1e-6);
QVERIFY(qAbs(test.valueForProgress(0.75) - 0.950962) < 1e-6);
}
{
// If both the start point and the first control point
// are placed a 0.0, and the second control point is
// placed close to 1/3, we get a case where a = ~0 and b != 0.
// It's not truly a quadratic equation, but should be treated
// as one, because it causes some cubic solvers to fail.
QEasingCurve test(QEasingCurve::BezierSpline);
const qreal p1 = 0.0;
const qreal p2 = 1.0 / 3.0 + 1e-6;
const qreal p3 = 1.0;
test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0));
QVERIFY(qAbs(test.valueForProgress(0.25) - 0.499999) < 1e-6);
QVERIFY(qAbs(test.valueForProgress(0.5) - 0.792892) < 1e-6);
QVERIFY(qAbs(test.valueForProgress(0.75) - 0.950961) < 1e-6);
}
{
// A bad case, where the segment is of zero length.
// However, it might still happen in user code,
// and we should return a sensible answer.
QEasingCurve test(QEasingCurve::BezierSpline);
const qreal p0 = 0.0;
const qreal p1 = p0;
const qreal p2 = p0;
const qreal p3 = p0;
test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0));
test.addCubicBezierSegment(QPointF(p3, 1.0), QPointF(1.0, 1.0), QPointF(1.0, 1.0));
QCOMPARE(test.valueForProgress(0.0), 0.0);
}
}
QTEST_MAIN(tst_QEasingCurve)
#include "tst_qeasingcurve.moc"

View File

@ -957,19 +957,21 @@ void tst_QVarLengthArray::insertMove()
QCOMPARE(MyBase::copyCount, 0);
{
QVarLengthArray<MyMovable, 4> vec;
QVarLengthArray<MyMovable, 6> vec;
MyMovable m1;
MyMovable m2;
MyMovable m3;
MyMovable m4;
MyMovable m5;
MyMovable m6;
QCOMPARE(MyBase::copyCount, 0);
QCOMPARE(MyBase::liveCount, 4);
QCOMPARE(MyBase::liveCount, 6);
vec.append(std::move(m3));
QVERIFY(m3.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m3));
QCOMPARE(MyBase::errorCount, 0);
QCOMPARE(MyBase::liveCount, 4);
QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::movedCount, 1);
vec.push_back(std::move(m4));
@ -977,7 +979,7 @@ void tst_QVarLengthArray::insertMove()
QVERIFY(vec.at(0).wasConstructedAt(&m3));
QVERIFY(vec.at(1).wasConstructedAt(&m4));
QCOMPARE(MyBase::errorCount, 0);
QCOMPARE(MyBase::liveCount, 4);
QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::movedCount, 2);
vec.prepend(std::move(m1));
@ -986,7 +988,7 @@ void tst_QVarLengthArray::insertMove()
QVERIFY(vec.at(1).wasConstructedAt(&m3));
QVERIFY(vec.at(2).wasConstructedAt(&m4));
QCOMPARE(MyBase::errorCount, 0);
QCOMPARE(MyBase::liveCount, 4);
QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::movedCount, 3);
vec.insert(1, std::move(m2));
@ -995,11 +997,34 @@ void tst_QVarLengthArray::insertMove()
QVERIFY(vec.at(1).wasConstructedAt(&m2));
QVERIFY(vec.at(2).wasConstructedAt(&m3));
QVERIFY(vec.at(3).wasConstructedAt(&m4));
QCOMPARE(MyBase::errorCount, 0);
QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::movedCount, 4);
vec += std::move(m5);
QVERIFY(m5.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m1));
QVERIFY(vec.at(1).wasConstructedAt(&m2));
QVERIFY(vec.at(2).wasConstructedAt(&m3));
QVERIFY(vec.at(3).wasConstructedAt(&m4));
QVERIFY(vec.at(4).wasConstructedAt(&m5));
QCOMPARE(MyBase::errorCount, 0);
QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::movedCount, 5);
vec << std::move(m6);
QVERIFY(m6.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m1));
QVERIFY(vec.at(1).wasConstructedAt(&m2));
QVERIFY(vec.at(2).wasConstructedAt(&m3));
QVERIFY(vec.at(3).wasConstructedAt(&m4));
QVERIFY(vec.at(4).wasConstructedAt(&m5));
QVERIFY(vec.at(5).wasConstructedAt(&m6));
QCOMPARE(MyBase::copyCount, 0);
QCOMPARE(MyBase::liveCount, 4);
QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::errorCount, 0);
QCOMPARE(MyBase::movedCount, 4);
QCOMPARE(MyBase::movedCount, 6);
}
QCOMPARE(MyBase::liveCount, 0);
QCOMPARE(MyBase::errorCount, 0);
@ -1013,10 +1038,14 @@ void tst_QVarLengthArray::nonCopyable()
std::unique_ptr<int> val2(new int(2));
std::unique_ptr<int> val3(new int(3));
std::unique_ptr<int> val4(new int(4));
std::unique_ptr<int> val5(new int(5));
std::unique_ptr<int> val6(new int(6));
int *const ptr1 = val1.get();
int *const ptr2 = val2.get();
int *const ptr3 = val3.get();
int *const ptr4 = val4.get();
int *const ptr5 = val5.get();
int *const ptr6 = val6.get();
vec.append(std::move(val3));
QVERIFY(!val3);
@ -1035,6 +1064,22 @@ void tst_QVarLengthArray::nonCopyable()
QVERIFY(ptr1 == vec.at(0).get());
QVERIFY(ptr2 == vec.at(1).get());
QVERIFY(ptr3 == vec.at(2).get());
QVERIFY(ptr4 == vec.at(3).get());
vec += std::move(val5);
QVERIFY(!val5);
QVERIFY(ptr1 == vec.at(0).get());
QVERIFY(ptr2 == vec.at(1).get());
QVERIFY(ptr3 == vec.at(2).get());
QVERIFY(ptr4 == vec.at(3).get());
QVERIFY(ptr5 == vec.at(4).get());
vec << std::move(val6);
QVERIFY(!val6);
QVERIFY(ptr1 == vec.at(0).get());
QVERIFY(ptr2 == vec.at(1).get());
QVERIFY(ptr3 == vec.at(2).get());
QVERIFY(ptr4 == vec.at(3).get());
QVERIFY(ptr5 == vec.at(4).get());
QVERIFY(ptr6 == vec.at(5).get());
}
QTEST_APPLESS_MAIN(tst_QVarLengthArray)

View File

@ -2895,12 +2895,14 @@ void tst_QVector::insertMove() const
const int instancesCount = Movable::counter.loadAcquire();
{
QVector<Movable> vec;
vec.reserve(5);
vec.reserve(7);
Movable m0;
Movable m1;
Movable m2;
Movable m3;
Movable m4;
Movable m5;
Movable m6;
vec.append(std::move(m3));
QVERIFY(m3.wasConstructedAt(nullptr));
@ -2920,6 +2922,21 @@ void tst_QVector::insertMove() const
QVERIFY(vec.at(1).wasConstructedAt(&m2));
QVERIFY(vec.at(2).wasConstructedAt(&m3));
QVERIFY(vec.at(3).wasConstructedAt(&m4));
vec += std::move(m5);
QVERIFY(m5.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m1));
QVERIFY(vec.at(1).wasConstructedAt(&m2));
QVERIFY(vec.at(2).wasConstructedAt(&m3));
QVERIFY(vec.at(3).wasConstructedAt(&m4));
QVERIFY(vec.at(4).wasConstructedAt(&m5));
vec << std::move(m6);
QVERIFY(m6.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m1));
QVERIFY(vec.at(1).wasConstructedAt(&m2));
QVERIFY(vec.at(2).wasConstructedAt(&m3));
QVERIFY(vec.at(3).wasConstructedAt(&m4));
QVERIFY(vec.at(4).wasConstructedAt(&m5));
QVERIFY(vec.at(5).wasConstructedAt(&m6));
vec.push_front(std::move(m0));
QVERIFY(m0.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m0));
@ -2927,8 +2944,10 @@ void tst_QVector::insertMove() const
QVERIFY(vec.at(2).wasConstructedAt(&m2));
QVERIFY(vec.at(3).wasConstructedAt(&m3));
QVERIFY(vec.at(4).wasConstructedAt(&m4));
QVERIFY(vec.at(5).wasConstructedAt(&m5));
QVERIFY(vec.at(6).wasConstructedAt(&m6));
QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 10);
QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 14);
}
QCOMPARE(Movable::counter.loadAcquire(), instancesCount);
}

View File

@ -153,6 +153,7 @@ private slots:
void setEqualClipRegionAndPath();
void clipRectSaveRestore();
void clipStateSaveRestore();
void clippedFillPath_data();
void clippedFillPath();
@ -3425,6 +3426,35 @@ void tst_QPainter::clipRectSaveRestore()
QCOMPARE(img.pixel(0, 0), QColor(Qt::black).rgba());
}
void tst_QPainter::clipStateSaveRestore()
{
QImage img(16, 16, QImage::Format_RGB32);
img.fill(Qt::blue);
{
QPainter p(&img);
p.setClipRect(QRect(5, 5, 10, 10));
p.save();
p.setClipping(false);
p.restore();
p.fillRect(0, 0, 16, 16, Qt::red);
p.end();
QCOMPARE(img.pixel(0, 0), QColor(Qt::blue).rgb());
}
img.fill(Qt::blue);
{
QPainter p(&img);
p.setClipRect(QRect(5, 5, 10, 10));
p.setClipping(false);
p.save();
p.setClipping(true);
p.restore();
p.fillRect(0, 0, 16, 16, Qt::red);
p.end();
QCOMPARE(img.pixel(0, 0), QColor(Qt::red).rgb());
}
}
void tst_QPainter::clippedImage()
{
QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);

View File

@ -359,7 +359,6 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db )
<< qTableName("more_results", __FILE__, db)
<< qTableName("blobstest", __FILE__, db)
<< qTableName("oraRowId", __FILE__, db)
<< qTableName("qtest_batch", __FILE__, db)
<< qTableName("bug43874", __FILE__, db)
<< qTableName("bug6421", __FILE__, db).toUpper()
<< qTableName("bug5765", __FILE__, db)
@ -2439,64 +2438,90 @@ void tst_QSqlQuery::batchExec()
QSqlDatabase db = QSqlDatabase::database( dbName );
CHECK_DATABASE( db );
if ( !db.driver()->hasFeature( QSqlDriver::BatchOperations ) )
QSKIP( "Database can't do BatchOperations");
QSqlQuery q( db );
const QString tableName = qTableName("qtest_batch", __FILE__, db);
tst_Databases::safeDropTable(db, tableName);
QVERIFY_SQL(q, exec(QStringLiteral("create table ") + tableName +
QStringLiteral(" (id int, name varchar(20), dt date, num numeric(8, 4), "
"dtstamp TIMESTAMP(3), extraId int, extraName varchar(20))")));
QVERIFY_SQL(q, exec("create table " + tableName + " (id int, name varchar(20), dt date, num numeric(8, 4), dtstamp TIMESTAMP(3))"));
QVERIFY_SQL(q, prepare("insert into " + tableName + " (id, name, dt, num, dtstamp) values (?, ?, ?, ?, ?)"));
QVariantList intCol;
intCol << 1 << 2 << QVariant( QVariant::Int );
QVariantList charCol;
charCol << QLatin1String( "harald" ) << QLatin1String( "boris" ) << QVariant( QVariant::String );
QVariantList dateCol;
QDateTime dt = QDateTime( QDate::currentDate(), QTime( 1, 2, 3 ) );
dateCol << dt << dt.addDays( -1 ) << QVariant( QVariant::DateTime );
QVariantList numCol;
numCol << 2.3 << 3.4 << QVariant( QVariant::Double );
QVariantList timeStampCol;
const QDateTime dtStamp = QDateTime(QDate::currentDate(), QTime(1, 2, 3, 4));
timeStampCol << dtStamp << dtStamp.addDays(-1) << QVariant(QVariant::DateTime);
const QVariantList intCol = { 1, 2, QVariant(QVariant::Int) };
const QVariantList charCol = { QStringLiteral("harald"), QStringLiteral("boris"),
QVariant(QVariant::String) };
const QDateTime currentDateTime = QDateTime(QDateTime::currentDateTime());
const QVariantList dateCol = { currentDateTime.date(), currentDateTime.date().addDays(-1),
QVariant(QVariant::Date) };
const QVariantList numCol = { 2.3, 3.4, QVariant(QVariant::Double) };
const QVariantList timeStampCol = { currentDateTime, currentDateTime.addDays(-1),
QVariant(QVariant::DateTime) };
// Test with positional placeholders
QVERIFY_SQL(q, prepare(QStringLiteral("insert into ") + tableName +
QStringLiteral(" (id, name, dt, num, dtstamp, extraId, extraName) values "
"(?, ?, ?, ?, ?, ?, ?)")));
q.addBindValue(intCol);
q.addBindValue( charCol );
q.addBindValue( dateCol );
q.addBindValue( numCol );
q.addBindValue(timeStampCol);
q.addBindValue(intCol);
q.addBindValue(charCol);
QVERIFY_SQL( q, execBatch() );
QVERIFY_SQL(q, exec("select id, name, dt, num, dtstamp from " + tableName + " order by id"));
QVERIFY_SQL(q, exec(QStringLiteral("select id, name, dt, num, dtstamp, "
"extraId, extraName from ") + tableName));
QVERIFY( q.next() );
QCOMPARE( q.value( 0 ).toInt(), 1 );
QCOMPARE( q.value( 1 ).toString(), QString( "harald" ) );
QCOMPARE( q.value( 2 ).toDateTime(), dt );
QCOMPARE( q.value( 3 ).toDouble(), 2.3 );
QCOMPARE(q.value(4).toDateTime(), dtStamp);
for (int i = 0; i < intCol.size(); ++i) {
QVERIFY(q.next());
QCOMPARE(q.value(0).toInt(), intCol.at(i));
QCOMPARE(q.value(1).toString(), charCol.at(i));
QCOMPARE(q.value(2).toDate(), dateCol.at(i));
QCOMPARE(q.value(3).toDouble(), numCol.at(i));
if (tst_Databases::getDatabaseType(db) == QSqlDriver::MySqlServer && timeStampCol.at(i).isNull()) {
QEXPECT_FAIL("", "This appears to be a bug in MySQL as it converts null datetimes to the "
"current datetime for a timestamp field", Continue);
}
QCOMPARE(q.value(4).toDateTime(), timeStampCol.at(i));
QCOMPARE(q.value(5).toInt(), intCol.at(i));
QCOMPARE(q.value(6).toString(), charCol.at(i));
}
QVERIFY( q.next() );
QCOMPARE( q.value( 0 ).toInt(), 2 );
QCOMPARE( q.value( 1 ).toString(), QString( "boris" ) );
QCOMPARE( q.value( 2 ).toDateTime(), dt.addDays( -1 ) );
QCOMPARE( q.value( 3 ).toDouble(), 3.4 );
QCOMPARE(q.value(4).toDateTime(), dtStamp.addDays(-1));
// Empty table ready for retesting with duplicated named placeholders
QVERIFY_SQL(q, exec(QStringLiteral("delete from ") + tableName));
QVERIFY_SQL(q, prepare(QStringLiteral("insert into ") + tableName +
QStringLiteral(" (id, name, dt, num, dtstamp, extraId, extraName) "
"values (:id, :name, :dt, :num, :dtstamp, :id, :name)")));
q.bindValue(":id", intCol);
q.bindValue(":name", charCol);
q.bindValue(":dt", dateCol);
q.bindValue(":num", numCol);
q.bindValue(":dtstamp", timeStampCol);
QVERIFY( q.next() );
QVERIFY( q.value( 0 ).isNull() );
QVERIFY( q.value( 1 ).isNull() );
QVERIFY( q.value( 2 ).isNull() );
QVERIFY( q.value( 3 ).isNull() );
QVERIFY(q.value(4).isNull());
QVERIFY_SQL(q, execBatch());
QVERIFY_SQL(q, exec(QStringLiteral("select id, name, dt, num, dtstamp, extraId, extraName from ") +
tableName));
for (int i = 0; i < intCol.size(); ++i) {
QVERIFY(q.next());
QCOMPARE(q.value(0).toInt(), intCol.at(i));
QCOMPARE(q.value(1).toString(), charCol.at(i));
QCOMPARE(q.value(2).toDate(), dateCol.at(i));
QCOMPARE(q.value(3).toDouble(), numCol.at(i));
if (tst_Databases::getDatabaseType(db) == QSqlDriver::MySqlServer && timeStampCol.at(i).isNull()) {
QEXPECT_FAIL("", "This appears to be a bug in MySQL as it converts null datetimes to the "
"current datetime for a timestamp field", Continue);
}
QCOMPARE(q.value(4).toDateTime(), timeStampCol.at(i));
QCOMPARE(q.value(5).toInt(), intCol.at(i));
QCOMPARE(q.value(6).toString(), charCol.at(i));
}
// Only test the prepared stored procedure approach where the driver has support
// for batch operations as this will not work without it
if (db.driver()->hasFeature(QSqlDriver::BatchOperations)) {
const QString procName = qTableName("qtest_batch_proc", __FILE__, db);
QVERIFY_SQL(q, exec("create or replace procedure " + procName + " (x in timestamp, y out timestamp) is\n"
QVERIFY_SQL(q, exec("create or replace procedure " + procName +
" (x in timestamp, y out timestamp) is\n"
"begin\n"
" y := x;\n"
"end;\n"));
@ -2509,6 +2534,7 @@ void tst_QSqlQuery::batchExec()
q.addBindValue(emptyDateTimes, QSql::Out);
QVERIFY_SQL(q, execBatch());
QCOMPARE(q.boundValue(1).toList(), timeStampCol);
}
}
void tst_QSqlQuery::QTBUG_43874()

View File

@ -36,11 +36,11 @@ if(*-g++*|*-icc*|*-clang*|*-llvm):!win32-*: HEADERS += os9-newlines.h win-newlin
if(*-g++*|*-clang*): HEADERS += dollars.h
SOURCES += tst_moc.cpp
QT = core sql network testlib
qtHaveModule(dbus) {
DEFINES += WITH_DBUS
QT += dbus
}
QT = core testlib
qtHaveModule(dbus): QT += dbus
qtHaveModule(concurrent): QT += concurrent
qtHaveModule(network): QT += network
qtHaveModule(sql): QT += sql
# tst_Moc::specifyMetaTagsFromCmdline()
# Ensure that plugin_metadata.h are moc-ed with some extra -M arguments:

View File

@ -37,16 +37,19 @@
#define slots Baz
#define emit Yoyodyne
#include <QtCore/QtCore>
#ifdef QT_CONCURRENT_LIB
#include <QtConcurrent/QtConcurrent>
#include <QtCore>
#include <QtNetwork/QtNetwork>
#include <QtSql/QtSql>
//#include <QtSvg>
#if defined(WITH_DBUS)
#include <QtDBus>
#endif
#ifdef QT_SCRIPT_LIB
#include <QtScript>
#ifdef QT_NETWORK_LIB
#include <QtNetwork/QtNetwork>
#endif
#ifdef QT_SQL_LIB
#include <QtSql/QtSql>
#endif
#ifdef QT_DBUS_LIB
#include <QtDBus/QtDBus>
#endif
#undef signals

View File

@ -1604,6 +1604,12 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
<< ""
<< true;
QTest::newRow("$$absolute_path(): relative file & relative path")
<< "VAR = $$absolute_path(dir/file.ext, some/where)"
<< "VAR = " + qindir + "/some/where/dir/file.ext"
<< ""
<< true;
QTest::newRow("$$absolute_path(): file & path")
<< "VAR = $$absolute_path(dir/file.ext, " EVAL_DRIVE "/root/sub)"
<< "VAR = " EVAL_DRIVE "/root/sub/dir/file.ext"
@ -1642,6 +1648,12 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
<< ""
<< true;
QTest::newRow("$$relative_path(): relative file & relative path")
<< "VAR = $$relative_path(dir/file.ext, some/where)"
<< "VAR = dir/file.ext"
<< ""
<< true;
QTest::newRow("$$relative_path(): relative file to empty")
<< "VAR = $$relative_path(dir/..)"
<< "VAR = ."
@ -2752,9 +2764,9 @@ void tst_qmakelib::proEval_data()
// Raw data leak with empty file name. Verify with Valgrind or asan.
QTest::newRow("QTBUG-54550")
<< "FULL = /there/is\n"
<< "FULL = " EVAL_DRIVE "/there/is\n"
"VAR = $$absolute_path(, $$FULL/nothing/here/really)"
<< "VAR = /there/is/nothing/here/really"
<< "VAR = " EVAL_DRIVE "/there/is/nothing/here/really"
<< ""
<< true;
}

View File

@ -2992,19 +2992,14 @@ void tst_QGraphicsView::acceptMousePressEvent()
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QMouseEvent event(QEvent::MouseButtonPress,
view.viewport()->rect().center(),
view.viewport()->mapToGlobal(view.viewport()->rect().center()),
Qt::LeftButton, 0, 0);
event.setAccepted(false);
QApplication::sendEvent(view.viewport(), &event);
QTest::mouseClick(view.viewport(), Qt::LeftButton);
QVERIFY(!view.pressAccepted);
QSignalSpy spy(&scene, &QGraphicsScene::changed);
scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable);
QVERIFY(spy.wait());
qApp->processEvents(); // ensure scene rect is updated
QApplication::sendEvent(view.viewport(), &event);
QTest::mouseClick(view.viewport(), Qt::LeftButton);
QVERIFY(view.pressAccepted);
}
@ -3016,19 +3011,14 @@ void tst_QGraphicsView::acceptMouseDoubleClickEvent()
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QMouseEvent event(QEvent::MouseButtonDblClick,
view.viewport()->rect().center(),
view.viewport()->mapToGlobal(view.viewport()->rect().center()),
Qt::LeftButton, 0, 0);
event.setAccepted(false);
QApplication::sendEvent(view.viewport(), &event);
QTest::mouseDClick(view.viewport(), Qt::LeftButton);
QVERIFY(!view.doubleClickAccepted);
QSignalSpy spy(&scene, &QGraphicsScene::changed);
scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable);
QVERIFY(spy.wait());
qApp->processEvents(); // ensure scene rect is updated
QApplication::sendEvent(view.viewport(), &event);
QTest::mouseDClick(view.viewport(), Qt::LeftButton);
QVERIFY(view.doubleClickAccepted);
}