diff options
Diffstat (limited to 'src')
35 files changed, 390 insertions, 576 deletions
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index 82179cfd89a..8aad11dfca7 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -1157,6 +1157,18 @@ function(_qt_internal_assign_to_internal_targets_folder target) endif() endfunction() +# Returns the metatypes build dir where the Qt build system places module metatypes json files and +# other supporting metatypes files like ${target}_json_file_list.txt. +# The path is usually the target's BINARY_DIR + "/meta_types" +function(_qt_internal_get_metatypes_build_dir out_var target) + get_target_property(target_binary_dir "${target}" BINARY_DIR) + set(out_dir "${target_binary_dir}/meta_types") + set(${out_var} "${out_dir}" PARENT_SCOPE) +endfunction() + +# The AUTOGEN build dir is the location where all the generated .cpp files are placed, as well +# as the moc_predefs.h, timestamp file and deps files. +# E.g. ${CMAKE_CURRENT_BINARY_DIR}/${target}_autogen/moc_predefs.h function(_qt_internal_get_target_autogen_build_dir target out_var) get_property(target_autogen_build_dir TARGET ${target} PROPERTY AUTOGEN_BUILD_DIR) if(target_autogen_build_dir) @@ -1167,6 +1179,14 @@ function(_qt_internal_get_target_autogen_build_dir target out_var) endif() endfunction() +# The AUTOGEN info dir is the location where AutogenInfo.json and ParseCache.txt files are placed. +# E.g. ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target}_autogen.dir/ParseCache.txt +function(_qt_internal_get_target_autogen_info_dir target out_var) + get_target_property(target_binary_dir ${target} BINARY_DIR) + set(autogen_info_dir "${target_binary_dir}/CMakeFiles/${target}_autogen.dir") + set(${out_var} "${autogen_info_dir}" PARENT_SCOPE) +endfunction() + function(_qt_internal_should_install_metatypes target) set(args_option INTERNAL_INSTALL @@ -1354,12 +1374,14 @@ function(qt6_extract_metatypes target) return() endif() - get_target_property(target_binary_dir ${target} BINARY_DIR) - set(type_list_file "${target_binary_dir}/meta_types/${target}_json_file_list.txt") - set(type_list_file_manual "${target_binary_dir}/meta_types/${target}_json_file_list_manual.txt") + _qt_internal_get_metatypes_build_dir(metatypes_dir "${target}") + + set(type_list_file "${metatypes_dir}/${target}_json_file_list.txt") + set(type_list_file_manual "${metatypes_dir}/${target}_json_file_list_manual.txt") set(target_autogen_build_dir "") _qt_internal_get_target_autogen_build_dir(${target} target_autogen_build_dir) + _qt_internal_get_target_autogen_info_dir(${target} target_autogen_info_dir) get_target_property(uses_automoc ${target} AUTOMOC) set(automoc_args) @@ -1373,21 +1395,18 @@ function(qt6_extract_metatypes target) get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(NOT is_multi_config) - set(cmake_autogen_cache_file - "${target_binary_dir}/CMakeFiles/${target}_autogen.dir/ParseCache.txt") + set(cmake_autogen_cache_file "${target_autogen_info_dir}/ParseCache.txt") set(multi_config_args --cmake-autogen-include-dir-path "${target_autogen_build_dir}/include" ) else() - set(cmake_autogen_cache_file - "${target_binary_dir}/CMakeFiles/${target}_autogen.dir/ParseCache_$<CONFIG>.txt") + set(cmake_autogen_cache_file "${target_autogen_info_dir}/ParseCache_$<CONFIG>.txt") set(multi_config_args --cmake-autogen-include-dir-path "${target_autogen_build_dir}/include_$<CONFIG>" "--cmake-multi-config") endif() - set(cmake_autogen_info_file - "${target_binary_dir}/CMakeFiles/${target}_autogen.dir/AutogenInfo.json") + set(cmake_autogen_info_file "${target_autogen_info_dir}/AutogenInfo.json") set (use_dep_files FALSE) if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.17") # Requires automoc changes present only in 3.17 @@ -1502,11 +1521,11 @@ function(qt6_extract_metatypes target) string(TOLOWER ${target} target_lowercase) set(metatypes_file_name "qt6${target_lowercase}_metatypes.json") - set(metatypes_file "${target_binary_dir}/meta_types/${metatypes_file_name}") - set(metatypes_file_gen "${target_binary_dir}/meta_types/${metatypes_file_name}.gen") + set(metatypes_file "${metatypes_dir}/${metatypes_file_name}") + set(metatypes_file_gen "${metatypes_dir}/${metatypes_file_name}.gen") set(metatypes_dep_file_name "qt6${target_lowercase}_metatypes_dep.txt") - set(metatypes_dep_file "${target_binary_dir}/meta_types/${metatypes_dep_file_name}") + set(metatypes_dep_file "${metatypes_dir}/${metatypes_dep_file_name}") # Due to generated source file dependency rules being tied to the directory # scope in which they are created it is not possible for other targets which @@ -1517,7 +1536,7 @@ function(qt6_extract_metatypes target) # file is then replaced with the contents of the generated file during # build. if (NOT EXISTS ${metatypes_file}) - file(MAKE_DIRECTORY "${target_binary_dir}/meta_types") + file(MAKE_DIRECTORY "${metatypes_dir}") file(TOUCH ${metatypes_file}) endif() 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/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/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/qarraydataops.h b/src/corelib/tools/qarraydataops.h index 80641c4a281..c6259354de9 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -916,8 +916,10 @@ public: void assign(InputIterator first, InputIterator last, Projection proj = {}) { // This function only provides the basic exception guarantee. - using Category = typename std::iterator_traits<InputIterator>::iterator_category; - constexpr bool IsFwdIt = std::is_convertible_v<Category, std::forward_iterator_tag>; + constexpr bool IsFwdIt = std::is_convertible_v< + typename std::iterator_traits<InputIterator>::iterator_category, + std::forward_iterator_tag>; + constexpr bool IsIdentity = std::is_same_v<Projection, q20::identity>; const qsizetype n = IsFwdIt ? std::distance(first, last) : 0; bool undoPrependOptimization = true; @@ -993,23 +995,26 @@ public: } } - assign_impl(first, last, dst, dend, proj, Category{}); - } - - template <typename InputIterator, typename Projection> - void assign_impl(InputIterator first, InputIterator last, T *dst, T *dend, Projection proj, - std::input_iterator_tag) - { while (true) { if (first == last) { // ran out of elements to assign std::destroy(dst, dend); break; } if (dst == dend) { // ran out of existing elements to overwrite - do { - this->emplace(this->size, std::invoke(proj, *first)); - } while (++first != last); - return; // size() is already correct (and dst invalidated)! + if constexpr (IsFwdIt && IsIdentity) { + dst = std::uninitialized_copy(first, last, dst); + break; + } else if constexpr (IsFwdIt && !IsIdentity + && std::is_nothrow_constructible_v<T, decltype(std::invoke(proj, *first))>) { + for (; first != last; ++dst, ++first) // uninitialized_copy with projection + q20::construct_at(dst, std::invoke(proj, *first)); + break; + } else { + do { + this->emplace(this->size, std::invoke(proj, *first)); + } while (++first != last); + return; // size() is already correct (and dst invalidated)! + } } *dst = std::invoke(proj, *first); // overwrite existing element ++dst; @@ -1017,38 +1022,6 @@ public: } this->size = dst - this->begin(); } - - template <typename InputIterator, typename Projection> - void assign_impl(InputIterator first, InputIterator last, T *dst, T *, Projection proj, - std::forward_iterator_tag) - { - constexpr bool IsIdentity = std::is_same_v<Projection, q20::identity>; - const qsizetype n = std::distance(first, last); - if constexpr (IsIdentity && !QTypeInfo<T>::isComplex) { - // For non-complex types, we prefer a single std::copy() -> memcpy() - // call. We can do that because either the default constructor is - // trivial (so the lifetime has started) or the copy constructor is - // (and won't care what the stored value is). - std::copy(first, last, dst); - } else { - // overwrite existing elements and create new - qsizetype i = 0; - qsizetype size = this->size; - for ( ; i < size; ++i) { - *dst = std::invoke(proj, *first); // overwrite existing element - ++first; - ++dst; - } - for ( ; i < n; ++i) { - q20::construct_at(dst, std::invoke(proj, *first)); - ++first; - ++dst; - } - if (i < size) - std::destroy_n(dst, size - i); - } - this->size = n; - } }; } // namespace QtPrivate diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 098d0331327..4a3ed3ee110 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2626,6 +2626,7 @@ void QGuiApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::En } currentMouseWindow = e->enter; + lastCursorPosition = e->globalPos; // TODO later: EnterEvent must report _which_ mouse entered the window; for now we assume primaryPointingDevice() QEnterEvent event(e->localPos, e->localPos, e->globalPos); @@ -3407,6 +3408,15 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E return; QWindowPrivate *p = qt_window_private(window); + if (e->isExposed) { + // If the window has been automatically positioned or resized by the + // window manager, we now assume those have taken effect, even for + // asynchronous window managers. From this point on we want the window + // to keep its geometry, even when recreated. + p->positionAutomatic = false; + p->resizeAutomatic = false; + } + if (!p->receivedExpose) { if (p->resizeEventPending) { // as a convenience for plugins, send a resize event before the first expose event if they haven't done so diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index c23be8eb3ad..bad5932c457 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -582,12 +582,6 @@ void QWindowPrivate::create(bool recursive) platformWindow->initialize(); - // Now that the window is created and initialized the platform has had - // a chance to position and size it automatically. From this point on - // we want the window to keep its geometry, even when recreated. - positionAutomatic = false; - resizeAutomatic = false; - QObjectList childObjects = q->children(); for (int i = 0; i < childObjects.size(); i ++) { QObject *object = childObjects.at(i); diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 5763696266a..38c4a9ea87f 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -2937,6 +2937,8 @@ qreal QPainterPath::percentAtLength(qreal len) const if (len > totalLength) return 1; + Q_ASSERT(totalLength != 0); + if (d->cacheEnabled) { const int ei = qMax(d->elementAtT(len / totalLength), 1); // Skip initial MoveTo qreal res = 0; @@ -3117,6 +3119,7 @@ QPointF QPainterPath::pointAtPercent(qreal t) const qreal curLen = 0; qreal bezierLen = 0; QBezier b = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen); + Q_ASSERT(bezierLen != 0); qreal realT = (totalLength * t - curLen) / bezierLen; return b.pointAt(qBound(qreal(0), realT, qreal(1))); @@ -3141,10 +3144,14 @@ qreal QPainterPath::angleAtPercent(qreal t) const return 0; } + if (isEmpty()) + return 0; + qreal totalLength = length(); qreal curLen = 0; qreal bezierLen = 0; QBezier bez = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen); + Q_ASSERT(bezierLen != 0); qreal realT = (totalLength * t - curLen) / bezierLen; qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4); @@ -3170,10 +3177,14 @@ qreal QPainterPath::slopeAtPercent(qreal t) const return 0; } + if (isEmpty()) + return 0; + qreal totalLength = length(); qreal curLen = 0; qreal bezierLen = 0; QBezier bez = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen); + Q_ASSERT(bezierLen != 0); qreal realT = (totalLength * t - curLen) / bezierLen; qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4); diff --git a/src/gui/platform/darwin/qappleiconengine.mm b/src/gui/platform/darwin/qappleiconengine.mm index 20d50b0d8a8..3228b97fdb0 100644 --- a/src/gui/platform/darwin/qappleiconengine.mm +++ b/src/gui/platform/darwin/qappleiconengine.mm @@ -30,27 +30,28 @@ auto *loadImage(const QString &iconName) {"call-start"_L1, @"phone.arrow.up.right"}, {"call-stop"_L1, @"phone.down"}, {"contact-new"_L1, @"person.crop.circle.badge.plus"}, - {"document-new"_L1, @"doc.badge.plus"}, - {"document-open"_L1, @"folder"}, - {"document-open-recent"_L1, @"doc.badge.clock"}, - {"document-page-setup"_L1, @"doc.badge.gearshape"}, + {"document-new"_L1, @"plus"}, + {"document-open"_L1, @"arrow.up.forward"}, + {"document-open-recent"_L1, @"clock"}, + {"document-page-setup"_L1, @"text.page"}, {"document-print"_L1, @"printer"}, - //{"document-print-preview"_L1, @""}, - {"document-properties"_L1, @"doc.badge.ellipsis"}, - //{"document-revert"_L1, @""}, + {"document-print-preview"_L1, @"richtext.page"}, + {"document-properties"_L1, @"info.circle.text.page"}, + {"document-revert"_L1, @"arrow.counterclockwise"}, {"document-save"_L1, @"square.and.arrow.down"}, - //{"document-save-as"_L1, @""}, + {"document-save-as"_L1, @"square.and.arrow.down.on.square"}, {"document-send"_L1, @"paperplane"}, + {"document-export"_L1, @"square.and.arrow.up"}, {"edit-clear"_L1, @"xmark.circle"}, {"edit-copy"_L1, @"doc.on.doc"}, {"edit-cut"_L1, @"scissors"}, - {"edit-delete"_L1, @"delete.left"}, - {"edit-find"_L1, @"magnifyingglass"}, + {"edit-delete"_L1, @"trash"}, + {"edit-find"_L1, @"text.page.badge.magnifyingglass"}, //{"edit-find-replace"_L1, @"arrow.up.left.and.down.right.magnifyingglass"}, - {"edit-paste"_L1, @"clipboard"}, - {"edit-redo"_L1, @"arrowshape.turn.up.right"}, - //{"edit-select-all"_L1, @""}, - {"edit-undo"_L1, @"arrowshape.turn.up.left"}, + {"edit-paste"_L1, @"document.on.clipboard"}, + {"edit-redo"_L1, @"arrow.uturn.forward"}, + {"edit-select-all"_L1, @"character.textbox"}, + {"edit-undo"_L1, @"arrow.uturn.backward"}, {"folder-new"_L1, @"folder.badge.plus"}, {"format-indent-less"_L1, @"decrease.indent"}, {"format-indent-more"_L1, @"increase.indent"}, @@ -65,35 +66,36 @@ auto *loadImage(const QString &iconName) {"format-text-underline"_L1, @"underline"}, {"format-text-strikethrough"_L1, @"strikethrough"}, //{"go-bottom"_L1, @""}, - {"go-down"_L1, @"arrowshape.down"}, - {"go-first"_L1, @"increase.indent"}, + {"go-down"_L1, @"chevron.down"}, + //{"go-first"_L1, @""}, {"go-home"_L1, @"house"}, //{"go-jump"_L1, @""}, //{"go-last"_L1, @""}, - {"go-next"_L1, @"arrowshape.right"}, - {"go-previous"_L1, @"arrowshape.left"}, + {"go-next"_L1, @"chevron.right"}, + {"go-previous"_L1, @"chevron.left"}, //{"go-top"_L1, @""}, - {"go-up"_L1, @"arrowshape.up"}, + {"go-up"_L1, @"chevron.up"}, {"help-about"_L1, @"info.circle"}, //{"help-contents"_L1, @""}, {"help-faq"_L1, @"questionmark.app"}, {"insert-image"_L1, @"photo.badge.plus"}, {"insert-link"_L1, @"link.badge.plus"}, - //{"insert-object"_L1, @""}, - {"insert-text"_L1, @"textformat"}, + {"insert-object"_L1, @"widget.small.badge.plus"}, + {"insert-text"_L1, @"text.badge.plus"}, {"list-add"_L1, @"plus.circle"}, {"list-remove"_L1, @"minus.circle"}, {"mail-forward"_L1, @"arrowshape.turn.up.right"}, {"mail-mark-important"_L1, @"star"}, {"mail-mark-junk"_L1, @"xmark.bin"}, - {"mail-mark-notjunk"_L1, @"trash.slash"}, + {"mail-mark-notjunk"_L1, @"arrow.up.bin"}, {"mail-mark-read"_L1, @"envelope.open"}, - {"mail-mark-unread"_L1, @"envelope.fill"}, + {"mail-mark-unread"_L1, @"envelope.badge"}, {"mail-message-new"_L1, @"square.and.pencil"}, {"mail-reply-all"_L1, @"arrowshape.turn.up.left.2"}, {"mail-reply-sender"_L1, @"arrowshape.turn.up.left"}, - {"mail-send"_L1, @"paperplane"}, - {"mail-send-receive"_L1, @"envelope.arrow.triangle.branch"}, + {"mail-send"_L1, @"arrow.up.circle.fill"}, + {"mail-send-receive"_L1, @"arrow.trianglehead.2.clockwise.rotate.90"}, + {"mail-replied"_L1, @"envelope.and.arrow.trianglehead.branch"}, {"media-eject"_L1, @"eject"}, {"media-playback-pause"_L1, @"pause"}, {"media-playback-start"_L1, @"play"}, @@ -108,61 +110,61 @@ auto *loadImage(const QString &iconName) {"object-rotate-left"_L1, @"rotate.left"}, {"object-rotate-right"_L1, @"rotate.right"}, {"process-stop"_L1, @"stop.circle"}, - {"system-lock-screen"_L1, @"lock.display"}, - {"system-log-out"_L1, @"door.left.hand.open"}, + {"system-lock-screen"_L1, @"lock"}, + {"system-log-out"_L1, @"person.crop.circle"}, //{"system-run"_L1, @""}, {"system-search"_L1, @"magnifyingglass"}, - //{"system-reboot"_L1, @""}, + {"system-reboot"_L1, @"restart"}, {"system-shutdown"_L1, @"power"}, - //{"tools-check-spelling"_L1, @""}, + {"tools-check-spelling"_L1, @"textformat.characters.dottedunderline"}, {"view-fullscreen"_L1, @"arrow.up.left.and.arrow.down.right"}, {"view-refresh"_L1, @"arrow.clockwise"}, {"view-restore"_L1, @"arrow.down.right.and.arrow.up.left"}, - //{"view-sort-ascending"_L1, @""}, - //{"view-sort-descending"_L1, @""}, + {"view-sort-ascending"_L1, @"arrow.up"}, + {"view-sort-descending"_L1, @"arrow.down"}, {"window-close"_L1, @"xmark.circle"}, {"window-new"_L1, @"macwindow.badge.plus"}, {"zoom-fit-best"_L1, @"square.arrowtriangle.4.outward"}, {"zoom-in"_L1, @"plus.magnifyingglass"}, - //{"zoom-original"_L1, @""}, + {"zoom-original"_L1, @"1.magnifyingglass"}, {"zoom-out"_L1, @"minus.magnifyingglass"}, {"process-working"_L1, @"circle.dotted"}, - //{"accessories-calculator"_L1, @""}, - //{"accessories-character-map"_L1, @""}, + {"accessories-calculator"_L1, @"plus.forwardslash.minus"}, + {"accessories-character-map"_L1, @"keyboard.macwindow"}, {"accessories-dictionary"_L1, @"character.book.closed"}, {"accessories-text-editor"_L1, @"textformat"}, {"help-browser"_L1, @"folder.badge.questionmark"}, {"multimedia-volume-control"_L1, @"speaker.wave.3"}, {"preferences-desktop-accessibility"_L1, @"accessibility"}, - //{"preferences-desktop-font"_L1, @""}, - {"preferences-desktop-keyboard"_L1, @"keyboard.badge.ellipsis"}, - //{"preferences-desktop-locale"_L1, @""}, - //{"preferences-desktop-multimedia"_L1, @""}, - //{"preferences-desktop-screensaver"_L1, @""}, - //{"preferences-desktop-theme"_L1, @""}, - //{"preferences-desktop-wallpaper"_L1, @""}, + {"preferences-desktop-font"_L1, @"textformat.characters"}, + {"preferences-desktop-keyboard"_L1, @"keyboard"}, + {"preferences-desktop-locale"_L1, @"mappin.and.ellipse"}, + {"preferences-desktop-multimedia"_L1, @"music.note.tv"}, + {"preferences-desktop-screensaver"_L1, @"display"}, + {"preferences-desktop-theme"_L1, @"paintpalette"}, + {"preferences-desktop-wallpaper"_L1, @"photo.tv"}, {"system-file-manager"_L1, @"folder.badge.gearshape"}, - //{"system-software-install"_L1, @""}, - //{"system-software-update"_L1, @""}, d - //{"utilities-system-monitor"_L1, @""}, + {"system-software-install"_L1, @"laptopcomputer.and.arrow.down"}, + {"system-software-update"_L1, @"laptopcomputer.badge.checkmark"}, + {"utilities-system-monitor"_L1, @"chart.bar.xaxis"}, {"utilities-terminal"_L1, @"apple.terminal"}, - //{"applications-accessories"_L1, @""}, - //{"applications-development"_L1, @""}, - //{"applications-engineering"_L1, @""}, - {"applications-games"_L1, @"gamecontroller"}, - //{"applications-graphics"_L1, @""}, + {"applications-accessories"_L1, @"scanner"}, + {"applications-development"_L1, @"hammer"}, + {"applications-engineering"_L1, @"wrench.and.screwdriver"}, + {"applications-games"_L1, @"gamecontroller.circle"}, + {"applications-graphics"_L1, @"theatermask.and.paintbrush"}, {"applications-internet"_L1, @"network"}, {"applications-multimedia"_L1, @"tv.and.mediabox"}, - //{"applications-office"_L1, @""}, - //{"applications-other"_L1, @""}, + {"applications-office"_L1, @"square.and.pencil.circle"}, + {"applications-other"_L1, @"app.grid"}, {"applications-science"_L1, @"atom"}, - //{"applications-system"_L1, @""}, - //{"applications-utilities"_L1, @""}, + {"applications-system"_L1, @"gear"}, + {"applications-utilities"_L1, @"wrench.and.screwdriver"}, {"preferences-desktop"_L1, @"menubar.dock.rectangle"}, - //{"preferences-desktop-peripherals"_L1, @""}, - //{"preferences-desktop-personal"_L1, @""}, - //{"preferences-other"_L1, @""}, - //{"preferences-system"_L1, @""}, + {"preferences-desktop-peripherals"_L1, @"iphone.and.ipod"}, + {"preferences-desktop-personal"_L1, @"person.badge.key"}, + {"preferences-other"_L1, @"gear"}, + {"preferences-system"_L1, @"gear"}, {"preferences-system-network"_L1, @"network"}, {"system-help"_L1, @"questionmark.diamond"}, {"audio-card"_L1, @"waveform.circle"}, @@ -175,40 +177,40 @@ auto *loadImage(const QString &iconName) {"drive-harddisk"_L1, @"internaldrive"}, {"drive-optical"_L1, @"opticaldiscdrive"}, {"drive-removable-media"_L1, @"externaldrive"}, - {"input-gaming"_L1, @"gamecontroller"}, // "games" also using this one + {"input-gaming"_L1, @"gamecontroller"}, {"input-keyboard"_L1, @"keyboard"}, {"input-mouse"_L1, @"computermouse"}, {"input-tablet"_L1, @"ipad"}, {"media-flash"_L1, @"mediastick"}, //{"media-floppy"_L1, @""}, - //{"media-optical"_L1, @""}, + {"media-optical"_L1, @"opticaldisc"}, {"media-tape"_L1, @"recordingtape"}, - //{"modem"_L1, @""}, - {"multimedia-player"_L1, @"play.rectangle"}, + {"modem"_L1, @"phone.connection"}, + {"multimedia-player"_L1, @"ipod"}, {"network-wired"_L1, @"app.connected.to.app.below.fill"}, {"network-wireless"_L1, @"wifi"}, {"network-workgroup"_L1, @"network"}, - //{"pda"_L1, @""}, + {"pda"_L1, @"flipphone"}, {"phone"_L1, @"iphone"}, {"printer"_L1, @"printer"}, {"scanner"_L1, @"scanner"}, {"video-display"_L1, @"play.display"}, - //{"emblem-default"_L1, @""}, + {"emblem-default"_L1, @"circle"}, {"emblem-documents"_L1, @"doc.circle"}, {"emblem-downloads"_L1, @"arrow.down.circle"}, - {"emblem-favorite"_L1, @"star"}, - {"emblem-important"_L1, @"exclamationmark.bubble.circle"}, - {"emblem-mail"_L1, @"envelope"}, - {"emblem-photos"_L1, @"photo.stack"}, - //{"emblem-readonly"_L1, @""}, - {"emblem-shared"_L1, @"folder.badge.person.crop"}, + {"emblem-favorite"_L1, @"star.circle"}, + {"emblem-important"_L1, @"exclamationmark.circle"}, + {"emblem-mail"_L1, @"envelope.circle"}, + {"emblem-photos"_L1, @"photo.circle"}, + {"emblem-readonly"_L1, @"eye.circle"}, + {"emblem-shared"_L1, @"person.2.circle"}, {"emblem-symbolic-link"_L1, @"link.circle"}, {"emblem-synchronized"_L1, @"arrow.triangle.2.circlepath.circle"}, - {"emblem-system"_L1, @"gear"}, - //{"emblem-unreadable"_L1, @""}, + {"emblem-system"_L1, @"gear.circle"}, + {"emblem-unreadable"_L1, @"eye.slash.circle"}, {"text-x-generic"_L1, @"doc"}, // until iOS 18/macOS 15; @"document" after that {"folder"_L1, @"folder"}, - //{"folder-remote"_L1, @""}, + {"folder-remote"_L1, @"icloud"}, {"network-server"_L1, @"server.rack"}, //{"start-here"_L1, @""}, {"user-bookmarks"_L1, @"bookmark.circle"}, @@ -229,28 +231,28 @@ auto *loadImage(const QString &iconName) {"dialog-question"_L1, @"questionmark.circle"}, {"dialog-warning"_L1, @"exclamationmark.octagon"}, {"folder-drag-accept"_L1, @"plus.rectangle.on.folder"}, - //{"folder-open"_L1, @""}, + {"folder-open"_L1, @"arrow.forward.folder"}, {"folder-visiting"_L1, @"folder.circle"}, - {"image-loading"_L1, @"photo.circle"}, - {"image-missing"_L1, @"photo"}, + {"image-loading"_L1, @"photo.badge.arrow.down"}, + {"image-missing"_L1, @"photo.badge.exclamationmark"}, {"mail-attachment"_L1, @"paperclip"}, {"mail-unread"_L1, @"envelope.badge"}, {"mail-read"_L1, @"envelope.open"}, - {"mail-replied"_L1, @"arrowshape.turn.up.left"}, + //{"mail-replied"_L1, @""}, //{"mail-signed"_L1, @""}, - //{"mail-signed-verified"_L1, @""}, - {"media-playlist-repeat"_L1, @"repet"}, + {"mail-signed-verified"_L1, @"envelope.badge.shield.half.filled"}, + {"media-playlist-repeat"_L1, @"repeat"}, {"media-playlist-shuffle"_L1, @"shuffle"}, - //{"network-error"_L1, @""}, - //{"network-idle"_L1, @""}, - {"network-offline"_L1, @"network.slash"}, - //{"network-receive"_L1, @""}, - //{"network-transmit"_L1, @""}, - //{"network-transmit-receive"_L1, @""}, + {"network-error"_L1, @"xmark.icloud"}, + {"network-idle"_L1, @"icloud"}, + {"network-offline"_L1, @"icloud.slash"}, + {"network-receive"_L1, @"icloud.and.arrow.down"}, + {"network-transmit"_L1, @"icloud.and.arrow.up"}, + {"network-transmit-receive"_L1, @"arrow.trianglehead.2.clockwise.rotate.90.icloud"}, //{"printer-error"_L1, @""}, - {"printer-printing"_L1, @"printer.dotmatrix.filled.and.paper"}, // not sure - {"security-high"_L1, @"lock.shield"}, - //{"security-medium"_L1, @""}, + {"printer-printing"_L1, @"printer.dotmatrix"}, + {"security-high"_L1, @"lock.badge.checkmark"}, + {"security-medium"_L1, @"lock"}, {"security-low"_L1, @"lock.trianglebadge.exclamationmark"}, {"software-update-available"_L1, @"arrowshape.up.circle"}, {"software-update-urgent"_L1, @"exclamationmark.transmission"}, @@ -258,9 +260,9 @@ auto *loadImage(const QString &iconName) {"sync-synchronizing"_L1, @"arrow.triangle.2.circlepath"}, {"task-due"_L1, @"clock.badge.exclamationmark"}, {"task-past-due"_L1, @"clock.badge.xmark"}, - {"user-available"_L1, @"person.crop.circle.badge.checkmark"}, - {"user-away"_L1, @"person.crop.circle.badge.clock"}, - //{"user-idle"_L1, @""}, + {"user-available"_L1, @"person.crop.circle.badge"}, + {"user-away"_L1, @"person.crop.circle.badge.moon"}, + {"user-idle"_L1, @"person.crop.circle.badge.clock"}, {"user-offline"_L1, @"person.crop.circle.badge.xmark"}, //{"user-trash-full"_L1, @""}, {"weather-clear"_L1, @"sun.max"}, @@ -269,9 +271,9 @@ auto *loadImage(const QString &iconName) {"weather-few-clouds-night"_L1, @"cloud.moon"}, {"weather-fog"_L1, @"cloud.fog"}, {"weather-overcast"_L1, @"cloud"}, - //{"weather-severe-alert"_L1, @""}, - {"weather-showers"_L1, @"cloud.rain"}, - //{"weather-showers-scattered"_L1, @""}, + {"weather-severe-alert"_L1, @"cloud.bolt.rain"}, + {"weather-showers"_L1, @"cloud.heavyrain"}, + {"weather-showers-scattered"_L1, @"cloud.drizzle"}, {"weather-snow"_L1, @"cloud.snow"}, {"weather-storm"_L1, @"tropicalstorm"}, }; diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 120d2ecbc78..430197ccc6e 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -33,7 +33,7 @@ #include <sys/socket.h> #include <netinet/sctp.h> #endif -#ifdef Q_OS_BSD4 +#ifdef AF_LINK # include <net/if_dl.h> #endif @@ -142,10 +142,6 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, level = IPPROTO_IP; #ifdef IP_PKTINFO n = IP_PKTINFO; -#elif defined(IP_RECVDSTADDR) - // variant found in QNX and FreeBSD; it will get us only the - // destination address, not the interface; we need IP_RECVIF for that. - n = IP_RECVDSTADDR; #endif } break; @@ -360,6 +356,18 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::BindExclusively: return true; + case QNativeSocketEngine::ReceivePacketInformation: + if (socketProtocol == QAbstractSocket::IPv4Protocol) { +#if !defined(IP_PKTINFO) && defined(IP_RECVDSTADDR) && defined(IP_RECVIF) + // Seen on FreeBSD and QNX. We need both to get the information we want. + int r = 0; + r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVDSTADDR, &v, sizeof(v)); + r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVIF, &v, sizeof(v)); + return r == 0; +#endif + } + break; + case QNativeSocketEngine::MaxStreamsSocketOption: { #ifndef QT_NO_SCTP sctp_initmsg sctpInitMsg; @@ -915,7 +923,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS { // we use quintptr to force the alignment quintptr cbuf[(CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)) -#if !defined(IP_PKTINFO) && defined(IP_RECVIF) && defined(Q_OS_BSD4) +#if !defined(IP_PKTINFO) && defined(IP_RECVIF) && defined(AF_LINK) + CMSG_SPACE(sizeof(sockaddr_dl)) #endif #ifndef QT_NO_SCTP @@ -1007,7 +1015,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS header->destinationAddress.setAddress(ntohl(addr->s_addr)); } # endif -# if defined(IP_RECVIF) && defined(Q_OS_BSD4) +# if defined(IP_RECVIF) && defined(AF_LINK) if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(sockaddr_dl))) { sockaddr_dl *sdl = reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr)); diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index d4c5d0f0425..e0ef6cec794 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -161,7 +161,8 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions; bool selectable = (m_options->acceptMode() == QFileDialogOptions::AcceptSave) || [self panel:m_panel shouldEnableURL:url]; - m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @""; + if (!openpanel_cast(m_panel)) + m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @""; [self updateProperties]; diff --git a/src/plugins/platforms/cocoa/qnsview_keys.mm b/src/plugins/platforms/cocoa/qnsview_keys.mm index aab01a7b439..e9ef769ec4b 100644 --- a/src/plugins/platforms/cocoa/qnsview_keys.mm +++ b/src/plugins/platforms/cocoa/qnsview_keys.mm @@ -114,6 +114,9 @@ static bool sendAsShortcut(const KeyEvent &keyEvent, QWindow *window) qCDebug(lcQpaKeys) << "Interpreting key event for focus object" << focusObject; m_currentlyInterpretedKeyEvent = nsevent; + // Asking the input context to handle the event will involve both + // the current input method, as well as NSKeyBindingManager, which + // may result in action callbacks to doCommandBySelector. if (![self.inputContext handleEvent:nsevent]) { qCDebug(lcQpaKeys) << "Input context did not consume event"; m_sendKeyEvent = true; diff --git a/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm index 4e019b69cc4..6ca6554f673 100644 --- a/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm +++ b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm @@ -7,8 +7,10 @@ #include "qiosdocumentpickercontroller.h" +#include <QtCore/qpointer.h> + @implementation QIOSDocumentPickerController { - QIOSFileDialog *m_fileDialog; + QPointer<QIOSFileDialog> m_fileDialog; } - (instancetype)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog @@ -61,6 +63,9 @@ { Q_UNUSED(controller); + if (!m_fileDialog) + return; + QList<QUrl> files; for (NSURL* url in urls) files.append(QUrl::fromNSURL(url)); @@ -71,12 +76,18 @@ - (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller { + if (!m_fileDialog) + return; + Q_UNUSED(controller); emit m_fileDialog->reject(); } - (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController { + if (!m_fileDialog) + return; + Q_UNUSED(presentationController); // "Called on the delegate when the user has taken action to dismiss the diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp index 35e804531bc..5fa79482217 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; }(); @@ -542,6 +543,7 @@ void QWasmAccessibility::linkToParent(QAccessibleInterface *iface) { emscripten::val element = getHtmlElement(iface); emscripten::val container = getElementContainer(iface); + if (container.isUndefined() || element.isUndefined()) return; @@ -554,21 +556,21 @@ void QWasmAccessibility::linkToParent(QAccessibleInterface *iface) emscripten::val next = emscripten::val::undefined(); const int thisIndex = iface->parent()->indexOfChild(iface); - Q_ASSERT(thisIndex >= 0 && thisIndex < iface->parent()->childCount()); - for (int i = thisIndex + 1; i < iface->parent()->childCount(); ++i) { - const auto elementI = getHtmlElement(iface->parent()->child(i)); - if (!elementI.isUndefined() && - elementI["parentElement"] == container) { - next = elementI; - break; + if (thisIndex >= 0) { + Q_ASSERT(thisIndex < iface->parent()->childCount()); + for (int i = thisIndex + 1; i < iface->parent()->childCount(); ++i) { + const auto elementI = getHtmlElement(iface->parent()->child(i)); + if (!elementI.isUndefined() && + elementI["parentElement"] == container) { + next = elementI; + break; + } } + if (next.isUndefined()) + container.call<void>("appendChild", element); + else + container.call<void>("insertBefore", element, next); } - if (next.isUndefined()) { - container.call<void>("appendChild", element); - } else { - container.call<void>("insertBefore", element, next); - } - const auto activeElementAfter = emscripten::val::take_ownership( getActiveElement_js(emscripten::val::undefined().as_handle())); if (activeElementBefore != activeElementAfter) { @@ -712,22 +714,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/plugins/platforms/wasm/qwasminputcontext.cpp b/src/plugins/platforms/wasm/qwasminputcontext.cpp index 614d5bd25a3..18a457198f1 100644 --- a/src/plugins/platforms/wasm/qwasminputcontext.cpp +++ b/src/plugins/platforms/wasm/qwasminputcontext.cpp @@ -225,8 +225,8 @@ void QWasmInputContext::updateGeometry() qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << "propagating inputItemRectangle:" << inputItemRectangle; m_inputElement["style"].set("left", std::to_string(inputItemRectangle.x()) + "px"); m_inputElement["style"].set("top", std::to_string(inputItemRectangle.y()) + "px"); - m_inputElement["style"].set("width", std::to_string(inputItemRectangle.width()) + "px"); - m_inputElement["style"].set("height", std::to_string(inputItemRectangle.height()) + "px"); + m_inputElement["style"].set("width", "1px"); + m_inputElement["style"].set("height", "1px"); } } diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp index 25142612c4f..3b1b7a7eacb 100644 --- a/src/plugins/styles/modernwindows/qwindows11style.cpp +++ b/src/plugins/styles/modernwindows/qwindows11style.cpp @@ -923,15 +923,13 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption case PE_IndicatorRadioButton: { const bool isRtl = option->direction == Qt::RightToLeft; const bool isOn = option->state & State_On; - qreal innerRadius = 7.0f; + qreal innerRadius = radioButtonInnerRadius(state); if (d->transitionsEnabled() && option->styleObject) { if (option->styleObject->property("_q_end_radius").isNull()) option->styleObject->setProperty("_q_end_radius", innerRadius); QNumberStyleAnimation *animation = qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject)); innerRadius = animation ? animation->currentValue() : option->styleObject->property("_q_end_radius").toFloat(); option->styleObject->setProperty("_q_inner_radius", innerRadius); - } else { - innerRadius = radioButtonInnerRadius(state); } QRectF rect = isRtl ? option->rect.adjusted(0, 0, -2, 0) : option->rect.adjusted(2, 0, 0, 0); @@ -2452,9 +2450,6 @@ void QWindows11Style::polish(QPalette& result) SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Text, result.text().color()); SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::WindowText, result.windowText().color()); - if (highContrastTheme) - result.setColor(QPalette::Active, QPalette::HighlightedText, result.windowText().color()); - auto *d = const_cast<QWindows11StylePrivate *>(d_func()); d->m_titleBarMinIcon = QIcon(); d->m_titleBarMaxIcon = QIcon(); diff --git a/src/testinternal/QtRunCMakeTestWrappers.cmake b/src/testinternal/QtRunCMakeTestWrappers.cmake index fdf93692e1f..cead9e52c82 100644 --- a/src/testinternal/QtRunCMakeTestWrappers.cmake +++ b/src/testinternal/QtRunCMakeTestWrappers.cmake @@ -30,10 +30,24 @@ function(qt_internal_add_RunCMake_test test) string(JOIN "\n" pre_run_code ${_qt_internal_skip_build_test_pre_run}) + set(android_code "") + if(ANDROID) + qt_internal_get_android_cmake_policy_version_minimum_value(version) + string(APPEND android_code " +# Avoid cmake policy deprecation warnings with older android NDKs appearing in stderr, which +# causes test failures if the test doesn't set +# set(RunCMake_TEST_OUTPUT_MERGE 1) +# to avoid stderr being polluted. +if(NOT QT_NO_SET_RUN_CMAKE_TESTS_CMAKE_POLICY_VERSION_MINIMUM) + set(ENV{CMAKE_POLICY_VERSION_MINIMUM} ${version}) +endif()") + endif() + _qt_internal_configure_file(CONFIGURE OUTPUT "${wrapper_file}" CONTENT " ${pre_run_code} +${android_code} include(\"${script_path_to_include}\") ") 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/testlib/qtestcase.h b/src/testlib/qtestcase.h index ebb32238d67..ad3874bd4c9 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -430,7 +430,7 @@ namespace QTest Q_TESTLIB_EXPORT int qExec(QObject *testObject, const QStringList &arguments); #if QT_CONFIG(batch_test_support) || defined(Q_QDOC) - using TestEntryFunction = int (*)(int, char **); + using TestEntryFunction = std::function<int(int, char **)>; Q_TESTLIB_EXPORT void qRegisterTestCase(const QString &name, TestEntryFunction entryFunction); #endif // QT_CONFIG(batch_test_support) diff --git a/src/testlib/qtestregistry_p.h b/src/testlib/qtestregistry_p.h index 85e236cd046..fcfa6c60701 100644 --- a/src/testlib/qtestregistry_p.h +++ b/src/testlib/qtestregistry_p.h @@ -26,7 +26,7 @@ QT_BEGIN_NAMESPACE namespace QTest { class TestRegistry { public: - using TestEntryFunction = int(*)(int argv, char** argc); + using TestEntryFunction = std::function<int(int, char **)>; static TestRegistry* instance(); diff --git a/src/tools/macdeployqt/macdeployqt/main.cpp b/src/tools/macdeployqt/macdeployqt/main.cpp index f5e6ab8f31a..ecbccdef2b3 100644 --- a/src/tools/macdeployqt/macdeployqt/main.cpp +++ b/src/tools/macdeployqt/macdeployqt/main.cpp @@ -77,7 +77,7 @@ int main(int argc, char **argv) QStringList qmlDirs; QStringList qmlImportPaths; extern bool runCodesign; - extern QString codesignIdentiy; + QString codesignIdentity = QStringLiteral("-"); extern bool hardenedRuntime; bool noCodesignExplicit = false; extern bool appstoreCompliant; @@ -166,7 +166,7 @@ int main(int argc, char **argv) return 1; } else { runCodesign = true; - codesignIdentiy = argument.mid(index+1); + codesignIdentity = argument.mid(index + 1); } } else if (argument.startsWith(QByteArray("-sign-for-notarization"))) { LogDebug() << "Argument found:" << argument; @@ -182,7 +182,7 @@ int main(int argc, char **argv) runCodesign = true; hardenedRuntime = true; secureTimestamp = true; - codesignIdentiy = argument.mid(index+1); + codesignIdentity = argument.mid(index + 1); } } else if (argument.startsWith(QByteArray("-hardened-runtime"))) { LogDebug() << "Argument found:" << argument; @@ -273,7 +273,7 @@ int main(int argc, char **argv) stripAppBinary(appBundlePath); if (runCodesign) - codesign(codesignIdentiy, appBundlePath); + codesign(codesignIdentity, appBundlePath); if (dmg) { LogNormal(); diff --git a/src/tools/macdeployqt/shared/shared.cpp b/src/tools/macdeployqt/shared/shared.cpp index 4e81229ebf5..bd7f4fba854 100644 --- a/src/tools/macdeployqt/shared/shared.cpp +++ b/src/tools/macdeployqt/shared/shared.cpp @@ -30,7 +30,6 @@ bool runStripEnabled = true; bool alwaysOwerwriteEnabled = false; bool runCodesign = true; QStringList librarySearchPath; -QString codesignIdentiy = "-"; QString extraEntitlements; bool hardenedRuntime = false; bool secureTimestamp = false; diff --git a/src/widgets/doc/src/modelview.qdoc b/src/widgets/doc/src/modelview.qdoc index b2448a2c705..121cc30ed09 100644 --- a/src/widgets/doc/src/modelview.qdoc +++ b/src/widgets/doc/src/modelview.qdoc @@ -573,281 +573,10 @@ out of range when using ModelTest. - \section1 4. Good Sources of Additional Information - - \section2 4.1 Books - - Model/View programming is covered quite extensively in the documentation of - Qt but also in several good books. - - \list 1 - \li \b{C++ GUI Programming with Qt 4} / Jasmin Blanchette, Mark Summerfield, - \e{Prentice Hall, 2nd edition}, ISBN 0-13-235416-0. Also available in - German: \b{C++ GUI Programmierung mit Qt 4: Die offizielle Einführung}, - \e{Addison-Wesley}, ISBN 3-827327-29-6 - \li \b{The Book of Qt4, The Art of Building Qt Applications} / Daniel Molkentin, - \e{Open Source Press}, ISBN 1-59327-147-6. - Translated from \b{Qt 4, Einführung in die Applikationsentwicklung}, - \e{Open Source Press}, ISBN 3-937514-12-0. - \li \b{Foundations of Qt Development} / Johan Thelin, \e{Apress}, ISBN 1-59059-831-8. - \li \b{Advanced Qt Programming} / Mark Summerfield, \e{Prentice Hall}, ISBN 0-321-63590-6. - This book covers Model/View programming on more than 150 pages. - \endlist - - The following list provides an overview of example programs contained in the first three - books listed above. Some of them make very good templates for developing similar - applications. - - \table - \header - \li Example name - \li View class used - \li Model used - \li Aspects covered - \li - \row - \li Team Leaders - \li QListview - \li QStringListModel - \li - \li Book 1, Chapter 10, Figure 10.6 - \row - \li Color Names - \li QListView - \li QSortFilterProxyModel - applied to QStringListModel - \li - \li Book 1, Chapter 10, Figure 10.8 - \row - \li Currencies - \li QTableView - \li custom model based on - QAbstractTableModel - \li Read only - \li Book 1, Chapter 10, Figure 10.10 - \row - \li Cities - \li QTableView - \li Custom model based on - QAbstractTableModel - \li Read / write - \li Book 1, Chapter 10, Figure 10.12 - \row - \li Boolean Parser - \li QTreeView - \li Custom model based on - QAbstractItemModel - \li Read only - \li Book 1, Chapter 10, Figure 10.14 - \row - \li Track Editor - \li {2, 1} QTableWidget - \li Custom delegate providing a custom editor - \li Book 1, Chapter 10, Figure 10.15 - - \row - \li Address Book - \li QListView - QTableView - QTreeView - \li Custom model based on - QAbstractTableModel - \li Read / write - \li Book2, Chapter 8.4 - \row - \li Address Book with sorting - \li - \li QSortfilterProxyModel - \li Introducing sort and filter capabilities - \li Book2, Chapter 8.5 - \row - \li Address Book - with checkboxes - \li - \li - \li Introducing checkboxes in model/view - \li Book2, Chapter 8.6 - \row - \li Address Book with transposed grid - \li - \li Custom proxy Model based on QAbstractProxyModel - \li Introducing a custom model - \li Book2, Chapter 8.7 - \row - \li Address Book with drag and drop - \li - \li - \li Introducing drag and drop support - \li Book2, Chapter 8.8 - \row - \li Address Book with custom editor - \li - \li - \li Introducing custom delegates - \li Book2, Chapter 8.9 - \row - \li Views - \li QListView - QTableView - QTreeView - \li QStandardItemModel - \li Read only - \li Book 3, Chapter 5, figure 5-3 - \row - \li Bardelegate - \li QTableView - \li - \li Custom delegate for presentation based on QAbstractItemDelegate - \li Book 3, Chapter 5, figure 5-5 - \row - \li Editdelegate - \li QTableView - \li - \li Custom delegate for editing based on QAbstractItemDelegate - \li Book 3, Chapter 5, figure 5-6 - \row - \li Singleitemview - \li Custom view based on QAbstractItemView - \li - \li Custom view - \li Book 3, - Chapter 5, - figure 5-7 - \row - \li listmodel - \li QTableView - \li Custom Model based on QAbstractTableModel - \li Read only - \li Book 3, Chapter 5, Figure 5-8 - \row - \li treemodel - \li QTreeView - \li Custom Model based on QAbstractItemModel - \li Read only - \li Book 3, Chapter 5, Figure 5-10 - \row - \li edit integers - \li QListView - \li Custom Model based on QAbstractListModel - \li Read / write - \li Book 3, Chapter 5, Listing 5-37, Figure 5-11 - \row - \li sorting - \li QTableView - \li QSortFilterProxyModel applied to QStringListModel - \li Demonstrates sorting - \li Book 3, Chapter 5, Figure 5-12 - \endtable - - - \section2 4.2 Qt Documentation - - Qt 5.0 comes with 19 examples for model/view. - The examples can be found on the \l{Item Views Examples} page. - - \table - \header - \li Example name - \li View class used - \li Model used - \li Aspects covered - \row - \li Address Book - \li QTableView - \li QAbstractTableModel - QSortFilterProxyModel - \li Usage of QSortFilterProxyModel to generate different - subsets from one data pool - \row - \li Basic Sort/Filter Model - \li QTreeView - \li QStandardItemModel - QSortFilterProxyModel - \li - \row - \li Chart - \li Custom view - \li QStandardItemModel - \li Designing custom views that cooperate with selection models - \row - \li Color Editor Factory - \li {2, 1} QTableWidget - \li Enhancing the standard delegate with a new custom editor to choose colours - \row - \li Combo Widget Mapper - \li QDataWidgetMapper to map QLineEdit, QTextEdit and QComboBox - \li QStandardItemModel - \li Shows how a QComboBox can serve as a view class - \row - \li Custom Sort/Filter Model - \li QTreeView - \li QStandardItemModel - QSortFilterProxyModel - \li Subclass QSortFilterProxyModel for advanced sorting and filtering - \row - \li Dir View - \li QTreeView - \li QFileSystemModel - \li Very small example to demonstrate how to assign a model to a view - \row - \li Editable Tree Model - \li QTreeView - \li Custom tree model - \li Comprehensive example for working with trees, demonstrates - editing cells and tree structure with an underlying custom - model - \row - \li Fetch More - \li QListView - \li Custom list model - \li Dynamically changing model - \row - \li Frozen Column - \li QTableView - \li QStandardItemModel - \li - \row - \li Interview - \li Multiple - \li Custom item model - \li Multiple views - \row - \li Pixelator - \li QTableView - \li Custom table model - \li Implementation of a custom delegate - \row - \li Puzzle - \li QListView - \li Custom list model - \li Model/view with drag and drop - \row - \li Simple DOM Model - \li QTreeView - \li Custom tree model - \li Read only example for a custom tree model - \row - \li Simple Tree Model - \li QTreeView - \li Custom tree model - \li Read only example for a custom tree model - \row - \li Simple Widget Mapper - \li QDataWidgetMapper to map QLineEdit, QTextEdit and QSpinBox - \li QStandardItemModel - \li Basic QDataWidgetMapper usage - \row - \li Spreadsheet - \li {2, 1} QTableView - \li Custom delegates - \row - \li Star Delegate - \li {2, 1} QTableWidget - \li Comprehensive custom delegate example. - \endtable + \section1 Examples - A \l{Model/View Programming}{reference document} for model/view technology - is also available. + Qt comes with multiple examples for model/view. You can find them on the + \l{Item Views Examples} page. */ /*! 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/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 82d16cb1252..b2cfb27e814 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -3419,29 +3419,28 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC } QRect gr = subControlRect(cc, opt, SC_SliderGroove, w); - if (slider->subControls & SC_SliderGroove) { + if (slider->subControls & SC_SliderGroove) grooveSubRule.drawRule(p, gr); - } if (slider->subControls & SC_SliderHandle) { QRect hr = subControlRect(cc, opt, SC_SliderHandle, w); - QRenderRule subRule1 = renderRule(w, opt, PseudoElement_SliderSubPage); - if (subRule1.hasDrawable()) { - QRect r(gr.topLeft(), - slider->orientation == Qt::Horizontal - ? QPoint(hr.x()+hr.width()/2, gr.y()+gr.height() - 1) - : QPoint(gr.x()+gr.width() - 1, hr.y()+hr.height()/2)); - subRule1.drawRule(p, r); - } - - QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SliderAddPage); - if (subRule2.hasDrawable()) { - QRect r(slider->orientation == Qt::Horizontal - ? QPoint(hr.x()+hr.width()/2+1, gr.y()) - : QPoint(gr.x(), hr.y()+hr.height()/2+1), - gr.bottomRight()); - subRule2.drawRule(p, r); + if (slider->subControls & SC_SliderGroove) { + const bool isHor = slider->orientation == Qt::Horizontal; + QRenderRule subRule1 = renderRule(w, opt, PseudoElement_SliderSubPage); + if (subRule1.hasDrawable()) { + QRect r(gr.topLeft(), + isHor ? QPoint(hr.x() + hr.width() / 2, gr.y() + gr.height() - 1) + : QPoint(gr.x() + gr.width() - 1, hr.y() + hr.height() / 2)); + subRule1.drawRule(p, r); + } + QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SliderAddPage); + if (subRule2.hasDrawable()) { + QRect r(isHor ? QPoint(hr.x() + hr.width() / 2 + 1, gr.y()) + : QPoint(gr.x(), hr.y() + hr.height() / 2 + 1), + gr.bottomRight()); + subRule2.drawRule(p, r); + } } handleSubRule.drawRule(p, handleSubRule.boxRect(hr, Margin)); diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 1708a53f163..055d8f3d11e 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -572,8 +572,6 @@ bool QDockWidgetGroupWindow::hasNativeDecos() const #endif } -QT_WARNING_PUSH -QT_WARNING_DISABLE_GCC("-Waggressive-loop-optimizations") /* The given widget is hovered over this floating group. This function will save the state and create a gap in the actual state. @@ -625,7 +623,6 @@ bool QDockWidgetGroupWindow::hover(QLayoutItem *widgetItem, const QPoint &mouseP layoutInfo()->apply(opts & QMainWindow::AnimatedDocks); return true; } -QT_WARNING_POP void QDockWidgetGroupWindow::updateCurrentGapRect() { diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp index 1ca6b8a47a1..7aff0da3327 100644 --- a/src/widgets/widgets/qmdisubwindow.cpp +++ b/src/widgets/widgets/qmdisubwindow.cpp @@ -2220,7 +2220,7 @@ QMdiSubWindow::QMdiSubWindow(QWidget *parent, Qt::WindowFlags flags) d->titleBarPalette = d->desktopPalette(); d->font = QApplication::font("QMdiSubWindowTitleBar"); // We don't want the menu icon by default on mac. -#ifndef Q_OS_MAC +#ifndef Q_OS_DARWIN if (windowIcon().isNull()) d->menuIcon = style()->standardIcon(QStyle::SP_TitleBarMenuButton, nullptr, this); else @@ -2847,8 +2847,11 @@ bool QMdiSubWindow::event(QEvent *event) break; case QEvent::WindowIconChange: d->menuIcon = windowIcon(); + // We don't want the default menu icon on mac. +#ifndef Q_OS_DARWIN if (d->menuIcon.isNull()) d->menuIcon = style()->standardIcon(QStyle::SP_TitleBarMenuButton, nullptr, this); +#endif if (d->controlContainer) d->controlContainer->updateWindowIcon(d->menuIcon); if (!maximizedSystemMenuIconWidget()) diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 3177ed5c2d4..92ff14dd44f 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -771,7 +771,8 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason #endif hideMenu(hideActiveMenu); } else if (!currentAction || !currentAction->menu()) { - sloppyState.startTimerIfNotRunning(); + if (reason != SelectionReason::SelectedFromAPI) + sloppyState.startTimerIfNotRunning(); } } } @@ -2172,7 +2173,7 @@ void QMenu::hideTearOffMenu() void QMenu::setActiveAction(QAction *act) { Q_D(QMenu); - d->setCurrentAction(act, 0); + d->setCurrentAction(act, 0, QMenuPrivate::SelectionReason::SelectedFromAPI); if (d->scroll && act) d->scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollCenter); } @@ -2971,7 +2972,7 @@ void QMenu::mouseReleaseEvent(QMouseEvent *e) #endif d->activateAction(action, QAction::Trigger); } - } else if ((!action || action->isEnabled()) && !action->isSeparator()) { + } else if (!action || (action->isEnabled() && !action->isSeparator())) { d->hideUpToMenuBar(); } } diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index dd1f058a288..d9dcd7d0362 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -362,7 +362,8 @@ public: } delayState; enum SelectionReason { SelectedFromKeyboard, - SelectedFromElsewhere + SelectedFromAPI, + SelectedFromElsewhere, }; enum class SelectionDirection { Up, |
