Merge remote-tracking branch 'origin/5.12' into 5.13

Change-Id: I371c5ae1af6f58e32e579671f485b92b586e0b76
This commit is contained in:
Qt Forward Merge Bot 2019-09-08 11:33:28 +02:00
commit 1f35c8caa0
17 changed files with 265 additions and 61 deletions

109
dist/changes-5.12.5 vendored Normal file
View File

@ -0,0 +1,109 @@
Qt 5.12.5 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.12.0 through 5.12.4.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qt-5/index.html
The Qt version 5.12 series is binary compatible with the 5.11.x series.
Applications compiled for 5.11 will continue to run with 5.12.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* QtCore *
****************************************************************************
- QBitArray:
* Fixed two bugs that caused QBitArrays created using fromBits() not to
compare equal to the equivalent QBitArray created using other methods
if the size was zero or not a multiple of 4. If the size modulus 8 was
5, 6, or 7, the data was actually incorrect.
- QCborStreamReader:
* Fixed a bug that caused the QIODevice that the data was being read
from not to show the entire CBOR message as consumed. This allows the
user to consume data that may follow the CBOR payload.
- QCryptographicHash:
* Fixed a bug that caused the SHA-3 and Keccak algorithms to crash if
passed 256 MB of data or more.
- QObject:
* Fixed a resource leak caused by a race condition if multiple QObjects
were created at the same time, for the first time in an application,
from multiple threads (implies threads not started with QThread).
- QStorageInfo:
* Fixed a bug that caused QStorageInfo to be unable to report all
filesystems if the options to mounted filesystems were too long (over
900 characters, roughly), such as those found in Docker overlay
mounts.
- QTimeZone:
* The IANA timezone database backend now properly follows symlinks even
when they point to variable locations like /run or /var (useful when
/etc is mounted read-only).
****************************************************************************
* QtGui *
****************************************************************************
- QImage:
* Improve loading time when loading png files that have the same size as
the target.
- QPixmapCache:
* [QTBUG-76694][QTBUG-72523] Ignore unsafe access from non-main threads
- Text:
* [QTBUG-76219] Fixed a bug which could cause the font cache to grow
larger than it was supposed to.
* [QTBUG-55096][QTBUG-74761] Fixed bug where regular text rendered with
a color font would always display in black.
* [QTBUG-69546] Fixed a crash bug in
QTextDocument::clearUndoRedoStacks(QTextDocument::UndoStack).
****************************************************************************
* QtNetwork *
****************************************************************************
- QHostInfo:
* Functors used in the lookupHost overloads are now called correctly in
the thread of the context object. When used without context object,
the thread that initiates the lookup will run the functor, and is
required to run an event loop.
- Windows:
* Correctly emit errors when trying to reach unreachable hosts or
services
****************************************************************************
* QtWidgets *
****************************************************************************
- QGraphicsView:
* Ignore disabled items when setting the mouse cursor.
- QSplashScreen:
* On macOS, lower the splash screen when a modal dialog is shown to make
sure the user sees the dialog.
- QSystemTrayIcon:
* On macOS, show the icon passed into showMessage in the notification
popup
****************************************************************************
* Android *
****************************************************************************
- [QTBUG-76293] Fix NDK r20 linking.
- [QTBUG-76036] Fixed an issue where menus would not work on 64 bit
builds.

View File

@ -8,7 +8,7 @@ QMAKE_MAC_SDK = macosx
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12 QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
QMAKE_APPLE_DEVICE_ARCHS = x86_64 QMAKE_APPLE_DEVICE_ARCHS = x86_64
QT_MAC_SDK_VERSION_MIN = 10.13 QT_MAC_SDK_VERSION_MIN = 10.13
QT_MAC_SDK_VERSION_MAX = 10.14 QT_MAC_SDK_VERSION_MAX = 10.15
device.sdk = macosx device.sdk = macosx
device.target = device device.target = device

View File

@ -514,6 +514,56 @@ static QList<QVariantMap> provisioningTeams()
return flatTeams; return flatTeams;
} }
bool ProjectBuilderMakefileGenerator::replaceLibrarySuffix(const QString &lib_file,
const ProString &opt,
QString &name, QString &library)
{
/* This isn't real nice, but it is real useful. This looks in a prl
for what the library will ultimately be called so we can stick it
in the ProjectFile. If the prl format ever changes (not likely) then
this will not really work. However, more concerning is that it will
encode the version number in the Project file which might be a bad
things in days to come? --Sam
*/
if (lib_file.isEmpty())
return false;
QMakeMetaInfo libinfo;
if (!libinfo.readLib(lib_file) || libinfo.isEmpty("QMAKE_PRL_TARGET"))
return false;
const QString libDir = fileInfo(lib_file).absolutePath();
library = libDir + Option::dir_sep + libinfo.first("QMAKE_PRL_TARGET");
debug_msg(1, "pbuilder: Found library (%s) via PRL %s (%s)",
opt.toLatin1().constData(), lib_file.toLatin1().constData(), library.toLatin1().constData());
if (project->isActiveConfig("xcode_dynamic_library_suffix")) {
QString suffixSetting = project->first("QMAKE_XCODE_LIBRARY_SUFFIX_SETTING").toQString();
if (!suffixSetting.isEmpty()) {
QString librarySuffix = project->first("QMAKE_XCODE_LIBRARY_SUFFIX").toQString();
suffixSetting = "$(" + suffixSetting + ")";
if (!librarySuffix.isEmpty()) {
int pos = library.lastIndexOf(librarySuffix + '.');
if (pos == -1) {
warn_msg(WarnLogic, "Failed to find expected suffix '%s' for library '%s'.",
qPrintable(librarySuffix), qPrintable(library));
} else {
library.replace(pos, librarySuffix.length(), suffixSetting);
if (name.endsWith(librarySuffix))
name.chop(librarySuffix.length());
}
} else {
int pos = library.lastIndexOf(name);
if (pos != -1)
library.insert(pos + name.length(), suffixSetting);
}
}
}
return true;
}
bool bool
ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
{ {
@ -833,6 +883,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
for (int i = 0; libs[i]; i++) { for (int i = 0; libs[i]; i++) {
tmp = project->values(libs[i]); tmp = project->values(libs[i]);
for(int x = 0; x < tmp.count();) { for(int x = 0; x < tmp.count();) {
bool libSuffixReplaced = false;
bool remove = false; bool remove = false;
QString library, name; QString library, name;
ProString opt = tmp[x]; ProString opt = tmp[x];
@ -845,49 +896,12 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
QString lib("lib" + name); QString lib("lib" + name);
for (ProStringList::Iterator lit = libdirs.begin(); lit != libdirs.end(); ++lit) { for (ProStringList::Iterator lit = libdirs.begin(); lit != libdirs.end(); ++lit) {
if(project->isActiveConfig("link_prl")) { if(project->isActiveConfig("link_prl")) {
/* This isn't real nice, but it is real useful. This looks in a prl const QString prlFilePath = QMakeMetaInfo::checkLib(
for what the library will ultimately be called so we can stick it Option::normalizePath((*lit) + Option::dir_sep + lib
in the ProjectFile. If the prl format ever changes (not likely) then + Option::prl_ext));
this will not really work. However, more concerning is that it will if (replaceLibrarySuffix(prlFilePath, opt, name, library))
encode the version number in the Project file which might be a bad
things in days to come? --Sam
*/
QString lib_file = QMakeMetaInfo::checkLib(Option::normalizePath(
(*lit) + Option::dir_sep + lib + Option::prl_ext));
if (!lib_file.isEmpty()) {
QMakeMetaInfo libinfo;
if(libinfo.readLib(lib_file)) {
if(!libinfo.isEmpty("QMAKE_PRL_TARGET")) {
library = (*lit) + Option::dir_sep + libinfo.first("QMAKE_PRL_TARGET");
debug_msg(1, "pbuilder: Found library (%s) via PRL %s (%s)",
opt.toLatin1().constData(), lib_file.toLatin1().constData(), library.toLatin1().constData());
remove = true; remove = true;
libSuffixReplaced = true;
if (project->isActiveConfig("xcode_dynamic_library_suffix")) {
QString suffixSetting = project->first("QMAKE_XCODE_LIBRARY_SUFFIX_SETTING").toQString();
if (!suffixSetting.isEmpty()) {
QString librarySuffix = project->first("QMAKE_XCODE_LIBRARY_SUFFIX").toQString();
suffixSetting = "$(" + suffixSetting + ")";
if (!librarySuffix.isEmpty()) {
int pos = library.lastIndexOf(librarySuffix + '.');
if (pos == -1) {
warn_msg(WarnLogic, "Failed to find expected suffix '%s' for library '%s'.",
qPrintable(librarySuffix), qPrintable(library));
} else {
library.replace(pos, librarySuffix.length(), suffixSetting);
if (name.endsWith(librarySuffix))
name.chop(librarySuffix.length());
}
} else {
int pos = library.lastIndexOf(name);
if (pos != -1)
library.insert(pos + name.length(), suffixSetting);
}
}
}
}
}
}
} }
if(!remove) { if(!remove) {
QString extns[] = { ".dylib", ".so", ".a", QString() }; QString extns[] = { ".dylib", ".so", ".a", QString() };
@ -937,6 +951,16 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
} }
} }
if(!library.isEmpty()) { if(!library.isEmpty()) {
if (!libSuffixReplaced) {
const QFileInfo fi = fileInfo(library);
const QString prlFilePath = QMakeMetaInfo::checkLib(
Option::normalizePath(fi.absolutePath() + '/' + fi.completeBaseName()
+ Option::prl_ext));
if (!prlFilePath.isEmpty()) {
name = fi.completeBaseName().mid(3);
replaceLibrarySuffix(prlFilePath, opt, name, library);
}
}
const int slsh = library.lastIndexOf(Option::dir_sep); const int slsh = library.lastIndexOf(Option::dir_sep);
if(name.isEmpty()) { if(name.isEmpty()) {
if(slsh != -1) if(slsh != -1)

View File

@ -41,6 +41,8 @@ class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator
bool writeSubDirs(QTextStream &); bool writeSubDirs(QTextStream &);
bool writeMakeParts(QTextStream &); bool writeMakeParts(QTextStream &);
bool writeMakefile(QTextStream &) override; bool writeMakefile(QTextStream &) override;
bool replaceLibrarySuffix(const QString &lib_file, const ProString &opt, QString &name,
QString &library);
QString pbxbuild(); QString pbxbuild();
QHash<QString, QString> keys; QHash<QString, QString> keys;

View File

@ -1814,8 +1814,8 @@ static void qt_message_print(QtMsgType msgType, const QMessageLogContext &contex
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
Q_TRACE(qt_message_print, msgType, context.category, context.function, context.file, context.line, message); Q_TRACE(qt_message_print, msgType, context.category, context.function, context.file, context.line, message);
// qDebug, qWarning, ... macros do not check whether category is enabled // qDebug, qWarning, ... macros do not check whether category is enabledgc
if (isDefaultCategory(context.category)) { if (msgType != QtFatalMsg && isDefaultCategory(context.category)) {
if (QLoggingCategory *defaultCategory = QLoggingCategory::defaultCategory()) { if (QLoggingCategory *defaultCategory = QLoggingCategory::defaultCategory()) {
if (!defaultCategory->isEnabled(msgType)) if (!defaultCategory->isEnabled(msgType))
return; return;

View File

@ -281,7 +281,7 @@ static quint32 icon_name_hash(const char *p)
QVector<const char *> QIconCacheGtkReader::lookup(const QStringRef &name) QVector<const char *> QIconCacheGtkReader::lookup(const QStringRef &name)
{ {
QVector<const char *> ret; QVector<const char *> ret;
if (!isValid()) if (!isValid() || name.isEmpty())
return ret; return ret;
QByteArray nameUtf8 = name.toUtf8(); QByteArray nameUtf8 = name.toUtf8();

View File

@ -2697,7 +2697,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
QWindow *window = e->window.data(); QWindow *window = e->window.data();
typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints; typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints;
QHash<QWindow *, StatesAndTouchPoints> windowsNeedingEvents; QHash<QWindow *, StatesAndTouchPoints> windowsNeedingEvents;
bool stationaryTouchPointChangedVelocity = false; bool stationaryTouchPointChangedProperty = false;
for (int i = 0; i < e->points.count(); ++i) { for (int i = 0; i < e->points.count(); ++i) {
QTouchEvent::TouchPoint touchPoint = e->points.at(i); QTouchEvent::TouchPoint touchPoint = e->points.at(i);
@ -2777,7 +2777,11 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
if (touchPoint.state() == Qt::TouchPointStationary) { if (touchPoint.state() == Qt::TouchPointStationary) {
if (touchInfo.touchPoint.velocity() != touchPoint.velocity()) { if (touchInfo.touchPoint.velocity() != touchPoint.velocity()) {
touchInfo.touchPoint.setVelocity(touchPoint.velocity()); touchInfo.touchPoint.setVelocity(touchPoint.velocity());
stationaryTouchPointChangedVelocity = true; stationaryTouchPointChangedProperty = true;
}
if (!qFuzzyCompare(touchInfo.touchPoint.pressure(), touchPoint.pressure())) {
touchInfo.touchPoint.setPressure(touchPoint.pressure());
stationaryTouchPointChangedProperty = true;
} }
} else { } else {
touchInfo.touchPoint = touchPoint; touchInfo.touchPoint = touchPoint;
@ -2818,7 +2822,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
break; break;
case Qt::TouchPointStationary: case Qt::TouchPointStationary:
// don't send the event if nothing changed // don't send the event if nothing changed
if (!stationaryTouchPointChangedVelocity) if (!stationaryTouchPointChangedProperty)
continue; continue;
Q_FALLTHROUGH(); Q_FALLTHROUGH();
default: default:

View File

@ -55,6 +55,8 @@
#include <QtNetwork/qnetworkproxy.h> #include <QtNetwork/qnetworkproxy.h>
#endif #endif
#include <qcoreapplication.h>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
@ -211,6 +213,29 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan
} }
} }
void QHttp2ProtocolHandler::handleConnectionClosure()
{
// The channel has just received RemoteHostClosedError and since it will
// not try (for HTTP/2) to re-connect, it's time to finish all replies
// with error.
// Maybe we still have some data to read and can successfully finish
// a stream/request?
_q_receiveReply();
// Finish all still active streams. If we previously had GOAWAY frame,
// we probably already closed some (or all) streams with ContentReSend
// error, but for those still active, not having any data to finish,
// we now report RemoteHostClosedError.
const auto errorString = QCoreApplication::translate("QHttp", "Connection closed");
for (auto it = activeStreams.begin(), eIt = activeStreams.end(); it != eIt; ++it)
finishStreamWithError(it.value(), QNetworkReply::RemoteHostClosedError, errorString);
// Make sure we'll never try to read anything later:
activeStreams.clear();
goingAway = true;
}
void QHttp2ProtocolHandler::_q_uploadDataReadyRead() void QHttp2ProtocolHandler::_q_uploadDataReadyRead()
{ {
if (!sender()) // QueuedConnection, firing after sender (byte device) was deleted. if (!sender()) // QueuedConnection, firing after sender (byte device) was deleted.

View File

@ -90,6 +90,8 @@ public:
QHttp2ProtocolHandler &operator = (const QHttp2ProtocolHandler &rhs) = delete; QHttp2ProtocolHandler &operator = (const QHttp2ProtocolHandler &rhs) = delete;
QHttp2ProtocolHandler &operator = (QHttp2ProtocolHandler &&rhs) = delete; QHttp2ProtocolHandler &operator = (QHttp2ProtocolHandler &&rhs) = delete;
Q_INVOKABLE void handleConnectionClosure();
private slots: private slots:
void _q_uploadDataReadyRead(); void _q_uploadDataReadyRead();
void _q_replyDestroyed(QObject* reply); void _q_replyDestroyed(QObject* reply);

View File

@ -850,8 +850,11 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
} }
state = QHttpNetworkConnectionChannel::IdleState; state = QHttpNetworkConnectionChannel::IdleState;
if (alreadyPipelinedRequests.length()) {
// If nothing was in a pipeline, no need in calling
// _q_startNextRequest (which it does):
requeueCurrentlyPipelinedRequests(); requeueCurrentlyPipelinedRequests();
}
pendingEncrypt = false; pendingEncrypt = false;
} }
@ -965,7 +968,18 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
if (!reply && state == QHttpNetworkConnectionChannel::IdleState) { if (!reply && state == QHttpNetworkConnectionChannel::IdleState) {
// Not actually an error, it is normal for Keep-Alive connections to close after some time if no request // Not actually an error, it is normal for Keep-Alive connections to close after some time if no request
// is sent on them. No need to error the other replies below. Just bail out here. // is sent on them. No need to error the other replies below. Just bail out here.
// The _q_disconnected will handle the possibly pipelined replies // The _q_disconnected will handle the possibly pipelined replies. HTTP/2 is special for now,
// we do not resend, but must report errors if any request is in progress (note, while
// not in its sendRequest(), protocol handler switches the channel to IdleState, thus
// this check is under this condition in 'if'):
if (protocolHandler.data()) {
if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct
|| connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2) {
auto h2Handler = static_cast<QHttp2ProtocolHandler *>(protocolHandler.data());
h2Handler->handleConnectionClosure();
protocolHandler.reset();
}
}
return; return;
} else if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) { } else if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) {
// Try to reconnect/resend before sending an error. // Try to reconnect/resend before sending an error.

View File

@ -532,7 +532,7 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
m_currentData.state = Qt::TouchPointReleased; m_currentData.state = Qt::TouchPointReleased;
if (m_typeB) if (m_typeB)
m_contacts[m_currentSlot].maj = m_currentData.maj; m_contacts[m_currentSlot].maj = m_currentData.maj;
} else if (data->code == ABS_PRESSURE) { } else if (data->code == ABS_PRESSURE || data->code == ABS_MT_PRESSURE) {
m_currentData.pressure = qBound(hw_pressure_min, data->value, hw_pressure_max); m_currentData.pressure = qBound(hw_pressure_min, data->value, hw_pressure_max);
if (m_typeB || m_singleTouch) if (m_typeB || m_singleTouch)
m_contacts[m_currentSlot].pressure = m_currentData.pressure; m_contacts[m_currentSlot].pressure = m_currentData.pressure;

View File

@ -42,6 +42,7 @@
#include "qwindowswindow.h" #include "qwindowswindow.h"
#include "qwindowsintegration.h" #include "qwindowsintegration.h"
#include "qwindowscursor.h" #include "qwindowscursor.h"
#include "qwindowstheme.h"
#include <QtCore/qt_windows.h> #include <QtCore/qt_windows.h>
@ -547,10 +548,13 @@ bool QWindowsScreenManager::handleScreenChanges()
// Look for changed monitors, add new ones // Look for changed monitors, add new ones
const WindowsScreenDataList newDataList = monitorData(); const WindowsScreenDataList newDataList = monitorData();
const bool lockScreen = newDataList.size() == 1 && (newDataList.front().flags & QWindowsScreenData::LockScreen); const bool lockScreen = newDataList.size() == 1 && (newDataList.front().flags & QWindowsScreenData::LockScreen);
bool primaryScreenChanged = false;
for (const QWindowsScreenData &newData : newDataList) { for (const QWindowsScreenData &newData : newDataList) {
const int existingIndex = indexOfMonitor(m_screens, newData.name); const int existingIndex = indexOfMonitor(m_screens, newData.name);
if (existingIndex != -1) { if (existingIndex != -1) {
m_screens.at(existingIndex)->handleChanges(newData); m_screens.at(existingIndex)->handleChanges(newData);
if (existingIndex == 0)
primaryScreenChanged = true;
} else { } else {
QWindowsScreen *newScreen = new QWindowsScreen(newData); QWindowsScreen *newScreen = new QWindowsScreen(newData);
m_screens.push_back(newScreen); m_screens.push_back(newScreen);
@ -567,6 +571,8 @@ bool QWindowsScreenManager::handleScreenChanges()
removeScreen(i); removeScreen(i);
} // for existing screens } // for existing screens
} // not lock screen } // not lock screen
if (primaryScreenChanged)
QWindowsTheme::instance()->refreshFonts();
return true; return true;
} }

View File

@ -85,6 +85,8 @@ public:
static bool useNativeMenus(); static bool useNativeMenus();
void refreshFonts();
static const char *name; static const char *name;
private: private:
@ -92,7 +94,6 @@ private:
void clearPalettes(); void clearPalettes();
void refreshPalettes(); void refreshPalettes();
void clearFonts(); void clearFonts();
void refreshFonts();
void refreshIconPixmapSizes(); void refreshIconPixmapSizes();
static QWindowsTheme *m_instance; static QWindowsTheme *m_instance;

View File

@ -665,24 +665,22 @@ int QShortcut::id() const
bool QShortcut::event(QEvent *e) bool QShortcut::event(QEvent *e)
{ {
Q_D(QShortcut); Q_D(QShortcut);
bool handled = false;
if (d->sc_enabled && e->type() == QEvent::Shortcut) { if (d->sc_enabled && e->type() == QEvent::Shortcut) {
QShortcutEvent *se = static_cast<QShortcutEvent *>(e); QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence){ if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence){
#if QT_CONFIG(whatsthis) #if QT_CONFIG(whatsthis)
if (QWhatsThis::inWhatsThisMode()) { if (QWhatsThis::inWhatsThisMode()) {
QWhatsThis::showText(QCursor::pos(), d->sc_whatsthis); QWhatsThis::showText(QCursor::pos(), d->sc_whatsthis);
handled = true;
} else } else
#endif #endif
if (se->isAmbiguous()) if (se->isAmbiguous())
emit activatedAmbiguously(); emit activatedAmbiguously();
else else
emit activated(); emit activated();
handled = true; return true;
} }
} }
return handled; return QObject::event(e);
} }
#endif // QT_NO_SHORTCUT #endif // QT_NO_SHORTCUT

View File

@ -456,6 +456,9 @@ void tst_Http2::goaway_data()
// - server waits for some time (enough for ur to init several streams on a // - server waits for some time (enough for ur to init several streams on a
// client side); then suddenly it replies with GOAWAY, never processing any // client side); then suddenly it replies with GOAWAY, never processing any
// request. // request.
if (clearTextHTTP2)
QSKIP("This test requires TLS with ALPN to work");
QTest::addColumn<int>("responseTimeoutMS"); QTest::addColumn<int>("responseTimeoutMS");
QTest::newRow("ImmediateGOAWAY") << 0; QTest::newRow("ImmediateGOAWAY") << 0;
QTest::newRow("DelayedGOAWAY") << 1000; QTest::newRow("DelayedGOAWAY") << 1000;

View File

@ -1010,6 +1010,9 @@ void PaintCommands::command_drawPixmap(QRegularExpressionMatch re)
qPrintable(re.captured(1)), pm.width(), pm.height(), pm.depth(), qPrintable(re.captured(1)), pm.width(), pm.height(), pm.depth(),
tx, ty, tw, th, sx, sy, sw, sh); tx, ty, tw, th, sx, sy, sw, sh);
if (!re.capturedLength(4)) // at most two coordinates specified
m_painter->drawPixmap(QPointF(tx, ty), pm);
else
m_painter->drawPixmap(QRectF(tx, ty, tw, th), pm, QRectF(sx, sy, sw, sh)); m_painter->drawPixmap(QRectF(tx, ty, tw, th), pm, QRectF(sx, sy, sw, sh));
} }
@ -1057,7 +1060,10 @@ void PaintCommands::command_drawImage(QRegularExpressionMatch re)
printf(" -(lance) drawImage('%s' dim=(%d, %d), (%f, %f, %f, %f), (%f, %f, %f, %f)\n", printf(" -(lance) drawImage('%s' dim=(%d, %d), (%f, %f, %f, %f), (%f, %f, %f, %f)\n",
qPrintable(re.captured(1)), im.width(), im.height(), tx, ty, tw, th, sx, sy, sw, sh); qPrintable(re.captured(1)), im.width(), im.height(), tx, ty, tw, th, sx, sy, sw, sh);
m_painter->drawImage(QRectF(tx, ty, tw, th), im, QRectF(sx, sy, sw, sh), Qt::OrderedDither | Qt::OrderedAlphaDither); if (!re.capturedLength(4)) // at most two coordinates specified
m_painter->drawImage(QPointF(tx, ty), im);
else
m_painter->drawImage(QRectF(tx, ty, tw, th), im, QRectF(sx, sy, sw, sh));
} }
/***************************************************************************************************/ /***************************************************************************************************/

View File

@ -123,6 +123,7 @@ private slots:
void context(); void context();
void duplicatedShortcutOverride(); void duplicatedShortcutOverride();
void shortcutToFocusProxy(); void shortcutToFocusProxy();
void deleteLater();
protected: protected:
static Qt::KeyboardModifiers toButtons( int key ); static Qt::KeyboardModifiers toButtons( int key );
@ -1305,5 +1306,14 @@ void tst_QShortcut::shortcutToFocusProxy()
QCOMPARE(le.text(), QString()); QCOMPARE(le.text(), QString());
} }
void tst_QShortcut::deleteLater()
{
QWidget w;
QPointer<QShortcut> sc(new QShortcut(QKeySequence(Qt::Key_1), &w));
sc->deleteLater();
QTRY_VERIFY(!sc);
}
QTEST_MAIN(tst_QShortcut) QTEST_MAIN(tst_QShortcut)
#include "tst_qshortcut.moc" #include "tst_qshortcut.moc"