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

Change-Id: I4134c0c6b6c9911950f58b3b5c86e789d28a185b
This commit is contained in:
Qt Forward Merge Bot 2019-12-04 01:00:23 +01:00
commit 0c29ebe374
67 changed files with 1113 additions and 474 deletions

View File

@ -27,6 +27,7 @@
/*! /*!
\example widgets/styles \example widgets/styles
\meta {tag} {gallery}
\title Styles Example \title Styles Example
\ingroup examples-widgets \ingroup examples-widgets
\brief The Styles example illustrates how to create custom widget \brief The Styles example illustrates how to create custom widget

View File

@ -65,6 +65,7 @@
#include <QRadioButton> #include <QRadioButton>
#include <QScrollBar> #include <QScrollBar>
#include <QSpinBox> #include <QSpinBox>
#include <QStyle>
#include <QStyleFactory> #include <QStyleFactory>
#include <QTableWidget> #include <QTableWidget>
#include <QTextEdit> #include <QTextEdit>
@ -77,8 +78,16 @@ WidgetGallery::WidgetGallery(QWidget *parent)
originalPalette = QApplication::palette(); originalPalette = QApplication::palette();
styleComboBox = new QComboBox; styleComboBox = new QComboBox;
styleComboBox->addItem("NorwegianWood"); const QString defaultStyleName = QApplication::style()->objectName();
styleComboBox->addItems(QStyleFactory::keys()); QStringList styleNames = QStyleFactory::keys();
styleNames.append("NorwegianWood");
for (int i = 1, size = styleNames.size(); i < size; ++i) {
if (defaultStyleName.compare(styleNames.at(i), Qt::CaseInsensitive) == 0) {
styleNames.swapItemsAt(0, i);
break;
}
}
styleComboBox->addItems(styleNames);
styleLabel = new QLabel(tr("&Style:")); styleLabel = new QLabel(tr("&Style:"));
styleLabel->setBuddy(styleComboBox); styleLabel->setBuddy(styleComboBox);
@ -134,7 +143,6 @@ WidgetGallery::WidgetGallery(QWidget *parent)
setLayout(mainLayout); setLayout(mainLayout);
setWindowTitle(tr("Styles")); setWindowTitle(tr("Styles"));
changeStyle("NorwegianWood");
} }
//! [4] //! [4]

View File

@ -173,11 +173,20 @@ macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATI
endif() endif()
set(_static_link_flags \"${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${Configuration}_LINK_FLAGS}\") set(_static_link_flags \"${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${Configuration}_LINK_FLAGS}\")
if(NOT CMAKE_VERSION VERSION_LESS \"3.13\" AND _static_link_flags) if(_static_link_flags)
set(_static_link_flags_genex \"$<${_genex_condition}:${_static_link_flags}>\") set(_static_link_flags_genex \"$<${_genex_condition}:${_static_link_flags}>\")
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY INTERFACE_LINK_OPTIONS if(NOT CMAKE_VERSION VERSION_LESS \"3.13\")
\"${_static_link_flags_genex}\" set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY INTERFACE_LINK_OPTIONS
) \"${_static_link_flags_genex}\"
)
else()
# Abuse INTERFACE_LINK_LIBRARIES to add link flags when CMake version is too low.
# Strip out SHELL:, because it is not supported in this property. And hope for the best.
string(REPLACE \"SHELL:\" \"\" _static_link_flags_genex \"${_static_link_flags_genex}\")
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY INTERFACE_LINK_LIBRARIES
\"${_static_link_flags_genex}\"
)
endif()
endif() endif()
!!ENDIF !!ENDIF
@ -546,11 +555,20 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
endif() endif()
set(_static_link_flags \"${_Qt5${Plugin}_STATIC_${Configuration}_LINK_FLAGS}\") set(_static_link_flags \"${_Qt5${Plugin}_STATIC_${Configuration}_LINK_FLAGS}\")
if(NOT CMAKE_VERSION VERSION_LESS \"3.13\" AND _static_link_flags) if(_static_link_flags)
set(_static_link_flags_genex \"$<${_genex_condition}:${_static_link_flags}>\") set(_static_link_flags_genex \"$<${_genex_condition}:${_static_link_flags}>\")
set_property(TARGET Qt5::${Plugin} APPEND PROPERTY INTERFACE_LINK_OPTIONS if(NOT CMAKE_VERSION VERSION_LESS \"3.13\")
\"${_static_link_flags_genex}\" set_property(TARGET Qt5::${Plugin} APPEND PROPERTY INTERFACE_LINK_OPTIONS
) \"${_static_link_flags_genex}\"
)
else()
# Abuse INTERFACE_LINK_LIBRARIES to add link flags when CMake version is too low.
# Strip out SHELL:, because it is not supported in this property. And hope for the best.
string(REPLACE \"SHELL:\" \"\" _static_link_flags_genex \"${_static_link_flags_genex}\")
set_property(TARGET Qt5::${Plugin} APPEND PROPERTY INTERFACE_LINK_LIBRARIES
\"${_static_link_flags_genex}\"
)
endif()
endif() endif()
!!ENDIF !!ENDIF
endmacro() endmacro()

View File

@ -45,6 +45,8 @@ isEmpty(WIN_INCLUDETEMP) {
QDOC_INCLUDE_PATHS=@$$shell_quote($$WIN_INCLUDETEMP) QDOC_INCLUDE_PATHS=@$$shell_quote($$WIN_INCLUDETEMP)
} }
macos: QDOC_INCLUDE_PATHS += $$join(QMAKE_DEFAULT_INCDIRS," -I","-I")
!build_online_docs: qtPrepareTool(QHELPGENERATOR, qhelpgenerator) !build_online_docs: qtPrepareTool(QHELPGENERATOR, qhelpgenerator)
qtPrepareTool(QTATTRIBUTIONSSCANNER, qtattributionsscanner) qtPrepareTool(QTATTRIBUTIONSSCANNER, qtattributionsscanner)
@ -93,7 +95,6 @@ qtattributionsscanner.CONFIG += phony
QMAKE_EXTRA_TARGETS += qtattributionsscanner QMAKE_EXTRA_TARGETS += qtattributionsscanner
doc_command = $$QDOC $$QMAKE_DOCS doc_command = $$QDOC $$QMAKE_DOCS
prepare_docs { prepare_docs {
prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors $$QDOC_INCLUDE_PATHS prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors $$QDOC_INCLUDE_PATHS
generate_docs.commands += $$doc_command -generate $$DOC_INDEXES $$QDOC_INCLUDE_PATHS generate_docs.commands += $$doc_command -generate $$DOC_INDEXES $$QDOC_INCLUDE_PATHS

View File

@ -9,6 +9,9 @@ testcase_exceptions: CONFIG += exceptions
# Set in qt_build_config.prf # Set in qt_build_config.prf
testcase_no_bundle: CONFIG -= app_bundle testcase_no_bundle: CONFIG -= app_bundle
# cmdline may have been specified and not processed yet
cmdline: CONFIG -= app_bundle
# Allow testcases to mark themselves as not supporting high-DPI # Allow testcases to mark themselves as not supporting high-DPI
testcase_lowdpi { testcase_lowdpi {
macos { macos {

View File

@ -39,7 +39,7 @@
include(CMakeParseArguments) include(CMakeParseArguments)
# macro used to create the names of output files preserving relative dirs # macro used to create the names of output files preserving relative dirs
macro(QT5_MAKE_OUTPUT_FILE infile prefix ext outfile ) macro(qt5_make_output_file infile prefix ext outfile )
string(LENGTH ${CMAKE_CURRENT_BINARY_DIR} _binlength) string(LENGTH ${CMAKE_CURRENT_BINARY_DIR} _binlength)
string(LENGTH ${infile} _infileLength) string(LENGTH ${infile} _infileLength)
set(_checkinfile ${CMAKE_CURRENT_SOURCE_DIR}) set(_checkinfile ${CMAKE_CURRENT_SOURCE_DIR})
@ -65,7 +65,7 @@ macro(QT5_MAKE_OUTPUT_FILE infile prefix ext outfile )
endmacro() endmacro()
macro(QT5_GET_MOC_FLAGS _moc_flags) macro(qt5_get_moc_flags _moc_flags)
set(${_moc_flags}) set(${_moc_flags})
get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES) get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES)
@ -97,7 +97,7 @@ endmacro()
# helper macro to set up a moc rule # helper macro to set up a moc rule
function(QT5_CREATE_MOC_COMMAND infile outfile moc_flags moc_options moc_target moc_depends) function(qt5_create_moc_command infile outfile moc_flags moc_options moc_target moc_depends)
# Pass the parameters in a file. Set the working directory to # Pass the parameters in a file. Set the working directory to
# be that containing the parameters file and reference it by # be that containing the parameters file and reference it by
# just the file name. This is necessary because the moc tool on # just the file name. This is necessary because the moc tool on
@ -143,7 +143,7 @@ function(QT5_CREATE_MOC_COMMAND infile outfile moc_flags moc_options moc_target
endfunction() endfunction()
function(QT5_GENERATE_MOC infile outfile ) function(qt5_generate_moc infile outfile )
# get include dirs and flags # get include dirs and flags
qt5_get_moc_flags(moc_flags) qt5_get_moc_flags(moc_flags)
get_filename_component(abs_infile ${infile} ABSOLUTE) get_filename_component(abs_infile ${infile} ABSOLUTE)
@ -160,7 +160,7 @@ endfunction()
# qt5_wrap_cpp(outfiles inputfile ... ) # qt5_wrap_cpp(outfiles inputfile ... )
function(QT5_WRAP_CPP outfiles ) function(qt5_wrap_cpp outfiles )
# get include dirs # get include dirs
qt5_get_moc_flags(moc_flags) qt5_get_moc_flags(moc_flags)
@ -189,7 +189,7 @@ endfunction()
# _qt5_parse_qrc_file(infile _out_depends _rc_depends) # _qt5_parse_qrc_file(infile _out_depends _rc_depends)
# internal # internal
function(_QT5_PARSE_QRC_FILE infile _out_depends _rc_depends) function(_qt5_parse_qrc_file infile _out_depends _rc_depends)
get_filename_component(rc_path ${infile} PATH) get_filename_component(rc_path ${infile} PATH)
if(EXISTS "${infile}") if(EXISTS "${infile}")
@ -222,7 +222,7 @@ endfunction()
# qt5_add_binary_resources(target inputfiles ... ) # qt5_add_binary_resources(target inputfiles ... )
function(QT5_ADD_BINARY_RESOURCES target ) function(qt5_add_binary_resources target )
set(options) set(options)
set(oneValueArgs DESTINATION) set(oneValueArgs DESTINATION)
@ -241,7 +241,7 @@ function(QT5_ADD_BINARY_RESOURCES target )
foreach(it ${rcc_files}) foreach(it ${rcc_files})
get_filename_component(infile ${it} ABSOLUTE) get_filename_component(infile ${it} ABSOLUTE)
_QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends) _qt5_parse_qrc_file(${infile} _out_depends _rc_depends)
set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON)
set(infiles ${infiles} ${infile}) set(infiles ${infiles} ${infile})
set(out_depends ${out_depends} ${_out_depends}) set(out_depends ${out_depends} ${_out_depends})
@ -258,7 +258,7 @@ endfunction()
# qt5_add_resources(outfiles inputfile ... ) # qt5_add_resources(outfiles inputfile ... )
function(QT5_ADD_RESOURCES outfiles ) function(qt5_add_resources outfiles )
set(options) set(options)
set(oneValueArgs) set(oneValueArgs)
@ -278,7 +278,7 @@ function(QT5_ADD_RESOURCES outfiles )
get_filename_component(infile ${it} ABSOLUTE) get_filename_component(infile ${it} ABSOLUTE)
set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.cpp) set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.cpp)
_QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends) _qt5_parse_qrc_file(${infile} _out_depends _rc_depends)
set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON)
add_custom_command(OUTPUT ${outfile} add_custom_command(OUTPUT ${outfile}
@ -295,7 +295,7 @@ endfunction()
# qt5_add_big_resources(outfiles inputfile ... ) # qt5_add_big_resources(outfiles inputfile ... )
function(QT5_ADD_BIG_RESOURCES outfiles ) function(qt5_add_big_resources outfiles )
if (CMAKE_VERSION VERSION_LESS 3.9) if (CMAKE_VERSION VERSION_LESS 3.9)
message(FATAL_ERROR, "qt5_add_big_resources requires CMake 3.9 or newer") message(FATAL_ERROR, "qt5_add_big_resources requires CMake 3.9 or newer")
endif() endif()
@ -319,7 +319,7 @@ function(QT5_ADD_BIG_RESOURCES outfiles )
set(tmpoutfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}tmp.cpp) set(tmpoutfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}tmp.cpp)
set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.o) set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.o)
_QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends) _qt5_parse_qrc_file(${infile} _out_depends _rc_depends)
set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON)
add_custom_command(OUTPUT ${tmpoutfile} add_custom_command(OUTPUT ${tmpoutfile}
COMMAND ${Qt5Core_RCC_EXECUTABLE} ${rcc_options} --name ${outfilename} --pass 1 --output ${tmpoutfile} ${infile} COMMAND ${Qt5Core_RCC_EXECUTABLE} ${rcc_options} --name ${outfilename} --pass 1 --output ${tmpoutfile} ${infile}
@ -343,58 +343,53 @@ endfunction()
set(_Qt5_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..") set(_Qt5_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..")
if (NOT CMAKE_VERSION VERSION_LESS 2.8.9) macro(qt5_use_modules _target _link_type)
macro(qt5_use_modules _target _link_type) if(CMAKE_WARN_DEPRECATED)
if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.11) set(messageType WARNING)
if(CMAKE_WARN_DEPRECATED) endif()
set(messageType WARNING) if(CMAKE_ERROR_DEPRECATED)
endif() set(messageType FATAL_ERROR)
if(CMAKE_ERROR_DEPRECATED) endif()
set(messageType FATAL_ERROR) if(messageType)
endif() message(${messageType} "The qt5_use_modules macro is obsolete. Use target_link_libraries with IMPORTED targets instead.")
if(messageType) endif()
message(${messageType} "The qt5_use_modules macro is obsolete. Use target_link_libraries with IMPORTED targets instead.")
endif()
endif()
if (NOT TARGET ${_target}) if (NOT TARGET ${_target})
message(FATAL_ERROR "The first argument to qt5_use_modules must be an existing target.") message(FATAL_ERROR "The first argument to qt5_use_modules must be an existing target.")
endif() endif()
if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE" ) if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE" )
set(_qt5_modules ${ARGN}) set(_qt5_modules ${ARGN})
set(_qt5_link_type ${_link_type}) set(_qt5_link_type ${_link_type})
else() else()
set(_qt5_modules ${_link_type} ${ARGN}) set(_qt5_modules ${_link_type} ${ARGN})
endif() endif()
if ("${_qt5_modules}" STREQUAL "") if ("${_qt5_modules}" STREQUAL "")
message(FATAL_ERROR "qt5_use_modules requires at least one Qt module to use.") message(FATAL_ERROR "qt5_use_modules requires at least one Qt module to use.")
endif() endif()
foreach(_module ${_qt5_modules}) 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) if (NOT Qt5${_module}_FOUND)
find_package(Qt5${_module} PATHS "${_Qt5_COMPONENT_PATH}" NO_DEFAULT_PATH) message(FATAL_ERROR "Cannot use \"${_module}\" module which has not yet been found.")
if (NOT Qt5${_module}_FOUND)
message(FATAL_ERROR "Cannot use \"${_module}\" module which has not yet been found.")
endif()
endif() endif()
target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES}) endif()
set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${Qt5${_module}_INCLUDE_DIRS}) target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES})
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${Qt5${_module}_COMPILE_DEFINITIONS}) set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${Qt5${_module}_INCLUDE_DIRS})
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG) set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${Qt5${_module}_COMPILE_DEFINITIONS})
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG) set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG)
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG) set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG)
if (Qt5_POSITION_INDEPENDENT_CODE set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG)
AND (CMAKE_VERSION VERSION_LESS 2.8.12 if (Qt5_POSITION_INDEPENDENT_CODE
AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))) OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))
set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE}) set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE})
endif() endif()
endforeach() endforeach()
endmacro() endmacro()
endif()
function(QT5_IMPORT_PLUGINS TARGET_NAME) function(qt5_import_plugins TARGET_NAME)
set(_doing "") set(_doing "")
foreach(_arg ${ARGN}) foreach(_arg ${ARGN})
if(_arg STREQUAL "INCLUDE") if(_arg STREQUAL "INCLUDE")

View File

@ -107,7 +107,6 @@ QByteArray QGb18030Codec::convertFromUnicode(const QChar *uc, int len, Converter
if (high >= 0) { if (high >= 0) {
if (uc[i].isLowSurrogate()) { if (uc[i].isLowSurrogate()) {
// valid surrogate pair // valid surrogate pair
++i;
uint u = QChar::surrogateToUcs4(high, uc[i].unicode()); uint u = QChar::surrogateToUcs4(high, uc[i].unicode());
len = qt_UnicodeToGb18030(u, buf); len = qt_UnicodeToGb18030(u, buf);
if (len >= 2) { if (len >= 2) {

View File

@ -244,6 +244,7 @@ QF16_MAKE_ARITH_OP_INT(/)
QT_WARNING_PUSH QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
inline bool operator>(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) > static_cast<float>(b); } inline bool operator>(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) > static_cast<float>(b); }
inline bool operator<(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) < static_cast<float>(b); } inline bool operator<(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) < static_cast<float>(b); }

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the documentation of the Qt Toolkit. ** This file is part of the documentation of the Qt Toolkit.
@ -724,9 +724,17 @@
\value LocalDate \e{This enum value is deprecated.} Use Qt::SystemLocaleShortDate \value LocalDate \e{This enum value is deprecated.} Use Qt::SystemLocaleShortDate
instead (or Qt::SystemLocaleLongDate if you want long dates). instead (or Qt::SystemLocaleLongDate if you want long dates).
\value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format: either \value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format:
\c{[ddd,] dd MMM yyyy hh:mm[:ss] +/-TZ} or \c{ddd MMM dd yyyy hh:mm[:ss] +/-TZ} either \c{[ddd,] dd MMM yyyy [hh:mm[:ss]][ ±tzoff]}
for combined dates and times. or \c{ddd MMM dd[ hh:mm:ss] yyyy[ ±tzoff]} are recognized for combined dates
and times, where \c{tzoff} is a timezone offset in \c{hhmm} format. For
dates and times separately, the same formats are matched and the unwanted
parts are ignored. In particular, note that a time is not recognized without
an accompanying date. When converting dates to string form,
format \c{dd MMM yyyy} is used, for times the format is \c{hh:mm:ss}. For
combined date and time, these are combined
as \c{dd MMM yyyy hh:mm:ss ±tzoff} (omitting the optional leading day of the
week from the first format recognized).
\note For \c ISODate formats, each \c Y, \c M and \c D represents a single digit \note For \c ISODate formats, each \c Y, \c M and \c D represents a single digit
of the year, month and day used to specify the date. Each \c H, \c M and \c S of the year, month and day used to specify the date. Each \c H, \c M and \c S

View File

@ -359,14 +359,14 @@ QT_BEGIN_NAMESPACE
/*! /*!
\fn QString QStandardPaths::writableLocation(StandardLocation type) \fn QString QStandardPaths::writableLocation(StandardLocation type)
\include standardpath/functiondoc.qdocinc writableLocation \include standardpath/functiondocs.qdocinc writableLocation
*/ */
/*! /*!
\fn QStringList QStandardPaths::standardLocations(StandardLocation type) \fn QStringList QStandardPaths::standardLocations(StandardLocation type)
\include standardpath/functiondoc.qdocinc standardLocations \include standardpath/functiondocs.qdocinc standardLocations
\sa writableLocation() \sa writableLocation()
*/ */
@ -390,7 +390,7 @@ static bool existsAsSpecified(const QString &path, QStandardPaths::LocateOptions
} }
/*! /*!
\include standardpath/functiondoc.qdocinc locate \include standardpath/functiondocs.qdocinc locate
*/ */
QString QStandardPaths::locate(StandardLocation type, const QString &fileName, LocateOptions options) QString QStandardPaths::locate(StandardLocation type, const QString &fileName, LocateOptions options)
{ {
@ -404,7 +404,7 @@ QString QStandardPaths::locate(StandardLocation type, const QString &fileName, L
} }
/*! /*!
\include standardpath/functiondoc.qdocinc locateAll \include standardpath/functiondocs.qdocinc locateAll
*/ */
QStringList QStandardPaths::locateAll(StandardLocation type, const QString &fileName, LocateOptions options) QStringList QStandardPaths::locateAll(StandardLocation type, const QString &fileName, LocateOptions options)
{ {
@ -477,7 +477,7 @@ static inline QString
#endif // Q_OS_WIN #endif // Q_OS_WIN
/*! /*!
\include standardpath/functiondoc.qdocinc findExecutable \include standardpath/functiondocs.qdocinc findExecutable
*/ */
QString QStandardPaths::findExecutable(const QString &executableName, const QStringList &paths) QString QStandardPaths::findExecutable(const QString &executableName, const QStringList &paths)
{ {
@ -535,7 +535,7 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr
} }
/*! /*!
\include standardpath/functiondoc.qdocinc displayName \include standardpath/functiondocs.qdocinc displayName
*/ */
#if !defined(Q_OS_MAC) && !defined(QT_BOOTSTRAPPED) #if !defined(Q_OS_MAC) && !defined(QT_BOOTSTRAPPED)
@ -592,7 +592,7 @@ QString QStandardPaths::displayName(StandardLocation type)
/*! /*!
\fn void QStandardPaths::setTestModeEnabled(bool testMode) \fn void QStandardPaths::setTestModeEnabled(bool testMode)
\include standardpath/functiondoc.qdocinc setTestModeEnabled \include standardpath/functiondocs.qdocinc setTestModeEnabled
*/ */
static bool qsp_testMode = false; static bool qsp_testMode = false;

View File

@ -761,6 +761,85 @@ QT_BEGIN_NAMESPACE
using namespace QtCbor; using namespace QtCbor;
static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
{
qint64 tag = d->elements.at(0).value;
auto &e = d->elements[1];
const ByteData *b = d->byteData(e);
auto replaceByteData = [&](const char *buf, qsizetype len, Element::ValueFlags f) {
d->data.clear();
d->usedData = 0;
e.flags = Element::HasByteData | f;
e.value = d->addByteData(buf, len);
};
switch (tag) {
case qint64(QCborKnownTags::DateTimeString):
case qint64(QCborKnownTags::UnixTime_t): {
QDateTime dt;
if (tag == qint64(QCborKnownTags::DateTimeString) && b &&
e.type == QCborValue::String && (e.flags & Element::StringIsUtf16) == 0) {
// The data is supposed to be US-ASCII. If it isn't (contains UTF-8),
// QDateTime::fromString will fail anyway.
dt = QDateTime::fromString(b->asLatin1(), Qt::ISODateWithMs);
} else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Integer) {
dt = QDateTime::fromSecsSinceEpoch(e.value, Qt::UTC);
} else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Double) {
dt = QDateTime::fromMSecsSinceEpoch(qint64(e.fpvalue() * 1000), Qt::UTC);
}
if (dt.isValid()) {
QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1();
replaceByteData(text, text.size(), Element::StringIsAscii);
e.type = QCborValue::String;
d->elements[0].value = qint64(QCborKnownTags::DateTimeString);
return QCborValue::DateTime;
}
break;
}
#ifndef QT_BOOTSTRAPPED
case qint64(QCborKnownTags::Url):
if (e.type == QCborValue::String) {
if (b) {
// normalize to a short (decoded) form, so as to save space
QUrl url(e.flags & Element::StringIsUtf16 ?
b->asQStringRaw() :
b->toUtf8String());
QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8();
replaceByteData(encoded, encoded.size(), {});
}
return QCborValue::Url;
}
break;
#endif // QT_BOOTSTRAPPED
#if QT_CONFIG(regularexpression)
case quint64(QCborKnownTags::RegularExpression):
if (e.type == QCborValue::String) {
// no normalization is necessary
return QCborValue::RegularExpression;
}
break;
#endif // QT_CONFIG(regularexpression)
case qint64(QCborKnownTags::Uuid):
if (e.type == QCborValue::ByteArray) {
// force the size to 16
char buf[sizeof(QUuid)] = {};
if (b)
memcpy(buf, b->byte(), qMin(sizeof(buf), size_t(b->len)));
replaceByteData(buf, sizeof(buf), {});
return QCborValue::Uuid;
}
break;
}
// no enriching happened
return QCborValue::Tag;
}
#if QT_CONFIG(cborstream) #if QT_CONFIG(cborstream)
// in qcborstream.cpp // in qcborstream.cpp
extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error); extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
@ -1390,77 +1469,10 @@ static QCborValue taggedValueFromCbor(QCborStreamReader &reader)
d->decodeValueFromCbor(reader); d->decodeValueFromCbor(reader);
} }
QCborValue::Type type = QCborValue::Tag; QCborValue::Type type;
if (reader.lastError() == QCborError::NoError) { if (reader.lastError() == QCborError::NoError) {
// post-process to create our extended types // post-process to create our extended types
qint64 tag = d->elements.at(0).value; type = convertToExtendedType(d);
auto &e = d->elements[1];
const ByteData *b = d->byteData(e);
auto replaceByteData = [&](const char *buf, qsizetype len) {
d->data.clear();
d->usedData = 0;
e.flags = Element::HasByteData | Element::StringIsAscii;
e.value = d->addByteData(buf, len);
};
switch (tag) {
case qint64(QCborKnownTags::DateTimeString):
case qint64(QCborKnownTags::UnixTime_t): {
QDateTime dt;
if (tag == qint64(QCborKnownTags::DateTimeString) && b &&
e.type == QCborValue::String && (e.flags & Element::StringIsUtf16) == 0) {
// The data is supposed to be US-ASCII. If it isn't,
// QDateTime::fromString will fail anyway.
dt = QDateTime::fromString(b->asLatin1(), Qt::ISODateWithMs);
} else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Integer) {
dt = QDateTime::fromSecsSinceEpoch(e.value, Qt::UTC);
} else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Double) {
dt = QDateTime::fromMSecsSinceEpoch(qint64(e.fpvalue() * 1000), Qt::UTC);
}
if (dt.isValid()) {
QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1();
replaceByteData(text, text.size());
e.type = QCborValue::String;
d->elements[0].value = qint64(QCborKnownTags::DateTimeString);
type = QCborValue::DateTime;
}
break;
}
case qint64(QCborKnownTags::Url):
if (e.type == QCborValue::String) {
if (b) {
// normalize to a short (decoded) form, so as to save space
QUrl url(e.flags & Element::StringIsUtf16 ?
b->asQStringRaw() :
b->toUtf8String());
QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8();
replaceByteData(encoded, encoded.size());
}
type = QCborValue::Url;
}
break;
case quint64(QCborKnownTags::RegularExpression):
if (e.type == QCborValue::String) {
// no normalization is necessary
type = QCborValue::RegularExpression;
}
break;
case qint64(QCborKnownTags::Uuid):
if (e.type == QCborValue::ByteArray) {
// force the size to 16
char buf[sizeof(QUuid)] = {};
if (b)
memcpy(buf, b->byte(), qMin(sizeof(buf), size_t(b->len)));
replaceByteData(buf, sizeof(buf));
type = QCborValue::Uuid;
}
break;
}
} else { } else {
// decoding error // decoding error
type = QCborValue::Invalid; type = QCborValue::Invalid;
@ -1724,21 +1736,22 @@ QCborValue::QCborValue(const QCborMap &m)
} }
/*! /*!
\fn QCborValue::QCborValue(QCborTag t, const QCborValue &tv) \fn QCborValue::QCborValue(QCborTag tag, const QCborValue &tv)
\fn QCborValue::QCborValue(QCborKnownTags t, const QCborValue &tv) \fn QCborValue::QCborValue(QCborKnownTags tag, const QCborValue &tv)
Creates a QCborValue for the extended type represented by the tag value \a Creates a QCborValue for the extended type represented by the tag value \a
t, tagging value \a tv. The tag can later be retrieved using tag() and tag, tagging value \a tv. The tag can later be retrieved using tag() and
the tagged value using taggedValue(). the tagged value using taggedValue().
\sa isTag(), tag(), taggedValue(), QCborKnownTags \sa isTag(), tag(), taggedValue(), QCborKnownTags
*/ */
QCborValue::QCborValue(QCborTag t, const QCborValue &tv) QCborValue::QCborValue(QCborTag tag, const QCborValue &tv)
: n(-1), container(new QCborContainerPrivate), t(Tag) : n(-1), container(new QCborContainerPrivate), t(Tag)
{ {
container->ref.storeRelaxed(1); container->ref.storeRelaxed(1);
container->append(t); container->append(tag);
container->append(tv); container->append(tv);
t = convertToExtendedType(container);
} }
/*! /*!

View File

@ -164,8 +164,8 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s)
{ {
ParsedRfcDateTime result; ParsedRfcDateTime result;
// Matches "Wdy, dd Mon yyyy HH:mm:ss ±hhmm" (Wdy, being optional) // Matches "[ddd,] dd MMM yyyy[ hh:mm[:ss]] [±hhmm]" - correct RFC 822, 2822, 5322 format
QRegExp rex(QStringLiteral("^(?:[A-Z][a-z]+,)?[ \\t]*(\\d{1,2})[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d)(?::(\\d\\d))?)?[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?")); QRegExp rex(QStringLiteral("^[ \\t]*(?:[A-Z][a-z]+,)?[ \\t]*(\\d{1,2})[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d)(?::(\\d\\d))?)?[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?"));
if (s.indexOf(rex) == 0) { if (s.indexOf(rex) == 0) {
const QStringList cap = rex.capturedTexts(); const QStringList cap = rex.capturedTexts();
result.date = QDate(cap[3].toInt(), qt_monthNumberFromShortName(cap[2]), cap[1].toInt()); result.date = QDate(cap[3].toInt(), qt_monthNumberFromShortName(cap[2]), cap[1].toInt());
@ -176,8 +176,8 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s)
const int minOffset = cap[9].toInt(); const int minOffset = cap[9].toInt();
result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60)); result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
} else { } else {
// Matches "Wdy Mon dd HH:mm:ss yyyy" // Matches "ddd MMM dd[ hh:mm:ss] yyyy [±hhmm]" - permissive RFC 850, 1036 (read only)
QRegExp rex(QStringLiteral("^[A-Z][a-z]+[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d):(\\d\\d))?[ \\t]+(\\d\\d\\d\\d)[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?")); QRegExp rex(QStringLiteral("^[ \\t]*[A-Z][a-z]+[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d):(\\d\\d))?[ \\t]+(\\d\\d\\d\\d)[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?"));
if (s.indexOf(rex) == 0) { if (s.indexOf(rex) == 0) {
const QStringList cap = rex.capturedTexts(); const QStringList cap = rex.capturedTexts();
result.date = QDate(cap[6].toInt(), qt_monthNumberFromShortName(cap[1]), cap[2].toInt()); result.date = QDate(cap[6].toInt(), qt_monthNumberFromShortName(cap[1]), cap[2].toInt());

View File

@ -1,5 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2014 Drew Parsons <dparsons@emerall.com> ** Copyright (C) 2014 Drew Parsons <dparsons@emerall.com>
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -53,9 +54,10 @@ QT_BEGIN_NAMESPACE
QAndroidTimeZonePrivate::QAndroidTimeZonePrivate() QAndroidTimeZonePrivate::QAndroidTimeZonePrivate()
: QTimeZonePrivate() : QTimeZonePrivate()
{ {
// start with system time zone // Keep in sync with systemTimeZoneId():
androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod(
init("UTC"); "java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
m_id = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;").toString().toUtf8();
} }
// Create a named time zone // Create a named time zone
@ -76,32 +78,33 @@ QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate()
{ {
} }
void QAndroidTimeZonePrivate::init(const QByteArray &ianaId) void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
{ {
QJNIObjectPrivate jo_ianaId = QJNIObjectPrivate::fromString( QString::fromUtf8(ianaId) ); const QString iana = QString::fromUtf8(ianaId);
androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;", static_cast<jstring>(jo_ianaId.object()) ); androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod(
"java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;",
static_cast<jstring>(QJNIObjectPrivate::fromString(iana).object()));
// The ID or display name of the zone we've got, if it looks like what we asked for:
const auto match = [iana](const QJNIObjectPrivate &jname) -> QByteArray {
const QString name = jname.toString();
if (iana.compare(name, Qt::CaseInsensitive))
return name.toUtf8();
return QByteArray();
};
// Painfully, JNI gives us back a default zone object if it doesn't // Painfully, JNI gives us back a default zone object if it doesn't
// recognize the name; so check for whether ianaId is a recognized name of // recognize the name; so check for whether ianaId is a recognized name of
// the zone object we got and ignore the zone if not. // the zone object we got and ignore the zone if not.
// Try checking ianaId against getID(), getDisplayName(): // Try checking ianaId against getID(), getDisplayName():
QJNIObjectPrivate jname = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;"); m_id = match(androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;"));
bool found = (jname.toString().toUtf8() == ianaId); for (int style = 1; m_id.isEmpty() && style-- > 0;) {
for (int style = 1; !found && style-- > 0;) { for (int dst = 1; m_id.isEmpty() && dst-- > 0;) {
for (int dst = 1; !found && dst-- > 0;) { m_id = match(androidTimeZone.callObjectMethod(
jname = androidTimeZone.callObjectMethod("getDisplayName", "(ZI;)Ljava/lang/String;", "getDisplayName", "(ZI;)Ljava/lang/String;", bool(dst), style));
bool(dst), style);
found = (jname.toString().toUtf8() == ianaId);
} }
} }
if (!found)
m_id.clear();
else if (ianaId.isEmpty())
m_id = systemTimeZoneId();
else
m_id = ianaId;
} }
QAndroidTimeZonePrivate *QAndroidTimeZonePrivate::clone() const QAndroidTimeZonePrivate *QAndroidTimeZonePrivate::clone() const
@ -225,11 +228,10 @@ QTimeZonePrivate::Data QAndroidTimeZonePrivate::previousTransition(qint64 before
QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const
{ {
QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); // Keep in sync with default constructor:
QJNIObjectPrivate systemTZIdAndroid = androidSystemTimeZone.callObjectMethod<jstring>("getID"); QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod(
QByteArray systemTZid = systemTZIdAndroid.toString().toUtf8(); "java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
return androidSystemTimeZone.callObjectMethod<jstring>("getID").toString().toUtf8();
return systemTZid;
} }
QList<QByteArray> QAndroidTimeZonePrivate::availableTimeZoneIds() const QList<QByteArray> QAndroidTimeZonePrivate::availableTimeZoneIds() const

View File

@ -1,5 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2013 John Layt <jlayt@kde.org> ** Copyright (C) 2013 John Layt <jlayt@kde.org>
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -94,6 +95,16 @@ void QMacTimeZonePrivate::init(const QByteArray &ianaId)
if (m_nstz) if (m_nstz)
m_id = ianaId; m_id = ianaId;
} }
if (!m_nstz) {
// macOS has been seen returning a systemTimeZone which reports its name
// as Asia/Kolkata, which doesn't appear in knownTimeZoneNames (which
// calls the zone Asia/Calcutta). So explicitly check for the name
// systemTimeZoneId() returns, and use systemTimeZone if we get it:
m_nstz = [NSTimeZone.systemTimeZone retain];
Q_ASSERT(m_nstz);
if (QString::fromNSString(m_nstz.name).toUtf8() == ianaId)
m_id = ianaId;
}
} }
QString QMacTimeZonePrivate::comment() const QString QMacTimeZonePrivate::comment() const

View File

@ -597,10 +597,7 @@ Q_INLINE_TEMPLATE QHash<Key, T> &QHash<Key, T>::unite(const QHash &other)
QHash copy(other); QHash copy(other);
const_iterator it = copy.constEnd(); const_iterator it = copy.constEnd();
while (it != copy.constBegin()) { while (it != copy.constBegin()) {
QT_WARNING_PUSH it.i = QHashData::previousNode(it.i);
QT_WARNING_DISABLE_DEPRECATED
--it;
QT_WARNING_POP
insertMulti(it.key(), it.value()); insertMulti(it.key(), it.value());
} }
#else #else

View File

@ -352,6 +352,7 @@ Q_DECL_RELAXED_CONSTEXPR inline QPointF &QPointF::operator*=(qreal c)
QT_WARNING_PUSH QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
Q_DECL_CONSTEXPR inline bool operator==(const QPointF &p1, const QPointF &p2) Q_DECL_CONSTEXPR inline bool operator==(const QPointF &p1, const QPointF &p2)
{ {

View File

@ -665,6 +665,7 @@ Q_DECL_CONSTEXPR inline QRectF::QRectF(const QRect &r) noexcept
QT_WARNING_PUSH QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
Q_DECL_CONSTEXPR inline bool QRectF::isNull() const noexcept Q_DECL_CONSTEXPR inline bool QRectF::isNull() const noexcept
{ return w == 0. && h == 0.; } { return w == 0. && h == 0.; }

View File

@ -34,7 +34,7 @@ include(MacroAddFileDependencies)
include(CMakeParseArguments) include(CMakeParseArguments)
function(QT5_ADD_DBUS_INTERFACE _sources _interface _basename) function(qt5_add_dbus_interface _sources _interface _basename)
get_filename_component(_infile ${_interface} ABSOLUTE) get_filename_component(_infile ${_interface} ABSOLUTE)
set(_header "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h") set(_header "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h")
set(_impl "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp") set(_impl "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp")
@ -71,7 +71,7 @@ function(QT5_ADD_DBUS_INTERFACE _sources _interface _basename)
endfunction() endfunction()
function(QT5_ADD_DBUS_INTERFACES _sources) function(qt5_add_dbus_interfaces _sources)
foreach(_current_FILE ${ARGN}) foreach(_current_FILE ${ARGN})
get_filename_component(_infile ${_current_FILE} ABSOLUTE) get_filename_component(_infile ${_current_FILE} ABSOLUTE)
get_filename_component(_basename ${_current_FILE} NAME) get_filename_component(_basename ${_current_FILE} NAME)
@ -84,7 +84,7 @@ function(QT5_ADD_DBUS_INTERFACES _sources)
endfunction() endfunction()
function(QT5_GENERATE_DBUS_INTERFACE _header) # _customName OPTIONS -some -options ) function(qt5_generate_dbus_interface _header) # _customName OPTIONS -some -options )
set(options) set(options)
set(oneValueArgs) set(oneValueArgs)
set(multiValueArgs OPTIONS) set(multiValueArgs OPTIONS)
@ -117,7 +117,7 @@ function(QT5_GENERATE_DBUS_INTERFACE _header) # _customName OPTIONS -some -optio
endfunction() endfunction()
function(QT5_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optionalBasename _optionalClassName) function(qt5_add_dbus_adaptor _sources _xml_file _include _parentClass) # _optionalBasename _optionalClassName)
get_filename_component(_infile ${_xml_file} ABSOLUTE) get_filename_component(_infile ${_xml_file} ABSOLUTE)
set(_optionalBasename "${ARGV4}") set(_optionalBasename "${ARGV4}")

View File

@ -204,7 +204,9 @@ QDBusInterfacePrivate::~QDBusInterfacePrivate()
interface \a interface on object at path \a path on service \a interface \a interface on object at path \a path on service \a
service, using the given \a connection. If \a interface is an service, using the given \a connection. If \a interface is an
empty string, the object created will refer to the merging of all empty string, the object created will refer to the merging of all
interfaces found in that object. interfaces found by introspecting that object. Otherwise if
\a interface is not empty, the QDBusInterface object will be cached
to speedup further creations of the same interface.
\a parent is passed to the base class constructor. \a parent is passed to the base class constructor.

View File

@ -215,6 +215,7 @@ private:
QT_WARNING_PUSH QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE);
inline QMatrix4x4::QMatrix4x4 inline QMatrix4x4::QMatrix4x4

View File

@ -171,6 +171,7 @@ inline QQuaternion::QQuaternion(float aScalar, float xpos, float ypos, float zpo
QT_WARNING_PUSH QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
inline bool QQuaternion::isNull() const inline bool QQuaternion::isNull() const
{ {
return wp == 0.0f && xp == 0.0f && yp == 0.0f && zp == 0.0f; return wp == 0.0f && xp == 0.0f && yp == 0.0f && zp == 0.0f;

View File

@ -207,6 +207,7 @@ inline QVector2D &QVector2D::operator/=(const QVector2D &vector)
QT_WARNING_PUSH QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
Q_DECL_CONSTEXPR inline bool operator==(const QVector2D &v1, const QVector2D &v2) Q_DECL_CONSTEXPR inline bool operator==(const QVector2D &v1, const QVector2D &v2)
{ {
return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1]; return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1];

View File

@ -232,6 +232,7 @@ inline QVector3D &QVector3D::operator/=(const QVector3D &vector)
QT_WARNING_PUSH QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
Q_DECL_CONSTEXPR inline bool operator==(const QVector3D &v1, const QVector3D &v2) Q_DECL_CONSTEXPR inline bool operator==(const QVector3D &v1, const QVector3D &v2)
{ {
return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2]; return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2];

View File

@ -232,6 +232,7 @@ inline QVector4D &QVector4D::operator/=(const QVector4D &vector)
QT_WARNING_PUSH QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
Q_DECL_CONSTEXPR inline bool operator==(const QVector4D &v1, const QVector4D &v2) Q_DECL_CONSTEXPR inline bool operator==(const QVector4D &v1, const QVector4D &v2)
{ {
return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2] && v1.v[3] == v2.v[3]; return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2] && v1.v[3] == v2.v[3];

View File

@ -658,13 +658,11 @@ void QOpenGLFramebufferObjectPrivate::initDepthStencilAttachments(QOpenGLContext
funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer); funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer)); Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
GLenum storageFormat = GL_DEPTH_STENCIL;
if (samples != 0 ) { if (samples != 0 ) {
funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
storageFormat, dsSize.width(), dsSize.height()); GL_DEPTH24_STENCIL8, dsSize.width(), dsSize.height());
} else { } else {
funcs.glRenderbufferStorage(GL_RENDERBUFFER, storageFormat, funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL,
dsSize.width(), dsSize.height()); dsSize.width(), dsSize.height());
} }

View File

@ -388,8 +388,12 @@ static int qt_gl_resolve_extensions()
| QOpenGLExtensions::MapBufferRange | QOpenGLExtensions::MapBufferRange
| QOpenGLExtensions::FramebufferBlit | QOpenGLExtensions::FramebufferBlit
| QOpenGLExtensions::FramebufferMultisample | QOpenGLExtensions::FramebufferMultisample
| QOpenGLExtensions::Sized8Formats | QOpenGLExtensions::Sized8Formats;
| QOpenGLExtensions::TextureSwizzle; #ifndef Q_OS_WASM
// WebGL 2.0 specification explicitly does not support texture swizzles
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.19
extensions |= QOpenGLExtensions::TextureSwizzle;
#endif
} else { } else {
// Recognize features by extension name. // Recognize features by extension name.
if (extensionMatcher.match("GL_OES_packed_depth_stencil")) if (extensionMatcher.match("GL_OES_packed_depth_stencil"))

View File

@ -303,6 +303,7 @@ inline qreal QTransform::dy() const
QT_WARNING_PUSH QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
inline QTransform &QTransform::operator*=(qreal num) inline QTransform &QTransform::operator*=(qreal num)
{ {

View File

@ -3142,8 +3142,7 @@ bool QGles2RenderBuffer::build()
switch (m_type) { switch (m_type) {
case QRhiRenderBuffer::DepthStencil: case QRhiRenderBuffer::DepthStencil:
if (rhiD->caps.msaaRenderBuffer && samples > 1) { if (rhiD->caps.msaaRenderBuffer && samples > 1) {
const GLenum storage = rhiD->caps.needsDepthStencilCombinedAttach ? GL_DEPTH_STENCIL : GL_DEPTH24_STENCIL8; rhiD->f->glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8,
rhiD->f->glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, storage,
size.width(), size.height()); size.width(), size.height());
stencilRenderbuffer = 0; stencilRenderbuffer = 0;
} else if (rhiD->caps.packedDepthStencil || rhiD->caps.needsDepthStencilCombinedAttach) { } else if (rhiD->caps.packedDepthStencil || rhiD->caps.needsDepthStencilCombinedAttach) {

View File

@ -48,7 +48,7 @@
#include <qmath.h> #include <qmath.h>
#include <QVulkanFunctions> #include <QVulkanFunctions>
#include <QVulkanWindow> #include <QtGui/qwindow.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -92,6 +92,7 @@
#endif #endif
#include <algorithm> #include <algorithm>
#include <memory>
#include <string.h> #include <string.h>
@ -2169,6 +2170,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
errors << QSslError(QSslError::UnspecifiedError); errors << QSslError(QSslError::UnspecifiedError);
return errors; return errors;
} }
const std::unique_ptr<X509_STORE, decltype(&q_X509_STORE_free)> storeGuard(certStore, q_X509_STORE_free);
if (s_loadRootCertsOnDemand) { if (s_loadRootCertsOnDemand) {
setDefaultCaCertificates(defaultCaCertificates() + systemCaCertificates()); setDefaultCaCertificates(defaultCaCertificates() + systemCaCertificates());
@ -2209,7 +2211,6 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null(); intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null();
if (!intermediates) { if (!intermediates) {
q_X509_STORE_free(certStore);
errors << QSslError(QSslError::UnspecifiedError); errors << QSslError(QSslError::UnspecifiedError);
return errors; return errors;
} }
@ -2227,14 +2228,12 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
X509_STORE_CTX *storeContext = q_X509_STORE_CTX_new(); X509_STORE_CTX *storeContext = q_X509_STORE_CTX_new();
if (!storeContext) { if (!storeContext) {
q_X509_STORE_free(certStore);
errors << QSslError(QSslError::UnspecifiedError); errors << QSslError(QSslError::UnspecifiedError);
return errors; return errors;
} }
std::unique_ptr<X509_STORE_CTX, decltype(&q_X509_STORE_CTX_free)> ctxGuard(storeContext, q_X509_STORE_CTX_free);
if (!q_X509_STORE_CTX_init(storeContext, certStore, reinterpret_cast<X509 *>(certificateChain[0].handle()), intermediates)) { if (!q_X509_STORE_CTX_init(storeContext, certStore, reinterpret_cast<X509 *>(certificateChain[0].handle()), intermediates)) {
q_X509_STORE_CTX_free(storeContext);
q_X509_STORE_free(certStore);
errors << QSslError(QSslError::UnspecifiedError); errors << QSslError(QSslError::UnspecifiedError);
return errors; return errors;
} }
@ -2243,8 +2242,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
// We ignore the result of this function since we process errors via the // We ignore the result of this function since we process errors via the
// callback. // callback.
(void) q_X509_verify_cert(storeContext); (void) q_X509_verify_cert(storeContext);
ctxGuard.reset();
q_X509_STORE_CTX_free(storeContext);
q_OPENSSL_sk_free((OPENSSL_STACK *)intermediates); q_OPENSSL_sk_free((OPENSSL_STACK *)intermediates);
// Now process the errors // Now process the errors
@ -2266,8 +2264,6 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
for (const auto &error : qAsConst(lastErrors)) for (const auto &error : qAsConst(lastErrors))
errors << _q_OpenSSL_to_QSslError(error.code, certificateChain.value(error.depth)); errors << _q_OpenSSL_to_QSslError(error.code, certificateChain.value(error.depth));
q_X509_STORE_free(certStore);
return errors; return errors;
} }

View File

@ -374,17 +374,6 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>::fontEngine
QCFType<CTFontDescriptorRef> descriptor = QCFType<CTFontDescriptorRef>::constructFromGet( QCFType<CTFontDescriptorRef> descriptor = QCFType<CTFontDescriptorRef>::constructFromGet(
static_cast<CTFontDescriptorRef>(usrPtr)); static_cast<CTFontDescriptorRef>(usrPtr));
// CoreText will sometimes invalidate information in font descriptors that refer
// to system fonts in certain function calls or application states. While the descriptor
// looks the same from the outside, some internal plumbing is different, causing the results
// of creating CTFonts from those descriptors unreliable. The work-around for this
// is to copy the attributes of those descriptors each time we make a new CTFont
// from them instead of referring to the original, as that may trigger the CoreText bug.
if (m_systemFontDescriptors.contains(descriptor)) {
QCFType<CFDictionaryRef> attributes = CTFontDescriptorCopyAttributes(descriptor);
descriptor = CTFontDescriptorCreateWithAttributes(attributes);
}
// Since we do not pass in the destination DPI to CoreText when making // Since we do not pass in the destination DPI to CoreText when making
// the font, we need to pass in a point size which is scaled to include // the font, we need to pass in a point size which is scaled to include
// the DPI. The default DPI for the screen is 72, thus the scale factor // the DPI. The default DPI for the screen is 72, thus the scale factor

View File

@ -11,7 +11,7 @@ SUBDIRS = \
qtConfig(freetype)|darwin|win32: \ qtConfig(freetype)|darwin|win32: \
SUBDIRS += fontdatabases SUBDIRS += fontdatabases
qtConfig(evdev)|qtConfig(tslib)|qtConfig(libinput)|qtConfig(integrityhid) { qtConfig(evdev)|qtConfig(tslib)|qtConfig(libinput)|qtConfig(integrityhid)|qtConfig(xkbcommon) {
SUBDIRS += input SUBDIRS += input
input.depends += devicediscovery input.depends += devicediscovery
} }

View File

@ -87,6 +87,11 @@ qtConfig(accessibility) {
qcocoaaccessibility.h qcocoaaccessibility.h
} }
qtConfig(sessionmanager) {
SOURCES += qcocoasessionmanager.cpp
HEADERS += qcocoasessionmanager.h
}
RESOURCES += qcocoaresources.qrc RESOURCES += qcocoaresources.qrc
LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -framework IOSurface -lcups LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -framework IOSurface -lcups

View File

@ -133,7 +133,7 @@ static void populateRoleMap()
roleMap[QAccessible::SpinBox] = NSAccessibilityIncrementorRole; roleMap[QAccessible::SpinBox] = NSAccessibilityIncrementorRole;
roleMap[QAccessible::Slider] = NSAccessibilitySliderRole; roleMap[QAccessible::Slider] = NSAccessibilitySliderRole;
roleMap[QAccessible::ProgressBar] = NSAccessibilityProgressIndicatorRole; roleMap[QAccessible::ProgressBar] = NSAccessibilityProgressIndicatorRole;
roleMap[QAccessible::ComboBox] = NSAccessibilityPopUpButtonRole; roleMap[QAccessible::ComboBox] = NSAccessibilityComboBoxRole;
roleMap[QAccessible::RadioButton] = NSAccessibilityRadioButtonRole; roleMap[QAccessible::RadioButton] = NSAccessibilityRadioButtonRole;
roleMap[QAccessible::CheckBox] = NSAccessibilityCheckBoxRole; roleMap[QAccessible::CheckBox] = NSAccessibilityCheckBoxRole;
roleMap[QAccessible::StaticText] = NSAccessibilityStaticTextRole; roleMap[QAccessible::StaticText] = NSAccessibilityStaticTextRole;

View File

@ -79,11 +79,14 @@
#include "qcocoamenuitem.h" #include "qcocoamenuitem.h"
#include "qcocoansmenu.h" #include "qcocoansmenu.h"
#if QT_CONFIG(sessionmanager)
# include "qcocoasessionmanager.h"
#endif
#include <qevent.h> #include <qevent.h>
#include <qurl.h> #include <qurl.h>
#include <qdebug.h> #include <qdebug.h>
#include <qguiapplication.h> #include <qguiapplication.h>
#include <private/qguiapplication_p.h>
#include "qt_mac_p.h" #include "qt_mac_p.h"
#include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface.h>
#include <qwindowdefs.h> #include <qwindowdefs.h>
@ -157,6 +160,17 @@ QT_USE_NAMESPACE
return NSTerminateNow; return NSTerminateNow;
} }
#if QT_CONFIG(sessionmanager)
QCocoaSessionManager *cocoaSessionManager = QCocoaSessionManager::instance();
cocoaSessionManager->resetCancellation();
cocoaSessionManager->appCommitData();
if (cocoaSessionManager->wasCanceled()) {
qCDebug(lcQpaApplication) << "Session management canceled application termination";
return NSTerminateCancel;
}
#endif
if (!QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>()) { if (!QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>()) {
qCDebug(lcQpaApplication) << "Application termination canceled"; qCDebug(lcQpaApplication) << "Application termination canceled";
return NSTerminateCancel; return NSTerminateCancel;

View File

@ -134,7 +134,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
NSImage *nsimage = qt_mac_create_nsimage(pm); NSImage *nsimage = qt_mac_create_nsimage(pm);
[nsimage setSize:NSSizeFromCGSize(pmDeviceIndependentSize.toCGSize())]; [nsimage setSize:NSSizeFromCGSize(pmDeviceIndependentSize.toCGSize())];
QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacInternalPasteboardMime::MIME_DND); QMacPasteboard dragBoard(CFStringRef(NSPasteboardNameDrag), QMacInternalPasteboardMime::MIME_DND);
m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy")); m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy"));
dragBoard.setMimeData(m_drag->mimeData(), QMacPasteboard::LazyRequest); dragBoard.setMimeData(m_drag->mimeData(), QMacPasteboard::LazyRequest);
@ -145,7 +145,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
CGFloat flippedY = pmDeviceIndependentSize.height() - hotSpot.y(); CGFloat flippedY = pmDeviceIndependentSize.height() - hotSpot.y();
event_location.y -= flippedY; event_location.y -= flippedY;
NSSize mouseOffset_unused = NSMakeSize(0.0, 0.0); NSSize mouseOffset_unused = NSMakeSize(0.0, 0.0);
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSPasteboardNameDrag];
[theWindow dragImage:nsimage [theWindow dragImage:nsimage
at:event_location at:event_location

View File

@ -92,6 +92,10 @@ public:
QCocoaVulkanInstance *getCocoaVulkanInstance() const; QCocoaVulkanInstance *getCocoaVulkanInstance() const;
#endif #endif
#if QT_CONFIG(sessionmanager)
QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const override;
#endif
QCoreTextFontDatabase *fontDatabase() const override; QCoreTextFontDatabase *fontDatabase() const override;
QCocoaNativeInterface *nativeInterface() const override; QCocoaNativeInterface *nativeInterface() const override;
QPlatformInputContext *inputContext() const override; QPlatformInputContext *inputContext() const override;

View File

@ -52,6 +52,9 @@
#include "qcocoamimetypes.h" #include "qcocoamimetypes.h"
#include "qcocoaaccessibility.h" #include "qcocoaaccessibility.h"
#include "qcocoascreen.h" #include "qcocoascreen.h"
#if QT_CONFIG(sessionmanager)
# include "qcocoasessionmanager.h"
#endif
#include <qpa/qplatforminputcontextfactory_p.h> #include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatformaccessibility.h> #include <qpa/qplatformaccessibility.h>
@ -197,16 +200,6 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
[cocoaApplication setMenu:[qtMenuLoader menu]]; [cocoaApplication setMenu:[qtMenuLoader menu]];
} }
// The presentation options such as whether or not the dock and/or menu bar is
// hidden (automatically by the system) affects the main screen's available
// geometry. Since we're initializing the screens synchronously at application
// startup we need to ensure that the presentation options have been propagated
// to the screen before we read out its properties. Normally OS X does this in
// an asynchronous callback, but that's too late for us. We force the propagation
// by explicitly setting the presentation option to the magic 'default value',
// which will resolve to an actual value and result in screen invalidation.
cocoaApplication.presentationOptions = NSApplicationPresentationDefault;
QCocoaScreen::initializeScreens(); QCocoaScreen::initializeScreens();
QMacInternalPasteboardMime::initializeMimeTypes(); QMacInternalPasteboardMime::initializeMimeTypes();
@ -255,6 +248,13 @@ QCocoaIntegration::Options QCocoaIntegration::options() const
return mOptions; return mOptions;
} }
#if QT_CONFIG(sessionmanager)
QPlatformSessionManager *QCocoaIntegration::createPlatformSessionManager(const QString &id, const QString &key) const
{
return new QCocoaSessionManager(id, key);
}
#endif
bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{ {
switch (cap) { switch (cap) {

View File

@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2019 Samuel Gaist <samuel.gaist@idiap.ch>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QT_NO_SESSIONMANAGER
#include <private/qsessionmanager_p.h>
#include <private/qguiapplication_p.h>
#include <qcocoasessionmanager.h>
#include <qstring.h>
QT_BEGIN_NAMESPACE
QCocoaSessionManager::QCocoaSessionManager(const QString &id, const QString &key)
: QPlatformSessionManager(id, key),
m_canceled(false)
{
}
QCocoaSessionManager::~QCocoaSessionManager()
{
}
bool QCocoaSessionManager::allowsInteraction()
{
return false;
}
void QCocoaSessionManager::resetCancellation()
{
m_canceled = false;
}
void QCocoaSessionManager::cancel()
{
m_canceled = true;
}
bool QCocoaSessionManager::wasCanceled() const
{
return m_canceled;
}
QCocoaSessionManager *QCocoaSessionManager::instance()
{
auto *qGuiAppPriv = QGuiApplicationPrivate::instance();
auto *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(qGuiAppPriv->session_manager));
return static_cast<QCocoaSessionManager *>(managerPrivate->platformSessionManager);
}
QT_END_NAMESPACE
#endif // QT_NO_SESSIONMANAGER

View File

@ -0,0 +1,81 @@
/****************************************************************************
**
** Copyright (C) 2019 Samuel Gaist <samuel.gaist@idiap.ch>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QCOCOASESSIONMANAGER_H
#define QCOCOASESSIONMANAGER_H
//
// W A R N I N G
// -------------
//
// This file is part of the QPA API and is not meant to be used
// in applications. Usage of this API may make your code
// source and binary incompatible with future versions of Qt.
//
#ifndef QT_NO_SESSIONMANAGER
#include <qpa/qplatformsessionmanager.h>
QT_BEGIN_NAMESPACE
class QCocoaSessionManager : public QPlatformSessionManager
{
public:
QCocoaSessionManager(const QString &id, const QString &key);
virtual ~QCocoaSessionManager();
bool allowsInteraction() override;
void cancel() override;
void resetCancellation();
bool wasCanceled() const;
static QCocoaSessionManager *instance();
private:
bool m_canceled;
Q_DISABLE_COPY(QCocoaSessionManager)
};
QT_END_NAMESPACE
#endif // QT_NO_SESSIONMANAGER
#endif // QCOCOASESSIONMANAGER_H

View File

@ -1689,9 +1689,9 @@ void QCocoaWindow::registerTouch(bool enable)
{ {
m_registerTouchCount += enable ? 1 : -1; m_registerTouchCount += enable ? 1 : -1;
if (enable && m_registerTouchCount == 1) if (enable && m_registerTouchCount == 1)
[m_view setAcceptsTouchEvents:YES]; m_view.allowedTouchTypes |= NSTouchTypeMaskIndirect;
else if (m_registerTouchCount == 0) else if (m_registerTouchCount == 0)
[m_view setAcceptsTouchEvents:NO]; m_view.allowedTouchTypes &= ~NSTouchTypeMaskIndirect;
} }
void QCocoaWindow::setContentBorderThickness(int topThickness, int bottomThickness) void QCocoaWindow::setContentBorderThickness(int topThickness, int bottomThickness)

View File

@ -781,12 +781,16 @@
- (UIView *)textInputView - (UIView *)textInputView
{ {
auto *focusWindow = QGuiApplication::focusWindow();
if (!focusWindow)
return nil;
// iOS expects rects we return from other UITextInput methods // iOS expects rects we return from other UITextInput methods
// to be relative to the view this method returns. // to be relative to the view this method returns.
// Since QInputMethod returns rects relative to the top level // Since QInputMethod returns rects relative to the top level
// QWindow, that is also the view we need to return. // QWindow, that is also the view we need to return.
Q_ASSERT(qApp->focusWindow()->handle()); Q_ASSERT(focusWindow->handle());
QPlatformWindow *topLevel = qApp->focusWindow()->handle(); QPlatformWindow *topLevel = focusWindow->handle();
while (QPlatformWindow *p = topLevel->parent()) while (QPlatformWindow *p = topLevel->parent())
topLevel = p; topLevel = p;
return reinterpret_cast<UIView *>(topLevel->winId()); return reinterpret_cast<UIView *>(topLevel->winId());

View File

@ -283,8 +283,11 @@ void QWindowsInputContext::showInputPanel()
// We only call ShowCaret() on Windows 10 after 1703 as in earlier versions // We only call ShowCaret() on Windows 10 after 1703 as in earlier versions
// the caret would actually be visible (QTBUG-74492) and the workaround for // the caret would actually be visible (QTBUG-74492) and the workaround for
// the Surface seems unnecessary there anyway. But leave it hidden for IME. // the Surface seems unnecessary there anyway. But leave it hidden for IME.
if (QOperatingSystemVersion::current() >= // Only trigger the native OSK if the Qt OSK is not in use.
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 16299)) { static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE");
if (imModuleEmpty
&& QOperatingSystemVersion::current()
>= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 16299)) {
ShowCaret(platformWindow->handle()); ShowCaret(platformWindow->handle());
} else { } else {
HideCaret(platformWindow->handle()); HideCaret(platformWindow->handle());

View File

@ -390,7 +390,17 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
setVariantI4(UIA_WindowControlTypeId, pRetVal); setVariantI4(UIA_WindowControlTypeId, pRetVal);
} else { } else {
// Control type converted from role. // Control type converted from role.
setVariantI4(roleToControlTypeId(accessible->role()), pRetVal); auto controlType = roleToControlTypeId(accessible->role());
// The native OSK should be disbled if the Qt OSK is in use.
static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE");
// If we want to disable the native OSK auto-showing
// we have to report text fields as non-editable.
if (controlType == UIA_EditControlTypeId && !imModuleEmpty)
controlType = UIA_TextControlTypeId;
setVariantI4(controlType, pRetVal);
} }
break; break;
case UIA_HelpTextPropertyId: case UIA_HelpTextPropertyId:

View File

@ -1388,14 +1388,22 @@ void QMacStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widg
// High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize // High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize
tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height())); tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height()));
*iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2, const int stylePadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2 - hpadding;
tabIconSize.width(), tabIconSize.height());
if (opt->documentMode) {
// documents show the icon as part of the the text
const int textWidth =
opt->fontMetrics.boundingRect(tr, Qt::AlignCenter | Qt::TextShowMnemonic, opt->text).width();
*iconRect = QRect(tr.center().x() - textWidth / 2 - stylePadding - tabIconSize.width(),
tr.center().y() - tabIconSize.height() / 2,
tabIconSize.width(), tabIconSize.height());
} else {
*iconRect = QRect(tr.left() + stylePadding, tr.center().y() - tabIconSize.height() / 2,
tabIconSize.width(), tabIconSize.height());
}
if (!verticalTabs) if (!verticalTabs)
*iconRect = proxyStyle->visualRect(opt->direction, opt->rect, *iconRect); *iconRect = proxyStyle->visualRect(opt->direction, opt->rect, *iconRect);
int stylePadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2;
stylePadding -= hpadding;
tr.setLeft(tr.left() + stylePadding + tabIconSize.width() + 4); tr.setLeft(tr.left() + stylePadding + tabIconSize.width() + 4);
tr.setRight(tr.right() - stylePadding - tabIconSize.width() - 4); tr.setRight(tr.right() - stylePadding - tabIconSize.width() - 4);
} }

View File

@ -284,7 +284,7 @@ public:
CocoaControlType windowButtonCocoaControl(QStyle::SubControl sc) const; CocoaControlType windowButtonCocoaControl(QStyle::SubControl sc) const;
#if QT_CONFIG(tabbar) #if QT_CONFIG(tabbar)
void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const; void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const override;
static Direction tabDirection(QTabBar::Shape shape); static Direction tabDirection(QTabBar::Shape shape);
static bool verticalTabs(QMacStylePrivate::Direction tabDirection); static bool verticalTabs(QMacStylePrivate::Direction tabDirection);
#endif #endif

View File

@ -41,7 +41,7 @@ include(CMakeParseArguments)
# qt5_wrap_ui(outfiles inputfile ... ) # qt5_wrap_ui(outfiles inputfile ... )
function(QT5_WRAP_UI outfiles ) function(qt5_wrap_ui outfiles )
set(options) set(options)
set(oneValueArgs) set(oneValueArgs)
set(multiValueArgs OPTIONS) set(multiValueArgs OPTIONS)

View File

@ -1892,6 +1892,8 @@ void QTreeView::mousePressEvent(QMouseEvent *event)
handled = d->expandOrCollapseItemAtPos(event->pos()); handled = d->expandOrCollapseItemAtPos(event->pos());
if (!handled && d->itemDecorationAt(event->pos()) == -1) if (!handled && d->itemDecorationAt(event->pos()) == -1)
QAbstractItemView::mousePressEvent(event); QAbstractItemView::mousePressEvent(event);
else
d->pressedIndex = QModelIndex();
} }
/*! /*!

View File

@ -7002,8 +7002,10 @@ void QWidget::resize(const QSize &s)
d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false); d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
d->setDirtyOpaqueRegion(); d->setDirtyOpaqueRegion();
} else { } else {
const auto oldRect = data->crect;
data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize())); data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
setAttribute(Qt::WA_PendingResizeEvent); if (oldRect != data->crect)
setAttribute(Qt::WA_PendingResizeEvent);
} }
} }
@ -7018,10 +7020,13 @@ void QWidget::setGeometry(const QRect &r)
d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true); d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
d->setDirtyOpaqueRegion(); d->setDirtyOpaqueRegion();
} else { } else {
const auto oldRect = data->crect;
data->crect.setTopLeft(r.topLeft()); data->crect.setTopLeft(r.topLeft());
data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize())); data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
setAttribute(Qt::WA_PendingMoveEvent); if (oldRect != data->crect) {
setAttribute(Qt::WA_PendingResizeEvent); setAttribute(Qt::WA_PendingMoveEvent);
setAttribute(Qt::WA_PendingResizeEvent);
}
} }
if (d->extra && d->extra->hasWindowContainer) if (d->extra && d->extra->hasWindowContainer)

View File

@ -122,7 +122,7 @@ public:
mutable QIcon tabBarcloseButtonIcon; mutable QIcon tabBarcloseButtonIcon;
#if QT_CONFIG(tabbar) #if QT_CONFIG(tabbar)
void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const; virtual void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const;
#endif #endif
int animationFps; int animationFps;

View File

@ -274,6 +274,12 @@ void drawDial(const QStyleOptionSlider *option, QPainter *painter)
painter->drawLines(QStyleHelper::calcLines(option)); painter->drawLines(QStyleHelper::calcLines(option));
} }
// setting color before BEGIN_STYLE_PIXMAPCACHE since
// otherwise it is not set when the image is in the cache
buttonColor.setHsv(buttonColor .hue(),
qMin(140, buttonColor .saturation()),
qMax(180, buttonColor.value()));
// Cache dial background // Cache dial background
BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("qdial")); BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("qdial"));
p->setRenderHint(QPainter::Antialiasing); p->setRenderHint(QPainter::Antialiasing);
@ -285,9 +291,6 @@ void drawDial(const QStyleOptionSlider *option, QPainter *painter)
QRectF br = QRectF(dx + 0.5, dy + 0.5, QRectF br = QRectF(dx + 0.5, dy + 0.5,
int(r * 2 - 2 * d_ - 2), int(r * 2 - 2 * d_ - 2),
int(r * 2 - 2 * d_ - 2)); int(r * 2 - 2 * d_ - 2));
buttonColor.setHsv(buttonColor .hue(),
qMin(140, buttonColor .saturation()),
qMax(180, buttonColor.value()));
if (enabled) { if (enabled) {
// Drop shadow // Drop shadow

View File

@ -1200,12 +1200,18 @@ QMargins QLineEdit::textMargins() const
Unset the mask and return to normal QLineEdit operation by passing Unset the mask and return to normal QLineEdit operation by passing
an empty string (""). an empty string ("").
The table below shows the characters that can be used in an input mask. The input mask is an input template string. It can contain the following elements:
A space character, the default character for a blank, is needed for cases \table
where a character is \e{permitted but not required}. \row \li Mask Characters \li Defines the class of input characters that are
considered valid in this position
\row \li Meta Characters \li Various special meanings
\row \li Separators \li All other characters are regarded as immutable separators
\endtable
The following table shows the mask and meta characters that can be used in an input mask.
\table \table
\header \li Character \li Meaning \header \li Mask Character \li Meaning
\row \li \c A \li ASCII alphabetic character required. A-Z, a-z. \row \li \c A \li ASCII alphabetic character required. A-Z, a-z.
\row \li \c a \li ASCII alphabetic character permitted but not required. \row \li \c a \li ASCII alphabetic character permitted but not required.
\row \li \c N \li ASCII alphanumeric character required. A-Z, a-z, 0-9. \row \li \c N \li ASCII alphanumeric character required. A-Z, a-z, 0-9.
@ -1221,19 +1227,28 @@ QMargins QLineEdit::textMargins() const
\row \li \c h \li Hexadecimal character permitted but not required. \row \li \c h \li Hexadecimal character permitted but not required.
\row \li \c B \li Binary character required. 0-1. \row \li \c B \li Binary character required. 0-1.
\row \li \c b \li Binary character permitted but not required. \row \li \c b \li Binary character permitted but not required.
\header \li Meta Character \li Meaning
\row \li \c > \li All following alphabetic characters are uppercased. \row \li \c > \li All following alphabetic characters are uppercased.
\row \li \c < \li All following alphabetic characters are lowercased. \row \li \c < \li All following alphabetic characters are lowercased.
\row \li \c ! \li Switch off case conversion. \row \li \c ! \li Switch off case conversion.
\row \li \c {;c} \li Terminates the input mask and sets the \e{blank} character to \e{c}.
\row \li \c {[ ] { }} \li Reserved. \row \li \c {[ ] { }} \li Reserved.
\row \li \tt{\\} \li Use \tt{\\} to escape the special \row \li \tt{\\} \li Use \tt{\\} to escape the special
characters listed above to use them as characters listed above to use them as
separators. separators.
\endtable \endtable
The mask consists of a string of mask characters and separators, When created or cleared, the line edit will be filled with a copy of the
optionally followed by a semicolon and the character used for input mask string where the meta characters have been removed, and the mask
blanks. The blank characters are always removed from the text characters have been replaced with the \e{blank} character (by default, a
after editing. \c space).
When an input mask is set, the text() method returns a modified copy of the
line edit content where all the \e{blank} characters have been removed. The
unmodified content can be read using displayText().
The hasAcceptableInput() method returns false if the current content of the
line edit does not fulfil the requirements of the input mask.
Examples: Examples:
\table \table
@ -1242,7 +1257,7 @@ QMargins QLineEdit::textMargins() const
\row \li \c HH:HH:HH:HH:HH:HH;_ \li MAC address \row \li \c HH:HH:HH:HH:HH:HH;_ \li MAC address
\row \li \c 0000-00-00 \li ISO Date; blanks are \c space \row \li \c 0000-00-00 \li ISO Date; blanks are \c space
\row \li \c >AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;# \li License number; \row \li \c >AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;# \li License number;
blanks are \c - and all (alphabetic) characters are converted to blanks are \c{#} and all (alphabetic) characters are converted to
uppercase. uppercase.
\endtable \endtable

View File

@ -40,6 +40,7 @@
#include <QtCore/qcborvalue.h> #include <QtCore/qcborvalue.h>
#include <QtTest> #include <QtTest>
Q_DECLARE_METATYPE(QCborKnownTags)
Q_DECLARE_METATYPE(QCborValue) Q_DECLARE_METATYPE(QCborValue)
Q_DECLARE_METATYPE(QCborValue::EncodingOptions) Q_DECLARE_METATYPE(QCborValue::EncodingOptions)
@ -294,34 +295,77 @@ void tst_QCborValue::tagged()
void tst_QCborValue::extendedTypes_data() void tst_QCborValue::extendedTypes_data()
{ {
QTest::addColumn<QCborValue>("extended"); QTest::addColumn<QCborValue>("extended");
QTest::addColumn<QCborValue>("tagged"); QTest::addColumn<QCborKnownTags>("tag");
QTest::addColumn<QCborValue>("taggedValue");
QTest::addColumn<QCborValue>("correctedTaggedValue");
QCborValue v(QCborValue::Invalid);
QDateTime dt = QDateTime::currentDateTimeUtc(); QDateTime dt = QDateTime::currentDateTimeUtc();
QDateTime dtTzOffset(dt.date(), dt.time(), Qt::OffsetFromUTC, dt.offsetFromUtc());
QUuid uuid = QUuid::createUuid(); QUuid uuid = QUuid::createUuid();
// non-correcting extended types (tagged value remains unchanged)
QTest::newRow("DateTime") << QCborValue(dt) QTest::newRow("DateTime") << QCborValue(dt)
<< QCborValue(QCborKnownTags::DateTimeString, dt.toString(Qt::ISODateWithMs)); << QCborKnownTags::DateTimeString << QCborValue(dt.toString(Qt::ISODateWithMs)) << v;
QTest::newRow("DateTime:TzOffset") << QCborValue(dtTzOffset)
<< QCborKnownTags::DateTimeString << QCborValue(dtTzOffset.toString(Qt::ISODateWithMs)) << v;
QTest::newRow("Url:Empty") << QCborValue(QUrl()) QTest::newRow("Url:Empty") << QCborValue(QUrl())
<< QCborValue(QCborKnownTags::Url, QString()); << QCborKnownTags::Url << QCborValue(QString()) << v;
QTest::newRow("Url:Authority") << QCborValue(QUrl("https://example.com")) QTest::newRow("Url:Authority") << QCborValue(QUrl("https://example.com"))
<< QCborValue(QCborKnownTags::Url, "https://example.com"); << QCborKnownTags::Url << QCborValue("https://example.com") << v;
QTest::newRow("Url:Path") << QCborValue(QUrl("file:///tmp/none")) QTest::newRow("Url:Path") << QCborValue(QUrl("file:///tmp/none"))
<< QCborValue(QCborKnownTags::Url, "file:///tmp/none"); << QCborKnownTags::Url << QCborValue("file:///tmp/none") << v;
QTest::newRow("Url:QueryFragment") << QCborValue(QUrl("whatever:?a=b&c=d#e")) QTest::newRow("Url:QueryFragment") << QCborValue(QUrl("whatever:?a=b&c=d#e"))
<< QCborValue(QCborKnownTags::Url, "whatever:?a=b&c=d#e"); << QCborKnownTags::Url << QCborValue("whatever:?a=b&c=d#e") << v;
QTest::newRow("Regex:Empty") << QCborValue(QRegularExpression()) QTest::newRow("Regex:Empty") << QCborValue(QRegularExpression())
<< QCborValue(QCborKnownTags::RegularExpression, QString()); << QCborKnownTags::RegularExpression << QCborValue(QString()) << v;
QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$")) QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$"))
<< QCborValue(QCborKnownTags::RegularExpression, QString("^.*$")); << QCborKnownTags::RegularExpression << QCborValue(QString("^.*$")) << v;
QTest::newRow("Uuid") << QCborValue(uuid) QTest::newRow("Uuid") << QCborValue(uuid)
<< QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122()); << QCborKnownTags::Uuid << QCborValue(uuid.toRfc4122()) << v;
// correcting extended types
QDateTime dtNoMsecs = dt.fromSecsSinceEpoch(dt.toSecsSinceEpoch(), Qt::UTC);
QUrl url("https://example.com/\xc2\xa9 ");
QTest::newRow("UnixTime_t:Integer") << QCborValue(dtNoMsecs) << QCborKnownTags::UnixTime_t
<< QCborValue(dtNoMsecs.toSecsSinceEpoch())
<< QCborValue(dtNoMsecs.toString(Qt::ISODateWithMs));
QTest::newRow("UnixTime_t:Double") << QCborValue(dt) << QCborKnownTags::UnixTime_t
<< QCborValue(dt.toMSecsSinceEpoch() / 1000.)
<< QCborValue(dt.toString(Qt::ISODateWithMs));
QTest::newRow("DateTime::JustDate") << QCborValue(QDateTime({2018, 1, 1}, {}))
<< QCborKnownTags::DateTimeString
<< QCborValue("2018-01-01") << QCborValue("2018-01-01T00:00:00.000");
QTest::newRow("DateTime::TzOffset") << QCborValue(QDateTime({2018, 1, 1}, {9, 0, 0}, Qt::UTC))
<< QCborKnownTags::DateTimeString
<< QCborValue("2018-01-01T09:00:00.000+00:00")
<< QCborValue("2018-01-01T09:00:00.000Z");
QTest::newRow("Url:NotNormalized") << QCborValue(url) << QCborKnownTags::Url
<< QCborValue("HTTPS://EXAMPLE.COM/%c2%a9%20")
<< QCborValue(url.toString());
QTest::newRow("Uuid:Zero") << QCborValue(QUuid()) << QCborKnownTags::Uuid
<< QCborValue(QByteArray())
<< QCborValue(QByteArray(sizeof(QUuid), 0));
QTest::newRow("Uuid:TooShort") << QCborValue(QUuid(0x12345678, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
<< QCborKnownTags::Uuid
<< QCborValue(raw("\x12\x34\x56\x78"))
<< QCborValue(raw("\x12\x34\x56\x78" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0"));
QTest::newRow("Uuid:TooLong") << QCborValue(uuid) << QCborKnownTags::Uuid
<< QCborValue(uuid.toRfc4122() + "\1\2\3\4") << QCborValue(uuid.toRfc4122());
} }
void tst_QCborValue::extendedTypes() void tst_QCborValue::extendedTypes()
{ {
QFETCH(QCborValue, extended); QFETCH(QCborValue, extended);
QFETCH(QCborValue, tagged); QFETCH(QCborKnownTags, tag);
QFETCH(QCborValue, taggedValue);
QFETCH(QCborValue, correctedTaggedValue);
if (correctedTaggedValue.isInvalid())
correctedTaggedValue = taggedValue;
QCborValue tagged(tag, taggedValue);
QVERIFY(extended.isTag()); QVERIFY(extended.isTag());
QVERIFY(tagged.isTag()); QVERIFY(tagged.isTag());
QCOMPARE(tagged.taggedValue(), correctedTaggedValue);
QVERIFY(extended == tagged); QVERIFY(extended == tagged);
QVERIFY(tagged == extended); QVERIFY(tagged == extended);
@ -1224,8 +1268,11 @@ void tst_QCborValue::sorting()
QCborValue va1(QCborValue::Array), va2(QCborArray{1}), va3(QCborArray{0, 0}); QCborValue va1(QCborValue::Array), va2(QCborArray{1}), va3(QCborArray{0, 0});
QCborValue vm1(QCborValue::Map), vm2(QCborMap{{1, 0}}), vm3(QCborMap{{0, 0}, {1, 0}}); QCborValue vm1(QCborValue::Map), vm2(QCborMap{{1, 0}}), vm3(QCborMap{{0, 0}, {1, 0}});
QCborValue vdt1(QDateTime::fromMSecsSinceEpoch(0, Qt::UTC)), vdt2(QDateTime::currentDateTimeUtc()); QCborValue vdt1(QDateTime::fromMSecsSinceEpoch(0, Qt::UTC)), vdt2(QDateTime::currentDateTimeUtc());
QCborValue vtagged1(QCborKnownTags::UnixTime_t, 0), vtagged2(QCborKnownTags::UnixTime_t, 0.0), QCborValue vtagged1(QCborKnownTags::PositiveBignum, QByteArray()),
vtagged3(QCborKnownTags::Signature, 0), vtagged4(QCborTag(-2), 0), vtagged5(QCborTag(-1), 0); vtagged2(QCborKnownTags::PositiveBignum, 0.0), // bignums are supposed to have byte arrays...
vtagged3(QCborKnownTags::Signature, 0),
vtagged4(QCborTag(-2), 0),
vtagged5(QCborTag(-1), 0);
QCborValue vurl1(QUrl("https://example.net")), vurl2(QUrl("https://example.com/")); QCborValue vurl1(QUrl("https://example.net")), vurl2(QUrl("https://example.com/"));
QCborValue vuuid1{QUuid()}, vuuid2(QUuid::createUuid()); QCborValue vuuid1{QUuid()}, vuuid2(QUuid::createUuid());
QCborValue vsimple1(QCborSimpleType(1)), vsimple32(QCborSimpleType(32)), vsimple255(QCborSimpleType(255)); QCborValue vsimple1(QCborSimpleType(1)), vsimple32(QCborSimpleType(32)), vsimple255(QCborSimpleType(255));
@ -1391,6 +1438,9 @@ static void addCommonCborData()
QTest::newRow("Url") << QCborValue(QUrl("HTTPS://example.com/{%30%31}?q=%3Ca+b%20%C2%A9%3E&%26")) QTest::newRow("Url") << QCborValue(QUrl("HTTPS://example.com/{%30%31}?q=%3Ca+b%20%C2%A9%3E&%26"))
<< raw("\xd8\x20\x78\x27" "https://example.com/{01}?q=<a+b \xC2\xA9>&%26") << raw("\xd8\x20\x78\x27" "https://example.com/{01}?q=<a+b \xC2\xA9>&%26")
<< noxfrm; << noxfrm;
QTest::newRow("Url:NonAscii") << QCborValue(QUrl("https://example.com/\xc2\xa0"))
<< raw("\xd8\x20\x76" "https://example.com/\xc2\xa0")
<< noxfrm;
QTest::newRow("Regex:Empty") << QCborValue(QRegularExpression()) << raw("\xd8\x23\x60") << noxfrm; QTest::newRow("Regex:Empty") << QCborValue(QRegularExpression()) << raw("\xd8\x23\x60") << noxfrm;
QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$")) QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$"))
<< raw("\xd8\x23\x64" "^.*$") << noxfrm; << raw("\xd8\x23\x64" "^.*$") << noxfrm;

View File

@ -1136,8 +1136,14 @@ void tst_QDate::fromStringDateFormat_data()
// Test Qt::RFC2822Date format (RFC 2822). // Test Qt::RFC2822Date format (RFC 2822).
QTest::newRow("RFC 2822") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100") QTest::newRow("RFC 2822") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDate(1987, 2, 13); << Qt::RFC2822Date << QDate(1987, 2, 13);
QTest::newRow("RFC 2822 after space")
<< QString::fromLatin1(" 13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDate(1987, 2, 13);
QTest::newRow("RFC 2822 with day") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000") QTest::newRow("RFC 2822 with day") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QDate(1970, 1, 1); << Qt::RFC2822Date << QDate(1970, 1, 1);
QTest::newRow("RFC 2822 with day after space")
<< QString::fromLatin1(" Thu, 01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QDate(1970, 1, 1);
// No timezone // No timezone
QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34") QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34")
<< Qt::RFC2822Date << QDate(1970, 1, 1); << Qt::RFC2822Date << QDate(1970, 1, 1);
@ -1153,38 +1159,56 @@ void tst_QDate::fromStringDateFormat_data()
<< Qt::RFC2822Date << QDate(); << Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100") QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100")
<< Qt::RFC2822Date << QDate(); << Qt::RFC2822Date << QDate();
// Test invalid characters (should ignore invalid characters at end of string). // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038).
QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!") QTest::newRow("RFC 2822 invalid character at end")
<< QString::fromLatin1("01 Jan 2012 08:00:00 +0100!")
<< Qt::RFC2822Date << QDate(2012, 1, 1);
QTest::newRow("RFC 2822 invalid character at front")
<< QString::fromLatin1("!01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid character both ends")
<< QString::fromLatin1("!01 Jan 2012 08:00:00 +0100!") << Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid character at front, 2 at back")
<< QString::fromLatin1("!01 Jan 2012 08:00:00 +0100..") << Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid character 2 at front")
<< QString::fromLatin1("!!01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << QDate();
// The common date text used by the "invalid character" tests, just to be
// sure *it's* not what's invalid:
QTest::newRow("RFC 2822 (not invalid)")
<< QString::fromLatin1("01 Jan 2012 08:00:00 +0100")
<< Qt::RFC2822Date << QDate(2012, 1, 1); << Qt::RFC2822Date << QDate(2012, 1, 1);
QTest::newRow("RFC 2822 invalid character at front") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid character both ends") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000!")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid character at front, 2 at back") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000..")
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000")
<< Qt::RFC2822Date << QDate();
// Test Qt::RFC2822Date format (RFC 850 and 1036). // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive).
QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QDate(1987, 2, 13); << Qt::RFC2822Date << QDate(1987, 2, 13);
QTest::newRow("RFC 850 and 1036 after space")
<< QString::fromLatin1(" Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QDate(1987, 2, 13);
// No timezone // No timezone
QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970") QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970")
<< Qt::RFC2822Date << QDate(1970, 1, 1); << Qt::RFC2822Date << QDate(1970, 1, 1);
// No time specified // No time specified
QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002") QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002")
<< Qt::RFC2822Date << QDate(2002, 11, 1); << Qt::RFC2822Date << QDate(2002, 11, 1);
// Test invalid characters (should ignore invalid characters at end of string). // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038).
QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!") QTest::newRow("RFC 850 and 1036 invalid character at end")
<< QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!")
<< Qt::RFC2822Date << QDate(2012, 1, 1); << Qt::RFC2822Date << QDate(2012, 1, 1);
QTest::newRow("RFC 850 and 1036 invalid character at front") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000") QTest::newRow("RFC 850 and 1036 invalid character at front")
<< QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100")
<< Qt::RFC2822Date << QDate(); << Qt::RFC2822Date << QDate();
QTest::newRow("RFC 850 and 1036 invalid character both ends") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000!") QTest::newRow("RFC 850 and 1036 invalid character both ends")
<< QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100!")
<< Qt::RFC2822Date << QDate(); << Qt::RFC2822Date << QDate();
QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000..") QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back")
<< QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100..")
<< Qt::RFC2822Date << QDate(); << Qt::RFC2822Date << QDate();
QTest::newRow("RFC 850 and 1036 invalid character 2 at front") << QString::fromLatin1("!!Sun Jan 01 08:00:00 2012 +0000") QTest::newRow("RFC 850 and 1036 invalid character 2 at front")
<< QString::fromLatin1("!!Sun Jan 01 08:00:00 2012 +0100")
<< Qt::RFC2822Date << QDate(); << Qt::RFC2822Date << QDate();
// Again, check the text in the "invalid character" tests isn't the source of invalidity:
QTest::newRow("RFC 850 and 1036 (not invalid)")
<< QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100")
<< Qt::RFC2822Date << QDate(2012, 1, 1);
QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << QDate(); QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << QDate();
} }

View File

@ -1003,8 +1003,9 @@ void tst_QDateTime::toString_rfcDate()
// Set to non-English locale to confirm still uses English // Set to non-English locale to confirm still uses English
QLocale oldLocale; QLocale oldLocale;
QLocale::setDefault(QLocale("de_DE")); QLocale::setDefault(QLocale("de_DE"));
QCOMPARE(dt.toString(Qt::RFC2822Date), formatted); QString actual(dt.toString(Qt::RFC2822Date));
QLocale::setDefault(oldLocale); QLocale::setDefault(oldLocale);
QCOMPARE(actual, formatted);
} }
void tst_QDateTime::toString_enumformat() void tst_QDateTime::toString_enumformat()
@ -2310,8 +2311,14 @@ void tst_QDateTime::fromStringDateFormat_data()
// Test Qt::RFC2822Date format (RFC 2822). // Test Qt::RFC2822Date format (RFC 2822).
QTest::newRow("RFC 2822 +0100") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100") QTest::newRow("RFC 2822 +0100") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("RFC 2822 after space +0100")
<< QString::fromLatin1(" 13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("RFC 2822 with day +0100") << QString::fromLatin1("Fri, 13 Feb 1987 13:24:51 +0100") QTest::newRow("RFC 2822 with day +0100") << QString::fromLatin1("Fri, 13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("RFC 2822 with day after space +0100")
<< QString::fromLatin1(" Fri, 13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("RFC 2822 -0100") << QString::fromLatin1("13 Feb 1987 13:24:51 -0100") QTest::newRow("RFC 2822 -0100") << QString::fromLatin1("13 Feb 1987 13:24:51 -0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(14, 24, 51), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(14, 24, 51), Qt::UTC);
QTest::newRow("RFC 2822 with day -0100") << QString::fromLatin1("Fri, 13 Feb 1987 13:24:51 -0100") QTest::newRow("RFC 2822 with day -0100") << QString::fromLatin1("Fri, 13 Feb 1987 13:24:51 -0100")
@ -2324,6 +2331,11 @@ void tst_QDateTime::fromStringDateFormat_data()
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
QTest::newRow("RFC 2822 with day +0000") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000") QTest::newRow("RFC 2822 with day +0000") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
// Should be invalid, but current implementation would just ignore the
// offset as trailing junk if we insist on the space:
QTest::newRow("RFC 2822 missing space before +0100")
<< QString::fromLatin1("Thu, 01 Jan 1970 00:12:34+0100") << Qt::RFC2822Date
<< QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::OffsetFromUTC, 3600);
// No timezone assume UTC // No timezone assume UTC
QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34") QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
@ -2339,21 +2351,34 @@ void tst_QDateTime::fromStringDateFormat_data()
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100") QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100")
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
// Test invalid characters (should ignore invalid characters at end of string). // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038).
QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!") QTest::newRow("RFC 2822 invalid character at end")
<< QString::fromLatin1("01 Jan 2012 08:00:00 +0100!")
<< Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC);
QTest::newRow("RFC 2822 invalid character at front") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000") QTest::newRow("RFC 2822 invalid character at front")
<< QString::fromLatin1("!01 Jan 2012 08:00:00 +0100")
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 2822 invalid character both ends") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000!") QTest::newRow("RFC 2822 invalid character both ends")
<< QString::fromLatin1("!01 Jan 2012 08:00:00 +0100!")
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 2822 invalid character at front, 2 at back") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000..") QTest::newRow("RFC 2822 invalid character at front, 2 at back")
<< QString::fromLatin1("!01 Jan 2012 08:00:00 +0100..")
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000") QTest::newRow("RFC 2822 invalid character 2 at front")
<< QString::fromLatin1("!!01 Jan 2012 08:00:00 +0100")
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
// The common date text used by the "invalid character" tests, just to be
// sure *it's* not what's invalid:
QTest::newRow("RFC 2822 (not invalid)")
<< QString::fromLatin1("01 Jan 2012 08:00:00 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC);
// Test Qt::RFC2822Date format (RFC 850 and 1036). // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive).
QTest::newRow("RFC 850 and 1036 +0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") QTest::newRow("RFC 850 and 1036 +0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("RFC 1036 after space +0100")
<< QString::fromLatin1(" Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("RFC 850 and 1036 -0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 -0100") QTest::newRow("RFC 850 and 1036 -0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 -0100")
<< Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(14, 24, 51), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(14, 24, 51), Qt::UTC);
QTest::newRow("RFC 850 and 1036 +0000") << QString::fromLatin1("Thu Jan 01 00:12:34 1970 +0000") QTest::newRow("RFC 850 and 1036 +0000") << QString::fromLatin1("Thu Jan 01 00:12:34 1970 +0000")
@ -2364,19 +2389,29 @@ void tst_QDateTime::fromStringDateFormat_data()
QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970") QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
// No time specified // No time specified
QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002") QTest::newRow("RFC 850 and 1036 date only")
<< QString::fromLatin1("Fri Nov 01 2002")
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
// Test invalid characters (should ignore invalid characters at end of string). // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038).
QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!") QTest::newRow("RFC 850 and 1036 invalid character at end")
<< QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!")
<< Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC); << Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC);
QTest::newRow("RFC 850 and 1036 invalid character at front") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000") QTest::newRow("RFC 850 and 1036 invalid character at front")
<< QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100")
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 850 and 1036 invalid character both ends") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000!") QTest::newRow("RFC 850 and 1036 invalid character both ends")
<< QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100!")
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000..") QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back")
<< QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100..")
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 850 and 1036 invalid character 2 at front") << QString::fromLatin1("!!Sun Jan 01 08:00:00 2012 +0000") QTest::newRow("RFC 850 and 1036 invalid character 2 at front")
<< QString::fromLatin1("!!Sun Jan 01 08:00:00 2012 +0100")
<< Qt::RFC2822Date << invalidDateTime(); << Qt::RFC2822Date << invalidDateTime();
// Again, check the text in the "invalid character" tests isn't the source of invalidity:
QTest::newRow("RFC 850 and 1036 (not invalid)")
<< QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100")
<< Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC);
QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << invalidDateTime(); QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << invalidDateTime();
} }

View File

@ -619,8 +619,14 @@ void tst_QTime::fromStringDateFormat_data()
// Test Qt::RFC2822Date format (RFC 2822). // Test Qt::RFC2822Date format (RFC 2822).
QTest::newRow("RFC 2822") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100") QTest::newRow("RFC 2822") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51); << Qt::RFC2822Date << QTime(13, 24, 51);
QTest::newRow("RFC 2822 after space")
<< QString::fromLatin1(" 13 Feb 1987 13:24:51 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51);
QTest::newRow("RFC 2822 with day") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000") QTest::newRow("RFC 2822 with day") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QTime(0, 12, 34); << Qt::RFC2822Date << QTime(0, 12, 34);
QTest::newRow("RFC 2822 with day after space")
<< QString::fromLatin1(" Thu, 01 Jan 1970 00:12:34 +0000")
<< Qt::RFC2822Date << QTime(0, 12, 34);
// No timezone // No timezone
QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34") QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34")
<< Qt::RFC2822Date << QTime(0, 12, 34); << Qt::RFC2822Date << QTime(0, 12, 34);
@ -636,36 +642,58 @@ void tst_QTime::fromStringDateFormat_data()
<< Qt::RFC2822Date << QTime(13, 24, 51); << Qt::RFC2822Date << QTime(13, 24, 51);
QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100") QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51); << Qt::RFC2822Date << QTime(13, 24, 51);
// Test invalid characters (should ignore invalid characters at end of string). // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038).
QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!") QTest::newRow("RFC 2822 invalid character at end")
<< QString::fromLatin1("01 Jan 2012 08:00:00 +0100!")
<< Qt::RFC2822Date << QTime(8, 0, 0); << Qt::RFC2822Date << QTime(8, 0, 0);
QTest::newRow("RFC 2822 invalid character at front") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000") QTest::newRow("RFC 2822 invalid character at front")
<< QString::fromLatin1("!01 Jan 2012 08:00:00 +0100")
<< Qt::RFC2822Date << invalidTime(); << Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC 2822 invalid character both ends") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000!") QTest::newRow("RFC 2822 invalid character both ends")
<< QString::fromLatin1("!01 Jan 2012 08:00:00 +0100!")
<< Qt::RFC2822Date << invalidTime(); << Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC 2822 invalid character at front, 2 at back") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000..") QTest::newRow("RFC 2822 invalid character at front, 2 at back")
<< QString::fromLatin1("!01 Jan 2012 08:00:00 +0100..")
<< Qt::RFC2822Date << invalidTime(); << Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000") QTest::newRow("RFC 2822 invalid character 2 at front")
<< QString::fromLatin1("!!01 Jan 2012 08:00:00 +0100")
<< Qt::RFC2822Date << invalidTime(); << Qt::RFC2822Date << invalidTime();
// The common date text used by the "invalid character" tests, just to be
// sure *it's* not what's invalid:
QTest::newRow("RFC 2822 invalid character at end")
<< QString::fromLatin1("01 Jan 2012 08:00:00 +0100")
<< Qt::RFC2822Date << QTime(8, 0, 0);
// Test Qt::RFC2822Date format (RFC 850 and 1036). // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive).
QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51); << Qt::RFC2822Date << QTime(13, 24, 51);
QTest::newRow("RFC 850 and 1036 after space")
<< QString::fromLatin1(" Fri Feb 13 13:24:51 1987 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51);
// No timezone // No timezone
QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970") QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970")
<< Qt::RFC2822Date << QTime(0, 12, 34); << Qt::RFC2822Date << QTime(0, 12, 34);
// No time specified // No time specified
QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002") QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002")
<< Qt::RFC2822Date << invalidTime(); << Qt::RFC2822Date << invalidTime();
// Test invalid characters (should ignore invalid characters at end of string). // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038).
QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!") QTest::newRow("RFC 850 and 1036 invalid character at end")
<< QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!")
<< Qt::RFC2822Date << QTime(8, 0, 0); << Qt::RFC2822Date << QTime(8, 0, 0);
QTest::newRow("RFC 850 and 1036 invalid character at front") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000") QTest::newRow("RFC 850 and 1036 invalid character at front")
<< QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100")
<< Qt::RFC2822Date << invalidTime(); << Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC 850 and 1036 invalid character both ends") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000!") QTest::newRow("RFC 850 and 1036 invalid character both ends")
<< QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100!")
<< Qt::RFC2822Date << invalidTime(); << Qt::RFC2822Date << invalidTime();
QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000..") QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back")
<< QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100..")
<< Qt::RFC2822Date << invalidTime(); << Qt::RFC2822Date << invalidTime();
// The common date text used by the "invalid character" tests, just to be
// sure *it's* not what's invalid:
QTest::newRow("RFC 850 and 1036 invalid character at end")
<< QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100")
<< Qt::RFC2822Date << QTime(8, 0, 0);
QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << invalidTime(); QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << invalidTime();
} }

View File

@ -46,6 +46,7 @@ private slots:
// Public class default system tests // Public class default system tests
void createTest(); void createTest();
void nullTest(); void nullTest();
void systemZone();
void dataStreamTest(); void dataStreamTest();
void isTimeZoneIdAvailable(); void isTimeZoneIdAvailable();
void availableTimeZoneIds(); void availableTimeZoneIds();
@ -317,6 +318,14 @@ void tst_QTimeZone::nullTest()
QCOMPARE(data.daylightTimeOffset, std::numeric_limits<int>::min()); QCOMPARE(data.daylightTimeOffset, std::numeric_limits<int>::min());
} }
void tst_QTimeZone::systemZone()
{
const QTimeZone zone = QTimeZone::systemTimeZone();
QVERIFY(zone.isValid());
QCOMPARE(zone.id(), QTimeZone::systemTimeZoneId());
QCOMPARE(zone, QTimeZone(QTimeZone::systemTimeZoneId()));
}
void tst_QTimeZone::dataStreamTest() void tst_QTimeZone::dataStreamTest()
{ {
// Test the OffsetFromUtc backend serialization. First with a custom timezone: // Test the OffsetFromUtc backend serialization. First with a custom timezone:

View File

@ -1,4 +1,3 @@
# QTBUG-65667 # QTBUG-65667
[localAddress:linklocal-ipv4] [localAddress:linklocal-ipv4]
msvc-2015 ci windows ci
msvc-2017 ci

View File

@ -1,13 +0,0 @@
# OpenSSL version is too new. Rich will fix :)
[subjectAndIssuerAttributes]
ubuntu-16.04
rhel-7.6
opensuse-leap
windows-7sp1
ubuntu-18.04
rhel-7.4
b2qt
windows-10 msvc-2017
windows-10 msvc-2015
opensuse-42.3

View File

@ -33,6 +33,10 @@
#include <qsslsocket.h> #include <qsslsocket.h>
#include <qsslcertificateextension.h> #include <qsslcertificateextension.h>
#ifndef QT_NO_OPENSSL
#include <openssl/obj_mac.h>
#endif
class tst_QSslCertificate : public QObject class tst_QSslCertificate : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -960,8 +964,12 @@ void tst_QSslCertificate::subjectAndIssuerAttributes()
certList = QSslCertificate::fromPath(testDataDir + "more-certificates/natwest-banking.pem"); certList = QSslCertificate::fromPath(testDataDir + "more-certificates/natwest-banking.pem");
QVERIFY(certList.count() > 0); QVERIFY(certList.count() > 0);
QByteArray shortName("1.3.6.1.4.1.311.60.2.1.3");
#if !defined(QT_NO_OPENSSL) && defined(SN_jurisdictionCountryName)
shortName = SN_jurisdictionCountryName;
#endif
attributes = certList[0].subjectInfoAttributes(); attributes = certList[0].subjectInfoAttributes();
QVERIFY(attributes.contains(QByteArray("1.3.6.1.4.1.311.60.2.1.3"))); QVERIFY(attributes.contains(shortName));
} }
void tst_QSslCertificate::verify() void tst_QSslCertificate::verify()

View File

@ -0,0 +1,10 @@
CONFIG += testcase
TARGET = tst_sessionmanagement_macos
OBJECTIVE_SOURCES += tst_sessionmanagement_macos.mm
QT = testlib gui core
LIBS += -framework AppKit
requires(mac)
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0

View File

@ -0,0 +1,61 @@
/****************************************************************************
**
** Copyright (C) 2019 Samuel Gaist <samuel.gaist@idiap.ch>
** 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/QtTest>
#include <QSignalSpy>
#include <QSessionManager>
#include <AppKit/AppKit.h>
// Q_DECLARE_METATYPE(QSessionManager)
class tst_SessionManagement_macOS : public QObject
{
Q_OBJECT
private slots:
void stopApplication();
};
/*
Test that session handling code is properly called
*/
void tst_SessionManagement_macOS::stopApplication()
{
int argc = 0;
QGuiApplication app(argc, nullptr);
QSignalSpy spy(&app, &QGuiApplication::commitDataRequest);
QTimer::singleShot(1000, []() {
[NSApp terminate:nil];
});
app.exec();
QCOMPARE(spy.count(), 1);
}
QTEST_APPLESS_MAIN(tst_SessionManagement_macOS)
#include "tst_sessionmanagement_macos.moc"

View File

@ -4922,13 +4922,27 @@ void tst_QTreeView::taskQTBUG_61476()
const QPoint pos = rect.center(); const QPoint pos = rect.center();
QTest::mousePress(tv.viewport(), Qt::LeftButton, {}, pos); QTest::mousePress(tv.viewport(), Qt::LeftButton, {}, pos);
if (tv.style()->styleHint(QStyle::SH_ListViewExpand_SelectMouseType, nullptr, &tv) == const bool expandsOnPress =
QEvent::MouseButtonPress) (tv.style()->styleHint(QStyle::SH_ListViewExpand_SelectMouseType, nullptr, &tv) == QEvent::MouseButtonPress);
if (expandsOnPress)
QTRY_VERIFY(!tv.isExpanded(mi)); QTRY_VERIFY(!tv.isExpanded(mi));
QTest::mouseRelease(tv.viewport(), Qt::LeftButton, {}, pos); QTest::mouseRelease(tv.viewport(), Qt::LeftButton, {}, pos);
QTRY_VERIFY(!tv.isExpanded(mi)); QTRY_VERIFY(!tv.isExpanded(mi));
QCOMPARE(lastTopLevel->checkState(), Qt::Checked); QCOMPARE(lastTopLevel->checkState(), Qt::Checked);
// Test that it does not toggle the check state of a previously selected item when collapsing an
// item causes it to position the item under the mouse to be the decoration for the selected item
tv.expandAll();
tv.verticalScrollBar()->setValue(tv.verticalScrollBar()->maximum());
// It is not enough to programmatically select the item, we need to have it clicked on
QTest::mouseClick(tv.viewport(), Qt::LeftButton, {}, tv.visualRect(lastTopLevel->index()).center());
QTest::mousePress(tv.viewport(), Qt::LeftButton, {}, pos);
if (expandsOnPress)
QTRY_VERIFY(!tv.isExpanded(mi));
QTest::mouseRelease(tv.viewport(), Qt::LeftButton, nullptr, pos);
QTRY_VERIFY(!tv.isExpanded(mi));
QCOMPARE(lastTopLevel->checkState(), Qt::Checked);
} }
QTEST_MAIN(tst_QTreeView) QTEST_MAIN(tst_QTreeView)

View File

@ -53,6 +53,7 @@
#include <qmainwindow.h> #include <qmainwindow.h>
#include <qdockwidget.h> #include <qdockwidget.h>
#include <qrandom.h> #include <qrandom.h>
#include <qstylehints.h>
#include <qtoolbar.h> #include <qtoolbar.h>
#include <qtoolbutton.h> #include <qtoolbutton.h>
#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qoperatingsystemversion.h>
@ -198,6 +199,7 @@ private slots:
void hideWhenFocusWidgetIsChild(); void hideWhenFocusWidgetIsChild();
void normalGeometry(); void normalGeometry();
void setGeometry(); void setGeometry();
void setGeometryHidden();
void windowOpacity(); void windowOpacity();
void raise(); void raise();
void lower(); void lower();
@ -2946,6 +2948,38 @@ void tst_QWidget::setGeometry()
QCOMPARE(tlw.geometry(), tr); QCOMPARE(tlw.geometry(), tr);
} }
void tst_QWidget::setGeometryHidden()
{
if (QGuiApplication::styleHints()->showIsMaximized())
QSKIP("Platform does not support QWidget::setGeometry() - skipping");
QWidget tlw;
tlw.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
QWidget child(&tlw);
const QRect tr(m_availableTopLeft + QPoint(100, 100), 2 * m_testWidgetSize);
const QRect cr(QPoint(50, 50), m_testWidgetSize);
tlw.setGeometry(tr);
child.setGeometry(cr);
tlw.showNormal();
tlw.hide();
QTRY_VERIFY(tlw.isHidden());
tlw.setGeometry(cr);
QVERIFY(tlw.testAttribute(Qt::WA_PendingMoveEvent));
QVERIFY(tlw.testAttribute(Qt::WA_PendingResizeEvent));
QImage img(tlw.size(), QImage::Format_ARGB32); // just needed to call QWidget::render()
tlw.render(&img);
QVERIFY(!tlw.testAttribute(Qt::WA_PendingMoveEvent));
QVERIFY(!tlw.testAttribute(Qt::WA_PendingResizeEvent));
tlw.setGeometry(cr);
QVERIFY(!tlw.testAttribute(Qt::WA_PendingMoveEvent));
QVERIFY(!tlw.testAttribute(Qt::WA_PendingResizeEvent));
tlw.resize(cr.size());
QVERIFY(!tlw.testAttribute(Qt::WA_PendingMoveEvent));
QVERIFY(!tlw.testAttribute(Qt::WA_PendingResizeEvent));
}
void tst_QWidget::windowOpacity() void tst_QWidget::windowOpacity()
{ {
QWidget widget; QWidget widget;

View File

@ -42,7 +42,7 @@ public:
}; };
DragWidget::DragWidget(QString text, QWidget *parent) DragWidget::DragWidget(QString text, QWidget *parent)
: QWidget(parent), otherWindow(nullptr) : QWidget(parent)
{ {
int x = 5; int x = 5;
int y = 5; int y = 5;
@ -52,9 +52,9 @@ DragWidget::DragWidget(QString text, QWidget *parent)
text = "You can drag from this window and drop text here"; text = "You can drag from this window and drop text here";
QStringList words = text.split(' '); QStringList words = text.split(' ');
foreach (QString word, words) { for (const QString &word : words) {
if (!word.isEmpty()) { if (!word.isEmpty()) {
FramedLabel *wordLabel = new FramedLabel(word, this); auto wordLabel = new FramedLabel(word, this);
wordLabel->move(x, y); wordLabel->move(x, y);
wordLabel->show(); wordLabel->show();
x += wordLabel->width() + 2; x += wordLabel->width() + 2;
@ -105,7 +105,6 @@ void DragWidget::dragLeaveEvent(QDragLeaveEvent *)
update(); update();
} }
void DragWidget::dropEvent(QDropEvent *event) void DragWidget::dropEvent(QDropEvent *event)
{ {
if (event->mimeData()->hasText()) { if (event->mimeData()->hasText()) {
@ -141,9 +140,9 @@ void DragWidget::dropEvent(QDropEvent *event)
} else { } else {
event->ignore(); event->ignore();
} }
foreach (QObject *child, children()) { for (QObject *child : children()) {
if (child->inherits("QWidget")) { if (child->isWidgetType()) {
QWidget *widget = static_cast<QWidget *>(child); auto widget = static_cast<QWidget *>(child);
if (!widget->isVisible()) if (!widget->isVisible())
widget->deleteLater(); widget->deleteLater();
} }
@ -170,7 +169,7 @@ void DragWidget::mousePressEvent(QMouseEvent *event)
pixmap.setDevicePixelRatio(dpr); pixmap.setDevicePixelRatio(dpr);
child->render(&pixmap); child->render(&pixmap);
QDrag *drag = new QDrag(this); auto drag = new QDrag(this);
drag->setMimeData(mimeData); drag->setMimeData(mimeData);
drag->setPixmap(pixmap); drag->setPixmap(pixmap);
drag->setHotSpot(hotSpot); drag->setHotSpot(hotSpot);

View File

@ -40,7 +40,7 @@ QT_END_NAMESPACE
class DragWidget : public QWidget class DragWidget : public QWidget
{ {
public: public:
DragWidget(QString text = QString(), QWidget *parent = 0); DragWidget(QString text = QString(), QWidget *parent = nullptr);
protected: protected:
void dragEnterEvent(QDragEnterEvent *event) override; void dragEnterEvent(QDragEnterEvent *event) override;
@ -52,12 +52,13 @@ protected:
void timerEvent(QTimerEvent *event) override; void timerEvent(QTimerEvent *event) override;
void showEvent(QShowEvent *event) override; void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override; void hideEvent(QHideEvent *event) override;
private: private:
QPoint dragPos; QPoint dragPos;
QPoint dropPos; QPoint dropPos;
QBasicTimer dragTimer; QBasicTimer dragTimer;
QBasicTimer dropTimer; QBasicTimer dropTimer;
QWidget *otherWindow; QWidget *otherWindow = nullptr;
}; };
#endif // DRAGWIDGET_H #endif // DRAGWIDGET_H

View File

@ -30,6 +30,7 @@
#include <QMenuBar> #include <QMenuBar>
#include <QLabel> #include <QLabel>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QFormLayout>
#include <QApplication> #include <QApplication>
#include <QAction> #include <QAction>
#include <QStyle> #include <QStyle>
@ -61,27 +62,38 @@
#include "dragwidget.h" #include "dragwidget.h"
#include <utility>
static QTextStream &operator<<(QTextStream &str, const QRect &r) static QTextStream &operator<<(QTextStream &str, const QRect &r)
{ {
str << r.width() << 'x' << r.height() << Qt::forcesign << r.x() << r.y() << Qt::noforcesign; str << r.width() << 'x' << r.height() << Qt::forcesign << r.x() << r.y() << Qt::noforcesign;
return str; return str;
} }
static QString formatWindowTitle(const QString &title)
{
QString result;
QTextStream(&result) << title << ' ' << QT_VERSION_STR << " ("
<< QGuiApplication::platformName()
<< '/' << QApplication::style()->objectName() << ')';
return result;
}
class DemoContainerBase class DemoContainerBase
{ {
public: public:
DemoContainerBase() : m_widget(nullptr) {} DemoContainerBase() = default;
virtual ~DemoContainerBase() {} virtual ~DemoContainerBase() = default;
QString name() { return option().names().first(); } QString name() { return option().names().constFirst(); }
virtual QCommandLineOption &option() = 0; virtual QCommandLineOption &option() = 0;
virtual void makeVisible(bool visible, QWidget *parent) = 0; virtual void makeVisible(bool visible, QWidget *parent) = 0;
QWidget *widget() { return m_widget; } QWidget *widget() const { return m_widget; }
protected: protected:
QWidget *m_widget; QWidget *m_widget = nullptr;
}; };
typedef QList<DemoContainerBase*> DemoContainerList ; using DemoContainerList = QVector<DemoContainerBase*>;
template <class T> template <class T>
class DemoContainer : public DemoContainerBase class DemoContainer : public DemoContainerBase
@ -93,16 +105,25 @@ public:
} }
~DemoContainer() { delete m_widget; } ~DemoContainer() { delete m_widget; }
QCommandLineOption &option() { return m_option; } QCommandLineOption &option() override { return m_option; }
void makeVisible(bool visible, QWidget *parent) { void makeVisible(bool visible, QWidget *parent) override
{
if (visible && !m_widget) { if (visible && !m_widget) {
m_widget = new T; m_widget = new T;
if (m_widget->windowTitle().isEmpty()) {
QString title = m_option.description();
if (title.startsWith("Test ", Qt::CaseInsensitive))
title.remove(0, 5);
title[0] = title.at(0).toUpper();
m_widget->setWindowTitle(formatWindowTitle(title));
}
m_widget->installEventFilter(parent); m_widget->installEventFilter(parent);
} }
if (m_widget) if (m_widget)
m_widget->setVisible(visible); m_widget->setVisible(visible);
} }
private: private:
QCommandLineOption m_option; QCommandLineOption m_option;
}; };
@ -134,12 +155,15 @@ public:
connect(m_slider, &QSlider::sliderMoved, this, &LabelSlider::updateLabel); connect(m_slider, &QSlider::sliderMoved, this, &LabelSlider::updateLabel);
connect(m_slider, &QSlider::valueChanged, this, &LabelSlider::valueChanged); connect(m_slider, &QSlider::valueChanged, this, &LabelSlider::valueChanged);
} }
void setValue(int scaleFactor) { void setValue(int scaleFactor)
{
m_slider->setValue(scaleFactor); m_slider->setValue(scaleFactor);
updateLabel(scaleFactor); updateLabel(scaleFactor);
} }
private slots: private slots:
void updateLabel(int scaleFactor) { void updateLabel(int scaleFactor)
{
// slider value is scale factor times ten; // slider value is scale factor times ten;
qreal scalefactorF = qreal(scaleFactor) / 10.0; qreal scalefactorF = qreal(scaleFactor) / 10.0;
@ -149,8 +173,10 @@ private slots:
number.append(".0"); number.append(".0");
m_label->setText(number); m_label->setText(number);
} }
signals: signals:
void valueChanged(int scaleFactor); void valueChanged(int scaleFactor);
private: private:
QSlider *m_slider; QSlider *m_slider;
QLabel *m_label; QLabel *m_label;
@ -172,31 +198,35 @@ static inline qreal getGlobalScaleFactor()
class DemoController : public QWidget class DemoController : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
DemoController(DemoContainerList *demos, QCommandLineParser *parser); DemoController(DemoContainerList demos, QCommandLineParser *parser);
~DemoController(); ~DemoController();
protected: protected:
bool eventFilter(QObject *object, QEvent *event); bool eventFilter(QObject *object, QEvent *event) override;
void closeEvent(QCloseEvent *) { qApp->quit(); } void closeEvent(QCloseEvent *) override { QCoreApplication::quit(); }
private slots: private slots:
void handleButton(int id, bool toggled); void handleButton(int id, bool toggled);
private: private:
DemoContainerList *m_demos; DemoContainerList m_demos;
QButtonGroup *m_group; QButtonGroup *m_group;
}; };
DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *parser) DemoController::DemoController(DemoContainerList demos, QCommandLineParser *parser)
: m_demos(demos) : m_demos(std::move(demos))
{ {
setWindowTitle("screen scale factors"); setWindowTitle(formatWindowTitle("Screen Scale Factors"));
setObjectName("controller"); // make WindowScaleFactorSetter skip this window setObjectName("controller"); // make WindowScaleFactorSetter skip this window
QGridLayout *layout = new QGridLayout; auto mainLayout = new QVBoxLayout(this);
setLayout(layout); auto scaleLayout = new QGridLayout;
mainLayout->addLayout(scaleLayout);
int layoutRow = 0; int layoutRow = 0;
LabelSlider *globalScaleSlider = new LabelSlider(this, "Global scale factor", layout, layoutRow++); LabelSlider *globalScaleSlider = new LabelSlider(this, "Global scale factor", scaleLayout, layoutRow++);
globalScaleSlider->setValue(int(getGlobalScaleFactor() * 10)); globalScaleSlider->setValue(int(getGlobalScaleFactor() * 10));
connect(globalScaleSlider, &LabelSlider::valueChanged, [](int scaleFactor){ connect(globalScaleSlider, &LabelSlider::valueChanged, [](int scaleFactor){
// slider value is scale factor times ten; // slider value is scale factor times ten;
@ -205,13 +235,13 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par
}); });
// set up one scale control line per screen // set up one scale control line per screen
QList<QScreen *> screens = QGuiApplication::screens(); const auto screens = QGuiApplication::screens();
foreach (QScreen *screen, screens) { for (QScreen *screen : screens) {
// create scale control line // create scale control line
QSize screenSize = screen->geometry().size(); QSize screenSize = screen->geometry().size();
QString screenId = screen->name() + QLatin1Char(' ') + QString::number(screenSize.width()) QString screenId = screen->name() + QLatin1Char(' ') + QString::number(screenSize.width())
+ QLatin1Char(' ') + QString::number(screenSize.height()); + QLatin1Char(' ') + QString::number(screenSize.height());
LabelSlider *slider = new LabelSlider(this, screenId, layout, layoutRow++); LabelSlider *slider = new LabelSlider(this, screenId, scaleLayout, layoutRow++);
slider->setValue(getScreenFactorWithoutPixelDensity(screen) * 10); slider->setValue(getScreenFactorWithoutPixelDensity(screen) * 10);
// handle slider value change // handle slider value change
@ -228,15 +258,18 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par
}); });
} }
auto demoLayout = new QFormLayout;
mainLayout->addLayout(demoLayout);
m_group = new QButtonGroup(this); m_group = new QButtonGroup(this);
m_group->setExclusive(false); m_group->setExclusive(false);
for (int i = 0; i < m_demos->size(); ++i) { for (int i = 0; i < m_demos.size(); ++i) {
DemoContainerBase *demo = m_demos->at(i); DemoContainerBase *demo = m_demos.at(i);
QPushButton *button = new QPushButton(demo->name()); QString name = demo->name();
button->setToolTip(demo->option().description()); name[0] = name.at(0).toUpper();
auto button = new QPushButton(name);
button->setCheckable(true); button->setCheckable(true);
layout->addWidget(button, layoutRow++, 0, 1, -1); demoLayout->addRow(demo->option().description(), button);
m_group->addButton(button, i); m_group->addButton(button, i);
if (parser->isSet(demo->option())) { if (parser->isSet(demo->option())) {
@ -244,19 +277,20 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par
button->setChecked(true); button->setChecked(true);
} }
} }
connect(m_group, SIGNAL(buttonToggled(int, bool)), this, SLOT(handleButton(int, bool))); connect(m_group, QOverload<int,bool>::of(&QButtonGroup::buttonToggled),
this, &DemoController::handleButton);
} }
DemoController::~DemoController() DemoController::~DemoController()
{ {
qDeleteAll(*m_demos); qDeleteAll(m_demos);
} }
bool DemoController::eventFilter(QObject *object, QEvent *event) bool DemoController::eventFilter(QObject *object, QEvent *event)
{ {
if (event->type() == QEvent::Close) { if (event->type() == QEvent::Close) {
for (int i = 0; i < m_demos->size(); ++i) { for (int i = 0; i < m_demos.size(); ++i) {
DemoContainerBase *demo = m_demos->at(i); DemoContainerBase *demo = m_demos.at(i);
if (demo->widget() == object) { if (demo->widget() == object) {
m_group->button(i)->setChecked(false); m_group->button(i)->setChecked(false);
break; break;
@ -268,15 +302,17 @@ bool DemoController::eventFilter(QObject *object, QEvent *event)
void DemoController::handleButton(int id, bool toggled) void DemoController::handleButton(int id, bool toggled)
{ {
m_demos->at(id)->makeVisible(toggled, this); m_demos.at(id)->makeVisible(toggled, this);
} }
class PixmapPainter : public QWidget class PixmapPainter : public QWidget
{ {
public: public:
PixmapPainter(); PixmapPainter();
void paintEvent(QPaintEvent *event);
void paintEvent(QPaintEvent *event) override;
private:
QPixmap pixmap1X; QPixmap pixmap1X;
QPixmap pixmap2X; QPixmap pixmap2X;
QPixmap pixmapLarge; QPixmap pixmapLarge;
@ -348,12 +384,14 @@ void PixmapPainter::paintEvent(QPaintEvent *)
class TiledPixmapPainter : public QWidget class TiledPixmapPainter : public QWidget
{ {
public: public:
TiledPixmapPainter();
void paintEvent(QPaintEvent *event) override;
private:
QPixmap pixmap1X; QPixmap pixmap1X;
QPixmap pixmap2X; QPixmap pixmap2X;
QPixmap pixmapLarge; QPixmap pixmapLarge;
TiledPixmapPainter();
void paintEvent(QPaintEvent *event);
}; };
TiledPixmapPainter::TiledPixmapPainter() TiledPixmapPainter::TiledPixmapPainter()
@ -404,6 +442,7 @@ class Labels : public QWidget
public: public:
Labels(); Labels();
private:
QPixmap pixmap1X; QPixmap pixmap1X;
QPixmap pixmap2X; QPixmap pixmap2X;
QPixmap pixmapLarge; QPixmap pixmapLarge;
@ -419,7 +458,7 @@ Labels::Labels()
qtIcon.addFile(":/qticon32.png"); qtIcon.addFile(":/qticon32.png");
qtIcon.addFile(":/qticon32@2x.png"); qtIcon.addFile(":/qticon32@2x.png");
setWindowIcon(qtIcon); setWindowIcon(qtIcon);
setWindowTitle("Labels"); setWindowTitle(formatWindowTitle("Labels"));
QLabel *label1x = new QLabel(); QLabel *label1x = new QLabel();
label1x->setPixmap(pixmap1X); label1x->setPixmap(pixmap1X);
@ -454,18 +493,17 @@ private:
QIcon qtIcon2x; QIcon qtIcon2x;
QToolBar *fileToolBar; QToolBar *fileToolBar;
int menuCount;
QAction *m_maskAction; QAction *m_maskAction;
int menuCount = 0;
}; };
MainWindow::MainWindow() MainWindow::MainWindow()
:menuCount(0)
{ {
// beware that QIcon auto-loads the @2x versions. // beware that QIcon auto-loads the @2x versions.
qtIcon1x.addFile(":/qticon16.png"); qtIcon1x.addFile(":/qticon16.png");
qtIcon2x.addFile(":/qticon32.png"); qtIcon2x.addFile(":/qticon32.png");
setWindowIcon(qtIcon); setWindowIcon(qtIcon);
setWindowTitle("MainWindow"); setWindowTitle(formatWindowTitle("MainWindow"));
fileToolBar = addToolBar(tr("File")); fileToolBar = addToolBar(tr("File"));
// fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); // fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
@ -484,7 +522,6 @@ MainWindow::MainWindow()
addNewMenu("&Help", 2); addNewMenu("&Help", 2);
} }
QMenu *MainWindow::addNewMenu(const QString &title, int itemCount) QMenu *MainWindow::addNewMenu(const QString &title, int itemCount)
{ {
QMenu *menu = menuBar()->addMenu(title); QMenu *menu = menuBar()->addMenu(title);
@ -516,7 +553,7 @@ void MainWindow::maskActionToggled(bool t)
class StandardIcons : public QWidget class StandardIcons : public QWidget
{ {
public: public:
void paintEvent(QPaintEvent *) void paintEvent(QPaintEvent *) override
{ {
int x = 10; int x = 10;
int y = 10; int y = 10;
@ -538,7 +575,7 @@ public:
class Caching : public QWidget class Caching : public QWidget
{ {
public: public:
void paintEvent(QPaintEvent *) void paintEvent(QPaintEvent *) override
{ {
QSize layoutSize(75, 75); QSize layoutSize(75, 75);
@ -576,16 +613,12 @@ public:
} }
}; };
class Style : public QWidget { class Style : public QWidget
{
public: public:
QPushButton *button; Style()
QLineEdit *lineEdit; {
QSlider *slider; row1 = new QHBoxLayout(this);
QHBoxLayout *row1;
Style() {
row1 = new QHBoxLayout();
setLayout(row1);
button = new QPushButton(); button = new QPushButton();
button->setText("Test Button"); button->setText("Test Button");
@ -601,17 +634,23 @@ public:
row1->addWidget(new QSpinBox); row1->addWidget(new QSpinBox);
row1->addWidget(new QScrollBar); row1->addWidget(new QScrollBar);
QTabBar *tab = new QTabBar(); auto tab = new QTabBar();
tab->addTab("Foo"); tab->addTab("Foo");
tab->addTab("Bar"); tab->addTab("Bar");
row1->addWidget(tab); row1->addWidget(tab);
} }
private:
QPushButton *button;
QLineEdit *lineEdit;
QSlider *slider;
QHBoxLayout *row1;
}; };
class Fonts : public QWidget class Fonts : public QWidget
{ {
public: public:
void paintEvent(QPaintEvent *) void paintEvent(QPaintEvent *) override
{ {
QPainter painter(this); QPainter painter(this);
@ -690,7 +729,7 @@ public:
iconNormalDpi.reset(new QIcon(path32_2)); // does not have a 2x version. iconNormalDpi.reset(new QIcon(path32_2)); // does not have a 2x version.
} }
void paintEvent(QPaintEvent *) void paintEvent(QPaintEvent *) override
{ {
int x = 10; int x = 10;
int y = 10; int y = 10;
@ -782,7 +821,7 @@ public:
tab->move(10, 100); tab->move(10, 100);
tab->show(); tab->show();
QToolBar *toolBar = new QToolBar(this); auto toolBar = new QToolBar(this);
toolBar->addAction(QIcon(":/qticon16.png"), "16"); toolBar->addAction(QIcon(":/qticon16.png"), "16");
toolBar->addAction(QIcon(":/qticon16@2x.png"), "16@2x"); toolBar->addAction(QIcon(":/qticon16@2x.png"), "16@2x");
toolBar->addAction(QIcon(":/qticon32.png"), "32"); toolBar->addAction(QIcon(":/qticon32.png"), "32");
@ -796,11 +835,12 @@ public:
class LinePainter : public QWidget class LinePainter : public QWidget
{ {
public: public:
void paintEvent(QPaintEvent *event); void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event) override;
private:
QPoint lastMousePoint; QPoint lastMousePoint;
QVector<QPoint> linePoints; QVector<QPoint> linePoints;
}; };
@ -855,17 +895,15 @@ void LinePainter::mouseMoveEvent(QMouseEvent *event)
class CursorTester : public QWidget class CursorTester : public QWidget
{ {
public: public:
CursorTester() CursorTester() = default;
:moveLabel(nullptr), moving(false)
{
}
inline QRect getRect(int idx) const inline QRect getRect(int idx) const
{ {
int h = height() / 2; int h = height() / 2;
return QRect(10, 10 + h * (idx - 1), width() - 20, h - 20); return QRect(10, 10 + h * (idx - 1), width() - 20, h - 20);
} }
void paintEvent(QPaintEvent *)
void paintEvent(QPaintEvent *) override
{ {
QPainter p(this); QPainter p(this);
QRect r1 = getRect(1); QRect r1 = getRect(1);
@ -899,7 +937,7 @@ public:
} }
} }
void mousePressEvent(QMouseEvent *e) void mousePressEvent(QMouseEvent *e) override
{ {
if (moving) if (moving)
return; return;
@ -923,7 +961,7 @@ public:
moveLabel->show(); moveLabel->show();
} }
void mouseReleaseEvent(QMouseEvent *) void mouseReleaseEvent(QMouseEvent *) override
{ {
if (moveLabel) if (moveLabel)
moveLabel->hide(); moveLabel->hide();
@ -931,7 +969,7 @@ public:
moving = false; moving = false;
} }
void mouseMoveEvent(QMouseEvent *e) void mouseMoveEvent(QMouseEvent *e) override
{ {
if (!moving) if (!moving)
return; return;
@ -943,32 +981,32 @@ public:
} }
private: private:
QLabel *moveLabel; QLabel *moveLabel = nullptr;
bool useCursorPos;
bool moving;
QPoint mousePos; QPoint mousePos;
bool useCursorPos = false;
bool moving = false;
}; };
class ScreenDisplayer : public QWidget class ScreenDisplayer : public QWidget
{ {
public: public:
ScreenDisplayer() ScreenDisplayer() = default;
: QWidget(), moveLabel(nullptr), scaleFactor(1.0)
{
}
void timerEvent(QTimerEvent *) { void timerEvent(QTimerEvent *) override
{
update(); update();
} }
void mousePressEvent(QMouseEvent *) { void mousePressEvent(QMouseEvent *) override
{
if (!moveLabel) if (!moveLabel)
moveLabel = new QLabel(this,Qt::BypassWindowManagerHint|Qt::FramelessWindowHint|Qt::Window ); moveLabel = new QLabel(this,Qt::BypassWindowManagerHint|Qt::FramelessWindowHint|Qt::Window );
moveLabel->setText("Hello, Qt this is a label\nwith some text"); moveLabel->setText("Hello, Qt this is a label\nwith some text");
moveLabel->show(); moveLabel->show();
} }
void mouseMoveEvent(QMouseEvent *e) {
void mouseMoveEvent(QMouseEvent *e) override
{
if (!moveLabel) if (!moveLabel)
return; return;
moveLabel->move(e->pos() / scaleFactor); moveLabel->move(e->pos() / scaleFactor);
@ -978,23 +1016,30 @@ public:
dbg << moveLabel->geometry(); dbg << moveLabel->geometry();
moveLabel->setText(str); moveLabel->setText(str);
} }
void mouseReleaseEvent(QMouseEvent *) {
void mouseReleaseEvent(QMouseEvent *) override
{
if (moveLabel) if (moveLabel)
moveLabel->hide(); moveLabel->hide();
} }
void showEvent(QShowEvent *) {
void showEvent(QShowEvent *) override
{
refreshTimer.start(300, this); refreshTimer.start(300, this);
} }
void hideEvent(QHideEvent *) {
void hideEvent(QHideEvent *) override
{
refreshTimer.stop(); refreshTimer.stop();
} }
void paintEvent(QPaintEvent *) {
void paintEvent(QPaintEvent *) override
{
QPainter p(this); QPainter p(this);
QRectF total; QRectF total;
QList<QScreen*> screens = qApp->screens(); const auto screens = QGuiApplication::screens();
foreach (QScreen *screen, screens) { for (const QScreen *screen : screens)
total |= screen->geometry(); total |= screen->geometry();
}
if (total.isEmpty()) if (total.isEmpty())
return; return;
@ -1006,8 +1051,7 @@ public:
p.setPen(QPen(Qt::white, 10)); p.setPen(QPen(Qt::white, 10));
p.setBrush(Qt::gray); p.setBrush(Qt::gray);
for (const QScreen *screen : screens) {
foreach (QScreen *screen, screens) {
p.drawRect(screen->geometry()); p.drawRect(screen->geometry());
QFont f = font(); QFont f = font();
f.setPixelSize(screen->geometry().height() / 8); f.setPixelSize(screen->geometry().height() / 8);
@ -1015,7 +1059,9 @@ public:
p.drawText(screen->geometry(), Qt::AlignCenter, screen->name()); p.drawText(screen->geometry(), Qt::AlignCenter, screen->name());
} }
p.setBrush(QColor(200,220,255,127)); p.setBrush(QColor(200,220,255,127));
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
const auto topLevels = QApplication::topLevelWidgets();
for (QWidget *widget : topLevels) {
if (!widget->isHidden()) if (!widget->isHidden())
p.drawRect(widget->geometry()); p.drawRect(widget->geometry());
} }
@ -1028,42 +1074,51 @@ public:
cursorShape.translate(QCursor::pos()); cursorShape.translate(QCursor::pos());
p.drawPolygon(cursorShape); p.drawPolygon(cursorShape);
} }
private: private:
QLabel *moveLabel; QLabel *moveLabel = nullptr;
qreal scaleFactor = 1;
QBasicTimer refreshTimer; QBasicTimer refreshTimer;
qreal scaleFactor;
}; };
class PhysicalSizeTest : public QWidget class PhysicalSizeTest : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
PhysicalSizeTest() : QWidget(), m_ignoreResize(false) {} PhysicalSizeTest() = default;
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *) { void paintEvent(QPaintEvent *event) override;
void resizeEvent(QResizeEvent *) override
{
qreal ppi = window()->windowHandle()->screen()->physicalDotsPerInchX(); qreal ppi = window()->windowHandle()->screen()->physicalDotsPerInchX();
QSizeF s = size(); QSizeF s = size();
if (!m_ignoreResize) if (!m_ignoreResize)
m_physicalSize = s / ppi; m_physicalSize = s / ppi;
} }
bool event(QEvent *event) {
bool event(QEvent *event) override
{
if (event->type() == QEvent::ScreenChangeInternal) { if (event->type() == QEvent::ScreenChangeInternal) {
// we will get resize events when the scale factor changes // we will get resize events when the scale factor changes
m_ignoreResize = true; m_ignoreResize = true;
QTimer::singleShot(100, this, SLOT(handleScreenChange())); QTimer::singleShot(100, this, &PhysicalSizeTest::handleScreenChange);
} }
return QWidget::event(event); return QWidget::event(event);
} }
public slots: public slots:
void handleScreenChange() { void handleScreenChange()
{
qreal ppi = window()->windowHandle()->screen()->physicalDotsPerInchX(); qreal ppi = window()->windowHandle()->screen()->physicalDotsPerInchX();
QSizeF newSize = m_physicalSize * ppi; QSizeF newSize = m_physicalSize * ppi;
resize(newSize.toSize()); resize(newSize.toSize());
m_ignoreResize = false; m_ignoreResize = false;
} }
private: private:
QSizeF m_physicalSize; QSizeF m_physicalSize;
bool m_ignoreResize; bool m_ignoreResize = false;
}; };
void PhysicalSizeTest::paintEvent(QPaintEvent *) void PhysicalSizeTest::paintEvent(QPaintEvent *)
@ -1166,8 +1221,9 @@ void PhysicalSizeTest::paintEvent(QPaintEvent *)
class GraphicsViewCaching : public QGraphicsView class GraphicsViewCaching : public QGraphicsView
{ {
public: public:
GraphicsViewCaching() { GraphicsViewCaching()
QGraphicsScene *scene = new QGraphicsScene(0, 0, 400, 400); {
auto scene = new QGraphicsScene(0, 0, 400, 400);
QGraphicsTextItem *item = scene->addText("NoCache"); QGraphicsTextItem *item = scene->addText("NoCache");
item->setCacheMode(QGraphicsItem::NoCache); item->setCacheMode(QGraphicsItem::NoCache);
@ -1187,14 +1243,13 @@ public:
class MetricsTest : public QWidget class MetricsTest : public QWidget
{ {
QPlainTextEdit *m_textEdit; Q_OBJECT
public: public:
MetricsTest() MetricsTest()
{ {
qDebug() << R"( qDebug().noquote().nospace() << "MetricsTest " << QT_VERSION_STR
MetricsTest << ' ' << QGuiApplication::platformName() << '\n'
Relevant environment variables are: << R"(Relevant environment variables are:
QT_FONT_DPI=N QT_FONT_DPI=N
QT_SCALE_FACTOR=n QT_SCALE_FACTOR=n
QT_ENABLE_HIGHDPI_SCALING=0|1 QT_ENABLE_HIGHDPI_SCALING=0|1
@ -1205,12 +1260,23 @@ QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)";
resize(480, 360); resize(480, 360);
QVBoxLayout *layout = new QVBoxLayout(); auto layout = new QVBoxLayout(this);
setLayout(layout);
m_textEdit = new QPlainTextEdit; m_textEdit = new QPlainTextEdit;
m_textEdit->setReadOnly(true); m_textEdit->setReadOnly(true);
layout->addWidget(m_textEdit); layout->addWidget(m_textEdit);
setWindowTitle(formatWindowTitle("Screens"));
}
void setVisible(bool visible) override
{
QWidget::setVisible(visible);
if (visible && !m_screenChangedConnected) {
m_screenChangedConnected = true;
QObject::connect(windowHandle(), &QWindow::screenChanged,
this, &MetricsTest::screenChanged);
updateMetrics();
}
} }
void updateMetrics() void updateMetrics()
@ -1254,24 +1320,42 @@ QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)";
m_textEdit->setPlainText(text); m_textEdit->setPlainText(text);
} }
void paintEvent(QPaintEvent *ev) private slots:
void screenChanged()
{ {
// We get a paint event on screen change, so this is a convenient place qDebug().noquote() << __FUNCTION__ << windowHandle()->screen()->name();
// to update the metrics, at the possible risk of doing something else
// than painting in a paint event.
updateMetrics(); updateMetrics();
QWidget::paintEvent(ev);
} }
private:
QPlainTextEdit *m_textEdit;
bool m_screenChangedConnected = false;
}; };
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
#define NOSCALINGOPTION "noscaling"
#define SCALINGOPTION "scaling"
qInfo("High DPI tester %s", QT_VERSION_STR);
int preAppOptionCount = 0;
for (int a = 1; a < argc; ++a) {
if (qstrcmp(argv[a], "--" NOSCALINGOPTION) == 0) {
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
preAppOptionCount++;
qInfo("AA_DisableHighDpiScaling");
} else if (qstrcmp(argv[a], "--" SCALINGOPTION) == 0) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
preAppOptionCount++;
qInfo("AA_EnableHighDpiScaling");
}
}
QApplication app(argc, argv); QApplication app(argc, argv);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QCoreApplication::setApplicationVersion(QT_VERSION_STR); QCoreApplication::setApplicationVersion(QT_VERSION_STR);
int argumentCount = QCoreApplication::arguments().count();
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription("High DPI tester. Pass one or more of the options to\n" parser.setApplicationDescription("High DPI tester. Pass one or more of the options to\n"
"test various high-dpi aspects. \n" "test various high-dpi aspects. \n"
@ -1281,7 +1365,8 @@ int main(int argc, char **argv)
parser.addVersionOption(); parser.addVersionOption();
QCommandLineOption controllerOption("interactive", "Show configuration window."); QCommandLineOption controllerOption("interactive", "Show configuration window.");
parser.addOption(controllerOption); parser.addOption(controllerOption);
parser.addOption(QCommandLineOption(NOSCALINGOPTION, "Set AA_DisableHighDpiScaling"));
parser.addOption(QCommandLineOption(SCALINGOPTION, "Set AA_EnableHighDpiScaling"));
DemoContainerList demoList; DemoContainerList demoList;
demoList << new DemoContainer<PixmapPainter>("pixmap", "Test pixmap painter"); demoList << new DemoContainer<PixmapPainter>("pixmap", "Test pixmap painter");
@ -1300,17 +1385,17 @@ int main(int argc, char **argv)
demoList << new DemoContainer<ScreenDisplayer>("screens", "Test screen and window positioning"); demoList << new DemoContainer<ScreenDisplayer>("screens", "Test screen and window positioning");
demoList << new DemoContainer<PhysicalSizeTest>("physicalsize", "Test manual highdpi support using physicalDotsPerInch"); demoList << new DemoContainer<PhysicalSizeTest>("physicalsize", "Test manual highdpi support using physicalDotsPerInch");
demoList << new DemoContainer<GraphicsViewCaching>("graphicsview", "Test QGraphicsView caching"); demoList << new DemoContainer<GraphicsViewCaching>("graphicsview", "Test QGraphicsView caching");
demoList << new DemoContainer<MetricsTest>("metrics", "Show display metrics"); demoList << new DemoContainer<MetricsTest>("metrics", "Show screen metrics");
foreach (DemoContainerBase *demo, demoList) for (DemoContainerBase *demo : qAsConst(demoList))
parser.addOption(demo->option()); parser.addOption(demo->option());
parser.process(app); parser.process(app);
//controller takes ownership of all demos //controller takes ownership of all demos
DemoController controller(&demoList, &parser); DemoController controller(demoList, &parser);
if (parser.isSet(controllerOption) || argumentCount <= 1) if (parser.isSet(controllerOption) || (QCoreApplication::arguments().count() - preAppOptionCount) <= 1)
controller.show(); controller.show();
if (QApplication::topLevelWidgets().isEmpty()) if (QApplication::topLevelWidgets().isEmpty())