Merge "Merge remote-tracking branch 'origin/5.12' into 5.13" into refs/staging/5.13
This commit is contained in:
commit
ac244dbcf2
@ -260,25 +260,31 @@ static int installFile(const QString &source, const QString &target, bool exe =
|
||||
return 3;
|
||||
}
|
||||
|
||||
QFileDevice::Permissions targetPermissions = QFileDevice::ReadOwner | QFileDevice::WriteOwner
|
||||
| QFileDevice::ReadUser | QFileDevice::WriteUser
|
||||
| QFileDevice::ReadGroup | QFileDevice::ReadOther;
|
||||
if (exe) {
|
||||
targetPermissions |= QFileDevice::ExeOwner | QFileDevice::ExeUser |
|
||||
QFileDevice::ExeGroup | QFileDevice::ExeOther;
|
||||
}
|
||||
if (!targetFile.setPermissions(targetPermissions)) {
|
||||
fprintf(stderr, "Error setting permissions on %s: %s\n",
|
||||
qPrintable(target), qPrintable(targetFile.errorString()));
|
||||
return 3;
|
||||
if (!targetFile.setPermissions(sourceFile.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser |
|
||||
QFileDevice::ExeGroup | QFileDevice::ExeOther)) {
|
||||
fprintf(stderr, "Error setting execute permissions on %s: %s\n",
|
||||
qPrintable(target), qPrintable(targetFile.errorString()));
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy file times
|
||||
QString error;
|
||||
#ifdef Q_OS_WIN
|
||||
const QFile::Permissions permissions = targetFile.permissions();
|
||||
const bool readOnly = !(permissions & QFile::WriteUser);
|
||||
if (readOnly)
|
||||
targetFile.setPermissions(permissions | QFile::WriteUser);
|
||||
#endif
|
||||
if (!IoUtils::touchFile(target, sourceFile.fileName(), &error)) {
|
||||
fprintf(stderr, "%s", qPrintable(error));
|
||||
return 3;
|
||||
}
|
||||
#ifdef Q_OS_WIN
|
||||
if (readOnly)
|
||||
targetFile.setPermissions(permissions);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
2
src/3rdparty/wintab/LICENSE.txt
vendored
Normal file
2
src/3rdparty/wintab/LICENSE.txt
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
The text and information contained in this file may be freely used,
|
||||
copied, or distributed without compensation or licensing restrictions.
|
6
src/3rdparty/wintab/qt_attribution.json
vendored
6
src/3rdparty/wintab/qt_attribution.json
vendored
@ -5,9 +5,9 @@
|
||||
"QtUsage": "Used in the Qt platform plugin for Windows. Configure with -no-feature-tabletevent to avoid.",
|
||||
|
||||
"Description": "Wintab is a de facto API for pointing devices on Windows.",
|
||||
"Version": "Upstream no longer offers updates; treat as final",
|
||||
"Homepage": "http://www.pointing.com/Wintab.html",
|
||||
"License": "Public Domain",
|
||||
"PackageComment": "Upstream http://www.pointing.com/Wintab.html no longer offers updates; treat as final",
|
||||
"License": "Custom License",
|
||||
"LicenseFile": "LICENSE.txt",
|
||||
"LicenseId": "NONE",
|
||||
"Copyright": "Copyright 1991-1998 by LCS/Telegraphics."
|
||||
}
|
||||
|
@ -140,6 +140,10 @@ public:
|
||||
// Inlined for its one caller in qdatetime.cpp
|
||||
inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch);
|
||||
#endif // timezone
|
||||
|
||||
// ### Qt 5.14: expose publicly in QDateTime
|
||||
// The first and last years of which QDateTime can represent some part:
|
||||
enum class YearRange : qint32 { First = -292275056, Last = +292278994 };
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include "qtimezone.h"
|
||||
#include "qtimezoneprivate_p.h"
|
||||
#include "qdatetime_p.h" // ### Qt 5.14: remove once YearRange is on QDateTime
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QHash>
|
||||
@ -520,19 +521,14 @@ PosixZone PosixZone::parse(const char *&pos, const char *end)
|
||||
|
||||
static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule,
|
||||
int startYear, int endYear,
|
||||
int lastTranMSecs)
|
||||
qint64 lastTranMSecs)
|
||||
{
|
||||
QVector<QTimeZonePrivate::Data> result;
|
||||
|
||||
// Limit year by qint64 max size for msecs
|
||||
if (startYear > 292278994)
|
||||
startYear = 292278994;
|
||||
if (endYear > 292278994)
|
||||
endYear = 292278994;
|
||||
|
||||
// POSIX Format is like "TZ=CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00"
|
||||
// i.e. "std offset dst [offset],start[/time],end[/time]"
|
||||
// See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
|
||||
// See the section about TZ at
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
|
||||
QList<QByteArray> parts = posixRule.split(',');
|
||||
|
||||
PosixZone stdZone, dstZone = PosixZone::invalid();
|
||||
@ -583,6 +579,13 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
else
|
||||
stdTime = QTime(2, 0, 0);
|
||||
|
||||
// Limit year to the range QDateTime can represent:
|
||||
const int minYear = int(QDateTimePrivate::YearRange::First);
|
||||
const int maxYear = int(QDateTimePrivate::YearRange::Last);
|
||||
startYear = qBound(minYear, startYear, maxYear);
|
||||
endYear = qBound(minYear, endYear, maxYear);
|
||||
Q_ASSERT(startYear <= endYear);
|
||||
|
||||
for (int year = startYear; year <= endYear; ++year) {
|
||||
QTimeZonePrivate::Data dstData;
|
||||
QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
|
||||
@ -598,13 +601,16 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
stdData.standardTimeOffset = stdZone.offset;
|
||||
stdData.daylightTimeOffset = 0;
|
||||
stdData.abbreviation = stdZone.name;
|
||||
// Part of the high year will overflow
|
||||
if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
|
||||
// Part of maxYear will overflow (likewise for minYear, below):
|
||||
if (year == maxYear && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
|
||||
if (dstData.atMSecsSinceEpoch > 0) {
|
||||
result << dstData;
|
||||
} else if (stdData.atMSecsSinceEpoch > 0) {
|
||||
result << stdData;
|
||||
}
|
||||
} else if (year < 1970) { // We ignore DST before the epoch.
|
||||
if (year > minYear || stdData.atMSecsSinceEpoch != QTimeZonePrivate::invalidMSecs())
|
||||
result << stdData;
|
||||
} else if (dst < std) {
|
||||
result << dstData << stdData;
|
||||
} else {
|
||||
@ -794,6 +800,8 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId)
|
||||
tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000;
|
||||
m_tranTimes.append(tran);
|
||||
}
|
||||
if (m_tranTimes.isEmpty() && m_posixRule.isEmpty())
|
||||
return; // Invalid after all !
|
||||
|
||||
if (ianaId.isEmpty())
|
||||
m_id = systemTimeZoneId();
|
||||
@ -954,22 +962,25 @@ QVector<QTimeZonePrivate::Data> QTzTimeZonePrivate::getPosixTransitions(qint64 m
|
||||
QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
|
||||
{
|
||||
// If the required time is after the last transition (or there were none)
|
||||
// and we have a POSIX rule then use it:
|
||||
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch)
|
||||
&& !m_posixRule.isEmpty() && forMSecsSinceEpoch >= 0) {
|
||||
// and we have a POSIX rule, then use it:
|
||||
if (!m_posixRule.isEmpty()
|
||||
&& (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch)) {
|
||||
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(forMSecsSinceEpoch);
|
||||
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
|
||||
[forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
|
||||
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
|
||||
});
|
||||
if (it > posixTrans.cbegin()) {
|
||||
QTimeZonePrivate::Data data = *--it;
|
||||
// Use most recent, if any in the past; or the first if we have no other rules:
|
||||
if (it > posixTrans.cbegin() || (m_tranTimes.isEmpty() && it < posixTrans.cend())) {
|
||||
QTimeZonePrivate::Data data = *(it > posixTrans.cbegin() ? it - 1 : it);
|
||||
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
if (m_tranTimes.isEmpty()) // Only possible if !isValid()
|
||||
return invalidData();
|
||||
|
||||
// Otherwise, if we can find a valid tran, then use its rule:
|
||||
// Otherwise, use the rule for the most recent or first transition:
|
||||
auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
|
||||
[forMSecsSinceEpoch] (const QTzTransitionTime &at) {
|
||||
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
|
||||
@ -989,9 +1000,9 @@ bool QTzTimeZonePrivate::hasTransitions() const
|
||||
QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
|
||||
{
|
||||
// If the required time is after the last transition (or there were none)
|
||||
// and we have a POSIX rule then use it:
|
||||
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch)
|
||||
&& !m_posixRule.isEmpty() && afterMSecsSinceEpoch >= 0) {
|
||||
// and we have a POSIX rule, then use it:
|
||||
if (!m_posixRule.isEmpty()
|
||||
&& (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch)) {
|
||||
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(afterMSecsSinceEpoch);
|
||||
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
|
||||
[afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
|
||||
@ -1012,9 +1023,9 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
|
||||
QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
|
||||
{
|
||||
// If the required time is after the last transition (or there were none)
|
||||
// and we have a POSIX rule then use it:
|
||||
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)
|
||||
&& !m_posixRule.isEmpty() && beforeMSecsSinceEpoch > 0) {
|
||||
// and we have a POSIX rule, then use it:
|
||||
if (!m_posixRule.isEmpty()
|
||||
&& (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)) {
|
||||
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(beforeMSecsSinceEpoch);
|
||||
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
|
||||
[beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
|
||||
|
@ -764,7 +764,8 @@
|
||||
},
|
||||
"headers": [ "xkbcommon/xkbcommon.h" ],
|
||||
"sources": [
|
||||
{ "type": "pkgConfig", "args": "xkbcommon >= 0.5.0" }
|
||||
{ "type": "pkgConfig", "args": "xkbcommon >= 0.5.0" },
|
||||
"-lxkbcommon"
|
||||
]
|
||||
},
|
||||
"xkbcommon_x11": {
|
||||
@ -774,7 +775,8 @@
|
||||
},
|
||||
"headers": [ "xkbcommon/xkbcommon-x11.h" ],
|
||||
"sources": [
|
||||
{ "type": "pkgConfig", "args": "xkbcommon-x11" }
|
||||
{ "type": "pkgConfig", "args": "xkbcommon-x11" },
|
||||
"-lxkbcommon -lxkbcommon-x11"
|
||||
]
|
||||
},
|
||||
"xrender": {
|
||||
|
@ -54,8 +54,8 @@ void Server::initSocket()
|
||||
udpSocket = new QUdpSocket(this);
|
||||
udpSocket->bind(QHostAddress::LocalHost, 7755);
|
||||
|
||||
connect(udpSocket, SIGNAL(readyRead()),
|
||||
this, SLOT(readPendingDatagrams()));
|
||||
connect(udpSocket, &QUdpSocket::readyRead,
|
||||
this, &Server::readPendingDatagrams);
|
||||
}
|
||||
|
||||
void Server::readPendingDatagrams()
|
||||
|
@ -39,8 +39,11 @@ qtConfig(dnslookup) {
|
||||
|
||||
unix {
|
||||
!integrity:qtConfig(dnslookup): SOURCES += kernel/qdnslookup_unix.cpp
|
||||
|
||||
SOURCES += kernel/qhostinfo_unix.cpp
|
||||
|
||||
qtConfig(dlopen): QMAKE_USE_PRIVATE += libdl
|
||||
|
||||
qtConfig(linux-netlink): SOURCES += kernel/qnetworkinterface_linux.cpp
|
||||
else: SOURCES += kernel/qnetworkinterface_unix.cpp
|
||||
}
|
||||
|
@ -59,6 +59,10 @@
|
||||
# include <gnu/lib-names.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen)
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -87,6 +91,18 @@ struct QDnsLookupStateDeleter
|
||||
}
|
||||
};
|
||||
|
||||
static QFunctionPointer resolveSymbol(QLibrary &lib, const char *sym)
|
||||
{
|
||||
if (lib.isLoaded())
|
||||
return lib.resolve(sym);
|
||||
|
||||
#if defined(RTLD_DEFAULT) && (defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen))
|
||||
return reinterpret_cast<QFunctionPointer>(dlsym(RTLD_DEFAULT, sym));
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool resolveLibraryInternal()
|
||||
{
|
||||
QLibrary lib;
|
||||
@ -96,31 +112,30 @@ static bool resolveLibraryInternal()
|
||||
#endif
|
||||
{
|
||||
lib.setFileName(QLatin1String("resolv"));
|
||||
if (!lib.load())
|
||||
return false;
|
||||
lib.load();
|
||||
}
|
||||
|
||||
local_dn_expand = dn_expand_proto(lib.resolve("__dn_expand"));
|
||||
local_dn_expand = dn_expand_proto(resolveSymbol(lib, "__dn_expand"));
|
||||
if (!local_dn_expand)
|
||||
local_dn_expand = dn_expand_proto(lib.resolve("dn_expand"));
|
||||
local_dn_expand = dn_expand_proto(resolveSymbol(lib, "dn_expand"));
|
||||
|
||||
local_res_nclose = res_nclose_proto(lib.resolve("__res_nclose"));
|
||||
local_res_nclose = res_nclose_proto(resolveSymbol(lib, "__res_nclose"));
|
||||
if (!local_res_nclose)
|
||||
local_res_nclose = res_nclose_proto(lib.resolve("res_9_nclose"));
|
||||
local_res_nclose = res_nclose_proto(resolveSymbol(lib, "res_9_nclose"));
|
||||
if (!local_res_nclose)
|
||||
local_res_nclose = res_nclose_proto(lib.resolve("res_nclose"));
|
||||
local_res_nclose = res_nclose_proto(resolveSymbol(lib, "res_nclose"));
|
||||
|
||||
local_res_ninit = res_ninit_proto(lib.resolve("__res_ninit"));
|
||||
local_res_ninit = res_ninit_proto(resolveSymbol(lib, "__res_ninit"));
|
||||
if (!local_res_ninit)
|
||||
local_res_ninit = res_ninit_proto(lib.resolve("res_9_ninit"));
|
||||
local_res_ninit = res_ninit_proto(resolveSymbol(lib, "res_9_ninit"));
|
||||
if (!local_res_ninit)
|
||||
local_res_ninit = res_ninit_proto(lib.resolve("res_ninit"));
|
||||
local_res_ninit = res_ninit_proto(resolveSymbol(lib, "res_ninit"));
|
||||
|
||||
local_res_nquery = res_nquery_proto(lib.resolve("__res_nquery"));
|
||||
local_res_nquery = res_nquery_proto(resolveSymbol(lib, "__res_nquery"));
|
||||
if (!local_res_nquery)
|
||||
local_res_nquery = res_nquery_proto(lib.resolve("res_9_nquery"));
|
||||
local_res_nquery = res_nquery_proto(resolveSymbol(lib, "res_9_nquery"));
|
||||
if (!local_res_nquery)
|
||||
local_res_nquery = res_nquery_proto(lib.resolve("res_nquery"));
|
||||
local_res_nquery = res_nquery_proto(resolveSymbol(lib, "res_nquery"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -66,6 +66,10 @@
|
||||
# include <gnu/lib-names.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen)
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// Almost always the same. If not, specify in qplatformdefs.h.
|
||||
@ -115,6 +119,18 @@ struct LibResolv
|
||||
};
|
||||
}
|
||||
|
||||
static QFunctionPointer resolveSymbol(QLibrary &lib, const char *sym)
|
||||
{
|
||||
if (lib.isLoaded())
|
||||
return lib.resolve(sym);
|
||||
|
||||
#if defined(RTLD_DEFAULT) && (defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen))
|
||||
return reinterpret_cast<QFunctionPointer>(dlsym(RTLD_DEFAULT, sym));
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
LibResolv::LibResolv()
|
||||
{
|
||||
QLibrary lib;
|
||||
@ -124,31 +140,30 @@ LibResolv::LibResolv()
|
||||
#endif
|
||||
{
|
||||
lib.setFileName(QLatin1String("resolv"));
|
||||
if (!lib.load())
|
||||
return;
|
||||
lib.load();
|
||||
}
|
||||
|
||||
// res_ninit is required for localDomainName()
|
||||
local_res_ninit = res_ninit_proto(lib.resolve("__res_ninit"));
|
||||
local_res_ninit = res_ninit_proto(resolveSymbol(lib, "__res_ninit"));
|
||||
if (!local_res_ninit)
|
||||
local_res_ninit = res_ninit_proto(lib.resolve("res_ninit"));
|
||||
local_res_ninit = res_ninit_proto(resolveSymbol(lib, "res_ninit"));
|
||||
if (local_res_ninit) {
|
||||
// we must now find res_nclose
|
||||
local_res_nclose = res_nclose_proto(lib.resolve("res_nclose"));
|
||||
local_res_nclose = res_nclose_proto(resolveSymbol(lib, "res_nclose"));
|
||||
if (!local_res_nclose)
|
||||
local_res_nclose = res_nclose_proto(lib.resolve("__res_nclose"));
|
||||
local_res_nclose = res_nclose_proto(resolveSymbol(lib, "__res_nclose"));
|
||||
if (!local_res_nclose)
|
||||
local_res_ninit = nullptr;
|
||||
}
|
||||
|
||||
if (ReinitNecessary || !local_res_ninit) {
|
||||
local_res_init = res_init_proto(lib.resolve("__res_init"));
|
||||
local_res_init = res_init_proto(resolveSymbol(lib, "__res_init"));
|
||||
if (!local_res_init)
|
||||
local_res_init = res_init_proto(lib.resolve("res_init"));
|
||||
local_res_init = res_init_proto(resolveSymbol(lib, "res_init"));
|
||||
|
||||
if (local_res_init && !local_res_ninit) {
|
||||
// if we can't get a thread-safe context, we have to use the global _res state
|
||||
local_res = res_state_ptr(lib.resolve("_res"));
|
||||
local_res = res_state_ptr(resolveSymbol(lib, "_res"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -381,6 +381,7 @@ qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddre
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 5.8
|
||||
\overload
|
||||
|
||||
Sends the datagram \a datagram to the host address and port numbers
|
||||
@ -431,6 +432,8 @@ qint64 QUdpSocket::writeDatagram(const QNetworkDatagram &datagram)
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.8
|
||||
|
||||
Receives a datagram no larger than \a maxSize bytes and returns it in the
|
||||
QNetworkDatagram object, along with the sender's host address and port. If
|
||||
possible, this function will also try to determine the datagram's
|
||||
|
@ -878,8 +878,6 @@ void QWidgetWindow::handleDragEnterEvent(QDragEnterEvent *event, QWidget *widget
|
||||
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
|
||||
QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(),
|
||||
event->mouseButtons(), event->keyboardModifiers());
|
||||
translated.setDropAction(event->dropAction());
|
||||
translated.setAccepted(event->isAccepted());
|
||||
QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
|
||||
event->setAccepted(translated.isAccepted());
|
||||
event->setDropAction(translated.dropAction());
|
||||
|
@ -539,8 +539,13 @@ void tst_QTimeZone::checkOffset_data()
|
||||
int year, month, day, hour, min, sec;
|
||||
int std, dst;
|
||||
} table[] = {
|
||||
// Zone with no transitions (QTBUG-74614, when TZ backend uses minimalist data)
|
||||
// Zone with no transitions (QTBUG-74614, QTBUG-74666, when TZ backend uses minimal data)
|
||||
{ "Etc/UTC", "epoch", 1970, 1, 1, 0, 0, 0, 0, 0 },
|
||||
{ "Etc/UTC", "pre_int32", 1901, 12, 13, 20, 45, 51, 0, 0 },
|
||||
{ "Etc/UTC", "post_int32", 2038, 1, 19, 3, 14, 9, 0, 0 },
|
||||
{ "Etc/UTC", "post_uint32", 2106, 2, 7, 6, 28, 17, 0, 0 },
|
||||
{ "Etc/UTC", "initial", -292275056, 5, 16, 16, 47, 5, 0, 0 },
|
||||
{ "Etc/UTC", "final", 292278994, 8, 17, 7, 12, 55, 0, 0 },
|
||||
// Kiev: regression test for QTBUG-64122 (on MS):
|
||||
{ "Europe/Kiev", "summer", 2017, 10, 27, 12, 0, 0, 2 * 3600, 3600 },
|
||||
{ "Europe/Kiev", "winter", 2017, 10, 29, 12, 0, 0, 2 * 3600, 0 }
|
||||
|
@ -46,6 +46,9 @@
|
||||
#include <private/qwindow_p.h>
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <qpa/qplatformdrag.h>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
|
||||
#include <QtTest/private/qtesthelpers_p.h>
|
||||
|
||||
@ -87,6 +90,7 @@ private slots:
|
||||
#if QT_CONFIG(draganddrop)
|
||||
void tst_dnd();
|
||||
void tst_dnd_events();
|
||||
void tst_dnd_propagation();
|
||||
#endif
|
||||
|
||||
void tst_qtbug35600();
|
||||
@ -744,6 +748,77 @@ void tst_QWidget_window::tst_dnd_events()
|
||||
|
||||
QCOMPARE(dndWidget._dndEvents, expectedDndEvents);
|
||||
}
|
||||
|
||||
class DropTarget : public QWidget
|
||||
{
|
||||
public:
|
||||
explicit DropTarget()
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
|
||||
const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
|
||||
auto width = availableGeometry.width() / 6;
|
||||
auto height = availableGeometry.height() / 4;
|
||||
|
||||
setGeometry(availableGeometry.x() + 200, availableGeometry.y() + 200, width, height);
|
||||
|
||||
QLabel *label = new QLabel(QStringLiteral("Test"), this);
|
||||
label->setGeometry(40, 40, 60, 60);
|
||||
label->setAcceptDrops(true);
|
||||
}
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event) override
|
||||
{
|
||||
event->accept();
|
||||
mDndEvents.append("enter ");
|
||||
}
|
||||
|
||||
void dragMoveEvent(QDragMoveEvent *event) override
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void dragLeaveEvent(QDragLeaveEvent *) override
|
||||
{
|
||||
mDndEvents.append("leave ");
|
||||
}
|
||||
|
||||
void dropEvent(QDropEvent *event) override
|
||||
{
|
||||
event->accept();
|
||||
mDndEvents.append("drop ");
|
||||
}
|
||||
|
||||
QString mDndEvents;
|
||||
};
|
||||
|
||||
void tst_QWidget_window::tst_dnd_propagation()
|
||||
{
|
||||
QMimeData mimeData;
|
||||
mimeData.setText(QLatin1String("testmimetext"));
|
||||
|
||||
DropTarget target;
|
||||
target.show();
|
||||
QVERIFY(QTest::qWaitForWindowActive(&target));
|
||||
|
||||
Qt::DropActions supportedActions = Qt::DropAction::CopyAction;
|
||||
QWindow *window = target.windowHandle();
|
||||
|
||||
auto posInsideDropTarget = QHighDpi::toNativePixels(QPoint(20, 20), window->screen());
|
||||
auto posInsideLabel = QHighDpi::toNativePixels(QPoint(60, 60), window->screen());
|
||||
|
||||
// Enter DropTarget.
|
||||
QWindowSystemInterface::handleDrag(window, &mimeData, posInsideDropTarget, supportedActions, 0, 0);
|
||||
// Enter QLabel. This will propagate because default QLabel does
|
||||
// not accept the drop event in dragEnterEvent().
|
||||
QWindowSystemInterface::handleDrag(window, &mimeData, posInsideLabel, supportedActions, 0, 0);
|
||||
// Drop on QLabel. DropTarget will get dropEvent(), because it accepted the event.
|
||||
QWindowSystemInterface::handleDrop(window, &mimeData, posInsideLabel, supportedActions, 0, 0);
|
||||
|
||||
QGuiApplication::processEvents();
|
||||
|
||||
QCOMPARE(target.mDndEvents, "enter leave enter drop ");
|
||||
}
|
||||
#endif
|
||||
|
||||
void tst_QWidget_window::tst_qtbug35600()
|
||||
|
Loading…
x
Reference in New Issue
Block a user