summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-05-04 11:33:10 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2020-05-04 17:38:40 +0200
commit0f7987f0c934b311bd39a5a496ffb0c6128eb8df (patch)
treedea392deb3c43e377a224271c4f450dcff3fc76f /src
parentea7d85457d30e915ad470919d2e74867cba9cad8 (diff)
parentf0ea852d4dd6b3139869a952ee92e74cd367866d (diff)
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts: src/corelib/text/qlocale.cpp src/network/access/qnetworkaccessmanager.cpp Regenerated tests/auto/testlib/selftests/float/CMakeLists.txt Change-Id: I5a8ae42511380ca49a38b13c6fa8a3c5df8bed01
Diffstat (limited to 'src')
-rw-r--r--src/corelib/serialization/qcborvalue.cpp45
-rw-r--r--src/corelib/serialization/qjsonobject.cpp8
-rw-r--r--src/corelib/text/qstring.cpp32
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp29
-rw-r--r--src/gui/image/qimage_conversions.cpp44
-rw-r--r--src/gui/kernel/qevent.cpp1
-rw-r--r--src/gui/painting/qcoregraphics.mm9
-rw-r--r--src/gui/text/qfont.cpp11
-rw-r--r--src/network/access/qnetworkaccesscachebackend.cpp6
-rw-r--r--src/network/access/qnetworkaccesscachebackend_p.h1
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp2
-rw-r--r--src/network/access/qnetworkreplywasmimpl.cpp2
-rw-r--r--src/network/kernel/qauthenticator.cpp8
-rw-r--r--src/network/ssl/qasn1element.cpp7
-rw-r--r--src/network/ssl/qdtls.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.mm11
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm36
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindowmanager.mm12
-rw-r--r--src/plugins/platforms/cocoa/qmultitouch_mac.mm5
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.mm82
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm13
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm11
-rw-r--r--src/plugins/platforms/ios/qiostheme.h5
-rw-r--r--src/plugins/platforms/ios/qiostheme.mm38
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm10
-rw-r--r--src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp2
-rw-r--r--src/testlib/qtestcase.cpp17
-rw-r--r--src/testlib/qtestcase.qdoc21
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp6
-rw-r--r--src/widgets/doc/snippets/customviewstyle.cpp7
-rw-r--r--src/widgets/doc/snippets/filedialogurls.cpp8
-rw-r--r--src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp17
-rw-r--r--src/widgets/doc/snippets/graphicsview.cpp64
-rw-r--r--src/widgets/doc/snippets/graphicsview_snippet.cpp63
-rw-r--r--src/widgets/doc/snippets/mdiareasnippets.cpp3
-rw-r--r--src/widgets/doc/snippets/myscrollarea.cpp23
-rw-r--r--src/widgets/doc/snippets/snippets.pro16
-rw-r--r--src/widgets/doc/src/graphicsview.qdoc2
-rw-r--r--src/widgets/widgets/qmenu.cpp13
40 files changed, 501 insertions, 195 deletions
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index a3f93e5eed..7d6782cd7f 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -788,17 +788,34 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
// 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);
+ } else if (tag == qint64(QCborKnownTags::UnixTime_t)) {
+ qint64 msecs;
+ bool ok = false;
+ if (e.type == QCborValue::Integer) {
+#if QT_POINTER_SIZE == 8
+ // we don't have a fast 64-bit mul_overflow implementation on
+ // 32-bit architectures.
+ ok = !mul_overflow(e.value, qint64(1000), &msecs);
+#else
+ static const qint64 Limit = std::numeric_limits<qint64>::max() / 1000;
+ ok = (e.value > -Limit && e.value < Limit);
+ if (ok)
+ msecs = e.value * 1000;
+#endif
+ } else if (e.type == QCborValue::Double) {
+ ok = convertDoubleTo(round(e.fpvalue() * 1000), &msecs);
+ }
+ if (ok)
+ dt = QDateTime::fromMSecsSinceEpoch(msecs, 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;
+ if (!text.isEmpty()) {
+ replaceByteData(text, text.size(), Element::StringIsAscii);
+ e.type = QCborValue::String;
+ d->elements[0].value = qint64(QCborKnownTags::DateTimeString);
+ return QCborValue::DateTime;
+ }
}
break;
}
@@ -810,9 +827,11 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
// 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(), {});
+ b->toUtf8String(), QUrl::StrictMode);
+ if (url.isValid()) {
+ QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8();
+ replaceByteData(encoded, encoded.size(), {});
+ }
}
return QCborValue::Url;
}
@@ -1561,8 +1580,6 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
if (newSize > MaxByteArraySize)
return -1;
- // since usedData <= data.size(), this can't overflow
- usedData += increment;
data.resize(newSize);
return offset;
};
@@ -1635,7 +1652,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
}
// update size
- if (e.flags & Element::HasByteData) {
+ if (r.status == QCborStreamReader::EndOfString && e.flags & Element::HasByteData) {
auto b = new (dataPtr() + e.value) ByteData;
b->len = data.size() - e.value - int(sizeof(*b));
usedData += b->len;
diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp
index a03855d4a3..bf2bdb957d 100644
--- a/src/corelib/serialization/qjsonobject.cpp
+++ b/src/corelib/serialization/qjsonobject.cpp
@@ -577,7 +577,7 @@ void QJsonObject::removeImpl(T key)
if (!keyExists)
return;
- removeAt(index);
+ removeAt(index / 2);
}
#if QT_STRINGVIEW_LEVEL < 2
@@ -629,7 +629,7 @@ QJsonValue QJsonObject::takeImpl(T key)
return QJsonValue(QJsonValue::Undefined);
const QJsonValue v = QJsonPrivate::Value::fromTrustedCbor(o->extractAt(index + 1));
- removeAt(index);
+ removeAt(index / 2);
return v;
}
@@ -1486,8 +1486,8 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val)
void QJsonObject::removeAt(int index)
{
detach2();
- o->removeAt(index + 1);
- o->removeAt(index);
+ o->removeAt(2 * index + 1);
+ o->removeAt(2 * index);
}
size_t qHash(const QJsonObject &object, size_t seed)
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 6eb84f6c99..f87cf41bf1 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -1781,57 +1781,39 @@ const QString::Null QString::null = { };
/*! \typedef QString::const_iterator
- This typedef provides an STL-style const iterator for QString.
-
\sa QString::iterator
*/
/*! \typedef QString::iterator
- The QString::iterator typedef provides an STL-style non-const
- iterator for QString.
-
\sa QString::const_iterator
*/
/*! \typedef QString::const_reverse_iterator
\since 5.6
- This typedef provides an STL-style const reverse iterator for QString.
-
\sa QString::reverse_iterator, QString::const_iterator
*/
/*! \typedef QString::reverse_iterator
\since 5.6
- This typedef provides an STL-style non-const reverse iterator for QString.
-
\sa QString::const_reverse_iterator, QString::iterator
*/
/*!
\typedef QString::size_type
-
- The QString::size_type typedef provides an STL-style type for sizes (int).
*/
/*!
\typedef QString::difference_type
-
- The QString::size_type typedef provides an STL-style type for difference between pointers.
*/
/*!
\typedef QString::const_reference
-
- This typedef provides an STL-style const reference for a QString element (QChar).
*/
/*!
\typedef QString::reference
-
- This typedef provides an STL-style
- reference for a QString element (QChar).
*/
/*!
@@ -1849,8 +1831,6 @@ const QString::Null QString::null = { };
/*!
\typedef QString::value_type
-
- This typedef provides an STL-style value type for QString.
*/
/*! \fn QString::iterator QString::begin()
@@ -9397,8 +9377,6 @@ QString &QString::setRawData(const QChar *unicode, int size)
\typedef QLatin1String::iterator
\since 5.10
- This typedef provides an STL-style const iterator for QLatin1String.
-
QLatin1String does not support mutable iterators, so this is the same
as const_iterator.
@@ -9409,8 +9387,6 @@ QString &QString::setRawData(const QChar *unicode, int size)
\typedef QLatin1String::const_iterator
\since 5.10
- This typedef provides an STL-style const iterator for QLatin1String.
-
\sa iterator, const_reverse_iterator
*/
@@ -9418,8 +9394,6 @@ QString &QString::setRawData(const QChar *unicode, int size)
\typedef QLatin1String::reverse_iterator
\since 5.10
- This typedef provides an STL-style const reverse iterator for QLatin1String.
-
QLatin1String does not support mutable reverse iterators, so this is the
same as const_reverse_iterator.
@@ -9430,8 +9404,6 @@ QString &QString::setRawData(const QChar *unicode, int size)
\typedef QLatin1String::const_reverse_iterator
\since 5.10
- This typedef provides an STL-style const reverse iterator for QLatin1String.
-
\sa reverse_iterator, const_iterator
*/
@@ -10332,8 +10304,6 @@ QDataStream &operator>>(QDataStream &in, QString &str)
\typedef QStringRef::const_iterator
\since 5.4
- This typedef provides an STL-style const iterator for QStringRef.
-
\sa QStringRef::const_reverse_iterator
*/
@@ -10341,8 +10311,6 @@ QDataStream &operator>>(QDataStream &in, QString &str)
\typedef QStringRef::const_reverse_iterator
\since 5.7
- This typedef provides an STL-style const reverse iterator for QStringRef.
-
\sa QStringRef::const_iterator
*/
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index 48501f5271..a3d2a2f7c0 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -1063,18 +1063,23 @@ QString QCommandLineParser::helpText() const
return d->helpText(false);
}
-static QString wrapText(const QString &names, int longestOptionNameString, const QString &description)
+static QString wrapText(const QString &names, int optionNameMaxWidth, const QString &description)
{
const QLatin1Char nl('\n');
const QLatin1String indentation(" ");
- if (description.isEmpty())
- return indentation + names + nl;
- QString text = indentation + names.leftJustified(longestOptionNameString) + QLatin1Char(' ');
- const int indent = text.length();
+ // In case the list of option names is very long, wrap it as well
+ int nameIndex = 0;
+ auto nextNameSection = [&]() {
+ QString section = names.mid(nameIndex, optionNameMaxWidth);
+ nameIndex += section.size();
+ return section;
+ };
+
+ QString text;
int lineStart = 0;
int lastBreakable = -1;
- const int max = 79 - indent;
+ const int max = 79 - (indentation.size() + optionNameMaxWidth + 1);
int x = 0;
const int len = description.length();
@@ -1103,8 +1108,7 @@ static QString wrapText(const QString &names, int longestOptionNameString, const
if (breakAt != -1) {
const int numChars = breakAt - lineStart;
//qDebug() << "breakAt=" << description.at(breakAt) << "breakAtSpace=" << breakAtSpace << lineStart << "to" << breakAt << description.mid(lineStart, numChars);
- if (lineStart > 0)
- text += QString(indent, QLatin1Char(' '));
+ text += indentation + nextNameSection().leftJustified(optionNameMaxWidth) + QLatin1Char(' ');
text += description.midRef(lineStart, numChars) + nl;
x = 0;
lastBreakable = -1;
@@ -1115,6 +1119,10 @@ static QString wrapText(const QString &names, int longestOptionNameString, const
}
}
+ while (nameIndex < names.size()) {
+ text += indentation + nextNameSection() + nl;
+ }
+
return text;
}
@@ -1158,11 +1166,12 @@ QString QCommandLineParserPrivate::helpText(bool includeQtOptions) const
longestOptionNameString = qMax(longestOptionNameString, optionNamesString.length());
}
++longestOptionNameString;
+ const int optionNameMaxWidth = qMin(50, longestOptionNameString);
auto optionNameIterator = optionNameList.cbegin();
for (const QCommandLineOption &option : qAsConst(options)) {
if (option.flags() & QCommandLineOption::HiddenFromHelp)
continue;
- text += wrapText(*optionNameIterator, longestOptionNameString, option.description());
+ text += wrapText(*optionNameIterator, optionNameMaxWidth, option.description());
++optionNameIterator;
}
if (!positionalArgumentDefinitions.isEmpty()) {
@@ -1170,7 +1179,7 @@ QString QCommandLineParserPrivate::helpText(bool includeQtOptions) const
text += nl;
text += QCommandLineParser::tr("Arguments:") + nl;
for (const PositionalArgumentDefinition &arg : positionalArgumentDefinitions)
- text += wrapText(arg.name, longestOptionNameString, arg.description);
+ text += wrapText(arg.name, optionNameMaxWidth, arg.description);
}
return text;
}
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 34d2b8d8c7..506ebc797f 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -2016,6 +2016,21 @@ static void convert_Mono_to_Indexed8(QImageData *dest, const QImageData *src, Qt
}
}
+static void copy_8bit_pixels(QImageData *dest, const QImageData *src)
+{
+ if (src->bytes_per_line == dest->bytes_per_line) {
+ memcpy(dest->data, src->data, src->bytes_per_line * src->height);
+ } else {
+ const uchar *sdata = src->data;
+ uchar *ddata = dest->data;
+ for (int y = 0; y < src->height; ++y) {
+ memcpy(ddata, sdata, src->width);
+ sdata += src->bytes_per_line;
+ ddata += dest->bytes_per_line;
+ }
+ }
+}
+
static void convert_Indexed8_to_Alpha8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->format == QImage::Format_Indexed8);
@@ -2031,11 +2046,15 @@ static void convert_Indexed8_to_Alpha8(QImageData *dest, const QImageData *src,
}
if (simpleCase)
- memcpy(dest->data, src->data, src->bytes_per_line * src->height);
+ copy_8bit_pixels(dest, src);
else {
- qsizetype size = src->bytes_per_line * src->height;
- for (qsizetype i = 0; i < size; ++i) {
- dest->data[i] = translate[src->data[i]];
+ const uchar *sdata = src->data;
+ uchar *ddata = dest->data;
+ for (int y = 0; y < src->height; ++y) {
+ for (int x = 0; x < src->width; ++x)
+ ddata[x] = translate[sdata[x]];
+ sdata += src->bytes_per_line;
+ ddata += dest->bytes_per_line;
}
}
}
@@ -2055,11 +2074,15 @@ static void convert_Indexed8_to_Grayscale8(QImageData *dest, const QImageData *s
}
if (simpleCase)
- memcpy(dest->data, src->data, src->bytes_per_line * src->height);
+ copy_8bit_pixels(dest, src);
else {
- qsizetype size = src->bytes_per_line * src->height;
- for (qsizetype i = 0; i < size; ++i) {
- dest->data[i] = translate[src->data[i]];
+ const uchar *sdata = src->data;
+ uchar *ddata = dest->data;
+ for (int y = 0; y < src->height; ++y) {
+ for (int x = 0; x < src->width; ++x)
+ ddata[x] = translate[sdata[x]];
+ sdata += src->bytes_per_line;
+ ddata += dest->bytes_per_line;
}
}
}
@@ -2107,7 +2130,7 @@ static void convert_Alpha8_to_Indexed8(QImageData *dest, const QImageData *src,
Q_ASSERT(src->format == QImage::Format_Alpha8);
Q_ASSERT(dest->format == QImage::Format_Indexed8);
- memcpy(dest->data, src->data, src->bytes_per_line * src->height);
+ copy_8bit_pixels(dest, src);
dest->colortable = defaultColorTables->alpha;
}
@@ -2117,8 +2140,7 @@ static void convert_Grayscale8_to_Indexed8(QImageData *dest, const QImageData *s
Q_ASSERT(src->format == QImage::Format_Grayscale8);
Q_ASSERT(dest->format == QImage::Format_Indexed8);
- memcpy(dest->data, src->data, src->bytes_per_line * src->height);
-
+ copy_8bit_pixels(dest, src);
dest->colortable = defaultColorTables->gray;
}
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 834f969680..13a5bbb009 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -951,6 +951,7 @@ QWheelEvent::~QWheelEvent()
/*!
\fn QPoint QWheelEvent::position() const
+ \since 5.14
Returns the position of the mouse cursor relative to the widget
that received the event.
diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm
index 1125a9183c..0030e8e29c 100644
--- a/src/gui/painting/qcoregraphics.mm
+++ b/src/gui/painting/qcoregraphics.mm
@@ -162,12 +162,12 @@ QT_END_NAMESPACE
if (icon.isNull())
return nil;
- auto nsImage = [[NSImage alloc] initWithSize:NSZeroSize];
-
auto availableSizes = icon.availableSizes();
if (availableSizes.isEmpty() && size > 0)
availableSizes << QSize(size, size);
+ auto nsImage = [[[NSImage alloc] initWithSize:NSZeroSize] autorelease];
+
for (QSize size : qAsConst(availableSizes)) {
QImage image = icon.pixmap(size).toImage();
if (image.isNull())
@@ -182,12 +182,15 @@ QT_END_NAMESPACE
[nsImage addRepresentation:[imageRep autorelease]];
}
+ if (!nsImage.representations.count)
+ return nil;
+
[nsImage setTemplate:icon.isMask()];
if (size)
nsImage.size = CGSizeMake(size, size);
- return [nsImage autorelease];
+ return nsImage;
}
@end
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 959566d4c1..cb87cfa09b 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -420,7 +420,9 @@ QFontEngineData::~QFontEngineData()
be removed with removeSubstitutions(). Use substitute() to retrieve
a family's first substitute, or the family name itself if it has
no substitutes. Use substitutes() to retrieve a list of a family's
- substitutes (which may be empty).
+ substitutes (which may be empty). After substituting a font, you must
+ trigger the updating of the font by destroying and re-creating all
+ QFont objects.
Every QFont has a key() which you can use, for example, as the key
in a cache or dictionary. If you want to store a user's font
@@ -1864,6 +1866,9 @@ QStringList QFont::substitutes(const QString &familyName)
Inserts \a substituteName into the substitution
table for the family \a familyName.
+ After substituting a font, trigger the updating of the font by destroying
+ and re-creating all QFont objects.
+
\sa insertSubstitutions(), removeSubstitutions(), substitutions(), substitute(), substitutes()
*/
void QFont::insertSubstitution(const QString &familyName,
@@ -1882,6 +1887,10 @@ void QFont::insertSubstitution(const QString &familyName,
Inserts the list of families \a substituteNames into the
substitution list for \a familyName.
+ After substituting a font, trigger the updating of the font by destroying
+ and re-creating all QFont objects.
+
+
\sa insertSubstitution(), removeSubstitutions(), substitutions(), substitute()
*/
void QFont::insertSubstitutions(const QString &familyName,
diff --git a/src/network/access/qnetworkaccesscachebackend.cpp b/src/network/access/qnetworkaccesscachebackend.cpp
index 22fdc5bb0b..4986b36ab1 100644
--- a/src/network/access/qnetworkaccesscachebackend.cpp
+++ b/src/network/access/qnetworkaccesscachebackend.cpp
@@ -123,6 +123,12 @@ bool QNetworkAccessCacheBackend::sendCacheContents()
return true;
}
+bool QNetworkAccessCacheBackend::start()
+{
+ open();
+ return true;
+}
+
void QNetworkAccessCacheBackend::closeDownstreamChannel()
{
}
diff --git a/src/network/access/qnetworkaccesscachebackend_p.h b/src/network/access/qnetworkaccesscachebackend_p.h
index dfb0ce84d9..ceb02946dc 100644
--- a/src/network/access/qnetworkaccesscachebackend_p.h
+++ b/src/network/access/qnetworkaccesscachebackend_p.h
@@ -68,6 +68,7 @@ public:
void open() override;
void closeDownstreamChannel() override;
void closeUpstreamChannel();
+ bool start() override;
void upstreamReadyRead();
void downstreamReadyWrite() override;
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index e5414665de..1c5e29f8ac 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp
index af8b39bab6..5b84014789 100644
--- a/src/network/access/qnetworkreplywasmimpl.cpp
+++ b/src/network/access/qnetworkreplywasmimpl.cpp
@@ -245,7 +245,7 @@ void QNetworkReplyWasmImplPrivate::doSendRequest()
attr.password = request.url().password().toUtf8();
}
- attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_PERSIST_FILE | EMSCRIPTEN_FETCH_REPLACE;
+ attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
QNetworkRequest::CacheLoadControl CacheLoadControlAttribute =
(QNetworkRequest::CacheLoadControl)request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt();
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp
index c95b1280b0..3ac54605e4 100644
--- a/src/network/kernel/qauthenticator.cpp
+++ b/src/network/kernel/qauthenticator.cpp
@@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE
static QByteArray qNtlmPhase1();
static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phase2data);
#if QT_CONFIG(sspi) // SSPI
+static bool q_SSPI_library_load();
static QByteArray qSspiStartup(QAuthenticatorPrivate *ctx, QAuthenticatorPrivate::Method method,
const QString& host);
static QByteArray qSspiContinue(QAuthenticatorPrivate *ctx, QAuthenticatorPrivate::Method method,
@@ -503,8 +504,13 @@ QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMet
if (challenge.isEmpty()) {
#if QT_CONFIG(sspi) // SSPI
QByteArray phase1Token;
- if (user.isEmpty()) // Only pull from system if no user was specified in authenticator
+ if (user.isEmpty()) { // Only pull from system if no user was specified in authenticator
phase1Token = qSspiStartup(this, method, host);
+ } else if (!q_SSPI_library_load()) {
+ // Since we're not running qSspiStartup we have to make sure the library is loaded
+ qWarning("Failed to load the SSPI libraries");
+ return "";
+ }
if (!phase1Token.isEmpty()) {
response = phase1Token.toBase64();
phase = Phase2;
diff --git a/src/network/ssl/qasn1element.cpp b/src/network/ssl/qasn1element.cpp
index 6558643386..5634332a67 100644
--- a/src/network/ssl/qasn1element.cpp
+++ b/src/network/ssl/qasn1element.cpp
@@ -45,6 +45,7 @@
#include <QtCore/qvector.h>
#include <QDebug>
+#include <limits>
#include <locale>
QT_BEGIN_NAMESPACE
@@ -120,7 +121,7 @@ bool QAsn1Element::read(QDataStream &stream)
return false;
// length
- qint64 length = 0;
+ quint64 length = 0;
quint8 first;
stream >> first;
if (first & 0x80) {
@@ -139,11 +140,13 @@ bool QAsn1Element::read(QDataStream &stream)
length = (first & 0x7f);
}
+ if (length > quint64(std::numeric_limits<int>::max()))
+ return false;
// value
QByteArray tmpValue;
tmpValue.resize(length);
int count = stream.readRawData(tmpValue.data(), tmpValue.size());
- if (count != length)
+ if (count != int(length))
return false;
mType = tmpType;
diff --git a/src/network/ssl/qdtls.cpp b/src/network/ssl/qdtls.cpp
index a2280a7d10..74fb691dde 100644
--- a/src/network/ssl/qdtls.cpp
+++ b/src/network/ssl/qdtls.cpp
@@ -278,8 +278,6 @@
/*!
\typedef QDtls::GeneratorParameters
-
- This is a synonym for QDtlsClientVerifier::GeneratorParameters.
*/
/*!
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index e0dd103fbc..2d19809435 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -481,7 +481,9 @@ QList<QCocoaWindow *> *QCocoaIntegration::popupWindowStack()
void QCocoaIntegration::setApplicationIcon(const QIcon &icon) const
{
- NSApp.applicationIconImage = [NSImage imageFromQIcon:icon];
+ // Fall back to a size that looks good on the highest resolution screen available
+ auto fallbackSize = NSApp.dockTile.size.width * qGuiApp->devicePixelRatio();
+ NSApp.applicationIconImage = [NSImage imageFromQIcon:icon withSize:fallbackSize];
}
void QCocoaIntegration::beep() const
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm
index e4dd4cf6c6..6a3172fb19 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.mm
+++ b/src/plugins/platforms/cocoa/qcocoascreen.mm
@@ -614,7 +614,11 @@ QPixmap QCocoaScreen::grabWindow(WId view, int x, int y, int width, int height)
QRect windowRect;
for (uint i = 0; i < displayCount; ++i) {
QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(displays[i])).toRect();
- windowRect = windowRect.united(displayBounds);
+ // Only include the screen if it is positioned past the x/y position
+ if ((displayBounds.x() >= x || displayBounds.right() > x) &&
+ (displayBounds.y() >= y || displayBounds.bottom() > y)) {
+ windowRect = windowRect.united(displayBounds);
+ }
}
if (grabRect.width() < 0)
grabRect.setWidth(windowRect.width());
@@ -631,6 +635,11 @@ QPixmap QCocoaScreen::grabWindow(WId view, int x, int y, int width, int height)
auto display = displays[i];
QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(display)).toRect();
QRect grabBounds = displayBounds.intersected(grabRect);
+ if (grabBounds.isNull()) {
+ destinations.append(QRect());
+ images.append(QImage());
+ continue;
+ }
QRect displayLocalGrabBounds = QRect(QPoint(grabBounds.topLeft() - displayBounds.topLeft()), grabBounds.size());
QImage displayImage = qt_mac_toQImage(QCFType<CGImageRef>(CGDisplayCreateImageForRect(display, displayLocalGrabBounds.toCGRect())));
displayImage.setDevicePixelRatio(displayImage.size().width() / displayLocalGrabBounds.size().width());
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index e471d2af28..14833267d2 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -368,8 +368,18 @@ void QCocoaWindow::setVisible(bool visible)
} else if (window()->modality() == Qt::ApplicationModal) {
// Show the window as application modal
eventDispatcher()->beginModalSession(window());
- } else if (m_view.window.canBecomeKeyWindow && !eventDispatcher()->hasModalSession()) {
- [m_view.window makeKeyAndOrderFront:nil];
+ } else if (m_view.window.canBecomeKeyWindow) {
+ bool shouldBecomeKeyNow = !NSApp.modalWindow || m_view.window.worksWhenModal;
+
+ // Panels with becomesKeyOnlyIfNeeded set should not activate until a view
+ // with needsPanelToBecomeKey, for example a line edit, is clicked.
+ if ([m_view.window isKindOfClass:[NSPanel class]])
+ shouldBecomeKeyNow &= !(static_cast<NSPanel*>(m_view.window).becomesKeyOnlyIfNeeded);
+
+ if (shouldBecomeKeyNow)
+ [m_view.window makeKeyAndOrderFront:nil];
+ else
+ [m_view.window orderFront:nil];
} else {
[m_view.window orderFront:nil];
}
@@ -891,10 +901,13 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon)
QMacAutoReleasePool pool;
- if (icon.isNull())
+ if (icon.isNull()) {
iconButton.image = [NSWorkspace.sharedWorkspace iconForFile:m_view.window.representedFilename];
- else
- iconButton.image = [NSImage imageFromQIcon:icon];
+ } else {
+ // Fall back to a size that looks good on the highest resolution screen available
+ auto fallbackSize = iconButton.frame.size.height * qGuiApp->devicePixelRatio();
+ iconButton.image = [NSImage imageFromQIcon:icon withSize:fallbackSize];
+ }
}
void QCocoaWindow::setAlertState(bool enabled)
@@ -1814,8 +1827,17 @@ void QCocoaWindow::updateNSToolbar()
bool QCocoaWindow::testContentBorderAreaPosition(int position) const
{
- return isContentView() && m_drawContentBorderGradient &&
- 0 <= position && position < [m_view.window contentBorderThicknessForEdge:NSMaxYEdge];
+ if (!m_drawContentBorderGradient || !isContentView())
+ return false;
+
+ // Determine if the given y postion (relative to the content area) is inside the
+ // unified toolbar area. Note that the value returned by contentBorderThicknessForEdge
+ // includes the title bar height; subtract it.
+ const int contentBorderThickness = [m_view.window contentBorderThicknessForEdge:NSMaxYEdge];
+ const NSRect frameRect = m_view.window.frame;
+ const NSRect contentRect = [m_view.window contentRectForFrameRect:frameRect];
+ const CGFloat titlebarHeight = frameRect.size.height - contentRect.size.height;
+ return 0 <= position && position < (contentBorderThickness - titlebarHeight);
}
qreal QCocoaWindow::devicePixelRatio() const
diff --git a/src/plugins/platforms/cocoa/qcocoawindowmanager.mm b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm
index 9c45d8c7fc..5e218157c2 100644
--- a/src/plugins/platforms/cocoa/qcocoawindowmanager.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm
@@ -100,6 +100,18 @@ void QCocoaWindowManager::modalSessionChanged()
}
}
}
+
+ // Our worksWhenModal implementation is declarative and will normally be picked
+ // up by AppKit when needed, but to make sure AppKit also reflects the state
+ // in the window tag, so that the window can be ordered front by clicking it,
+ // we need to explicitly call setWorksWhenModal.
+ for (id window in NSApp.windows) {
+ if ([window isKindOfClass:[QNSPanel class]]) {
+ auto *panel = static_cast<QNSPanel *>(window);
+ // Call setter to tell AppKit that our state has changed
+ [panel setWorksWhenModal:panel.worksWhenModal];
+ }
+ }
}
static void initializeWindowManager() { Q_UNUSED(QCocoaWindowManager::instance()); }
diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
index 95256657fe..ac2317b217 100644
--- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm
+++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
@@ -184,7 +184,10 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch)
if (_touchCount != _currentTouches.size()) {
// Remove all instances, and basically start from scratch:
touchPoints.clear();
- for (QCocoaTouch *qcocoaTouch : _currentTouches) {
+ // Deleting touch points will remove them from current touches,
+ // so we make a copy of the touches before iterating them.
+ const auto currentTouchesSnapshot = _currentTouches;
+ for (QCocoaTouch *qcocoaTouch : currentTouchesSnapshot) {
if (!_updateInternalStateOnly) {
qcocoaTouch->_touchPoint.state = Qt::TouchPointReleased;
touchPoints.insert(qcocoaTouch->_touchPoint.id, qcocoaTouch->_touchPoint);
diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm
index 6b4e110af2..311c291252 100644
--- a/src/plugins/platforms/cocoa/qnswindow.mm
+++ b/src/plugins/platforms/cocoa/qnswindow.mm
@@ -158,7 +158,78 @@ static bool isMouseEvent(NSEvent *ev)
#define QNSWINDOW_PROTOCOL_IMPLMENTATION 1
#include "qnswindow.mm"
#undef QNSWINDOW_PROTOCOL_IMPLMENTATION
+
+- (BOOL)worksWhenModal
+{
+ if (!m_platformWindow)
+ return NO;
+
+ // Conceptually there are two sets of windows we need consider:
+ //
+ // - windows 'lower' in the modal session stack
+ // - windows 'within' the current modal session
+ //
+ // The first set of windows should always be blocked by the current
+ // modal session, regardless of window type. The latter set may contain
+ // windows with a transient parent, which from Qt's point of view makes
+ // them 'child' windows, so we treat them as operable within the current
+ // modal session.
+
+ if (!NSApp.modalWindow)
+ return NO;
+
+ // If the current modal window (top level modal session) is not a Qt window we
+ // have no way of knowing if this window is transient child of the modal window.
+ if (![NSApp.modalWindow conformsToProtocol:@protocol(QNSWindowProtocol)])
+ return NO;
+
+ if (auto *modalWindow = static_cast<QCocoaNSWindow *>(NSApp.modalWindow).platformWindow) {
+ if (modalWindow->window()->isAncestorOf(m_platformWindow->window(), QWindow::IncludeTransients))
+ return YES;
+ }
+
+ return NO;
+}
+@end
+
+#if !defined(QT_APPLE_NO_PRIVATE_APIS)
+// When creating an NSWindow the worksWhenModal function is queried,
+// and the resulting state is used to set the corresponding window tag,
+// which the window server uses to determine whether or not the window
+// should be allowed to activate via mouse clicks in the title-bar.
+// Unfortunately, prior to macOS 10.15, this window tag was never
+// updated after the initial assignment in [NSWindow _commonAwake],
+// which meant that windows that dynamically change their worksWhenModal
+// state will behave as if they were never allowed to work when modal.
+// We work around this by manually updating the window tag when needed.
+
+typedef uint32_t CGSConnectionID;
+typedef uint32_t CGSWindowID;
+
+extern "C" {
+CGSConnectionID CGSMainConnectionID() __attribute__((weak_import));
+OSStatus CGSSetWindowTags(const CGSConnectionID, const CGSWindowID, int *, int) __attribute__((weak_import));
+OSStatus CGSClearWindowTags(const CGSConnectionID, const CGSWindowID, int *, int) __attribute__((weak_import));
+}
+
+@interface QNSPanel (WorksWhenModalWindowTagWorkaround) @end
+@implementation QNSPanel (WorksWhenModalWindowTagWorkaround)
+- (void)setWorksWhenModal:(BOOL)worksWhenModal
+{
+ [super setWorksWhenModal:worksWhenModal];
+
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSCatalina) {
+ if (CGSMainConnectionID && CGSSetWindowTags && CGSClearWindowTags) {
+ static int kWorksWhenModalWindowTag = 0x40;
+ auto *function = worksWhenModal ? CGSSetWindowTags : CGSClearWindowTags;
+ function(CGSMainConnectionID(), self.windowNumber, &kWorksWhenModalWindowTag, 64);
+ } else {
+ qWarning() << "Missing APIs for window tag handling, can not update worksWhenModal state";
+ }
+ }
+}
@end
+#endif // QT_APPLE_NO_PRIVATE_APIS
#else // QNSWINDOW_PROTOCOL_IMPLMENTATION
@@ -237,17 +308,6 @@ static bool isMouseEvent(NSEvent *ev)
return canBecomeMain;
}
-- (BOOL)worksWhenModal
-{
- if (m_platformWindow && [self isKindOfClass:[QNSPanel class]]) {
- Qt::WindowType type = m_platformWindow->window()->type();
- if (type == Qt::Popup || type == Qt::Dialog || type == Qt::Tool)
- return YES;
- }
-
- return [super worksWhenModal];
-}
-
- (BOOL)isOpaque
{
return m_platformWindow ? m_platformWindow->isOpaque() : [super isOpaque];
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index b0e60d76fc..4dbb0a4cdf 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -45,6 +45,7 @@
#include "qiosapplicationdelegate.h"
#include "qiosviewcontroller.h"
#include "quiview.h"
+#include "qiostheme.h"
#include <QtCore/private/qcore_mac_p.h>
@@ -208,6 +209,18 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
[super sendEvent:event];
}
+- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
+{
+ [super traitCollectionDidChange:previousTraitCollection];
+
+ if (self.screen == UIScreen.mainScreen) {
+ if (previousTraitCollection.userInterfaceStyle != self.traitCollection.userInterfaceStyle) {
+ QIOSTheme::initializeSystemPalette();
+ QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>(nullptr);
+ }
+ }
+}
+
@end
// -------------------------------------------------------------------------
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index a3350bda87..19e476a064 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -416,6 +416,17 @@
if (unknownAction)
return [super canPerformAction:action withSender:sender];
+
+ QObject *focusObject = QGuiApplication::focusObject();
+ if (focusObject && focusObject->property("qt_im_readonly").toBool()) {
+ // exceptional menu items for read-only views: do include Copy, do not include Paste etc.
+ if (action == @selector(cut:)
+ || action == @selector(paste:)
+ || action == @selector(delete:))
+ return NO;
+ if (action == @selector(copy:))
+ return YES;
+ }
return (hasSelection && isEditAction) || (!hasSelection && isSelectAction);
}
diff --git a/src/plugins/platforms/ios/qiostheme.h b/src/plugins/platforms/ios/qiostheme.h
index c917679a91..c9d833713d 100644
--- a/src/plugins/platforms/ios/qiostheme.h
+++ b/src/plugins/platforms/ios/qiostheme.h
@@ -65,9 +65,12 @@ public:
static const char *name;
+ static void initializeSystemPalette();
+
private:
mutable QHash<QPlatformTheme::Font, QFont *> m_fonts;
- QPalette m_systemPalette;
+
+ static QPalette s_systemPalette;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm
index 5534264a60..626fbb66fe 100644
--- a/src/plugins/platforms/ios/qiostheme.mm
+++ b/src/plugins/platforms/ios/qiostheme.mm
@@ -44,6 +44,7 @@
#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/QFont>
+#include <QtGui/private/qcoregraphics_p.h>
#include <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -63,10 +64,8 @@ QT_BEGIN_NAMESPACE
const char *QIOSTheme::name = "ios";
QIOSTheme::QIOSTheme()
- : m_systemPalette(*QPlatformTheme::palette(QPlatformTheme::SystemPalette))
{
- m_systemPalette.setBrush(QPalette::Highlight, QColor(204, 221, 237));
- m_systemPalette.setBrush(QPalette::HighlightedText, Qt::black);
+ initializeSystemPalette();
}
QIOSTheme::~QIOSTheme()
@@ -74,10 +73,41 @@ QIOSTheme::~QIOSTheme()
qDeleteAll(m_fonts);
}
+QPalette QIOSTheme::s_systemPalette;
+
+void QIOSTheme::initializeSystemPalette()
+{
+ Q_DECL_IMPORT QPalette qt_fusionPalette(void);
+ s_systemPalette = qt_fusionPalette();
+
+ if (@available(ios 13.0, *)) {
+ s_systemPalette.setBrush(QPalette::Window, qt_mac_toQBrush(UIColor.systemGroupedBackgroundColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::WindowText, qt_mac_toQBrush(UIColor.labelColor.CGColor));
+
+ s_systemPalette.setBrush(QPalette::Base, qt_mac_toQBrush(UIColor.secondarySystemGroupedBackgroundColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::Text, qt_mac_toQBrush(UIColor.labelColor.CGColor));
+
+ s_systemPalette.setBrush(QPalette::Button, qt_mac_toQBrush(UIColor.secondarySystemBackgroundColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::ButtonText, qt_mac_toQBrush(UIColor.labelColor.CGColor));
+
+ s_systemPalette.setBrush(QPalette::Active, QPalette::BrightText, qt_mac_toQBrush(UIColor.lightTextColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::PlaceholderText, qt_mac_toQBrush(UIColor.placeholderTextColor.CGColor));
+
+ s_systemPalette.setBrush(QPalette::Active, QPalette::Link, qt_mac_toQBrush(UIColor.linkColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::LinkVisited, qt_mac_toQBrush(UIColor.linkColor.CGColor));
+
+ s_systemPalette.setBrush(QPalette::Highlight, QColor(11, 70, 150, 60));
+ s_systemPalette.setBrush(QPalette::HighlightedText, qt_mac_toQBrush(UIColor.labelColor.CGColor));
+ } else {
+ s_systemPalette.setBrush(QPalette::Highlight, QColor(204, 221, 237));
+ s_systemPalette.setBrush(QPalette::HighlightedText, Qt::black);
+ }
+}
+
const QPalette *QIOSTheme::palette(QPlatformTheme::Palette type) const
{
if (type == QPlatformTheme::SystemPalette)
- return &m_systemPalette;
+ return &s_systemPalette;
return 0;
}
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index c08e5b0cf1..871f4b8fb0 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -3964,13 +3964,19 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// which makes no sense on tabs.
NSPopUpArrowPosition oldPosition = NSPopUpArrowAtCenter;
NSPopUpButtonCell *pbCell = nil;
- if (isPopupButton) {
+ auto rAdjusted = r;
+ if (isPopupButton && tp == QStyleOptionTab::OnlyOneTab) {
pbCell = static_cast<NSPopUpButtonCell *>(pb.cell);
oldPosition = pbCell.arrowPosition;
pbCell.arrowPosition = NSPopUpNoArrow;
+ if (pb.state == NSOffState) {
+ // NSPopUpButton in this state is smaller.
+ rAdjusted.origin.x -= 3;
+ rAdjusted.size.width += 6;
+ }
}
- [pb.cell drawBezelWithFrame:r inView:pb.superview];
+ [pb.cell drawBezelWithFrame:rAdjusted inView:pb.superview];
if (pbCell) // Restore, we may reuse it for a ComboBox.
pbCell.arrowPosition = oldPosition;
diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp
index eda0f430a1..cfa999a6f4 100644
--- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp
+++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp
@@ -84,7 +84,7 @@ class TestQString : public QObject
void wrapInFunction()
{
//! [1]
-QVERIFY2(qIsNaN(0.0 / 0.0), "Ill-defined division produced unambiguous result.");
+QVERIFY2(QFileInfo("file.txt").exists(), "file.txt does not exist.");
//! [1]
//! [2]
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 8b5df06d82..e1da9e617c 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -2541,16 +2541,21 @@ bool QTest::compare_helper(bool success, const char *failureMsg,
}
template <typename T>
-static bool floatingCompare(const T &t1, const T &t2)
+static bool floatingCompare(const T &actual, const T &expected)
{
- switch (qFpClassify(t1))
+ switch (qFpClassify(expected))
{
case FP_INFINITE:
- return (t1 < 0) == (t2 < 0) && qFpClassify(t2) == FP_INFINITE;
+ return (expected < 0) == (actual < 0) && qFpClassify(actual) == FP_INFINITE;
case FP_NAN:
- return qFpClassify(t2) == FP_NAN;
+ return qFpClassify(actual) == FP_NAN;
default:
- return qFuzzyCompare(t1, t2);
+ if (!qFuzzyIsNull(expected))
+ return qFuzzyCompare(actual, expected);
+ Q_FALLTHROUGH();
+ case FP_SUBNORMAL: // subnormal is always fuzzily null
+ case FP_ZERO:
+ return qFuzzyIsNull(actual);
}
}
diff --git a/src/testlib/qtestcase.qdoc b/src/testlib/qtestcase.qdoc
index e4e1825bb5..72f8cdaf8c 100644
--- a/src/testlib/qtestcase.qdoc
+++ b/src/testlib/qtestcase.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -109,19 +109,18 @@
continues. If not, a failure is recorded in the test log and the test
function returns without attempting any later checks.
- Always respect QCOMPARE() parameter semantics. The first parameter passed to it
- should always be the actual value produced by the code-under-test, while the
- second parameter should always be the expected value. When the values don't
- match, QCOMPARE() prints them with the labels \e Actual and \e Expected.
- If the parameter order is swapped, debugging a failing test can be confusing.
+ Always respect QCOMPARE() parameter semantics. The first parameter passed to
+ it should always be the actual value produced by the code-under-test, while
+ the second parameter should always be the expected value. When the values
+ don't match, QCOMPARE() prints them with the labels \e Actual and \e
+ Expected. If the parameter order is swapped, debugging a failing test can be
+ confusing and tests expecting zero may fail due to rounding errors.
When comparing floating-point types (\c float, \c double, and \c qfloat16),
- \l qFuzzyCompare() is used for finite values. Infinities match if they have
+ \l qFuzzyCompare() is used for finite values. If qFuzzyIsNull() is true for
+ both values, they are also considered equal. Infinities match if they have
the same sign, and any NaN as actual value matches with any NaN as expected
- value (even though NaN != NaN, even when they're identical). This means that
- expecting 0 can fail when the actual value may be affected by rounding errors.
- One solution to this is to offset both actual and expected values by adding
- some suitable constant (such as 1).
+ value (even though NaN != NaN, even when they're identical).
QCOMPARE() tries to output the contents of the values if the comparison fails,
so it is visible from the test log why the comparison failed.
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 5b4d861b8d..5b890e0f8d 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -1378,6 +1378,9 @@ QStringList qt_make_filter_list(const QString &filter)
\snippet code/src_gui_dialogs_qfiledialog.cpp 6
+ \note This is not supported on Android's native file dialog. Use
+ \l{setMimeTypeFilters()} instead.
+
\sa setMimeTypeFilters(), setNameFilters()
*/
void QFileDialog::setNameFilter(const QString &filter)
@@ -1428,6 +1431,9 @@ QStringList qt_strip_filters(const QStringList &filters)
filters for each file type. For example, JPEG images have three possible
extensions; if your application can open such files, selecting the
\c image/jpeg mime type as a filter will allow you to open all of them.
+
+ \note This is not supported on Android's native file dialog. Use
+ \l{setMimeTypeFilters()} instead.
*/
void QFileDialog::setNameFilters(const QStringList &filters)
{
diff --git a/src/widgets/doc/snippets/customviewstyle.cpp b/src/widgets/doc/snippets/customviewstyle.cpp
index b9c10cb31d..1e4cf2b711 100644
--- a/src/widgets/doc/snippets/customviewstyle.cpp
+++ b/src/widgets/doc/snippets/customviewstyle.cpp
@@ -50,11 +50,10 @@
#include <QtWidgets>
-#include "customviewstyle.h"
+#include "./customstyle/customstyle.h"
-
-
-void CustomViewStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
+void CustomStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
+ QPainter *painter, const QWidget *widget) const
{
//![0]
diff --git a/src/widgets/doc/snippets/filedialogurls.cpp b/src/widgets/doc/snippets/filedialogurls.cpp
index cd91e797e7..4b73a6c818 100644
--- a/src/widgets/doc/snippets/filedialogurls.cpp
+++ b/src/widgets/doc/snippets/filedialogurls.cpp
@@ -49,11 +49,10 @@
****************************************************************************/
#include <QtGui>
+#include <QFileDialog>
-int main(int argv, char **args)
+int loadFileDialog()
{
- QApplication app(argv, args);
-
//![0]
QList<QUrl> urls;
urls << QUrl::fromLocalFile("/Users/foo/Code/qt5")
@@ -66,6 +65,5 @@ int main(int argv, char **args)
// ...
}
//![0]
-
- return app.exec();
+ return 1;
}
diff --git a/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp b/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp
index 96e6bd650c..0ce135dc63 100644
--- a/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp
+++ b/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp
@@ -49,6 +49,9 @@
****************************************************************************/
#include <QtGui>
+#include <QGraphicsScene>
+#include <QGraphicsEllipseItem>
+#include <QStyleOptionGraphicsItem>
class CustomScene : public QGraphicsScene
{
@@ -70,21 +73,9 @@ void CustomScene::drawItems(QPainter *painter, int numItems,
for (int i = 0; i < numItems; ++i) {
// Draw the item
painter->save();
- painter->setMatrix(items[i]->sceneMatrix(), true);
+ painter->setTransform(items[i]->sceneTransform(), true);
items[i]->paint(painter, &options[i], widget);
painter->restore();
}
}
//! [0]
-
-int main(int argv, char **args)
-{
- QApplication app(argv, args);
-
- CustomScene scene;
- QGraphicsView view(&scene);
-
- view.show();
-
- return app.exec();
-}
diff --git a/src/widgets/doc/snippets/graphicsview.cpp b/src/widgets/doc/snippets/graphicsview.cpp
index 9578f91eec..6262137c90 100644
--- a/src/widgets/doc/snippets/graphicsview.cpp
+++ b/src/widgets/doc/snippets/graphicsview.cpp
@@ -47,53 +47,70 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
+#include <QGraphicsView>
+#include <QOpenGLWidget>
+#include <QPrinter>
+#include <QPrintDialog>
+#include <QStandardItem>
+#include <QMimeData>
+#include <QDrag>
+#include <QGraphicsSceneMouseEvent>
+
+int main()
+{
//! [0]
QGraphicsScene scene;
QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
-QGraphicsItem *item = scene.itemAt(50, 50);
-// item == rect
+QGraphicsItem *item = scene.itemAt(50, 50, QTransform());
//! [0]
+Q_UNUSED(rect);
+Q_UNUSED(item);
+}
+void myPopulateScene(QGraphicsScene *)
+{
+ // Intentionally left empty
+}
+void snippetThatUsesMyPopulateScene()
+{
//! [1]
QGraphicsScene scene;
myPopulateScene(&scene);
-
QGraphicsView view(&scene);
view.show();
//! [1]
+}
-
-//! [2]
-class View : public QGraphicsView
+class CustomItem : public QStandardItem
{
-Q_OBJECT
- ...
-public slots:
- void zoomIn() { scale(1.2, 1.2); }
- void zoomOut() { scale(1 / 1.2, 1 / 1.2); }
- void rotateLeft() { rotate(-10); }
- void rotateRight() { rotate(10); }
- ...
+public:
+ using QStandardItem::QStandardItem;
+
+ int type() const override { return UserType; }
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ QStandardItem *clone() const override { return new CustomItem; }
};
-//! [2]
+void printScene()
+{
//! [3]
QGraphicsScene scene;
+QPrinter printer;
scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green));
-QPrinter printer;
if (QPrintDialog(&printer).exec() == QDialog::Accepted) {
QPainter painter(&printer);
painter.setRenderHint(QPainter::Antialiasing);
scene.render(&painter);
}
//! [3]
+}
-
+void pixmapScene()
+{
//! [4]
QGraphicsScene scene;
scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green));
@@ -106,21 +123,21 @@ painter.end();
pixmap.save("scene.png");
//! [4]
-
+}
//! [5]
void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QMimeData *data = new QMimeData;
- data->setColor(Qt::green);
-
QDrag *drag = new QDrag(event->widget());
drag->setMimeData(data);
- drag->start();
+ drag->exec();
}
//! [5]
-
+void viewScene()
+{
+QGraphicsScene scene;
//! [6]
QGraphicsView view(&scene);
QOpenGLWidget *gl = new QOpenGLWidget();
@@ -129,3 +146,4 @@ format.setSamples(4);
gl->setFormat(format);
view.setViewport(gl);
//! [6]
+}
diff --git a/src/widgets/doc/snippets/graphicsview_snippet.cpp b/src/widgets/doc/snippets/graphicsview_snippet.cpp
new file mode 100644
index 0000000000..9d058d0f6a
--- /dev/null
+++ b/src/widgets/doc/snippets/graphicsview_snippet.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [2]
+class View : public QGraphicsView
+{
+Q_OBJECT
+ ...
+public slots:
+ void zoomIn() { scale(1.2, 1.2); }
+ void zoomOut() { scale(1 / 1.2, 1 / 1.2); }
+ void rotateLeft() { rotate(-10); }
+ void rotateRight() { rotate(10); }
+ ...
+};
+//! [2]
diff --git a/src/widgets/doc/snippets/mdiareasnippets.cpp b/src/widgets/doc/snippets/mdiareasnippets.cpp
index dec7aaa1e7..c1e2d37ccb 100644
--- a/src/widgets/doc/snippets/mdiareasnippets.cpp
+++ b/src/widgets/doc/snippets/mdiareasnippets.cpp
@@ -85,6 +85,7 @@ void addingSubWindowsExample()
mdiArea.show();
}
+/*
int main(int argv, char **args)
{
QApplication app(argv, args);
@@ -103,5 +104,5 @@ int main(int argv, char **args)
return app.exec();
}
-
+*/
diff --git a/src/widgets/doc/snippets/myscrollarea.cpp b/src/widgets/doc/snippets/myscrollarea.cpp
index dbf8da1603..8afe4a6834 100644
--- a/src/widgets/doc/snippets/myscrollarea.cpp
+++ b/src/widgets/doc/snippets/myscrollarea.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
class MyScrollArea : public QAbstractScrollArea
{
@@ -97,8 +97,10 @@ void MyScrollArea::updateWidgetPosition()
//! [0]
}
-void MyScrollArea::scrollContentsBy(int /*dx*/, int /*dy*/)
+void MyScrollArea::scrollContentsBy(int dx, int dy)
{
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
updateWidgetPosition();
}
@@ -118,21 +120,6 @@ void MyScrollArea::updateArea()
void MyScrollArea::resizeEvent(QResizeEvent *event)
{
+ Q_UNUSED(event);
updateArea();
}
-
-int main(int argv, char **args)
-{
- QApplication app(argv, args);
-
- QPixmap pixmap("mypixmap.png");
- QLabel label;
- label.setPixmap(pixmap);
- MyScrollArea area(&label);
- area.resize(300, 300);
- area.show();
-
- area.setWidget(&label);
-
- return app.exec();
-}
diff --git a/src/widgets/doc/snippets/snippets.pro b/src/widgets/doc/snippets/snippets.pro
new file mode 100644
index 0000000000..f1d3596f9d
--- /dev/null
+++ b/src/widgets/doc/snippets/snippets.pro
@@ -0,0 +1,16 @@
+requires(qtHaveModule(widgets))
+requires(qtHaveModule(printsupport))
+
+TEMPLATE = app
+
+TARGET = widgets_snippets
+
+QT += widgets printsupport
+
+SOURCES += customviewstyle.cpp \
+ filedialogurls.cpp \
+ graphicssceneadditemsnippet.cpp \
+ graphicsview.cpp \
+ mdiareasnippets.cpp \
+ myscrollarea.cpp
+
diff --git a/src/widgets/doc/src/graphicsview.qdoc b/src/widgets/doc/src/graphicsview.qdoc
index 0489203e40..2dfad442a3 100644
--- a/src/widgets/doc/src/graphicsview.qdoc
+++ b/src/widgets/doc/src/graphicsview.qdoc
@@ -327,7 +327,7 @@
Here is an example of how to implement zoom and rotate slots in a
subclass of QGraphicsView:
- \snippet graphicsview.cpp 2
+ \snippet graphicsview_snippet.cpp 2
The slots could be connected to \l{QToolButton}{QToolButtons} with
\l{QAbstractButton::autoRepeat}{autoRepeat} enabled.
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 64cd87df38..fe5c52ee93 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -40,6 +40,7 @@
#include "qmenu.h"
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include <QtWidgets/private/qwidgetwindow_p.h>
#include "qactiongroup.h"
#include "qdebug.h"
@@ -2353,15 +2354,23 @@ void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction po
// Use d->popupScreen to remember, because initialScreenIndex will be reset after the first showing.
// However if eventLoop exists, then exec() already did this by calling createWinId(); so leave it alone. (QTBUG-76162)
if (!eventLoop) {
+ bool screenSet = false;
const int screenIndex = topData()->initialScreenIndex;
if (screenIndex >= 0)
popupScreen = screenIndex;
if (auto s = QGuiApplication::screens().value(popupScreen)) {
if (setScreen(s))
itemsDirty = true;
- } else if (setScreenForPoint(p)) {
- itemsDirty = true;
+ screenSet = true;
+ } else if (QMenu *parentMenu = qobject_cast<QMenu *>(parent)) {
+ // a submenu is always opened from an open parent menu,
+ // so show it on the same screen where the parent is. (QTBUG-76162)
+ if (setScreen(QMenuPrivate::get(parentMenu)->windowHandle()->screen()))
+ itemsDirty = true;
+ screenSet = true;
}
+ if (!screenSet && setScreenForPoint(p))
+ itemsDirty = true;
}
const bool contextMenu = isContextMenu();