Merge "Merge remote-tracking branch 'origin/5.9' into 5.10" into refs/staging/5.10
This commit is contained in:
commit
ae03f905d6
@ -4296,6 +4296,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
|
||||
/*!
|
||||
\macro qDebug(const char *message, ...)
|
||||
\relates <QtGlobal>
|
||||
\threadsafe
|
||||
|
||||
Calls the message handler with the debug message \a message. If no
|
||||
message handler has been installed, the message is printed to
|
||||
@ -4332,6 +4333,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
|
||||
/*!
|
||||
\macro qInfo(const char *message, ...)
|
||||
\relates <QtGlobal>
|
||||
\threadsafe
|
||||
\since 5.5
|
||||
|
||||
Calls the message handler with the informational message \a message. If no
|
||||
@ -4369,6 +4371,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
|
||||
/*!
|
||||
\macro qWarning(const char *message, ...)
|
||||
\relates <QtGlobal>
|
||||
\threadsafe
|
||||
|
||||
Calls the message handler with the warning message \a message. If no
|
||||
message handler has been installed, the message is printed to
|
||||
@ -4406,6 +4409,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
|
||||
/*!
|
||||
\macro qCritical(const char *message, ...)
|
||||
\relates <QtGlobal>
|
||||
\threadsafe
|
||||
|
||||
Calls the message handler with the critical message \a message. If no
|
||||
message handler has been installed, the message is printed to
|
||||
|
@ -595,6 +595,9 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
|
||||
params.dwSize = sizeof(params);
|
||||
params.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
params.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
|
||||
params.dwSecurityQosFlags = SECURITY_ANONYMOUS;
|
||||
params.lpSecurityAttributes = NULL;
|
||||
params.hTemplateFile = NULL;
|
||||
const HANDLE handle =
|
||||
CreateFile2((const wchar_t*)entry.nativeFilePath().utf16(), 0,
|
||||
FILE_SHARE_READ, OPEN_EXISTING, ¶ms);
|
||||
|
@ -445,6 +445,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
/*!
|
||||
\macro qCDebug(category)
|
||||
\relates QLoggingCategory
|
||||
\threadsafe
|
||||
\since 5.2
|
||||
|
||||
Returns an output stream for debug messages in the logging category
|
||||
@ -469,6 +470,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
/*!
|
||||
\macro qCDebug(category, const char *message, ...)
|
||||
\relates QLoggingCategory
|
||||
\threadsafe
|
||||
\since 5.3
|
||||
|
||||
Logs a debug message \a message in the logging category \a category.
|
||||
@ -490,6 +492,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
/*!
|
||||
\macro qCInfo(category)
|
||||
\relates QLoggingCategory
|
||||
\threadsafe
|
||||
\since 5.5
|
||||
|
||||
Returns an output stream for informational messages in the logging category
|
||||
@ -514,6 +517,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
/*!
|
||||
\macro qCInfo(category, const char *message, ...)
|
||||
\relates QLoggingCategory
|
||||
\threadsafe
|
||||
\since 5.5
|
||||
|
||||
Logs an informational message \a message in the logging category \a category.
|
||||
@ -535,6 +539,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
/*!
|
||||
\macro qCWarning(category)
|
||||
\relates QLoggingCategory
|
||||
\threadsafe
|
||||
\since 5.2
|
||||
|
||||
Returns an output stream for warning messages in the logging category
|
||||
@ -559,6 +564,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
/*!
|
||||
\macro qCWarning(category, const char *message, ...)
|
||||
\relates QLoggingCategory
|
||||
\threadsafe
|
||||
\since 5.3
|
||||
|
||||
Logs a warning message \a message in the logging category \a category.
|
||||
@ -580,6 +586,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
/*!
|
||||
\macro qCCritical(category)
|
||||
\relates QLoggingCategory
|
||||
\threadsafe
|
||||
\since 5.2
|
||||
|
||||
Returns an output stream for critical messages in the logging category
|
||||
@ -604,6 +611,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
/*!
|
||||
\macro qCCritical(category, const char *message, ...)
|
||||
\relates QLoggingCategory
|
||||
\threadsafe
|
||||
\since 5.3
|
||||
|
||||
Logs a critical message \a message in the logging category \a category.
|
||||
|
@ -2335,6 +2335,13 @@ QVariant QInputMethodQueryEvent::value(Qt::InputMethodQuery query) const
|
||||
cursor and touchpad. Qt recognizes these by their names. Otherwise, if the
|
||||
tablet is configured to use the evdev driver, there will be only one device
|
||||
and applications may not be able to distinguish the stylus from the eraser.
|
||||
|
||||
\section1 Notes for Windows Users
|
||||
|
||||
Tablet support currently requires the WACOM windows driver providing the DLL
|
||||
\c{wintab32.dll} to be installed. It is contained in older packages,
|
||||
for example \c{pentablet_5.3.5-3.exe}.
|
||||
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -476,6 +476,8 @@ bool QHttpMultiPartIODevice::isSequential() const
|
||||
|
||||
bool QHttpMultiPartIODevice::reset()
|
||||
{
|
||||
// Reset QIODevice's data
|
||||
QIODevice::reset();
|
||||
for (int a = 0; a < multiPart->parts.count(); a++)
|
||||
if (!multiPart->parts[a].d->reset())
|
||||
return false;
|
||||
|
@ -607,8 +607,14 @@ void QHttpNetworkConnectionChannel::handleStatus()
|
||||
if (redirectUrl.isValid())
|
||||
reply->setRedirectUrl(redirectUrl);
|
||||
|
||||
if (qobject_cast<QHttpNetworkConnection *>(connection))
|
||||
if ((statusCode == 307 || statusCode == 308) && !resetUploadData()) {
|
||||
// Couldn't reset the upload data, which means it will be unable to POST the data -
|
||||
// this would lead to a long wait until it eventually failed and then retried.
|
||||
// Instead of doing that we fail here instead, resetUploadData will already have emitted
|
||||
// a ContentReSendError, so we're done.
|
||||
} else if (qobject_cast<QHttpNetworkConnection *>(connection)) {
|
||||
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 401: // auth required
|
||||
|
@ -140,7 +140,7 @@ void QNetworkCookieJar::setAllCookies(const QList<QNetworkCookie> &cookieList)
|
||||
|
||||
static inline bool isParentPath(const QString &path, const QString &reference)
|
||||
{
|
||||
if (path.startsWith(reference)) {
|
||||
if ((path.isEmpty() && reference == QLatin1String("/")) || path.startsWith(reference)) {
|
||||
//The cookie-path and the request-path are identical.
|
||||
if (path.length() == reference.length())
|
||||
return true;
|
||||
|
@ -165,6 +165,16 @@ static QHash<QByteArray, QByteArray> parseHttpOptionHeader(const QByteArray &hea
|
||||
}
|
||||
}
|
||||
|
||||
#if QT_CONFIG(bearermanagement)
|
||||
static bool isSessionNeeded(const QUrl &url)
|
||||
{
|
||||
// Connections to the local machine does not require a session
|
||||
QString host = url.host().toLower();
|
||||
return !QHostAddress(host).isLoopback() && host != QLatin1String("localhost")
|
||||
&& host != QSysInfo::machineHostName().toLower();
|
||||
}
|
||||
#endif // bearer management
|
||||
|
||||
QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager* const manager,
|
||||
const QNetworkRequest& request,
|
||||
QNetworkAccessManager::Operation& operation,
|
||||
@ -1109,10 +1119,15 @@ QNetworkAccessManager::Operation QNetworkReplyHttpImplPrivate::getRedirectOperat
|
||||
switch (currentOp) {
|
||||
case QNetworkAccessManager::HeadOperation:
|
||||
return QNetworkAccessManager::HeadOperation;
|
||||
case QNetworkAccessManager::PostOperation:
|
||||
// We MUST keep using POST when being redirected with 307 or 308.
|
||||
if (statusCode == 307 || statusCode == 308)
|
||||
return QNetworkAccessManager::PostOperation;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// For now, we're always returning GET for anything other than HEAD
|
||||
// Use GET for everything else.
|
||||
return QNetworkAccessManager::GetOperation;
|
||||
}
|
||||
|
||||
@ -1187,11 +1202,30 @@ void QNetworkReplyHttpImplPrivate::followRedirect()
|
||||
{
|
||||
Q_Q(QNetworkReplyHttpImpl);
|
||||
|
||||
rawHeaders.clear();
|
||||
cookedHeaders.clear();
|
||||
|
||||
if (managerPrivate->thread)
|
||||
managerPrivate->thread->disconnect();
|
||||
|
||||
#if QT_CONFIG(bearermanagement)
|
||||
// If the original request didn't need a session (i.e. it was to localhost)
|
||||
// then we might not have a session open, to which to redirect, if the
|
||||
// new URL is remote. When this happens, we need to open the session now:
|
||||
if (managerPrivate && isSessionNeeded(url)) {
|
||||
if (auto session = managerPrivate->getNetworkSession()) {
|
||||
if (session->state() != QNetworkSession::State::Connected || !session->isOpen()) {
|
||||
startWaitForSession(session);
|
||||
// Need to set 'request' to the redirectRequest so that when QNAM restarts
|
||||
// the request after the session starts it will not repeat the previous request.
|
||||
request = redirectRequest;
|
||||
// Return now, QNAM will start the request when the session has started.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // bearer management
|
||||
|
||||
QMetaObject::invokeMethod(q, "start", Qt::QueuedConnection,
|
||||
Q_ARG(QNetworkRequest, redirectRequest));
|
||||
}
|
||||
@ -1776,10 +1810,8 @@ bool QNetworkReplyHttpImplPrivate::start(const QNetworkRequest &newHttpRequest)
|
||||
}
|
||||
|
||||
// This is not ideal.
|
||||
const QString host = url.host();
|
||||
if (host == QLatin1String("localhost") ||
|
||||
QHostAddress(host).isLoopback()) {
|
||||
// Don't need an open session for localhost access.
|
||||
if (!isSessionNeeded(url)) {
|
||||
// Don't need to check for an open session if we don't need one.
|
||||
postRequest(newHttpRequest);
|
||||
return true;
|
||||
}
|
||||
@ -1803,6 +1835,34 @@ bool QNetworkReplyHttpImplPrivate::start(const QNetworkRequest &newHttpRequest)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if QT_CONFIG(bearermanagement)
|
||||
bool QNetworkReplyHttpImplPrivate::startWaitForSession(QSharedPointer<QNetworkSession> &session)
|
||||
{
|
||||
Q_Q(QNetworkReplyHttpImpl);
|
||||
state = WaitingForSession;
|
||||
|
||||
if (session) {
|
||||
QObject::connect(session.data(), SIGNAL(error(QNetworkSession::SessionError)),
|
||||
q, SLOT(_q_networkSessionFailed()), Qt::QueuedConnection);
|
||||
|
||||
if (!session->isOpen()) {
|
||||
QVariant isBackground = request.attribute(QNetworkRequest::BackgroundRequestAttribute,
|
||||
QVariant::fromValue(false));
|
||||
session->setSessionProperty(QStringLiteral("ConnectInBackground"), isBackground);
|
||||
session->open();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const Qt::ConnectionType connection = synchronous ? Qt::DirectConnection : Qt::QueuedConnection;
|
||||
qWarning("Backend is waiting for QNetworkSession to connect, but there is none!");
|
||||
QMetaObject::invokeMethod(q, "_q_error", connection,
|
||||
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::NetworkSessionFailedError),
|
||||
Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "Network session error.")));
|
||||
QMetaObject::invokeMethod(q, "_q_finished", connection);
|
||||
return false;
|
||||
}
|
||||
#endif // QT_CONFIG(bearermanagement)
|
||||
|
||||
void QNetworkReplyHttpImplPrivate::_q_startOperation()
|
||||
{
|
||||
Q_Q(QNetworkReplyHttpImpl);
|
||||
@ -1830,24 +1890,8 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation()
|
||||
// backend failed to start because the session state is not Connected.
|
||||
// QNetworkAccessManager will call reply->backend->start() again for us when the session
|
||||
// state changes.
|
||||
state = WaitingForSession;
|
||||
|
||||
if (session) {
|
||||
QObject::connect(session.data(), SIGNAL(error(QNetworkSession::SessionError)),
|
||||
q, SLOT(_q_networkSessionFailed()), Qt::QueuedConnection);
|
||||
|
||||
if (!session->isOpen()) {
|
||||
session->setSessionProperty(QStringLiteral("ConnectInBackground"), isBackground);
|
||||
session->open();
|
||||
}
|
||||
} else {
|
||||
qWarning("Backend is waiting for QNetworkSession to connect, but there is none!");
|
||||
QMetaObject::invokeMethod(q, "_q_error", synchronous ? Qt::DirectConnection : Qt::QueuedConnection,
|
||||
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::NetworkSessionFailedError),
|
||||
Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "Network session error.")));
|
||||
QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection);
|
||||
if (!startWaitForSession(session))
|
||||
return;
|
||||
}
|
||||
} else if (session) {
|
||||
QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)),
|
||||
q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)),
|
||||
|
@ -161,6 +161,10 @@ signals:
|
||||
|
||||
class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
|
||||
{
|
||||
#if QT_CONFIG(bearermanagement)
|
||||
bool startWaitForSession(QSharedPointer<QNetworkSession> &session);
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio);
|
||||
|
@ -520,7 +520,7 @@ static inline int fromBase8(const char *s, const char *end)
|
||||
{
|
||||
int result = 0;
|
||||
while (*s && s != end) {
|
||||
if (*s <= '0' || *s >= '7')
|
||||
if (*s < '0' || *s > '7')
|
||||
return 0;
|
||||
result *= 8;
|
||||
result += *s - '0';
|
||||
|
@ -104,11 +104,11 @@ namespace QtAndroidAccessibility
|
||||
static jintArray childIdListForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId)
|
||||
{
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
if (iface) {
|
||||
if (iface && iface->isValid()) {
|
||||
jintArray jArray = env->NewIntArray(jsize(iface->childCount()));
|
||||
for (int i = 0; i < iface->childCount(); ++i) {
|
||||
QAccessibleInterface *child = iface->child(i);
|
||||
if (child) {
|
||||
if (child && child->isValid()) {
|
||||
QAccessible::Id ifaceId = QAccessible::uniqueId(child);
|
||||
jint jid = ifaceId;
|
||||
env->SetIntArrayRegion(jArray, i, 1, &jid);
|
||||
@ -123,9 +123,9 @@ namespace QtAndroidAccessibility
|
||||
static jint parentId(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
|
||||
{
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
if (iface) {
|
||||
if (iface && iface->isValid()) {
|
||||
QAccessibleInterface *parent = iface->parent();
|
||||
if (parent) {
|
||||
if (parent && parent->isValid()) {
|
||||
if (parent->role() == QAccessible::Application)
|
||||
return -1;
|
||||
return QAccessible::uniqueId(parent);
|
||||
@ -151,7 +151,7 @@ namespace QtAndroidAccessibility
|
||||
static jint hitTest(JNIEnv */*env*/, jobject /*thiz*/, jfloat x, jfloat y)
|
||||
{
|
||||
QAccessibleInterface *root = interfaceFromId(-1);
|
||||
if (root) {
|
||||
if (root && root->isValid()) {
|
||||
QPoint pos = QHighDpi::fromNativePixels(QPoint(int(x), int(y)), root->window());
|
||||
|
||||
QAccessibleInterface *child = root->childAt(pos.x(), pos.y());
|
||||
@ -170,7 +170,7 @@ namespace QtAndroidAccessibility
|
||||
{
|
||||
// qDebug() << "A11Y: CLICK: " << objectId;
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
if (iface && iface->actionInterface()) {
|
||||
if (iface && iface->isValid() && iface->actionInterface()) {
|
||||
if (iface->actionInterface()->actionNames().contains(QAccessibleActionInterface::pressAction()))
|
||||
iface->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
|
||||
else
|
||||
@ -182,13 +182,17 @@ namespace QtAndroidAccessibility
|
||||
static jboolean scrollForward(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
|
||||
{
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::increaseAction());
|
||||
if (iface && iface->isValid())
|
||||
return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::increaseAction());
|
||||
return false;
|
||||
}
|
||||
|
||||
static jboolean scrollBackward(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
|
||||
{
|
||||
QAccessibleInterface *iface = interfaceFromId(objectId);
|
||||
return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::decreaseAction());
|
||||
if (iface && iface->isValid())
|
||||
return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::decreaseAction());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
TARGET = qcocoa
|
||||
|
||||
OBJECTIVE_SOURCES += main.mm \
|
||||
SOURCES += main.mm \
|
||||
qcocoaintegration.mm \
|
||||
qcocoascreen.mm \
|
||||
qcocoatheme.mm \
|
||||
@ -32,9 +32,8 @@ OBJECTIVE_SOURCES += main.mm \
|
||||
qcocoasystemtrayicon.mm \
|
||||
qcocoaintrospection.mm \
|
||||
qcocoakeymapper.mm \
|
||||
qcocoamimetypes.mm
|
||||
|
||||
SOURCES += messages.cpp
|
||||
qcocoamimetypes.mm \
|
||||
messages.cpp
|
||||
|
||||
HEADERS += qcocoaintegration.h \
|
||||
qcocoascreen.h \
|
||||
@ -70,7 +69,7 @@ HEADERS += qcocoaintegration.h \
|
||||
qcocoamimetypes.h
|
||||
|
||||
qtConfig(opengl.*) {
|
||||
OBJECTIVE_SOURCES += qcocoaglcontext.mm
|
||||
SOURCES += qcocoaglcontext.mm
|
||||
|
||||
HEADERS += qcocoaglcontext.h
|
||||
}
|
||||
@ -89,7 +88,7 @@ CONFIG += no_app_extension_api_only
|
||||
qtHaveModule(widgets) {
|
||||
QT_FOR_CONFIG += widgets
|
||||
|
||||
OBJECTIVE_SOURCES += \
|
||||
SOURCES += \
|
||||
qpaintengine_mac.mm \
|
||||
qprintengine_mac.mm \
|
||||
qcocoaprintersupport.mm \
|
||||
|
@ -92,7 +92,6 @@
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
||||
@class QT_MANGLE_NAMESPACE(QNSMenu);
|
||||
@class QT_MANGLE_NAMESPACE(QNSImageView);
|
||||
|
||||
@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject <NSUserNotificationCenterDelegate>
|
||||
@ -123,16 +122,8 @@ QT_USE_NAMESPACE
|
||||
-(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton;
|
||||
@end
|
||||
|
||||
@interface QT_MANGLE_NAMESPACE(QNSMenu) : NSMenu <NSMenuDelegate> {
|
||||
QPlatformMenu *qmenu;
|
||||
}
|
||||
-(QPlatformMenu*)menu;
|
||||
-(id)initWithQMenu:(QPlatformMenu*)qmenu;
|
||||
@end
|
||||
|
||||
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSStatusItem);
|
||||
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSImageView);
|
||||
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSMenu);
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QSystemTrayIconSys
|
||||
@ -447,26 +438,4 @@ QT_END_NAMESPACE
|
||||
|
||||
@end
|
||||
|
||||
class QSystemTrayIconQMenu : public QPlatformMenu
|
||||
{
|
||||
public:
|
||||
void doAboutToShow() { emit aboutToShow(); }
|
||||
private:
|
||||
QSystemTrayIconQMenu();
|
||||
};
|
||||
|
||||
@implementation QNSMenu
|
||||
-(id)initWithQMenu:(QPlatformMenu*)qm {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self->qmenu = qm;
|
||||
[self setDelegate:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
-(QPlatformMenu*)menu {
|
||||
return qmenu;
|
||||
}
|
||||
@end
|
||||
|
||||
#endif // QT_NO_SYSTEMTRAYICON
|
||||
|
@ -2,9 +2,10 @@ TARGET = qdirect2d
|
||||
|
||||
QT += \
|
||||
core-private gui-private \
|
||||
eventdispatcher_support-private accessibility_support-private \
|
||||
eventdispatcher_support-private \
|
||||
fontdatabase_support-private theme_support-private
|
||||
|
||||
qtConfig(accessibility): QT += accessibility_support-private
|
||||
qtConfig(vulkan): QT += vulkan_support-private
|
||||
|
||||
LIBS += -ldwmapi -ld2d1 -ld3d11 -ldwrite -lVersion -lgdi32
|
||||
|
@ -47,7 +47,9 @@
|
||||
#include "qwindowsmenu.h"
|
||||
#include "qwindowsmime.h"
|
||||
#include "qwindowsinputcontext.h"
|
||||
#include "qwindowstabletsupport.h"
|
||||
#if QT_CONFIG(tabletevent)
|
||||
# include "qwindowstabletsupport.h"
|
||||
#endif
|
||||
#include "qwindowstheme.h"
|
||||
#include <private/qguiapplication_p.h>
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
|
@ -352,16 +352,26 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
|
||||
{
|
||||
PACKET proximityBuffer[1]; // we are only interested in the first packet in this case
|
||||
const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer);
|
||||
if (!totalPacks)
|
||||
return false;
|
||||
|
||||
if (!LOWORD(lParam)) {
|
||||
qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice;
|
||||
QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime,
|
||||
m_devices.at(m_currentDevice).currentDevice,
|
||||
m_devices.at(m_currentDevice).currentPointerType,
|
||||
m_devices.at(m_currentDevice).uniqueId);
|
||||
if (totalPacks > 0) {
|
||||
QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime,
|
||||
m_devices.at(m_currentDevice).currentDevice,
|
||||
m_devices.at(m_currentDevice).currentPointerType,
|
||||
m_devices.at(m_currentDevice).uniqueId);
|
||||
} else {
|
||||
QWindowSystemInterface::handleTabletLeaveProximityEvent(m_devices.at(m_currentDevice).currentDevice,
|
||||
m_devices.at(m_currentDevice).currentPointerType,
|
||||
m_devices.at(m_currentDevice).uniqueId);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!totalPacks)
|
||||
return false;
|
||||
|
||||
const UINT currentCursor = proximityBuffer[0].pkCursor;
|
||||
UINT physicalCursorId;
|
||||
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &physicalCursorId);
|
||||
|
@ -2,9 +2,10 @@ TARGET = qwindows
|
||||
|
||||
QT += \
|
||||
core-private gui-private \
|
||||
eventdispatcher_support-private accessibility_support-private \
|
||||
eventdispatcher_support-private \
|
||||
fontdatabase_support-private theme_support-private
|
||||
|
||||
qtConfig(accessibility): QT += accessibility_support-private
|
||||
qtConfig(vulkan): QT += vulkan_support-private
|
||||
|
||||
LIBS += -lgdi32 -ldwmapi
|
||||
|
@ -915,7 +915,9 @@ void QXcbWindow::hide()
|
||||
if (QWindow *childWindow = childWindowAt(enterWindow, cursorPos))
|
||||
enterWindow = childWindow;
|
||||
const QPoint localPos = enterWindow->mapFromGlobal(cursorPos);
|
||||
QWindowSystemInterface::handleEnterEvent(enterWindow, localPos, cursorPos);
|
||||
QWindowSystemInterface::handleEnterEvent(enterWindow,
|
||||
localPos * QHighDpiScaling::factor(enterWindow),
|
||||
nativePos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -289,8 +289,10 @@ static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidge
|
||||
// not the QMenu.) Since we can also reach this code by climbing the menu
|
||||
// hierarchy (see below), or when the shortcut is not a key-equivalent, we
|
||||
// need to check whether the QPA menu is actually disabled.
|
||||
// When there is no QPA menu, there will be no QCocoaMenuDelegate checking
|
||||
// for the actual shortcuts. We can then fallback to our own logic.
|
||||
QPlatformMenu *pm = menu->platformMenu();
|
||||
if (!pm || !pm->isEnabled())
|
||||
if (pm && !pm->isEnabled())
|
||||
continue;
|
||||
#endif
|
||||
QAction *a = menu->menuAction();
|
||||
|
@ -43,3 +43,8 @@ else:!qtConfig(process): SUBDIRS -= tools
|
||||
SUBDIRS -= dbus
|
||||
}
|
||||
}
|
||||
|
||||
# QTBUG-63915
|
||||
boot2qt: {
|
||||
contains(QT_ARCH, arm64): SUBDIRS -= dbus
|
||||
}
|
||||
|
3
tests/auto/corelib/global/qlogging/BLACKLIST
Normal file
3
tests/auto/corelib/global/qlogging/BLACKLIST
Normal file
@ -0,0 +1,3 @@
|
||||
[qMessagePattern:backtrace depth,separator]
|
||||
# QTBUG-63915
|
||||
b2qt 64bit
|
@ -340,6 +340,17 @@ void tst_QNetworkCookieJar::cookiesForUrl_data()
|
||||
QTest::newRow("no-match-domain-dot") << allCookies << "http://example.com" << result;
|
||||
result += cookieDot;
|
||||
QTest::newRow("match-domain-dot") << allCookies << "http://example.com." << result;
|
||||
|
||||
// Root path in cookie, empty url path
|
||||
allCookies.clear();
|
||||
QNetworkCookie rootCookie;
|
||||
rootCookie.setName("a");
|
||||
rootCookie.setPath("/");
|
||||
rootCookie.setDomain("qt-project.org");
|
||||
allCookies += rootCookie;
|
||||
result.clear();
|
||||
result += rootCookie;
|
||||
QTest::newRow("root-path-match") << allCookies << "http://qt-project.org" << result;
|
||||
}
|
||||
|
||||
void tst_QNetworkCookieJar::cookiesForUrl()
|
||||
|
@ -490,6 +490,11 @@ private Q_SLOTS:
|
||||
void ioHttpCookiesDuringRedirect();
|
||||
void ioHttpRedirect_data();
|
||||
void ioHttpRedirect();
|
||||
void ioHttpRedirectFromLocalToRemote();
|
||||
void ioHttpRedirectPost_data();
|
||||
void ioHttpRedirectPost();
|
||||
void ioHttpRedirectMultipartPost_data();
|
||||
void ioHttpRedirectMultipartPost();
|
||||
#ifndef QT_NO_SSL
|
||||
void putWithServerClosingConnectionImmediately();
|
||||
#endif
|
||||
@ -516,6 +521,17 @@ bool tst_QNetworkReply::seedCreated = false;
|
||||
QFAIL(qPrintable(errorMsg)); \
|
||||
} while (0)
|
||||
|
||||
static bool validateRedirectedResponseHeaders(QNetworkReplyPtr reply)
|
||||
{
|
||||
// QTBUG-61300: previously we were mixing 'raw' headers from all responses
|
||||
// along the redirect chain. The simplest test is to check/verify we have
|
||||
// no 'location' header anymore.
|
||||
Q_ASSERT(reply.data());
|
||||
|
||||
return !reply->hasRawHeader("location")
|
||||
&& !reply->header(QNetworkRequest::LocationHeader).isValid();
|
||||
}
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
static void setupSslServer(QSslSocket* serverSocket)
|
||||
{
|
||||
@ -530,7 +546,7 @@ static void setupSslServer(QSslSocket* serverSocket)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Does not work for POST/PUT!
|
||||
// Does not work for PUT! Limited support for POST.
|
||||
class MiniHttpServer: public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -545,6 +561,10 @@ public:
|
||||
bool multiple;
|
||||
int totalConnections;
|
||||
|
||||
bool hasContent = false;
|
||||
int contentRead = 0;
|
||||
int contentLength = 0;
|
||||
|
||||
MiniHttpServer(const QByteArray &data, bool ssl = false, QThread *thread = 0, bool useipv6 = false)
|
||||
: dataToTransmit(data), doClose(true), doSsl(ssl), ipv6(useipv6),
|
||||
multiple(false), totalConnections(0)
|
||||
@ -621,6 +641,18 @@ private:
|
||||
this, SLOT(slotError(QAbstractSocket::SocketError)));
|
||||
}
|
||||
|
||||
void parseContentLength()
|
||||
{
|
||||
int index = receivedData.indexOf("Content-Length:");
|
||||
index += sizeof("Content-Length:") - 1;
|
||||
const auto end = std::find(receivedData.cbegin() + index, receivedData.cend(), '\r');
|
||||
auto num = receivedData.mid(index, std::distance(receivedData.cbegin() + index, end));
|
||||
bool ok;
|
||||
contentLength = num.toInt(&ok);
|
||||
if (!ok)
|
||||
contentLength = -1;
|
||||
}
|
||||
|
||||
private slots:
|
||||
#ifndef QT_NO_SSL
|
||||
void slotSslErrors(const QList<QSslError>& errors)
|
||||
@ -642,12 +674,20 @@ public slots:
|
||||
{
|
||||
Q_ASSERT(!client.isNull());
|
||||
receivedData += client->readAll();
|
||||
int doubleEndlPos = receivedData.indexOf("\r\n\r\n");
|
||||
const int doubleEndlPos = receivedData.indexOf("\r\n\r\n");
|
||||
|
||||
if (doubleEndlPos != -1) {
|
||||
const int endOfHeader = doubleEndlPos + 4;
|
||||
hasContent = receivedData.startsWith("POST");
|
||||
if (hasContent && contentLength == 0)
|
||||
parseContentLength();
|
||||
contentRead = receivedData.length() - endOfHeader;
|
||||
if (hasContent && contentRead < contentLength)
|
||||
return;
|
||||
|
||||
// multiple requests incoming. remove the bytes of the current one
|
||||
if (multiple)
|
||||
receivedData.remove(0, doubleEndlPos+4);
|
||||
receivedData.remove(0, endOfHeader);
|
||||
|
||||
reply();
|
||||
}
|
||||
@ -8106,6 +8146,7 @@ void tst_QNetworkReply::ioHttpSingleRedirect()
|
||||
// Reply url is set to the redirect url
|
||||
QCOMPARE(reply->url(), redirectUrl);
|
||||
QCOMPARE(reply->error(), QNetworkReply::NoError);
|
||||
QVERIFY(validateRedirectedResponseHeaders(reply));
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpChangeMaxRedirects()
|
||||
@ -8154,6 +8195,7 @@ void tst_QNetworkReply::ioHttpChangeMaxRedirects()
|
||||
QCOMPARE(redSpy2.count(), 2);
|
||||
QCOMPARE(reply2->url(), server3Url);
|
||||
QCOMPARE(reply2->error(), QNetworkReply::NoError);
|
||||
QVERIFY(validateRedirectedResponseHeaders(reply2));
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpRedirectErrors_data()
|
||||
@ -8167,7 +8209,9 @@ void tst_QNetworkReply::ioHttpRedirectErrors_data()
|
||||
"location: http://localhost:%1\r\n\r\n");
|
||||
|
||||
QTest::newRow("too-many-redirects") << "http://localhost" << tempRedirectReply << QNetworkReply::TooManyRedirectsError;
|
||||
#if QT_CONFIG(ssl)
|
||||
QTest::newRow("insecure-redirect") << "https://localhost" << tempRedirectReply << QNetworkReply::InsecureRedirectError;
|
||||
#endif
|
||||
QTest::newRow("unknown-redirect") << "http://localhost"<< tempRedirectReply.replace("http", "bad_protocol") << QNetworkReply::ProtocolUnknownError;
|
||||
}
|
||||
|
||||
@ -8178,7 +8222,7 @@ void tst_QNetworkReply::ioHttpRedirectErrors()
|
||||
QFETCH(QNetworkReply::NetworkError, error);
|
||||
|
||||
QUrl localhost(url);
|
||||
MiniHttpServer server("", localhost.scheme() == "https");
|
||||
MiniHttpServer server("", localhost.scheme() == QLatin1String("https"));
|
||||
|
||||
localhost.setPort(server.serverPort());
|
||||
|
||||
@ -8228,11 +8272,13 @@ void tst_QNetworkReply::ioHttpRedirectPolicy_data()
|
||||
QTest::addColumn<int>("statusCode");
|
||||
|
||||
QTest::newRow("manual-nossl") << QNetworkRequest::ManualRedirectPolicy << false << 0 << 307;
|
||||
QTest::newRow("manual-ssl") << QNetworkRequest::ManualRedirectPolicy << true << 0 << 307;
|
||||
QTest::newRow("nolesssafe-nossl") << QNetworkRequest::NoLessSafeRedirectPolicy << false << 1 << 200;
|
||||
QTest::newRow("nolesssafe-ssl") << QNetworkRequest::NoLessSafeRedirectPolicy << true << 1 << 200;
|
||||
QTest::newRow("same-origin-nossl") << QNetworkRequest::SameOriginRedirectPolicy << false << 1 << 200;
|
||||
#if QT_CONFIG(ssl)
|
||||
QTest::newRow("manual-ssl") << QNetworkRequest::ManualRedirectPolicy << true << 0 << 307;
|
||||
QTest::newRow("nolesssafe-ssl") << QNetworkRequest::NoLessSafeRedirectPolicy << true << 1 << 200;
|
||||
QTest::newRow("same-origin-ssl") << QNetworkRequest::SameOriginRedirectPolicy << true << 1 << 200;
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpRedirectPolicy()
|
||||
@ -8240,10 +8286,6 @@ void tst_QNetworkReply::ioHttpRedirectPolicy()
|
||||
QFETCH(const QNetworkRequest::RedirectPolicy, policy);
|
||||
|
||||
QFETCH(const bool, ssl);
|
||||
#ifdef QT_NO_SSL
|
||||
if (ssl)
|
||||
QSKIP("SSL is not supported");
|
||||
#endif
|
||||
|
||||
QFETCH(const int, redirectCount);
|
||||
QFETCH(const int, statusCode);
|
||||
@ -8251,11 +8293,7 @@ void tst_QNetworkReply::ioHttpRedirectPolicy()
|
||||
// Setup HTTP server.
|
||||
SameOriginRedirector redirectServer("", ssl);
|
||||
|
||||
QUrl url(QLatin1String(
|
||||
#ifndef QT_NO_SSL
|
||||
ssl ? "https://localhost" :
|
||||
#endif
|
||||
"http://localhost"));
|
||||
QUrl url(QLatin1String(ssl ? "https://localhost" : "http://localhost"));
|
||||
|
||||
url.setPort(redirectServer.serverPort());
|
||||
redirectServer.responses.push_back(httpEmpty200Response);
|
||||
@ -8278,6 +8316,7 @@ void tst_QNetworkReply::ioHttpRedirectPolicy()
|
||||
QCOMPARE(finishedSpy.count(), 1);
|
||||
QCOMPARE(redirectSpy.count(), redirectCount);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), statusCode);
|
||||
QVERIFY(validateRedirectedResponseHeaders(reply) || statusCode != 200);
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpRedirectPolicyErrors_data()
|
||||
@ -8291,27 +8330,35 @@ void tst_QNetworkReply::ioHttpRedirectPolicyErrors_data()
|
||||
// 1. NoLessSafeRedirectsPolicy
|
||||
QTest::newRow("nolesssafe-nossl-nossl-too-many") << QNetworkRequest::NoLessSafeRedirectPolicy
|
||||
<< false << QString("http://localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
|
||||
#if QT_CONFIG(ssl)
|
||||
QTest::newRow("nolesssafe-ssl-ssl-too-many") << QNetworkRequest::NoLessSafeRedirectPolicy
|
||||
<< true << QString("https:/localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
|
||||
QTest::newRow("nolesssafe-ssl-nossl-insecure-redirect") << QNetworkRequest::NoLessSafeRedirectPolicy
|
||||
<< true << QString("http://localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
|
||||
#endif
|
||||
// 2. SameOriginRedirectsPolicy
|
||||
QTest::newRow("same-origin-nossl-nossl-too-many") << QNetworkRequest::SameOriginRedirectPolicy
|
||||
<< false << QString("http://localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
|
||||
#if QT_CONFIG(ssl)
|
||||
QTest::newRow("same-origin-ssl-ssl-too-many") << QNetworkRequest::SameOriginRedirectPolicy
|
||||
<< true << QString("https://localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
|
||||
QTest::newRow("same-origin-https-http-wrong-protocol") << QNetworkRequest::SameOriginRedirectPolicy
|
||||
<< true << QString("http://localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
|
||||
#endif
|
||||
QTest::newRow("same-origin-http-https-wrong-protocol") << QNetworkRequest::SameOriginRedirectPolicy
|
||||
<< false << QString("https://localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
|
||||
QTest::newRow("same-origin-http-http-wrong-host") << QNetworkRequest::SameOriginRedirectPolicy
|
||||
<< false << QString("http://not-so-localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
|
||||
#if QT_CONFIG(ssl)
|
||||
QTest::newRow("same-origin-https-https-wrong-host") << QNetworkRequest::SameOriginRedirectPolicy
|
||||
<< true << QString("https://not-so-localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
|
||||
#endif
|
||||
QTest::newRow("same-origin-http-http-wrong-port") << QNetworkRequest::SameOriginRedirectPolicy
|
||||
<< false << QString("http://localhost/%1") << 50 << QNetworkReply::InsecureRedirectError;
|
||||
#if QT_CONFIG(ssl)
|
||||
QTest::newRow("same-origin-https-https-wrong-port") << QNetworkRequest::SameOriginRedirectPolicy
|
||||
<< true << QString("https://localhost/%1") << 50 << QNetworkReply::InsecureRedirectError;
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpRedirectPolicyErrors()
|
||||
@ -8325,20 +8372,11 @@ void tst_QNetworkReply::ioHttpRedirectPolicyErrors()
|
||||
QFETCH(const int, maxRedirects);
|
||||
QFETCH(const QNetworkReply::NetworkError, expectedError);
|
||||
|
||||
#ifdef QT_NO_SSL
|
||||
if (ssl || location.contains("https"))
|
||||
QSKIP("SSL required to run this test");
|
||||
#endif
|
||||
|
||||
// Setup the server.
|
||||
MiniHttpServer server("", ssl);
|
||||
server.setDataToTransmit(tempRedirectReplyStr().arg(location.arg(server.serverPort())).toLatin1());
|
||||
|
||||
QUrl url(QLatin1String(
|
||||
#ifndef QT_NO_SSL
|
||||
ssl ? "https://localhost" :
|
||||
#endif
|
||||
"http://localhost"));
|
||||
QUrl url(QLatin1String(ssl ? "https://localhost" : "http://localhost"));
|
||||
url.setPort(server.serverPort());
|
||||
|
||||
QNetworkRequest request(url);
|
||||
@ -8411,6 +8449,7 @@ void tst_QNetworkReply::ioHttpUserVerifiedRedirect()
|
||||
waitForFinish(reply);
|
||||
QCOMPARE(finishedSpy.count(), 1);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), statusCode);
|
||||
QVERIFY(validateRedirectedResponseHeaders(reply) || statusCode != 200);
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpCookiesDuringRedirect()
|
||||
@ -8438,6 +8477,7 @@ void tst_QNetworkReply::ioHttpCookiesDuringRedirect()
|
||||
|
||||
QVERIFY(waitForFinish(reply) == Success);
|
||||
QVERIFY(target.receivedData.contains("\r\nCookie: hello=world\r\n"));
|
||||
QVERIFY(validateRedirectedResponseHeaders(reply));
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpRedirect_data()
|
||||
@ -8476,6 +8516,152 @@ void tst_QNetworkReply::ioHttpRedirect()
|
||||
|
||||
QCOMPARE(waitForFinish(reply), int(Success));
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
|
||||
QVERIFY(validateRedirectedResponseHeaders(reply));
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpRedirectFromLocalToRemote()
|
||||
{
|
||||
QUrl targetUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
|
||||
|
||||
QString redirectReply = tempRedirectReplyStr().arg(targetUrl.toString());
|
||||
MiniHttpServer redirectServer(redirectReply.toLatin1(), false);
|
||||
QUrl url("http://localhost/");
|
||||
url.setPort(redirectServer.serverPort());
|
||||
|
||||
QFile reference(testDataDir + "/rfc3252.txt");
|
||||
QVERIFY(reference.open(QIODevice::ReadOnly));
|
||||
QNetworkRequest request(url);
|
||||
|
||||
auto oldRedirectPolicy = manager.redirectPolicy();
|
||||
manager.setRedirectPolicy(QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy);
|
||||
QNetworkReplyPtr reply(manager.get(request));
|
||||
// Restore previous policy
|
||||
manager.setRedirectPolicy(oldRedirectPolicy);
|
||||
|
||||
QCOMPARE(waitForFinish(reply), int(Success));
|
||||
|
||||
QCOMPARE(reply->url(), targetUrl);
|
||||
QCOMPARE(reply->error(), QNetworkReply::NoError);
|
||||
QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), reference.size());
|
||||
QCOMPARE(reply->readAll(), reference.readAll());
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpRedirectPost_data()
|
||||
{
|
||||
QTest::addColumn<QString>("status");
|
||||
QTest::addColumn<QByteArray>("data");
|
||||
QTest::addColumn<QString>("contentType");
|
||||
|
||||
QByteArray data;
|
||||
data = "hello world";
|
||||
QTest::addRow("307") << "307 Temporary Redirect" << data << "text/plain";
|
||||
QString permanentRedirect = "308 Permanent Redirect";
|
||||
QTest::addRow("308") << permanentRedirect << data << "text/plain";
|
||||
|
||||
// Some data from ::putToFile_data
|
||||
data = "";
|
||||
QTest::newRow("empty") << permanentRedirect << data << "application/octet-stream";
|
||||
|
||||
data = QByteArray("abcd\0\1\2\abcd",12);
|
||||
QTest::newRow("with-nul") << permanentRedirect << data << "application/octet-stream";
|
||||
|
||||
data = QByteArray(4097, '\4');
|
||||
QTest::newRow("4k+1") << permanentRedirect << data << "application/octet-stream";
|
||||
|
||||
data = QByteArray(128*1024+1, '\177');
|
||||
QTest::newRow("128k+1") << permanentRedirect << data << "application/octet-stream";
|
||||
|
||||
data = QByteArray(2*1024*1024+1, '\177');
|
||||
QTest::newRow("2MB+1") << permanentRedirect << data << "application/octet-stream";
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpRedirectPost()
|
||||
{
|
||||
QFETCH(QString, status);
|
||||
QFETCH(QByteArray, data);
|
||||
QFETCH(QString, contentType);
|
||||
|
||||
QUrl targetUrl("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi");
|
||||
|
||||
QString redirectReply = QStringLiteral("HTTP/1.1 %1\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"location: %2\r\n"
|
||||
"\r\n").arg(status, targetUrl.toString());
|
||||
MiniHttpServer redirectServer(redirectReply.toLatin1());
|
||||
QUrl url("http://localhost/");
|
||||
url.setPort(redirectServer.serverPort());
|
||||
QNetworkRequest request(url);
|
||||
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, contentType);
|
||||
auto oldRedirectPolicy = manager.redirectPolicy();
|
||||
manager.setRedirectPolicy(QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy);
|
||||
|
||||
QNetworkReplyPtr reply(manager.post(request, data));
|
||||
// Restore previous policy:
|
||||
manager.setRedirectPolicy(oldRedirectPolicy);
|
||||
|
||||
QCOMPARE(waitForFinish(reply), int(Success));
|
||||
QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex());
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpRedirectMultipartPost_data()
|
||||
{
|
||||
postToHttpMultipart_data();
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::ioHttpRedirectMultipartPost()
|
||||
{
|
||||
// Note: This code is heavily based on postToHttpMultipart
|
||||
QFETCH(QUrl, url);
|
||||
|
||||
static QSet<QByteArray> boundaries;
|
||||
|
||||
QNetworkReplyPtr reply;
|
||||
|
||||
QFETCH(QHttpMultiPart *, multiPart);
|
||||
QFETCH(QByteArray, expectedReplyData);
|
||||
QFETCH(QByteArray, contentType);
|
||||
|
||||
QString redirectReply = tempRedirectReplyStr().arg(url.toString());
|
||||
MiniHttpServer redirectServer(redirectReply.toLatin1());
|
||||
QUrl redirectUrl("http://localhost/");
|
||||
redirectUrl.setPort(redirectServer.serverPort());
|
||||
QNetworkRequest request(redirectUrl);
|
||||
|
||||
// Restore policy when we leave this scope:
|
||||
struct PolicyRestorer
|
||||
{
|
||||
QNetworkAccessManager &qnam;
|
||||
QNetworkRequest::RedirectPolicy policy;
|
||||
PolicyRestorer(QNetworkAccessManager &qnam)
|
||||
: qnam(qnam), policy(qnam.redirectPolicy())
|
||||
{ qnam.setRedirectPolicy(QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy); }
|
||||
~PolicyRestorer() { qnam.setRedirectPolicy(policy); }
|
||||
} policyRestorer(manager);
|
||||
|
||||
// hack for testing the setting of the content-type header by hand:
|
||||
if (contentType == "custom") {
|
||||
QByteArray contentType("multipart/custom; boundary=\"" + multiPart->boundary() + "\"");
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, contentType);
|
||||
}
|
||||
|
||||
QVERIFY2(! boundaries.contains(multiPart->boundary()), "boundary '" + multiPart->boundary() + "' has been created twice");
|
||||
boundaries.insert(multiPart->boundary());
|
||||
|
||||
RUN_REQUEST(runMultipartRequest(request, reply, multiPart, "POST"));
|
||||
multiPart->deleteLater();
|
||||
|
||||
QCOMPARE(reply->url(), url);
|
||||
QCOMPARE(reply->error(), QNetworkReply::NoError);
|
||||
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 OK
|
||||
|
||||
QVERIFY(multiPart->boundary().count() > 20); // check that there is randomness after the "boundary_.oOo._" string
|
||||
QVERIFY(multiPart->boundary().count() < 70);
|
||||
QByteArray replyData = reply->readAll();
|
||||
|
||||
expectedReplyData.prepend("content type: multipart/" + contentType + "; boundary=\"" + multiPart->boundary() + "\"\n");
|
||||
// QEXPECT_FAIL("nested", "the server does not understand nested multipart messages", Continue); // see above
|
||||
QCOMPARE(replyData, expectedReplyData);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
|
@ -135,6 +135,7 @@ private slots:
|
||||
void menuSize_Scrolling_data();
|
||||
void menuSize_Scrolling();
|
||||
void tearOffMenuNotDisplayed();
|
||||
void QTBUG_61039_menu_shortcuts();
|
||||
|
||||
protected slots:
|
||||
void onActivated(QAction*);
|
||||
@ -1644,5 +1645,32 @@ void tst_QMenu::tearOffMenuNotDisplayed()
|
||||
QVERIFY(!torn->isVisible());
|
||||
}
|
||||
|
||||
void tst_QMenu::QTBUG_61039_menu_shortcuts()
|
||||
{
|
||||
QAction *actionKamen = new QAction("Action Kamen");
|
||||
actionKamen->setShortcut(QKeySequence(QLatin1String("K")));
|
||||
|
||||
QAction *actionJoe = new QAction("Action Joe");
|
||||
actionJoe->setShortcut(QKeySequence(QLatin1String("Ctrl+J")));
|
||||
|
||||
QMenu menu;
|
||||
menu.addAction(actionKamen);
|
||||
menu.addAction(actionJoe);
|
||||
QVERIFY(!menu.platformMenu());
|
||||
|
||||
QWidget widget;
|
||||
widget.addAction(menu.menuAction());
|
||||
widget.show();
|
||||
QVERIFY(QTest::qWaitForWindowActive(&widget));
|
||||
|
||||
QSignalSpy actionKamenSpy(actionKamen, &QAction::triggered);
|
||||
QTest::keyClick(&widget, Qt::Key_K);
|
||||
QTRY_COMPARE(actionKamenSpy.count(), 1);
|
||||
|
||||
QSignalSpy actionJoeSpy(actionJoe, &QAction::triggered);
|
||||
QTest::keyClick(&widget, Qt::Key_J, Qt::ControlModifier);
|
||||
QTRY_COMPARE(actionJoeSpy.count(), 1);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QMenu)
|
||||
#include "tst_qmenu.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user