Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"

This commit is contained in:
Ulf Hermann 2019-12-03 06:55:21 +01:00 committed by Liang Qi
commit 25bcd8f08b
52 changed files with 762 additions and 397 deletions

View File

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

View File

@ -65,6 +65,7 @@
#include <QRadioButton>
#include <QScrollBar>
#include <QSpinBox>
#include <QStyle>
#include <QStyleFactory>
#include <QTableWidget>
#include <QTextEdit>
@ -77,8 +78,16 @@ WidgetGallery::WidgetGallery(QWidget *parent)
originalPalette = QApplication::palette();
styleComboBox = new QComboBox;
styleComboBox->addItem("NorwegianWood");
styleComboBox->addItems(QStyleFactory::keys());
const QString defaultStyleName = QApplication::style()->objectName();
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->setBuddy(styleComboBox);
@ -134,7 +143,6 @@ WidgetGallery::WidgetGallery(QWidget *parent)
setLayout(mainLayout);
setWindowTitle(tr("Styles"));
changeStyle("NorwegianWood");
}
//! [4]

View File

@ -173,11 +173,20 @@ macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATI
endif()
set(_static_link_flags \"${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${Configuration}_LINK_FLAGS}\")
if(NOT CMAKE_VERSION VERSION_LESS \"3.13\" AND _static_link_flags)
if(_static_link_flags)
set(_static_link_flags_genex \"$<${_genex_condition}:${_static_link_flags}>\")
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY INTERFACE_LINK_OPTIONS
\"${_static_link_flags_genex}\"
)
if(NOT CMAKE_VERSION VERSION_LESS \"3.13\")
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
@ -546,11 +555,20 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
endif()
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_property(TARGET Qt5::${Plugin} APPEND PROPERTY INTERFACE_LINK_OPTIONS
\"${_static_link_flags_genex}\"
)
if(NOT CMAKE_VERSION VERSION_LESS \"3.13\")
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
endmacro()

View File

@ -45,6 +45,8 @@ isEmpty(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)
qtPrepareTool(QTATTRIBUTIONSSCANNER, qtattributionsscanner)
@ -93,7 +95,6 @@ qtattributionsscanner.CONFIG += phony
QMAKE_EXTRA_TARGETS += qtattributionsscanner
doc_command = $$QDOC $$QMAKE_DOCS
prepare_docs {
prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors $$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
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
testcase_lowdpi {
macos {

View File

@ -385,7 +385,7 @@ if (NOT CMAKE_VERSION VERSION_LESS 2.8.9)
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG)
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG)
if (Qt5_POSITION_INDEPENDENT_CODE
AND (CMAKE_VERSION VERSION_LESS 2.8.12
AND (CMAKE_VERSION VERSION_GREATER_EQUAL 2.8.12
AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)))
set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE})

View File

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

View File

@ -244,6 +244,7 @@ QF16_MAKE_ARITH_OP_INT(/)
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-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); }

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/
**
** 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
instead (or Qt::SystemLocaleLongDate if you want long dates).
\value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format: either
\c{[ddd,] dd MMM yyyy hh:mm[:ss] +/-TZ} or \c{ddd MMM dd yyyy hh:mm[:ss] +/-TZ}
for combined dates and times.
\value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format:
either \c{[ddd,] dd MMM yyyy [hh:mm[:ss]][ ±tzoff]}
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
of the year, month and day used to specify the date. Each \c H, \c M and \c S

View File

@ -357,14 +357,14 @@ QT_BEGIN_NAMESPACE
/*!
\fn QString QStandardPaths::writableLocation(StandardLocation type)
\include standardpath/functiondoc.qdocinc writableLocation
\include standardpath/functiondocs.qdocinc writableLocation
*/
/*!
\fn QStringList QStandardPaths::standardLocations(StandardLocation type)
\include standardpath/functiondoc.qdocinc standardLocations
\include standardpath/functiondocs.qdocinc standardLocations
\sa writableLocation()
*/
@ -388,7 +388,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)
{
@ -402,7 +402,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)
{
@ -475,7 +475,7 @@ static inline QString
#endif // Q_OS_WIN
/*!
\include standardpath/functiondoc.qdocinc findExecutable
\include standardpath/functiondocs.qdocinc findExecutable
*/
QString QStandardPaths::findExecutable(const QString &executableName, const QStringList &paths)
{
@ -533,7 +533,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)
@ -590,7 +590,7 @@ QString QStandardPaths::displayName(StandardLocation type)
/*!
\fn void QStandardPaths::setTestModeEnabled(bool testMode)
\include standardpath/functiondoc.qdocinc setTestModeEnabled
\include standardpath/functiondocs.qdocinc setTestModeEnabled
*/
static bool qsp_testMode = false;

View File

@ -761,6 +761,85 @@ QT_BEGIN_NAMESPACE
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)
// in qcborstream.cpp
extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
@ -1390,77 +1469,10 @@ static QCborValue taggedValueFromCbor(QCborStreamReader &reader)
d->decodeValueFromCbor(reader);
}
QCborValue::Type type = QCborValue::Tag;
QCborValue::Type type;
if (reader.lastError() == QCborError::NoError) {
// post-process to create our extended types
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) {
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;
}
type = convertToExtendedType(d);
} else {
// decoding error
type = QCborValue::Invalid;
@ -1724,21 +1736,22 @@ QCborValue::QCborValue(const QCborMap &m)
}
/*!
\fn QCborValue::QCborValue(QCborTag t, const QCborValue &tv)
\fn QCborValue::QCborValue(QCborKnownTags t, const QCborValue &tv)
\fn QCborValue::QCborValue(QCborTag tag, const QCborValue &tv)
\fn QCborValue::QCborValue(QCborKnownTags tag, const QCborValue &tv)
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().
\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)
{
container->ref.storeRelaxed(1);
container->append(t);
container->append(tag);
container->append(tv);
t = convertToExtendedType(container);
}
/*!

View File

@ -164,8 +164,8 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s)
{
ParsedRfcDateTime result;
// Matches "Wdy, dd Mon yyyy HH:mm:ss ±hhmm" (Wdy, being optional)
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))?"));
// Matches "[ddd,] dd MMM yyyy[ hh:mm[:ss]] [±hhmm]" - correct RFC 822, 2822, 5322 format
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) {
const QStringList cap = rex.capturedTexts();
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();
result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
} else {
// Matches "Wdy Mon dd HH:mm:ss yyyy"
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))?"));
// Matches "ddd MMM dd[ hh:mm:ss] yyyy [±hhmm]" - permissive RFC 850, 1036 (read only)
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) {
const QStringList cap = rex.capturedTexts();
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>
** Contact: https://www.qt.io/licensing/
**
@ -53,9 +54,10 @@ QT_BEGIN_NAMESPACE
QAndroidTimeZonePrivate::QAndroidTimeZonePrivate()
: QTimeZonePrivate()
{
// start with system time zone
androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
init("UTC");
// Keep in sync with systemTimeZoneId():
androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod(
"java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
m_id = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;").toString().toUtf8();
}
// Create a named time zone
@ -76,32 +78,33 @@ QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate()
{
}
void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
{
QJNIObjectPrivate jo_ianaId = QJNIObjectPrivate::fromString( QString::fromUtf8(ianaId) );
androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;", static_cast<jstring>(jo_ianaId.object()) );
const QString iana = QString::fromUtf8(ianaId);
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
// recognize the name; so check for whether ianaId is a recognized name of
// the zone object we got and ignore the zone if not.
// Try checking ianaId against getID(), getDisplayName():
QJNIObjectPrivate jname = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;");
bool found = (jname.toString().toUtf8() == ianaId);
for (int style = 1; !found && style-- > 0;) {
for (int dst = 1; !found && dst-- > 0;) {
jname = androidTimeZone.callObjectMethod("getDisplayName", "(ZI;)Ljava/lang/String;",
bool(dst), style);
found = (jname.toString().toUtf8() == ianaId);
m_id = match(androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;"));
for (int style = 1; m_id.isEmpty() && style-- > 0;) {
for (int dst = 1; m_id.isEmpty() && dst-- > 0;) {
m_id = match(androidTimeZone.callObjectMethod(
"getDisplayName", "(ZI;)Ljava/lang/String;", bool(dst), style));
}
}
if (!found)
m_id.clear();
else if (ianaId.isEmpty())
m_id = systemTimeZoneId();
else
m_id = ianaId;
}
QAndroidTimeZonePrivate *QAndroidTimeZonePrivate::clone() const
@ -225,11 +228,10 @@ QTimeZonePrivate::Data QAndroidTimeZonePrivate::previousTransition(qint64 before
QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const
{
QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
QJNIObjectPrivate systemTZIdAndroid = androidSystemTimeZone.callObjectMethod<jstring>("getID");
QByteArray systemTZid = systemTZIdAndroid.toString().toUtf8();
return systemTZid;
// Keep in sync with default constructor:
QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod(
"java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
return androidSystemTimeZone.callObjectMethod<jstring>("getID").toString().toUtf8();
}
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>
** Contact: https://www.qt.io/licensing/
**
@ -94,6 +95,16 @@ void QMacTimeZonePrivate::init(const QByteArray &ianaId)
if (m_nstz)
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

View File

@ -352,6 +352,7 @@ Q_DECL_RELAXED_CONSTEXPR inline QPointF &QPointF::operator*=(qreal c)
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-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)
{

View File

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

View File

@ -215,6 +215,7 @@ private:
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE);
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_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal")
QT_WARNING_DISABLE_INTEL(1572)
inline bool QQuaternion::isNull() const
{
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_DISABLE_CLANG("-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)
{
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_DISABLE_CLANG("-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)
{
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_DISABLE_CLANG("-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)
{
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);
Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
GLenum storageFormat = GL_DEPTH_STENCIL;
if (samples != 0 ) {
funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
storageFormat, dsSize.width(), dsSize.height());
GL_DEPTH24_STENCIL8, dsSize.width(), dsSize.height());
} else {
funcs.glRenderbufferStorage(GL_RENDERBUFFER, storageFormat,
funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL,
dsSize.width(), dsSize.height());
}

View File

@ -388,8 +388,12 @@ static int qt_gl_resolve_extensions()
| QOpenGLExtensions::MapBufferRange
| QOpenGLExtensions::FramebufferBlit
| QOpenGLExtensions::FramebufferMultisample
| QOpenGLExtensions::Sized8Formats
| QOpenGLExtensions::TextureSwizzle;
| QOpenGLExtensions::Sized8Formats;
#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 {
// Recognize features by extension name.
if (extensionMatcher.match("GL_OES_packed_depth_stencil"))

View File

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

View File

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

View File

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

View File

@ -92,6 +92,7 @@
#endif
#include <algorithm>
#include <memory>
#include <string.h>
@ -1957,6 +1958,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
const std::unique_ptr<X509_STORE, decltype(&q_X509_STORE_free)> storeGuard(certStore, q_X509_STORE_free);
if (s_loadRootCertsOnDemand) {
setDefaultCaCertificates(defaultCaCertificates() + systemCaCertificates());
@ -1997,7 +1999,6 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null();
if (!intermediates) {
q_X509_STORE_free(certStore);
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
@ -2015,14 +2016,12 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
X509_STORE_CTX *storeContext = q_X509_STORE_CTX_new();
if (!storeContext) {
q_X509_STORE_free(certStore);
errors << QSslError(QSslError::UnspecifiedError);
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)) {
q_X509_STORE_CTX_free(storeContext);
q_X509_STORE_free(certStore);
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
@ -2031,8 +2030,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
// We ignore the result of this function since we process errors via the
// callback.
(void) q_X509_verify_cert(storeContext);
q_X509_STORE_CTX_free(storeContext);
ctxGuard.reset();
q_OPENSSL_sk_free((OPENSSL_STACK *)intermediates);
// Now process the errors
@ -2054,8 +2052,6 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
for (const auto &error : qAsConst(lastErrors))
errors << _q_OpenSSL_to_QSslError(error.code, certificateChain.value(error.depth));
q_X509_STORE_free(certStore);
return errors;
}

View File

@ -374,17 +374,6 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>::fontEngine
QCFType<CTFontDescriptorRef> descriptor = QCFType<CTFontDescriptorRef>::constructFromGet(
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
// 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

View File

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

View File

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

View File

@ -134,7 +134,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
NSImage *nsimage = qt_mac_create_nsimage(pm);
[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"));
dragBoard.setMimeData(m_drag->mimeData(), QMacPasteboard::LazyRequest);
@ -145,7 +145,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
CGFloat flippedY = pmDeviceIndependentSize.height() - hotSpot.y();
event_location.y -= flippedY;
NSSize mouseOffset_unused = NSMakeSize(0.0, 0.0);
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSPasteboardNameDrag];
[theWindow dragImage:nsimage
at:event_location

View File

@ -200,16 +200,6 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
[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();
QMacInternalPasteboardMime::initializeMimeTypes();

View File

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

View File

@ -781,12 +781,16 @@
- (UIView *)textInputView
{
auto *focusWindow = QGuiApplication::focusWindow();
if (!focusWindow)
return nil;
// iOS expects rects we return from other UITextInput methods
// to be relative to the view this method returns.
// Since QInputMethod returns rects relative to the top level
// QWindow, that is also the view we need to return.
Q_ASSERT(qApp->focusWindow()->handle());
QPlatformWindow *topLevel = qApp->focusWindow()->handle();
Q_ASSERT(focusWindow->handle());
QPlatformWindow *topLevel = focusWindow->handle();
while (QPlatformWindow *p = topLevel->parent())
topLevel = p;
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
// the caret would actually be visible (QTBUG-74492) and the workaround for
// the Surface seems unnecessary there anyway. But leave it hidden for IME.
if (QOperatingSystemVersion::current() >=
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 16299)) {
// Only trigger the native OSK if the Qt OSK is not in use.
static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE");
if (imModuleEmpty
&& QOperatingSystemVersion::current()
>= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 16299)) {
ShowCaret(platformWindow->handle());
} else {
HideCaret(platformWindow->handle());

View File

@ -390,7 +390,17 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
setVariantI4(UIA_WindowControlTypeId, pRetVal);
} else {
// 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;
case UIA_HelpTextPropertyId:

View File

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

View File

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

View File

@ -274,6 +274,12 @@ void drawDial(const QStyleOptionSlider *option, QPainter *painter)
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
BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("qdial"));
p->setRenderHint(QPainter::Antialiasing);
@ -285,9 +291,6 @@ void drawDial(const QStyleOptionSlider *option, QPainter *painter)
QRectF br = QRectF(dx + 0.5, dy + 0.5,
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) {
// Drop shadow

View File

@ -1198,12 +1198,18 @@ QMargins QLineEdit::textMargins() const
Unset the mask and return to normal QLineEdit operation by passing
an empty string ("").
The table below shows the characters that can be used in an input mask.
A space character, the default character for a blank, is needed for cases
where a character is \e{permitted but not required}.
The input mask is an input template string. It can contain the following elements:
\table
\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
\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 permitted but not required.
\row \li \c N \li ASCII alphanumeric character required. A-Z, a-z, 0-9.
@ -1219,19 +1225,28 @@ QMargins QLineEdit::textMargins() const
\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 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 lowercased.
\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 \tt{\\} \li Use \tt{\\} to escape the special
characters listed above to use them as
separators.
\endtable
The mask consists of a string of mask characters and separators,
optionally followed by a semicolon and the character used for
blanks. The blank characters are always removed from the text
after editing.
When created or cleared, the line edit will be filled with a copy of the
input mask string where the meta characters have been removed, and the mask
characters have been replaced with the \e{blank} character (by default, a
\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:
\table
@ -1240,7 +1255,7 @@ QMargins QLineEdit::textMargins() const
\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 >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.
\endtable

View File

@ -40,6 +40,7 @@
#include <QtCore/qcborvalue.h>
#include <QtTest>
Q_DECLARE_METATYPE(QCborKnownTags)
Q_DECLARE_METATYPE(QCborValue)
Q_DECLARE_METATYPE(QCborValue::EncodingOptions)
@ -294,34 +295,77 @@ void tst_QCborValue::tagged()
void tst_QCborValue::extendedTypes_data()
{
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 dtTzOffset(dt.date(), dt.time(), Qt::OffsetFromUTC, dt.offsetFromUtc());
QUuid uuid = QUuid::createUuid();
// non-correcting extended types (tagged value remains unchanged)
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())
<< QCborValue(QCborKnownTags::Url, QString());
<< QCborKnownTags::Url << QCborValue(QString()) << v;
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"))
<< 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"))
<< 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())
<< QCborValue(QCborKnownTags::RegularExpression, QString());
<< QCborKnownTags::RegularExpression << QCborValue(QString()) << v;
QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$"))
<< QCborValue(QCborKnownTags::RegularExpression, QString("^.*$"));
<< QCborKnownTags::RegularExpression << QCborValue(QString("^.*$")) << v;
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()
{
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(tagged.isTag());
QCOMPARE(tagged.taggedValue(), correctedTaggedValue);
QVERIFY(extended == tagged);
QVERIFY(tagged == extended);
@ -1224,8 +1268,11 @@ void tst_QCborValue::sorting()
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 vdt1(QDateTime::fromMSecsSinceEpoch(0, Qt::UTC)), vdt2(QDateTime::currentDateTimeUtc());
QCborValue vtagged1(QCborKnownTags::UnixTime_t, 0), vtagged2(QCborKnownTags::UnixTime_t, 0.0),
vtagged3(QCborKnownTags::Signature, 0), vtagged4(QCborTag(-2), 0), vtagged5(QCborTag(-1), 0);
QCborValue vtagged1(QCborKnownTags::PositiveBignum, QByteArray()),
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 vuuid1{QUuid()}, vuuid2(QUuid::createUuid());
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"))
<< raw("\xd8\x20\x78\x27" "https://example.com/{01}?q=<a+b \xC2\xA9>&%26")
<< 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") << QCborValue(QRegularExpression("^.*$"))
<< raw("\xd8\x23\x64" "^.*$") << noxfrm;

View File

@ -1136,8 +1136,14 @@ void tst_QDate::fromStringDateFormat_data()
// Test Qt::RFC2822Date format (RFC 2822).
QTest::newRow("RFC 2822") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100")
<< 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")
<< 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
QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34")
<< Qt::RFC2822Date << QDate(1970, 1, 1);
@ -1153,38 +1159,56 @@ void tst_QDate::fromStringDateFormat_data()
<< Qt::RFC2822Date << QDate();
QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100")
<< Qt::RFC2822Date << QDate();
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!")
// 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!")
<< 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);
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")
<< 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
QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970")
<< Qt::RFC2822Date << QDate(1970, 1, 1);
// No time specified
QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002")
<< Qt::RFC2822Date << QDate(2002, 11, 1);
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!")
// 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!")
<< 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();
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();
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();
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();
// 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();
}

View File

@ -1003,8 +1003,9 @@ void tst_QDateTime::toString_rfcDate()
// Set to non-English locale to confirm still uses English
QLocale oldLocale;
QLocale::setDefault(QLocale("de_DE"));
QCOMPARE(dt.toString(Qt::RFC2822Date), formatted);
QString actual(dt.toString(Qt::RFC2822Date));
QLocale::setDefault(oldLocale);
QCOMPARE(actual, formatted);
}
void tst_QDateTime::toString_enumformat()
@ -2310,8 +2311,14 @@ void tst_QDateTime::fromStringDateFormat_data()
// Test Qt::RFC2822Date format (RFC 2822).
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);
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")
<< 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")
<< 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")
@ -2324,6 +2331,11 @@ void tst_QDateTime::fromStringDateFormat_data()
<< 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")
<< 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
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);
@ -2339,21 +2351,34 @@ void tst_QDateTime::fromStringDateFormat_data()
<< Qt::RFC2822Date << invalidDateTime();
QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100")
<< Qt::RFC2822Date << invalidDateTime();
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!")
// 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!")
<< 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();
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();
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();
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();
// 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")
<< 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")
<< 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")
@ -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")
<< Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC);
// 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();
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!")
// 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!")
<< 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();
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();
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();
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();
// 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();
}

View File

@ -619,8 +619,14 @@ void tst_QTime::fromStringDateFormat_data()
// Test Qt::RFC2822Date format (RFC 2822).
QTest::newRow("RFC 2822") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100")
<< 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")
<< 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
QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34")
<< Qt::RFC2822Date << QTime(0, 12, 34);
@ -636,36 +642,58 @@ void tst_QTime::fromStringDateFormat_data()
<< Qt::RFC2822Date << QTime(13, 24, 51);
QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100")
<< Qt::RFC2822Date << QTime(13, 24, 51);
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!")
// 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!")
<< 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();
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();
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();
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();
// 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")
<< 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
QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970")
<< Qt::RFC2822Date << QTime(0, 12, 34);
// No time specified
QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002")
<< Qt::RFC2822Date << invalidTime();
// Test invalid characters (should ignore invalid characters at end of string).
QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!")
// 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!")
<< 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();
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();
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();
// 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();
}

View File

@ -46,6 +46,7 @@ private slots:
// Public class default system tests
void createTest();
void nullTest();
void systemZone();
void dataStreamTest();
void isTimeZoneIdAvailable();
void availableTimeZoneIds();
@ -317,6 +318,14 @@ void tst_QTimeZone::nullTest()
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()
{
// Test the OffsetFromUtc backend serialization. First with a custom timezone:

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 <qsslcertificateextension.h>
#ifndef QT_NO_OPENSSL
#include <openssl/obj_mac.h>
#endif
class tst_QSslCertificate : public QObject
{
Q_OBJECT
@ -960,8 +964,12 @@ void tst_QSslCertificate::subjectAndIssuerAttributes()
certList = QSslCertificate::fromPath(testDataDir + "more-certificates/natwest-banking.pem");
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();
QVERIFY(attributes.contains(QByteArray("1.3.6.1.4.1.311.60.2.1.3")));
QVERIFY(attributes.contains(shortName));
}
void tst_QSslCertificate::verify()

View File

@ -4922,13 +4922,27 @@ void tst_QTreeView::taskQTBUG_61476()
const QPoint pos = rect.center();
QTest::mousePress(tv.viewport(), Qt::LeftButton, {}, pos);
if (tv.style()->styleHint(QStyle::SH_ListViewExpand_SelectMouseType, nullptr, &tv) ==
QEvent::MouseButtonPress)
const bool expandsOnPress =
(tv.style()->styleHint(QStyle::SH_ListViewExpand_SelectMouseType, nullptr, &tv) == QEvent::MouseButtonPress);
if (expandsOnPress)
QTRY_VERIFY(!tv.isExpanded(mi));
QTest::mouseRelease(tv.viewport(), Qt::LeftButton, {}, pos);
QTRY_VERIFY(!tv.isExpanded(mi));
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)

View File

@ -53,6 +53,7 @@
#include <qmainwindow.h>
#include <qdockwidget.h>
#include <qrandom.h>
#include <qstylehints.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <QtCore/qoperatingsystemversion.h>
@ -198,6 +199,7 @@ private slots:
void hideWhenFocusWidgetIsChild();
void normalGeometry();
void setGeometry();
void setGeometryHidden();
void windowOpacity();
void raise();
void lower();
@ -2946,6 +2948,38 @@ void tst_QWidget::setGeometry()
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()
{
QWidget widget;

View File

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

View File

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

View File

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