diff options
22 files changed, 400 insertions, 588 deletions
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 e44d9b1468b..4a3ed3ee110 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -3408,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/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/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..849d0461b3f 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); 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/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/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp b/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp index 593cae6ddfc..29b78415924 100644 --- a/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp +++ b/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp @@ -92,8 +92,8 @@ private slots: void uncPaths(); #endif #ifndef Q_OS_WIN - void hiddenFiles(); - void hiddenDirs(); + void hidden_data(); + void hidden(); #endif void withStdAlgorithms(); @@ -871,45 +871,46 @@ void tst_QDirListing::uncPaths() // anything starting by a '.' is a hidden file. // For that reason these two tests aren't run on Windows. -void tst_QDirListing::hiddenFiles() +void tst_QDirListing::hidden_data() { - QStringList expected = { + QTest::addColumn<QDirListing::IteratorFlags>("flags"); + QTest::addColumn<QStringList>("expected"); + + using F = QDirListing::IteratorFlag; + + QTest::newRow("Recursive-ExcludeDirs") + << (F::ExcludeDirs | F::IncludeHidden | F::Recursive) + << QStringList{ "hiddenDirs_hiddenFiles/.hiddenDirectory/.hiddenFile"_L1, "hiddenDirs_hiddenFiles/.hiddenDirectory/normalFile"_L1, "hiddenDirs_hiddenFiles/.hiddenFile"_L1, "hiddenDirs_hiddenFiles/normalDirectory/.hiddenFile"_L1, "hiddenDirs_hiddenFiles/normalDirectory/normalFile"_L1, "hiddenDirs_hiddenFiles/normalFile"_L1, - }; - - constexpr auto flags = ItFlag::ExcludeDirs | ItFlag::IncludeHidden | ItFlag::Recursive; - QStringList list; - list.reserve(expected.size()); - for (const auto &dirEntry : QDirListing(u"hiddenDirs_hiddenFiles"_s, flags)) { - QVERIFY(dirEntry.isFile()); - list.emplace_back(dirEntry.filePath()); - } - list.sort(); - - QCOMPARE_EQ(list, expected); -} + }; -void tst_QDirListing::hiddenDirs() -{ - QStringList expected = { + QTest::newRow("Recursive-ExcludeFiles") + << (F::ExcludeFiles | F::IncludeHidden | F::Recursive) + << QStringList{ "hiddenDirs_hiddenFiles/.hiddenDirectory"_L1, "hiddenDirs_hiddenFiles/.hiddenDirectory/.hidden-subdir"_L1, "hiddenDirs_hiddenFiles/.hiddenDirectory/subdir"_L1, "hiddenDirs_hiddenFiles/normalDirectory"_L1, "hiddenDirs_hiddenFiles/normalDirectory/.hidden-subdir"_L1, "hiddenDirs_hiddenFiles/normalDirectory/subdir"_L1, - }; + }; +} + +void tst_QDirListing::hidden() +{ + QFETCH(QDirListing::IteratorFlags, flags); + QFETCH(QStringList, expected); - constexpr auto flags = ItFlag::ExcludeFiles | ItFlag::IncludeHidden | ItFlag::Recursive; QStringList list; list.reserve(expected.size()); + bool isDir = flags.testFlags(ItFlag::ExcludeFiles); for (const auto &dirEntry : QDirListing(u"hiddenDirs_hiddenFiles"_s, flags)) { - QVERIFY(dirEntry.isDir()); + QVERIFY(isDir ? dirEntry.isDir() : dirEntry.isFile()); list.emplace_back(dirEntry.filePath()); } list.sort(); diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp index 2e0d8dd7be2..dbaf6873af2 100644 --- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp +++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp @@ -3595,7 +3595,7 @@ void tst_QtJson::bom() QCOMPARE(error.error, QJsonParseError::NoError); } -void tst_QtJson::nesting() +static void nesting_test() { // check that we abort parsing too deeply nested json documents. // this is to make sure we don't crash because the parser exhausts the @@ -3654,6 +3654,26 @@ void tst_QtJson::nesting() } +void tst_QtJson::nesting() +{ +#if defined(Q_OS_QNX) || defined(Q_OS_VXWORKS) || defined(Q_OS_WASM) + // This test misbehaving probably indicates a stack overflow due to the + // recursive parser in qjsonparser.cpp. The recursion prevention limit may + // be too high for this platform. Someone should investigate. + QSKIP("Test freezes or crashes - probably a stack overflow"); +#endif + + QThread *thr = QThread::create(nesting_test); +#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) || \ + defined(__SANITIZE_THREAD__) || __has_feature(thread_sanitizer) + // force a larger stack size - 8 MB seems sufficient + thr->setStackSize(8192 * 1024); +#endif + thr->start(); + thr->wait(); + delete thr; +} + void tst_QtJson::longStrings() { // test around 15 and 16 bit boundaries, as these are limits diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp index bd9e00fc376..7b4193e3749 100644 --- a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp +++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp @@ -86,6 +86,9 @@ private slots: void intersectionPointOnEdge(); void boundsAtStartPoint(); + + void percentAtEmptyPath_data(); + void percentAtEmptyPath(); }; void tst_QPainterPath::cleanupTestCase() @@ -1637,6 +1640,29 @@ void tst_QPainterPath::boundsAtStartPoint() QCOMPARE(constructedPath.controlPointRect(), defaultPath.controlPointRect()); } +void tst_QPainterPath::percentAtEmptyPath_data() +{ + const QPointF qpf(2., 2.); + QTest::addColumn<QPainterPath>("path"); + + QTest::newRow("defaultConstructed") << QPainterPath(); + QTest::newRow("withStartPoint") << QPainterPath(qpf); + QPainterPath pp(qpf); + pp.lineTo(qpf); + QTest::newRow("equalPoints") << pp; +} + +void tst_QPainterPath::percentAtEmptyPath() +{ + QFETCH(QPainterPath, path); + + path.angleAtPercent(0.5); + path.pointAtPercent(0.5); + path.slopeAtPercent(0.5); + + path.percentAtLength(0); +} + QTEST_APPLESS_MAIN(tst_QPainterPath) #include "tst_qpainterpath.moc" diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 4814206cd75..40292f0c44d 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -132,6 +132,7 @@ private: bool m_skipUnsupportedIPv6Tests; bool m_workaroundLinuxKernelBug; + int loopbackInterface = 0; // unknown by default QList<QHostAddress> allAddresses; QHostAddress multicastGroup4, multicastGroup6; QList<QHostAddress> linklocalMulticastGroups; @@ -140,6 +141,16 @@ private: QUdpSocket *m_asyncReceiver; }; +// Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of obtaining +// the packet's destination addresses. This means the destinationAddress() be +// empty, so whitelist the OSes for which we know we have an implementation. +// That's currently all of them, which means there probably is code in this +// test that assumes this works without checking this variable. +// +// Note: this applies to single-stack operations; dual stack implementations +// appear to be buggy or not present at all in some OSes. +static constexpr bool HasWorkingIPv4DestinationAddress = true; + #ifdef SHOULD_CHECK_SYSCALL_SUPPORT bool tst_QUdpSocket::ipv6SetsockoptionMissing(int level, int optname) { @@ -246,7 +257,23 @@ void tst_QUdpSocket::initTestCase() if (!QtNetworkSettings::verifyTestNetworkSettings()) QSKIP("No network test server available"); #endif - allAddresses = QNetworkInterface::allAddresses(); + + allAddresses.clear(); + for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) { + if (!iface.flags().testAnyFlags(QNetworkInterface::IsUp)) + continue; + if (iface.flags().testAnyFlags(QNetworkInterface::IsLoopBack)) + loopbackInterface = iface.index(); + + // add this interface's addresses + const QList<QNetworkAddressEntry> addresses = iface.addressEntries(); + for (const QNetworkAddressEntry &entry : addresses) { + allAddresses += entry.ip(); + if (!loopbackInterface && entry.ip().isLoopback()) + loopbackInterface = iface.index(); + } + } + m_skipUnsupportedIPv6Tests = shouldSkipIpv6TestsForBrokenSetsockopt(); // Create a pair of random multicast groups so we avoid clashing with any @@ -568,12 +595,12 @@ void tst_QUdpSocket::broadcasting() QVERIFY2(allAddresses.contains(dgram.senderAddress()), dgram.senderAddress().toString().toLatin1()); QCOMPARE(dgram.senderPort(), int(broadcastSocket.localPort())); - if (!dgram.destinationAddress().isNull()) { + if (HasWorkingIPv4DestinationAddress) { QVERIFY2(dgram.destinationAddress() == QHostAddress::Broadcast || broadcastAddresses.contains(dgram.destinationAddress()), dgram.destinationAddress().toString().toLatin1()); - QCOMPARE(dgram.destinationPort(), int(serverSocket.localPort())); } + QCOMPARE(dgram.destinationPort(), int(serverSocket.localPort())); int ttl = dgram.hopLimit(); if (ttl != -1) @@ -738,15 +765,7 @@ void tst_QUdpSocket::loop() QCOMPARE(paulDatagram.senderPort(), int(peter.localPort())); QCOMPARE(peterDatagram.senderPort(), int(paul.localPort())); - // Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of - // obtaining the packet's destination addresses. The destinationAddress and - // destinationPort calls could fail, so whitelist the OSes for which we - // know we have an implementation. -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN) - QVERIFY(peterDatagram.destinationPort() != -1); - QVERIFY(paulDatagram.destinationPort() != -1); -#endif - if (peterDatagram.destinationPort() == -1) { + if (!HasWorkingIPv4DestinationAddress) { QCOMPARE(peterDatagram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol); QCOMPARE(paulDatagram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol); } else { @@ -754,6 +773,11 @@ void tst_QUdpSocket::loop() QCOMPARE(paulDatagram.destinationAddress(), makeNonAny(paul.localAddress())); QVERIFY(peterDatagram.destinationAddress().isEqual(makeNonAny(peter.localAddress()))); QVERIFY(paulDatagram.destinationAddress().isEqual(makeNonAny(paul.localAddress()))); + + if (loopbackInterface) { + QCOMPARE(peterDatagram.interfaceIndex(), loopbackInterface); + QCOMPARE(paulDatagram.interfaceIndex(), loopbackInterface); + } } } @@ -820,6 +844,11 @@ void tst_QUdpSocket::ipv6Loop() QCOMPARE(paulDatagram.destinationAddress(), makeNonAny(paul.localAddress())); QCOMPARE(peterDatagram.destinationPort(), peterPort); QCOMPARE(paulDatagram.destinationPort(), paulPort); + + if (loopbackInterface) { + QCOMPARE(peterDatagram.interfaceIndex(), loopbackInterface); + QCOMPARE(paulDatagram.interfaceIndex(), loopbackInterface); + } } void tst_QUdpSocket::dualStack() @@ -850,6 +879,8 @@ void tst_QUdpSocket::dualStack() QCOMPARE(dgram.destinationPort(), int(dualSock.localPort())); QVERIFY(dgram.destinationAddress().isEqual(makeNonAny(dualSock.localAddress(), QHostAddress::LocalHost))); } else { + // Observed on QNX: the IPV6_PKTINFO ancillary data appears to be + // missing if the sender is IPv4. qInfo("Getting IPv4 destination address failed."); } @@ -889,12 +920,11 @@ void tst_QUdpSocket::dualStack() QCOMPARE(dgram.data(), dualData); QCOMPARE(dgram.senderPort(), int(dualSock.localPort())); QCOMPARE(dgram.senderAddress(), makeNonAny(dualSock.localAddress(), QHostAddress::LocalHost)); -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN) - QVERIFY(dgram.destinationPort() != -1); -#endif - if (dgram.destinationPort() != -1) { - QCOMPARE(dgram.destinationPort(), int(v4Sock.localPort())); + QCOMPARE(dgram.destinationPort(), int(v4Sock.localPort())); + if (HasWorkingIPv4DestinationAddress) { QCOMPARE(dgram.destinationAddress(), makeNonAny(v4Sock.localAddress(), QHostAddress::LocalHost)); + if (loopbackInterface) + QCOMPARE(dgram.interfaceIndex(), loopbackInterface); } } @@ -1748,10 +1778,10 @@ void tst_QUdpSocket::multicast() QVERIFY2(allAddresses.contains(dgram.senderAddress()), dgram.senderAddress().toString().toLatin1()); QCOMPARE(dgram.senderPort(), int(sender.localPort())); - if (!dgram.destinationAddress().isNull()) { + if (HasWorkingIPv4DestinationAddress) { QCOMPARE(dgram.destinationAddress(), groupAddress); - QCOMPARE(dgram.destinationPort(), int(receiver.localPort())); } + QCOMPARE(dgram.destinationPort(), int(receiver.localPort())); int ttl = dgram.hopLimit(); if (ttl != -1) @@ -1962,19 +1992,12 @@ void tst_QUdpSocket::linkLocalIPv4() QCOMPARE(dgram.data().size(), testData.size()); QCOMPARE(dgram.data(), testData); - // Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of - // obtaining the packet's destination addresses. The destinationAddress - // and destinationPort calls could fail, so whitelist the OSes we know - // we have an implementation. -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN) - QVERIFY(dgram.destinationPort() != -1); -#endif - if (dgram.destinationPort() == -1) { + if (!HasWorkingIPv4DestinationAddress) { QCOMPARE(dgram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol); } else { QCOMPARE(dgram.destinationAddress(), s->localAddress()); - QCOMPARE(dgram.destinationPort(), int(neutral.localPort())); } + QCOMPARE(dgram.destinationPort(), int(neutral.localPort())); QVERIFY(neutral.writeDatagram(dgram.makeReply(testData))); QVERIFY2(s->waitForReadyRead(10000), QtNetworkSettings::msgSocketError(*s).constData()); diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index 17acdea014e..2f0cbf78b25 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -25,6 +25,7 @@ #include <QtWidgets/qtablewidget.h> #include <QtGui/qevent.h> +#include <QtGui/qstylehints.h> #include <QtGui/private/qhighdpiscaling_p.h> #include <QtCore/qmimedata.h> @@ -3333,7 +3334,7 @@ void tst_QGraphicsProxyWidget::clickFocus() EventSpy proxySpy(proxy); EventSpy widgetSpy(proxy->widget()); - view.setFrameStyle(0); + view.setFrameStyle(QFrame::NoFrame); view.resize(300, 300); view.show(); QVERIFY(QTest::qWaitForWindowFocused(&view)); @@ -3469,10 +3470,12 @@ void tst_QGraphicsProxyWidget::QTBUG_6986_sendMouseEventToAlienWidget() auto *hoverButton = new HoverButton(background); hoverButton->setText("Second button"_L1); hoverButton->setGeometry(10, 10, 200, 50); + hoverButton->setAttribute(Qt::WA_Hover, true); scene.addWidget(background); auto *hideButton = new QPushButton("I'm a button with a very very long text"_L1); hideButton->setGeometry(10, 10, 400, 50); + hideButton->setAttribute(Qt::WA_Hover, true); QGraphicsProxyWidget *topButton = scene.addWidget(hideButton); connect(hideButton, &QPushButton::clicked, &scene, [&]() { topButton->hide(); }); topButton->setFocus(); @@ -3659,6 +3662,11 @@ public: return QWidget::event(event); } + void paintEvent(QPaintEvent *) override + { + QPainter p(this); + p.fillRect(rect(), Qt::green); + } }; #if QT_CONFIG(wheelevent) @@ -3676,6 +3684,11 @@ public: */ void tst_QGraphicsProxyWidget::wheelEventPropagation() { + qApp->styleHints()->setWheelScrollLines(3); + const auto guard = qScopeGuard([&]() { + qApp->styleHints()->setWheelScrollLines(-1); + }); + QGraphicsScene scene(0, 0, 600, 600); auto *label = new QLabel("Direct"_L1); @@ -3697,6 +3710,11 @@ void tst_QGraphicsProxyWidget::wheelEventPropagation() int wheelEventCount = 0; protected: + void paintEvent(QPaintEvent *) override + { + QPainter p(this); + p.fillRect(rect(), Qt::green); + } void wheelEvent(QWheelEvent *) override { ++wheelEventCount; @@ -3710,10 +3728,13 @@ void tst_QGraphicsProxyWidget::wheelEventPropagation() QGraphicsView view(&scene); view.setFixedHeight(200); + view.setFixedWidth(700); + view.setFrameStyle(QFrame::NoFrame); view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); QVERIFY(view.verticalScrollBar()->isVisible()); + QVERIFY(!view.horizontalScrollBar()->isVisible()); view.verticalScrollBar()->setValue(0); QSignalSpy scrollSpy(view.verticalScrollBar(), &QScrollBar::valueChanged); @@ -3729,6 +3750,8 @@ void tst_QGraphicsProxyWidget::wheelEventPropagation() phase); QCoreApplication::processEvents(); }; + auto vs = view.verticalScrollBar(); + vs->setSingleStep(9); // each wheel event: wheelScrollLines() * 9 = 27px qsizetype scrollCount = 0; // test non-kinetic events; they are not grabbed, and should scroll the view unless @@ -3816,6 +3839,7 @@ void tst_QGraphicsProxyWidget::forwardTouchEvent() QGraphicsView view(&scene); view.show(); + view.setFrameStyle(QFrame::NoFrame); QVERIFY(QTest::qWaitForWindowActive(&view)); EventSpy eventSpy(widget); @@ -3832,16 +3856,14 @@ void tst_QGraphicsProxyWidget::forwardTouchEvent() QTest::touchEvent(&view, device.get()).move(0, QPoint(16, 16), &view); QTest::touchEvent(&view, device.get()).release(0, QPoint(15, 15), &view); - QApplication::processEvents(); - - QCOMPARE(eventSpy.counts[QEvent::TouchBegin], 1); - QCOMPARE(eventSpy.counts[QEvent::TouchUpdate], 2); - QCOMPARE(eventSpy.counts[QEvent::TouchEnd], 1); + QTRY_COMPARE(eventSpy.counts[QEvent::TouchBegin], 1); + QTRY_COMPARE(eventSpy.counts[QEvent::TouchUpdate], 2); + QTRY_COMPARE(eventSpy.counts[QEvent::TouchEnd], 1); } void tst_QGraphicsProxyWidget::touchEventPropagation() { - QGraphicsScene scene(0, 0, 300, 200); + QGraphicsScene scene; auto *simpleWidget = new QWidget; simpleWidget->setObjectName("simpleWidget"); simpleWidget->setAttribute(Qt::WA_AcceptTouchEvents, true); @@ -3873,15 +3895,26 @@ void tst_QGraphicsProxyWidget::touchEventPropagation() vbox->addWidget(touchWidget2); QGraphicsProxyWidget *formProxy = scene.addWidget(formWidget); formProxy->setAcceptTouchEvents(true); - formProxy->setGeometry(QRectF(50, 50, 200, 160)); + const auto minSize = formWidget->minimumSize(); + formProxy->setGeometry(QRectF(50, 50, minSize.width(), minSize.height())); + + // topLeft must be 0/0 + const auto sceneRect = scene.sceneRect(); + scene.setSceneRect(QRectF(0, 0, sceneRect.width(), sceneRect.height())); QGraphicsView view(&scene); + // by setting NoFrame, view and view.viewport() have the same + // coordinate system + view.setFrameStyle(QFrame::NoFrame); + // make sure to not have scrollbars view.setFixedSize(scene.width(), scene.height()); view.verticalScrollBar()->setValue(0); view.horizontalScrollBar()->setValue(0); view.viewport()->setObjectName("GraphicsView's Viewport"); view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); + QVERIFY(!view.horizontalScrollBar()->isVisible()); + QVERIFY(!view.verticalScrollBar()->isVisible()); class TouchEventSpy : public QObject { @@ -3913,8 +3946,12 @@ void tst_QGraphicsProxyWidget::touchEventPropagation() case QEvent::TouchEnd: { auto *touchEvent = static_cast<QTouchEvent *>(event); // instead of detaching each QEventPoint, just store the relative positions - for (const auto &touchPoint : touchEvent->points()) - records[touchPoint.id()] << TouchRecord{receiver, event->type(), touchPoint.position()}; + for (const auto& touchPoint : touchEvent->points()) { + records[touchPoint.id()] + << TouchRecord{ receiver, event->type(), touchPoint.position() }; + qCDebug(lcTests) << touchPoint.id() << "recv:" << receiver << "type" + << event->type() << "pos" << touchPoint.position(); + } qCDebug(lcTests) << "Recording" << event << receiver; break; } @@ -3944,9 +3981,9 @@ void tst_QGraphicsProxyWidget::touchEventPropagation() }; // verify that the embedded widget gets the correctly translated event - QTest::touchEvent(&view, touchDevice.get()).press(0, simpleCenter.toPoint()); + QTest::touchEvent(&view, touchDevice.get()).press(0, view.mapFromScene(simpleCenter)); // window, viewport, scene, simpleProxy, simpleWidget - QCOMPARE(eventSpy.count(), 5); + QTRY_COMPARE(eventSpy.count(), 5); QCOMPARE(eventSpy.at(0).receiver, view.windowHandle()); QCOMPARE(eventSpy.at(1).receiver, view.viewport()); QCOMPARE(eventSpy.at(2).receiver, &scene); @@ -3969,7 +4006,7 @@ void tst_QGraphicsProxyWidget::touchEventPropagation() QCOMPARE(formWidget->childAt(touchWidget2->pos() + tw2Center), touchWidget2); // touch events are sent to the view, in view coordinates - const QPoint formProxyPox = view.mapFromScene(formProxy->pos().toPoint()); + const QPoint formProxyPox = view.mapFromScene(formProxy->pos()); const QPoint pb1TouchPos = pushButton1->pos() + pb1Center + formProxyPox; const QPoint pb2TouchPos = pushButton2->pos() + pb2Center + formProxyPox; const QPoint tw1TouchPos = touchWidget1->pos() + tw1Center + formProxyPox; diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index df19ea1568e..48310996c46 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -2058,28 +2058,21 @@ void tst_QGraphicsView::mapFromSceneRect() QWidget topLevel; QGraphicsView view(&scene,&topLevel); view.rotate(90); - view.setFixedSize(200, 200); - view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + const auto fw = view.frameWidth() * 2; + view.setFixedSize(200 + fw, 200 + fw); topLevel.show(); - QVERIFY(QTest::qWaitForWindowActive(&view)); + QVERIFY(QTest::qWaitForWindowActive(&topLevel)); + QVERIFY(!view.horizontalScrollBar()->isVisible()); + QVERIFY(!view.verticalScrollBar()->isVisible()); - QPolygon polygon; - polygon << QPoint(98, 98); - polygon << QPoint(98, 108); - polygon << QPoint(88, 108); - polygon << QPoint(88, 98); - - - QPolygon viewPolygon = view.mapFromScene(0, 0, 10, 10); - for (int i = 0; i < 4; ++i) { - QVERIFY(qAbs(viewPolygon[i].x() - polygon[i].x()) < 3); - QVERIFY(qAbs(viewPolygon[i].y() - polygon[i].y()) < 3); - } + const QRectF input(0, 0, 10, 10); + // fixed size is 200x200 so center is 100x100 + const QPolygon polygon{ QPoint(100, 100), QPoint(100, 110), QPoint(90, 110), QPoint(90, 100) }; + const QPolygon viewPolygon = view.mapFromScene(input); + QCOMPARE(viewPolygon, polygon); QPoint pt = view.mapFromScene(QPointF()); - QPolygon p; - p << pt << pt << pt << pt; + QPolygon p{ pt, pt, pt, pt }; QCOMPARE(view.mapFromScene(QRectF()), p); } @@ -2088,28 +2081,18 @@ void tst_QGraphicsView::mapFromScenePoly() QGraphicsScene scene; QGraphicsView view(&scene); view.rotate(90); - view.setFixedSize(200, 200); - view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + const auto fw = view.frameWidth() * 2; + view.setFixedSize(200 + fw, 200 + fw); view.show(); - - QPolygonF polygon; - polygon << QPoint(0, 0); - polygon << QPoint(10, 0); - polygon << QPoint(10, 10); - polygon << QPoint(0, 10); - - QPolygon polygon2; - polygon2 << QPoint(98, 98); - polygon2 << QPoint(98, 108); - polygon2 << QPoint(88, 108); - polygon2 << QPoint(88, 98); - - QPolygon viewPolygon = view.mapFromScene(polygon); - for (int i = 0; i < 4; ++i) { - QVERIFY(qAbs(viewPolygon[i].x() - polygon2[i].x()) < 3); - QVERIFY(qAbs(viewPolygon[i].y() - polygon2[i].y()) < 3); - } + QVERIFY(QTest::qWaitForWindowActive(&view)); + QVERIFY(!view.horizontalScrollBar()->isVisible()); + QVERIFY(!view.verticalScrollBar()->isVisible()); + + const QPolygonF input{ QPoint(0, 0), QPoint(10, 0), QPoint(10, 10), QPoint(0, 10) }; + // fixed size is 200x200 so center is 100x100 + const QPolygon polygon{ QPoint(100, 100), QPoint(100, 110), QPoint(90, 110), QPoint(90, 100) }; + const QPolygon viewPolygon = view.mapFromScene(input); + QCOMPARE(viewPolygon, polygon); } void tst_QGraphicsView::mapFromScenePath() @@ -2117,34 +2100,22 @@ void tst_QGraphicsView::mapFromScenePath() QGraphicsScene scene; QGraphicsView view(&scene); view.rotate(90); - view.setFixedSize(200, 200); - view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + const auto fw = view.frameWidth() * 2; + view.setFixedSize(200 + fw, 200 + fw); view.show(); - - QPolygonF polygon; - polygon << QPoint(0, 0); - polygon << QPoint(10, 0); - polygon << QPoint(10, 10); - polygon << QPoint(0, 10); + QVERIFY(QTest::qWaitForWindowActive(&view)); + QVERIFY(!view.horizontalScrollBar()->isVisible()); + QVERIFY(!view.verticalScrollBar()->isVisible()); + + const QPolygonF input{ QPoint(0, 0), QPoint(10, 0), QPoint(10, 10), QPoint(0, 10) }; + QPainterPath inputPath; + inputPath.addPolygon(input); + // fixed size is 200x200 so center is 100x100 + const QPolygon polygon{ QPoint(100, 100), QPoint(100, 110), QPoint(90, 110), QPoint(90, 100) }; QPainterPath path; path.addPolygon(polygon); - - QPolygon polygon2; - polygon2 << QPoint(98, 98); - polygon2 << QPoint(98, 108); - polygon2 << QPoint(88, 108); - polygon2 << QPoint(88, 98); - QPainterPath path2; - path2.addPolygon(polygon2); - - QPolygonF pathPoly = view.mapFromScene(path).toFillPolygon(); - QPolygonF path2Poly = path2.toFillPolygon(); - - for (int i = 0; i < pathPoly.size(); ++i) { - QVERIFY(qAbs(pathPoly[i].x() - path2Poly[i].x()) < 3); - QVERIFY(qAbs(pathPoly[i].y() - path2Poly[i].y()) < 3); - } + QPainterPath viewPath = view.mapFromScene(inputPath); + QCOMPARE(viewPath, path); } void tst_QGraphicsView::sendEvent() |