Merge remote-tracking branch 'origin/5.4.2' into 5.4
Change-Id: I209def43673df62c75add4f623350fb1c98887a1
2
configure
vendored
@ -674,7 +674,7 @@ CFG_SSE4_1=auto
|
||||
CFG_SSE4_2=auto
|
||||
CFG_AVX=auto
|
||||
CFG_AVX2=auto
|
||||
CFG_REDUCE_RELOCATIONS=auto
|
||||
CFG_REDUCE_RELOCATIONS=no
|
||||
CFG_ACCESSIBILITY=auto
|
||||
CFG_ACCESSIBILITY_ATSPI_BRIDGE=no # will be enabled depending on dbus and accessibility being enabled
|
||||
CFG_NEON=auto
|
||||
|
107
dist/changes-5.4.2
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
Qt 5.4.2 is a bug-fix release. It maintains both forward and backward
|
||||
compatibility (source and binary) with Qt 5.4.1. Compatibility with Qt
|
||||
5.4.0 is also retained, except on Windows when using MSVC 2012 or MSVC
|
||||
2013. See note below.
|
||||
|
||||
For more details, refer to the online documentation included in this
|
||||
distribution. The documentation is also available online:
|
||||
|
||||
http://doc.qt.io/qt-5.4/
|
||||
|
||||
The Qt version 5.4 series is binary compatible with the 5.3.x series.
|
||||
Applications compiled for 5.3 will continue to run with 5.4 with the
|
||||
exception of on Windows when using MSVC 2012 or MSVC 2013. See note
|
||||
below.
|
||||
|
||||
Some of the changes listed in this file include issue tracking numbers
|
||||
corresponding to tasks in the Qt Bug Tracker:
|
||||
|
||||
http://bugreports.qt.io/
|
||||
|
||||
Each of these identifiers can be entered in the bug tracker to obtain more
|
||||
information about a particular change.
|
||||
|
||||
****************************************************************************
|
||||
* Important Behavior Changes *
|
||||
****************************************************************************
|
||||
- Restored binary compatibility with Qt 5.3.2 on Windows when using MSVC
|
||||
2012 or MSVC 2013. This means that Qt 5.4.1 and 5.4.2 are no longer
|
||||
binary compatible with Qt 5.4.0 when using either of those compilers.
|
||||
- [QTBUG-42594] OS X binary package: fixed incorrect linking to libraries in
|
||||
/opt/local/lib
|
||||
- EXIF orientation is no longer applied to JPEG images on read. EXIF
|
||||
orientation on JPEG was introduced in 5.4.0, but due to a bug the most
|
||||
common EXIF-format (big-endian) was not working until 5.4.1. 5.4.2 restores the
|
||||
behavior of 5.4.0 and earlier for most EXIF-tagged JPEGs.
|
||||
EXIF orientation will be an opt-in starting with Qt 5.5.
|
||||
|
||||
****************************************************************************
|
||||
* Library *
|
||||
****************************************************************************
|
||||
|
||||
QtCore
|
||||
------
|
||||
- [QTBUG-43893] Fixed memory leak in qSetMessagePattern
|
||||
- [QTBUG-43513] QXmlStreamReader: Correctly parse XML containing NUL bytes
|
||||
in the input stream
|
||||
- [QTBUG-43352] QTemporaryDirectory: Properly clean up in case of a failure
|
||||
- [QTBUG-43827] Fixed regression in QSortFilterProxyModel which crashed when
|
||||
sorting a tree model
|
||||
|
||||
QtGui
|
||||
-----
|
||||
- [QTBUG-44273] Fixed misplacement of outlined text with native text rendering
|
||||
- [QTBUG-44147] Fixed VNC not working on some VNC servers
|
||||
- [QTBUG-43850] Fixed crash with multi-threaded font usage
|
||||
- [QTBUG-43850] Made the old harfbuzz fallback available at runtime
|
||||
- Improvements to the experimental high-dpi support
|
||||
- [QTBUG-43318] Better resolution of GLES 3 functions to avoid issues when
|
||||
deploying on systems with GLES 2.0 only
|
||||
|
||||
QtWidgets
|
||||
---------
|
||||
- [QTBUG-43830] Fixed crash in stylesheets when styling QProgressBar
|
||||
- [QTBUG-43663] QColorDialog: Don't lose focus while color picking
|
||||
|
||||
QtNetwork
|
||||
---------
|
||||
- [QTBUG-43793] Fixed disconnects of QSSLSocket after starting encryption
|
||||
|
||||
QtPrintSupport
|
||||
--------------
|
||||
- [QTBUG-43124] Fixed QPrinter::{width,height} return values
|
||||
|
||||
****************************************************************************
|
||||
* Platform Specific Changes *
|
||||
****************************************************************************
|
||||
|
||||
Android
|
||||
-------
|
||||
|
||||
- [QTBUG-44648] Fixed rendering Chinese text on Android 5
|
||||
|
||||
Linux/XCB
|
||||
---------
|
||||
|
||||
- [QTBUG-45071] Don't crash when resizing windows to bigger than 3840x2160
|
||||
|
||||
****************************************************************************
|
||||
* Tools *
|
||||
****************************************************************************
|
||||
|
||||
configure & build system
|
||||
------------------------
|
||||
|
||||
- CMake-based projects using Qt will now always be built with -fPIE,
|
||||
which fixes function pointer based QObject::connect() on ARM. This
|
||||
is consistent with qmake
|
||||
- [Android] Fixed compilation on armv5 with 4.9 toolchain
|
||||
|
||||
qmake
|
||||
-----
|
||||
|
||||
- [VS] Fixed handling of files that are excluded from build
|
||||
- [QTBUG-44413][VS] Fixed vcxproj generation for CONFIG-=flat, again
|
||||
- [QTBUG-44595] Restored Qt 4 behavior of qtLibraryTarget()
|
||||
- [QTBUG-45118][Windows] Fixed parallel build when using TYPELIBS
|
||||
- [OS X/iOS] Fixed QMAKE_INFO_PLIST path resolution for shadow builds
|
@ -1100,7 +1100,9 @@ public class ExtractStyle {
|
||||
{
|
||||
try {
|
||||
InsetDrawable d = (InsetDrawable)drawable;
|
||||
Object mInsetStateObject = getAccessibleField(InsetDrawable.class, "mInsetState").get(d);
|
||||
// mInsetState changed to mState in Android 5.1 (22)
|
||||
Object mInsetStateObject = getAccessibleField(InsetDrawable.class, (Build.VERSION.SDK_INT > 21) ? "mState"
|
||||
: "mInsetState").get(d);
|
||||
Rect _padding = new Rect();
|
||||
boolean hasPadding = d.getPadding(_padding);
|
||||
return getDrawable(getAccessibleField(mInsetStateObject.getClass(), "mDrawable").get(mInsetStateObject), filename, hasPadding ? _padding : null);
|
||||
|
@ -187,7 +187,7 @@ public class QtActivity extends Activity
|
||||
QT_ANDROID_THEMES = new String[] {"Theme_Light"};
|
||||
QT_ANDROID_DEFAULT_THEME = "Theme_Light";
|
||||
}
|
||||
else if ((Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT <= 13) || Build.VERSION.SDK_INT == 21){
|
||||
else if ((Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT <= 13) || Build.VERSION.SDK_INT >= 21){
|
||||
QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"};
|
||||
QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light";
|
||||
} else {
|
||||
|
@ -236,6 +236,11 @@ qint64 QNonContiguousByteDeviceByteArrayImpl::size()
|
||||
return byteArray->size();
|
||||
}
|
||||
|
||||
qint64 QNonContiguousByteDeviceByteArrayImpl::pos()
|
||||
{
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QSharedPointer<QRingBuffer> rb)
|
||||
: QNonContiguousByteDevice(), currentPosition(0)
|
||||
{
|
||||
@ -273,6 +278,11 @@ bool QNonContiguousByteDeviceRingBufferImpl::atEnd()
|
||||
return currentPosition >= size();
|
||||
}
|
||||
|
||||
qint64 QNonContiguousByteDeviceRingBufferImpl::pos()
|
||||
{
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
bool QNonContiguousByteDeviceRingBufferImpl::reset()
|
||||
{
|
||||
if (resetDisabled)
|
||||
@ -406,6 +416,14 @@ qint64 QNonContiguousByteDeviceIoDeviceImpl::size()
|
||||
return device->size() - initialPosition;
|
||||
}
|
||||
|
||||
qint64 QNonContiguousByteDeviceIoDeviceImpl::pos()
|
||||
{
|
||||
if (device->isSequential())
|
||||
return -1;
|
||||
|
||||
return device->pos();
|
||||
}
|
||||
|
||||
QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0)
|
||||
{
|
||||
byteDevice = bd;
|
||||
|
@ -61,6 +61,7 @@ public:
|
||||
virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0;
|
||||
virtual bool advanceReadPointer(qint64 amount) = 0;
|
||||
virtual bool atEnd() = 0;
|
||||
virtual qint64 pos() { return -1; }
|
||||
virtual bool reset() = 0;
|
||||
void disableReset();
|
||||
bool isResetDisabled() { return resetDisabled; }
|
||||
@ -106,6 +107,7 @@ public:
|
||||
bool atEnd();
|
||||
bool reset();
|
||||
qint64 size();
|
||||
qint64 pos() Q_DECL_OVERRIDE;
|
||||
protected:
|
||||
QByteArray* byteArray;
|
||||
qint64 currentPosition;
|
||||
@ -121,6 +123,7 @@ public:
|
||||
bool atEnd();
|
||||
bool reset();
|
||||
qint64 size();
|
||||
qint64 pos() Q_DECL_OVERRIDE;
|
||||
protected:
|
||||
QSharedPointer<QRingBuffer> ringBuffer;
|
||||
qint64 currentPosition;
|
||||
@ -138,6 +141,7 @@ public:
|
||||
bool atEnd();
|
||||
bool reset();
|
||||
qint64 size();
|
||||
qint64 pos() Q_DECL_OVERRIDE;
|
||||
protected:
|
||||
QIODevice* device;
|
||||
QByteArray* currentReadBuffer;
|
||||
|
@ -726,7 +726,7 @@ public:
|
||||
};
|
||||
|
||||
QJpegHandlerPrivate(QJpegHandler *qq)
|
||||
: quality(75), exifOrientation(1), iod_src(0), state(Ready), q(qq)
|
||||
: quality(75), iod_src(0), state(Ready), q(qq)
|
||||
{}
|
||||
|
||||
~QJpegHandlerPrivate()
|
||||
@ -741,10 +741,8 @@ public:
|
||||
|
||||
bool readJpegHeader(QIODevice*);
|
||||
bool read(QImage *image);
|
||||
void applyExifOrientation(QImage *image);
|
||||
|
||||
int quality;
|
||||
int exifOrientation;
|
||||
QVariant size;
|
||||
QImage::Format format;
|
||||
QSize scaledSize;
|
||||
@ -762,97 +760,6 @@ public:
|
||||
QJpegHandler *q;
|
||||
};
|
||||
|
||||
static bool readExifHeader(QDataStream &stream)
|
||||
{
|
||||
char prefix[6];
|
||||
if (stream.readRawData(prefix, sizeof(prefix)) != sizeof(prefix))
|
||||
return false;
|
||||
if (prefix[0] != 'E' || prefix[1] != 'x' || prefix[2] != 'i' || prefix[3] != 'f' || prefix[4] != 0 || prefix[5] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns -1 on error
|
||||
* Returns 0 if no Exif orientation was found
|
||||
* Returns 1 orientation is horizontal (normal)
|
||||
* Returns 2 mirror horizontal
|
||||
* Returns 3 rotate 180
|
||||
* Returns 4 mirror vertical
|
||||
* Returns 5 mirror horizontal and rotate 270 CCW
|
||||
* Returns 6 rotate 90 CW
|
||||
* Returns 7 mirror horizontal and rotate 90 CW
|
||||
* Returns 8 rotate 270 CW
|
||||
*/
|
||||
static int getExifOrientation(QByteArray &exifData)
|
||||
{
|
||||
QDataStream stream(&exifData, QIODevice::ReadOnly);
|
||||
|
||||
if (!readExifHeader(stream))
|
||||
return -1;
|
||||
|
||||
quint16 val;
|
||||
quint32 offset;
|
||||
|
||||
// read byte order marker
|
||||
stream >> val;
|
||||
if (val == 0x4949) // 'II' == Intel
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
else if (val == 0x4d4d) // 'MM' == Motorola
|
||||
stream.setByteOrder(QDataStream::BigEndian);
|
||||
else
|
||||
return -1; // unknown byte order
|
||||
|
||||
// read size
|
||||
stream >> val;
|
||||
if (val != 0x2a)
|
||||
return -1;
|
||||
|
||||
stream >> offset;
|
||||
// we have already used 8 bytes of TIFF header
|
||||
offset -= 8;
|
||||
|
||||
// read IFD
|
||||
while (!stream.atEnd()) {
|
||||
quint16 numEntries;
|
||||
|
||||
// skip offset bytes to get the next IFD
|
||||
if (stream.skipRawData(offset) != (qint32)offset)
|
||||
return -1;
|
||||
|
||||
stream >> numEntries;
|
||||
|
||||
for (;numEntries > 0; --numEntries) {
|
||||
quint16 tag;
|
||||
quint16 type;
|
||||
quint32 components;
|
||||
quint16 value;
|
||||
quint16 dummy;
|
||||
|
||||
stream >> tag >> type >> components >> value >> dummy;
|
||||
if (tag == 0x0112) { // Tag Exif.Image.Orientation
|
||||
if (components !=1)
|
||||
return -1;
|
||||
if (type != 3) // we are expecting it to be an unsigned short
|
||||
return -1;
|
||||
if (value < 1 || value > 8) // check for valid range
|
||||
return -1;
|
||||
|
||||
// It is possible to include the orientation multiple times.
|
||||
// Right now the first value is returned.
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// read offset to next IFD
|
||||
stream >> offset;
|
||||
if (offset == 0) // this is the last IFD
|
||||
break;
|
||||
}
|
||||
|
||||
// No Exif orientation was found
|
||||
return 0;
|
||||
}
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
@ -872,7 +779,6 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
||||
|
||||
if (!setjmp(err.setjmp_buffer)) {
|
||||
jpeg_save_markers(&info, JPEG_COM, 0xFFFF);
|
||||
jpeg_save_markers(&info, JPEG_APP0+1, 0xFFFF); // Exif uses APP1 marker
|
||||
|
||||
(void) jpeg_read_header(&info, TRUE);
|
||||
|
||||
@ -884,8 +790,6 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
||||
format = QImage::Format_Invalid;
|
||||
read_jpeg_format(format, &info);
|
||||
|
||||
QByteArray exifData;
|
||||
|
||||
for (jpeg_saved_marker_ptr marker = info.marker_list; marker != NULL; marker = marker->next) {
|
||||
if (marker->marker == JPEG_COM) {
|
||||
QString key, value;
|
||||
@ -903,18 +807,9 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
||||
description += key + QLatin1String(": ") + value.simplified();
|
||||
readTexts.append(key);
|
||||
readTexts.append(value);
|
||||
} else if (marker->marker == JPEG_APP0+1) {
|
||||
exifData.append((const char*)marker->data, marker->data_length);
|
||||
}
|
||||
}
|
||||
|
||||
if (exifData.size()) {
|
||||
// Exif data present
|
||||
int orientation = getExifOrientation(exifData);
|
||||
if (orientation > 0)
|
||||
exifOrientation = orientation;
|
||||
}
|
||||
|
||||
state = ReadHeader;
|
||||
return true;
|
||||
}
|
||||
@ -928,48 +823,6 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
||||
return true;
|
||||
}
|
||||
|
||||
void QJpegHandlerPrivate::applyExifOrientation(QImage *image)
|
||||
{
|
||||
// This is not an optimized implementation, but easiest to maintain
|
||||
QTransform transform;
|
||||
|
||||
switch (exifOrientation) {
|
||||
case 1: // normal
|
||||
break;
|
||||
case 2: // mirror horizontal
|
||||
*image = image->mirrored(true, false);
|
||||
break;
|
||||
case 3: // rotate 180
|
||||
transform.rotate(180);
|
||||
*image = image->transformed(transform);
|
||||
break;
|
||||
case 4: // mirror vertical
|
||||
*image = image->mirrored(false, true);
|
||||
break;
|
||||
case 5: // mirror horizontal and rotate 270 CCW
|
||||
*image = image->mirrored(true, false);
|
||||
transform.rotate(270);
|
||||
*image = image->transformed(transform);
|
||||
break;
|
||||
case 6: // rotate 90 CW
|
||||
transform.rotate(90);
|
||||
*image = image->transformed(transform);
|
||||
break;
|
||||
case 7: // mirror horizontal and rotate 90 CW
|
||||
*image = image->mirrored(true, false);
|
||||
transform.rotate(90);
|
||||
*image = image->transformed(transform);
|
||||
break;
|
||||
case 8: // rotate 270 CW
|
||||
transform.rotate(-90);
|
||||
*image = image->transformed(transform);
|
||||
break;
|
||||
default:
|
||||
qWarning("This should never happen");
|
||||
}
|
||||
exifOrientation = 1;
|
||||
}
|
||||
|
||||
bool QJpegHandlerPrivate::read(QImage *image)
|
||||
{
|
||||
if(state == Ready)
|
||||
@ -981,7 +834,6 @@ bool QJpegHandlerPrivate::read(QImage *image)
|
||||
if (success) {
|
||||
for (int i = 0; i < readTexts.size()-1; i+=2)
|
||||
image->setText(readTexts.at(i), readTexts.at(i+1));
|
||||
applyExifOrientation(image);
|
||||
|
||||
state = Ready;
|
||||
return true;
|
||||
|
@ -106,15 +106,19 @@ void QHttpNetworkConnectionChannel::init()
|
||||
socket->setProxy(QNetworkProxy::NoProxy);
|
||||
#endif
|
||||
|
||||
// We want all signals (except the interactive ones) be connected as QueuedConnection
|
||||
// because else we're falling into cases where we recurse back into the socket code
|
||||
// and mess up the state. Always going to the event loop (and expecting that when reading/writing)
|
||||
// is safer.
|
||||
QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
|
||||
this, SLOT(_q_bytesWritten(qint64)),
|
||||
Qt::DirectConnection);
|
||||
Qt::QueuedConnection);
|
||||
QObject::connect(socket, SIGNAL(connected()),
|
||||
this, SLOT(_q_connected()),
|
||||
Qt::DirectConnection);
|
||||
Qt::QueuedConnection);
|
||||
QObject::connect(socket, SIGNAL(readyRead()),
|
||||
this, SLOT(_q_readyRead()),
|
||||
Qt::DirectConnection);
|
||||
Qt::QueuedConnection);
|
||||
|
||||
// The disconnected() and error() signals may already come
|
||||
// while calling connectToHost().
|
||||
@ -143,13 +147,13 @@ void QHttpNetworkConnectionChannel::init()
|
||||
// won't be a sslSocket if encrypt is false
|
||||
QObject::connect(sslSocket, SIGNAL(encrypted()),
|
||||
this, SLOT(_q_encrypted()),
|
||||
Qt::DirectConnection);
|
||||
Qt::QueuedConnection);
|
||||
QObject::connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
|
||||
this, SLOT(_q_sslErrors(QList<QSslError>)),
|
||||
Qt::DirectConnection);
|
||||
QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
|
||||
this, SLOT(_q_encryptedBytesWritten(qint64)),
|
||||
Qt::DirectConnection);
|
||||
Qt::QueuedConnection);
|
||||
|
||||
if (ignoreAllSslErrors)
|
||||
sslSocket->ignoreSslErrors();
|
||||
@ -186,8 +190,11 @@ void QHttpNetworkConnectionChannel::close()
|
||||
// pendingEncrypt must only be true in between connected and encrypted states
|
||||
pendingEncrypt = false;
|
||||
|
||||
if (socket)
|
||||
if (socket) {
|
||||
// socket can be 0 since the host lookup is done from qhttpnetworkconnection.cpp while
|
||||
// there is no socket yet.
|
||||
socket->close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -353,6 +360,14 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This code path for ConnectedState
|
||||
if (pendingEncrypt) {
|
||||
// Let's only be really connected when we have received the encrypted() signal. Else the state machine seems to mess up
|
||||
// and corrupt the things sent to the server.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -659,6 +674,12 @@ bool QHttpNetworkConnectionChannel::isSocketReading() const
|
||||
void QHttpNetworkConnectionChannel::_q_bytesWritten(qint64 bytes)
|
||||
{
|
||||
Q_UNUSED(bytes);
|
||||
if (ssl) {
|
||||
// In the SSL case we want to send data from encryptedBytesWritten signal since that one
|
||||
// is the one going down to the actual network, not only into some SSL buffer.
|
||||
return;
|
||||
}
|
||||
|
||||
// bytes have been written to the socket. write even more of them :)
|
||||
if (isSocketWriting())
|
||||
sendRequest();
|
||||
@ -734,7 +755,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
|
||||
|
||||
// ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again!
|
||||
//channels[i].reconnectAttempts = 2;
|
||||
if (pendingEncrypt) {
|
||||
if (ssl || pendingEncrypt) { // FIXME: Didn't work properly with pendingEncrypt only, we should refactor this into an EncrypingState
|
||||
#ifndef QT_NO_SSL
|
||||
if (connection->sslContext().isNull()) {
|
||||
// this socket is making the 1st handshake for this connection,
|
||||
|
@ -83,6 +83,8 @@ typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
|
||||
class QHttpNetworkConnectionChannel : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// TODO: Refactor this to add an EncryptingState (and remove pendingEncrypt).
|
||||
// Also add an Unconnected state so IdleState does not have double meaning.
|
||||
enum ChannelState {
|
||||
IdleState = 0, // ready to send request
|
||||
ConnectingState = 1, // connecting to host
|
||||
|
@ -368,6 +368,13 @@ bool QHttpProtocolHandler::sendRequest()
|
||||
// nothing to read currently, break the loop
|
||||
break;
|
||||
} else {
|
||||
if (m_channel->written != uploadByteDevice->pos()) {
|
||||
// Sanity check. This was useful in tracking down an upload corruption.
|
||||
qWarning() << "QHttpProtocolHandler: Internal error in sendRequest. Expected to write at position" << m_channel->written << "but read device is at" << uploadByteDevice->pos();
|
||||
Q_ASSERT(m_channel->written == uploadByteDevice->pos());
|
||||
m_connection->d_func()->emitReplyError(m_socket, m_reply, QNetworkReply::ProtocolFailure);
|
||||
return false;
|
||||
}
|
||||
qint64 currentWriteSize = m_socket->write(readPointer, currentReadSize);
|
||||
if (currentWriteSize == -1 || currentWriteSize != currentReadSize) {
|
||||
// socket broke down
|
||||
|
@ -187,6 +187,7 @@ protected:
|
||||
QByteArray m_dataArray;
|
||||
bool m_atEnd;
|
||||
qint64 m_size;
|
||||
qint64 m_pos; // to match calls of haveDataSlot with the expected position
|
||||
public:
|
||||
QNonContiguousByteDeviceThreadForwardImpl(bool aE, qint64 s)
|
||||
: QNonContiguousByteDevice(),
|
||||
@ -194,7 +195,8 @@ public:
|
||||
m_amount(0),
|
||||
m_data(0),
|
||||
m_atEnd(aE),
|
||||
m_size(s)
|
||||
m_size(s),
|
||||
m_pos(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -202,6 +204,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
qint64 pos() Q_DECL_OVERRIDE
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
const char* readPointer(qint64 maximumLength, qint64 &len)
|
||||
{
|
||||
if (m_amount > 0) {
|
||||
@ -229,11 +236,10 @@ public:
|
||||
|
||||
m_amount -= a;
|
||||
m_data += a;
|
||||
m_pos += a;
|
||||
|
||||
// To main thread to inform about our state
|
||||
emit processedData(a);
|
||||
|
||||
// FIXME possible optimization, already ask user thread for some data
|
||||
// To main thread to inform about our state. The m_pos will be sent as a sanity check.
|
||||
emit processedData(m_pos, a);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -250,10 +256,21 @@ public:
|
||||
{
|
||||
m_amount = 0;
|
||||
m_data = 0;
|
||||
m_dataArray.clear();
|
||||
|
||||
if (wantDataPending) {
|
||||
// had requested the user thread to send some data (only 1 in-flight at any moment)
|
||||
wantDataPending = false;
|
||||
}
|
||||
|
||||
// Communicate as BlockingQueuedConnection
|
||||
bool b = false;
|
||||
emit resetData(&b);
|
||||
if (b) {
|
||||
// the reset succeeded, we're at pos 0 again
|
||||
m_pos = 0;
|
||||
// the HTTP code will anyway abort the request if !b.
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@ -264,8 +281,13 @@ public:
|
||||
|
||||
public slots:
|
||||
// From user thread:
|
||||
void haveDataSlot(QByteArray dataArray, bool dataAtEnd, qint64 dataSize)
|
||||
void haveDataSlot(qint64 pos, QByteArray dataArray, bool dataAtEnd, qint64 dataSize)
|
||||
{
|
||||
if (pos != m_pos) {
|
||||
// Sometimes when re-sending a request in the qhttpnetwork* layer there is a pending haveData from the
|
||||
// user thread on the way to us. We need to ignore it since it is the data for the wrong(later) chunk.
|
||||
return;
|
||||
}
|
||||
wantDataPending = false;
|
||||
|
||||
m_dataArray = dataArray;
|
||||
@ -285,7 +307,7 @@ signals:
|
||||
|
||||
// to main thread:
|
||||
void wantData(qint64);
|
||||
void processedData(qint64);
|
||||
void processedData(qint64 pos, qint64 amount);
|
||||
void resetData(bool *b);
|
||||
};
|
||||
|
||||
|
@ -424,6 +424,7 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate()
|
||||
, synchronous(false)
|
||||
, state(Idle)
|
||||
, statusCode(0)
|
||||
, uploadByteDevicePosition(false)
|
||||
, uploadDeviceChoking(false)
|
||||
, outgoingData(0)
|
||||
, bytesUploaded(-1)
|
||||
@ -863,9 +864,9 @@ void QNetworkReplyHttpImplPrivate::postRequest()
|
||||
q, SLOT(uploadByteDeviceReadyReadSlot()),
|
||||
Qt::QueuedConnection);
|
||||
|
||||
// From main thread to user thread:
|
||||
QObject::connect(q, SIGNAL(haveUploadData(QByteArray,bool,qint64)),
|
||||
forwardUploadDevice, SLOT(haveDataSlot(QByteArray,bool,qint64)), Qt::QueuedConnection);
|
||||
// From user thread to http thread:
|
||||
QObject::connect(q, SIGNAL(haveUploadData(qint64,QByteArray,bool,qint64)),
|
||||
forwardUploadDevice, SLOT(haveDataSlot(qint64,QByteArray,bool,qint64)), Qt::QueuedConnection);
|
||||
QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()),
|
||||
forwardUploadDevice, SIGNAL(readyRead()),
|
||||
Qt::QueuedConnection);
|
||||
@ -873,8 +874,8 @@ void QNetworkReplyHttpImplPrivate::postRequest()
|
||||
// From http thread to user thread:
|
||||
QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)),
|
||||
q, SLOT(wantUploadDataSlot(qint64)));
|
||||
QObject::connect(forwardUploadDevice, SIGNAL(processedData(qint64)),
|
||||
q, SLOT(sentUploadDataSlot(qint64)));
|
||||
QObject::connect(forwardUploadDevice,SIGNAL(processedData(qint64, qint64)),
|
||||
q, SLOT(sentUploadDataSlot(qint64,qint64)));
|
||||
QObject::connect(forwardUploadDevice, SIGNAL(resetData(bool*)),
|
||||
q, SLOT(resetUploadDataSlot(bool*)),
|
||||
Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued!
|
||||
@ -1268,12 +1269,22 @@ void QNetworkReplyHttpImplPrivate::replySslConfigurationChanged(const QSslConfig
|
||||
void QNetworkReplyHttpImplPrivate::resetUploadDataSlot(bool *r)
|
||||
{
|
||||
*r = uploadByteDevice->reset();
|
||||
if (*r) {
|
||||
// reset our own position which is used for the inter-thread communication
|
||||
uploadByteDevicePosition = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
|
||||
void QNetworkReplyHttpImplPrivate::sentUploadDataSlot(qint64 amount)
|
||||
void QNetworkReplyHttpImplPrivate::sentUploadDataSlot(qint64 pos, qint64 amount)
|
||||
{
|
||||
if (uploadByteDevicePosition + amount != pos) {
|
||||
// Sanity check, should not happen.
|
||||
error(QNetworkReply::UnknownNetworkError, "");
|
||||
return;
|
||||
}
|
||||
uploadByteDevice->advanceReadPointer(amount);
|
||||
uploadByteDevicePosition += amount;
|
||||
}
|
||||
|
||||
// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
|
||||
@ -1298,7 +1309,7 @@ void QNetworkReplyHttpImplPrivate::wantUploadDataSlot(qint64 maxSize)
|
||||
QByteArray dataArray(data, currentUploadDataLength);
|
||||
|
||||
// Communicate back to HTTP thread
|
||||
emit q->haveUploadData(dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size());
|
||||
emit q->haveUploadData(uploadByteDevicePosition, dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size());
|
||||
}
|
||||
|
||||
void QNetworkReplyHttpImplPrivate::uploadByteDeviceReadyReadSlot()
|
||||
|
@ -120,7 +120,7 @@ public:
|
||||
|
||||
Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r))
|
||||
Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
|
||||
Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64))
|
||||
Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64,qint64))
|
||||
Q_PRIVATE_SLOT(d_func(), void uploadByteDeviceReadyReadSlot())
|
||||
Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
|
||||
@ -144,7 +144,7 @@ signals:
|
||||
|
||||
void startHttpRequestSynchronously();
|
||||
|
||||
void haveUploadData(QByteArray dataArray, bool dataAtEnd, qint64 dataSize);
|
||||
void haveUploadData(const qint64 pos, QByteArray dataArray, bool dataAtEnd, qint64 dataSize);
|
||||
};
|
||||
|
||||
class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
|
||||
@ -195,6 +195,7 @@ public:
|
||||
// upload
|
||||
QNonContiguousByteDevice* createUploadByteDevice();
|
||||
QSharedPointer<QNonContiguousByteDevice> uploadByteDevice;
|
||||
qint64 uploadByteDevicePosition;
|
||||
bool uploadDeviceChoking; // if we couldn't readPointer() any data at the moment
|
||||
QIODevice *outgoingData;
|
||||
QSharedPointer<QRingBuffer> outgoingDataBuffer;
|
||||
@ -283,7 +284,7 @@ public:
|
||||
// From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread:
|
||||
void resetUploadDataSlot(bool *r);
|
||||
void wantUploadDataSlot(qint64);
|
||||
void sentUploadDataSlot(qint64);
|
||||
void sentUploadDataSlot(qint64, qint64);
|
||||
|
||||
// From user's QNonContiguousByteDevice
|
||||
void uploadByteDeviceReadyReadSlot();
|
||||
|
@ -168,8 +168,20 @@ public:
|
||||
QModelIndex index;
|
||||
int col = -1;
|
||||
int row = -1;
|
||||
const QMimeData *mime = event->mimeData();
|
||||
|
||||
// Drag enter event shall always be accepted, if mime type and action match.
|
||||
// Whether the data can actually be dropped will be checked in drag move.
|
||||
if (event->type() == QEvent::DragEnter) {
|
||||
const QStringList modelTypes = model->mimeTypes();
|
||||
for (int i = 0; i < modelTypes.count(); ++i)
|
||||
if (mime->hasFormat(modelTypes.at(i))
|
||||
&& (event->dropAction() & model->supportedDropActions()))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dropOn(event, &row, &col, &index)) {
|
||||
return model->canDropMimeData(event->mimeData(),
|
||||
return model->canDropMimeData(mime,
|
||||
dragDropMode == QAbstractItemView::InternalMove ? Qt::MoveAction : event->dropAction(),
|
||||
row, col, index);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 910 B |
Before Width: | Height: | Size: 910 B |
Before Width: | Height: | Size: 988 B |
Before Width: | Height: | Size: 995 B |
Before Width: | Height: | Size: 912 B |
Before Width: | Height: | Size: 911 B |
Before Width: | Height: | Size: 911 B |
Before Width: | Height: | Size: 987 B |
Before Width: | Height: | Size: 991 B |
@ -173,9 +173,6 @@ private slots:
|
||||
void invertPixelsRGB_data();
|
||||
void invertPixelsRGB();
|
||||
|
||||
void exifOrientation_data();
|
||||
void exifOrientation();
|
||||
|
||||
void cleanupFunctions();
|
||||
|
||||
private:
|
||||
@ -2649,36 +2646,6 @@ void tst_QImage::invertPixelsRGB()
|
||||
QCOMPARE(qBlue(pixel) >> 4, (255 - 96) >> 4);
|
||||
}
|
||||
|
||||
void tst_QImage::exifOrientation_data()
|
||||
{
|
||||
QTest::addColumn<QString>("fileName");
|
||||
QTest::newRow("Orientation 1, Intel format") << m_prefix + "jpeg_exif_orientation_value_1.jpg";
|
||||
QTest::newRow("Orientation 2, Intel format") << m_prefix + "jpeg_exif_orientation_value_2.jpg";
|
||||
QTest::newRow("Orientation 3, Intel format") << m_prefix + "jpeg_exif_orientation_value_3.jpg";
|
||||
QTest::newRow("Orientation 4, Intel format") << m_prefix + "jpeg_exif_orientation_value_4.jpg";
|
||||
QTest::newRow("Orientation 5, Intel format") << m_prefix + "jpeg_exif_orientation_value_5.jpg";
|
||||
QTest::newRow("Orientation 6, Intel format") << m_prefix + "jpeg_exif_orientation_value_6.jpg";
|
||||
QTest::newRow("Orientation 6, Motorola format") << m_prefix + "jpeg_exif_orientation_value_6_motorola.jpg";
|
||||
QTest::newRow("Orientation 7, Intel format") << m_prefix + "jpeg_exif_orientation_value_7.jpg";
|
||||
QTest::newRow("Orientation 8, Intel format") << m_prefix + "jpeg_exif_orientation_value_8.jpg";
|
||||
}
|
||||
|
||||
void tst_QImage::exifOrientation()
|
||||
{
|
||||
QFETCH(QString, fileName);
|
||||
|
||||
QImage img;
|
||||
QRgb px;
|
||||
|
||||
QVERIFY(img.load(fileName));
|
||||
|
||||
px = img.pixel(0, 0);
|
||||
QVERIFY(qRed(px) > 250 && qGreen(px) < 5 && qBlue(px) < 5);
|
||||
|
||||
px = img.pixel(img.width() - 1, 0);
|
||||
QVERIFY(qRed(px) < 5 && qGreen(px) < 5 && qBlue(px) > 250);
|
||||
}
|
||||
|
||||
static void cleanupFunction(void* info)
|
||||
{
|
||||
bool *called = static_cast<bool*>(info);
|
||||
|
@ -457,6 +457,10 @@ private Q_SLOTS:
|
||||
|
||||
void putWithRateLimiting();
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
void putWithServerClosingConnectionImmediately();
|
||||
#endif
|
||||
|
||||
// NOTE: This test must be last!
|
||||
void parentingRepliesToTheApp();
|
||||
private:
|
||||
@ -4718,18 +4722,22 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag()
|
||||
class SslServer : public QTcpServer {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SslServer() : socket(0) {};
|
||||
SslServer() : socket(0), m_ssl(true) {}
|
||||
void incomingConnection(qintptr socketDescriptor) {
|
||||
QSslSocket *serverSocket = new QSslSocket;
|
||||
serverSocket->setParent(this);
|
||||
|
||||
if (serverSocket->setSocketDescriptor(socketDescriptor)) {
|
||||
connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
|
||||
if (!m_ssl) {
|
||||
emit newPlainConnection(serverSocket);
|
||||
return;
|
||||
}
|
||||
QString testDataDir = QFileInfo(QFINDTESTDATA("rfc3252.txt")).absolutePath();
|
||||
if (testDataDir.isEmpty())
|
||||
testDataDir = QCoreApplication::applicationDirPath();
|
||||
|
||||
connect(serverSocket, SIGNAL(encrypted()), this, SLOT(encryptedSlot()));
|
||||
connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
|
||||
serverSocket->setProtocol(QSsl::AnyProtocol);
|
||||
connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), serverSocket, SLOT(ignoreSslErrors()));
|
||||
serverSocket->setLocalCertificate(testDataDir + "/certs/server.pem");
|
||||
@ -4740,11 +4748,12 @@ public:
|
||||
}
|
||||
}
|
||||
signals:
|
||||
void newEncryptedConnection();
|
||||
void newEncryptedConnection(QSslSocket *s);
|
||||
void newPlainConnection(QSslSocket *s);
|
||||
public slots:
|
||||
void encryptedSlot() {
|
||||
socket = (QSslSocket*) sender();
|
||||
emit newEncryptedConnection();
|
||||
emit newEncryptedConnection(socket);
|
||||
}
|
||||
void readyReadSlot() {
|
||||
// for the incoming sockets, not the server socket
|
||||
@ -4753,6 +4762,7 @@ public slots:
|
||||
|
||||
public:
|
||||
QSslSocket *socket;
|
||||
bool m_ssl;
|
||||
};
|
||||
|
||||
// very similar to ioPostToHttpUploadProgress but for SSL
|
||||
@ -4780,7 +4790,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
|
||||
QNetworkReplyPtr reply(manager.post(request, sourceFile));
|
||||
|
||||
QSignalSpy spy(reply.data(), SIGNAL(uploadProgress(qint64,qint64)));
|
||||
connect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
connect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply.data(), SLOT(ignoreSslErrors()));
|
||||
|
||||
// get the request started and the incoming socket connected
|
||||
@ -4788,7 +4798,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
QTcpSocket *incomingSocket = server.socket;
|
||||
QVERIFY(incomingSocket);
|
||||
disconnect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
disconnect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
|
||||
|
||||
incomingSocket->setReadBufferSize(1*1024);
|
||||
@ -7905,6 +7915,159 @@ void tst_QNetworkReply::putWithRateLimiting()
|
||||
}
|
||||
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
|
||||
class PutWithServerClosingConnectionImmediatelyHandler: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
bool m_parsedHeaders;
|
||||
QByteArray m_receivedData;
|
||||
QByteArray m_expectedData;
|
||||
QSslSocket *m_socket;
|
||||
PutWithServerClosingConnectionImmediatelyHandler(QSslSocket *s, QByteArray expected) :m_parsedHeaders(false), m_expectedData(expected), m_socket(s)
|
||||
{
|
||||
m_socket->setParent(this);
|
||||
connect(m_socket, SIGNAL(readyRead()), SLOT(readyReadSlot()));
|
||||
connect(m_socket, SIGNAL(disconnected()), SLOT(disconnectedSlot()));
|
||||
}
|
||||
signals:
|
||||
void correctFileUploadReceived();
|
||||
void corruptFileUploadReceived();
|
||||
|
||||
public slots:
|
||||
void closeDelayed() {
|
||||
m_socket->close();
|
||||
}
|
||||
|
||||
void readyReadSlot()
|
||||
{
|
||||
QByteArray data = m_socket->readAll();
|
||||
m_receivedData += data;
|
||||
if (!m_parsedHeaders && m_receivedData.contains("\r\n\r\n")) {
|
||||
m_parsedHeaders = true;
|
||||
QTimer::singleShot(qrand()%10, this, SLOT(closeDelayed())); // simulate random network latency
|
||||
// This server simulates a web server connection closing, e.g. because of Apaches MaxKeepAliveRequests or KeepAliveTimeout
|
||||
// In this case QNAM needs to re-send the upload data but it had a bug which then corrupts the upload
|
||||
// This test catches that.
|
||||
}
|
||||
|
||||
}
|
||||
void disconnectedSlot()
|
||||
{
|
||||
if (m_parsedHeaders) {
|
||||
//qDebug() << m_receivedData.left(m_receivedData.indexOf("\r\n\r\n"));
|
||||
m_receivedData = m_receivedData.mid(m_receivedData.indexOf("\r\n\r\n")+4); // check only actual data
|
||||
}
|
||||
if (m_receivedData.length() > 0 && !m_expectedData.startsWith(m_receivedData)) {
|
||||
// We had received some data but it is corrupt!
|
||||
qDebug() << "CORRUPT" << m_receivedData.count();
|
||||
|
||||
// Use this to track down the pattern of the corruption and conclude the source
|
||||
// QFile a("/tmp/corrupt");
|
||||
// a.open(QIODevice::WriteOnly);
|
||||
// a.write(m_receivedData);
|
||||
// a.close();
|
||||
|
||||
// QFile b("/tmp/correct");
|
||||
// b.open(QIODevice::WriteOnly);
|
||||
// b.write(m_expectedData);
|
||||
// b.close();
|
||||
//exit(1);
|
||||
emit corruptFileUploadReceived();
|
||||
} else {
|
||||
emit correctFileUploadReceived();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class PutWithServerClosingConnectionImmediatelyServer: public SslServer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
int m_correctUploads;
|
||||
int m_corruptUploads;
|
||||
int m_repliesFinished;
|
||||
int m_expectedReplies;
|
||||
QByteArray m_expectedData;
|
||||
PutWithServerClosingConnectionImmediatelyServer() : SslServer(), m_correctUploads(0), m_corruptUploads(0), m_repliesFinished(0), m_expectedReplies(0)
|
||||
{
|
||||
QObject::connect(this, SIGNAL(newEncryptedConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*)));
|
||||
QObject::connect(this, SIGNAL(newPlainConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*)));
|
||||
}
|
||||
|
||||
public slots:
|
||||
void createHandlerForConnection(QSslSocket* s) {
|
||||
PutWithServerClosingConnectionImmediatelyHandler *handler = new PutWithServerClosingConnectionImmediatelyHandler(s, m_expectedData);
|
||||
handler->setParent(this);
|
||||
QObject::connect(handler, SIGNAL(correctFileUploadReceived()), this, SLOT(increaseCorrect()));
|
||||
QObject::connect(handler, SIGNAL(corruptFileUploadReceived()), this, SLOT(increaseCorrupt()));
|
||||
}
|
||||
void increaseCorrect() {
|
||||
m_correctUploads++;
|
||||
}
|
||||
void increaseCorrupt() {
|
||||
m_corruptUploads++;
|
||||
}
|
||||
void replyFinished() {
|
||||
m_repliesFinished++;
|
||||
if (m_repliesFinished == m_expectedReplies) {
|
||||
QTestEventLoop::instance().exitLoop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
void tst_QNetworkReply::putWithServerClosingConnectionImmediately()
|
||||
{
|
||||
const int numUploads = 40;
|
||||
qint64 wantedSize = 512*1024; // 512 kB
|
||||
QByteArray sourceFile;
|
||||
for (int i = 0; i < wantedSize; ++i) {
|
||||
sourceFile += (char)'a' +(i%26);
|
||||
}
|
||||
bool withSsl = false;
|
||||
|
||||
for (int s = 0; s <= 1; s++) {
|
||||
withSsl = (s == 1);
|
||||
// Test also needs to run several times because of 9c2ecf89
|
||||
for (int j = 0; j < 20; j++) {
|
||||
// emulate a minimal https server
|
||||
PutWithServerClosingConnectionImmediatelyServer server;
|
||||
server.m_ssl = withSsl;
|
||||
server.m_expectedData = sourceFile;
|
||||
server.m_expectedReplies = numUploads;
|
||||
server.listen(QHostAddress(QHostAddress::LocalHost), 0);
|
||||
|
||||
for (int i = 0; i < numUploads; i++) {
|
||||
// create the request
|
||||
QUrl url = QUrl(QString("http%1://127.0.0.1:%2/file=%3").arg(withSsl ? "s" : "").arg(server.serverPort()).arg(i));
|
||||
QNetworkRequest request(url);
|
||||
QNetworkReply *reply = manager.put(request, sourceFile);
|
||||
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply, SLOT(ignoreSslErrors()));
|
||||
connect(reply, SIGNAL(finished()), &server, SLOT(replyFinished()));
|
||||
reply->setParent(&server);
|
||||
}
|
||||
|
||||
// get the request started and the incoming socket connected
|
||||
QTestEventLoop::instance().enterLoop(10);
|
||||
|
||||
//qDebug() << "correct=" << server.m_correctUploads << "corrupt=" << server.m_corruptUploads << "expected=" <<numUploads;
|
||||
|
||||
// Sanity check because ecause of 9c2ecf89 most replies will error out but we want to make sure at least some of them worked
|
||||
QVERIFY(server.m_correctUploads > 5);
|
||||
// Because actually important is that we don't get any corruption:
|
||||
QCOMPARE(server.m_corruptUploads, 0);
|
||||
|
||||
server.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// NOTE: This test must be last testcase in tst_qnetworkreply!
|
||||
void tst_QNetworkReply::parentingRepliesToTheApp()
|
||||
|
2
tests/auto/widgets/widgets/qmenu/BLACKLIST
Normal file
@ -0,0 +1,2 @@
|
||||
[task258920_mouseBorder]
|
||||
osx
|
@ -1696,7 +1696,7 @@ void Configure::applySpecSpecifics()
|
||||
dictionary[ "LARGE_FILE" ] = "no";
|
||||
dictionary[ "ANGLE" ] = "no";
|
||||
dictionary[ "DYNAMICGL" ] = "no";
|
||||
dictionary[ "REDUCE_RELOCATIONS" ] = "yes";
|
||||
dictionary[ "REDUCE_RELOCATIONS" ] = "no";
|
||||
dictionary[ "QT_GETIFADDRS" ] = "no";
|
||||
dictionary[ "QT_XKBCOMMON" ] = "no";
|
||||
dictionary["ANDROID_STYLE_ASSETS"] = "yes";
|
||||
|