Merge "Merge remote-tracking branch 'origin/5.4' into merge5.5" into refs/staging/5.5
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
|
@ -43,7 +43,7 @@ QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -g
|
|||||||
QMAKE_CFLAGS_DEBUG += -g
|
QMAKE_CFLAGS_DEBUG += -g
|
||||||
QMAKE_CFLAGS_SHLIB += -fPIC
|
QMAKE_CFLAGS_SHLIB += -fPIC
|
||||||
QMAKE_CFLAGS_STATIC_LIB += -fPIC
|
QMAKE_CFLAGS_STATIC_LIB += -fPIC
|
||||||
QMAKE_CFLAGS_APP += -fPIE
|
QMAKE_CFLAGS_APP += -fPIC
|
||||||
QMAKE_CFLAGS_ISYSTEM = -isystem
|
QMAKE_CFLAGS_ISYSTEM = -isystem
|
||||||
QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses
|
QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses
|
||||||
QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden
|
QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden
|
||||||
|
@ -23,7 +23,7 @@ QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -g
|
|||||||
QMAKE_CFLAGS_DEBUG += -g
|
QMAKE_CFLAGS_DEBUG += -g
|
||||||
QMAKE_CFLAGS_SHLIB += -fPIC -shared
|
QMAKE_CFLAGS_SHLIB += -fPIC -shared
|
||||||
QMAKE_CFLAGS_STATIC_LIB += -fPIC
|
QMAKE_CFLAGS_STATIC_LIB += -fPIC
|
||||||
QMAKE_CFLAGS_APP += -fPIE
|
QMAKE_CFLAGS_APP += -fPIC
|
||||||
QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses
|
QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses
|
||||||
QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden
|
QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden
|
||||||
QMAKE_CFLAGS_SSE2 += -msse2
|
QMAKE_CFLAGS_SSE2 += -msse2
|
||||||
|
@ -12,7 +12,7 @@ QMAKE_LEXFLAGS =
|
|||||||
QMAKE_YACC = yacc
|
QMAKE_YACC = yacc
|
||||||
QMAKE_YACCFLAGS = -d
|
QMAKE_YACCFLAGS = -d
|
||||||
QMAKE_CFLAGS =
|
QMAKE_CFLAGS =
|
||||||
QMAKE_CFLAGS_APP = -fPIE
|
QMAKE_CFLAGS_APP = -fPIC
|
||||||
QMAKE_CFLAGS_DEPS = -M
|
QMAKE_CFLAGS_DEPS = -M
|
||||||
QMAKE_CFLAGS_WARN_ON = -w1 -Wall -Wcheck -wd1572,873,2259,2261
|
QMAKE_CFLAGS_WARN_ON = -w1 -Wall -Wcheck -wd1572,873,2259,2261
|
||||||
QMAKE_CFLAGS_WARN_OFF = -w
|
QMAKE_CFLAGS_WARN_OFF = -w
|
||||||
|
@ -1092,7 +1092,9 @@ public class ExtractStyle {
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
InsetDrawable d = (InsetDrawable)drawable;
|
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();
|
Rect _padding = new Rect();
|
||||||
boolean hasPadding = d.getPadding(_padding);
|
boolean hasPadding = d.getPadding(_padding);
|
||||||
return getDrawable(getAccessibleField(mInsetStateObject.getClass(), "mDrawable").get(mInsetStateObject), filename, hasPadding ? _padding : null);
|
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_THEMES = new String[] {"Theme_Light"};
|
||||||
QT_ANDROID_DEFAULT_THEME = "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_THEMES = new String[] {"Theme_Holo_Light"};
|
||||||
QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light";
|
QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light";
|
||||||
} else {
|
} else {
|
||||||
|
@ -71,7 +71,7 @@ set(_qt5_corelib_extra_includes)
|
|||||||
# macro to add it.
|
# macro to add it.
|
||||||
set(Qt5_POSITION_INDEPENDENT_CODE True)
|
set(Qt5_POSITION_INDEPENDENT_CODE True)
|
||||||
set_property(TARGET Qt5::Core PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\")
|
set_property(TARGET Qt5::Core PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\")
|
||||||
set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIE\")
|
set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIC\")
|
||||||
|
|
||||||
!!IF !isEmpty(QT_NAMESPACE)
|
!!IF !isEmpty(QT_NAMESPACE)
|
||||||
list(APPEND Qt5Core_DEFINITIONS -DQT_NAMESPACE=$$QT_NAMESPACE)
|
list(APPEND Qt5Core_DEFINITIONS -DQT_NAMESPACE=$$QT_NAMESPACE)
|
||||||
|
@ -1062,9 +1062,9 @@ Q_CORE_EXPORT int qrand();
|
|||||||
|
|
||||||
#define QT_MODULE(x)
|
#define QT_MODULE(x)
|
||||||
|
|
||||||
#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && !defined(__PIC__) && !defined(__PIE__)
|
#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && !defined(__PIC__)
|
||||||
# error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\
|
# error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\
|
||||||
"Compile your code with -fPIC or -fPIE."
|
"Compile your code with -fPIC."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace QtPrivate {
|
namespace QtPrivate {
|
||||||
|
@ -185,11 +185,11 @@ bool QLockFilePrivate::isApparentlyStale() const
|
|||||||
{
|
{
|
||||||
qint64 pid;
|
qint64 pid;
|
||||||
QString hostname, appname;
|
QString hostname, appname;
|
||||||
if (!getLockInfo(&pid, &hostname, &appname))
|
if (getLockInfo(&pid, &hostname, &appname)) {
|
||||||
return false;
|
if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
|
||||||
if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
|
if (::kill(pid, 0) == -1 && errno == ESRCH)
|
||||||
if (::kill(pid, 0) == -1 && errno == ESRCH)
|
return true; // PID doesn't exist anymore
|
||||||
return true; // PID doesn't exist anymore
|
}
|
||||||
}
|
}
|
||||||
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
||||||
return staleLockTime > 0 && age > staleLockTime;
|
return staleLockTime > 0 && age > staleLockTime;
|
||||||
|
@ -126,21 +126,21 @@ bool QLockFilePrivate::isApparentlyStale() const
|
|||||||
{
|
{
|
||||||
qint64 pid;
|
qint64 pid;
|
||||||
QString hostname, appname;
|
QString hostname, appname;
|
||||||
if (!getLockInfo(&pid, &hostname, &appname))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// On WinRT there seems to be no way of obtaining information about other
|
// On WinRT there seems to be no way of obtaining information about other
|
||||||
// processes due to sandboxing
|
// processes due to sandboxing
|
||||||
#ifndef Q_OS_WINRT
|
#ifndef Q_OS_WINRT
|
||||||
if (hostname == QString::fromLocal8Bit(localHostName())) {
|
if (getLockInfo(&pid, &hostname, &appname)) {
|
||||||
HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
if (hostname == QString::fromLocal8Bit(localHostName())) {
|
||||||
if (!procHandle)
|
HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||||
return true;
|
if (!procHandle)
|
||||||
// We got a handle but check if process is still alive
|
return true;
|
||||||
DWORD dwR = ::WaitForSingleObject(procHandle, 0);
|
// We got a handle but check if process is still alive
|
||||||
::CloseHandle(procHandle);
|
DWORD dwR = ::WaitForSingleObject(procHandle, 0);
|
||||||
if (dwR == WAIT_TIMEOUT)
|
::CloseHandle(procHandle);
|
||||||
return true;
|
if (dwR == WAIT_TIMEOUT)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // !Q_OS_WINRT
|
#endif // !Q_OS_WINRT
|
||||||
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
||||||
|
@ -216,6 +216,11 @@ qint64 QNonContiguousByteDeviceByteArrayImpl::size()
|
|||||||
return byteArray->size();
|
return byteArray->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint64 QNonContiguousByteDeviceByteArrayImpl::pos()
|
||||||
|
{
|
||||||
|
return currentPosition;
|
||||||
|
}
|
||||||
|
|
||||||
QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QSharedPointer<QRingBuffer> rb)
|
QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QSharedPointer<QRingBuffer> rb)
|
||||||
: QNonContiguousByteDevice(), currentPosition(0)
|
: QNonContiguousByteDevice(), currentPosition(0)
|
||||||
{
|
{
|
||||||
@ -253,6 +258,11 @@ bool QNonContiguousByteDeviceRingBufferImpl::atEnd()
|
|||||||
return currentPosition >= size();
|
return currentPosition >= size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint64 QNonContiguousByteDeviceRingBufferImpl::pos()
|
||||||
|
{
|
||||||
|
return currentPosition;
|
||||||
|
}
|
||||||
|
|
||||||
bool QNonContiguousByteDeviceRingBufferImpl::reset()
|
bool QNonContiguousByteDeviceRingBufferImpl::reset()
|
||||||
{
|
{
|
||||||
currentPosition = 0;
|
currentPosition = 0;
|
||||||
@ -381,6 +391,14 @@ qint64 QNonContiguousByteDeviceIoDeviceImpl::size()
|
|||||||
return device->size() - initialPosition;
|
return device->size() - initialPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint64 QNonContiguousByteDeviceIoDeviceImpl::pos()
|
||||||
|
{
|
||||||
|
if (device->isSequential())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return device->pos();
|
||||||
|
}
|
||||||
|
|
||||||
QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0)
|
QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0)
|
||||||
{
|
{
|
||||||
byteDevice = bd;
|
byteDevice = bd;
|
||||||
|
@ -61,6 +61,7 @@ public:
|
|||||||
virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0;
|
virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0;
|
||||||
virtual bool advanceReadPointer(qint64 amount) = 0;
|
virtual bool advanceReadPointer(qint64 amount) = 0;
|
||||||
virtual bool atEnd() = 0;
|
virtual bool atEnd() = 0;
|
||||||
|
virtual qint64 pos() { return -1; }
|
||||||
virtual bool reset() = 0;
|
virtual bool reset() = 0;
|
||||||
virtual qint64 size() = 0;
|
virtual qint64 size() = 0;
|
||||||
|
|
||||||
@ -103,6 +104,7 @@ public:
|
|||||||
bool atEnd() Q_DECL_OVERRIDE;
|
bool atEnd() Q_DECL_OVERRIDE;
|
||||||
bool reset() Q_DECL_OVERRIDE;
|
bool reset() Q_DECL_OVERRIDE;
|
||||||
qint64 size() Q_DECL_OVERRIDE;
|
qint64 size() Q_DECL_OVERRIDE;
|
||||||
|
qint64 pos() Q_DECL_OVERRIDE;
|
||||||
protected:
|
protected:
|
||||||
QByteArray* byteArray;
|
QByteArray* byteArray;
|
||||||
qint64 currentPosition;
|
qint64 currentPosition;
|
||||||
@ -118,6 +120,7 @@ public:
|
|||||||
bool atEnd() Q_DECL_OVERRIDE;
|
bool atEnd() Q_DECL_OVERRIDE;
|
||||||
bool reset() Q_DECL_OVERRIDE;
|
bool reset() Q_DECL_OVERRIDE;
|
||||||
qint64 size() Q_DECL_OVERRIDE;
|
qint64 size() Q_DECL_OVERRIDE;
|
||||||
|
qint64 pos() Q_DECL_OVERRIDE;
|
||||||
protected:
|
protected:
|
||||||
QSharedPointer<QRingBuffer> ringBuffer;
|
QSharedPointer<QRingBuffer> ringBuffer;
|
||||||
qint64 currentPosition;
|
qint64 currentPosition;
|
||||||
@ -135,6 +138,7 @@ public:
|
|||||||
bool atEnd() Q_DECL_OVERRIDE;
|
bool atEnd() Q_DECL_OVERRIDE;
|
||||||
bool reset() Q_DECL_OVERRIDE;
|
bool reset() Q_DECL_OVERRIDE;
|
||||||
qint64 size() Q_DECL_OVERRIDE;
|
qint64 size() Q_DECL_OVERRIDE;
|
||||||
|
qint64 pos() Q_DECL_OVERRIDE;
|
||||||
protected:
|
protected:
|
||||||
QIODevice* device;
|
QIODevice* device;
|
||||||
QByteArray* currentReadBuffer;
|
QByteArray* currentReadBuffer;
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
#include <qdebug.h>
|
#include <qdebug.h>
|
||||||
#include <qelapsedtimer.h>
|
#include <qelapsedtimer.h>
|
||||||
#include <qeventloop.h>
|
#include <qeventloop.h>
|
||||||
#include <qtimer.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -45,13 +44,11 @@ QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
|
|||||||
handle(INVALID_HANDLE_VALUE),
|
handle(INVALID_HANDLE_VALUE),
|
||||||
readBufferMaxSize(0),
|
readBufferMaxSize(0),
|
||||||
actualReadBufferSize(0),
|
actualReadBufferSize(0),
|
||||||
|
stopped(true),
|
||||||
readSequenceStarted(false),
|
readSequenceStarted(false),
|
||||||
emitReadyReadTimer(new QTimer(this)),
|
|
||||||
pipeBroken(false),
|
pipeBroken(false),
|
||||||
readyReadEmitted(false)
|
readyReadEmitted(false)
|
||||||
{
|
{
|
||||||
emitReadyReadTimer->setSingleShot(true);
|
|
||||||
connect(emitReadyReadTimer, SIGNAL(timeout()), SIGNAL(readyRead()));
|
|
||||||
dataReadNotifier = new QWinOverlappedIoNotifier(this);
|
dataReadNotifier = new QWinOverlappedIoNotifier(this);
|
||||||
connect(dataReadNotifier, &QWinOverlappedIoNotifier::notified, this, &QWindowsPipeReader::notified);
|
connect(dataReadNotifier, &QWinOverlappedIoNotifier::notified, this, &QWindowsPipeReader::notified);
|
||||||
}
|
}
|
||||||
@ -73,12 +70,7 @@ static bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped)
|
|||||||
|
|
||||||
QWindowsPipeReader::~QWindowsPipeReader()
|
QWindowsPipeReader::~QWindowsPipeReader()
|
||||||
{
|
{
|
||||||
if (readSequenceStarted) {
|
stop();
|
||||||
if (qt_cancelIo(handle, &overlapped))
|
|
||||||
dataReadNotifier->waitForNotified(-1, &overlapped);
|
|
||||||
else
|
|
||||||
qErrnoWarning("QWindowsPipeReader: qt_cancelIo on handle %x failed.", handle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -89,9 +81,9 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
|
|||||||
readBuffer.clear();
|
readBuffer.clear();
|
||||||
actualReadBufferSize = 0;
|
actualReadBufferSize = 0;
|
||||||
handle = hPipeReadEnd;
|
handle = hPipeReadEnd;
|
||||||
ZeroMemory(&overlapped, sizeof(overlapped));
|
|
||||||
pipeBroken = false;
|
pipeBroken = false;
|
||||||
readyReadEmitted = false;
|
readyReadEmitted = false;
|
||||||
|
stopped = false;
|
||||||
if (hPipeReadEnd != INVALID_HANDLE_VALUE) {
|
if (hPipeReadEnd != INVALID_HANDLE_VALUE) {
|
||||||
dataReadNotifier->setHandle(hPipeReadEnd);
|
dataReadNotifier->setHandle(hPipeReadEnd);
|
||||||
dataReadNotifier->setEnabled(true);
|
dataReadNotifier->setEnabled(true);
|
||||||
@ -100,13 +92,24 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
Stops the asynchronous read sequence.
|
Stops the asynchronous read sequence.
|
||||||
This function assumes that the file already has been closed.
|
If the read sequence is running then the I/O operation is canceled.
|
||||||
It does not cancel any I/O operation.
|
|
||||||
*/
|
*/
|
||||||
void QWindowsPipeReader::stop()
|
void QWindowsPipeReader::stop()
|
||||||
{
|
{
|
||||||
dataReadNotifier->setEnabled(false);
|
stopped = true;
|
||||||
|
if (readSequenceStarted) {
|
||||||
|
if (qt_cancelIo(handle, &overlapped)) {
|
||||||
|
dataReadNotifier->waitForNotified(-1, &overlapped);
|
||||||
|
} else {
|
||||||
|
const DWORD dwError = GetLastError();
|
||||||
|
if (dwError != ERROR_NOT_FOUND) {
|
||||||
|
qErrnoWarning(dwError, "QWindowsPipeReader: qt_cancelIo on handle %x failed.",
|
||||||
|
handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
readSequenceStarted = false;
|
readSequenceStarted = false;
|
||||||
|
dataReadNotifier->setEnabled(false);
|
||||||
handle = INVALID_HANDLE_VALUE;
|
handle = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +122,7 @@ qint64 QWindowsPipeReader::bytesAvailable() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Stops the asynchronous read sequence.
|
Copies at most \c{maxlen} bytes from the internal read buffer to \c{data}.
|
||||||
*/
|
*/
|
||||||
qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
|
qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
|
||||||
{
|
{
|
||||||
@ -147,9 +150,7 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!pipeBroken) {
|
if (!pipeBroken) {
|
||||||
if (!actualReadBufferSize)
|
if (!readSequenceStarted && !stopped)
|
||||||
emitReadyReadTimer->stop();
|
|
||||||
if (!readSequenceStarted)
|
|
||||||
startAsyncRead();
|
startAsyncRead();
|
||||||
if (readSoFar == 0)
|
if (readSoFar == 0)
|
||||||
return -2; // signal EWOULDBLOCK
|
return -2; // signal EWOULDBLOCK
|
||||||
@ -172,13 +173,41 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
|
|||||||
{
|
{
|
||||||
if (&overlapped != notifiedOverlapped)
|
if (&overlapped != notifiedOverlapped)
|
||||||
return;
|
return;
|
||||||
if (!completeAsyncRead(numberOfBytesRead, errorCode)) {
|
|
||||||
|
switch (errorCode) {
|
||||||
|
case ERROR_SUCCESS:
|
||||||
|
break;
|
||||||
|
case ERROR_MORE_DATA:
|
||||||
|
// This is not an error. We're connected to a message mode
|
||||||
|
// pipe and the message didn't fit into the pipe's system
|
||||||
|
// buffer. We will read the remaining data in the next call.
|
||||||
|
break;
|
||||||
|
case ERROR_BROKEN_PIPE:
|
||||||
|
case ERROR_PIPE_NOT_CONNECTED:
|
||||||
pipeBroken = true;
|
pipeBroken = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead"));
|
||||||
|
pipeBroken = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
readSequenceStarted = false;
|
||||||
|
|
||||||
|
// After the reader was stopped, the only reason why this function can be called is the
|
||||||
|
// completion of a cancellation. No signals should be emitted, and no new read sequence should
|
||||||
|
// be started in this case.
|
||||||
|
if (stopped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pipeBroken) {
|
||||||
emit pipeClosed();
|
emit pipeClosed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actualReadBufferSize += numberOfBytesRead;
|
||||||
|
readBuffer.truncate(actualReadBufferSize);
|
||||||
startAsyncRead();
|
startAsyncRead();
|
||||||
emitReadyReadTimer->stop();
|
|
||||||
readyReadEmitted = true;
|
readyReadEmitted = true;
|
||||||
emit readyRead();
|
emit readyRead();
|
||||||
}
|
}
|
||||||
@ -206,6 +235,7 @@ void QWindowsPipeReader::startAsyncRead()
|
|||||||
char *ptr = readBuffer.reserve(bytesToRead);
|
char *ptr = readBuffer.reserve(bytesToRead);
|
||||||
|
|
||||||
readSequenceStarted = true;
|
readSequenceStarted = true;
|
||||||
|
ZeroMemory(&overlapped, sizeof(overlapped));
|
||||||
if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
|
if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
|
||||||
// We get notified by the QWinOverlappedIoNotifier - even in the synchronous case.
|
// We get notified by the QWinOverlappedIoNotifier - even in the synchronous case.
|
||||||
return;
|
return;
|
||||||
@ -239,38 +269,6 @@ void QWindowsPipeReader::startAsyncRead()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
\internal
|
|
||||||
Sets the correct size of the read buffer after a read operation.
|
|
||||||
Returns \c false, if an error occurred or the connection dropped.
|
|
||||||
*/
|
|
||||||
bool QWindowsPipeReader::completeAsyncRead(DWORD bytesRead, DWORD errorCode)
|
|
||||||
{
|
|
||||||
readSequenceStarted = false;
|
|
||||||
|
|
||||||
switch (errorCode) {
|
|
||||||
case ERROR_SUCCESS:
|
|
||||||
break;
|
|
||||||
case ERROR_MORE_DATA:
|
|
||||||
// This is not an error. We're connected to a message mode
|
|
||||||
// pipe and the message didn't fit into the pipe's system
|
|
||||||
// buffer. We will read the remaining data in the next call.
|
|
||||||
break;
|
|
||||||
case ERROR_BROKEN_PIPE:
|
|
||||||
case ERROR_PIPE_NOT_CONNECTED:
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
actualReadBufferSize += bytesRead;
|
|
||||||
readBuffer.truncate(actualReadBufferSize);
|
|
||||||
if (!emitReadyReadTimer->isActive())
|
|
||||||
emitReadyReadTimer->start();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
Returns the number of available bytes in the pipe.
|
Returns the number of available bytes in the pipe.
|
||||||
|
@ -47,7 +47,6 @@
|
|||||||
|
|
||||||
#include <qbytearray.h>
|
#include <qbytearray.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qtimer.h>
|
|
||||||
#include <private/qringbuffer_p.h>
|
#include <private/qringbuffer_p.h>
|
||||||
|
|
||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
@ -89,7 +88,6 @@ private Q_SLOTS:
|
|||||||
void notified(quint32 numberOfBytesRead, quint32 errorCode, OVERLAPPED *notifiedOverlapped);
|
void notified(quint32 numberOfBytesRead, quint32 errorCode, OVERLAPPED *notifiedOverlapped);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool completeAsyncRead(DWORD bytesRead, DWORD errorCode);
|
|
||||||
DWORD checkPipeState();
|
DWORD checkPipeState();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -99,8 +97,8 @@ private:
|
|||||||
qint64 readBufferMaxSize;
|
qint64 readBufferMaxSize;
|
||||||
QRingBuffer readBuffer;
|
QRingBuffer readBuffer;
|
||||||
int actualReadBufferSize;
|
int actualReadBufferSize;
|
||||||
|
bool stopped;
|
||||||
bool readSequenceStarted;
|
bool readSequenceStarted;
|
||||||
QTimer *emitReadyReadTimer;
|
|
||||||
bool pipeBroken;
|
bool pipeBroken;
|
||||||
bool readyReadEmitted;
|
bool readyReadEmitted;
|
||||||
};
|
};
|
||||||
|
@ -714,7 +714,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
QJpegHandlerPrivate(QJpegHandler *qq)
|
QJpegHandlerPrivate(QJpegHandler *qq)
|
||||||
: quality(75), exifOrientation(1), iod_src(0),
|
: quality(75), iod_src(0),
|
||||||
rgb888ToRgb32ConverterPtr(qt_convert_rgb888_to_rgb32), state(Ready), optimize(false), progressive(false), q(qq)
|
rgb888ToRgb32ConverterPtr(qt_convert_rgb888_to_rgb32), state(Ready), optimize(false), progressive(false), q(qq)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -730,10 +730,8 @@ public:
|
|||||||
|
|
||||||
bool readJpegHeader(QIODevice*);
|
bool readJpegHeader(QIODevice*);
|
||||||
bool read(QImage *image);
|
bool read(QImage *image);
|
||||||
void applyExifOrientation(QImage *image);
|
|
||||||
|
|
||||||
int quality;
|
int quality;
|
||||||
int exifOrientation;
|
|
||||||
QVariant size;
|
QVariant size;
|
||||||
QImage::Format format;
|
QImage::Format format;
|
||||||
QSize scaledSize;
|
QSize scaledSize;
|
||||||
@ -756,97 +754,6 @@ public:
|
|||||||
QJpegHandler *q;
|
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
|
\internal
|
||||||
*/
|
*/
|
||||||
@ -866,7 +773,6 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
|||||||
|
|
||||||
if (!setjmp(err.setjmp_buffer)) {
|
if (!setjmp(err.setjmp_buffer)) {
|
||||||
jpeg_save_markers(&info, JPEG_COM, 0xFFFF);
|
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);
|
(void) jpeg_read_header(&info, TRUE);
|
||||||
|
|
||||||
@ -878,8 +784,6 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
|||||||
format = QImage::Format_Invalid;
|
format = QImage::Format_Invalid;
|
||||||
read_jpeg_format(format, &info);
|
read_jpeg_format(format, &info);
|
||||||
|
|
||||||
QByteArray exifData;
|
|
||||||
|
|
||||||
for (jpeg_saved_marker_ptr marker = info.marker_list; marker != NULL; marker = marker->next) {
|
for (jpeg_saved_marker_ptr marker = info.marker_list; marker != NULL; marker = marker->next) {
|
||||||
if (marker->marker == JPEG_COM) {
|
if (marker->marker == JPEG_COM) {
|
||||||
QString key, value;
|
QString key, value;
|
||||||
@ -897,18 +801,9 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
|||||||
description += key + QLatin1String(": ") + value.simplified();
|
description += key + QLatin1String(": ") + value.simplified();
|
||||||
readTexts.append(key);
|
readTexts.append(key);
|
||||||
readTexts.append(value);
|
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;
|
state = ReadHeader;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -922,48 +817,6 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
|||||||
return true;
|
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)
|
bool QJpegHandlerPrivate::read(QImage *image)
|
||||||
{
|
{
|
||||||
if(state == Ready)
|
if(state == Ready)
|
||||||
@ -975,7 +828,6 @@ bool QJpegHandlerPrivate::read(QImage *image)
|
|||||||
if (success) {
|
if (success) {
|
||||||
for (int i = 0; i < readTexts.size()-1; i+=2)
|
for (int i = 0; i < readTexts.size()-1; i+=2)
|
||||||
image->setText(readTexts.at(i), readTexts.at(i+1));
|
image->setText(readTexts.at(i), readTexts.at(i+1));
|
||||||
applyExifOrientation(image);
|
|
||||||
|
|
||||||
state = Ready;
|
state = Ready;
|
||||||
return true;
|
return true;
|
||||||
|
@ -106,15 +106,19 @@ void QHttpNetworkConnectionChannel::init()
|
|||||||
socket->setProxy(QNetworkProxy::NoProxy);
|
socket->setProxy(QNetworkProxy::NoProxy);
|
||||||
#endif
|
#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)),
|
QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
|
||||||
this, SLOT(_q_bytesWritten(qint64)),
|
this, SLOT(_q_bytesWritten(qint64)),
|
||||||
Qt::DirectConnection);
|
Qt::QueuedConnection);
|
||||||
QObject::connect(socket, SIGNAL(connected()),
|
QObject::connect(socket, SIGNAL(connected()),
|
||||||
this, SLOT(_q_connected()),
|
this, SLOT(_q_connected()),
|
||||||
Qt::DirectConnection);
|
Qt::QueuedConnection);
|
||||||
QObject::connect(socket, SIGNAL(readyRead()),
|
QObject::connect(socket, SIGNAL(readyRead()),
|
||||||
this, SLOT(_q_readyRead()),
|
this, SLOT(_q_readyRead()),
|
||||||
Qt::DirectConnection);
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
// The disconnected() and error() signals may already come
|
// The disconnected() and error() signals may already come
|
||||||
// while calling connectToHost().
|
// while calling connectToHost().
|
||||||
@ -143,7 +147,7 @@ void QHttpNetworkConnectionChannel::init()
|
|||||||
// won't be a sslSocket if encrypt is false
|
// won't be a sslSocket if encrypt is false
|
||||||
QObject::connect(sslSocket, SIGNAL(encrypted()),
|
QObject::connect(sslSocket, SIGNAL(encrypted()),
|
||||||
this, SLOT(_q_encrypted()),
|
this, SLOT(_q_encrypted()),
|
||||||
Qt::DirectConnection);
|
Qt::QueuedConnection);
|
||||||
QObject::connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
|
QObject::connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
|
||||||
this, SLOT(_q_sslErrors(QList<QSslError>)),
|
this, SLOT(_q_sslErrors(QList<QSslError>)),
|
||||||
Qt::DirectConnection);
|
Qt::DirectConnection);
|
||||||
@ -152,7 +156,7 @@ void QHttpNetworkConnectionChannel::init()
|
|||||||
Qt::DirectConnection);
|
Qt::DirectConnection);
|
||||||
QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
|
QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
|
||||||
this, SLOT(_q_encryptedBytesWritten(qint64)),
|
this, SLOT(_q_encryptedBytesWritten(qint64)),
|
||||||
Qt::DirectConnection);
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
if (ignoreAllSslErrors)
|
if (ignoreAllSslErrors)
|
||||||
sslSocket->ignoreSslErrors();
|
sslSocket->ignoreSslErrors();
|
||||||
@ -189,8 +193,11 @@ void QHttpNetworkConnectionChannel::close()
|
|||||||
// pendingEncrypt must only be true in between connected and encrypted states
|
// pendingEncrypt must only be true in between connected and encrypted states
|
||||||
pendingEncrypt = false;
|
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();
|
socket->close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -356,6 +363,14 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
|
|||||||
}
|
}
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,6 +677,12 @@ bool QHttpNetworkConnectionChannel::isSocketReading() const
|
|||||||
void QHttpNetworkConnectionChannel::_q_bytesWritten(qint64 bytes)
|
void QHttpNetworkConnectionChannel::_q_bytesWritten(qint64 bytes)
|
||||||
{
|
{
|
||||||
Q_UNUSED(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 :)
|
// bytes have been written to the socket. write even more of them :)
|
||||||
if (isSocketWriting())
|
if (isSocketWriting())
|
||||||
sendRequest();
|
sendRequest();
|
||||||
@ -737,7 +758,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
|
|||||||
|
|
||||||
// ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again!
|
// ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again!
|
||||||
//channels[i].reconnectAttempts = 2;
|
//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
|
#ifndef QT_NO_SSL
|
||||||
if (connection->sslContext().isNull()) {
|
if (connection->sslContext().isNull()) {
|
||||||
// this socket is making the 1st handshake for this connection,
|
// this socket is making the 1st handshake for this connection,
|
||||||
|
@ -83,6 +83,8 @@ typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
|
|||||||
class QHttpNetworkConnectionChannel : public QObject {
|
class QHttpNetworkConnectionChannel : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
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 {
|
enum ChannelState {
|
||||||
IdleState = 0, // ready to send request
|
IdleState = 0, // ready to send request
|
||||||
ConnectingState = 1, // connecting to host
|
ConnectingState = 1, // connecting to host
|
||||||
|
@ -368,6 +368,13 @@ bool QHttpProtocolHandler::sendRequest()
|
|||||||
// nothing to read currently, break the loop
|
// nothing to read currently, break the loop
|
||||||
break;
|
break;
|
||||||
} else {
|
} 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);
|
qint64 currentWriteSize = m_socket->write(readPointer, currentReadSize);
|
||||||
if (currentWriteSize == -1 || currentWriteSize != currentReadSize) {
|
if (currentWriteSize == -1 || currentWriteSize != currentReadSize) {
|
||||||
// socket broke down
|
// socket broke down
|
||||||
|
@ -189,6 +189,7 @@ protected:
|
|||||||
QByteArray m_dataArray;
|
QByteArray m_dataArray;
|
||||||
bool m_atEnd;
|
bool m_atEnd;
|
||||||
qint64 m_size;
|
qint64 m_size;
|
||||||
|
qint64 m_pos; // to match calls of haveDataSlot with the expected position
|
||||||
public:
|
public:
|
||||||
QNonContiguousByteDeviceThreadForwardImpl(bool aE, qint64 s)
|
QNonContiguousByteDeviceThreadForwardImpl(bool aE, qint64 s)
|
||||||
: QNonContiguousByteDevice(),
|
: QNonContiguousByteDevice(),
|
||||||
@ -196,7 +197,8 @@ public:
|
|||||||
m_amount(0),
|
m_amount(0),
|
||||||
m_data(0),
|
m_data(0),
|
||||||
m_atEnd(aE),
|
m_atEnd(aE),
|
||||||
m_size(s)
|
m_size(s),
|
||||||
|
m_pos(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,6 +206,11 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint64 pos() Q_DECL_OVERRIDE
|
||||||
|
{
|
||||||
|
return m_pos;
|
||||||
|
}
|
||||||
|
|
||||||
const char* readPointer(qint64 maximumLength, qint64 &len) Q_DECL_OVERRIDE
|
const char* readPointer(qint64 maximumLength, qint64 &len) Q_DECL_OVERRIDE
|
||||||
{
|
{
|
||||||
if (m_amount > 0) {
|
if (m_amount > 0) {
|
||||||
@ -231,11 +238,10 @@ public:
|
|||||||
|
|
||||||
m_amount -= a;
|
m_amount -= a;
|
||||||
m_data += a;
|
m_data += a;
|
||||||
|
m_pos += a;
|
||||||
|
|
||||||
// To main thread to inform about our state
|
// To main thread to inform about our state. The m_pos will be sent as a sanity check.
|
||||||
emit processedData(a);
|
emit processedData(m_pos, a);
|
||||||
|
|
||||||
// FIXME possible optimization, already ask user thread for some data
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -252,10 +258,21 @@ public:
|
|||||||
{
|
{
|
||||||
m_amount = 0;
|
m_amount = 0;
|
||||||
m_data = 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
|
// Communicate as BlockingQueuedConnection
|
||||||
bool b = false;
|
bool b = false;
|
||||||
emit resetData(&b);
|
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;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,8 +283,13 @@ public:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
// From user thread:
|
// 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;
|
wantDataPending = false;
|
||||||
|
|
||||||
m_dataArray = dataArray;
|
m_dataArray = dataArray;
|
||||||
@ -287,7 +309,7 @@ signals:
|
|||||||
|
|
||||||
// to main thread:
|
// to main thread:
|
||||||
void wantData(qint64);
|
void wantData(qint64);
|
||||||
void processedData(qint64);
|
void processedData(qint64 pos, qint64 amount);
|
||||||
void resetData(bool *b);
|
void resetData(bool *b);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -424,6 +424,7 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate()
|
|||||||
, synchronous(false)
|
, synchronous(false)
|
||||||
, state(Idle)
|
, state(Idle)
|
||||||
, statusCode(0)
|
, statusCode(0)
|
||||||
|
, uploadByteDevicePosition(false)
|
||||||
, uploadDeviceChoking(false)
|
, uploadDeviceChoking(false)
|
||||||
, outgoingData(0)
|
, outgoingData(0)
|
||||||
, bytesUploaded(-1)
|
, bytesUploaded(-1)
|
||||||
@ -867,9 +868,9 @@ void QNetworkReplyHttpImplPrivate::postRequest()
|
|||||||
q, SLOT(uploadByteDeviceReadyReadSlot()),
|
q, SLOT(uploadByteDeviceReadyReadSlot()),
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
// From main thread to user thread:
|
// From user thread to http thread:
|
||||||
QObject::connect(q, SIGNAL(haveUploadData(QByteArray,bool,qint64)),
|
QObject::connect(q, SIGNAL(haveUploadData(qint64,QByteArray,bool,qint64)),
|
||||||
forwardUploadDevice, SLOT(haveDataSlot(QByteArray,bool,qint64)), Qt::QueuedConnection);
|
forwardUploadDevice, SLOT(haveDataSlot(qint64,QByteArray,bool,qint64)), Qt::QueuedConnection);
|
||||||
QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()),
|
QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()),
|
||||||
forwardUploadDevice, SIGNAL(readyRead()),
|
forwardUploadDevice, SIGNAL(readyRead()),
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
@ -877,8 +878,8 @@ void QNetworkReplyHttpImplPrivate::postRequest()
|
|||||||
// From http thread to user thread:
|
// From http thread to user thread:
|
||||||
QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)),
|
QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)),
|
||||||
q, SLOT(wantUploadDataSlot(qint64)));
|
q, SLOT(wantUploadDataSlot(qint64)));
|
||||||
QObject::connect(forwardUploadDevice, SIGNAL(processedData(qint64)),
|
QObject::connect(forwardUploadDevice,SIGNAL(processedData(qint64, qint64)),
|
||||||
q, SLOT(sentUploadDataSlot(qint64)));
|
q, SLOT(sentUploadDataSlot(qint64,qint64)));
|
||||||
QObject::connect(forwardUploadDevice, SIGNAL(resetData(bool*)),
|
QObject::connect(forwardUploadDevice, SIGNAL(resetData(bool*)),
|
||||||
q, SLOT(resetUploadDataSlot(bool*)),
|
q, SLOT(resetUploadDataSlot(bool*)),
|
||||||
Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued!
|
Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued!
|
||||||
@ -1278,12 +1279,22 @@ void QNetworkReplyHttpImplPrivate::replyPreSharedKeyAuthenticationRequiredSlot(Q
|
|||||||
void QNetworkReplyHttpImplPrivate::resetUploadDataSlot(bool *r)
|
void QNetworkReplyHttpImplPrivate::resetUploadDataSlot(bool *r)
|
||||||
{
|
{
|
||||||
*r = uploadByteDevice->reset();
|
*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
|
// 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, QString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
uploadByteDevice->advanceReadPointer(amount);
|
uploadByteDevice->advanceReadPointer(amount);
|
||||||
|
uploadByteDevicePosition += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
|
// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
|
||||||
@ -1308,7 +1319,7 @@ void QNetworkReplyHttpImplPrivate::wantUploadDataSlot(qint64 maxSize)
|
|||||||
QByteArray dataArray(data, currentUploadDataLength);
|
QByteArray dataArray(data, currentUploadDataLength);
|
||||||
|
|
||||||
// Communicate back to HTTP thread
|
// 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()
|
void QNetworkReplyHttpImplPrivate::uploadByteDeviceReadyReadSlot()
|
||||||
|
@ -121,7 +121,7 @@ public:
|
|||||||
|
|
||||||
Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r))
|
Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r))
|
||||||
Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
|
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 uploadByteDeviceReadyReadSlot())
|
||||||
Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
|
Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
|
||||||
Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
|
Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
|
||||||
@ -145,7 +145,7 @@ signals:
|
|||||||
|
|
||||||
void startHttpRequestSynchronously();
|
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
|
class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
|
||||||
@ -196,6 +196,7 @@ public:
|
|||||||
// upload
|
// upload
|
||||||
QNonContiguousByteDevice* createUploadByteDevice();
|
QNonContiguousByteDevice* createUploadByteDevice();
|
||||||
QSharedPointer<QNonContiguousByteDevice> uploadByteDevice;
|
QSharedPointer<QNonContiguousByteDevice> uploadByteDevice;
|
||||||
|
qint64 uploadByteDevicePosition;
|
||||||
bool uploadDeviceChoking; // if we couldn't readPointer() any data at the moment
|
bool uploadDeviceChoking; // if we couldn't readPointer() any data at the moment
|
||||||
QIODevice *outgoingData;
|
QIODevice *outgoingData;
|
||||||
QSharedPointer<QRingBuffer> outgoingDataBuffer;
|
QSharedPointer<QRingBuffer> outgoingDataBuffer;
|
||||||
@ -285,7 +286,7 @@ public:
|
|||||||
// From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread:
|
// From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread:
|
||||||
void resetUploadDataSlot(bool *r);
|
void resetUploadDataSlot(bool *r);
|
||||||
void wantUploadDataSlot(qint64);
|
void wantUploadDataSlot(qint64);
|
||||||
void sentUploadDataSlot(qint64);
|
void sentUploadDataSlot(qint64, qint64);
|
||||||
|
|
||||||
// From user's QNonContiguousByteDevice
|
// From user's QNonContiguousByteDevice
|
||||||
void uploadByteDeviceReadyReadSlot();
|
void uploadByteDeviceReadyReadSlot();
|
||||||
|
@ -688,8 +688,10 @@ void QCocoaWindow::setVisible(bool visible)
|
|||||||
&& [m_nsWindow isKindOfClass:[NSPanel class]]) {
|
&& [m_nsWindow isKindOfClass:[NSPanel class]]) {
|
||||||
[(NSPanel *)m_nsWindow setWorksWhenModal:YES];
|
[(NSPanel *)m_nsWindow setWorksWhenModal:YES];
|
||||||
if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) {
|
if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) {
|
||||||
monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDown handler:^(NSEvent *) {
|
monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) {
|
||||||
QWindowSystemInterface::handleMouseEvent(window(), QPointF(-1, -1), QPointF(window()->framePosition() - QPointF(1, 1)), Qt::LeftButton);
|
QPointF localPoint = qt_mac_flipPoint([NSEvent mouseLocation]);
|
||||||
|
QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint,
|
||||||
|
cocoaButton2QtButton([e buttonNumber]));
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,8 +168,20 @@ public:
|
|||||||
QModelIndex index;
|
QModelIndex index;
|
||||||
int col = -1;
|
int col = -1;
|
||||||
int row = -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)) {
|
if (dropOn(event, &row, &col, &index)) {
|
||||||
return model->canDropMimeData(event->mimeData(),
|
return model->canDropMimeData(mime,
|
||||||
dragDropMode == QAbstractItemView::InternalMove ? Qt::MoveAction : event->dropAction(),
|
dragDropMode == QAbstractItemView::InternalMove ? Qt::MoveAction : event->dropAction(),
|
||||||
row, col, index);
|
row, col, index);
|
||||||
}
|
}
|
||||||
|
@ -4273,15 +4273,16 @@ void QApplicationPrivate::cleanupMultitouch_sys()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *QApplicationPrivate::findClosestTouchPointTarget(QTouchDevice *device, const QPointF &screenPos)
|
QWidget *QApplicationPrivate::findClosestTouchPointTarget(QTouchDevice *device, const QTouchEvent::TouchPoint &touchPoint)
|
||||||
{
|
{
|
||||||
|
const QPointF screenPos = touchPoint.screenPos();
|
||||||
int closestTouchPointId = -1;
|
int closestTouchPointId = -1;
|
||||||
QObject *closestTarget = 0;
|
QObject *closestTarget = 0;
|
||||||
qreal closestDistance = qreal(0.);
|
qreal closestDistance = qreal(0.);
|
||||||
QHash<ActiveTouchPointsKey, ActiveTouchPointsValue>::const_iterator it = activeTouchPoints.constBegin(),
|
QHash<ActiveTouchPointsKey, ActiveTouchPointsValue>::const_iterator it = activeTouchPoints.constBegin(),
|
||||||
ite = activeTouchPoints.constEnd();
|
ite = activeTouchPoints.constEnd();
|
||||||
while (it != ite) {
|
while (it != ite) {
|
||||||
if (it.key().device == device) {
|
if (it.key().device == device && it.key().touchPointId != touchPoint.id()) {
|
||||||
const QTouchEvent::TouchPoint &touchPoint = it->touchPoint;
|
const QTouchEvent::TouchPoint &touchPoint = it->touchPoint;
|
||||||
qreal dx = screenPos.x() - touchPoint.screenPos().x();
|
qreal dx = screenPos.x() - touchPoint.screenPos().x();
|
||||||
qreal dy = screenPos.y() - touchPoint.screenPos().y();
|
qreal dy = screenPos.y() - touchPoint.screenPos().y();
|
||||||
@ -4337,7 +4338,7 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (device->type() == QTouchDevice::TouchScreen) {
|
if (device->type() == QTouchDevice::TouchScreen) {
|
||||||
QWidget *closestWidget = d->findClosestTouchPointTarget(device, touchPoint.screenPos());
|
QWidget *closestWidget = d->findClosestTouchPointTarget(device, touchPoint);
|
||||||
QWidget *widget = static_cast<QWidget *>(target.data());
|
QWidget *widget = static_cast<QWidget *>(target.data());
|
||||||
if (closestWidget
|
if (closestWidget
|
||||||
&& (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) {
|
&& (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) {
|
||||||
|
@ -280,7 +280,7 @@ public:
|
|||||||
void initializeMultitouch_sys();
|
void initializeMultitouch_sys();
|
||||||
void cleanupMultitouch();
|
void cleanupMultitouch();
|
||||||
void cleanupMultitouch_sys();
|
void cleanupMultitouch_sys();
|
||||||
QWidget *findClosestTouchPointTarget(QTouchDevice *device, const QPointF &screenPos);
|
QWidget *findClosestTouchPointTarget(QTouchDevice *device, const QTouchEvent::TouchPoint &touchPoint);
|
||||||
void appendTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
|
void appendTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
|
||||||
void removeTouchPoint(int touchPointId);
|
void removeTouchPoint(int touchPointId);
|
||||||
static bool translateRawTouchEvent(QWidget *widget,
|
static bool translateRawTouchEvent(QWidget *widget,
|
||||||
|
@ -897,7 +897,7 @@ void QToolButton::setDefaultAction(QAction *action)
|
|||||||
return;
|
return;
|
||||||
if (!actions().contains(action))
|
if (!actions().contains(action))
|
||||||
addAction(action);
|
addAction(action);
|
||||||
setText(action->iconText());
|
setText(action->text());
|
||||||
setIcon(action->icon());
|
setIcon(action->icon());
|
||||||
#ifndef QT_NO_TOOLTIP
|
#ifndef QT_NO_TOOLTIP
|
||||||
setToolTip(action->toolTip());
|
setToolTip(action->toolTip());
|
||||||
|
@ -62,6 +62,7 @@ private slots:
|
|||||||
void staleLockRace();
|
void staleLockRace();
|
||||||
void noPermissions();
|
void noPermissions();
|
||||||
void noPermissionsWindows();
|
void noPermissionsWindows();
|
||||||
|
void corruptedLockFile();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QString m_helperApp;
|
QString m_helperApp;
|
||||||
@ -480,5 +481,21 @@ void tst_QLockFile::noPermissionsWindows()
|
|||||||
QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError));
|
QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QLockFile::corruptedLockFile()
|
||||||
|
{
|
||||||
|
const QString fileName = dir.path() + "/corruptedLockFile";
|
||||||
|
|
||||||
|
{
|
||||||
|
// Create a empty file. Typically the result of a computer crash or hard disk full.
|
||||||
|
QFile file(fileName);
|
||||||
|
QVERIFY(file.open(QFile::WriteOnly));
|
||||||
|
}
|
||||||
|
|
||||||
|
QLockFile secondLock(fileName);
|
||||||
|
secondLock.setStaleLockTime(100);
|
||||||
|
QVERIFY(secondLock.tryLock(10000));
|
||||||
|
QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QLockFile)
|
QTEST_MAIN(tst_QLockFile)
|
||||||
#include "tst_qlockfile.moc"
|
#include "tst_qlockfile.moc"
|
||||||
|
@ -87,8 +87,19 @@ static void addFixedTypes()
|
|||||||
QTest::newRow("int64") << DBUS_TYPE_INT64_AS_STRING << true << true;
|
QTest::newRow("int64") << DBUS_TYPE_INT64_AS_STRING << true << true;
|
||||||
QTest::newRow("uint64") << DBUS_TYPE_UINT64_AS_STRING << true << true;
|
QTest::newRow("uint64") << DBUS_TYPE_UINT64_AS_STRING << true << true;
|
||||||
QTest::newRow("double") << DBUS_TYPE_DOUBLE_AS_STRING << true << true;
|
QTest::newRow("double") << DBUS_TYPE_DOUBLE_AS_STRING << true << true;
|
||||||
|
|
||||||
#ifdef DBUS_TYPE_UNIX_FD_AS_STRING
|
#ifdef DBUS_TYPE_UNIX_FD_AS_STRING
|
||||||
QTest::newRow("unixfd") << DBUS_TYPE_UNIX_FD_AS_STRING << true << true;
|
# ifndef QT_LINKED_LIBDBUS
|
||||||
|
// We have got the macro from dbus_minimal_p.h, so we need to check if
|
||||||
|
// the library recognizes this as valid type first.
|
||||||
|
// The following function was added for Unix FD support, so if it is
|
||||||
|
// present, so is support for Unix FDs.
|
||||||
|
bool supportsUnixFds = qdbus_resolve_conditionally("dbus_connection_can_send_type");
|
||||||
|
# else
|
||||||
|
bool supportsUnixFds = true;
|
||||||
|
# endif
|
||||||
|
if (supportsUnixFds)
|
||||||
|
QTest::newRow("unixfd") << DBUS_TYPE_UNIX_FD_AS_STRING << true << true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 |
@ -181,9 +181,6 @@ private slots:
|
|||||||
void invertPixelsRGB_data();
|
void invertPixelsRGB_data();
|
||||||
void invertPixelsRGB();
|
void invertPixelsRGB();
|
||||||
|
|
||||||
void exifOrientation_data();
|
|
||||||
void exifOrientation();
|
|
||||||
|
|
||||||
void cleanupFunctions();
|
void cleanupFunctions();
|
||||||
|
|
||||||
void devicePixelRatio();
|
void devicePixelRatio();
|
||||||
@ -2813,36 +2810,6 @@ void tst_QImage::invertPixelsRGB()
|
|||||||
QCOMPARE(qBlue(pixel) >> 4, (255 - 96) >> 4);
|
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)
|
static void cleanupFunction(void* info)
|
||||||
{
|
{
|
||||||
bool *called = static_cast<bool*>(info);
|
bool *called = static_cast<bool*>(info);
|
||||||
|
@ -456,6 +456,10 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
void putWithRateLimiting();
|
void putWithRateLimiting();
|
||||||
|
|
||||||
|
#ifndef QT_NO_SSL
|
||||||
|
void putWithServerClosingConnectionImmediately();
|
||||||
|
#endif
|
||||||
|
|
||||||
// NOTE: This test must be last!
|
// NOTE: This test must be last!
|
||||||
void parentingRepliesToTheApp();
|
void parentingRepliesToTheApp();
|
||||||
private:
|
private:
|
||||||
@ -4723,18 +4727,22 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag()
|
|||||||
class SslServer : public QTcpServer {
|
class SslServer : public QTcpServer {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SslServer() : socket(0) {};
|
SslServer() : socket(0), m_ssl(true) {}
|
||||||
void incomingConnection(qintptr socketDescriptor) {
|
void incomingConnection(qintptr socketDescriptor) {
|
||||||
QSslSocket *serverSocket = new QSslSocket;
|
QSslSocket *serverSocket = new QSslSocket;
|
||||||
serverSocket->setParent(this);
|
serverSocket->setParent(this);
|
||||||
|
|
||||||
if (serverSocket->setSocketDescriptor(socketDescriptor)) {
|
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();
|
QString testDataDir = QFileInfo(QFINDTESTDATA("rfc3252.txt")).absolutePath();
|
||||||
if (testDataDir.isEmpty())
|
if (testDataDir.isEmpty())
|
||||||
testDataDir = QCoreApplication::applicationDirPath();
|
testDataDir = QCoreApplication::applicationDirPath();
|
||||||
|
|
||||||
connect(serverSocket, SIGNAL(encrypted()), this, SLOT(encryptedSlot()));
|
connect(serverSocket, SIGNAL(encrypted()), this, SLOT(encryptedSlot()));
|
||||||
connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
|
|
||||||
serverSocket->setProtocol(QSsl::AnyProtocol);
|
serverSocket->setProtocol(QSsl::AnyProtocol);
|
||||||
connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), serverSocket, SLOT(ignoreSslErrors()));
|
connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), serverSocket, SLOT(ignoreSslErrors()));
|
||||||
serverSocket->setLocalCertificate(testDataDir + "/certs/server.pem");
|
serverSocket->setLocalCertificate(testDataDir + "/certs/server.pem");
|
||||||
@ -4745,11 +4753,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
signals:
|
signals:
|
||||||
void newEncryptedConnection();
|
void newEncryptedConnection(QSslSocket *s);
|
||||||
|
void newPlainConnection(QSslSocket *s);
|
||||||
public slots:
|
public slots:
|
||||||
void encryptedSlot() {
|
void encryptedSlot() {
|
||||||
socket = (QSslSocket*) sender();
|
socket = (QSslSocket*) sender();
|
||||||
emit newEncryptedConnection();
|
emit newEncryptedConnection(socket);
|
||||||
}
|
}
|
||||||
void readyReadSlot() {
|
void readyReadSlot() {
|
||||||
// for the incoming sockets, not the server socket
|
// for the incoming sockets, not the server socket
|
||||||
@ -4758,6 +4767,7 @@ public slots:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QSslSocket *socket;
|
QSslSocket *socket;
|
||||||
|
bool m_ssl;
|
||||||
};
|
};
|
||||||
|
|
||||||
// very similar to ioPostToHttpUploadProgress but for SSL
|
// very similar to ioPostToHttpUploadProgress but for SSL
|
||||||
@ -4785,7 +4795,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
|
|||||||
QNetworkReplyPtr reply(manager.post(request, sourceFile));
|
QNetworkReplyPtr reply(manager.post(request, sourceFile));
|
||||||
|
|
||||||
QSignalSpy spy(reply.data(), SIGNAL(uploadProgress(qint64,qint64)));
|
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()));
|
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply.data(), SLOT(ignoreSslErrors()));
|
||||||
|
|
||||||
// get the request started and the incoming socket connected
|
// get the request started and the incoming socket connected
|
||||||
@ -4793,7 +4803,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
|
|||||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||||
QTcpSocket *incomingSocket = server.socket;
|
QTcpSocket *incomingSocket = server.socket;
|
||||||
QVERIFY(incomingSocket);
|
QVERIFY(incomingSocket);
|
||||||
disconnect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
disconnect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||||
|
|
||||||
|
|
||||||
incomingSocket->setReadBufferSize(1*1024);
|
incomingSocket->setReadBufferSize(1*1024);
|
||||||
@ -7963,6 +7973,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!
|
// NOTE: This test must be last testcase in tst_qnetworkreply!
|
||||||
void tst_QNetworkReply::parentingRepliesToTheApp()
|
void tst_QNetworkReply::parentingRepliesToTheApp()
|
||||||
|
@ -680,7 +680,7 @@ void tst_Moc::oldStyleCasts()
|
|||||||
|
|
||||||
QStringList args;
|
QStringList args;
|
||||||
args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "."
|
args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "."
|
||||||
<< "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIE" << "-";
|
<< "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-";
|
||||||
proc.start("gcc", args);
|
proc.start("gcc", args);
|
||||||
QVERIFY(proc.waitForStarted());
|
QVERIFY(proc.waitForStarted());
|
||||||
proc.write(mocOut);
|
proc.write(mocOut);
|
||||||
@ -750,7 +750,7 @@ void tst_Moc::inputFileNameWithDotsButNoExtension()
|
|||||||
|
|
||||||
QStringList args;
|
QStringList args;
|
||||||
args << "-c" << "-x" << "c++" << "-I" << ".."
|
args << "-c" << "-x" << "c++" << "-I" << ".."
|
||||||
<< "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIE" << "-";
|
<< "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-";
|
||||||
proc.start("gcc", args);
|
proc.start("gcc", args);
|
||||||
QVERIFY(proc.waitForStarted());
|
QVERIFY(proc.waitForStarted());
|
||||||
proc.write(mocOut);
|
proc.write(mocOut);
|
||||||
@ -1029,7 +1029,7 @@ void tst_Moc::ignoreOptionClashes()
|
|||||||
// If -pthread wasn't ignored, it was parsed as a prefix of "thread/", which breaks compilation.
|
// If -pthread wasn't ignored, it was parsed as a prefix of "thread/", which breaks compilation.
|
||||||
QStringList gccArgs;
|
QStringList gccArgs;
|
||||||
gccArgs << "-c" << "-x" << "c++" << "-I" << ".."
|
gccArgs << "-c" << "-x" << "c++" << "-I" << ".."
|
||||||
<< "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null" << "-fPIE" << "-";
|
<< "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null" << "-fPIC" << "-";
|
||||||
proc.start("gcc", gccArgs);
|
proc.start("gcc", gccArgs);
|
||||||
QVERIFY(proc.waitForStarted());
|
QVERIFY(proc.waitForStarted());
|
||||||
proc.write(mocOut);
|
proc.write(mocOut);
|
||||||
|
@ -436,6 +436,7 @@ private slots:
|
|||||||
void grabKeyboard();
|
void grabKeyboard();
|
||||||
|
|
||||||
void touchEventSynthesizedMouseEvent();
|
void touchEventSynthesizedMouseEvent();
|
||||||
|
void touchUpdateOnNewTouch();
|
||||||
|
|
||||||
void styleSheetPropagation();
|
void styleSheetPropagation();
|
||||||
|
|
||||||
@ -9757,6 +9758,9 @@ class TouchMouseWidget : public QWidget {
|
|||||||
public:
|
public:
|
||||||
explicit TouchMouseWidget(QWidget *parent = 0)
|
explicit TouchMouseWidget(QWidget *parent = 0)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
|
m_touchBeginCount(0),
|
||||||
|
m_touchUpdateCount(0),
|
||||||
|
m_touchEndCount(0),
|
||||||
m_touchEventCount(0),
|
m_touchEventCount(0),
|
||||||
m_acceptTouch(false),
|
m_acceptTouch(false),
|
||||||
m_mouseEventCount(0),
|
m_mouseEventCount(0),
|
||||||
@ -9783,6 +9787,12 @@ protected:
|
|||||||
case QEvent::TouchBegin:
|
case QEvent::TouchBegin:
|
||||||
case QEvent::TouchUpdate:
|
case QEvent::TouchUpdate:
|
||||||
case QEvent::TouchEnd:
|
case QEvent::TouchEnd:
|
||||||
|
if (e->type() == QEvent::TouchBegin)
|
||||||
|
++m_touchBeginCount;
|
||||||
|
else if (e->type() == QEvent::TouchUpdate)
|
||||||
|
++m_touchUpdateCount;
|
||||||
|
else if (e->type() == QEvent::TouchEnd)
|
||||||
|
++m_touchEndCount;
|
||||||
++m_touchEventCount;
|
++m_touchEventCount;
|
||||||
if (m_acceptTouch)
|
if (m_acceptTouch)
|
||||||
e->accept();
|
e->accept();
|
||||||
@ -9807,6 +9817,9 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
int m_touchBeginCount;
|
||||||
|
int m_touchUpdateCount;
|
||||||
|
int m_touchEndCount;
|
||||||
int m_touchEventCount;
|
int m_touchEventCount;
|
||||||
bool m_acceptTouch;
|
bool m_acceptTouch;
|
||||||
int m_mouseEventCount;
|
int m_mouseEventCount;
|
||||||
@ -9923,6 +9936,46 @@ void tst_QWidget::touchEventSynthesizedMouseEvent()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QWidget::touchUpdateOnNewTouch()
|
||||||
|
{
|
||||||
|
QTouchDevice *device = new QTouchDevice;
|
||||||
|
device->setType(QTouchDevice::TouchScreen);
|
||||||
|
QWindowSystemInterface::registerTouchDevice(device);
|
||||||
|
|
||||||
|
TouchMouseWidget widget;
|
||||||
|
widget.setAcceptTouch(true);
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
|
layout->addWidget(new QWidget);
|
||||||
|
widget.setLayout(layout);
|
||||||
|
widget.show();
|
||||||
|
|
||||||
|
QWindow* window = widget.windowHandle();
|
||||||
|
QVERIFY(QTest::qWaitForWindowExposed(window));
|
||||||
|
QCOMPARE(widget.m_touchBeginCount, 0);
|
||||||
|
QCOMPARE(widget.m_touchUpdateCount, 0);
|
||||||
|
QCOMPARE(widget.m_touchEndCount, 0);
|
||||||
|
QTest::touchEvent(window, device).press(0, QPoint(20, 20), window);
|
||||||
|
QCOMPARE(widget.m_touchBeginCount, 1);
|
||||||
|
QCOMPARE(widget.m_touchUpdateCount, 0);
|
||||||
|
QCOMPARE(widget.m_touchEndCount, 0);
|
||||||
|
QTest::touchEvent(window, device).move(0, QPoint(25, 25), window);
|
||||||
|
QCOMPARE(widget.m_touchBeginCount, 1);
|
||||||
|
QCOMPARE(widget.m_touchUpdateCount, 1);
|
||||||
|
QCOMPARE(widget.m_touchEndCount, 0);
|
||||||
|
QTest::touchEvent(window, device).stationary(0).press(1, QPoint(40, 40), window);
|
||||||
|
QCOMPARE(widget.m_touchBeginCount, 1);
|
||||||
|
QCOMPARE(widget.m_touchUpdateCount, 2);
|
||||||
|
QCOMPARE(widget.m_touchEndCount, 0);
|
||||||
|
QTest::touchEvent(window, device).stationary(1).release(0, QPoint(25, 25), window);
|
||||||
|
QCOMPARE(widget.m_touchBeginCount, 1);
|
||||||
|
QCOMPARE(widget.m_touchUpdateCount, 3);
|
||||||
|
QCOMPARE(widget.m_touchEndCount, 0);
|
||||||
|
QTest::touchEvent(window, device).release(1, QPoint(40, 40), window);
|
||||||
|
QCOMPARE(widget.m_touchBeginCount, 1);
|
||||||
|
QCOMPARE(widget.m_touchUpdateCount, 3);
|
||||||
|
QCOMPARE(widget.m_touchEndCount, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QWidget::styleSheetPropagation()
|
void tst_QWidget::styleSheetPropagation()
|
||||||
{
|
{
|
||||||
QTableView tw;
|
QTableView tw;
|
||||||
|
2
tests/auto/widgets/widgets/qmenu/BLACKLIST
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[task258920_mouseBorder]
|
||||||
|
osx
|
@ -2,3 +2,5 @@
|
|||||||
ubuntu-14.04
|
ubuntu-14.04
|
||||||
[taskQTBUG4965_escapeEaten]
|
[taskQTBUG4965_escapeEaten]
|
||||||
ubuntu-14.04
|
ubuntu-14.04
|
||||||
|
[task256322_highlight]
|
||||||
|
osx
|
||||||
|