Submitted By: Pierre Labastie
Date: 2023-06-12
Initial Package Version: 5.15.10
Upstream Status: Applied (according to KDE)
Origin: KDE patch set
Description: Patch set maintained by the KDE folks
see https://dot.kde.org/2021/04/06/announcing-kdes-qt-5-patch-collection
Patch generated using the procedure in
https://wiki.linuxfromscratch.org/blfs/ticket/17476#comment:3
Submodule qtbase 29400a68..e8d9e68d:
diff --git a/qtbase/doc/global/html-footer.qdocconf b/qtbase/doc/global/html-footer.qdocconf
index 673e500291..f799534c58 100644
--- a/qtbase/doc/global/html-footer.qdocconf
+++ b/qtbase/doc/global/html-footer.qdocconf
@@ -14,7 +14,7 @@ HTML.footer = \
" The documentation provided herein is licensed under the terms of the" \
" GNU Free Documentation" \
" License version 1.3 as published by the Free Software Foundation. " \
- " Qt and respective logos are trademarks of The Qt Company Ltd. " \
- " in Finland and/or other countries worldwide. All other trademarks are property\n" \
- " of their respective owners.
\n" \
+ " Qt and respective logos are " \
+ " trademarks of The Qt Company Ltd. in Finland and/or other countries\n" \
+ " worldwide. All other trademarks are property of their respective owners. \n" \
"\n" \
diff --git a/qtbase/doc/global/qt-module-defaults-online.qdocconf b/qtbase/doc/global/qt-module-defaults-online.qdocconf
index 635caf0b94..b35790e2d8 100644
--- a/qtbase/doc/global/qt-module-defaults-online.qdocconf
+++ b/qtbase/doc/global/qt-module-defaults-online.qdocconf
@@ -11,9 +11,9 @@ HTML.footer = \
" The documentation provided herein is licensed under the terms of the" \
" GNU Free Documentation" \
" License version 1.3 as published by the Free Software Foundation. " \
- " Qt and respective logos are trademarks of The Qt Company Ltd. " \
- " in Finland and/or other countries worldwide. All other trademarks are property\n" \
- " of their respective owners. \n"
+ " Qt and respective logos are " \
+ " trademarks of The Qt Company Ltd. in Finland and/or other countries\n" \
+ " worldwide. All other trademarks are property of their respective owners. \n"
#include standard set of macros and C++ defines and ignores
include(macros.qdocconf)
diff --git a/qtbase/mkspecs/common/android/qplatformdefs.h b/qtbase/mkspecs/common/android/qplatformdefs.h
index f75bc4093b..2bd59410d4 100644
--- a/qtbase/mkspecs/common/android/qplatformdefs.h
+++ b/qtbase/mkspecs/common/android/qplatformdefs.h
@@ -144,11 +144,7 @@
#define QT_SIGNAL_ARGS int
#define QT_SIGNAL_IGNORE SIG_IGN
-#if defined(__GLIBC__) && (__GLIBC__ >= 2)
#define QT_SOCKLEN_T socklen_t
-#else
-#define QT_SOCKLEN_T int
-#endif
#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
#define QT_SNPRINTF ::snprintf
diff --git a/qtbase/mkspecs/linux-clang/qplatformdefs.h b/qtbase/mkspecs/linux-clang/qplatformdefs.h
index a818d973f0..c1ab72fbc6 100644
--- a/qtbase/mkspecs/linux-clang/qplatformdefs.h
+++ b/qtbase/mkspecs/linux-clang/qplatformdefs.h
@@ -79,14 +79,6 @@
#define QT_USE_XOPEN_LFS_EXTENSIONS
#include "../common/posix/qplatformdefs.h"
-#undef QT_SOCKLEN_T
-
-#if defined(__GLIBC__) && (__GLIBC__ >= 2)
-#define QT_SOCKLEN_T socklen_t
-#else
-#define QT_SOCKLEN_T int
-#endif
-
#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
#define QT_SNPRINTF ::snprintf
#define QT_VSNPRINTF ::vsnprintf
diff --git a/qtbase/mkspecs/linux-g++/qplatformdefs.h b/qtbase/mkspecs/linux-g++/qplatformdefs.h
index 13523f0702..4d2750d9ec 100644
--- a/qtbase/mkspecs/linux-g++/qplatformdefs.h
+++ b/qtbase/mkspecs/linux-g++/qplatformdefs.h
@@ -79,14 +79,6 @@
#define QT_USE_XOPEN_LFS_EXTENSIONS
#include "../common/posix/qplatformdefs.h"
-#undef QT_SOCKLEN_T
-
-#if defined(__GLIBC__) && (__GLIBC__ < 2)
-#define QT_SOCKLEN_T int
-#else
-#define QT_SOCKLEN_T socklen_t
-#endif
-
#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
#define QT_SNPRINTF ::snprintf
#define QT_VSNPRINTF ::vsnprintf
diff --git a/qtbase/mkspecs/linux-llvm/qplatformdefs.h b/qtbase/mkspecs/linux-llvm/qplatformdefs.h
index dc750ab1ef..d3cc39b47f 100644
--- a/qtbase/mkspecs/linux-llvm/qplatformdefs.h
+++ b/qtbase/mkspecs/linux-llvm/qplatformdefs.h
@@ -80,14 +80,6 @@
#define QT_USE_XOPEN_LFS_EXTENSIONS
#include "../common/posix/qplatformdefs.h"
-#undef QT_SOCKLEN_T
-
-#if defined(__GLIBC__) && (__GLIBC__ >= 2)
-#define QT_SOCKLEN_T socklen_t
-#else
-#define QT_SOCKLEN_T int
-#endif
-
#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
#define QT_SNPRINTF ::snprintf
#define QT_VSNPRINTF ::vsnprintf
diff --git a/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h b/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h
index 4c4e53da2a..83baffb3e3 100644
--- a/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h
+++ b/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h
@@ -85,16 +85,9 @@
#include "../common/posix/qplatformdefs.h"
#undef QT_OPEN_LARGEFILE
-#undef QT_SOCKLEN_T
#define QT_OPEN_LARGEFILE 0
-#if defined(__GLIBC__) && (__GLIBC__ >= 2)
-#define QT_SOCKLEN_T socklen_t
-#else
-#define QT_SOCKLEN_T int
-#endif
-
#ifndef SIOCGIFBRDADDR
# define SIOCGIFBRDADDR 0x8919
#endif
diff --git a/qtbase/mkspecs/lynxos-g++/qplatformdefs.h b/qtbase/mkspecs/lynxos-g++/qplatformdefs.h
index 4339ea2b23..6007af0055 100644
--- a/qtbase/mkspecs/lynxos-g++/qplatformdefs.h
+++ b/qtbase/mkspecs/lynxos-g++/qplatformdefs.h
@@ -72,14 +72,6 @@
#include "../common/posix/qplatformdefs.h"
-#undef QT_SOCKLEN_T
-
-#if defined(__GLIBC__) && (__GLIBC__ >= 2)
-#define QT_SOCKLEN_T socklen_t
-#else
-#define QT_SOCKLEN_T int
-#endif
-
#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
#define QT_SNPRINTF ::snprintf
#define QT_VSNPRINTF ::vsnprintf
diff --git a/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp b/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
index c3c184258f..32af3f8f29 100644
--- a/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
+++ b/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
@@ -10,6 +10,7 @@
#include "libANGLE/HandleAllocator.h"
#include
+#include
#include "common/debug.h"
diff --git a/qtbase/src/3rdparty/forkfd/forkfd_linux.c b/qtbase/src/3rdparty/forkfd/forkfd_linux.c
index ffe0e9a5e2..b1f5408d11 100644
--- a/qtbase/src/3rdparty/forkfd/forkfd_linux.c
+++ b/qtbase/src/3rdparty/forkfd/forkfd_linux.c
@@ -82,7 +82,8 @@ static int sys_clone(unsigned long cloneflags, int *ptid)
return syscall(__NR_clone, cloneflags, child_stack, stack_size, ptid, newtls, ctid);
#elif defined(__arc__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
defined(__nds32__) || defined(__hppa__) || defined(__powerpc__) || defined(__i386__) || \
- defined(__x86_64__) || defined(__xtensa__) || defined(__alpha__) || defined(__riscv)
+ defined(__x86_64__) || defined(__xtensa__) || defined(__alpha__) || defined(__riscv) || \
+ defined(__loongarch__)
/* ctid and newtls are inverted on CONFIG_CLONE_BACKWARDS architectures,
* but since both values are 0, there's no harm. */
return syscall(__NR_clone, cloneflags, child_stack, ptid, ctid, newtls);
diff --git a/qtbase/src/concurrent/qtconcurrentreducekernel.h b/qtbase/src/concurrent/qtconcurrentreducekernel.h
index 8f9a938952..a98dedef2e 100644
--- a/qtbase/src/concurrent/qtconcurrentreducekernel.h
+++ b/qtbase/src/concurrent/qtconcurrentreducekernel.h
@@ -212,11 +212,13 @@ public:
inline bool shouldThrottle()
{
+ std::lock_guard locker(mutex);
return (resultsMapSize > (ReduceQueueThrottleLimit * threadCount));
}
inline bool shouldStartThread()
{
+ std::lock_guard locker(mutex);
return (resultsMapSize <= (ReduceQueueStartLimit * threadCount));
}
};
diff --git a/qtbase/src/concurrent/qtconcurrentthreadengine.cpp b/qtbase/src/concurrent/qtconcurrentthreadengine.cpp
index ea6ce3ac42..7f91a2ba68 100644
--- a/qtbase/src/concurrent/qtconcurrentthreadengine.cpp
+++ b/qtbase/src/concurrent/qtconcurrentthreadengine.cpp
@@ -176,6 +176,39 @@ void ThreadEngineBase::startSingleThreaded()
finish();
}
+void ThreadEngineBase::startBlocking()
+{
+ start();
+ barrier.acquire();
+ startThreads();
+
+ bool throttled = false;
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ while (threadFunction() == ThrottleThread) {
+ if (threadThrottleExit()) {
+ throttled = true;
+ break;
+ }
+ }
+#ifndef QT_NO_EXCEPTIONS
+ } catch (QException &e) {
+ handleException(e);
+ } catch (...) {
+ handleException(QUnhandledException());
+ }
+#endif
+
+ if (throttled == false) {
+ barrier.release();
+ }
+
+ barrier.wait();
+ finish();
+ exceptionStore.throwPossibleException();
+}
+
void ThreadEngineBase::startThread()
{
startThreadInternal();
diff --git a/qtbase/src/concurrent/qtconcurrentthreadengine.h b/qtbase/src/concurrent/qtconcurrentthreadengine.h
index 7c30cebdbc..a4c8548cc4 100644
--- a/qtbase/src/concurrent/qtconcurrentthreadengine.h
+++ b/qtbase/src/concurrent/qtconcurrentthreadengine.h
@@ -91,6 +91,7 @@ public:
ThreadEngineBase();
virtual ~ThreadEngineBase();
void startSingleThreaded();
+ void startBlocking();
void startThread();
bool isCanceled();
void waitForResume();
@@ -143,6 +144,15 @@ public:
return result();
}
+ // Runs the user algorithm using multiple threads.
+ // This function blocks until the algorithm is finished,
+ // and then returns the result.
+ T *startBlocking()
+ {
+ ThreadEngineBase::startBlocking();
+ return result();
+ }
+
// Runs the user algorithm using multiple threads.
// Does not block, returns a future.
QFuture startAsynchronously()
@@ -223,6 +233,13 @@ class ThreadEngineStarter : public ThreadEngineStarterBase
public:
ThreadEngineStarter(TypedThreadEngine *eng)
: Base(eng) { }
+
+ T startBlocking()
+ {
+ T t = *this->threadEngine->startBlocking();
+ delete this->threadEngine;
+ return t;
+ }
};
// Full template specialization where T is void.
@@ -232,6 +249,12 @@ class ThreadEngineStarter : public ThreadEngineStarterBase
public:
ThreadEngineStarter(ThreadEngine *_threadEngine)
: ThreadEngineStarterBase(_threadEngine) {}
+
+ void startBlocking()
+ {
+ this->threadEngine->startBlocking();
+ delete this->threadEngine;
+ }
};
//! [qtconcurrentthreadengine-1]
diff --git a/qtbase/src/corelib/global/qglobal.cpp b/qtbase/src/corelib/global/qglobal.cpp
index ac2e85c51e..f46a6f68ad 100644
--- a/qtbase/src/corelib/global/qglobal.cpp
+++ b/qtbase/src/corelib/global/qglobal.cpp
@@ -97,6 +97,10 @@
# include
#endif
+#if defined(Q_OS_MACOS)
+#include
+#endif
+
#ifdef Q_OS_UNIX
#include
#include
@@ -2133,6 +2137,15 @@ QT_WARNING_POP
static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
{
#ifdef Q_OS_MACOS
+ if (version.majorVersion() == 13)
+ return "Ventura";
+ if (version.majorVersion() == 12)
+ return "Monterey";
+ // Compare against predefined constant to handle 10.16/11.0
+ if (QVersionNumber(QOperatingSystemVersion::MacOSBigSur.majorVersion(),
+ QOperatingSystemVersion::MacOSBigSur.minorVersion(), QOperatingSystemVersion::MacOSBigSur.microVersion()).isPrefixOf(
+ QVersionNumber(version.majorVersion(), version.minorVersion(), version.microVersion())))
+ return "Big Sur";
if (version.majorVersion() == 10) {
switch (version.minorVersion()) {
case 9:
@@ -2147,13 +2160,15 @@ static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSyst
return "High Sierra";
case 14:
return "Mojave";
+ case 15:
+ return "Catalina";
}
}
// unknown, future version
#else
Q_UNUSED(version);
#endif
- return 0;
+ return nullptr;
}
#endif
@@ -2278,7 +2293,7 @@ static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSyst
}
#undef Q_WINVER
// unknown, future version
- return 0;
+ return nullptr;
}
#endif
diff --git a/qtbase/src/corelib/global/qnamespace.h b/qtbase/src/corelib/global/qnamespace.h
index ad4150b317..bf19b1627b 100644
--- a/qtbase/src/corelib/global/qnamespace.h
+++ b/qtbase/src/corelib/global/qnamespace.h
@@ -1864,7 +1864,7 @@ public:
QT_Q_ENUM(TimerType)
QT_Q_ENUM(ScrollPhase)
QT_Q_ENUM(MouseEventSource)
- QT_Q_FLAG(MouseEventFlag)
+ QT_Q_FLAG(MouseEventFlags)
QT_Q_ENUM(ChecksumType)
QT_Q_ENUM(HighDpiScaleFactorRoundingPolicy)
QT_Q_ENUM(TabFocusBehavior)
diff --git a/qtbase/src/corelib/io/qfilesystemengine_win.cpp b/qtbase/src/corelib/io/qfilesystemengine_win.cpp
index 81d3a71986..c86ed1f9b0 100644
--- a/qtbase/src/corelib/io/qfilesystemengine_win.cpp
+++ b/qtbase/src/corelib/io/qfilesystemengine_win.cpp
@@ -664,14 +664,14 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
return QFileSystemEntry(ret, QFileSystemEntry::FromInternalPath());
}
-#if defined(Q_CC_MINGW) && WINVER < 0x0602 // Windows 8 onwards
+#if defined(Q_CC_MINGW) && WINVER < 0x0602 && _WIN32_WINNT < _WIN32_WINNT_WIN8 // Windows 8 onwards
typedef struct _FILE_ID_INFO {
ULONGLONG VolumeSerialNumber;
FILE_ID_128 FileId;
} FILE_ID_INFO, *PFILE_ID_INFO;
-#endif // if defined (Q_CC_MINGW) && WINVER < 0x0602
+#endif // if defined(Q_CC_MINGW) && WINVER < 0x0602 && _WIN32_WINNT < _WIN32_WINNT_WIN8
// File ID for Windows up to version 7 and FAT32 drives
static inline QByteArray fileId(HANDLE handle)
diff --git a/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp b/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp
index 94d9d06bcb..27e0b13b0b 100644
--- a/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -366,7 +366,9 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
// qDebug("QInotifyFileSystemWatcherEngine::readFromInotify");
int buffSize = 0;
- ioctl(inotifyFd, FIONREAD, (char *) &buffSize);
+ if (ioctl(inotifyFd, FIONREAD, (char *) &buffSize) == -1 || buffSize == 0)
+ return;
+
QVarLengthArray buffer(buffSize);
buffSize = read(inotifyFd, buffer.data(), buffSize);
char *at = buffer.data();
diff --git a/qtbase/src/corelib/io/qfsfileengine.cpp b/qtbase/src/corelib/io/qfsfileengine.cpp
index 3042eac2f0..a862ce9166 100644
--- a/qtbase/src/corelib/io/qfsfileengine.cpp
+++ b/qtbase/src/corelib/io/qfsfileengine.cpp
@@ -361,7 +361,7 @@ bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode, int fd)
// Seek to the end when in Append mode.
if (openMode & QFile::Append) {
- int ret;
+ QT_OFF_T ret;
do {
ret = QT_LSEEK(fd, 0, SEEK_END);
} while (ret == -1 && errno == EINTR);
diff --git a/qtbase/src/corelib/io/qfsfileengine_unix.cpp b/qtbase/src/corelib/io/qfsfileengine_unix.cpp
index 4610e9306c..65e921c15a 100644
--- a/qtbase/src/corelib/io/qfsfileengine_unix.cpp
+++ b/qtbase/src/corelib/io/qfsfileengine_unix.cpp
@@ -141,7 +141,7 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
// Seek to the end when in Append mode.
if (flags & QFile::Append) {
- int ret;
+ QT_OFF_T ret;
do {
ret = QT_LSEEK(fd, 0, SEEK_END);
} while (ret == -1 && errno == EINTR);
diff --git a/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 3d7fe43cd3..f2871a2da7 100644
--- a/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -939,8 +939,9 @@ void QSortFilterProxyModelPrivate::insert_source_items(
q->beginInsertColumns(proxy_parent, proxy_start, proxy_end);
}
- for (int i = 0; i < source_items.size(); ++i)
- proxy_to_source.insert(proxy_start + i, source_items.at(i));
+ // TODO: use the range QList::insert() overload once it is implemented (QTBUG-58633).
+ proxy_to_source.insert(proxy_start, source_items.size(), 0);
+ std::copy(source_items.cbegin(), source_items.cend(), proxy_to_source.begin() + proxy_start);
build_source_to_proxy_mapping(proxy_to_source, source_to_proxy);
@@ -3131,8 +3132,9 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &
if (d->filter_data.isEmpty())
return true;
+
+ int column_count = d->model->columnCount(source_parent);
if (d->filter_column == -1) {
- int column_count = d->model->columnCount(source_parent);
for (int column = 0; column < column_count; ++column) {
QModelIndex source_index = d->model->index(source_row, column, source_parent);
QString key = d->model->data(source_index, d->filter_role).toString();
@@ -3141,9 +3143,10 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &
}
return false;
}
- QModelIndex source_index = d->model->index(source_row, d->filter_column, source_parent);
- if (!source_index.isValid()) // the column may not exist
+
+ if (d->filter_column >= column_count) // the column may not exist
return true;
+ QModelIndex source_index = d->model->index(source_row, d->filter_column, source_parent);
QString key = d->model->data(source_index, d->filter_role).toString();
return d->filter_data.hasMatch(key);
}
diff --git a/qtbase/src/corelib/kernel/qcoreapplication.cpp b/qtbase/src/corelib/kernel/qcoreapplication.cpp
index 2a2dcc72ca..d671f70bd3 100644
--- a/qtbase/src/corelib/kernel/qcoreapplication.cpp
+++ b/qtbase/src/corelib/kernel/qcoreapplication.cpp
@@ -1157,7 +1157,7 @@ static bool doNotify(QObject *receiver, QEvent *event)
bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
{
// We can't access the application event filters outside of the main thread (race conditions)
- Q_ASSERT(receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread());
+ Q_ASSERT(receiver->d_func()->threadData.loadAcquire()->thread.loadRelaxed() == mainThread());
if (extraData) {
// application event filters are only called for objects in the GUI thread
diff --git a/qtbase/src/corelib/kernel/qobject.cpp b/qtbase/src/corelib/kernel/qobject.cpp
index d57bcc31cc..4fccf8dd56 100644
--- a/qtbase/src/corelib/kernel/qobject.cpp
+++ b/qtbase/src/corelib/kernel/qobject.cpp
@@ -1010,7 +1010,7 @@ QObject::~QObject()
emit destroyed(this);
}
- if (d->declarativeData) {
+ if (!d->isDeletingChildren && d->declarativeData) {
if (static_cast(d->declarativeData)->ownedByQml1) {
if (QAbstractDeclarativeData::destroyed_qml1)
QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
@@ -1580,7 +1580,7 @@ void QObject::moveToThread(QThread *targetThread)
QThreadData *currentData = QThreadData::current();
QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr;
- QThreadData *thisThreadData = d->threadData.loadRelaxed();
+ QThreadData *thisThreadData = d->threadData.loadAcquire();
if (!thisThreadData->thread.loadAcquire() && currentData == targetData) {
// one exception to the rule: we allow moving objects with no thread affinity to the current thread
currentData = d->threadData;
@@ -2622,7 +2622,7 @@ int QObject::receivers(const char *signal) const
if (!d->isSignalConnected(signal_index))
return receivers;
- if (d->declarativeData && QAbstractDeclarativeData::receivers) {
+ if (!d->isDeletingChildren && d->declarativeData && QAbstractDeclarativeData::receivers) {
receivers += QAbstractDeclarativeData::receivers(d->declarativeData, this,
signal_index);
}
diff --git a/qtbase/src/corelib/kernel/qobject_p.h b/qtbase/src/corelib/kernel/qobject_p.h
index 0b827a52ca..13ffb88999 100644
--- a/qtbase/src/corelib/kernel/qobject_p.h
+++ b/qtbase/src/corelib/kernel/qobject_p.h
@@ -444,7 +444,7 @@ inline void QObjectPrivate::checkForIncompatibleLibraryVersion(int version) cons
inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const
{
- return declarativeData && QAbstractDeclarativeData::isSignalConnected
+ return !isDeletingChildren && declarativeData && QAbstractDeclarativeData::isSignalConnected
&& QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index);
}
diff --git a/qtbase/src/corelib/kernel/qtranslator.cpp b/qtbase/src/corelib/kernel/qtranslator.cpp
index 2812ffb7ea..bc0177c5ec 100644
--- a/qtbase/src/corelib/kernel/qtranslator.cpp
+++ b/qtbase/src/corelib/kernel/qtranslator.cpp
@@ -902,7 +902,7 @@ static QString getMessage(const uchar *m, const uchar *end, const char *context,
goto end;
case Tag_Translation: {
int len = read32(m);
- if (len % 1)
+ if (len & 1)
return QString();
m += 4;
if (!numerus--) {
diff --git a/qtbase/src/corelib/mimetypes/qmimedatabase.cpp b/qtbase/src/corelib/mimetypes/qmimedatabase.cpp
index 9de22cef33..ff868a3268 100644
--- a/qtbase/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/qtbase/src/corelib/mimetypes/qmimedatabase.cpp
@@ -389,20 +389,23 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
// Disambiguate conflicting extensions (if magic matching found something)
if (candidateByData.isValid() && magicAccuracy > 0) {
const QString sniffedMime = candidateByData.name();
- // If the sniffedMime matches a glob match, use it
+ // If the sniffedMime matches a highest-weight glob match, use it
if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) {
*accuracyPtr = 100;
return candidateByData;
}
- for (const QString &m : qAsConst(candidatesByName.m_matchingMimeTypes)) {
+ for (const QString &m : qAsConst(candidatesByName.m_allMatchingMimeTypes)) {
if (inherits(m, sniffedMime)) {
// We have magic + pattern pointing to this, so it's a pretty good match
*accuracyPtr = 100;
return mimeTypeForName(m);
}
}
- *accuracyPtr = magicAccuracy;
- return candidateByData;
+ if (candidatesByName.m_allMatchingMimeTypes.isEmpty()) {
+ // No glob, use magic
+ *accuracyPtr = magicAccuracy;
+ return candidateByData;
+ }
}
}
diff --git a/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp b/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp
index b1de8907b2..fa8f4c545d 100644
--- a/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp
+++ b/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp
@@ -83,7 +83,10 @@ void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const Q
}
if (!m_matchingMimeTypes.contains(mimeType)) {
m_matchingMimeTypes.append(mimeType);
- m_allMatchingMimeTypes.append(mimeType);
+ if (replace)
+ m_allMatchingMimeTypes.prepend(mimeType); // highest-weight first
+ else
+ m_allMatchingMimeTypes.append(mimeType);
m_knownSuffixLength = knownSuffixLength;
}
}
diff --git a/qtbase/src/corelib/mimetypes/qmimeprovider.cpp b/qtbase/src/corelib/mimetypes/qmimeprovider.cpp
index 258dddf8cb..4642d0f2d0 100644
--- a/qtbase/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/qtbase/src/corelib/mimetypes/qmimeprovider.cpp
@@ -244,15 +244,18 @@ void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobM
const QString lowerFileName = fileName.toLower();
// Check literals (e.g. "Makefile")
matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosLiteralListOffset), fileName);
- // Check complex globs (e.g. "callgrind.out[0-9]*")
- matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName);
// Check the very common *.txt cases with the suffix tree
- const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset);
- const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
- const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
- matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false);
+ if (result.m_matchingMimeTypes.isEmpty()) {
+ const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset);
+ const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
+ const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
+ matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false);
+ if (result.m_matchingMimeTypes.isEmpty())
+ matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true);
+ }
+ // Check complex globs (e.g. "callgrind.out[0-9]*" or "README*")
if (result.m_matchingMimeTypes.isEmpty())
- matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true);
+ matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName);
}
void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName)
diff --git a/qtbase/src/corelib/serialization/qcborvalue.cpp b/qtbase/src/corelib/serialization/qcborvalue.cpp
index 89a928d348..3a8c2cb9ec 100644
--- a/qtbase/src/corelib/serialization/qcborvalue.cpp
+++ b/qtbase/src/corelib/serialization/qcborvalue.cpp
@@ -2123,7 +2123,8 @@ QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
Q_ASSERT(n == -1 || container == nullptr);
if (n < 0)
dd = container;
- return dd ? QCborArray(*dd) : defaultValue;
+ // return QCborArray(*dd); but that's UB if dd is nullptr
+ return dd ? QCborArray(*dd) : QCborArray();
}
/*!
@@ -2165,7 +2166,8 @@ QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
Q_ASSERT(n == -1 || container == nullptr);
if (n < 0)
dd = container;
- return dd ? QCborMap(*dd) : defaultValue;
+ // return QCborMap(*dd); but that's UB if dd is nullptr
+ return dd ? QCborMap(*dd) : QCborMap();
}
/*!
diff --git a/qtbase/src/corelib/text/qstringiterator_p.h b/qtbase/src/corelib/text/qstringiterator_p.h
index 219589b6e4..1d0c66cc78 100644
--- a/qtbase/src/corelib/text/qstringiterator_p.h
+++ b/qtbase/src/corelib/text/qstringiterator_p.h
@@ -61,6 +61,8 @@ class QStringIterator
{
QString::const_iterator i, pos, e;
Q_STATIC_ASSERT((std::is_same::value));
+ static bool less(const QChar *lhs, const QChar *rhs) noexcept
+ { return std::less{}(lhs, rhs); }
public:
explicit QStringIterator(QStringView string, qsizetype idx = 0)
: i(string.begin()),
@@ -95,7 +97,8 @@ public:
inline void setPosition(QString::const_iterator position)
{
- Q_ASSERT_X(i <= position && position <= e, Q_FUNC_INFO, "position out of bounds");
+ Q_ASSERT_X(!less(position, i) && !less(e, position),
+ Q_FUNC_INFO, "position out of bounds");
pos = position;
}
@@ -103,7 +106,7 @@ public:
inline bool hasNext() const
{
- return pos < e;
+ return less(pos, e);
}
inline void advance()
@@ -120,16 +123,20 @@ public:
{
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
- if (Q_UNLIKELY((pos++)->isHighSurrogate()))
+ if (Q_UNLIKELY((pos++)->isHighSurrogate())) {
+ Q_ASSERT(hasNext() && pos->isLowSurrogate());
++pos;
+ }
}
inline uint peekNextUnchecked() const
{
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
- if (Q_UNLIKELY(pos->isHighSurrogate()))
+ if (Q_UNLIKELY(pos->isHighSurrogate())) {
+ Q_ASSERT(less(pos + 1, e) && pos[1].isLowSurrogate());
return QChar::surrogateToUcs4(pos[0], pos[1]);
+ }
return pos->unicode();
}
@@ -155,8 +162,10 @@ public:
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
const QChar cur = *pos++;
- if (Q_UNLIKELY(cur.isHighSurrogate()))
+ if (Q_UNLIKELY(cur.isHighSurrogate())) {
+ Q_ASSERT(hasNext() && pos->isLowSurrogate());
return QChar::surrogateToUcs4(cur, *pos++);
+ }
return cur.unicode();
}
@@ -166,7 +175,7 @@ public:
const QChar uc = *pos++;
if (Q_UNLIKELY(uc.isSurrogate())) {
- if (Q_LIKELY(uc.isHighSurrogate() && pos < e && pos->isLowSurrogate()))
+ if (Q_LIKELY(uc.isHighSurrogate() && hasNext() && pos->isLowSurrogate()))
return QChar::surrogateToUcs4(uc, *pos++);
return invalidAs;
}
@@ -178,7 +187,7 @@ public:
inline bool hasPrevious() const
{
- return pos > i;
+ return less(i, pos);
}
inline void recede()
@@ -196,16 +205,20 @@ public:
{
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
- if (Q_UNLIKELY((--pos)->isLowSurrogate()))
+ if (Q_UNLIKELY((--pos)->isLowSurrogate())) {
+ Q_ASSERT(hasPrevious() && pos[-1].isHighSurrogate());
--pos;
+ }
}
inline uint peekPreviousUnchecked() const
{
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
- if (Q_UNLIKELY(pos[-1].isLowSurrogate()))
+ if (Q_UNLIKELY(pos[-1].isLowSurrogate())) {
+ Q_ASSERT(less(i + 1, pos) && pos[-2].isHighSurrogate());
return QChar::surrogateToUcs4(pos[-2], pos[-1]);
+ }
return pos[-1].unicode();
}
@@ -230,8 +243,10 @@ public:
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
const QChar cur = *--pos;
- if (Q_UNLIKELY(cur.isLowSurrogate()))
+ if (Q_UNLIKELY(cur.isLowSurrogate())) {
+ Q_ASSERT(hasPrevious() && pos[-1].isHighSurrogate());
return QChar::surrogateToUcs4(*--pos, cur);
+ }
return cur.unicode();
}
@@ -241,7 +256,7 @@ public:
const QChar uc = *--pos;
if (Q_UNLIKELY(uc.isSurrogate())) {
- if (Q_LIKELY(uc.isLowSurrogate() && pos > i && pos[-1].isHighSurrogate()))
+ if (Q_LIKELY(uc.isLowSurrogate() && hasPrevious() && pos[-1].isHighSurrogate()))
return QChar::surrogateToUcs4(*--pos, uc);
return invalidAs;
}
diff --git a/qtbase/src/corelib/thread/qfutex_p.h b/qtbase/src/corelib/thread/qfutex_p.h
index f287b752d7..e294537787 100644
--- a/qtbase/src/corelib/thread/qfutex_p.h
+++ b/qtbase/src/corelib/thread/qfutex_p.h
@@ -52,6 +52,7 @@
//
#include
+#include
QT_BEGIN_NAMESPACE
@@ -106,16 +107,13 @@ namespace QtLinuxFutex {
inline int _q_futex(int *addr, int op, int val, quintptr val2 = 0,
int *addr2 = nullptr, int val3 = 0) noexcept
{
- // A futex call ensures total ordering on the futex words
- // (in either success or failure of the call). Instruct TSAN accordingly,
- // as TSAN does not understand the futex(2) syscall.
- _q_tsan_release(addr, addr2);
+ QtTsan::futexRelease(addr, addr2);
// we use __NR_futex because some libcs (like Android's bionic) don't
// provide SYS_futex etc.
int result = syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
- _q_tsan_acquire(addr, addr2);
+ QtTsan::futexAcquire(addr, addr2);
return result;
}
diff --git a/qtbase/src/corelib/thread/qmutex.cpp b/qtbase/src/corelib/thread/qmutex.cpp
index 310d1cb14f..7097122d8e 100644
--- a/qtbase/src/corelib/thread/qmutex.cpp
+++ b/qtbase/src/corelib/thread/qmutex.cpp
@@ -152,6 +152,7 @@ public:
/*!
\enum QMutex::RecursionMode
+ \obsolete Use QRecursiveMutex to create a recursive mutex.
\value Recursive In this mode, a thread can lock the same mutex
multiple times and the mutex won't be unlocked
@@ -173,6 +174,7 @@ public:
/*!
Constructs a new mutex. The mutex is created in an unlocked state.
+ \obsolete Use QRecursiveMutex to create a recursive mutex.
If \a mode is QMutex::Recursive, a thread can lock the same mutex
multiple times and the mutex won't be unlocked until a
@@ -197,7 +199,7 @@ QMutex::QMutex(RecursionMode mode)
QMutex::~QMutex()
{
QMutexData *d = d_ptr.loadRelaxed();
- if (isRecursive()) {
+ if (QBasicMutex::isRecursive()) {
delete static_cast(d);
} else if (d) {
#ifndef QT_LINUX_FUTEX
diff --git a/qtbase/src/corelib/thread/qmutex.h b/qtbase/src/corelib/thread/qmutex.h
index 73c9e00663..1bae573a03 100644
--- a/qtbase/src/corelib/thread/qmutex.h
+++ b/qtbase/src/corelib/thread/qmutex.h
@@ -42,6 +42,7 @@
#include
#include
+#include
#include
#if __has_include()
@@ -77,19 +78,37 @@ public:
// BasicLockable concept
inline void lock() QT_MUTEX_LOCK_NOEXCEPT {
+ QtTsan::mutexPreLock(this, 0u);
+
if (!fastTryLock())
lockInternal();
+
+ QtTsan::mutexPostLock(this, 0u, 0);
}
// BasicLockable concept
inline void unlock() noexcept {
Q_ASSERT(d_ptr.loadRelaxed()); //mutex must be locked
+
+ QtTsan::mutexPreUnlock(this, 0u);
+
if (!fastTryUnlock())
unlockInternal();
+
+ QtTsan::mutexPostUnlock(this, 0u);
}
bool tryLock() noexcept {
- return fastTryLock();
+ unsigned tsanFlags = QtTsan::TryLock;
+ QtTsan::mutexPreLock(this, tsanFlags);
+
+ const bool success = fastTryLock();
+
+ if (!success)
+ tsanFlags |= QtTsan::TryLockFailed;
+ QtTsan::mutexPostLock(this, tsanFlags, 0);
+
+ return success;
}
// Lockable concept
@@ -134,8 +153,16 @@ public:
#else
QMutex() { d_ptr.storeRelaxed(nullptr); }
#endif
+#if QT_DEPRECATED_SINCE(5,15)
enum RecursionMode { NonRecursive, Recursive };
+ QT_DEPRECATED_VERSION_X(5, 15, "Use QRecursiveMutex instead of a recursive QMutex")
explicit QMutex(RecursionMode mode);
+
+ QT_DEPRECATED_VERSION_X(5, 15, "Use QRecursiveMutex instead of a recursive QMutex")
+ bool isRecursive() const noexcept
+ { return QBasicMutex::isRecursive(); }
+#endif
+
~QMutex();
// BasicLockable concept
@@ -166,9 +193,6 @@ public:
}
#endif
- bool isRecursive() const noexcept
- { return QBasicMutex::isRecursive(); }
-
private:
Q_DISABLE_COPY(QMutex)
friend class QMutexLocker;
diff --git a/qtbase/src/corelib/thread/qreadwritelock.cpp b/qtbase/src/corelib/thread/qreadwritelock.cpp
index 63637ae05b..9dd8503116 100644
--- a/qtbase/src/corelib/thread/qreadwritelock.cpp
+++ b/qtbase/src/corelib/thread/qreadwritelock.cpp
@@ -453,6 +453,7 @@ QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() co
if (!d)
return Unlocked;
+ const auto lock = qt_scoped_lock(d->mutex);
if (d->writerCount > 1)
return RecursivelyLocked;
else if (d->writerCount == 1)
diff --git a/qtbase/src/corelib/thread/qthread_unix.cpp b/qtbase/src/corelib/thread/qthread_unix.cpp
index f6499b38d0..a27782d37c 100644
--- a/qtbase/src/corelib/thread/qthread_unix.cpp
+++ b/qtbase/src/corelib/thread/qthread_unix.cpp
@@ -169,8 +169,7 @@ static void set_thread_data(QThreadData *data)
static void clear_thread_data()
{
- currentThreadData = nullptr;
- pthread_setspecific(current_thread_data_key, nullptr);
+ set_thread_data(nullptr);
}
template
diff --git a/qtbase/src/corelib/thread/qthreadpool.cpp b/qtbase/src/corelib/thread/qthreadpool.cpp
index 40cc646519..8aa06a4c8f 100644
--- a/qtbase/src/corelib/thread/qthreadpool.cpp
+++ b/qtbase/src/corelib/thread/qthreadpool.cpp
@@ -602,8 +602,12 @@ bool QThreadPool::tryStart(std::function functionToRun)
return false;
QRunnable *runnable = QRunnable::create(std::move(functionToRun));
+ Q_ASSERT(runnable->ref == 0);
+ ++runnable->ref;
if (d->tryStart(runnable))
return true;
+ --runnable->ref;
+ Q_ASSERT(runnable->ref == 0);
delete runnable;
return false;
}
diff --git a/qtbase/src/corelib/thread/qtsan_impl.h b/qtbase/src/corelib/thread/qtsan_impl.h
new file mode 100644
index 0000000000..580a738b91
--- /dev/null
+++ b/qtbase/src/corelib/thread/qtsan_impl.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Copyright (C) 2022 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTSAN_IMPL_H
+#define QTSAN_IMPL_H
+
+#include
+
+#if (__has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)) && __has_include()
+# define QT_BUILDING_UNDER_TSAN
+# include
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QtTsan {
+#ifdef QT_BUILDING_UNDER_TSAN
+inline void futexAcquire(void *addr, void *addr2 = nullptr)
+{
+ // A futex call ensures total ordering on the futex words
+ // (in either success or failure of the call). Instruct TSAN accordingly,
+ // as TSAN does not understand the futex(2) syscall (or equivalent).
+ ::__tsan_acquire(addr);
+ if (addr2)
+ ::__tsan_acquire(addr2);
+}
+
+inline void futexRelease(void *addr, void *addr2 = nullptr)
+{
+ if (addr2)
+ ::__tsan_release(addr2);
+ ::__tsan_release(addr);
+}
+
+inline void mutexPreLock(void *addr, unsigned flags)
+{
+ ::__tsan_mutex_pre_lock(addr, flags);
+}
+
+inline void mutexPostLock(void *addr, unsigned flags, int recursion)
+{
+ ::__tsan_mutex_post_lock(addr, flags, recursion);
+}
+
+inline void mutexPreUnlock(void *addr, unsigned flags)
+{
+ ::__tsan_mutex_pre_unlock(addr, flags);
+}
+
+inline void mutexPostUnlock(void *addr, unsigned flags)
+{
+ ::__tsan_mutex_post_unlock(addr, flags);
+}
+
+enum : unsigned {
+ MutexWriteReentrant = ::__tsan_mutex_write_reentrant,
+ TryLock = ::__tsan_mutex_try_lock,
+ TryLockFailed = ::__tsan_mutex_try_lock_failed,
+};
+#else
+inline void futexAcquire(void *, void * = nullptr) {}
+inline void futexRelease(void *, void * = nullptr) {}
+
+enum : unsigned {
+ MutexWriteReentrant,
+ TryLock,
+ TryLockFailed,
+};
+inline void mutexPreLock(void *, unsigned) {}
+inline void mutexPostLock(void *, unsigned, int) {}
+inline void mutexPreUnlock(void *, unsigned) {}
+inline void mutexPostUnlock(void *, unsigned) {}
+#endif // QT_BUILDING_UNDER_TSAN
+} // namespace QtTsan
+
+QT_END_NAMESPACE
+
+#endif // QTSAN_IMPL_H
diff --git a/qtbase/src/corelib/thread/qwaitcondition_unix.cpp b/qtbase/src/corelib/thread/qwaitcondition_unix.cpp
index 88b058f410..0f1da4dc9b 100644
--- a/qtbase/src/corelib/thread/qwaitcondition_unix.cpp
+++ b/qtbase/src/corelib/thread/qwaitcondition_unix.cpp
@@ -213,7 +213,7 @@ bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline)
{
if (! mutex)
return false;
- if (mutex->isRecursive()) {
+ if (static_cast(mutex)->isRecursive()) {
qWarning("QWaitCondition: cannot wait on recursive mutexes");
return false;
}
diff --git a/qtbase/src/corelib/time/qtimezone.cpp b/qtbase/src/corelib/time/qtimezone.cpp
index 0309e43e52..3d451696a1 100644
--- a/qtbase/src/corelib/time/qtimezone.cpp
+++ b/qtbase/src/corelib/time/qtimezone.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 John Layt
+** Copyright (C) 2020 John Layt
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -975,9 +975,15 @@ QList QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId,
}
#ifndef QT_NO_DATASTREAM
+// Invalid, as an IANA ID: too long, starts with - and has other invalid characters in it
+static inline QString invalidId() { return QStringLiteral("-No Time Zone Specified!"); }
+
QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz)
{
- tz.d->serialize(ds);
+ if (tz.isValid())
+ tz.d->serialize(ds);
+ else
+ ds << invalidId();
return ds;
}
@@ -985,7 +991,9 @@ QDataStream &operator>>(QDataStream &ds, QTimeZone &tz)
{
QString ianaId;
ds >> ianaId;
- if (ianaId == QLatin1String("OffsetFromUtc")) {
+ if (ianaId == invalidId()) {
+ tz = QTimeZone();
+ } else if (ianaId == QLatin1String("OffsetFromUtc")) {
int utcOffset;
QString name;
QString abbreviation;
diff --git a/qtbase/src/corelib/tools/qarraydata.h b/qtbase/src/corelib/tools/qarraydata.h
index dcd95924c1..d01739e7e6 100644
--- a/qtbase/src/corelib/tools/qarraydata.h
+++ b/qtbase/src/corelib/tools/qarraydata.h
@@ -42,6 +42,7 @@
#include
#include
+#include
QT_BEGIN_NAMESPACE
@@ -58,14 +59,14 @@ struct Q_CORE_EXPORT QArrayData
{
Q_ASSERT(size == 0
|| offset < 0 || size_t(offset) >= sizeof(QArrayData));
- return reinterpret_cast(this) + offset;
+ return reinterpret_cast (reinterpret_cast(this) + offset);
}
const void *data() const
{
Q_ASSERT(size == 0
|| offset < 0 || size_t(offset) >= sizeof(QArrayData));
- return reinterpret_cast(this) + offset;
+ return reinterpret_cast (reinterpret_cast(this) + offset);
}
// This refers to array data mutability, not "header data" represented by
diff --git a/qtbase/src/dbus/qdbusintegrator.cpp b/qtbase/src/dbus/qdbusintegrator.cpp
index 5b66ce971b..28a3b0ffea 100644
--- a/qtbase/src/dbus/qdbusintegrator.cpp
+++ b/qtbase/src/dbus/qdbusintegrator.cpp
@@ -1135,7 +1135,13 @@ void QDBusConnectionPrivate::closeConnection()
}
}
- qDeleteAll(pendingCalls);
+ for (auto it = pendingCalls.begin(); it != pendingCalls.end(); ++it) {
+ auto call = *it;
+ if (!call->ref.deref()) {
+ delete call;
+ }
+ }
+ pendingCalls.clear();
// Disconnect all signals from signal hooks and from the object tree to
// avoid QObject::destroyed being sent to dbus daemon thread which has
@@ -2584,6 +2590,11 @@ QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &pa
if (mo)
return mo;
}
+ if (path.isEmpty()) {
+ error = QDBusError(QDBusError::InvalidObjectPath, QLatin1String("Object path cannot be empty"));
+ lastError = error;
+ return nullptr;
+ }
// introspect the target object
QDBusMessage msg = QDBusMessage::createMethodCall(service, path,
diff --git a/qtbase/src/gui/configure.json b/qtbase/src/gui/configure.json
index 1f08795c57..12c95742d2 100644
--- a/qtbase/src/gui/configure.json
+++ b/qtbase/src/gui/configure.json
@@ -834,7 +834,8 @@
"// embedded devices, are not intended to be used together with X. EGL support",
"// has to be disabled in plugins like xcb in this case since the native display,",
"// window and pixmap types will be different than what an X-based platform",
- "// plugin would expect."
+ "// plugin would expect.",
+ "#define USE_X11"
],
"include": [ "EGL/egl.h", "X11/Xlib.h" ],
"main": [
diff --git a/qtbase/src/gui/image/qbmphandler.cpp b/qtbase/src/gui/image/qbmphandler.cpp
index 96f1e8cb1d..0e73bbbdb0 100644
--- a/qtbase/src/gui/image/qbmphandler.cpp
+++ b/qtbase/src/gui/image/qbmphandler.cpp
@@ -150,16 +150,42 @@ static QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi)
return s;
}
-static int calc_shift(uint mask)
+static uint calc_shift(uint mask)
{
- int result = 0;
- while (mask && !(mask & 1)) {
+ uint result = 0;
+ while ((mask >= 0x100) || (!(mask & 1) && mask)) {
result++;
mask >>= 1;
}
return result;
}
+static uint calc_scale(uint low_mask)
+{
+ uint result = 8;
+ while (low_mask && result) {
+ result--;
+ low_mask >>= 1;
+ }
+ return result;
+}
+
+static inline uint apply_scale(uint value, uint scale)
+{
+ if (!(scale & 0x07)) // return immediately if scale == 8 or 0
+ return value;
+
+ uint filled = 8 - scale;
+ uint result = value << scale;
+
+ do {
+ result |= result >> filled;
+ filled <<= 1;
+ } while (filled < 8);
+
+ return result;
+}
+
static bool read_dib_fileheader(QDataStream &s, BMP_FILEHDR &bf)
{
// read BMP file header
@@ -222,14 +248,14 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
uint green_mask = 0;
uint blue_mask = 0;
uint alpha_mask = 0;
- int red_shift = 0;
- int green_shift = 0;
- int blue_shift = 0;
- int alpha_shift = 0;
- int red_scale = 0;
- int green_scale = 0;
- int blue_scale = 0;
- int alpha_scale = 0;
+ uint red_shift = 0;
+ uint green_shift = 0;
+ uint blue_shift = 0;
+ uint alpha_shift = 0;
+ uint red_scale = 0;
+ uint green_scale = 0;
+ uint blue_scale = 0;
+ uint alpha_scale = 0;
if (!d->isSequential())
d->seek(startpos + BMP_FILEHDR_SIZE + bi.biSize); // goto start of colormap or masks
@@ -308,19 +334,19 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
red_shift = calc_shift(red_mask);
if (((red_mask >> red_shift) + 1) == 0)
return false;
- red_scale = 256 / ((red_mask >> red_shift) + 1);
+ red_scale = calc_scale(red_mask >> red_shift);
green_shift = calc_shift(green_mask);
if (((green_mask >> green_shift) + 1) == 0)
return false;
- green_scale = 256 / ((green_mask >> green_shift) + 1);
+ green_scale = calc_scale(green_mask >> green_shift);
blue_shift = calc_shift(blue_mask);
if (((blue_mask >> blue_shift) + 1) == 0)
return false;
- blue_scale = 256 / ((blue_mask >> blue_shift) + 1);
+ blue_scale = calc_scale(blue_mask >> blue_shift);
alpha_shift = calc_shift(alpha_mask);
if (((alpha_mask >> alpha_shift) + 1) == 0)
return false;
- alpha_scale = 256 / ((alpha_mask >> alpha_shift) + 1);
+ alpha_scale = calc_scale(alpha_mask >> alpha_shift);
} else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) {
blue_mask = 0x000000ff;
green_mask = 0x0000ff00;
@@ -328,17 +354,15 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
blue_shift = 0;
green_shift = 8;
red_shift = 16;
- blue_scale = green_scale = red_scale = 1;
+ blue_scale = green_scale = red_scale = 0;
} else if (comp == BMP_RGB && nbits == 16) {
blue_mask = 0x001f;
green_mask = 0x03e0;
red_mask = 0x7c00;
blue_shift = 0;
- green_shift = 2;
- red_shift = 7;
- red_scale = 1;
- green_scale = 1;
- blue_scale = 8;
+ green_shift = 5;
+ red_shift = 10;
+ blue_scale = green_scale = red_scale = 3;
}
#if 0
@@ -544,10 +568,10 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
c |= *(uchar*)(b+2)<<16;
if (nbits > 24)
c |= *(uchar*)(b+3)<<24;
- *p++ = qRgba(((c & red_mask) >> red_shift) * red_scale,
- ((c & green_mask) >> green_shift) * green_scale,
- ((c & blue_mask) >> blue_shift) * blue_scale,
- transp ? ((c & alpha_mask) >> alpha_shift) * alpha_scale : 0xff);
+ *p++ = qRgba(apply_scale((c & red_mask) >> red_shift, red_scale),
+ apply_scale((c & green_mask) >> green_shift, green_scale),
+ apply_scale((c & blue_mask) >> blue_shift, blue_scale),
+ transp ? apply_scale((c & alpha_mask) >> alpha_shift, alpha_scale) : 0xff);
b += nbits/8;
}
}
diff --git a/qtbase/src/gui/image/qimage.cpp b/qtbase/src/gui/image/qimage.cpp
index 53bb3beb10..04e1a00429 100644
--- a/qtbase/src/gui/image/qimage.cpp
+++ b/qtbase/src/gui/image/qimage.cpp
@@ -4694,6 +4694,8 @@ QImage QImage::smoothScaled(int w, int h) const {
static QImage rotated90(const QImage &image)
{
QImage out(image.height(), image.width(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
@@ -4722,6 +4724,8 @@ static QImage rotated180(const QImage &image)
return image.mirrored(true, true);
QImage out(image.width(), image.height(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
@@ -4734,6 +4738,8 @@ static QImage rotated180(const QImage &image)
static QImage rotated270(const QImage &image)
{
QImage out(image.height(), image.width(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
diff --git a/qtbase/src/gui/image/qimage_neon.cpp b/qtbase/src/gui/image/qimage_neon.cpp
index 9dbcb11db5..c17f76f2b0 100644
--- a/qtbase/src/gui/image/qimage_neon.cpp
+++ b/qtbase/src/gui/image/qimage_neon.cpp
@@ -54,7 +54,7 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons
// align dst on 128 bits
const int offsetToAlignOn16Bytes = (reinterpret_cast(dst) >> 2) & 0x3;
- for (int i = 0; i < offsetToAlignOn16Bytes; ++i) {
+ for (int i = 0; i < qMin(len, offsetToAlignOn16Bytes); ++i) {
*dst++ = qRgb(src[0], src[1], src[2]);
src += 3;
}
diff --git a/qtbase/src/gui/image/qimagereader.cpp b/qtbase/src/gui/image/qimagereader.cpp
index 5cb7e1328e..1274622d53 100644
--- a/qtbase/src/gui/image/qimagereader.cpp
+++ b/qtbase/src/gui/image/qimagereader.cpp
@@ -515,9 +515,9 @@ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq)
*/
QImageReaderPrivate::~QImageReaderPrivate()
{
+ delete handler;
if (deleteDevice)
delete device;
- delete handler;
}
/*!
@@ -774,12 +774,12 @@ bool QImageReader::decideFormatFromContent() const
*/
void QImageReader::setDevice(QIODevice *device)
{
+ delete d->handler;
+ d->handler = nullptr;
if (d->device && d->deleteDevice)
delete d->device;
d->device = device;
d->deleteDevice = false;
- delete d->handler;
- d->handler = nullptr;
d->text.clear();
}
diff --git a/qtbase/src/gui/image/qimagewriter.cpp b/qtbase/src/gui/image/qimagewriter.cpp
index 33f5e491c7..a679f25757 100644
--- a/qtbase/src/gui/image/qimagewriter.cpp
+++ b/qtbase/src/gui/image/qimagewriter.cpp
@@ -349,9 +349,9 @@ QImageWriter::QImageWriter(const QString &fileName, const QByteArray &format)
*/
QImageWriter::~QImageWriter()
{
+ delete d->handler;
if (d->deleteDevice)
delete d->device;
- delete d->handler;
delete d;
}
@@ -396,13 +396,13 @@ QByteArray QImageWriter::format() const
*/
void QImageWriter::setDevice(QIODevice *device)
{
+ delete d->handler;
+ d->handler = nullptr;
if (d->device && d->deleteDevice)
delete d->device;
d->device = device;
d->deleteDevice = false;
- delete d->handler;
- d->handler = nullptr;
}
/*!
diff --git a/qtbase/src/gui/kernel/qhighdpiscaling.cpp b/qtbase/src/gui/kernel/qhighdpiscaling.cpp
index 85ff58c14c..a433e94c22 100644
--- a/qtbase/src/gui/kernel/qhighdpiscaling.cpp
+++ b/qtbase/src/gui/kernel/qhighdpiscaling.cpp
@@ -580,9 +580,8 @@ void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor)
else
qNamedScreenScaleFactors()->insert(name, factor);
- // hack to force re-evaluation of screen geometry
if (screen->handle())
- screen->d_func()->setPlatformScreen(screen->handle()); // updates geometries based on scale factor
+ screen->d_func()->updateLogicalDpi();
}
QPoint QHighDpiScaling::mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen)
diff --git a/qtbase/src/gui/kernel/qkeysequence.cpp b/qtbase/src/gui/kernel/qkeysequence.cpp
index 23be5e1ac0..268e0e3ab1 100644
--- a/qtbase/src/gui/kernel/qkeysequence.cpp
+++ b/qtbase/src/gui/kernel/qkeysequence.cpp
@@ -701,6 +701,10 @@ static const struct {
{ Qt::Key_TouchpadToggle, QT_TRANSLATE_NOOP("QShortcut", "Touchpad Toggle") },
{ Qt::Key_TouchpadOn, QT_TRANSLATE_NOOP("QShortcut", "Touchpad On") },
{ Qt::Key_TouchpadOff, QT_TRANSLATE_NOOP("QShortcut", "Touchpad Off") },
+ { Qt::Key_Shift, QT_TRANSLATE_NOOP("QShortcut", "Shift") },
+ { Qt::Key_Control, QT_TRANSLATE_NOOP("QShortcut", "Control") },
+ { Qt::Key_Alt, QT_TRANSLATE_NOOP("QShortcut", "Alt") },
+ { Qt::Key_Meta, QT_TRANSLATE_NOOP("QShortcut", "Meta") },
};
static Q_CONSTEXPR int numKeyNames = sizeof keyname / sizeof *keyname;
diff --git a/qtbase/src/gui/kernel/qplatformservices.cpp b/qtbase/src/gui/kernel/qplatformservices.cpp
index fdc6a6c4aa..ac47f98c5d 100644
--- a/qtbase/src/gui/kernel/qplatformservices.cpp
+++ b/qtbase/src/gui/kernel/qplatformservices.cpp
@@ -55,6 +55,19 @@ QT_BEGIN_NAMESPACE
\brief The QPlatformServices provides the backend for desktop-related functionality.
*/
+/*!
+ \enum QPlatformServices::Capability
+
+ Capabilities are used to determine a specific platform service's availability.
+
+ \value ColorPickingFromScreen The platform natively supports color picking from screen.
+ This capability indicates that the platform supports "opaque" color picking, where the
+ platform implements a complete user experience for color picking and outputs a color.
+ This is in contrast to the application implementing the color picking user experience
+ (taking care of showing a cross hair, instructing the platform integration to obtain
+ the color at a given pixel, etc.). The related service function is pickColor().
+ */
+
QPlatformServices::QPlatformServices()
{ }
@@ -85,5 +98,16 @@ QByteArray QPlatformServices::desktopEnvironment() const
return QByteArray("UNKNOWN");
}
+QPlatformServiceColorPicker *QPlatformServices::colorPicker(QWindow *parent)
+{
+ Q_UNUSED(parent);
+ return nullptr;
+}
+
+bool QPlatformServices::hasCapability(Capability capability) const
+{
+ Q_UNUSED(capability)
+ return false;
+}
QT_END_NAMESPACE
diff --git a/qtbase/src/gui/kernel/qplatformservices.h b/qtbase/src/gui/kernel/qplatformservices.h
index 5de96cfa7d..a8b2a4ce71 100644
--- a/qtbase/src/gui/kernel/qplatformservices.h
+++ b/qtbase/src/gui/kernel/qplatformservices.h
@@ -50,16 +50,32 @@
//
#include
+#include
QT_BEGIN_NAMESPACE
class QUrl;
+class QWindow;
+
+class Q_GUI_EXPORT QPlatformServiceColorPicker : public QObject
+{
+ Q_OBJECT
+public:
+ using QObject::QObject;
+ virtual void pickColor() = 0;
+Q_SIGNALS:
+ void colorPicked(const QColor &color);
+};
class Q_GUI_EXPORT QPlatformServices
{
public:
Q_DISABLE_COPY_MOVE(QPlatformServices)
+ enum Capability {
+ ColorPicking,
+ };
+
QPlatformServices();
virtual ~QPlatformServices() { }
@@ -67,6 +83,10 @@ public:
virtual bool openDocument(const QUrl &url);
virtual QByteArray desktopEnvironment() const;
+
+ virtual bool hasCapability(Capability capability) const;
+
+ virtual QPlatformServiceColorPicker *colorPicker(QWindow *parent = nullptr);
};
QT_END_NAMESPACE
diff --git a/qtbase/src/gui/kernel/qplatformtheme.cpp b/qtbase/src/gui/kernel/qplatformtheme.cpp
index 71521c0339..2325873245 100644
--- a/qtbase/src/gui/kernel/qplatformtheme.cpp
+++ b/qtbase/src/gui/kernel/qplatformtheme.cpp
@@ -163,6 +163,8 @@ QT_BEGIN_NAMESPACE
\value ShowShortcutsInContextMenus (bool) Whether to display shortcut key sequences in context menus.
+ \value ButtonPressKeys (QList) A list of keys that can be used to press buttons via keyboard input.
+
\sa themeHint(), QStyle::pixelMetric()
*/
@@ -563,6 +565,8 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
}
case MouseQuickSelectionThreshold:
return QVariant(10);
+ case ButtonPressKeys:
+ return QVariant::fromValue(QList({ Qt::Key_Space, Qt::Key_Select }));
}
return QVariant();
}
diff --git a/qtbase/src/gui/kernel/qplatformtheme.h b/qtbase/src/gui/kernel/qplatformtheme.h
index 3185fc4541..7e6c9d5740 100644
--- a/qtbase/src/gui/kernel/qplatformtheme.h
+++ b/qtbase/src/gui/kernel/qplatformtheme.h
@@ -120,7 +120,8 @@ public:
TouchDoubleTapDistance,
ShowShortcutsInContextMenus,
IconFallbackSearchPaths,
- MouseQuickSelectionThreshold
+ MouseQuickSelectionThreshold,
+ ButtonPressKeys
};
enum DialogType {
diff --git a/qtbase/src/gui/kernel/qscreen.cpp b/qtbase/src/gui/kernel/qscreen.cpp
index 990272b0c2..d371dd60ab 100644
--- a/qtbase/src/gui/kernel/qscreen.cpp
+++ b/qtbase/src/gui/kernel/qscreen.cpp
@@ -77,6 +77,12 @@ QScreen::QScreen(QPlatformScreen *screen)
d->setPlatformScreen(screen);
}
+void QScreenPrivate::updateLogicalDpi()
+{
+ logicalDpi = QPlatformScreen::overrideDpi(platformScreen->logicalDpi());
+ updateGeometriesWithSignals(); // updates geometries based on scale factor
+}
+
void QScreenPrivate::updateGeometriesWithSignals()
{
const QRect oldGeometry = geometry;
diff --git a/qtbase/src/gui/kernel/qscreen_p.h b/qtbase/src/gui/kernel/qscreen_p.h
index 7da542c25e..e50fc3190b 100644
--- a/qtbase/src/gui/kernel/qscreen_p.h
+++ b/qtbase/src/gui/kernel/qscreen_p.h
@@ -70,6 +70,7 @@ public:
geometry = platformScreen->deviceIndependentGeometry();
availableGeometry = QHighDpi::fromNative(platformScreen->availableGeometry(), QHighDpiScaling::factor(platformScreen), geometry.topLeft());
}
+ void updateLogicalDpi();
void updatePrimaryOrientation();
void updateGeometriesWithSignals();
diff --git a/qtbase/src/gui/kernel/qshapedpixmapdndwindow.cpp b/qtbase/src/gui/kernel/qshapedpixmapdndwindow.cpp
index bb0d8e4ee7..b98fcc61e7 100644
--- a/qtbase/src/gui/kernel/qshapedpixmapdndwindow.cpp
+++ b/qtbase/src/gui/kernel/qshapedpixmapdndwindow.cpp
@@ -56,7 +56,7 @@ QShapedPixmapWindow::QShapedPixmapWindow(QScreen *screen)
QSurfaceFormat format;
format.setAlphaBufferSize(8);
setFormat(format);
- setFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint
+ setFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint
| Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus);
}
diff --git a/qtbase/src/gui/opengl/qopengltexture.cpp b/qtbase/src/gui/opengl/qopengltexture.cpp
index 5490ad8025..afd3d8dbe6 100644
--- a/qtbase/src/gui/opengl/qopengltexture.cpp
+++ b/qtbase/src/gui/opengl/qopengltexture.cpp
@@ -3725,6 +3725,12 @@ void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps)
return;
}
+ QImage glImage = image.convertToFormat(QImage::Format_RGBA8888);
+ if (glImage.isNull()) {
+ qWarning("QOpenGLTexture::setData() failed to convert image");
+ return;
+ }
+
if (context->isOpenGLES() && context->format().majorVersion() < 3)
setFormat(QOpenGLTexture::RGBAFormat);
else
@@ -3735,7 +3741,6 @@ void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps)
allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
// Upload pixel data and generate mipmaps
- QImage glImage = image.convertToFormat(QImage::Format_RGBA8888);
QOpenGLPixelTransferOptions uploadOptions;
uploadOptions.setAlignment(1);
setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, glImage.constBits(), &uploadOptions);
diff --git a/qtbase/src/gui/painting/qcolortrclut_p.h b/qtbase/src/gui/painting/qcolortrclut_p.h
index 76a6a60803..24fd522e6c 100644
--- a/qtbase/src/gui/painting/qcolortrclut_p.h
+++ b/qtbase/src/gui/painting/qcolortrclut_p.h
@@ -118,6 +118,7 @@ public:
return QRgba64::fromRgba64(r, g, b, qAlpha(rgb32) * 257);
#endif
}
+ QRgba64 toLinear64(QRgba64) const = delete;
QRgb toLinear(QRgb rgb32) const
{
diff --git a/qtbase/src/gui/painting/qdrawhelper.cpp b/qtbase/src/gui/painting/qdrawhelper.cpp
index a61793508a..5ba2d277b7 100644
--- a/qtbase/src/gui/painting/qdrawhelper.cpp
+++ b/qtbase/src/gui/painting/qdrawhelper.cpp
@@ -6091,7 +6091,7 @@ static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba
static inline void rgbBlendPixel(QRgba64 &dst, int coverage, QRgba64 slinear, const QColorTrcLut *colorProfile)
{
// Do a gammacorrected RGB alphablend...
- const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(dst) : dst;
+ const QRgba64 dlinear = colorProfile ? colorProfile->toLinear(dst) : dst;
QRgba64 blend = rgbBlend(dlinear, slinear, coverage);
diff --git a/qtbase/src/gui/painting/qfixed_p.h b/qtbase/src/gui/painting/qfixed_p.h
index 846592881c..57d750a4b3 100644
--- a/qtbase/src/gui/painting/qfixed_p.h
+++ b/qtbase/src/gui/painting/qfixed_p.h
@@ -54,6 +54,7 @@
#include
#include "QtCore/qdebug.h"
#include "QtCore/qpoint.h"
+#include
#include "QtCore/qsize.h"
QT_BEGIN_NAMESPACE
@@ -182,6 +183,14 @@ Q_DECL_CONSTEXPR inline bool operator<(int i, const QFixed &f) { return i * 64 <
Q_DECL_CONSTEXPR inline bool operator>(const QFixed &f, int i) { return f.value() > i * 64; }
Q_DECL_CONSTEXPR inline bool operator>(int i, const QFixed &f) { return i * 64 > f.value(); }
+inline bool qAddOverflow(QFixed v1, QFixed v2, QFixed *r)
+{
+ int val;
+ bool result = add_overflow(v1.value(), v2.value(), &val);
+ r->setValue(val);
+ return result;
+}
+
#ifndef QT_NO_DEBUG_STREAM
inline QDebug &operator<<(QDebug &dbg, const QFixed &f)
{ return dbg << f.toReal(); }
diff --git a/qtbase/src/gui/painting/qpainterpath.cpp b/qtbase/src/gui/painting/qpainterpath.cpp
index f9544a3241..d80fafeaf1 100644
--- a/qtbase/src/gui/painting/qpainterpath.cpp
+++ b/qtbase/src/gui/painting/qpainterpath.cpp
@@ -1253,7 +1253,7 @@ void QPainterPath::addText(const QPointF &point, const QFont &f, const QString &
if (si.analysis.flags < QScriptAnalysis::TabOrObject) {
QGlyphLayout glyphs = eng->shapedGlyphs(&si);
- QFontEngine *fe = f.d->engineForScript(si.analysis.script);
+ QFontEngine *fe = eng->fontEngine(si);
Q_ASSERT(fe);
fe->addOutlineToPath(x, y, glyphs, this,
si.analysis.bidiLevel % 2
diff --git a/qtbase/src/gui/painting/qpdf.cpp b/qtbase/src/gui/painting/qpdf.cpp
index 3066744f1b..2c8d3c3b53 100644
--- a/qtbase/src/gui/painting/qpdf.cpp
+++ b/qtbase/src/gui/painting/qpdf.cpp
@@ -2760,6 +2760,8 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
return gradientBrush(brush, matrix, gStateObject);
}
+ matrix = brush.transform() * matrix;
+
if ((!brush.isOpaque() && brush.style() < Qt::LinearGradientPattern) || opacity != 1.0)
*gStateObject = addConstantAlphaObject(qRound(brush.color().alpha() * opacity),
qRound(pen.color().alpha() * opacity));
diff --git a/qtbase/src/gui/painting/qt_attribution.json b/qtbase/src/gui/painting/qt_attribution.json
index 7b16e8c211..0e87d30aa2 100644
--- a/qtbase/src/gui/painting/qt_attribution.json
+++ b/qtbase/src/gui/painting/qt_attribution.json
@@ -10,7 +10,7 @@
"Homepage": "http://www.freetype.org",
"License": "Freetype Project License or GNU General Public License v2.0 only",
"LicenseId": "FTL or GPL-2.0",
- "LicenseFile": "../../3rdparty/freetype/docs/LICENSE.TXT",
+ "LicenseFile": "../../3rdparty/freetype/LICENSE.TXT",
"Copyright": "Copyright 2000-2016 by David Turner, Robert Wilhelm, and Werner Lemberg."
},
{
diff --git a/qtbase/src/gui/rhi/qshader_p_p.h b/qtbase/src/gui/rhi/qshader_p_p.h
index ec9d25971f..4a5a7a6d51 100644
--- a/qtbase/src/gui/rhi/qshader_p_p.h
+++ b/qtbase/src/gui/rhi/qshader_p_p.h
@@ -68,13 +68,13 @@ struct Q_GUI_EXPORT QShaderPrivate
{
}
- QShaderPrivate(const QShaderPrivate *other)
+ QShaderPrivate(const QShaderPrivate &other)
: ref(1),
- qsbVersion(other->qsbVersion),
- stage(other->stage),
- desc(other->desc),
- shaders(other->shaders),
- bindings(other->bindings)
+ qsbVersion(other.qsbVersion),
+ stage(other.stage),
+ desc(other.desc),
+ shaders(other.shaders),
+ bindings(other.bindings)
{
}
diff --git a/qtbase/src/gui/rhi/qshaderdescription_p_p.h b/qtbase/src/gui/rhi/qshaderdescription_p_p.h
index ec2b0b6b4c..3da33a8a2b 100644
--- a/qtbase/src/gui/rhi/qshaderdescription_p_p.h
+++ b/qtbase/src/gui/rhi/qshaderdescription_p_p.h
@@ -63,16 +63,16 @@ struct Q_GUI_EXPORT QShaderDescriptionPrivate
localSize[0] = localSize[1] = localSize[2] = 0;
}
- QShaderDescriptionPrivate(const QShaderDescriptionPrivate *other)
+ QShaderDescriptionPrivate(const QShaderDescriptionPrivate &other)
: ref(1),
- inVars(other->inVars),
- outVars(other->outVars),
- uniformBlocks(other->uniformBlocks),
- pushConstantBlocks(other->pushConstantBlocks),
- storageBlocks(other->storageBlocks),
- combinedImageSamplers(other->combinedImageSamplers),
- storageImages(other->storageImages),
- localSize(other->localSize)
+ inVars(other.inVars),
+ outVars(other.outVars),
+ uniformBlocks(other.uniformBlocks),
+ pushConstantBlocks(other.pushConstantBlocks),
+ storageBlocks(other.storageBlocks),
+ combinedImageSamplers(other.combinedImageSamplers),
+ storageImages(other.storageImages),
+ localSize(other.localSize)
{
}
diff --git a/qtbase/src/gui/text/qfontdatabase.cpp b/qtbase/src/gui/text/qfontdatabase.cpp
index 2011f935a9..7aa6228948 100644
--- a/qtbase/src/gui/text/qfontdatabase.cpp
+++ b/qtbase/src/gui/text/qfontdatabase.cpp
@@ -983,7 +983,7 @@ QFontEngine *loadSingleEngine(int script,
if (style->key.stretch != 0 && request.stretch != 0
&& (request.styleName.isEmpty() || request.styleName != style->styleName)) {
def.stretch = (request.stretch * 100 + style->key.stretch / 2) / style->key.stretch;
- } else {
+ } else if (request.stretch == QFont::AnyStretch) {
def.stretch = 100;
}
diff --git a/qtbase/src/gui/text/qtextengine.cpp b/qtbase/src/gui/text/qtextengine.cpp
index 6336fadf74..a6c66e5d2d 100644
--- a/qtbase/src/gui/text/qtextengine.cpp
+++ b/qtbase/src/gui/text/qtextengine.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
diff --git a/qtbase/src/gui/text/qtextlayout.cpp b/qtbase/src/gui/text/qtextlayout.cpp
index d4f0a5efdc..f6c69ff4a2 100644
--- a/qtbase/src/gui/text/qtextlayout.cpp
+++ b/qtbase/src/gui/text/qtextlayout.cpp
@@ -1336,13 +1336,13 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
bool rightToLeft = d->isRightToLeft();
if (itm >= 0) {
const QScriptItem &si = d->layoutData->items.at(itm);
- if (si.ascent >= 0)
+ if (si.ascent > 0)
base = si.ascent;
- if (si.descent >= 0)
+ if (si.descent > 0)
descent = si.descent;
rightToLeft = si.analysis.bidiLevel % 2;
}
- qreal y = position.y() + (sl.y + sl.base() + sl.descent - base - descent).toReal();
+ qreal y = position.y() + (sl.y + sl.base() - base).toReal();
bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing)
&& (p->transform().type() > QTransform::TxTranslate);
if (toggleAntialiasing)
@@ -2150,11 +2150,14 @@ found:
eng->maxWidth = qMax(eng->maxWidth, line.textWidth);
} else {
eng->minWidth = qMax(eng->minWidth, lbh.minw);
- eng->maxWidth += line.textWidth;
+ if (qAddOverflow(eng->maxWidth, line.textWidth, &eng->maxWidth))
+ eng->maxWidth = QFIXED_MAX;
}
- if (line.textWidth > 0 && item < eng->layoutData->items.size())
- eng->maxWidth += lbh.spaceData.textWidth;
+ if (line.textWidth > 0 && item < eng->layoutData->items.size()) {
+ if (qAddOverflow(eng->maxWidth, lbh.spaceData.textWidth, &eng->maxWidth))
+ eng->maxWidth = QFIXED_MAX;
+ }
line.textWidth += trailingSpace;
if (lbh.spaceData.length) {
diff --git a/qtbase/src/network/access/qhsts.cpp b/qtbase/src/network/access/qhsts.cpp
index 0cef0ad3dc..be7ef7ff58 100644
--- a/qtbase/src/network/access/qhsts.cpp
+++ b/qtbase/src/network/access/qhsts.cpp
@@ -364,8 +364,8 @@ quoted-pair = "\" CHAR
bool QHstsHeaderParser::parse(const QList> &headers)
{
for (const auto &h : headers) {
- // We use '==' since header name was already 'trimmed' for us:
- if (h.first == "Strict-Transport-Security") {
+ // We compare directly because header name was already 'trimmed' for us:
+ if (h.first.compare("Strict-Transport-Security", Qt::CaseInsensitive) == 0) {
header = h.second;
// RFC6797, 8.1:
//
diff --git a/qtbase/src/network/access/qnetworkreply.cpp b/qtbase/src/network/access/qnetworkreply.cpp
index 30e4e290ea..dadea58080 100644
--- a/qtbase/src/network/access/qnetworkreply.cpp
+++ b/qtbase/src/network/access/qnetworkreply.cpp
@@ -76,7 +76,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
itself.
QNetworkReply is a sequential-access QIODevice, which means that
- once data is read from the object, it no longer kept by the
+ once data is read from the object, it is no longer kept by the
device. It is therefore the application's responsibility to keep
this data if it needs to. Whenever more data is received from the
network and processed, the readyRead() signal is emitted.
@@ -344,7 +344,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
processing. After this signal is emitted, there will be no more
updates to the reply's data or metadata.
- Unless close() or abort() have been called, the reply will be still be opened
+ Unless close() or abort() have been called, the reply will still be opened
for reading, so the data can be retrieved by calls to read() or
readAll(). In particular, if no calls to read() were made as a
result of readyRead(), a call to readAll() will retrieve the full
diff --git a/qtbase/src/network/access/qnetworkreplyfileimpl.cpp b/qtbase/src/network/access/qnetworkreplyfileimpl.cpp
index b6be93147a..6e69b4c4d3 100644
--- a/qtbase/src/network/access/qnetworkreplyfileimpl.cpp
+++ b/qtbase/src/network/access/qnetworkreplyfileimpl.cpp
@@ -89,9 +89,10 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con
// we handle only local files
QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString());
setError(QNetworkReply::ProtocolInvalidOperationError, msg);
+ setFinished(true); // We're finished, will emit finished() after ctor is done.
QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError));
- fileOpenFinished(false);
+ QMetaObject::invokeMethod(this, [this](){ fileOpenFinished(false); }, Qt::QueuedConnection);
return;
}
#endif
diff --git a/qtbase/src/network/access/qnetworkreplyfileimpl_p.h b/qtbase/src/network/access/qnetworkreplyfileimpl_p.h
index 48d82abd3f..4bfbc3f7d1 100644
--- a/qtbase/src/network/access/qnetworkreplyfileimpl_p.h
+++ b/qtbase/src/network/access/qnetworkreplyfileimpl_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QNETWORKREPLYFILEIMPL_H
-#define QNETWORKREPLYFILEIMPL_H
+#ifndef QNETWORKREPLYFILEIMPL_P_H
+#define QNETWORKREPLYFILEIMPL_P_H
//
// W A R N I N G
@@ -99,4 +99,4 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(QNetworkRequest::KnownHeaders)
-#endif // QNETWORKREPLYFILEIMPL_H
+#endif // QNETWORKREPLYFILEIMPL_P_H
diff --git a/qtbase/src/network/configure.json b/qtbase/src/network/configure.json
index 271ff164ac..ffba2d1eea 100644
--- a/qtbase/src/network/configure.json
+++ b/qtbase/src/network/configure.json
@@ -53,7 +53,7 @@
},
"headers": "proxy.h",
"sources": [
- "-lproxy"
+ { "type": "pkgConfig", "args": "libproxy-1.0" }
]
},
"openssl_headers": {
diff --git a/qtbase/src/network/kernel/qdnslookup_unix.cpp b/qtbase/src/network/kernel/qdnslookup_unix.cpp
index 12b40fc35d..99e999d436 100644
--- a/qtbase/src/network/kernel/qdnslookup_unix.cpp
+++ b/qtbase/src/network/kernel/qdnslookup_unix.cpp
@@ -227,7 +227,6 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
// responseLength in case of error, we still can extract the
// exact error code from the response.
HEADER *header = (HEADER*)response;
- const int answerCount = ntohs(header->ancount);
switch (header->rcode) {
case NOERROR:
break;
@@ -260,18 +259,31 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
return;
}
- // Skip the query host, type (2 bytes) and class (2 bytes).
char host[PACKETSZ], answer[PACKETSZ];
unsigned char *p = response + sizeof(HEADER);
- int status = local_dn_expand(response, response + responseLength, p, host, sizeof(host));
- if (status < 0) {
+ int status;
+
+ if (ntohs(header->qdcount) == 1) {
+ // Skip the query host, type (2 bytes) and class (2 bytes).
+ status = local_dn_expand(response, response + responseLength, p, host, sizeof(host));
+ if (status < 0) {
+ reply->error = QDnsLookup::InvalidReplyError;
+ reply->errorString = tr("Could not expand domain name");
+ return;
+ }
+ if ((p - response) + status + 4 >= responseLength)
+ header->qdcount = 0xffff; // invalid reply below
+ else
+ p += status + 4;
+ }
+ if (ntohs(header->qdcount) > 1) {
reply->error = QDnsLookup::InvalidReplyError;
- reply->errorString = tr("Could not expand domain name");
+ reply->errorString = tr("Invalid reply received");
return;
}
- p += status + 4;
// Extract results.
+ const int answerCount = ntohs(header->ancount);
int answerIndex = 0;
while ((p < response + responseLength) && (answerIndex < answerCount)) {
status = local_dn_expand(response, response + responseLength, p, host, sizeof(host));
@@ -283,6 +295,11 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
const QString name = QUrl::fromAce(host);
p += status;
+
+ if ((p - response) + 10 > responseLength) {
+ // probably just a truncated reply, return what we have
+ return;
+ }
const quint16 type = (p[0] << 8) | p[1];
p += 2; // RR type
p += 2; // RR class
@@ -290,6 +307,8 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
p += 4;
const quint16 size = (p[0] << 8) | p[1];
p += 2;
+ if ((p - response) + size > responseLength)
+ return; // truncated
if (type == QDnsLookup::A) {
if (size != 4) {
diff --git a/qtbase/src/network/ssl/qsslcontext_openssl.cpp b/qtbase/src/network/ssl/qsslcontext_openssl.cpp
index c9f202f573..c992da9d8e 100644
--- a/qtbase/src/network/ssl/qsslcontext_openssl.cpp
+++ b/qtbase/src/network/ssl/qsslcontext_openssl.cpp
@@ -409,7 +409,7 @@ init_context:
break;
case QSsl::DtlsV1_0OrLater:
minVersion = DTLS1_VERSION;
- maxVersion = DTLS_MAX_VERSION;
+ maxVersion = 0;
break;
case QSsl::DtlsV1_2:
minVersion = DTLS1_2_VERSION;
@@ -417,7 +417,7 @@ init_context:
break;
case QSsl::DtlsV1_2OrLater:
minVersion = DTLS1_2_VERSION;
- maxVersion = DTLS_MAX_VERSION;
+ maxVersion = 0;
break;
case QSsl::TlsV1_3OrLater:
#ifdef TLS1_3_VERSION
@@ -455,7 +455,7 @@ init_context:
}
// Enable bug workarounds.
- long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
+ qssloptions options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
q_SSL_CTX_set_options(sslContext->ctx, options);
// Tell OpenSSL to release memory early
diff --git a/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
index aaf8741130..b58935372c 100644
--- a/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
+++ b/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
@@ -59,57 +59,6 @@
QT_BEGIN_NAMESPACE
-#ifdef OPENSSL_NO_DEPRECATED_3_0
-
-static int q_DH_check(DH *dh, int *status)
-{
- // DH_check was first deprecated in OpenSSL 3.0.0, as low-level
- // API; the EVP_PKEY family of functions was advised as an alternative.
- // As of now EVP_PKEY_params_check ends up calling ... DH_check,
- // which is good enough.
-
- Q_ASSERT(dh);
- Q_ASSERT(status);
-
- EVP_PKEY *key = q_EVP_PKEY_new();
- if (!key) {
- qCWarning(lcSsl, "EVP_PKEY_new failed");
- QSslSocketBackendPrivate::logAndClearErrorQueue();
- return 0;
- }
- const auto keyDeleter = qScopeGuard([key](){
- q_EVP_PKEY_free(key);
- });
- if (!q_EVP_PKEY_set1_DH(key, dh)) {
- qCWarning(lcSsl, "EVP_PKEY_set1_DH failed");
- QSslSocketBackendPrivate::logAndClearErrorQueue();
- return 0;
- }
-
- EVP_PKEY_CTX *keyCtx = q_EVP_PKEY_CTX_new(key, nullptr);
- if (!keyCtx) {
- qCWarning(lcSsl, "EVP_PKEY_CTX_new failed");
- QSslSocketBackendPrivate::logAndClearErrorQueue();
- return 0;
- }
- const auto ctxDeleter = qScopeGuard([keyCtx]{
- q_EVP_PKEY_CTX_free(keyCtx);
- });
-
- const int result = q_EVP_PKEY_param_check(keyCtx);
- QSslSocketBackendPrivate::logAndClearErrorQueue();
- // Note: unlike DH_check, we cannot obtain the 'status',
- // if the 'result' is 0 (actually the result is 1 only
- // if this 'status' was 0). We could probably check the
- // errors from the error queue, but it's not needed anyway
- // - see the 'isSafeDH' below, how it returns immediately
- // on 0.
- Q_UNUSED(status)
-
- return result;
-}
-#endif // OPENSSL_NO_DEPRECATED_3_0
-
static bool isSafeDH(DH *dh)
{
int status = 0;
diff --git a/qtbase/src/network/ssl/qsslsocket.cpp b/qtbase/src/network/ssl/qsslsocket.cpp
index 5bb6e7ee4a..2a0b3a4f1d 100644
--- a/qtbase/src/network/ssl/qsslsocket.cpp
+++ b/qtbase/src/network/ssl/qsslsocket.cpp
@@ -2221,6 +2221,10 @@ QSslSocketPrivate::QSslSocketPrivate()
, flushTriggered(false)
{
QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration);
+ // If the global configuration doesn't allow root certificates to be loaded
+ // on demand then we have to disable it for this socket as well.
+ if (!configuration.allowRootCertOnDemandLoading)
+ allowRootCertOnDemandLoading = false;
}
/*!
@@ -2470,6 +2474,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
ptr->sessionProtocol = global->sessionProtocol;
ptr->ciphers = global->ciphers;
ptr->caCertificates = global->caCertificates;
+ ptr->allowRootCertOnDemandLoading = global->allowRootCertOnDemandLoading;
ptr->protocol = global->protocol;
ptr->peerVerifyMode = global->peerVerifyMode;
ptr->peerVerifyDepth = global->peerVerifyDepth;
diff --git a/qtbase/src/network/ssl/qsslsocket_mac.cpp b/qtbase/src/network/ssl/qsslsocket_mac.cpp
index 77e847e972..e38a5e75de 100644
--- a/qtbase/src/network/ssl/qsslsocket_mac.cpp
+++ b/qtbase/src/network/ssl/qsslsocket_mac.cpp
@@ -468,6 +468,7 @@ void QSslSocketBackendPrivate::disconnectFromHost()
if (context) {
if (!shutdown) {
SSLClose(context);
+ context.reset(nullptr);
shutdown = true;
}
}
diff --git a/qtbase/src/network/ssl/qsslsocket_openssl.cpp b/qtbase/src/network/ssl/qsslsocket_openssl.cpp
index 37fad2a68f..8f6858c867 100644
--- a/qtbase/src/network/ssl/qsslsocket_openssl.cpp
+++ b/qtbase/src/network/ssl/qsslsocket_openssl.cpp
@@ -550,9 +550,9 @@ static void q_loadCiphersForConnection(SSL *connection, QList &ciphe
// Defined in qsslsocket.cpp
void q_setDefaultDtlsCiphers(const QList &ciphers);
-long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
+qssloptions QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
{
- long options;
+ qssloptions options;
if (protocol == QSsl::TlsV1SslV3)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
else if (protocol == QSsl::SecureProtocols)
diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_p.h b/qtbase/src/network/ssl/qsslsocket_openssl_p.h
index 4103de23e8..5547589256 100644
--- a/qtbase/src/network/ssl/qsslsocket_openssl_p.h
+++ b/qtbase/src/network/ssl/qsslsocket_openssl_p.h
@@ -107,6 +107,12 @@
QT_BEGIN_NAMESPACE
+#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
+typedef uint64_t qssloptions;
+#else
+typedef unsigned long qssloptions;
+#endif
+
struct QSslErrorEntry {
int code;
int depth;
@@ -171,7 +177,7 @@ public:
QVector ocspErrors;
QByteArray ocspResponseDer;
- Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
+ Q_AUTOTEST_EXPORT static qssloptions setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
static QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher);
static QList STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
static QList verify(const QList &certificateChain, const QString &hostName);
diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp b/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
index e53fb279f0..459ccd0b19 100644
--- a/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -148,7 +148,6 @@ DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *a, a, return 0, return)
DEFINEFUNC2(EVP_PKEY_CTX *, EVP_PKEY_CTX_new, EVP_PKEY *pkey, pkey, ENGINE *e, e, return nullptr, return)
DEFINEFUNC(int, EVP_PKEY_param_check, EVP_PKEY_CTX *ctx, ctx, return 0, return)
DEFINEFUNC(void, EVP_PKEY_CTX_free, EVP_PKEY_CTX *ctx, ctx, return, return)
-DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return)
DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return)
DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return)
DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return)
@@ -158,7 +157,7 @@ DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMM
DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG)
DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return)
DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return)
-DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return)
+DEFINEFUNC2(qssloptions, SSL_CTX_set_options, SSL_CTX *ctx, ctx, qssloptions op, op, return 0, return)
DEFINEFUNC(int, SSL_CTX_get_security_level, const SSL_CTX *ctx, ctx, return -1, return)
DEFINEFUNC2(void, SSL_CTX_set_security_level, SSL_CTX *ctx, ctx, int level, level, return, return)
#ifdef TLS1_3_VERSION
@@ -371,7 +370,15 @@ DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr
DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return)
DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return nullptr, return)
+
+#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
+DEFINEFUNC(X509 *, SSL_get1_peer_certificate, SSL *a, a, return nullptr, return)
+DEFINEFUNC(int, EVP_PKEY_get_base_id, const EVP_PKEY *pkey, pkey, return -1, return)
+#else
DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return nullptr, return)
+DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return)
+#endif // OPENSSL_VERSION_MAJOR >= 3
+
DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return)
DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return nullptr, return)
DEFINEFUNC(SSL_CTX *, SSL_get_SSL_CTX, SSL *a, a, return nullptr, return)
@@ -492,9 +499,7 @@ DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG)
DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return)
DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return)
-#ifndef OPENSSL_NO_DEPRECATED_3_0
DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return)
-#endif // OPENSSL_NO_DEPRECATED_3_0
DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return)
#ifndef OPENSSL_NO_EC
@@ -868,7 +873,6 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(EVP_PKEY_CTX_new)
RESOLVEFUNC(EVP_PKEY_param_check)
RESOLVEFUNC(EVP_PKEY_CTX_free)
- RESOLVEFUNC(EVP_PKEY_base_id)
RESOLVEFUNC(RSA_bits)
RESOLVEFUNC(OPENSSL_sk_new_null)
RESOLVEFUNC(OPENSSL_sk_push)
@@ -1107,7 +1111,15 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_version)
RESOLVEFUNC(SSL_get_error)
RESOLVEFUNC(SSL_get_peer_cert_chain)
+
+#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
+ RESOLVEFUNC(SSL_get1_peer_certificate)
+ RESOLVEFUNC(EVP_PKEY_get_base_id)
+#else
RESOLVEFUNC(SSL_get_peer_certificate)
+ RESOLVEFUNC(EVP_PKEY_base_id)
+#endif // OPENSSL_VERSION_MAJOR >= 3
+
RESOLVEFUNC(SSL_get_verify_result)
RESOLVEFUNC(SSL_new)
RESOLVEFUNC(SSL_get_SSL_CTX)
@@ -1206,9 +1218,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(DH_free)
RESOLVEFUNC(d2i_DHparams)
RESOLVEFUNC(i2d_DHparams)
-#ifndef OPENSSL_NO_DEPRECATED_3_0
RESOLVEFUNC(DH_check)
-#endif // OPENSSL_NO_DEPRECATED_3_0
RESOLVEFUNC(BN_bin2bn)
#ifndef OPENSSL_NO_EC
diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h b/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 95e8897a3b..27aeffa18a 100644
--- a/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -237,7 +237,6 @@ Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref(EVP_PKEY *a);
EVP_PKEY_CTX *q_EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
void q_EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
int q_EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
-int q_EVP_PKEY_base_id(EVP_PKEY *a);
int q_RSA_bits(RSA *a);
Q_AUTOTEST_EXPORT int q_OPENSSL_sk_num(OPENSSL_STACK *a);
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
@@ -246,7 +245,7 @@ Q_AUTOTEST_EXPORT void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_free(OPENSSL_STACK *a);
Q_AUTOTEST_EXPORT void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
int q_SSL_session_reused(SSL *a);
-unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
+qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions op);
int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen);
size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen);
@@ -510,7 +509,6 @@ const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
int q_SSL_version(const SSL *a);
int q_SSL_get_error(SSL *a, int b);
STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a);
-X509 *q_SSL_get_peer_certificate(SSL *a);
long q_SSL_get_verify_result(const SSL *a);
SSL *q_SSL_new(SSL_CTX *a);
SSL_CTX *q_SSL_get_SSL_CTX(SSL *a);
@@ -582,10 +580,7 @@ DH *q_DH_new();
void q_DH_free(DH *dh);
DH *q_d2i_DHparams(DH **a, const unsigned char **pp, long length);
int q_i2d_DHparams(DH *a, unsigned char **p);
-
-#ifndef OPENSSL_NO_DEPRECATED_3_0
int q_DH_check(DH *dh, int *codes);
-#endif // OPENSSL_NO_DEPRECATED_3_0
BIGNUM *q_BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
#define q_SSL_CTX_set_tmp_dh(ctx, dh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_DH, 0, (char *)dh)
@@ -754,6 +749,17 @@ void q_CRYPTO_free(void *str, const char *file, int line);
int q_SSL_CTX_get_security_level(const SSL_CTX *ctx);
void q_SSL_CTX_set_security_level(SSL_CTX *ctx, int level);
+// Here we have the ones that make difference between OpenSSL pre/post v3:
+#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
+X509 *q_SSL_get1_peer_certificate(SSL *a);
+#define q_SSL_get_peer_certificate q_SSL_get1_peer_certificate
+int q_EVP_PKEY_get_base_id(const EVP_PKEY *pkey);
+#define q_EVP_PKEY_base_id q_EVP_PKEY_get_base_id
+#else
+X509 *q_SSL_get_peer_certificate(SSL *a);
+int q_EVP_PKEY_base_id(EVP_PKEY *a);
+#endif // OPENSSL_VERSION_MAJOR >= 3
+
QT_END_NAMESPACE
#endif
diff --git a/qtbase/src/network/ssl/qsslsocket_schannel.cpp b/qtbase/src/network/ssl/qsslsocket_schannel.cpp
index c956ce3c2b..d1b23af29b 100644
--- a/qtbase/src/network/ssl/qsslsocket_schannel.cpp
+++ b/qtbase/src/network/ssl/qsslsocket_schannel.cpp
@@ -1880,6 +1880,28 @@ bool QSslSocketBackendPrivate::verifyCertContext(CERT_CONTEXT *certContext)
if (configuration.peerVerifyDepth > 0 && DWORD(configuration.peerVerifyDepth) < verifyDepth)
verifyDepth = DWORD(configuration.peerVerifyDepth);
+ const auto &caCertificates = q->sslConfiguration().caCertificates();
+
+ if (!rootCertOnDemandLoadingAllowed()
+ && !(chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_PARTIAL_CHAIN)
+ && (q->peerVerifyMode() == QSslSocket::VerifyPeer
+ || (isClient && q->peerVerifyMode() == QSslSocket::AutoVerifyPeer))) {
+ // When verifying a peer Windows "helpfully" builds a chain that
+ // may include roots from the system store. But we don't want that if
+ // the user has set their own CA certificates.
+ // Since Windows claims this is not a partial chain the root is included
+ // and we have to check that it is one of our configured CAs.
+ CERT_CHAIN_ELEMENT *element = chain->rgpElement[chain->cElement - 1];
+ QSslCertificate certificate = getCertificateFromChainElement(element);
+ if (!caCertificates.contains(certificate)) {
+ auto error = QSslError(QSslError::CertificateUntrusted, certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ }
+
for (DWORD i = 0; i < verifyDepth; i++) {
CERT_CHAIN_ELEMENT *element = chain->rgpElement[i];
QSslCertificate certificate = getCertificateFromChainElement(element);
diff --git a/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h b/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h
index bf37d07fd8..dbd42fb799 100644
--- a/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h
+++ b/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h
@@ -61,7 +61,11 @@
# if !defined(Q_OS_INTEGRITY)
# define WIN_INTERFACE_CUSTOM // NV
# endif // Q_OS_INTEGRITY
-#endif // QT_EGL_NO_X11
+#else // QT_EGL_NO_X11
+// If one has an eglplatform.h with https://github.com/KhronosGroup/EGL-Registry/pull/130
+// that needs USE_X11 to be defined.
+# define USE_X11
+#endif
#ifdef QT_EGL_WAYLAND
# define WAYLAND // NV
diff --git a/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index 159b490ce0..00aa80cd58 100644
--- a/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -567,6 +567,8 @@ void QFontconfigDatabase::populateFontDatabase()
fonts = FcFontList(nullptr, pattern, os);
FcObjectSetDestroy(os);
FcPatternDestroy(pattern);
+ if (!fonts)
+ return;
}
for (int i = 0; i < fonts->nfont; i++)
diff --git a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
index b713c19447..7cb9a8c79a 100644
--- a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
+++ b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
@@ -95,6 +95,7 @@ static constexpr const auto KeyTbl = qMakeArray(
Xkb2Qt,
Xkb2Qt,
Xkb2Qt,
+ Xkb2Qt,
Xkb2Qt<0x1005FF60, Qt::Key_SysReq>, // hardcoded Sun SysReq
Xkb2Qt<0x1007ff00, Qt::Key_SysReq>, // hardcoded X386 SysReq
@@ -471,7 +472,7 @@ QVector QXkbCommon::toKeysym(QKeyEvent *event)
} else if (event->modifiers() & Qt::KeypadModifier) {
if (qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9)
keysyms.append(XKB_KEY_KP_0 + (qtKey - Qt::Key_0));
- } else if (isLatin(qtKey) && event->text().isUpper()) {
+ } else if (isLatin1(qtKey) && event->text().isUpper()) {
keysyms.append(qtKey);
}
@@ -523,7 +524,7 @@ int QXkbCommon::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifie
// With standard shortcuts we should prefer a latin character, this is
// for checks like "some qkeyevent == QKeySequence::Copy" to work even
// when using for example 'russian' keyboard layout.
- if (!QXkbCommon::isLatin(keysym)) {
+ if (!QXkbCommon::isLatin1(keysym)) {
xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code);
if (latinKeysym != XKB_KEY_NoSymbol)
keysym = latinKeysym;
@@ -546,7 +547,7 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod
} else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) {
// numeric keypad keys
qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0);
- } else if (QXkbCommon::isLatin(keysym)) {
+ } else if (QXkbCommon::isLatin1(keysym)) {
qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym);
} else {
// check if we have a direct mapping
@@ -678,7 +679,7 @@ QList QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event,
Qt::KeyboardModifiers neededMods = ModsTbl[i];
if ((modifiers & neededMods) == neededMods) {
if (i == 8) {
- if (isLatin(baseQtKey))
+ if (isLatin1(baseQtKey))
continue;
// add a latin key as a fall back key
sym = lookupLatinKeysym(state, keycode);
@@ -733,7 +734,7 @@ void QXkbCommon::verifyHasLatinLayout(xkb_keymap *keymap)
for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
xkb_keymap_key_get_syms_by_level(keymap, code, layout, 0, &keysyms);
- if (keysyms && isLatin(keysyms[0]))
+ if (keysyms && isLatin1(keysyms[0]))
nrLatinKeys++;
if (nrLatinKeys > 10) // arbitrarily chosen threshold
return;
@@ -766,7 +767,7 @@ xkb_keysym_t QXkbCommon::lookupLatinKeysym(xkb_state *state, xkb_keycode_t keyco
xkb_level_index_t level = xkb_state_key_get_level(state, keycode, layout);
if (xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms) != 1)
continue;
- if (isLatin(syms[0])) {
+ if (isLatin1(syms[0])) {
sym = syms[0];
break;
}
diff --git a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
index 561eae03db..8389bd8f5a 100644
--- a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
+++ b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
@@ -94,8 +94,8 @@ public:
static void verifyHasLatinLayout(xkb_keymap *keymap);
static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode);
- static bool isLatin(xkb_keysym_t sym) {
- return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z'));
+ static bool isLatin1(xkb_keysym_t sym) {
+ return sym <= 0xff;
}
static bool isKeypad(xkb_keysym_t sym) {
return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9;
diff --git a/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp
index 8cd7f9b368..406f84663f 100644
--- a/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp
+++ b/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -318,7 +318,7 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
if (current < 0 && crtc_mode.clock != 0) {
modes << crtc_mode;
- current = mode.size() - 1;
+ current = modes.size() - 1;
}
if (configuration == OutputConfigCurrent)
diff --git a/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
index 9153fd20bb..255ea5e33e 100644
--- a/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
+++ b/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
@@ -194,6 +194,9 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" \n"
" \n"
" \n"
+ " \n"
+ " \n"
+ " \n"
" \n"
);
@@ -913,8 +916,17 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
}
case QAccessible::NameChanged: {
if (sendObject || sendObject_property_change || sendObject_property_change_accessible_name) {
- QString path = pathForInterface(event->accessibleInterface());
- QVariantList args = packDBusSignalArguments(QLatin1String("accessible-name"), 0, 0, variantForPath(path));
+ QAccessibleInterface *iface = event->accessibleInterface();
+ if (!iface) {
+ qCDebug(lcAccessibilityAtspi,
+ "NameChanged event from invalid accessible.");
+ return;
+ }
+
+ QString path = pathForInterface(iface);
+ QVariantList args = packDBusSignalArguments(
+ QLatin1String("accessible-name"), 0, 0,
+ QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Name))));
sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
QLatin1String("PropertyChange"), args);
}
@@ -922,8 +934,17 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
}
case QAccessible::DescriptionChanged: {
if (sendObject || sendObject_property_change || sendObject_property_change_accessible_description) {
- QString path = pathForInterface(event->accessibleInterface());
- QVariantList args = packDBusSignalArguments(QLatin1String("accessible-description"), 0, 0, variantForPath(path));
+ QAccessibleInterface *iface = event->accessibleInterface();
+ if (!iface) {
+ qCDebug(lcAccessibilityAtspi,
+ "DescriptionChanged event from invalid accessible.");
+ return;
+ }
+
+ QString path = pathForInterface(iface);
+ QVariantList args = packDBusSignalArguments(
+ QLatin1String("accessible-description"), 0, 0,
+ QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Description))));
sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
QLatin1String("PropertyChange"), args);
}
@@ -1038,7 +1059,9 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
// Combo Box with AT-SPI likes to be special
// It requires a name-change to update caches and then selection-changed
QString path = pathForInterface(iface);
- QVariantList args1 = packDBusSignalArguments(QLatin1String("accessible-name"), 0, 0, variantForPath(path));
+ QVariantList args1 = packDBusSignalArguments(
+ QLatin1String("accessible-name"), 0, 0,
+ QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Name))));
sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
QLatin1String("PropertyChange"), args1);
QVariantList args2 = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(QDBusVariant(QVariant(0))));
@@ -1358,6 +1381,26 @@ void AtSpiAdaptor::registerApplication()
delete registry;
}
+namespace {
+QString accessibleIdForAccessible(QAccessibleInterface *accessible)
+{
+ QString result;
+ while (accessible) {
+ if (!result.isEmpty())
+ result.prepend(QLatin1Char('.'));
+ if (auto obj = accessible->object()) {
+ const QString name = obj->objectName();
+ if (!name.isEmpty())
+ result.prepend(name);
+ else
+ result.prepend(QString::fromUtf8(obj->metaObject()->className()));
+ }
+ accessible = accessible->parent();
+ }
+ return result;
+}
+} // namespace
+
// Accessible
bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
{
@@ -1441,6 +1484,9 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
children << ref;
}
connection.send(message.createReply(QVariant::fromValue(children)));
+ } else if (function == QLatin1String("GetAccessibleId")) {
+ sendReply(connection, message,
+ QVariant::fromValue(QDBusVariant(accessibleIdForAccessible(interface))));
} else {
qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::accessibleInterface does not implement " << function << message.path();
return false;
diff --git a/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp b/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp
index 45ddc8e496..cc734abc63 100644
--- a/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp
+++ b/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp
@@ -69,6 +69,21 @@ QT_BEGIN_NAMESPACE
DBusConnection::DBusConnection(QObject *parent)
: QObject(parent), m_a11yConnection(QString()), m_enabled(false)
{
+ // If the bus is explicitly set via env var it overrides everything else.
+ QByteArray addressEnv = qgetenv("AT_SPI_BUS_ADDRESS");
+ if (!addressEnv.isEmpty()) {
+ // Only connect on next loop run, connections to our enabled signal are
+ // only established after the ctor returns.
+ QMetaObject::invokeMethod(
+ this,
+ [this, addressEnv] {
+ m_enabled = true;
+ connectA11yBus(QString::fromLocal8Bit(addressEnv));
+ },
+ Qt::QueuedConnection);
+ return;
+ }
+
// Start monitoring if "org.a11y.Bus" is registered as DBus service.
QDBusConnection c = QDBusConnection::sessionBus();
if (!c.isConnected()) {
diff --git a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp
index 1a3cab275d..2abe039126 100644
--- a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp
+++ b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp
@@ -51,6 +51,9 @@
#include
#include
+#include
+#include
+
#if QT_CONFIG(dbus)
// These QtCore includes are needed for xdg-desktop-portal support
#include
@@ -58,6 +61,8 @@
#include
#include
+#include
+
#include
#include
#include
@@ -142,6 +147,8 @@ static inline bool detectWebBrowser(const QByteArray &desktop,
}
if (desktop == QByteArray("KDE")) {
+ if (checkExecutable(QStringLiteral("kde-open5"), browser))
+ return true;
// Konqueror launcher
if (checkExecutable(QStringLiteral("kfmclient"), browser)) {
browser->append(QLatin1String(" exec"));
@@ -296,8 +303,135 @@ static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url)
return QDBusConnection::sessionBus().call(message);
}
+
+namespace {
+struct XDGDesktopColor
+{
+ double r = 0;
+ double g = 0;
+ double b = 0;
+
+ QColor toQColor() const
+ {
+ constexpr auto rgbMax = 255;
+ return { static_cast(r * rgbMax), static_cast(g * rgbMax),
+ static_cast(b * rgbMax) };
+ }
+};
+
+const QDBusArgument &operator>>(const QDBusArgument &argument, XDGDesktopColor &myStruct)
+{
+ argument.beginStructure();
+ argument >> myStruct.r >> myStruct.g >> myStruct.b;
+ argument.endStructure();
+ return argument;
+}
+
+class XdgDesktopPortalColorPicker : public QPlatformServiceColorPicker
+{
+ Q_OBJECT
+public:
+ XdgDesktopPortalColorPicker(const QString &parentWindowId, QWindow *parent)
+ : QPlatformServiceColorPicker(parent), m_parentWindowId(parentWindowId)
+ {
+ }
+
+ void pickColor() override
+ {
+ // DBus signature:
+ // PickColor (IN s parent_window,
+ // IN a{sv} options
+ // OUT o handle)
+ // Options:
+ // handle_token (s) - A string that will be used as the last element of the @handle.
+
+ QDBusMessage message = QDBusMessage::createMethodCall(
+ QStringLiteral("org.freedesktop.portal.Desktop"), QStringLiteral("/org/freedesktop/portal/desktop"),
+ QStringLiteral("org.freedesktop.portal.Screenshot"), QStringLiteral("PickColor"));
+ message << m_parentWindowId << QVariantMap();
+
+ QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
+ auto watcher = new QDBusPendingCallWatcher(pendingCall, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this,
+ [this](QDBusPendingCallWatcher *watcher) {
+ watcher->deleteLater();
+ QDBusPendingReply reply = *watcher;
+ if (reply.isError()) {
+ qWarning("DBus call to pick color failed: %s",
+ qPrintable(reply.error().message()));
+ Q_EMIT colorPicked({});
+ } else {
+ QDBusConnection::sessionBus().connect(
+ QStringLiteral("org.freedesktop.portal.Desktop"), reply.value().path(),
+ QStringLiteral("org.freedesktop.portal.Request"), QStringLiteral("Response"), this,
+ // clang-format off
+ SLOT(gotColorResponse(uint,QVariantMap))
+ // clang-format on
+ );
+ }
+ });
+ }
+
+private Q_SLOTS:
+ void gotColorResponse(uint result, const QVariantMap &map)
+ {
+ if (result != 0)
+ return;
+ XDGDesktopColor color{};
+ map.value(QStringLiteral("color")).value() >> color;
+ Q_EMIT colorPicked(color.toQColor());
+ deleteLater();
+ }
+
+private:
+ const QString m_parentWindowId;
+};
+} // namespace
+
#endif // QT_CONFIG(dbus)
+QGenericUnixServices::QGenericUnixServices()
+{
+#if QT_CONFIG(dbus)
+ if (qEnvironmentVariableIntValue("QT_NO_XDG_DESKTOP_PORTAL") > 0) {
+ return;
+ }
+ QDBusMessage message = QDBusMessage::createMethodCall(
+ QStringLiteral("org.freedesktop.portal.Desktop"), QStringLiteral("/org/freedesktop/portal/desktop"),
+ QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("Get"));
+ message << QStringLiteral("org.freedesktop.portal.Screenshot")
+ << QStringLiteral("version");
+
+ QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
+ auto watcher = new QDBusPendingCallWatcher(pendingCall);
+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, watcher,
+ [this](QDBusPendingCallWatcher *watcher) {
+ watcher->deleteLater();
+ QDBusPendingReply reply = *watcher;
+ if (!reply.isError() && reply.value().toUInt() >= 2)
+ m_hasScreenshotPortalWithColorPicking = true;
+ });
+
+#endif
+}
+
+QPlatformServiceColorPicker *QGenericUnixServices::colorPicker(QWindow *parent)
+{
+#if QT_CONFIG(dbus)
+ // Make double sure that we are in a wayland environment. In particular check
+ // WAYLAND_DISPLAY so also XWayland apps benefit from portal-based color picking.
+ // Outside wayland we'll rather rely on other means than the XDG desktop portal.
+ if (!qEnvironmentVariableIsEmpty("WAYLAND_DISPLAY")
+ || QGuiApplication::platformName().startsWith(QLatin1String("wayland"))) {
+ return new XdgDesktopPortalColorPicker(portalWindowIdentifier(parent), parent);
+ }
+ return nullptr;
+#else
+ Q_UNUSED(parent);
+ return nullptr;
+#endif
+}
+
QByteArray QGenericUnixServices::desktopEnvironment() const
{
static const QByteArray result = detectDesktopEnvironment();
@@ -352,6 +486,8 @@ bool QGenericUnixServices::openDocument(const QUrl &url)
}
#else
+QGenericUnixServices::QGenericUnixServices() = default;
+
QByteArray QGenericUnixServices::desktopEnvironment() const
{
return QByteArrayLiteral("UNKNOWN");
@@ -371,6 +507,30 @@ bool QGenericUnixServices::openDocument(const QUrl &url)
return false;
}
+QPlatformServiceColorPicker *QGenericUnixServices::colorPicker(QWindow *parent)
+{
+ Q_UNUSED(parent);
+ return nullptr;
+}
+
#endif // QT_NO_MULTIPROCESS
+QString QGenericUnixServices::portalWindowIdentifier(QWindow *window)
+{
+ if (QGuiApplication::platformName() == QLatin1String("xcb"))
+ return QStringLiteral("x11:") + QString::number(window->winId(), 16);
+ return QString();
+}
+
+bool QGenericUnixServices::hasCapability(Capability capability) const
+{
+ switch (capability) {
+ case Capability::ColorPicking:
+ return m_hasScreenshotPortalWithColorPicking;
+ }
+ return false;
+}
+
QT_END_NAMESPACE
+
+#include "qgenericunixservices.moc"
diff --git a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h
index 8ac3de6f03..30924e64bd 100644
--- a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h
+++ b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h
@@ -59,16 +59,21 @@ QT_BEGIN_NAMESPACE
class QGenericUnixServices : public QPlatformServices
{
public:
- QGenericUnixServices() {}
+ QGenericUnixServices();
QByteArray desktopEnvironment() const override;
+ bool hasCapability(Capability capability) const override;
bool openUrl(const QUrl &url) override;
bool openDocument(const QUrl &url) override;
+ QPlatformServiceColorPicker *colorPicker(QWindow *parent = nullptr) override;
+
+ virtual QString portalWindowIdentifier(QWindow *window);
private:
QString m_webBrowser;
QString m_documentLauncher;
+ bool m_hasScreenshotPortalWithColorPicking = false;
};
QT_END_NAMESPACE
diff --git a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
index 09470bccc6..cc7c7d4d8a 100644
--- a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
+++ b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
@@ -69,6 +69,7 @@ const QString MenuBarPath = QLatin1String("/MenuBar");
*/
QDBusMenuConnection::QDBusMenuConnection(QObject *parent, const QString &serviceName)
: QObject(parent)
+ , m_serviceName(serviceName)
, m_connection(serviceName.isNull() ? QDBusConnection::sessionBus()
: QDBusConnection::connectToBus(QDBusConnection::SessionBus, serviceName))
, m_dbusWatcher(new QDBusServiceWatcher(StatusNotifierWatcherService, m_connection, QDBusServiceWatcher::WatchForRegistration, this))
@@ -83,6 +84,12 @@ QDBusMenuConnection::QDBusMenuConnection(QObject *parent, const QString &service
#endif
}
+QDBusMenuConnection::~QDBusMenuConnection()
+{
+ if (!m_serviceName.isEmpty() && m_connection.isConnected())
+ QDBusConnection::disconnectFromBus(m_serviceName);
+}
+
void QDBusMenuConnection::dbusError(const QDBusError &error)
{
qWarning() << "QDBusTrayIcon encountered a D-Bus error:" << error;
@@ -105,13 +112,7 @@ void QDBusMenuConnection::unregisterTrayIconMenu(QDBusTrayIcon *item)
bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item)
{
- bool success = connection().registerService(item->instanceId());
- if (!success) {
- qWarning() << "failed to register service" << item->instanceId();
- return false;
- }
-
- success = connection().registerObject(StatusNotifierItemPath, item);
+ bool success = connection().registerObject(StatusNotifierItemPath, item);
if (!success) {
unregisterTrayIcon(item);
qWarning() << "failed to register" << item->instanceId() << StatusNotifierItemPath;
@@ -126,21 +127,18 @@ bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item)
bool QDBusMenuConnection::registerTrayIconWithWatcher(QDBusTrayIcon *item)
{
+ Q_UNUSED(item);
QDBusMessage registerMethod = QDBusMessage::createMethodCall(
StatusNotifierWatcherService, StatusNotifierWatcherPath, StatusNotifierWatcherService,
QLatin1String("RegisterStatusNotifierItem"));
- registerMethod.setArguments(QVariantList() << item->instanceId());
+ registerMethod.setArguments(QVariantList() << m_connection.baseService());
return m_connection.callWithCallback(registerMethod, this, SIGNAL(trayIconRegistered()), SLOT(dbusError(QDBusError)));
}
-bool QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item)
+void QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item)
{
unregisterTrayIconMenu(item);
connection().unregisterObject(StatusNotifierItemPath);
- bool success = connection().unregisterService(item->instanceId());
- if (!success)
- qWarning() << "failed to unregister service" << item->instanceId();
- return success;
}
#endif // QT_NO_SYSTEMTRAYICON
diff --git a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
index f484795fbb..97bdfabb85 100644
--- a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
+++ b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
@@ -70,6 +70,7 @@ class QDBusMenuConnection : public QObject
public:
QDBusMenuConnection(QObject *parent = nullptr, const QString &serviceName = QString());
+ ~QDBusMenuConnection();
QDBusConnection connection() const { return m_connection; }
QDBusServiceWatcher *dbusWatcher() const { return m_dbusWatcher; }
bool isStatusNotifierHostRegistered() const { return m_statusNotifierHostRegistered; }
@@ -78,7 +79,7 @@ public:
void unregisterTrayIconMenu(QDBusTrayIcon *item);
bool registerTrayIcon(QDBusTrayIcon *item);
bool registerTrayIconWithWatcher(QDBusTrayIcon *item);
- bool unregisterTrayIcon(QDBusTrayIcon *item);
+ void unregisterTrayIcon(QDBusTrayIcon *item);
#endif // QT_NO_SYSTEMTRAYICON
Q_SIGNALS:
@@ -90,6 +91,7 @@ private Q_SLOTS:
void dbusError(const QDBusError &error);
private:
+ QString m_serviceName;
QDBusConnection m_connection;
QDBusServiceWatcher *m_dbusWatcher;
bool m_statusNotifierHostRegistered;
diff --git a/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index cb1b39db64..6e01af052c 100644
--- a/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -755,6 +755,9 @@ QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
return QVariant(QChar(0x2022));
case QPlatformTheme::UiEffects:
return QVariant(int(HoverEffect));
+ case QPlatformTheme::ButtonPressKeys:
+ return QVariant::fromValue(
+ QList({ Qt::Key_Space, Qt::Key_Return, Qt::Key_Enter, Qt::Key_Select }));
default:
break;
}
diff --git a/qtbase/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml b/qtbase/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml
index 9c67a38c57..30c326d06f 100644
--- a/qtbase/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml
+++ b/qtbase/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.InputContext.xml
@@ -14,6 +14,12 @@
+
+
+
+
+
+
diff --git a/qtbase/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h b/qtbase/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
index 396a213aaa..31d5a71c41 100644
--- a/qtbase/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
+++ b/qtbase/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
@@ -112,6 +112,13 @@ public Q_SLOTS: // METHODS
return asyncCallWithArgumentList(QLatin1String("SetCursorLocation"), argumentList);
}
+ inline QDBusPendingReply<> SetCursorLocationRelative(int x, int y, int w, int h)
+ {
+ QList argumentList;
+ argumentList << QVariant::fromValue(x) << QVariant::fromValue(y) << QVariant::fromValue(w) << QVariant::fromValue(h);
+ return asyncCallWithArgumentList(QLatin1String("SetCursorLocationRelative"), argumentList);
+ }
+
inline QDBusPendingReply<> SetEngine(const QString &name)
{
QList argumentList;
diff --git a/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp b/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
index b35935bb5b..a3d6df7d11 100644
--- a/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
+++ b/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
@@ -343,8 +343,7 @@ void QEglFSCursor::paintOnScreen()
// screens are siblings of each other. When not enabled, the sibling list
// only contains m_screen itself.
for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
- if (screen->geometry().contains(cr.topLeft().toPoint() + m_cursor.hotSpot)
- && QOpenGLContext::currentContext()->screen() == screen->screen())
+ if (screen->geometry().contains(cr.topLeft().toPoint() + m_cursor.hotSpot))
{
cr.translate(-screen->geometry().topLeft());
const QSize screenSize = screen->geometry().size();
@@ -468,11 +467,12 @@ void QEglFSCursor::draw(const QRectF &r)
{
StateSaver stateSaver;
- QEglFSCursorData &gfx = static_cast(QOpenGLContext::currentContext()->handle())->cursorData;
- if (!gfx.program) {
- // one time initialization
+ // one time initialization
+ if (!QOpenGLFunctions::d_ptr)
initializeOpenGLFunctions();
+ QEglFSCursorData &gfx = static_cast(QOpenGLContext::currentContext()->handle())->cursorData;
+ if (!gfx.program) {
createShaderPrograms();
if (!gfx.atlasTexture) {
diff --git a/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp b/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp
index 645a0ae2e9..3e0e406f1a 100644
--- a/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp
+++ b/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp
@@ -179,7 +179,7 @@ void QEglFSKmsEventReader::create(QEglFSKmsDevice *device)
m_device = device;
- qCDebug(qLcEglfsKmsDebug, "Initalizing event reader for device %p fd %d",
+ qCDebug(qLcEglfsKmsDebug, "Initializing event reader for device %p fd %d",
m_device, m_device->fd());
m_thread = new QEglFSKmsEventReaderThread(m_device->fd());
diff --git a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
index 141fb68a23..d4294d425a 100644
--- a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
+++ b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
@@ -122,11 +122,13 @@ QOffscreenIntegration::QOffscreenIntegration()
#endif
m_services.reset(new QPlatformServices);
- QWindowSystemInterface::handleScreenAdded(new QOffscreenScreen);
+ m_screen = new QOffscreenScreen;
+ QWindowSystemInterface::handleScreenAdded(m_screen);
}
QOffscreenIntegration::~QOffscreenIntegration()
{
+ QWindowSystemInterface::handleScreenRemoved(m_screen);
}
void QOffscreenIntegration::initialize()
diff --git a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h
index 0ea90f6c2f..fe00fde07c 100644
--- a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h
+++ b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h
@@ -84,6 +84,7 @@ protected:
#endif
QScopedPointer m_inputContext;
QScopedPointer m_services;
+ QPlatformScreen *m_screen;
mutable QScopedPointer m_nativeInterface;
};
diff --git a/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp b/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
index 1afa00cfc9..118af6ce73 100644
--- a/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
+++ b/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
@@ -41,6 +41,7 @@
#include
#include
+#include
#include
#include
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbatom.cpp b/qtbase/src/plugins/platforms/xcb/qxcbatom.cpp
index 780816605a..a769ddadbd 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbatom.cpp
+++ b/qtbase/src/plugins/platforms/xcb/qxcbatom.cpp
@@ -90,6 +90,8 @@ static const char *xcb_atomnames = {
"_QT_CLOSE_CONNECTION\0"
+ "_QT_GET_TIMESTAMP\0"
+
"_MOTIF_WM_HINTS\0"
"DTWM_IS_RUNNING\0"
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbatom.h b/qtbase/src/plugins/platforms/xcb/qxcbatom.h
index 9cf93ec314..1ce6cca573 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbatom.h
+++ b/qtbase/src/plugins/platforms/xcb/qxcbatom.h
@@ -91,6 +91,8 @@ public:
// Qt/XCB specific
_QT_CLOSE_CONNECTION,
+ _QT_GET_TIMESTAMP,
+
_MOTIF_WM_HINTS,
DTWM_IS_RUNNING,
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp b/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp
index 0eafb9b368..152ab2c52d 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -488,12 +488,12 @@ void QXcbConnection::printXcbError(const char *message, xcb_generic_error_t *err
uint clamped_error_code = qMin(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
uint clamped_major_code = qMin(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
- qCWarning(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
- message,
- int(error->error_code), xcb_errors[clamped_error_code],
- int(error->sequence), int(error->resource_id),
- int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
- int(error->minor_code));
+ qCDebug(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
+ message,
+ int(error->error_code), xcb_errors[clamped_error_code],
+ int(error->sequence), int(error->resource_id),
+ int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
+ int(error->minor_code));
}
static Qt::MouseButtons translateMouseButtons(int s)
@@ -702,6 +702,8 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(propertyNotify->window);
if (virtualDesktop)
virtualDesktop->updateWorkArea();
+ } else if (propertyNotify->atom == atom(QXcbAtom::_NET_SUPPORTED)) {
+ m_wmSupport->updateNetWMAtoms();
} else {
HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
}
@@ -798,8 +800,8 @@ xcb_timestamp_t QXcbConnection::getTimestamp()
{
// send a dummy event to myself to get the timestamp from X server.
xcb_window_t window = rootWindow();
- xcb_atom_t dummyAtom = atom(QXcbAtom::CLIP_TEMPORARY);
- xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, window, dummyAtom,
+ xcb_atom_t dummyAtom = atom(QXcbAtom::_QT_GET_TIMESTAMP);
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window, dummyAtom,
XCB_ATOM_INTEGER, 32, 0, nullptr);
connection()->flush();
@@ -831,8 +833,6 @@ xcb_timestamp_t QXcbConnection::getTimestamp()
xcb_timestamp_t timestamp = pn->time;
free(event);
- xcb_delete_property(xcb_connection(), window, dummyAtom);
-
return timestamp;
}
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp b/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp
index 4210bf428e..0670b6ebce 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -300,7 +300,7 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c)
#endif // !QT_NO_CURSOR
QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
- : QXcbObject(conn), m_screen(screen), m_gtkCursorThemeInitialized(false)
+ : QXcbObject(conn), m_screen(screen), m_gtkCursorThemeInitialized(false), m_callbackForPropertyRegistered(false)
{
#if QT_CONFIG(cursor)
// see NUM_BITMAPS in libXcursor/src/xcursorint.h
@@ -343,7 +343,7 @@ QXcbCursor::~QXcbCursor()
{
xcb_connection_t *conn = xcb_connection();
- if (m_gtkCursorThemeInitialized) {
+ if (m_callbackForPropertyRegistered) {
m_screen->xSettings()->removeCallbackForHandle(this);
}
@@ -562,8 +562,10 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
xcb_cursor_t cursor = XCB_NONE;
#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
- if (m_screen->xSettings()->initialized())
+ if (m_screen->xSettings()->initialized()) {
m_screen->xSettings()->registerCallbackForProperty("Gtk/CursorThemeName",cursorThemePropertyChanged,this);
+ m_callbackForPropertyRegistered = true;
+ }
// Try Xcursor first
if (cshape >= 0 && cshape <= Qt::LastCursor) {
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbcursor.h b/qtbase/src/plugins/platforms/xcb/qxcbcursor.h
index 0b238823f0..82fb47e55d 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbcursor.h
+++ b/qtbase/src/plugins/platforms/xcb/qxcbcursor.h
@@ -122,6 +122,7 @@ private:
void *handle);
#endif
bool m_gtkCursorThemeInitialized;
+ bool m_callbackForPropertyRegistered;
};
QT_END_NAMESPACE
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp b/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp
index 76869ced60..02d2eebb56 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -274,8 +274,7 @@ QPlatformWindow *QXcbIntegration::createForeignWindow(QWindow *window, WId nativ
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
- QXcbScreen *screen = static_cast(context->screen()->handle());
- QXcbGlIntegration *glIntegration = screen->connection()->glIntegration();
+ QXcbGlIntegration *glIntegration = defaultConnection()->glIntegration();
if (!glIntegration) {
qWarning("QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enabled");
return nullptr;
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp b/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp
index bffad0fac5..c67ffa9dd7 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -299,11 +299,6 @@ void QXcbWindow::create()
return;
}
- QPlatformWindow::setGeometry(rect);
-
- if (platformScreen != currentScreen)
- QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
-
const QSize minimumSize = windowMinimumSize();
if (rect.width() > 0 || rect.height() > 0) {
rect.setWidth(qBound(1, rect.width(), XCOORD_MAX));
@@ -315,6 +310,11 @@ void QXcbWindow::create()
rect.setHeight(QHighDpi::toNativePixels(int(defaultWindowHeight), platformScreen->QPlatformScreen::screen()));
}
+ QPlatformWindow::setGeometry(rect);
+
+ if (platformScreen != currentScreen)
+ QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
+
xcb_window_t xcb_parent_id = platformScreen->root();
if (parent()) {
xcb_parent_id = static_cast(parent())->xcb_window();
@@ -1345,9 +1345,10 @@ void QXcbWindow::setWindowIcon(const QIcon &icon)
if (!icon_data.isEmpty()) {
// Ignore icon exceeding maximum xcb request length
- if (size_t(icon_data.size()) > xcb_get_maximum_request_length(xcb_connection())) {
- qWarning("Ignoring window icon: Size %d exceeds maximum xcb request length %u.",
- icon_data.size(), xcb_get_maximum_request_length(xcb_connection()));
+ if (quint64(icon_data.size()) > quint64(xcb_get_maximum_request_length(xcb_connection()))) {
+ qWarning() << "Ignoring window icon" << icon_data.size()
+ << "exceeds maximum xcb request length"
+ << xcb_get_maximum_request_length(xcb_connection());
return;
}
xcb_change_property(xcb_connection(),
diff --git a/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp b/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
index d264fabf0c..f464037989 100644
--- a/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
+++ b/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
@@ -85,6 +85,7 @@ QGtk3MenuItem::QGtk3MenuItem()
m_checkable(false),
m_checked(false),
m_enabled(true),
+ m_exclusive(false),
m_underline(false),
m_invalid(true),
m_menu(nullptr),
diff --git a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
index 32b2e84fa0..b2301c8c15 100644
--- a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
+++ b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
@@ -102,15 +102,12 @@ const QDBusArgument &operator >>(const QDBusArgument &arg, QXdgDesktopPortalFile
class QXdgDesktopPortalFileDialogPrivate
{
public:
- QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog)
+ QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
: nativeFileDialog(nativeFileDialog)
+ , fileChooserPortalVersion(fileChooserPortalVersion)
{ }
- WId winId = 0;
- bool directoryMode = false;
- bool modal = false;
- bool multipleFiles = false;
- bool saveFile = false;
+ QEventLoop loop;
QString acceptLabel;
QString directory;
QString title;
@@ -121,19 +118,27 @@ public:
QString selectedMimeTypeFilter;
QString selectedNameFilter;
QStringList selectedFiles;
- QPlatformFileDialogHelper *nativeFileDialog = nullptr;
+ std::unique_ptr nativeFileDialog;
+ uint fileChooserPortalVersion = 0;
+ bool failedToOpen = false;
+ bool directoryMode = false;
+ bool multipleFiles = false;
+ bool saveFile = false;
};
-QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog)
+QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
: QPlatformFileDialogHelper()
- , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog))
+ , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog, fileChooserPortalVersion))
{
Q_D(QXdgDesktopPortalFileDialog);
if (d->nativeFileDialog) {
- connect(d->nativeFileDialog, SIGNAL(accept()), this, SIGNAL(accept()));
- connect(d->nativeFileDialog, SIGNAL(reject()), this, SIGNAL(reject()));
+ connect(d->nativeFileDialog.get(), SIGNAL(accept()), this, SIGNAL(accept()));
+ connect(d->nativeFileDialog.get(), SIGNAL(reject()), this, SIGNAL(reject()));
}
+
+ d->loop.connect(this, SIGNAL(accept()), SLOT(quit()));
+ d->loop.connect(this, SIGNAL(reject()), SLOT(quit()));
}
QXdgDesktopPortalFileDialog::~QXdgDesktopPortalFileDialog()
@@ -177,7 +182,7 @@ void QXdgDesktopPortalFileDialog::initializeDialog()
setDirectory(options()->initialDirectory());
}
-void QXdgDesktopPortalFileDialog::openPortal()
+void QXdgDesktopPortalFileDialog::openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
{
Q_D(QXdgDesktopPortalFileDialog);
@@ -185,13 +190,13 @@ void QXdgDesktopPortalFileDialog::openPortal()
QLatin1String("/org/freedesktop/portal/desktop"),
QLatin1String("org.freedesktop.portal.FileChooser"),
d->saveFile ? QLatin1String("SaveFile") : QLatin1String("OpenFile"));
- QString parentWindowId = QLatin1String("x11:") + QString::number(d->winId, 16);
+ QString parentWindowId = QLatin1String("x11:") + QString::number(parent ? parent->winId() : 0, 16);
QVariantMap options;
if (!d->acceptLabel.isEmpty())
options.insert(QLatin1String("accept_label"), d->acceptLabel);
- options.insert(QLatin1String("modal"), d->modal);
+ options.insert(QLatin1String("modal"), windowModality != Qt::NonModal);
options.insert(QLatin1String("multiple"), d->multipleFiles);
options.insert(QLatin1String("directory"), d->directoryMode);
@@ -290,10 +295,18 @@ void QXdgDesktopPortalFileDialog::openPortal()
QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) {
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher *watcher) {
QDBusPendingReply reply = *watcher;
- if (reply.isError()) {
- Q_EMIT reject();
+ // Any error means the dialog is not shown and we need to fallback
+ d->failedToOpen = reply.isError();
+ if (d->failedToOpen) {
+ if (d->nativeFileDialog) {
+ d->nativeFileDialog->show(windowFlags, windowModality, parent);
+ if (d->loop.isRunning())
+ d->nativeFileDialog->exec();
+ } else {
+ Q_EMIT reject();
+ }
} else {
QDBusConnection::sessionBus().connect(nullptr,
reply.value().path(),
@@ -327,7 +340,7 @@ QUrl QXdgDesktopPortalFileDialog::directory() const
{
Q_D(const QXdgDesktopPortalFileDialog);
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ if (d->nativeFileDialog && useNativeFileDialog())
return d->nativeFileDialog->directory();
return d->directory;
@@ -349,7 +362,7 @@ QList QXdgDesktopPortalFileDialog::selectedFiles() const
{
Q_D(const QXdgDesktopPortalFileDialog);
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ if (d->nativeFileDialog && useNativeFileDialog())
return d->nativeFileDialog->selectedFiles();
QList files;
@@ -404,16 +417,13 @@ void QXdgDesktopPortalFileDialog::exec()
{
Q_D(QXdgDesktopPortalFileDialog);
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) {
+ if (d->nativeFileDialog && useNativeFileDialog()) {
d->nativeFileDialog->exec();
return;
}
// HACK we have to avoid returning until we emit that the dialog was accepted or rejected
- QEventLoop loop;
- loop.connect(this, SIGNAL(accept()), SLOT(quit()));
- loop.connect(this, SIGNAL(reject()), SLOT(quit()));
- loop.exec();
+ d->loop.exec();
}
void QXdgDesktopPortalFileDialog::hide()
@@ -430,13 +440,10 @@ bool QXdgDesktopPortalFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowMo
initializeDialog();
- d->modal = windowModality != Qt::NonModal;
- d->winId = parent ? parent->winId() : 0;
-
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ if (d->nativeFileDialog && useNativeFileDialog(OpenFallback))
return d->nativeFileDialog->show(windowFlags, windowModality, parent);
- openPortal();
+ openPortal(windowFlags, windowModality, parent);
return true;
}
@@ -466,6 +473,23 @@ void QXdgDesktopPortalFileDialog::gotResponse(uint response, const QVariantMap &
}
}
+bool QXdgDesktopPortalFileDialog::useNativeFileDialog(QXdgDesktopPortalFileDialog::FallbackType fallbackType) const
+{
+ Q_D(const QXdgDesktopPortalFileDialog);
+
+ if (d->failedToOpen && fallbackType != OpenFallback)
+ return true;
+
+ if (d->fileChooserPortalVersion < 3) {
+ if (options()->fileMode() == QFileDialogOptions::Directory)
+ return true;
+ else if (options()->fileMode() == QFileDialogOptions::DirectoryOnly)
+ return true;
+ }
+
+ return false;
+}
+
QT_END_NAMESPACE
#include "moc_qxdgdesktopportalfiledialog_p.cpp"
diff --git a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
index 4f4de96ecf..65e22a5cf2 100644
--- a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
+++ b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
@@ -51,6 +51,11 @@ class QXdgDesktopPortalFileDialog : public QPlatformFileDialogHelper
Q_OBJECT
Q_DECLARE_PRIVATE(QXdgDesktopPortalFileDialog)
public:
+ enum FallbackType {
+ GenericFallback,
+ OpenFallback
+ };
+
enum ConditionType : uint {
GlobalPattern = 0,
MimeType = 1
@@ -69,7 +74,7 @@ public:
};
typedef QVector FilterList;
- QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr);
+ QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr, uint fileChooserPortalVersion = 0);
~QXdgDesktopPortalFileDialog();
bool defaultNameFilterDisables() const override;
@@ -92,7 +97,8 @@ private Q_SLOTS:
private:
void initializeDialog();
- void openPortal();
+ void openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
+ bool useNativeFileDialog(FallbackType fallbackType = GenericFallback) const;
QScopedPointer d_ptr;
};
diff --git a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
index 2fc3167fd5..b809503122 100644
--- a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
+++ b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
@@ -153,11 +153,12 @@ QPlatformDialogHelper* QXdgDesktopPortalTheme::createPlatformDialogHelper(Dialog
{
Q_D(const QXdgDesktopPortalTheme);
- if (type == FileDialog) {
+ if (type == FileDialog && d->fileChooserPortalVersion) {
// Older versions of FileChooser portal don't support opening directories, therefore we fallback
// to native file dialog opened inside the sandbox to open a directory.
- if (d->fileChooserPortalVersion < 3 && d->baseTheme->usePlatformNativeDialog(type))
- return new QXdgDesktopPortalFileDialog(static_cast(d->baseTheme->createPlatformDialogHelper(type)));
+ if (d->baseTheme->usePlatformNativeDialog(type))
+ return new QXdgDesktopPortalFileDialog(static_cast(d->baseTheme->createPlatformDialogHelper(type)),
+ d->fileChooserPortalVersion);
return new QXdgDesktopPortalFileDialog;
}
diff --git a/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index 4427efb770..781dad8d0b 100644
--- a/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -1363,20 +1363,20 @@ bool QMYSQLDriver::open(const QString& db,
}
#if MYSQL_VERSION_ID >= 50007
- if (mysql_get_client_version() >= 50503 && mysql_get_server_version(d->mysql) >= 50503) {
- // force the communication to be utf8mb4 (only utf8mb4 supports 4-byte characters)
- mysql_set_character_set(d->mysql, "utf8mb4");
+ // force the communication to be utf8mb4 (only utf8mb4 supports 4-byte characters)
+ if (mysql_set_character_set(d->mysql, "utf8mb4")) {
+ // this failed, try forcing it to utf (BMP only)
+ if (mysql_set_character_set(d->mysql, "utf8"))
+ qWarning() << "MySQL: Unable to set the client character set to utf8.";
#if QT_CONFIG(textcodec)
- d->tc = QTextCodec::codecForName("UTF-8");
+ else
+ d->tc = codec(d->mysql);
#endif
- } else
- {
- // force the communication to be utf8
- mysql_set_character_set(d->mysql, "utf8");
+ }
#if QT_CONFIG(textcodec)
- d->tc = codec(d->mysql);
+ else
+ d->tc = QTextCodec::codecForName("UTF-8");
#endif
- }
#endif // MYSQL_VERSION_ID >= 50007
d->preparedQuerysEnabled = checkPreparedQueries(d->mysql);
diff --git a/qtbase/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/qtbase/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
index 5f51de3843..6cac60d03d 100644
--- a/qtbase/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+++ b/qtbase/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
@@ -92,23 +92,39 @@ inline static QString fromSQLTCHAR(const QVarLengthArray& input, int s
return result;
}
+template
+void toSQLTCHARImpl(QVarLengthArray &result, const QString &input); // primary template undefined
+
+template
+void do_append(QVarLengthArray &result, const Container &c)
+{
+ result.append(reinterpret_cast(c.data()), c.size());
+}
+
+template <>
+void toSQLTCHARImpl<1>(QVarLengthArray &result, const QString &input)
+{
+ const auto u8 = input.toUtf8();
+ do_append(result, u8);
+}
+
+template <>
+void toSQLTCHARImpl<2>(QVarLengthArray &result, const QString &input)
+{
+ do_append(result, input);
+}
+
+template <>
+void toSQLTCHARImpl<4>(QVarLengthArray &result, const QString &input)
+{
+ const auto u32 = input.toUcs4();
+ do_append(result, u32);
+}
+
inline static QVarLengthArray toSQLTCHAR(const QString &input)
{
QVarLengthArray result;
- result.resize(input.size());
- switch(sizeof(SQLTCHAR)) {
- case 1:
- memcpy(result.data(), input.toUtf8().data(), input.size());
- break;
- case 2:
- memcpy(result.data(), input.unicode(), input.size() * 2);
- break;
- case 4:
- memcpy(result.data(), input.toUcs4().data(), input.size() * 4);
- break;
- default:
- qCritical("sizeof(SQLTCHAR) is %d. Don't know how to handle this.", int(sizeof(SQLTCHAR)));
- }
+ toSQLTCHARImpl(result, input);
result.append(0); // make sure it's null terminated, doesn't matter if it already is, it does if it isn't.
return result;
}
@@ -763,6 +779,14 @@ QChar QODBCDriverPrivate::quoteChar()
return quote;
}
+static SQLRETURN qt_string_SQLSetConnectAttr(SQLHDBC handle, SQLINTEGER attr, const QString &val)
+{
+ auto encoded = toSQLTCHAR(val);
+ return SQLSetConnectAttr(handle, attr,
+ encoded.data(),
+ SQLINTEGER(encoded.size() * sizeof(SQLTCHAR))); // size in bytes
+}
+
bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
{
@@ -798,10 +822,7 @@ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
v = val.toUInt();
r = SQLSetConnectAttr(hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) size_t(v), 0);
} else if (opt.toUpper() == QLatin1String("SQL_ATTR_CURRENT_CATALOG")) {
- val.utf16(); // 0 terminate
- r = SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG,
- toSQLTCHAR(val).data(),
- val.length()*sizeof(SQLTCHAR));
+ r = qt_string_SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG, val);
} else if (opt.toUpper() == QLatin1String("SQL_ATTR_METADATA_ID")) {
if (val.toUpper() == QLatin1String("SQL_TRUE")) {
v = SQL_TRUE;
@@ -816,10 +837,7 @@ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
v = val.toUInt();
r = SQLSetConnectAttr(hDbc, SQL_ATTR_PACKET_SIZE, (SQLPOINTER) size_t(v), 0);
} else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACEFILE")) {
- val.utf16(); // 0 terminate
- r = SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE,
- toSQLTCHAR(val).data(),
- val.length()*sizeof(SQLTCHAR));
+ r = qt_string_SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE, val);
} else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACE")) {
if (val.toUpper() == QLatin1String("SQL_OPT_TRACE_OFF")) {
v = SQL_OPT_TRACE_OFF;
@@ -1022,9 +1040,12 @@ bool QODBCResult::reset (const QString& query)
return false;
}
- r = SQLExecDirect(d->hStmt,
- toSQLTCHAR(query).data(),
- (SQLINTEGER) query.length());
+ {
+ auto encoded = toSQLTCHAR(query);
+ r = SQLExecDirect(d->hStmt,
+ encoded.data(),
+ SQLINTEGER(encoded.size()));
+ }
if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r!= SQL_NO_DATA) {
setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
"Unable to execute statement"), QSqlError::StatementError, d));
@@ -1371,9 +1392,12 @@ bool QODBCResult::prepare(const QString& query)
return false;
}
- r = SQLPrepare(d->hStmt,
- toSQLTCHAR(query).data(),
- (SQLINTEGER) query.length());
+ {
+ auto encoded = toSQLTCHAR(query);
+ r = SQLPrepare(d->hStmt,
+ encoded.data(),
+ SQLINTEGER(encoded.size()));
+ }
if (r != SQL_SUCCESS) {
setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
@@ -1401,7 +1425,7 @@ bool QODBCResult::exec()
SQLCloseCursor(d->hStmt);
QVector& values = boundValues();
- QVector tmpStorage(values.count(), QByteArray()); // holds temporary buffers
+ QVector tmpStorage(values.count(), QByteArray()); // targets for SQLBindParameter()
QVarLengthArray indicators(values.count());
memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN));
@@ -1580,35 +1604,36 @@ bool QODBCResult::exec()
case QVariant::String:
if (d->unicode) {
QByteArray &ba = tmpStorage[i];
- QString str = val.toString();
+ {
+ const auto encoded = toSQLTCHAR(val.toString());
+ ba = QByteArray(reinterpret_cast(encoded.data()),
+ encoded.size() * sizeof(SQLTCHAR));
+ }
+
if (*ind != SQL_NULL_DATA)
- *ind = str.length() * sizeof(SQLTCHAR);
- int strSize = str.length() * sizeof(SQLTCHAR);
+ *ind = ba.size();
if (bindValueType(i) & QSql::Out) {
- const QVarLengthArray a(toSQLTCHAR(str));
- ba = QByteArray((const char *)a.constData(), a.size() * sizeof(SQLTCHAR));
r = SQLBindParameter(d->hStmt,
i + 1,
qParamType[bindValueType(i) & QSql::InOut],
SQL_C_TCHAR,
- strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
+ ba.size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
0, // god knows... don't change this!
0,
- ba.data(),
+ const_cast(ba.constData()), // don't detach
ba.size(),
ind);
break;
}
- ba = QByteArray ((const char *)toSQLTCHAR(str).constData(), str.size()*sizeof(SQLTCHAR));
r = SQLBindParameter(d->hStmt,
i + 1,
qParamType[bindValueType(i) & QSql::InOut],
SQL_C_TCHAR,
- strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
- strSize,
+ ba.size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
+ ba.size(),
0,
- const_cast(ba.constData()),
+ const_cast(ba.constData()), // don't detach
ba.size(),
ind);
break;
@@ -1716,10 +1741,11 @@ bool QODBCResult::exec()
case QVariant::String:
if (d->unicode) {
if (bindValueType(i) & QSql::Out) {
- const QByteArray &first = tmpStorage.at(i);
- QVarLengthArray array;
- array.append((const SQLTCHAR *)first.constData(), first.size());
- values[i] = fromSQLTCHAR(array, first.size()/sizeof(SQLTCHAR));
+ const QByteArray &bytes = tmpStorage.at(i);
+ const auto strSize = bytes.size() / int(sizeof(SQLTCHAR));
+ QVarLengthArray string(strSize);
+ memcpy(string.data(), bytes.data(), strSize * sizeof(SQLTCHAR));
+ values[i] = fromSQLTCHAR(string);
}
break;
}
@@ -1966,14 +1992,16 @@ bool QODBCDriver::open(const QString & db,
SQLSMALLINT cb;
QVarLengthArray connOut(1024);
memset(connOut.data(), 0, connOut.size() * sizeof(SQLTCHAR));
- r = SQLDriverConnect(d->hDbc,
- NULL,
- toSQLTCHAR(connQStr).data(),
- (SQLSMALLINT)connQStr.length(),
- connOut.data(),
- 1024,
- &cb,
- /*SQL_DRIVER_NOPROMPT*/0);
+ {
+ auto encoded = toSQLTCHAR(connQStr);
+ r = SQLDriverConnect(d->hDbc,
+ nullptr,
+ encoded.data(), SQLSMALLINT(encoded.size()),
+ connOut.data(),
+ 1024,
+ &cb,
+ /*SQL_DRIVER_NOPROMPT*/0);
+ }
if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d));
@@ -2352,17 +2380,15 @@ QStringList QODBCDriver::tables(QSql::TableType type) const
if (tableType.isEmpty())
return tl;
- QString joinedTableTypeString = tableType.join(QLatin1Char(','));
+ {
+ auto joinedTableTypeString = toSQLTCHAR(tableType.join(u','));
- r = SQLTables(hStmt,
- NULL,
- 0,
- NULL,
- 0,
- NULL,
- 0,
- toSQLTCHAR(joinedTableTypeString).data(),
- joinedTableTypeString.length() /* characters, not bytes */);
+ r = SQLTables(hStmt,
+ nullptr, 0,
+ nullptr, 0,
+ nullptr, 0,
+ joinedTableTypeString.data(), joinedTableTypeString.size());
+ }
if (r != SQL_SUCCESS)
qSqlWarning(QLatin1String("QODBCDriver::tables Unable to execute table list"), d);
@@ -2436,28 +2462,30 @@ QSqlIndex QODBCDriver::primaryIndex(const QString& tablename) const
SQL_ATTR_CURSOR_TYPE,
(SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
SQL_IS_UINTEGER);
- r = SQLPrimaryKeys(hStmt,
- catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(),
- catalog.length(),
- schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(),
- schema.length(),
- toSQLTCHAR(table).data(),
- table.length() /* in characters, not in bytes */);
+ {
+ auto c = toSQLTCHAR(catalog);
+ auto s = toSQLTCHAR(schema);
+ auto t = toSQLTCHAR(table);
+ r = SQLPrimaryKeys(hStmt,
+ catalog.isEmpty() ? nullptr : c.data(), c.size(),
+ schema.isEmpty() ? nullptr : s.data(), s.size(),
+ t.data(), t.size());
+ }
// if the SQLPrimaryKeys() call does not succeed (e.g the driver
// does not support it) - try an alternative method to get hold of
// the primary index (e.g MS Access and FoxPro)
if (r != SQL_SUCCESS) {
- r = SQLSpecialColumns(hStmt,
- SQL_BEST_ROWID,
- catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(),
- catalog.length(),
- schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(),
- schema.length(),
- toSQLTCHAR(table).data(),
- table.length(),
- SQL_SCOPE_CURROW,
- SQL_NULLABLE);
+ auto c = toSQLTCHAR(catalog);
+ auto s = toSQLTCHAR(schema);
+ auto t = toSQLTCHAR(table);
+ r = SQLSpecialColumns(hStmt,
+ SQL_BEST_ROWID,
+ catalog.isEmpty() ? nullptr : c.data(), c.size(),
+ schema.isEmpty() ? nullptr : s.data(), s.size(),
+ t.data(), t.size(),
+ SQL_SCOPE_CURROW,
+ SQL_NULLABLE);
if (r != SQL_SUCCESS) {
qSqlWarning(QLatin1String("QODBCDriver::primaryIndex: Unable to execute primary key list"), d);
@@ -2538,15 +2566,17 @@ QSqlRecord QODBCDriver::record(const QString& tablename) const
SQL_ATTR_CURSOR_TYPE,
(SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
SQL_IS_UINTEGER);
- r = SQLColumns(hStmt,
- catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(),
- catalog.length(),
- schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(),
- schema.length(),
- toSQLTCHAR(table).data(),
- table.length(),
- NULL,
- 0);
+ {
+ auto c = toSQLTCHAR(catalog);
+ auto s = toSQLTCHAR(schema);
+ auto t = toSQLTCHAR(table);
+ r = SQLColumns(hStmt,
+ catalog.isEmpty() ? nullptr : c.data(), c.size(),
+ schema.isEmpty() ? nullptr : s.data(), s.size(),
+ t.data(), t.size(),
+ nullptr,
+ 0);
+ }
if (r != SQL_SUCCESS)
qSqlWarning(QLatin1String("QODBCDriver::record: Unable to execute column list"), d);
diff --git a/qtbase/src/printsupport/dialogs/images/print-24.png b/qtbase/src/printsupport/dialogs/images/printer-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/print-24.png
rename to src/printsupport/dialogs/images/printer-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/print-32.png b/qtbase/src/printsupport/dialogs/images/printer-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/print-32.png
rename to src/printsupport/dialogs/images/printer-32.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-sided-24.png b/qtbase/src/printsupport/dialogs/images/view-pages-facing-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-sided-24.png
rename to src/printsupport/dialogs/images/view-pages-facing-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-sided-32.png b/qtbase/src/printsupport/dialogs/images/view-pages-facing-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-sided-32.png
rename to src/printsupport/dialogs/images/view-pages-facing-32.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-multi-24.png b/qtbase/src/printsupport/dialogs/images/view-pages-overview-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-multi-24.png
rename to src/printsupport/dialogs/images/view-pages-overview-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-multi-32.png b/qtbase/src/printsupport/dialogs/images/view-pages-overview-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-multi-32.png
rename to src/printsupport/dialogs/images/view-pages-overview-32.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-one-24.png b/qtbase/src/printsupport/dialogs/images/view-pages-single-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-one-24.png
rename to src/printsupport/dialogs/images/view-pages-single-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-one-32.png b/qtbase/src/printsupport/dialogs/images/view-pages-single-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-one-32.png
rename to src/printsupport/dialogs/images/view-pages-single-32.png
diff --git a/qtbase/src/printsupport/dialogs/images/fit-page-24.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-page-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/fit-page-24.png
rename to src/printsupport/dialogs/images/zoom-fit-page-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/fit-page-32.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-page-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/fit-page-32.png
rename to src/printsupport/dialogs/images/zoom-fit-page-32.png
diff --git a/qtbase/src/printsupport/dialogs/images/fit-width-24.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-width-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/fit-width-24.png
rename to src/printsupport/dialogs/images/zoom-fit-width-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/fit-width-32.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-width-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/fit-width-32.png
rename to src/printsupport/dialogs/images/zoom-fit-width-32.png
diff --git a/qtbase/src/printsupport/dialogs/qprintdialog.qrc b/qtbase/src/printsupport/dialogs/qprintdialog.qrc
index 5a579baa55..10b8e1d341 100644
--- a/qtbase/src/printsupport/dialogs/qprintdialog.qrc
+++ b/qtbase/src/printsupport/dialogs/qprintdialog.qrc
@@ -1,9 +1,9 @@
-images/fit-page-24.png
-images/fit-page-32.png
-images/fit-width-24.png
-images/fit-width-32.png
+images/zoom-fit-page-24.png
+images/zoom-fit-page-32.png
+images/zoom-fit-width-24.png
+images/zoom-fit-width-32.pngimages/go-first-24.pngimages/go-first-32.pngimages/go-last-24.png
@@ -18,14 +18,14 @@
images/layout-portrait-32.pngimages/page-setup-24.pngimages/page-setup-32.png
-images/print-24.png
-images/print-32.png
-images/view-page-multi-24.png
-images/view-page-multi-32.png
-images/view-page-one-24.png
-images/view-page-one-32.png
-images/view-page-sided-24.png
-images/view-page-sided-32.png
+images/printer-24.png
+images/printer-32.png
+images/view-pages-overview-24.png
+images/view-pages-overview-32.png
+images/view-pages-single-24.png
+images/view-pages-single-32.png
+images/view-pages-facing-24.png
+images/view-pages-facing-32.pngimages/zoom-in-24.pngimages/zoom-in-32.pngimages/zoom-out-24.png
diff --git a/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp b/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp
index 39575d5f57..23b7e89538 100644
--- a/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp
+++ b/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp
@@ -352,7 +352,7 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
static inline void qt_setupActionIcon(QAction *action, QLatin1String name)
{
QLatin1String imagePrefix(":/qt-project.org/dialogs/qprintpreviewdialog/images/");
- QIcon icon;
+ QIcon icon = QIcon::fromTheme(name);
icon.addFile(imagePrefix + name + QLatin1String("-24.png"), QSize(24, 24));
icon.addFile(imagePrefix + name + QLatin1String("-32.png"), QSize(32, 32));
action->setIcon(icon);
@@ -383,8 +383,8 @@ void QPrintPreviewDialogPrivate::setupActions()
fitPageAction->setObjectName(QLatin1String("fitPageAction"));
fitWidthAction->setCheckable(true);
fitPageAction->setCheckable(true);
- qt_setupActionIcon(fitWidthAction, QLatin1String("fit-width"));
- qt_setupActionIcon(fitPageAction, QLatin1String("fit-page"));
+ qt_setupActionIcon(fitWidthAction, QLatin1String("zoom-fit-width"));
+ qt_setupActionIcon(fitPageAction, QLatin1String("zoom-fit-page"));
QObject::connect(fitGroup, SIGNAL(triggered(QAction*)), q, SLOT(_q_fit(QAction*)));
// Zoom
@@ -410,9 +410,9 @@ void QPrintPreviewDialogPrivate::setupActions()
singleModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show single page"));
facingModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show facing pages"));
overviewModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show overview of all pages"));
- qt_setupActionIcon(singleModeAction, QLatin1String("view-page-one"));
- qt_setupActionIcon(facingModeAction, QLatin1String("view-page-sided"));
- qt_setupActionIcon(overviewModeAction, QLatin1String("view-page-multi"));
+ qt_setupActionIcon(singleModeAction, QLatin1String("view-pages-single"));
+ qt_setupActionIcon(facingModeAction, QLatin1String("view-pages-facing"));
+ qt_setupActionIcon(overviewModeAction, QLatin1String("view-pages-overview"));
singleModeAction->setObjectName(QLatin1String("singleModeAction"));
facingModeAction->setObjectName(QLatin1String("facingModeAction"));
overviewModeAction->setObjectName(QLatin1String("overviewModeAction"));
@@ -426,7 +426,7 @@ void QPrintPreviewDialogPrivate::setupActions()
printerGroup = new QActionGroup(q);
printAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Print"));
pageSetupAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Page setup"));
- qt_setupActionIcon(printAction, QLatin1String("print"));
+ qt_setupActionIcon(printAction, QLatin1String("printer"));
qt_setupActionIcon(pageSetupAction, QLatin1String("page-setup"));
QObject::connect(printAction, SIGNAL(triggered(bool)), q, SLOT(_q_print()));
QObject::connect(pageSetupAction, SIGNAL(triggered(bool)), q, SLOT(_q_pageSetup()));
diff --git a/qtbase/src/testlib/qabstractitemmodeltester.cpp b/qtbase/src/testlib/qabstractitemmodeltester.cpp
index 1cd18b98bb..41219a7e23 100644
--- a/qtbase/src/testlib/qabstractitemmodeltester.cpp
+++ b/qtbase/src/testlib/qabstractitemmodeltester.cpp
@@ -454,7 +454,7 @@ void QAbstractItemModelTesterPrivate::parent()
// Common error test #2, make sure that a second level index has a parent
// that is the first level index.
- if (model->rowCount(topIndex) > 0) {
+ if (model->rowCount(topIndex) > 0 && model->columnCount(topIndex) > 0) {
QModelIndex childIndex = model->index(0, 0, topIndex);
MODELTESTER_VERIFY(childIndex.isValid());
MODELTESTER_COMPARE(model->parent(childIndex), topIndex);
diff --git a/qtbase/src/testlib/qasciikey.cpp b/qtbase/src/testlib/qasciikey.cpp
index 9a308da2bc..93498b256f 100644
--- a/qtbase/src/testlib/qasciikey.cpp
+++ b/qtbase/src/testlib/qasciikey.cpp
@@ -498,6 +498,11 @@ char QTest::keyToAscii(Qt::Key key)
case Qt::Key_LaunchE : return 0; // = 0x10b0,
case Qt::Key_LaunchF : return 0; // = 0x10b1,
+ // Keypad navigation keys
+ case Qt::Key_Select : return 0; // = 0x01010000
+ case Qt::Key_Yes : return 0; // = 0x01010001
+ case Qt::Key_No : return 0; // = 0x01010002
+
default: QTEST_ASSERT(false); return 0;
}
}
diff --git a/qtbase/src/testlib/qtestresult.cpp b/qtbase/src/testlib/qtestresult.cpp
index 88028aac6e..2e89930776 100644
--- a/qtbase/src/testlib/qtestresult.cpp
+++ b/qtbase/src/testlib/qtestresult.cpp
@@ -251,7 +251,8 @@ bool QTestResult::verify(bool statement, const char *statementStr,
{
QTEST_ASSERT(statementStr);
- char msg[1024] = {'\0'};
+ char msg[1024];
+ msg[0] = '\0';
if (QTestLog::verboseLevel() >= 2) {
qsnprintf(msg, 1024, "QVERIFY(%s)", statementStr);
@@ -309,7 +310,8 @@ static bool compareHelper(bool success, const char *failureMsg,
bool hasValues = true)
{
const size_t maxMsgLen = 1024;
- char msg[maxMsgLen] = {'\0'};
+ char msg[maxMsgLen];
+ msg[0] = '\0';
QTEST_ASSERT(expected);
QTEST_ASSERT(actual);
diff --git a/qtbase/src/widgets/dialogs/qcolordialog.cpp b/qtbase/src/widgets/dialogs/qcolordialog.cpp
index 4247731275..cb325be85c 100644
--- a/qtbase/src/widgets/dialogs/qcolordialog.cpp
+++ b/qtbase/src/widgets/dialogs/qcolordialog.cpp
@@ -78,7 +78,10 @@
#include "qwindow.h"
#include "private/qdialog_p.h"
+#include "private/qguiapplication_p.h"
+#include
+#include
#include
QT_BEGIN_NAMESPACE
@@ -1611,6 +1614,20 @@ void QColorDialogPrivate::_q_newStandard(int r, int c)
void QColorDialogPrivate::_q_pickScreenColor()
{
Q_Q(QColorDialog);
+
+ auto *platformServices = QGuiApplicationPrivate::platformIntegration()->services();
+ if (platformServices->hasCapability(QPlatformServices::Capability::ColorPicking)) {
+ if (auto *colorPicker = platformServices->colorPicker(q->windowHandle())) {
+ q->connect(colorPicker, &QPlatformServiceColorPicker::colorPicked, q,
+ [q, colorPicker](const QColor &color) {
+ colorPicker->deleteLater();
+ q->setCurrentColor(color);
+ });
+ colorPicker->pickColor();
+ return;
+ }
+ }
+
if (!colorPickingEventFilter)
colorPickingEventFilter = new QColorPickingEventFilter(this, q);
q->installEventFilter(colorPickingEventFilter);
diff --git a/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp b/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp
index e120817edc..8ea36b5427 100644
--- a/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp
+++ b/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp
@@ -400,12 +400,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event,
const QString tooltip = index.isValid() ?
d->textForRole(Qt::ToolTipRole, index.data(Qt::ToolTipRole), option.locale, precision) :
QString();
- QRect rect;
- if (index.isValid()) {
- const QRect r = view->visualRect(index);
- rect = QRect(view->mapToGlobal(r.topLeft()), r.size());
- }
- QToolTip::showText(he->globalPos(), tooltip, view, rect);
+ QToolTip::showText(he->globalPos(), tooltip, view->viewport(), option.rect);
event->setAccepted(!tooltip.isEmpty());
break;
}
diff --git a/qtbase/src/widgets/itemviews/qabstractitemview.cpp b/qtbase/src/widgets/itemviews/qabstractitemview.cpp
index deb49ca23d..93dc5ee80c 100644
--- a/qtbase/src/widgets/itemviews/qabstractitemview.cpp
+++ b/qtbase/src/widgets/itemviews/qabstractitemview.cpp
@@ -2347,11 +2347,12 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
#if !defined(QT_NO_CLIPBOARD) && !defined(QT_NO_SHORTCUT)
if (event == QKeySequence::Copy) {
- QVariant variant;
- if (d->model)
- variant = d->model->data(currentIndex(), Qt::DisplayRole);
- if (variant.canConvert())
- QGuiApplication::clipboard()->setText(variant.toString());
+ const QModelIndex index = currentIndex();
+ if (index.isValid() && d->model) {
+ const QVariant variant = d->model->data(index, Qt::DisplayRole);
+ if (variant.canConvert())
+ QGuiApplication::clipboard()->setText(variant.toString());
+ }
event->accept();
}
#endif
diff --git a/qtbase/src/widgets/itemviews/qlistview.cpp b/qtbase/src/widgets/itemviews/qlistview.cpp
index 5a88f1b1ef..63f760269c 100644
--- a/qtbase/src/widgets/itemviews/qlistview.cpp
+++ b/qtbase/src/widgets/itemviews/qlistview.cpp
@@ -3388,6 +3388,7 @@ void QIconModeViewBase::updateContentsSize()
*/
void QListView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
+ QAbstractItemView::currentChanged(current, previous);
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
if (current.isValid()) {
@@ -3398,7 +3399,6 @@ void QListView::currentChanged(const QModelIndex ¤t, const QModelIndex &pr
}
}
#endif
- QAbstractItemView::currentChanged(current, previous);
}
/*!
diff --git a/qtbase/src/widgets/itemviews/qtableview.cpp b/qtbase/src/widgets/itemviews/qtableview.cpp
index d120c41dc9..09d34005a7 100644
--- a/qtbase/src/widgets/itemviews/qtableview.cpp
+++ b/qtbase/src/widgets/itemviews/qtableview.cpp
@@ -1013,6 +1013,7 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItem &
int QTableViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option) const
{
Q_Q(const QTableView);
+ const int oldHint = hint;
QWidget *editor = editorForIndex(index).widget.data();
if (editor && persistent.contains(editor)) {
hint = qMax(hint, editor->sizeHint().width());
@@ -1021,6 +1022,17 @@ int QTableViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, con
hint = qBound(min, hint, max);
}
hint = qMax(hint, q->itemDelegate(index)->sizeHint(option, index).width());
+
+ if (hasSpans()) {
+ auto span = spans.spanAt(index.column(), index.row());
+ if (span && span->m_left == index.column() && span->m_top == index.row()) {
+ // spans are screwed up when sections are moved
+ const auto left = logicalColumn(span->m_left);
+ for (int i = 1; i <= span->width(); ++i)
+ hint -= q->columnWidth(visualColumn(left + i));
+ }
+ hint = std::max(hint, oldHint);
+ }
return hint;
}
@@ -1053,6 +1065,11 @@ int QTableViewPrivate::heightHintForIndex(const QModelIndex &index, int hint, QS
option.rect.setHeight(height);
option.rect.setX(q->columnViewportPosition(index.column()));
option.rect.setWidth(q->columnWidth(index.column()));
+ if (hasSpans()) {
+ auto span = spans.spanAt(index.column(), index.row());
+ if (span && span->m_left == index.column() && span->m_top == index.row())
+ option.rect.setWidth(std::max(option.rect.width(), visualSpanRect(*span).width()));
+ }
// 1px less space when grid is shown (see drawCell)
if (showGrid)
option.rect.setWidth(option.rect.width() - 1);
diff --git a/qtbase/src/widgets/kernel/qaction.h b/qtbase/src/widgets/kernel/qaction.h
index 258a1ea0a0..737c1e8285 100644
--- a/qtbase/src/widgets/kernel/qaction.h
+++ b/qtbase/src/widgets/kernel/qaction.h
@@ -81,7 +81,7 @@ class Q_WIDGETS_EXPORT QAction : public QObject
Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed)
Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed)
Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu WRITE setShortcutVisibleInContextMenu NOTIFY changed)
- Q_PROPERTY(Priority priority READ priority WRITE setPriority)
+ Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY changed)
public:
// note this is copied into qplatformmenu.h, which must stay in sync
diff --git a/qtbase/src/widgets/styles/qcommonstyle.cpp b/qtbase/src/widgets/styles/qcommonstyle.cpp
index 502a527901..a79c33005c 100644
--- a/qtbase/src/widgets/styles/qcommonstyle.cpp
+++ b/qtbase/src/widgets/styles/qcommonstyle.cpp
@@ -1708,8 +1708,9 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
alignment |= Qt::TextHideMnemonic;
rect.translate(shiftX, shiftY);
p->setFont(toolbutton->font);
+ const QString text = d->toolButtonElideText(toolbutton, rect, alignment);
proxy()->drawItemText(p, rect, alignment, toolbutton->palette,
- opt->state & State_Enabled, toolbutton->text,
+ opt->state & State_Enabled, text,
QPalette::ButtonText);
} else {
QPixmap pm;
diff --git a/qtbase/src/widgets/styles/qfusionstyle.cpp b/qtbase/src/widgets/styles/qfusionstyle.cpp
index a225d4b563..35e2769ac4 100644
--- a/qtbase/src/widgets/styles/qfusionstyle.cpp
+++ b/qtbase/src/widgets/styles/qfusionstyle.cpp
@@ -1772,14 +1772,6 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget);
}
break;
- case CE_PushButtonLabel:
- if (const QStyleOptionButton *button = qstyleoption_cast(option)) {
- QStyleOptionButton b(*button);
- // no PM_ButtonShiftHorizontal and PM_ButtonShiftVertical for fusion style
- b.state &= ~(State_On | State_Sunken);
- QCommonStyle::drawControl(element, &b, painter, widget);
- }
- break;
case CE_MenuBarEmptyArea:
painter->save();
{
diff --git a/qtbase/src/widgets/styles/qstylesheetstyle.cpp b/qtbase/src/widgets/styles/qstylesheetstyle.cpp
index 55d95c7fb2..8e9d2abbaa 100644
--- a/qtbase/src/widgets/styles/qstylesheetstyle.cpp
+++ b/qtbase/src/widgets/styles/qstylesheetstyle.cpp
@@ -4453,12 +4453,15 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
case PE_PanelLineEdit:
if (const QStyleOptionFrame *frm = qstyleoption_cast(opt)) {
- QWidget *container = containerWidget(w);
- if (container != w) {
- QRenderRule containerRule = renderRule(container, opt);
- if (!containerRule.hasNativeBorder() || !containerRule.baseStyleCanDraw())
- return;
- rule = containerRule;
+ // Fall back to container widget's render rule
+ if (w) {
+ QWidget *container = containerWidget(w);
+ if (container != w) {
+ QRenderRule containerRule = renderRule(container, opt);
+ if (!containerRule.hasNativeBorder() || !containerRule.baseStyleCanDraw())
+ return;
+ rule = containerRule;
+ }
}
if (rule.hasNativeBorder()) {
diff --git a/qtbase/src/widgets/widgets/qabstractbutton.cpp b/qtbase/src/widgets/widgets/qabstractbutton.cpp
index a128b23950..dc40bf62fb 100644
--- a/qtbase/src/widgets/widgets/qabstractbutton.cpp
+++ b/qtbase/src/widgets/widgets/qabstractbutton.cpp
@@ -56,6 +56,7 @@
#ifndef QT_NO_ACCESSIBILITY
#include "qaccessible.h"
#endif
+#include
#include
@@ -1076,19 +1077,19 @@ void QAbstractButton::keyPressEvent(QKeyEvent *e)
{
Q_D(QAbstractButton);
bool next = true;
- switch (e->key()) {
- case Qt::Key_Enter:
- case Qt::Key_Return:
- e->ignore();
- break;
- case Qt::Key_Select:
- case Qt::Key_Space:
- if (!e->isAutoRepeat()) {
- setDown(true);
- repaint();
- d->emitPressed();
- }
- break;
+
+ const auto key = static_cast(e->key());
+ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+ ->themeHint(QPlatformTheme::ButtonPressKeys)
+ .value>();
+ if (buttonPressKeys.contains(key) && !e->isAutoRepeat()) {
+ setDown(true);
+ repaint();
+ d->emitPressed();
+ return;
+ }
+
+ switch (key) {
case Qt::Key_Up:
next = false;
Q_FALLTHROUGH();
@@ -1153,15 +1154,15 @@ void QAbstractButton::keyReleaseEvent(QKeyEvent *e)
if (!e->isAutoRepeat())
d->repeatTimer.stop();
- switch (e->key()) {
- case Qt::Key_Select:
- case Qt::Key_Space:
- if (!e->isAutoRepeat() && d->down)
- d->click();
- break;
- default:
- e->ignore();
+ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+ ->themeHint(QPlatformTheme::ButtonPressKeys)
+ .value>();
+ if (buttonPressKeys.contains(static_cast(e->key())) && !e->isAutoRepeat() && d->down) {
+ d->click();
+ return;
}
+
+ e->ignore();
}
/*!\reimp
diff --git a/qtbase/src/widgets/widgets/qcombobox.cpp b/qtbase/src/widgets/widgets/qcombobox.cpp
index 7a496c27e0..0a3d96647b 100644
--- a/qtbase/src/widgets/widgets/qcombobox.cpp
+++ b/qtbase/src/widgets/widgets/qcombobox.cpp
@@ -3352,7 +3352,23 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
Move move = NoMove;
int newIndex = currentIndex();
- switch (e->key()) {
+
+ bool pressLikeButton = !d->lineEdit;
+#ifdef QT_KEYPAD_NAVIGATION
+ pressLikeButton |= QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus();
+#endif
+ auto key = static_cast(e->key());
+ if (pressLikeButton) {
+ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+ ->themeHint(QPlatformTheme::ButtonPressKeys)
+ .value>();
+ if (buttonPressKeys.contains(key)) {
+ showPopup();
+ return;
+ }
+ }
+
+ switch (key) {
case Qt::Key_Up:
if (e->modifiers() & Qt::ControlModifier)
break; // pass to line edit for auto completion
@@ -3394,26 +3410,11 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
return;
}
break;
- case Qt::Key_Space:
- if (!d->lineEdit) {
- showPopup();
- return;
- }
- break;
- case Qt::Key_Enter:
- case Qt::Key_Return:
case Qt::Key_Escape:
if (!d->lineEdit)
e->ignore();
break;
#ifdef QT_KEYPAD_NAVIGATION
- case Qt::Key_Select:
- if (QApplicationPrivate::keypadNavigationEnabled()
- && (!hasEditFocus() || !d->lineEdit)) {
- showPopup();
- return;
- }
- break;
case Qt::Key_Left:
case Qt::Key_Right:
if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus())
diff --git a/qtbase/src/widgets/widgets/qdatetimeedit_p.h b/qtbase/src/widgets/widgets/qdatetimeedit_p.h
index d36b6f8f9a..e0df5b5158 100644
--- a/qtbase/src/widgets/widgets/qdatetimeedit_p.h
+++ b/qtbase/src/widgets/widgets/qdatetimeedit_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
diff --git a/qtbase/src/widgets/widgets/qgroupbox.cpp b/qtbase/src/widgets/widgets/qgroupbox.cpp
index 02a0bed325..3f3eccc370 100644
--- a/qtbase/src/widgets/widgets/qgroupbox.cpp
+++ b/qtbase/src/widgets/widgets/qgroupbox.cpp
@@ -54,6 +54,8 @@
#include "qaccessible.h"
#endif
#include
+#include
+#include
#include "qdebug.h"
@@ -360,7 +362,10 @@ bool QGroupBox::event(QEvent *e)
return true;
case QEvent::KeyPress: {
QKeyEvent *k = static_cast(e);
- if (!k->isAutoRepeat() && (k->key() == Qt::Key_Select || k->key() == Qt::Key_Space)) {
+ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+ ->themeHint(QPlatformTheme::ButtonPressKeys)
+ .value>();
+ if (!k->isAutoRepeat() && buttonPressKeys.contains(static_cast(k->key()))) {
d->pressedControl = QStyle::SC_GroupBoxCheckBox;
update(style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxCheckBox, this));
return true;
@@ -369,7 +374,10 @@ bool QGroupBox::event(QEvent *e)
}
case QEvent::KeyRelease: {
QKeyEvent *k = static_cast(e);
- if (!k->isAutoRepeat() && (k->key() == Qt::Key_Select || k->key() == Qt::Key_Space)) {
+ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+ ->themeHint(QPlatformTheme::ButtonPressKeys)
+ .value>();
+ if (!k->isAutoRepeat() && buttonPressKeys.contains(static_cast(k->key()))) {
bool toggle = (d->pressedControl == QStyle::SC_GroupBoxLabel
|| d->pressedControl == QStyle::SC_GroupBoxCheckBox);
d->pressedControl = QStyle::SC_None;
diff --git a/qtbase/src/widgets/widgets/qtoolbararealayout.cpp b/qtbase/src/widgets/widgets/qtoolbararealayout.cpp
index 493c094cc1..d5f4b59017 100644
--- a/qtbase/src/widgets/widgets/qtoolbararealayout.cpp
+++ b/qtbase/src/widgets/widgets/qtoolbararealayout.cpp
@@ -1367,7 +1367,7 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QListsetOrientation(floating ? ((shown & 2) ? Qt::Vertical : Qt::Horizontal) : dock.o);
toolBar->setVisible(shown & 1);
- toolBar->d_func()->setWindowState(floating, true, rect);
+ toolBar->d_func()->setWindowState(floating, false, rect);
item.preferredSize = item.size;
line.toolBarItems.append(item);
diff --git a/qtbase/src/widgets/widgets/qtoolbutton.cpp b/qtbase/src/widgets/widgets/qtoolbutton.cpp
index e380cb647b..9953db73af 100644
--- a/qtbase/src/widgets/widgets/qtoolbutton.cpp
+++ b/qtbase/src/widgets/widgets/qtoolbutton.cpp
@@ -982,7 +982,15 @@ QAction *QToolButton::defaultAction() const
return d->defaultAction;
}
-
+/*!
+ \reimp
+ */
+void QToolButton::checkStateSet()
+{
+ Q_D(QToolButton);
+ if (d->defaultAction && d->defaultAction->isCheckable())
+ d->defaultAction->setChecked(isChecked());
+}
/*!
\reimp
diff --git a/qtbase/src/widgets/widgets/qtoolbutton.h b/qtbase/src/widgets/widgets/qtoolbutton.h
index 52bd2d5f7a..82b5d7924f 100644
--- a/qtbase/src/widgets/widgets/qtoolbutton.h
+++ b/qtbase/src/widgets/widgets/qtoolbutton.h
@@ -118,6 +118,7 @@ protected:
void changeEvent(QEvent *) override;
bool hitButton(const QPoint &pos) const override;
+ void checkStateSet() override;
void nextCheckState() override;
void initStyleOption(QStyleOptionToolButton *option) const;
diff --git a/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
index 212c0a2e13..3c77b1ba0b 100644
--- a/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
+++ b/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
@@ -126,8 +126,7 @@ public:
void tst_QtConcurrentIterateKernel::instantiate()
{
- auto future = startThreadEngine(new PrintFor(0, 40)).startAsynchronously();
- future.waitForFinished();
+ startThreadEngine(new PrintFor(0, 40)).startBlocking();
QCOMPARE(iterations.loadRelaxed(), 40);
}
@@ -166,10 +165,8 @@ void tst_QtConcurrentIterateKernel::stresstest()
const int times = 50;
for (int i = 0; i < times; ++i) {
counter.storeRelaxed(0);
- // ThreadEngine will delete f when it finishes
- auto f = new CountFor(0, iterations);
- auto future = f->startAsynchronously();
- future.waitForFinished();
+ CountFor f(0, iterations);
+ f.startBlocking();
QCOMPARE(counter.loadRelaxed(), iterations);
}
}
@@ -177,11 +174,8 @@ void tst_QtConcurrentIterateKernel::stresstest()
void tst_QtConcurrentIterateKernel::noIterations()
{
const int times = 20000;
- for (int i = 0; i < times; ++i) {
- auto future = startThreadEngine(new IterateKernel(0, 0))
- .startAsynchronously();
- future.waitForFinished();
- }
+ for (int i = 0; i < times; ++i)
+ startThreadEngine(new IterateKernel(0, 0)).startBlocking();
}
QMutex threadsMutex;
@@ -236,10 +230,8 @@ void tst_QtConcurrentIterateKernel::throttling()
threads.clear();
- // ThreadEngine will delete f when it finishes
- auto f = new ThrottleFor(0, totalIterations);
- auto future = f->startAsynchronously();
- future.waitForFinished();
+ ThrottleFor f(0, totalIterations);
+ f.startBlocking();
QCOMPARE(iterations.loadRelaxed(), totalIterations);
diff --git a/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp b/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
index ac7be7acdd..81bc64c8d9 100644
--- a/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
+++ b/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
@@ -65,9 +65,16 @@ public:
void tst_QtConcurrentThreadEngine::runDirectly()
{
- PrintUser *engine = new PrintUser();
- QFuture f = engine->startAsynchronously();
- f.waitForFinished();
+ {
+ PrintUser engine;
+ engine.startSingleThreaded();
+ engine.startBlocking();
+ }
+ {
+ PrintUser *engine = new PrintUser();
+ QFuture f = engine->startAsynchronously();
+ f.waitForFinished();
+ }
}
class StringResultUser : public ThreadEngine
@@ -99,10 +106,8 @@ public:
void tst_QtConcurrentThreadEngine::result()
{
- // ThreadEngine will delete 'engine' when it finishes
- auto engine = new StringResultUser();
- auto future = engine->startAsynchronously();
- QCOMPARE(future.result(), QString("Foo"));
+ StringResultUser engine;
+ QCOMPARE(*engine.startBlocking(), QString("Foo"));
}
class VoidResultUser : public ThreadEngine
@@ -128,9 +133,17 @@ public:
void tst_QtConcurrentThreadEngine::runThroughStarter()
{
- ThreadEngineStarter starter = startThreadEngine(new StringResultUser());
- QFuture f = starter.startAsynchronously();
- QCOMPARE(f.result(), QString("Foo"));
+ {
+ ThreadEngineStarter starter = startThreadEngine(new StringResultUser());
+ QFuture f = starter.startAsynchronously();
+ QCOMPARE(f.result(), QString("Foo"));
+ }
+
+ {
+ ThreadEngineStarter starter = startThreadEngine(new StringResultUser());
+ QString str = starter.startBlocking();
+ QCOMPARE(str, QString("Foo"));
+ }
}
class CancelUser : public ThreadEngine
@@ -213,6 +226,12 @@ void tst_QtConcurrentThreadEngine::throttle()
f.waitForFinished();
QCOMPARE(count.loadRelaxed(), 0);
}
+
+ for (int i = 0; i < repeats; ++i) {
+ ThrottleAlwaysUser t;
+ t.startBlocking();
+ QCOMPARE(count.loadRelaxed(), 0);
+ }
}
QSet threads;
@@ -249,17 +268,35 @@ void tst_QtConcurrentThreadEngine::threadCount()
{
const int repeats = 10;
for (int i = 0; i < repeats; ++i) {
+ ThreadCountUser t;
+ t.startBlocking();
+ int count = threads.count();
+ int count_expected = QThreadPool::globalInstance()->maxThreadCount() + 1; // +1 for the main thread.
+ if (count != count_expected)
+ QEXPECT_FAIL("", "QTBUG-23333", Abort);
+ QCOMPARE(count, count_expected);
+
(new ThreadCountUser())->startAsynchronously().waitForFinished();
- const auto count = threads.count();
- const auto maxThreadCount = QThreadPool::globalInstance()->maxThreadCount();
- QVERIFY(count <= maxThreadCount);
- QVERIFY(!threads.contains(QThread::currentThread()));
+ count = threads.count();
+ count_expected = QThreadPool::globalInstance()->maxThreadCount();
+ if (count != count_expected)
+ QEXPECT_FAIL("", "QTBUG-23333", Abort);
+ QCOMPARE(count, count_expected);
}
// Set the finish flag immediately, this should give us one thread only.
for (int i = 0; i < repeats; ++i) {
+ ThreadCountUser t(true /*finishImmediately*/);
+ t.startBlocking();
+ int count = threads.count();
+ if (count != 1)
+ QEXPECT_FAIL("", "QTBUG-23333", Abort);
+ QCOMPARE(count, 1);
+
(new ThreadCountUser(true /*finishImmediately*/))->startAsynchronously().waitForFinished();
- const auto count = threads.count();
+ count = threads.count();
+ if (count != 1)
+ QEXPECT_FAIL("", "QTBUG-23333", Abort);
QCOMPARE(count, 1);
QVERIFY(!threads.contains(QThread::currentThread()));
}
@@ -400,6 +437,7 @@ public:
void tst_QtConcurrentThreadEngine::exceptions()
{
+ // Asynchronous mode:
{
bool caught = false;
try {
@@ -412,6 +450,32 @@ void tst_QtConcurrentThreadEngine::exceptions()
QVERIFY2(caught, "did not get exception");
}
+ // Blocking mode:
+ // test throwing the exception from a worker thread.
+ {
+ bool caught = false;
+ try {
+ QtConcurrentExceptionThrower e(QThread::currentThread());
+ e.startBlocking();
+ } catch (const QException &) {
+ caught = true;
+ }
+ QVERIFY2(caught, "did not get exception");
+ }
+
+ // test throwing the exception from the main thread (different code path)
+ {
+ bool caught = false;
+ try {
+ QtConcurrentExceptionThrower e(0);
+ e.startBlocking();
+ } catch (const QException &) {
+ caught = true;
+ }
+ QVERIFY2(caught, "did not get exception");
+ }
+
+ // Asynchronous mode:
{
bool caught = false;
try {
@@ -423,6 +487,31 @@ void tst_QtConcurrentThreadEngine::exceptions()
}
QVERIFY2(caught, "did not get exception");
}
+
+ // Blocking mode:
+ // test throwing the exception from a worker thread.
+ {
+ bool caught = false;
+ try {
+ UnrelatedExceptionThrower e(QThread::currentThread());
+ e.startBlocking();
+ } catch (const QUnhandledException &) {
+ caught = true;
+ }
+ QVERIFY2(caught, "did not get exception");
+ }
+
+ // test throwing the exception from the main thread (different code path)
+ {
+ bool caught = false;
+ try {
+ UnrelatedExceptionThrower e(0);
+ e.startBlocking();
+ } catch (const QUnhandledException &) {
+ caught = true;
+ }
+ QVERIFY2(caught, "did not get exception");
+ }
}
#endif
diff --git a/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp b/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
index e1ea7a4552..90972caa57 100644
--- a/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
+++ b/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
@@ -117,6 +117,7 @@ private Q_SLOTS:
void shouldPropagateDropAfterLastRow_data();
void shouldPropagateDropAfterLastRow();
void qtbug91788();
+ void qtbug91878();
private:
QStandardItemModel mod;
@@ -843,6 +844,22 @@ void tst_QConcatenateTablesProxyModel::qtbug91788()
QCOMPARE(proxyConcat.columnCount(), 0);
}
+void tst_QConcatenateTablesProxyModel::qtbug91878()
+{
+ QStandardItemModel m;
+ m.setRowCount(4);
+ m.setColumnCount(4);
+
+ QConcatenateTablesProxyModel pm;
+ QSortFilterProxyModel proxyFilter;
+ proxyFilter.setSourceModel(&pm);
+ proxyFilter.setFilterFixedString("something");
+ pm.addSourceModel(&m); // This should not assert
+
+ QCOMPARE(pm.columnCount(), 4);
+ QCOMPARE(pm.rowCount(), 4);
+}
+
QTEST_GUILESS_MAIN(tst_QConcatenateTablesProxyModel)
#include "tst_qconcatenatetablesproxymodel.moc"
diff --git a/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index 25da013292..5ca7d3e3bb 100644
--- a/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -158,6 +158,7 @@ private slots:
void nullReceiver();
void functorReferencesConnection();
void disconnectDisconnects();
+ void declarativeData();
};
struct QObjectCreatedOnShutdown
@@ -7689,5 +7690,81 @@ void tst_QObject::disconnectDisconnects()
Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro::Value);
Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro::Value);
+#ifdef QT_BUILD_INTERNAL
+/*
+ Since QObjectPrivate stores the declarativeData pointer in a union with the pointer
+ to the currently destroyed child, calls to the QtDeclarative handlers need to be
+ correctly guarded. QTBUG-105286
+*/
+namespace QtDeclarative {
+static QAbstractDeclarativeData *theData;
+
+static void destroyed(QAbstractDeclarativeData *data, QObject *)
+{
+ QCOMPARE(data, theData);
+}
+static void signalEmitted(QAbstractDeclarativeData *data, QObject *, int, void **)
+{
+ QCOMPARE(data, theData);
+}
+// we can't use QCOMPARE in the next two functions, as they don't return void
+static int receivers(QAbstractDeclarativeData *data, const QObject *, int)
+{
+ QTest::qCompare(data, theData, "data", "theData", __FILE__, __LINE__);
+ return 0;
+}
+static bool isSignalConnected(QAbstractDeclarativeData *data, const QObject *, int)
+{
+ QTest::qCompare(data, theData, "data", "theData", __FILE__, __LINE__);
+ return true;
+}
+
+class Object : public QObject
+{
+ Q_OBJECT
+public:
+ using QObject::QObject;
+ ~Object()
+ {
+ if (Object *p = static_cast