summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2015-05-04 13:05:26 +0200
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2015-05-04 13:05:40 +0200
commit98cf120f5e1803867ab8065778d8dec3f26ad2e4 (patch)
tree80e6ca98ab4415d88209a4f82890535e20a9805a /src
parent4db5d3ccd17d448b59db491e2f261892f31fec74 (diff)
parent1f281bfd63402b50f3db378a027da26ca52ffb27 (diff)
Merge remote-tracking branch 'origin/5.4.2' into 5.4
Diffstat (limited to 'src')
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java4
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java2
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp18
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h4
-rw-r--r--src/gui/image/qjpeghandler.cpp150
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp35
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h2
-rw-r--r--src/network/access/qhttpprotocolhandler.cpp7
-rw-r--r--src/network/access/qhttpthreaddelegate_p.h36
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp25
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h7
-rw-r--r--src/widgets/itemviews/qabstractitemview_p.h14
12 files changed, 128 insertions, 176 deletions
diff --git a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
index a8583cde17..79722183bf 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
@@ -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);
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
index 75f10ad3ba..a790e0ef6f 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
@@ -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 {
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
index 11510a8397..760ca3d933 100644
--- a/src/corelib/io/qnoncontiguousbytedevice.cpp
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -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;
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
index c05ae11b0f..4d7b7b043e 100644
--- a/src/corelib/io/qnoncontiguousbytedevice_p.h
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -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;
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
index 9cf9947b6c..14c8b4c0f4 100644
--- a/src/gui/image/qjpeghandler.cpp
+++ b/src/gui/image/qjpeghandler.cpp
@@ -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;
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 9f63280bf8..49c6793b1f 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -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,
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 692c0e6a94..231fe11135 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -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
diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp
index 28e10f751e..3357948519 100644
--- a/src/network/access/qhttpprotocolhandler.cpp
+++ b/src/network/access/qhttpprotocolhandler.cpp
@@ -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
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index 16610828cb..b553409391 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -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);
};
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 4ce7303dbb..974a101e9c 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -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()
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 77d9c5a368..1940922f6e 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -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();
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h
index c3bd1fb504..be5d4b7b71 100644
--- a/src/widgets/itemviews/qabstractitemview_p.h
+++ b/src/widgets/itemviews/qabstractitemview_p.h
@@ -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);
}