summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/widgets/gallery/widgetgallery.cpp3
-rw-r--r--src/corelib/global/qalloc.h1
-rw-r--r--src/corelib/global/qassert.h19
-rw-r--r--src/corelib/global/qcompilerdetection.h4
-rw-r--r--src/corelib/io/qlockfile_win.cpp28
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_p_p.h2
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_threadpool.cpp4
-rw-r--r--src/corelib/text/qbytearray.h4
-rw-r--r--src/corelib/text/qchar.h62
-rw-r--r--src/corelib/text/qstring.h4
-rw-r--r--src/corelib/thread/qsemaphore.cpp20
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h2
-rw-r--r--src/corelib/tools/qlist.h4
-rw-r--r--src/corelib/tools/qshareddata.h323
-rw-r--r--src/gui/image/qplatformpixmap.cpp1
-rw-r--r--src/gui/image/qplatformpixmap.h5
-rw-r--r--src/gui/painting/qdrawhelper_avx2.cpp2
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp13
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.cpp53
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.h2
-rw-r--r--src/testlib/qtest.h26
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp27
-rw-r--r--src/widgets/itemviews/qabstractitemview.h5
-rw-r--r--src/widgets/itemviews/qabstractitemview_p.h1
-rw-r--r--src/widgets/itemviews/qtreeview.cpp3
-rw-r--r--tests/auto/corelib/global/qglobal/tst_qglobal.cpp13
-rw-r--r--tests/auto/corelib/io/qsettings/tst_qsettings.cpp178
-rw-r--r--tests/auto/testlib/initmain/tst_initmain.cpp3
-rw-r--r--tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp14
29 files changed, 538 insertions, 288 deletions
diff --git a/examples/widgets/gallery/widgetgallery.cpp b/examples/widgets/gallery/widgetgallery.cpp
index 64a83676c02..e2ffec50e81 100644
--- a/examples/widgets/gallery/widgetgallery.cpp
+++ b/examples/widgets/gallery/widgetgallery.cpp
@@ -419,7 +419,8 @@ void WidgetGallery::updateSystemInfo()
QString systemInfo;
QTextStream str(&systemInfo);
str << "<html><head/><body><h3>Build</h3><p>" << QLibraryInfo::build() << "</p>"
- << "<h3>Operating System</h3><p>" << QSysInfo::prettyProductName() << "</p>"
+ << "<h3>Operating System</h3><p>\"" << QSysInfo::prettyProductName() << "\" / "
+ << QGuiApplication::platformName() << "</p>"
<< "<h3>Screens</h3><p>High DPI scale factor rounding policy: "
<< highDpiScaleFactorRoundingPolicy() << "</p><ol>";
const auto screens = QGuiApplication::screens();
diff --git a/src/corelib/global/qalloc.h b/src/corelib/global/qalloc.h
index 9d40f4261d3..a05c09ac63c 100644
--- a/src/corelib/global/qalloc.h
+++ b/src/corelib/global/qalloc.h
@@ -21,6 +21,7 @@
#include <QtCore/qtypeinfo.h>
#include <cstddef>
+#include <cstdlib>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/global/qassert.h b/src/corelib/global/qassert.h
index d1d306fd3ed..05210acb2d4 100644
--- a/src/corelib/global/qassert.h
+++ b/src/corelib/global/qassert.h
@@ -100,6 +100,25 @@ inline bool qt_assume_is_deprecated(bool cond) noexcept { return cond; }
Q_ASSUME_IMPL(valueOfExpression);\
}(qt_assume_is_deprecated(Expr))
+
+#if __has_builtin(__builtin_assume)
+// Clang has this intrinsic and won't warn about its use in C++20 mode
+# define Q_PRESUME_IMPL(assumption) __builtin_assume(assumption)
+#elif __has_cpp_attribute(assume)
+// GCC has implemented this attribute and allows its use in C++20 mode
+# define Q_PRESUME_IMPL(assumption) [[assume(assumption)]]
+#elif defined(Q_CC_MSVC)
+# define Q_PRESUME_IMPL(assumption) __assume(assumption)
+#else
+# define Q_PRESUME_IMPL(assumption) (void)0
+#endif
+
+#define Q_PRESUME(assumption) \
+ [&] { \
+ Q_ASSERT(assumption); \
+ Q_PRESUME_IMPL(assumption); \
+ }()
+
// Don't use these in C++ mode, use static_assert directly.
// These are here only to keep old code compiling.
# define Q_STATIC_ASSERT(Condition) static_assert(bool(Condition), #Condition)
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 700c59ab3c7..df55baf3120 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -1443,6 +1443,10 @@ QT_WARNING_DISABLE_MSVC(4706) /* assignment within conditional expression */
QT_WARNING_DISABLE_MSVC(4355) /* 'this' : used in base member initializer list */
QT_WARNING_DISABLE_MSVC(4710) /* function not inlined */
QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc */
+# elif defined(Q_CC_CLANG_ONLY)
+# if Q_CC_CLANG >= 2100
+ QT_WARNING_DISABLE_CLANG("-Wcharacter-conversion") /* until https://github.com/llvm/llvm-project/issues/163719 is fixed */
+# endif
# elif defined(Q_CC_BOR)
# pragma option -w-inl
# pragma option -w-aus
diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp
index 611f90679d5..ef5d49fb20e 100644
--- a/src/corelib/io/qlockfile_win.cpp
+++ b/src/corelib/io/qlockfile_win.cpp
@@ -55,9 +55,10 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
const QFileSystemEntry fileEntry(fileName);
// When writing, allow others to read.
// When reading, QFile will allow others to read and write, all good.
- // Adding FILE_SHARE_DELETE would allow forceful deletion of stale files,
- // but Windows doesn't allow recreating it while this handle is open anyway,
- // so this would only create confusion (can't lock, but no lock file to read from).
+ // ### Open the file with DELETE permission and use
+ // SetFileInformationByHandle to delete the file without needing to close
+ // the handle first, to avoid someone opening the handle again without the
+ // FILE_SHARE_DELETE flag in-between closure and deletion.
const DWORD dwShareMode = FILE_SHARE_READ;
SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
HANDLE fh = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(),
@@ -146,7 +147,26 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
int QLockFilePrivate::openNewFileDescriptor(const QString &fileName)
{
- return _open(fileName.toLocal8Bit().constData(), _O_RDONLY);
+ // We currently open with FILE_SHARE_DELETE, which would allow deletion to
+ // be requested even while other processes have the file open. We mostly
+ // want to do this so we can later open the file with the DELETE permission
+ // to delete the file using SetFileInformationByHandle, avoiding the need
+ // to close the handle first, where e.g. search indexer or antivirus may
+ // see their chance to open the file before we can delete it.
+ // We can't make this change immediately because currently-deployed
+ // applications will not be using FILE_SHARE_DELETE, so they would suddenly
+ // be unable to read the lockfile information.
+ HANDLE handle = CreateFile(reinterpret_cast<const wchar_t *>(fileName.utf16()), GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (handle == INVALID_HANDLE_VALUE)
+ return -1;
+ int fd = _open_osfhandle(intptr_t(handle), _O_RDONLY);
+ if (fd == -1) {
+ CloseHandle(handle);
+ return -1;
+ }
+ return fd;
}
void QLockFile::unlock()
diff --git a/src/corelib/io/qrandomaccessasyncfile_p_p.h b/src/corelib/io/qrandomaccessasyncfile_p_p.h
index 7b10edc6728..ef996c37f07 100644
--- a/src/corelib/io/qrandomaccessasyncfile_p_p.h
+++ b/src/corelib/io/qrandomaccessasyncfile_p_p.h
@@ -39,7 +39,7 @@ class QRandomAccessAsyncFilePrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QRandomAccessAsyncFile)
Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFilePrivate)
public:
- QRandomAccessAsyncFilePrivate(decltype(QObjectPrivateVersion) version = QObjectPrivateVersion);
+ QRandomAccessAsyncFilePrivate();
~QRandomAccessAsyncFilePrivate() override;
static QRandomAccessAsyncFilePrivate *get(QRandomAccessAsyncFile *file)
diff --git a/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp b/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
index 42d38cc3adb..4ebcf554655 100644
--- a/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
+++ b/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
@@ -64,8 +64,8 @@ static SharedThreadPool asyncFileThreadPool;
} // anonymous namespace
-QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate(decltype(QObjectPrivateVersion) version) :
- QObjectPrivate(version)
+QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate() :
+ QObjectPrivate()
{
asyncFileThreadPool.ref();
}
diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h
index ef30d5e0da1..9fb832545f8 100644
--- a/src/corelib/text/qbytearray.h
+++ b/src/corelib/text/qbytearray.h
@@ -512,10 +512,8 @@ public:
}
constexpr qsizetype size() const noexcept
{
-#if __has_cpp_attribute(assume)
constexpr size_t MaxSize = maxSize();
- [[assume(size_t(d.size) <= MaxSize)]];
-#endif
+ Q_PRESUME(size_t(d.size) <= MaxSize);
return d.size;
}
#if QT_DEPRECATED_SINCE(6, 4)
diff --git a/src/corelib/text/qchar.h b/src/corelib/text/qchar.h
index 008282232fb..4a3aad0ca0c 100644
--- a/src/corelib/text/qchar.h
+++ b/src/corelib/text/qchar.h
@@ -499,26 +499,26 @@ public:
Unicode_16_0,
};
- inline Category category() const noexcept { return QChar::category(ucs); }
- inline Direction direction() const noexcept { return QChar::direction(ucs); }
- inline JoiningType joiningType() const noexcept { return QChar::joiningType(ucs); }
- inline unsigned char combiningClass() const noexcept { return QChar::combiningClass(ucs); }
+ Category category() const noexcept { return QChar::category(char32_t(ucs)); }
+ Direction direction() const noexcept { return QChar::direction(char32_t(ucs)); }
+ JoiningType joiningType() const noexcept { return QChar::joiningType(char32_t(ucs)); }
+ unsigned char combiningClass() const noexcept { return QChar::combiningClass(char32_t(ucs)); }
- inline QChar mirroredChar() const noexcept { return QChar(QChar::mirroredChar(ucs)); }
- inline bool hasMirrored() const noexcept { return QChar::hasMirrored(ucs); }
+ QChar mirroredChar() const noexcept { return QChar(QChar::mirroredChar(char32_t(ucs))); }
+ bool hasMirrored() const noexcept { return QChar::hasMirrored(char32_t(ucs)); }
QString decomposition() const;
- inline Decomposition decompositionTag() const noexcept { return QChar::decompositionTag(ucs); }
+ Decomposition decompositionTag() const noexcept { return QChar::decompositionTag(char32_t(ucs)); }
- inline int digitValue() const noexcept { return QChar::digitValue(ucs); }
- inline QChar toLower() const noexcept { return QChar(QChar::toLower(ucs)); }
- inline QChar toUpper() const noexcept { return QChar(QChar::toUpper(ucs)); }
- inline QChar toTitleCase() const noexcept { return QChar(QChar::toTitleCase(ucs)); }
- inline QChar toCaseFolded() const noexcept { return QChar(QChar::toCaseFolded(ucs)); }
+ int digitValue() const noexcept { return QChar::digitValue(char32_t(ucs)); }
+ QChar toLower() const noexcept { return QChar(QChar::toLower(char32_t(ucs))); }
+ QChar toUpper() const noexcept { return QChar(QChar::toUpper(char32_t(ucs))); }
+ QChar toTitleCase() const noexcept { return QChar(QChar::toTitleCase(char32_t(ucs))); }
+ QChar toCaseFolded() const noexcept { return QChar(QChar::toCaseFolded(char32_t(ucs))); }
- inline Script script() const noexcept { return QChar::script(ucs); }
+ Script script() const noexcept { return QChar::script(char32_t(ucs)); }
- inline UnicodeVersion unicodeVersion() const noexcept { return QChar::unicodeVersion(ucs); }
+ UnicodeVersion unicodeVersion() const noexcept { return QChar::unicodeVersion(char32_t(ucs)); }
constexpr inline char toLatin1() const noexcept { return ucs > 0xff ? '\0' : char(ucs); }
constexpr inline char16_t unicode() const noexcept { return ucs; }
@@ -528,23 +528,23 @@ public:
constexpr inline bool isNull() const noexcept { return ucs == 0; }
- inline bool isPrint() const noexcept { return QChar::isPrint(ucs); }
- constexpr inline bool isSpace() const noexcept { return QChar::isSpace(ucs); }
- inline bool isMark() const noexcept { return QChar::isMark(ucs); }
- inline bool isPunct() const noexcept { return QChar::isPunct(ucs); }
- inline bool isSymbol() const noexcept { return QChar::isSymbol(ucs); }
- constexpr inline bool isLetter() const noexcept { return QChar::isLetter(ucs); }
- constexpr inline bool isNumber() const noexcept { return QChar::isNumber(ucs); }
- constexpr inline bool isLetterOrNumber() const noexcept { return QChar::isLetterOrNumber(ucs); }
- constexpr inline bool isDigit() const noexcept { return QChar::isDigit(ucs); }
- constexpr inline bool isLower() const noexcept { return QChar::isLower(ucs); }
- constexpr inline bool isUpper() const noexcept { return QChar::isUpper(ucs); }
- constexpr inline bool isTitleCase() const noexcept { return QChar::isTitleCase(ucs); }
-
- constexpr inline bool isNonCharacter() const noexcept { return QChar::isNonCharacter(ucs); }
- constexpr inline bool isHighSurrogate() const noexcept { return QChar::isHighSurrogate(ucs); }
- constexpr inline bool isLowSurrogate() const noexcept { return QChar::isLowSurrogate(ucs); }
- constexpr inline bool isSurrogate() const noexcept { return QChar::isSurrogate(ucs); }
+ bool isPrint() const noexcept { return QChar::isPrint(char32_t(ucs)); }
+ constexpr bool isSpace() const noexcept { return QChar::isSpace(char32_t(ucs)); }
+ bool isMark() const noexcept { return QChar::isMark(char32_t(ucs)); }
+ bool isPunct() const noexcept { return QChar::isPunct(char32_t(ucs)); }
+ bool isSymbol() const noexcept { return QChar::isSymbol(char32_t(ucs)); }
+ constexpr bool isLetter() const noexcept { return QChar::isLetter(char32_t(ucs)); }
+ constexpr bool isNumber() const noexcept { return QChar::isNumber(char32_t(ucs)); }
+ constexpr bool isLetterOrNumber() const noexcept { return QChar::isLetterOrNumber(char32_t(ucs)); }
+ constexpr bool isDigit() const noexcept { return QChar::isDigit(char32_t(ucs)); }
+ constexpr bool isLower() const noexcept { return QChar::isLower(char32_t(ucs)); }
+ constexpr bool isUpper() const noexcept { return QChar::isUpper(char32_t(ucs)); }
+ constexpr bool isTitleCase() const noexcept { return QChar::isTitleCase(char32_t(ucs)); }
+
+ constexpr bool isNonCharacter() const noexcept { return QChar::isNonCharacter(char32_t(ucs)); }
+ constexpr bool isHighSurrogate() const noexcept { return QChar::isHighSurrogate(char32_t(ucs)); }
+ constexpr bool isLowSurrogate() const noexcept { return QChar::isLowSurrogate(char32_t(ucs)); }
+ constexpr bool isSurrogate() const noexcept { return QChar::isSurrogate(char32_t(ucs)); }
constexpr inline uchar cell() const noexcept { return uchar(ucs & 0xff); }
constexpr inline uchar row() const noexcept { return uchar((ucs>>8)&0xff); }
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index b8acf7c923d..506d669d356 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -273,10 +273,8 @@ public:
}
constexpr qsizetype size() const noexcept
{
-#if __has_cpp_attribute(assume)
constexpr size_t MaxSize = maxSize();
- [[assume(size_t(d.size) <= MaxSize)]];
-#endif
+ Q_PRESUME(size_t(d.size) <= MaxSize);
return d.size;
}
#if QT_DEPRECATED_SINCE(6, 4)
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
index 0de30d3b9f9..a308c4419e2 100644
--- a/src/corelib/thread/qsemaphore.cpp
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -12,6 +12,9 @@
#include "qwaitcondition_p.h"
#include <chrono>
+#if !QT_CONFIG(thread)
+#include <limits>
+#endif
QT_BEGIN_NAMESPACE
@@ -684,7 +687,7 @@ bool QSemaphore::tryAcquire(int n, QDeadlineTimer timer)
// the calling thread (which is the only thread in the no-thread
// configuraton)
-QSemaphore::QSemaphore(int n)
+QSemaphore::QSemaphore(int)
{
}
@@ -704,6 +707,21 @@ void QSemaphore::release(int)
}
+int QSemaphore::available() const
+{
+ return std::numeric_limits<int>::max();
+}
+
+bool QSemaphore::tryAcquire(int)
+{
+ return true;
+}
+
+bool QSemaphore::tryAcquire(int, QDeadlineTimer)
+{
+ return true;
+}
+
#endif
QT_END_NAMESPACE
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index 611c8e4b5e7..2714c67b093 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -162,7 +162,7 @@ public:
QByteArray ianaId;
qsizetype nameLength = 0;
QTimeZone::TimeType timeType = QTimeZone::GenericTime;
- operator bool() { return nameLength > 0; }
+ operator bool() const { return nameLength > 0; }
};
static NamePrefixMatch findLongNamePrefix(QStringView text, const QLocale &locale,
std::optional<qint64> atEpochMillis = std::nullopt);
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 79b367b199c..93f7ddb9465 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -446,10 +446,8 @@ public:
static constexpr qsizetype maxSize() { return Data::maxSize(); }
constexpr qsizetype size() const noexcept
{
-#if __has_cpp_attribute(assume)
constexpr size_t MaxSize = maxSize();
- [[assume(size_t(d.size) <= MaxSize)]];
-#endif
+ Q_PRESUME(size_t(d.size) <= MaxSize);
return d.size;
}
constexpr qsizetype count() const noexcept { return size(); }
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index 7d0cec8c899..595efd7e3bf 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -4,16 +4,35 @@
#ifndef QSHAREDDATA_H
#define QSHAREDDATA_H
-#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
#include <QtCore/qcompare.h>
#include <QtCore/qhashfunctions.h>
-
QT_BEGIN_NAMESPACE
-
template <class T> class QSharedDataPointer;
+template <class T> class QExplicitlySharedDataPointer;
+
+namespace QtPrivate {
+template <template <typename> class P, typename T> struct QSharedDataPointerTraits;
+template <typename T> struct QSharedDataPointerTraits<QSharedDataPointer, T>
+{
+ static constexpr bool ImplicitlyDetaches = true;
+ using Type = T;
+ using pointer = T *;
+ // for const-qualified functions:
+ using constT = const T;
+};
+
+template <typename T> struct QSharedDataPointerTraits<QExplicitlySharedDataPointer, T>
+{
+ static constexpr bool ImplicitlyDetaches = false;
+ using Type = T;
+ using pointer = T *;
+ // for const-qualified functions:
+ using constT = T;
+};
+}
class QSharedData
{
@@ -30,41 +49,38 @@ public:
struct QAdoptSharedDataTag { explicit constexpr QAdoptSharedDataTag() = default; };
-template <typename T>
-class QSharedDataPointer
+// CRTP common base class for both QSharedDataPointer and QExplicitlySharedDataPointer
+template <template <typename> class P, typename T> class QSharedDataPointerBase
{
+#ifndef Q_QDOC
+ using Self = P<T>;
+ using Traits = QtPrivate::QSharedDataPointerTraits<P, T>;
+ using constT = typename Traits::constT;
+
+protected:
+ constexpr QSharedDataPointerBase(T *ptr = nullptr) noexcept : d(ptr) {}
+
public:
- typedef T Type;
- typedef T *pointer;
+ // When adding anything public to this class, make sure to add the doc version to
+ // both QSharedDataPointer and QExplicitlySharedDataPointer.
+
+ using Type = T;
+ using pointer = T *;
void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
- T &operator*() { detach(); return *(d.get()); }
- const T &operator*() const { return *(d.get()); }
- T *operator->() { detach(); return d.get(); }
- const T *operator->() const noexcept { return d.get(); }
- operator T *() { detach(); return d.get(); }
+ T &operator*() { implicitlyDetach(); return *(d.get()); }
+ constT &operator*() const { return *(d.get()); }
+ T *operator->() { implicitlyDetach(); return d.get(); }
+ constT *operator->() const noexcept { return d.get(); }
+ operator T *() { implicitlyDetach(); return d.get(); }
operator const T *() const noexcept { return d.get(); }
- T *data() { detach(); return d.get(); }
- T *get() { detach(); return d.get(); }
+ T *data() { implicitlyDetach(); return d.get(); }
+ T *get() { implicitlyDetach(); return d.get(); }
const T *data() const noexcept { return d.get(); }
const T *get() const noexcept { return d.get(); }
const T *constData() const noexcept { return d.get(); }
T *take() noexcept { return std::exchange(d, nullptr).get(); }
- Q_NODISCARD_CTOR
- QSharedDataPointer() noexcept : d(nullptr) { }
- ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d.get(); }
-
- Q_NODISCARD_CTOR
- explicit QSharedDataPointer(T *data) noexcept : d(data)
- { if (d) d->ref.ref(); }
- Q_NODISCARD_CTOR
- QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
- {}
- Q_NODISCARD_CTOR
- QSharedDataPointer(const QSharedDataPointer &o) noexcept : d(o.d)
- { if (d) d->ref.ref(); }
-
void reset(T *ptr = nullptr) noexcept
{
if (ptr != d.get()) {
@@ -72,10 +88,97 @@ public:
ptr->ref.ref();
T *old = std::exchange(d, Qt::totally_ordered_wrapper(ptr)).get();
if (old && !old->ref.deref())
- delete old;
+ destroy(old);
}
}
+ operator bool () const noexcept { return d != nullptr; }
+ bool operator!() const noexcept { return d == nullptr; }
+
+ void swap(Self &other) noexcept
+ { qt_ptr_swap(d, other.d); }
+
+private:
+ // The concrete class MUST override these, otherwise we will be calling
+ // ourselves.
+ T *clone() { return static_cast<Self *>(this)->clone(); }
+ template <typename... Args> static T *create(Args &&... args)
+ { return Self::create(std::forward(args)...); }
+ static void destroy(T *ptr) { Self::destroy(ptr); }
+
+ void implicitlyDetach()
+ {
+ if constexpr (Traits::ImplicitlyDetaches)
+ static_cast<Self *>(this)->detach();
+ }
+
+ friend bool comparesEqual(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
+ { return lhs.d == rhs.d; }
+ friend Qt::strong_ordering
+ compareThreeWay(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
+ { return Qt::compareThreeWay(lhs.d, rhs.d); }
+
+ friend bool comparesEqual(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
+ { return lhs.d == rhs; }
+ friend Qt::strong_ordering
+ compareThreeWay(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
+ { return Qt::compareThreeWay(lhs.d, rhs); }
+
+ friend bool comparesEqual(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
+ { return lhs.d == nullptr; }
+ friend Qt::strong_ordering
+ compareThreeWay(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
+ { return Qt::compareThreeWay(lhs.d, nullptr); }
+
+ friend size_t qHash(const QSharedDataPointerBase &ptr, size_t seed = 0) noexcept
+ { return qHash(ptr.data(), seed); }
+
+protected:
+ void detach_helper();
+
+ Qt::totally_ordered_wrapper<T *> d;
+#endif // !Q_QDOC
+};
+
+template <typename T>
+class QSharedDataPointer : public QSharedDataPointerBase<QSharedDataPointer, T>
+{
+ using Base = QSharedDataPointerBase<QSharedDataPointer, T>;
+ friend Base;
+public:
+ typedef T Type;
+ typedef T *pointer;
+
+ void detach() { Base::detach(); }
+#ifdef Q_QDOC
+ T &operator*();
+ const T &operator*() const;
+ T *operator->();
+ const T *operator->() const noexcept;
+ operator T *();
+ operator const T *() const noexcept;
+ T *data();
+ T *get();
+ const T *data() const noexcept;
+ const T *get() const noexcept;
+ const T *constData() const noexcept;
+ T *take() noexcept;
+#endif
+
+ Q_NODISCARD_CTOR
+ QSharedDataPointer() noexcept : Base(nullptr) { }
+ ~QSharedDataPointer() { if (d && !d->ref.deref()) destroy(d.get()); }
+
+ Q_NODISCARD_CTOR
+ explicit QSharedDataPointer(T *data) noexcept : Base(data)
+ { if (d) d->ref.ref(); }
+ Q_NODISCARD_CTOR
+ QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : Base(data)
+ {}
+ Q_NODISCARD_CTOR
+ QSharedDataPointer(const QSharedDataPointer &o) noexcept : Base(o.d.get())
+ { if (d) d->ref.ref(); }
+
QSharedDataPointer &operator=(const QSharedDataPointer &o) noexcept
{
reset(o.d.get());
@@ -87,76 +190,80 @@ public:
return *this;
}
Q_NODISCARD_CTOR
- QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(std::exchange(o.d, nullptr)) {}
+ QSharedDataPointer(QSharedDataPointer &&o) noexcept
+ : Base(std::exchange(o.d, nullptr).get())
+ {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedDataPointer)
- operator bool () const noexcept { return d != nullptr; }
- bool operator!() const noexcept { return d == nullptr; }
+#ifdef Q_QDOC
+ void reset(T *ptr = nullptr) noexcept;
- void swap(QSharedDataPointer &other) noexcept
- { qt_ptr_swap(d, other.d); }
+ operator bool () const noexcept;
+ bool operator!() const noexcept;
+
+ void swap(QSharedDataPointer &other) noexcept;
+#else
+ using Base::reset;
+ using Base::swap;
+#endif
protected:
T *clone();
+ template <typename... Args> static T *create(Args &&... args)
+ { return new T(std::forward(args)...); }
+ static void destroy(T *ptr) { delete ptr; }
private:
- friend bool comparesEqual(const QSharedDataPointer &lhs, const QSharedDataPointer &rhs) noexcept
- { return lhs.d == rhs.d; }
- friend Qt::strong_ordering
- compareThreeWay(const QSharedDataPointer &lhs, const QSharedDataPointer &rhs) noexcept
- { return Qt::compareThreeWay(lhs.d, rhs.d); }
Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer)
-
- friend bool comparesEqual(const QSharedDataPointer &lhs, const T *rhs) noexcept
- { return lhs.d == rhs; }
- friend Qt::strong_ordering
- compareThreeWay(const QSharedDataPointer &lhs, const T *rhs) noexcept
- { return Qt::compareThreeWay(lhs.d, rhs); }
Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, T*)
-
- friend bool comparesEqual(const QSharedDataPointer &lhs, std::nullptr_t) noexcept
- { return lhs.d == nullptr; }
- friend Qt::strong_ordering
- compareThreeWay(const QSharedDataPointer &lhs, std::nullptr_t) noexcept
- { return Qt::compareThreeWay(lhs.d, nullptr); }
Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, std::nullptr_t)
- void detach_helper();
-
- Qt::totally_ordered_wrapper<T *> d;
+ using Base::d;
};
template <typename T>
-class QExplicitlySharedDataPointer
+class QExplicitlySharedDataPointer : public QSharedDataPointerBase<QExplicitlySharedDataPointer, T>
{
+ using Base = QSharedDataPointerBase<QExplicitlySharedDataPointer, T>;
+ friend Base;
public:
typedef T Type;
typedef T *pointer;
- T &operator*() const { return *(d.get()); }
- T *operator->() noexcept { return d.get(); }
- T *operator->() const noexcept { return d.get(); }
+ // override to make explicit. Can use explicit(!ImplicitlyShared) once we
+ // can depend on C++20.
explicit operator T *() { return d.get(); }
explicit operator const T *() const noexcept { return d.get(); }
+
+ // override to make const. There is no const(cond), but we could use
+ // requires(!ImplicitlyShared)
T *data() const noexcept { return d.get(); }
T *get() const noexcept { return d.get(); }
- const T *constData() const noexcept { return d.get(); }
- T *take() noexcept { return std::exchange(d, nullptr).get(); }
- void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
+#ifdef Q_QDOC
+ T &operator*() const;
+ T *operator->() noexcept;
+ T *operator->() const noexcept;
+ T *data() const noexcept;
+ T *get() const noexcept;
+ const T *constData() const noexcept;
+ T *take() noexcept;
+#endif
+
+ void detach() { Base::detach(); }
Q_NODISCARD_CTOR
- QExplicitlySharedDataPointer() noexcept : d(nullptr) { }
+ QExplicitlySharedDataPointer() noexcept : Base(nullptr) { }
~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d.get(); }
Q_NODISCARD_CTOR
- explicit QExplicitlySharedDataPointer(T *data) noexcept : d(data)
+ explicit QExplicitlySharedDataPointer(T *data) noexcept : Base(data)
{ if (d) d->ref.ref(); }
Q_NODISCARD_CTOR
- QExplicitlySharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
+ QExplicitlySharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : Base(data)
{}
Q_NODISCARD_CTOR
- QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer &o) noexcept : d(o.d)
+ QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer &o) noexcept : Base(o.d.get())
{ if (d) d->ref.ref(); }
template<typename X>
@@ -165,20 +272,9 @@ public:
#ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
#error This macro has been removed in Qt 6.9.
#endif
- : d(o.data())
+ : Base(o.data())
{ if (d) d->ref.ref(); }
- void reset(T *ptr = nullptr) noexcept
- {
- if (ptr != d) {
- if (ptr)
- ptr->ref.ref();
- T *old = std::exchange(d, Qt::totally_ordered_wrapper(ptr)).get();
- if (old && !old->ref.deref())
- delete old;
- }
- }
-
QExplicitlySharedDataPointer &operator=(const QExplicitlySharedDataPointer &o) noexcept
{
reset(o.d.get());
@@ -190,72 +286,52 @@ public:
return *this;
}
Q_NODISCARD_CTOR
- QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(std::exchange(o.d, nullptr)) {}
+ QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept
+ : Base(std::exchange(o.d, nullptr).get())
+ {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QExplicitlySharedDataPointer)
- operator bool () const noexcept { return d != nullptr; }
- bool operator!() const noexcept { return d == nullptr; }
+#ifdef Q_QDOC
+ void reset(T *ptr = nullptr) noexcept;
- void swap(QExplicitlySharedDataPointer &other) noexcept
- { qt_ptr_swap(d, other.d); }
+ operator bool () const noexcept;
+ bool operator!() const noexcept;
+
+ void swap(QExplicitlySharedDataPointer &other) noexcept;
+#else
+ using Base::swap;
+ using Base::reset;
+#endif
protected:
T *clone();
+ template <typename... Args> static T *create(Args &&... args)
+ { return new T(std::forward(args)...); }
+ static void destroy(T *ptr) { delete ptr; }
private:
- friend bool comparesEqual(const QExplicitlySharedDataPointer &lhs,
- const QExplicitlySharedDataPointer &rhs) noexcept
- { return lhs.d == rhs.d; }
- friend Qt::strong_ordering
- compareThreeWay(const QExplicitlySharedDataPointer &lhs,
- const QExplicitlySharedDataPointer &rhs) noexcept
- { return Qt::compareThreeWay(lhs.d, rhs.d); }
Q_DECLARE_STRONGLY_ORDERED(QExplicitlySharedDataPointer)
-
- friend bool comparesEqual(const QExplicitlySharedDataPointer &lhs, const T *rhs) noexcept
- { return lhs.d == rhs; }
- friend Qt::strong_ordering
- compareThreeWay(const QExplicitlySharedDataPointer &lhs, const T *rhs) noexcept
- { return Qt::compareThreeWay(lhs.d, rhs); }
Q_DECLARE_STRONGLY_ORDERED(QExplicitlySharedDataPointer, const T*)
-
- friend bool comparesEqual(const QExplicitlySharedDataPointer &lhs, std::nullptr_t) noexcept
- { return lhs.d == nullptr; }
- friend Qt::strong_ordering
- compareThreeWay(const QExplicitlySharedDataPointer &lhs, std::nullptr_t) noexcept
- { return Qt::compareThreeWay(lhs.d, nullptr); }
Q_DECLARE_STRONGLY_ORDERED(QExplicitlySharedDataPointer, std::nullptr_t)
- void detach_helper();
-
- Qt::totally_ordered_wrapper<T *> d;
+ using Base::d;
};
// Declared here and as Q_OUTOFLINE_TEMPLATE to work-around MSVC bug causing missing symbols at link time.
template <typename T>
Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
{
- return new T(*d);
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
-{
- T *x = clone();
- x->ref.ref();
- if (!d.get()->ref.deref())
- delete d.get();
- d.reset(x);
+ return new T(*this->d);
}
template <typename T>
Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
{
- return new T(*d.get());
+ return new T(*this->d.get());
}
-template <typename T>
-Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
+template <template <typename> class P, typename T> Q_OUTOFLINE_TEMPLATE void
+QSharedDataPointerBase<P, T>::detach_helper()
{
T *x = clone();
x->ref.ref();
@@ -272,17 +348,6 @@ template <typename T>
void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) noexcept
{ p1.swap(p2); }
-template <typename T>
-size_t qHash(const QSharedDataPointer<T> &ptr, size_t seed = 0) noexcept
-{
- return qHash(ptr.data(), seed);
-}
-template <typename T>
-size_t qHash(const QExplicitlySharedDataPointer<T> &ptr, size_t seed = 0) noexcept
-{
- return qHash(ptr.data(), seed);
-}
-
template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_RELOCATABLE_TYPE);
template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_RELOCATABLE_TYPE);
diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp
index a2977360951..d1eab7f6ed3 100644
--- a/src/gui/image/qplatformpixmap.cpp
+++ b/src/gui/image/qplatformpixmap.cpp
@@ -36,7 +36,6 @@ QPlatformPixmap::QPlatformPixmap(PixelType pixelType, int objectId)
h(0),
d(0),
is_null(true),
- ref(0),
detach_no(0),
type(pixelType),
id(objectId),
diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h
index be86bf8850f..5621afa4da5 100644
--- a/src/gui/image/qplatformpixmap.h
+++ b/src/gui/image/qplatformpixmap.h
@@ -22,7 +22,7 @@ QT_BEGIN_NAMESPACE
class QImageReader;
-class Q_GUI_EXPORT QPlatformPixmap
+class Q_GUI_EXPORT QPlatformPixmap : public QSharedData
{
public:
enum PixelType {
@@ -113,10 +113,7 @@ private:
friend class QPixmap;
friend class QX11PlatformPixmap;
friend class QImagePixmapCleanupHooks; // Needs to set is_cached
- friend class QOpenGLTextureCache; //Needs to check the reference count
- friend class QExplicitlySharedDataPointer<QPlatformPixmap>;
- QAtomicInt ref;
int detach_no;
PixelType type;
diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp
index 72853be6e97..d7496845197 100644
--- a/src/gui/painting/qdrawhelper_avx2.cpp
+++ b/src/gui/painting/qdrawhelper_avx2.cpp
@@ -1525,7 +1525,7 @@ void QT_FASTCALL storeRGBA16FFromARGB32PM_avx2(uchar *dest, const uint *src, int
const __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
__m128 vsr = _mm_rcp_ps(vsa);
vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
- vsr = _mm_insert_ps(vsr, _mm_set_ss(1.0f), 0x30);
+ vsr = _mm_insert_ps(vsr, vf, 0x30);
vsf = _mm_mul_ps(vsf, vsr);
}
_mm_storel_epi64((__m128i *)(d + i), _mm_cvtps_ph(vsf, 0));
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index 028ae6d682a..6154f4121d2 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -726,9 +726,18 @@ namespace QtAndroidAccessibility
break;
}
+ float min = info.minValue.toFloat();
+ float max = info.maxValue.toFloat();
+ float current = info.currentValue.toFloat();
+ if (info.role == QAccessible::ProgressBar) {
+ rangeType = 2; // RANGE_TYPE_PERCENT
+ current = 100 * (current - min) / (max - min);
+ min = 0.0f;
+ max = 100.0f;
+ }
+
QJniObject rangeInfo("android/view/accessibility/AccessibilityNodeInfo$RangeInfo",
- "(IFFF)V", rangeType, info.minValue.toFloat(),
- info.maxValue.toFloat(), info.currentValue.toFloat());
+ "(IFFF)V", rangeType, min, max, current);
if (rangeInfo.isValid()) {
env->CallVoidMethod(node, m_setRangeInfoMethodID, rangeInfo.object());
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
index 35e804531bc..6a3c139a060 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.cpp
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
@@ -323,8 +323,9 @@ void QWasmAccessibility::setProperty(emscripten::val element, const std::string
}
-void QWasmAccessibility::addEventListener(emscripten::val element, const char *eventType)
+void QWasmAccessibility::addEventListener(QAccessibleInterface *iface, emscripten::val element, const char *eventType)
{
+ element.set("data-qta11yinterface", reinterpret_cast<size_t>(iface));
element.call<void>("addEventListener", emscripten::val(eventType),
QWasmSuspendResumeControl::get()->jsEventHandlerAt(m_eventHandlerIndex),
true);
@@ -352,7 +353,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
case QAccessible::Button: {
element = document.call<emscripten::val>("createElement", std::string("button"));
- addEventListener(element, "click");
+ addEventListener(iface, element, "click");
} break;
case QAccessible::CheckBox: {
@@ -360,7 +361,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
setAttribute(element, "type", "checkbox");
setAttribute(element, "checked", iface->state().checked);
setProperty(element, "indeterminate", iface->state().checkStateMixed);
- addEventListener(element, "change");
+ addEventListener(iface, element, "change");
} break;
case QAccessible::Switch: {
@@ -371,7 +372,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
setAttribute(element, "aria-checked", "true");
else
setAttribute(element, "aria-checked", "false");
- addEventListener(element, "change");
+ addEventListener(iface, element, "change");
} break;
case QAccessible::RadioButton: {
@@ -379,7 +380,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
setAttribute(element, "type", "radio");
setAttribute(element, "checked", iface->state().checked);
setProperty(element, "name", "buttonGroup");
- addEventListener(element, "change");
+ addEventListener(iface, element, "change");
} break;
case QAccessible::SpinBox:
@@ -413,7 +414,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("button"));
setAttribute(element, "role", "tab");
setAttribute(element, "title", text.toStdString());
- addEventListener(element, "click");
+ addEventListener(iface, element, "click");
} break;
case QAccessible::ScrollBar: {
@@ -422,7 +423,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("div"));
setAttribute(element, "role", "scrollbar");
setAttribute(element, "aria-valuenow", valueString);
- addEventListener(element, "change");
+ addEventListener(iface, element, "change");
} break;
case QAccessible::StaticText: {
@@ -436,7 +437,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("div"));
setAttribute(element, "role", "toolbar");
setAttribute(element, "title", text.toStdString());
- addEventListener(element, "click");
+ addEventListener(iface, element, "click");
}break;
case QAccessible::MenuItem:
case QAccessible::ButtonMenu: {
@@ -444,7 +445,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("button"));
setAttribute(element, "role", "menuitem");
setAttribute(element, "title", text.toStdString());
- addEventListener(element, "click");
+ addEventListener(iface, element, "click");
}break;
case QAccessible::MenuBar:
case QAccessible::PopupMenu: {
@@ -471,7 +472,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("div"));
}
- addEventListener(element, "focus");
+ addEventListener(iface, element, "focus");
return element;
}();
@@ -712,22 +713,26 @@ void QWasmAccessibility::handleLineEditUpdate(QAccessibleEvent *event)
void QWasmAccessibility::handleEventFromHtmlElement(const emscripten::val event)
{
- QAccessibleInterface *iface = m_elements.key(event["target"]);
+ if (event["target"].isNull() || event["target"].isUndefined())
+ return;
- if (iface == nullptr) {
+ if (event["target"]["data-qta11yinterface"].isNull() || event["target"]["data-qta11yinterface"].isUndefined())
return;
- } else {
- QString eventType = QString::fromStdString(event["type"].as<std::string>());
- const auto& actionNames = QAccessibleBridgeUtils::effectiveActionNames(iface);
-
- if (eventType == "focus") {
- if (actionNames.contains(QAccessibleActionInterface::setFocusAction()))
- iface->actionInterface()->doAction(QAccessibleActionInterface::setFocusAction());
- } else if (actionNames.contains(QAccessibleActionInterface::pressAction())) {
- iface->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
- } else if (actionNames.contains(QAccessibleActionInterface::toggleAction())) {
- iface->actionInterface()->doAction(QAccessibleActionInterface::toggleAction());
- }
+
+ auto iface = reinterpret_cast<QAccessibleInterface *>(event["target"]["data-qta11yinterface"].as<size_t>());
+ if (m_elements.find(iface) == m_elements.end())
+ return;
+
+ const QString eventType = QString::fromStdString(event["type"].as<std::string>());
+ const auto& actionNames = QAccessibleBridgeUtils::effectiveActionNames(iface);
+
+ if (eventType == "focus") {
+ if (actionNames.contains(QAccessibleActionInterface::setFocusAction()))
+ iface->actionInterface()->doAction(QAccessibleActionInterface::setFocusAction());
+ } else if (actionNames.contains(QAccessibleActionInterface::pressAction())) {
+ iface->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
+ } else if (actionNames.contains(QAccessibleActionInterface::toggleAction())) {
+ iface->actionInterface()->doAction(QAccessibleActionInterface::toggleAction());
}
}
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.h b/src/plugins/platforms/wasm/qwasmaccessibility.h
index 2b4716d64e7..26f3e0e9afe 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.h
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.h
@@ -116,7 +116,7 @@ private:
void setProperty(emscripten::val element, const std::string &attr, const char *val);
void setProperty(emscripten::val element, const std::string &attr, bool val);
- void addEventListener(emscripten::val element, const char *eventType);
+ void addEventListener(QAccessibleInterface *, emscripten::val element, const char *eventType);
private:
static QWasmAccessibility *s_instance;
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index c749cbd492f..431f91d5474 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -181,29 +181,17 @@ inline bool qCompare(quint32 const &t1, quint64 const &t2, const char *actual,
}
namespace Internal {
-template <typename T>
-class HasInitMain // SFINAE test for the presence of initMain()
-{
-private:
- using YesType = char[1];
- using NoType = char[2];
-
- template <typename C> static YesType& test( decltype(&C::initMain) ) ;
- template <typename C> static NoType& test(...);
-
-public:
- enum { value = sizeof(test<T>(nullptr)) == sizeof(YesType) };
-};
+template <typename T, typename = void>
+struct HasInitMain : std::false_type{};
-template<typename T>
-typename std::enable_if<HasInitMain<T>::value, void>::type callInitMain()
-{
- T::initMain();
-}
+template <typename T>
+struct HasInitMain<T, std::void_t<decltype(&T::initMain)>> : std::true_type {};
template<typename T>
-typename std::enable_if<!HasInitMain<T>::value, void>::type callInitMain()
+void callInitMain()
{
+ if constexpr (HasInitMain<T>::value)
+ T::initMain();
}
} // namespace Internal
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 51aea4079a1..6288aae096a 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -3108,7 +3108,8 @@ void QAbstractItemView::keyboardSearch(const QString &search)
QModelIndex startMatch;
QModelIndexList previous;
do {
- match = d->model->match(current, Qt::DisplayRole, d->keyboardInput);
+ match = d->model->match(current, Qt::DisplayRole, d->keyboardInput, 1,
+ d->keyboardSearchFlags);
if (match == previous)
break;
firstMatch = match.value(0);
@@ -3251,6 +3252,30 @@ void QAbstractItemView::setUpdateThreshold(int threshold)
}
/*!
+ \property QAbstractItemView::keyboardSearchFlags
+ \since 6.11
+ This property determines how the default implementation of
+ keyboardSearch() matches the given string against the model's data.
+
+ The default value is \c{Qt::MatchStartsWith|Qt::MatchWrap}.
+
+ \sa keyboardSearch()
+ \sa QAbstractItemModel::match()
+*/
+
+Qt::MatchFlags QAbstractItemView::keyboardSearchFlags() const
+{
+ Q_D(const QAbstractItemView);
+ return d->keyboardSearchFlags;
+}
+
+void QAbstractItemView::setKeyboardSearchFlags(Qt::MatchFlags searchFlags)
+{
+ Q_D(QAbstractItemView);
+ d->keyboardSearchFlags = searchFlags;
+}
+
+/*!
Opens a persistent editor on the item at the given \a index.
If no editor exists, the delegate will create a new editor.
diff --git a/src/widgets/itemviews/qabstractitemview.h b/src/widgets/itemviews/qabstractitemview.h
index 63adac8d6f2..973a9b044cb 100644
--- a/src/widgets/itemviews/qabstractitemview.h
+++ b/src/widgets/itemviews/qabstractitemview.h
@@ -48,6 +48,8 @@ class Q_WIDGETS_EXPORT QAbstractItemView : public QAbstractScrollArea
Q_PROPERTY(ScrollMode horizontalScrollMode READ horizontalScrollMode
WRITE setHorizontalScrollMode RESET resetHorizontalScrollMode)
Q_PROPERTY(int updateThreshold READ updateThreshold WRITE setUpdateThreshold)
+ Q_PROPERTY(Qt::MatchFlags keyboardSearchFlags READ keyboardSearchFlags
+ WRITE setKeyboardSearchFlags)
public:
enum SelectionMode {
@@ -182,6 +184,9 @@ public:
int updateThreshold() const;
void setUpdateThreshold(int threshold);
+ Qt::MatchFlags keyboardSearchFlags() const;
+ void setKeyboardSearchFlags(Qt::MatchFlags searchFlags);
+
void openPersistentEditor(const QModelIndex &index);
void closePersistentEditor(const QModelIndex &index);
bool isPersistentEditorOpen(const QModelIndex &index) const;
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h
index b24b2d21c33..60799fb8a50 100644
--- a/src/widgets/itemviews/qabstractitemview_p.h
+++ b/src/widgets/itemviews/qabstractitemview_p.h
@@ -383,6 +383,7 @@ public:
QString keyboardInput;
QElapsedTimer keyboardInputTime;
+ Qt::MatchFlags keyboardSearchFlags = Qt::MatchStartsWith | Qt::MatchWrap;
bool autoScroll;
QBasicTimer autoScrollTimer;
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index da1fbbd60df..84ff04c9f34 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -1030,7 +1030,8 @@ void QTreeView::keyboardSearch(const QString &search)
searchFrom = searchFrom.sibling(searchFrom.row(), start.column());
if (searchFrom.parent() == start.parent())
searchFrom = start;
- QModelIndexList match = d->model->match(searchFrom, Qt::DisplayRole, searchString);
+ QModelIndexList match = d->model->match(searchFrom, Qt::DisplayRole, searchString, 1,
+ keyboardSearchFlags());
if (match.size()) {
int hitIndex = d->viewIndex(match.at(0));
if (hitIndex >= 0 && hitIndex < startIndex)
diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
index 3804f53cae9..0b65673c393 100644
--- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
+++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
@@ -92,6 +92,7 @@ private slots:
void qIsNull();
void for_each();
void qassert();
+ void qpresume();
void qtry();
void checkptr();
void qstaticassert();
@@ -266,6 +267,18 @@ void tst_QGlobal::qassert()
QVERIFY(passed);
}
+/*non-static*/ Q_NEVER_INLINE char presumedValue(const char *str)
+{
+ Q_PRESUME(str);
+ // an optimizing compiler should delete the str? check
+ return str ? str[0] : '\0';
+}
+
+void tst_QGlobal::qpresume()
+{
+ QCOMPARE(presumedValue("Hello World"), 'H');
+}
+
void tst_QGlobal::qtry()
{
int i = 0;
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
index 9696f97f9f8..5453237cadb 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -188,6 +188,10 @@ private slots:
void testEscapedKeys();
void testUnescapedKeys_data();
void testUnescapedKeys();
+ void testEscapedStringList_data();
+ void testEscapedStringList();
+ void testUnescapedStringList_data();
+ void testUnescapedStringList();
void testNormalizedKey_data();
void testNormalizedKey();
void testVariantTypes_data() { populateWithFormats(); }
@@ -2836,26 +2840,6 @@ void tst_QSettings::testEscapes()
{
QSettings settings(QSettings::UserScope, "software.org", "KillerAPP");
-#define testEscapedStringList(plainStrList, escStrList) \
- { \
- QStringList plainList(plainStrList); \
- QByteArray escList(escStrList); \
- QCOMPARE(iniEscapedStringList(plainList), escList); \
- QCOMPARE(iniUnescapedStringList(escList), plainList); \
- } \
-
-
-#define testUnescapedStringList(escStrList, plainStrList, reescStrList) \
- { \
- QStringList plainList(plainStrList); \
- QByteArray escList(escStrList); \
- QByteArray reescList(reescStrList); \
- QCOMPARE(iniUnescapedStringList(escList), plainList); \
- QCOMPARE(iniEscapedStringList(plainList), reescList); \
- QCOMPARE(iniUnescapedStringList(reescList), plainList); \
- } \
-
-
#define testVariant(val, escStr, func) \
{ \
QVariant v(val); \
@@ -2871,41 +2855,6 @@ void tst_QSettings::testEscapes()
QCOMPARE(v.toString(), QString(vStr)); \
}
- testEscapedStringList("", "");
- testEscapedStringList(" ", "\" \"");
- testEscapedStringList(";", "\";\"");
- testEscapedStringList(",", "\",\"");
- testEscapedStringList("=", "\"=\"");
- testEscapedStringList("abc-def", "abc-def");
- testEscapedStringList(QChar(0) + QString("0"), "\\0\\x30");
- testEscapedStringList("~!@#$%^&*()_+.-/\\=", "\"~!@#$%^&*()_+.-/\\\\=\"");
- testEscapedStringList("~!@#$%^&*()_+.-/\\", "~!@#$%^&*()_+.-/\\\\");
- testEscapedStringList(QString("\x7F") + "12aFz", QByteArray("\x7f") + "12aFz");
- testEscapedStringList(QString(" \t\n\\n") + QChar(0x123) + QChar(0x4567), "\" \\t\\n\\\\n\xC4\xA3\xE4\x95\xA7\"");
- testEscapedStringList(QString("\a\b\f\n\r\t\v'\"?\001\002\x03\x04"), "\\a\\b\\f\\n\\r\\t\\v'\\\"?\\x1\\x2\\x3\\x4");
- testEscapedStringList(QStringList() << "," << ";" << "a" << "ab, \tc, d ", "\",\", \";\", a, \"ab, \\tc, d \"");
-
- /*
- Test .ini syntax that cannot be generated by QSettings (but can be entered by users).
- */
- testUnescapedStringList("", "", "");
- testUnescapedStringList("\"\"", "", "");
- testUnescapedStringList("\"abcdef\"", "abcdef", "abcdef");
- testUnescapedStringList("\"\\?\\'\\\"\"", "?'\"", "?'\\\"");
- testUnescapedStringList("\\0\\00\\000\\0000000\\1\\111\\11111\\x\\x0\\xABCDEFGH\\x0123456\\",
- QString() + QChar(0) + QChar(0) + QChar(0) + QChar(0) + QChar(1)
- + QChar(0111) + QChar(011111) + QChar(0) + QChar(0xCDEF) + "GH"
- + QChar(0x3456),
- "\\0\\0\\0\\0\\x1I\xE1\x89\x89\\0\xEC\xB7\xAFGH\xE3\x91\x96");
- testUnescapedStringList(QByteArray("\\c\\d\\e\\f\\g\\$\\*\\\0", 16), "\f", "\\f");
- testUnescapedStringList("\"a\", \t\"bc \", \" d\" , \"ef \" ,,g, hi i,,, ,",
- QStringList() << "a" << "bc " << " d" << "ef " << "" << "g" << "hi i"
- << "" << "" << "" << "",
- "a, \"bc \", \" d\", \"ef \", , g, hi i, , , , ");
- testUnescapedStringList("a , b , c d , efg ",
- QStringList() << "a" << "b" << "c d" << "efg",
- "a, b, c d, efg");
-
// streaming qvariant into a string
testVariant(QString("Hello World!"), QString("Hello World!"), toString);
testVariant(QString("Hello, World!"), QString("Hello, World!"), toString);
@@ -2994,6 +2943,125 @@ void tst_QSettings::testUnescapedKeys()
QCOMPARE(iniUnescapedKey(reescKey), plainKey);
}
+void tst_QSettings::testEscapedStringList_data()
+{
+ QTest::addColumn<QStringList>("plainStrList");
+ QTest::addColumn<QByteArray>("escapedList");
+
+ QTest::newRow("empty-string") << QStringList{u""_s} << ""_ba;
+ QTest::newRow("space") << QStringList{u" "_s} << "\" \""_ba;
+ QTest::newRow(";") << QStringList{u";"_s} << "\";\""_ba;
+ QTest::newRow(",") << QStringList{u","_s} << "\",\""_ba;
+ QTest::newRow("=") << QStringList{u"="_s} << "\"=\""_ba;
+ QTest::newRow("abc-def") << QStringList{u"abc-def"_s} << "abc-def"_ba;
+
+ QTest::newRow("starts-with-NUL")
+ << QStringList{QChar(0) + u"0"_s}
+ << "\\0\\x30"_ba;
+
+ QTest::newRow("special-characters1")
+ << QStringList{u"~!@#$%^&*()_+.-/\\="_s}
+ << "\"~!@#$%^&*()_+.-/\\\\=\""_ba;
+
+ QTest::newRow("special-characters2")
+ << QStringList{u"~!@#$%^&*()_+.-/\\"_s}
+ << "~!@#$%^&*()_+.-/\\\\"_ba;
+
+ QTest::newRow("DEL-character")
+ << QStringList{u"\x7F"_s + u"12aFz"_s}
+ << "\x7f"_ba + "12aFz"_ba;
+
+ QTest::newRow("tab-newline")
+ << QStringList{u" \t\n\\n"_s + QChar(0x123) + QChar(0x4567)}
+ << "\" \\t\\n\\\\n\xC4\xA3\xE4\x95\xA7\""_ba;
+
+ QTest::newRow("backslash-espcaped-input")
+ << QStringList{u"\a\b\f\n\r\t\v'\"?\001\002\x03\x04"_s}
+ << "\\a\\b\\f\\n\\r\\t\\v'\\\"?\\x1\\x2\\x3\\x4"_ba;
+
+ QTest::newRow("stringlist-with-tab")
+ << QStringList{u","_s, u";"_s, u"a"_s, u"ab, \tc, d "_s}
+ << "\",\", \";\", a, \"ab, \\tc, d \""_ba;
+}
+
+void tst_QSettings::testEscapedStringList()
+{
+ QFETCH(QStringList, plainStrList);
+ QFETCH(QByteArray, escapedList);
+
+ QSettings settings(QSettings::UserScope, "example.org", "KillerAPP");
+
+ QCOMPARE(iniEscapedStringList(plainStrList), escapedList);
+ QCOMPARE(iniUnescapedStringList(escapedList), plainStrList);
+}
+
+void tst_QSettings::testUnescapedStringList_data()
+{
+ QTest::addColumn<QByteArray>("escStrList");
+ QTest::addColumn<QStringList>("plainStrList");
+ QTest::addColumn<QByteArray>("reescStrList");
+
+ /*
+ Test .ini syntax that cannot be generated by QSettings (but can be entered by users).
+ */
+ QTest::newRow("empty")
+ << ""_ba
+ << QStringList{u""_s}
+ << ""_ba;
+
+ QTest::newRow("empty-double-quotes")
+ << "\"\""_ba
+ << QStringList{u""_s}
+ << ""_ba;
+
+ QTest::newRow("plain-quoted-string")
+ << "\"abcdef\""_ba
+ << QStringList{u"abcdef"_s}
+ << "abcdef"_ba;
+
+ QTest::newRow("backslash-non-letter-characters")
+ << "\"\\?\\'\\\"\""_ba
+ << QStringList{u"?'\""_s}
+ << "?'\\\""_ba;
+
+ const std::array arr = {QChar(0), QChar(0), QChar(0), QChar(0), QChar(1),
+ QChar(0111), QChar(011111), QChar(0), QChar(0xCDEF),
+ QChar(u'G'), QChar(u'H'), QChar(0x3456)};
+ QTest::newRow("array-of-qchar")
+ << "\\0\\00\\000\\0000000\\1\\111\\11111\\x\\x0\\xABCDEFGH\\x0123456\\"_ba
+ << QStringList{QString{arr}}
+ << "\\0\\0\\0\\0\\x1I\xE1\x89\x89\\0\xEC\xB7\xAFGH\xE3\x91\x96"_ba;
+
+ QTest::newRow("backslash-escapes")
+ << QByteArray("\\c\\d\\e\\f\\g\\$\\*\\\0", 16)
+ << QStringList{u"\f"_s}
+ << "\\f"_ba;
+
+ QTest::newRow("double-quotes-tab-character")
+ << "\"a\", \t\"bc \", \" d\" , \"ef \" ,,g, hi i,,, ,"_ba
+ << QStringList{u"a"_s, u"bc "_s, u" d"_s, u"ef "_s, u""_s, u"g"_s,
+ u"hi i"_s, u""_s, u""_s, u""_s, u""_s}
+ << "a, \"bc \", \" d\", \"ef \", , g, hi i, , , , "_ba;
+
+ QTest::newRow("abcdefg-extra-whitespaces")
+ << "a , b , c d , efg "_ba
+ << QStringList{u"a"_s, u"b"_s, u"c d"_s, u"efg"_s}
+ << "a, b, c d, efg"_ba;
+}
+
+void tst_QSettings::testUnescapedStringList()
+{
+ QFETCH(QByteArray, escStrList);
+ QFETCH(QStringList, plainStrList);
+ QFETCH(QByteArray, reescStrList);
+
+ QSettings settings(QSettings::UserScope, "example.org", "KillerAPP");
+
+ QCOMPARE(iniUnescapedStringList(escStrList), plainStrList);
+ QCOMPARE(iniEscapedStringList(plainStrList), reescStrList);
+ QCOMPARE(iniUnescapedStringList(reescStrList), plainStrList);
+}
+
#endif
void tst_QSettings::testCaseSensitivity()
diff --git a/tests/auto/testlib/initmain/tst_initmain.cpp b/tests/auto/testlib/initmain/tst_initmain.cpp
index 75a0d9ceb4d..cdaac0c14f4 100644
--- a/tests/auto/testlib/initmain/tst_initmain.cpp
+++ b/tests/auto/testlib/initmain/tst_initmain.cpp
@@ -19,6 +19,9 @@ private:
static bool m_initMainCalled;
};
+static_assert(QTest::Internals::HasInitMain<tst_InitMain>::value);
+static_assert(!QTest::Internals::HasInitMain<QObject>::value);
+
bool tst_InitMain::m_initMainCalled = false;
void tst_InitMain::testcase()
diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
index 8ee122ece18..6859f22c044 100644
--- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
+++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -842,6 +842,20 @@ void tst_QComboBox::virtualAutocompletion()
QApplication::sendEvent(testWidget, &kp2);
QApplication::sendEvent(testWidget, &kr2);
QTRY_COMPARE(testWidget->currentIndex(), 3);
+
+ QKeyEvent kp3(QEvent::KeyPress, Qt::Key_R, {}, "r");
+ QKeyEvent kr3(QEvent::KeyRelease, Qt::Key_R, {}, "r");
+ QTest::qWait(QApplication::keyboardInputInterval());
+ QApplication::sendEvent(testWidget, &kp3);
+ QApplication::sendEvent(testWidget, &kr3);
+ QTRY_COMPARE(testWidget->currentIndex(), 3);
+
+ QTest::qWait(QApplication::keyboardInputInterval());
+ testWidget->view()->setKeyboardSearchFlags(Qt::MatchContains | Qt::MatchWrap);
+ QApplication::sendEvent(testWidget, &kp3);
+ QApplication::sendEvent(testWidget, &kr3);
+ QTRY_COMPARE(testWidget->currentIndex(), 1);
+
#if defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS)
QApplication::setKeyboardInputInterval(oldInterval);
#endif