From f4889e63c7b7629f9c25f42ba6c8b7852b91366f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 16 Apr 2020 18:27:08 +0200 Subject: macOS: Rework worksWhenModal and update on modal session change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of basing the worksWhenModal property on the window type, which will include both windows inside the current modal session (as intend), but also windows below the current modal session (wrongly), we check to see if the window is a transient child of the current top level modal window. Going via NSApp.modalWindow means we also catch cases where the top level modal session is run by a native window, not part of the modal session stack in the Cocoa event dispatcher. The new logic relies on windows such as popups, dialogs, etc to set the correct transient parent, but this seems to be the case already. To ensure the window tag is also updated, we call setWorksWhenModal on modal session changes. We could change worksWhenModal into e.g. shouldWorkWhenModal and always use the setter, but that would mean the initial window tag update in [NSWindow _commonAwake] would pick up the incorrect value. And if the window tag is not updated after that due to the workaround in [QNSPanel setWorksWhenModal:] being compiled out, the window would not be possible to order front, which is worse than being able to order front a window with worksWhenModal=NO. Fixes: QTBUG-76654 Task-number: QTBUG-71480 Change-Id: I38b14422d274dcc03b4c7d5ef87066e282ed9111 Reviewed-by: Timur Pocheptsov Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoawindowmanager.mm | 12 ++++ src/plugins/platforms/cocoa/qnswindow.mm | 82 +++++++++++++++++++--- 2 files changed, 83 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindowmanager.mm b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm index 9c45d8c7fc..5e218157c2 100644 --- a/src/plugins/platforms/cocoa/qcocoawindowmanager.mm +++ b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm @@ -100,6 +100,18 @@ void QCocoaWindowManager::modalSessionChanged() } } } + + // Our worksWhenModal implementation is declarative and will normally be picked + // up by AppKit when needed, but to make sure AppKit also reflects the state + // in the window tag, so that the window can be ordered front by clicking it, + // we need to explicitly call setWorksWhenModal. + for (id window in NSApp.windows) { + if ([window isKindOfClass:[QNSPanel class]]) { + auto *panel = static_cast(window); + // Call setter to tell AppKit that our state has changed + [panel setWorksWhenModal:panel.worksWhenModal]; + } + } } static void initializeWindowManager() { Q_UNUSED(QCocoaWindowManager::instance()); } diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm index 6b4e110af2..311c291252 100644 --- a/src/plugins/platforms/cocoa/qnswindow.mm +++ b/src/plugins/platforms/cocoa/qnswindow.mm @@ -158,7 +158,78 @@ static bool isMouseEvent(NSEvent *ev) #define QNSWINDOW_PROTOCOL_IMPLMENTATION 1 #include "qnswindow.mm" #undef QNSWINDOW_PROTOCOL_IMPLMENTATION + +- (BOOL)worksWhenModal +{ + if (!m_platformWindow) + return NO; + + // Conceptually there are two sets of windows we need consider: + // + // - windows 'lower' in the modal session stack + // - windows 'within' the current modal session + // + // The first set of windows should always be blocked by the current + // modal session, regardless of window type. The latter set may contain + // windows with a transient parent, which from Qt's point of view makes + // them 'child' windows, so we treat them as operable within the current + // modal session. + + if (!NSApp.modalWindow) + return NO; + + // If the current modal window (top level modal session) is not a Qt window we + // have no way of knowing if this window is transient child of the modal window. + if (![NSApp.modalWindow conformsToProtocol:@protocol(QNSWindowProtocol)]) + return NO; + + if (auto *modalWindow = static_cast(NSApp.modalWindow).platformWindow) { + if (modalWindow->window()->isAncestorOf(m_platformWindow->window(), QWindow::IncludeTransients)) + return YES; + } + + return NO; +} +@end + +#if !defined(QT_APPLE_NO_PRIVATE_APIS) +// When creating an NSWindow the worksWhenModal function is queried, +// and the resulting state is used to set the corresponding window tag, +// which the window server uses to determine whether or not the window +// should be allowed to activate via mouse clicks in the title-bar. +// Unfortunately, prior to macOS 10.15, this window tag was never +// updated after the initial assignment in [NSWindow _commonAwake], +// which meant that windows that dynamically change their worksWhenModal +// state will behave as if they were never allowed to work when modal. +// We work around this by manually updating the window tag when needed. + +typedef uint32_t CGSConnectionID; +typedef uint32_t CGSWindowID; + +extern "C" { +CGSConnectionID CGSMainConnectionID() __attribute__((weak_import)); +OSStatus CGSSetWindowTags(const CGSConnectionID, const CGSWindowID, int *, int) __attribute__((weak_import)); +OSStatus CGSClearWindowTags(const CGSConnectionID, const CGSWindowID, int *, int) __attribute__((weak_import)); +} + +@interface QNSPanel (WorksWhenModalWindowTagWorkaround) @end +@implementation QNSPanel (WorksWhenModalWindowTagWorkaround) +- (void)setWorksWhenModal:(BOOL)worksWhenModal +{ + [super setWorksWhenModal:worksWhenModal]; + + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSCatalina) { + if (CGSMainConnectionID && CGSSetWindowTags && CGSClearWindowTags) { + static int kWorksWhenModalWindowTag = 0x40; + auto *function = worksWhenModal ? CGSSetWindowTags : CGSClearWindowTags; + function(CGSMainConnectionID(), self.windowNumber, &kWorksWhenModalWindowTag, 64); + } else { + qWarning() << "Missing APIs for window tag handling, can not update worksWhenModal state"; + } + } +} @end +#endif // QT_APPLE_NO_PRIVATE_APIS #else // QNSWINDOW_PROTOCOL_IMPLMENTATION @@ -237,17 +308,6 @@ static bool isMouseEvent(NSEvent *ev) return canBecomeMain; } -- (BOOL)worksWhenModal -{ - if (m_platformWindow && [self isKindOfClass:[QNSPanel class]]) { - Qt::WindowType type = m_platformWindow->window()->type(); - if (type == Qt::Popup || type == Qt::Dialog || type == Qt::Tool) - return YES; - } - - return [super worksWhenModal]; -} - - (BOOL)isOpaque { return m_platformWindow ? m_platformWindow->isOpaque() : [super isOpaque]; -- cgit v1.2.3 From d04c9e23ff11da35f0c5784d85133cd6c65a7741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 13 Feb 2019 13:57:31 +0100 Subject: macOS: Activate non-modal windows during modal session if they support it Commit 593ab638609e ensured that non-modal windows would not be activated during a modal session, which makes sense for windows that can't be interacted with. But some windows can, and we should activate them as normal. Task-number: QTBUG-46304 Change-Id: I4a9b7ec53157b042d4d6e9535336fa3254f41e0e Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoawindow.mm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 79dfe58a4e..5ddbfe4377 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -376,8 +376,11 @@ void QCocoaWindow::setVisible(bool visible) } else if (window()->modality() == Qt::ApplicationModal) { // Show the window as application modal eventDispatcher()->beginModalSession(window()); - } else if (m_view.window.canBecomeKeyWindow && !eventDispatcher()->hasModalSession()) { - [m_view.window makeKeyAndOrderFront:nil]; + } else if (m_view.window.canBecomeKeyWindow) { + if (!NSApp.modalWindow || m_view.window.worksWhenModal) + [m_view.window makeKeyAndOrderFront:nil]; + else + [m_view.window orderFront:nil]; } else { [m_view.window orderFront:nil]; } -- cgit v1.2.3 From a962bbec0789f05ba6f1ea50c8656eeb5ac3ab00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 13 Feb 2019 14:00:57 +0100 Subject: macOS: Support [NSPanel becomesKeyOnlyIfNeeded] We don't set this flag ourselves, but clients may do via winId(). If set, the panel will only activate if a view with needsPanelToBecomeKey is clicked. We do not implement needsPanelToBecomeKey in QNSView, which we ideally should, by e.g. looking at the IME hints. This still works as expected, as QtWidgets will make sure to activate the window as part of the normal focus handling. For other use-cases the user will have to catch the mouse event and activate the window manually. Change-Id: I4bacdd44b2f7df5920c6334806303bb5eb502b48 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoawindow.mm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 5ddbfe4377..2cbe1b8684 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -377,7 +377,14 @@ void QCocoaWindow::setVisible(bool visible) // Show the window as application modal eventDispatcher()->beginModalSession(window()); } else if (m_view.window.canBecomeKeyWindow) { - if (!NSApp.modalWindow || m_view.window.worksWhenModal) + bool shouldBecomeKeyNow = !NSApp.modalWindow || m_view.window.worksWhenModal; + + // Panels with becomesKeyOnlyIfNeeded set should not activate until a view + // with needsPanelToBecomeKey, for example a line edit, is clicked. + if ([m_view.window isKindOfClass:[NSPanel class]]) + shouldBecomeKeyNow &= !(static_cast(m_view.window).becomesKeyOnlyIfNeeded); + + if (shouldBecomeKeyNow) [m_view.window makeKeyAndOrderFront:nil]; else [m_view.window orderFront:nil]; -- cgit v1.2.3 From cd41b01f32104a484db53e8a1ea913d596c939c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 17 Apr 2020 17:04:33 +0200 Subject: macOS: Don't produce NSImages without a single representation Doing so results in exceptions inside AppKit when passed on to APIs that expect valid images. It's better to produce nil-images. Fixes: QTBUG-83494 Change-Id: I1e5bfa2a7fecd75a1ddb95bd1a6dc2e8db6b24f8 Reviewed-by: Volker Hilsheimer --- src/gui/painting/qcoregraphics.mm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm index 94ba004c93..7fb075d19e 100644 --- a/src/gui/painting/qcoregraphics.mm +++ b/src/gui/painting/qcoregraphics.mm @@ -162,12 +162,12 @@ QT_END_NAMESPACE if (icon.isNull()) return nil; - auto nsImage = [[NSImage alloc] initWithSize:NSZeroSize]; - auto availableSizes = icon.availableSizes(); if (availableSizes.isEmpty() && size > 0) availableSizes << QSize(size, size); + auto nsImage = [[[NSImage alloc] initWithSize:NSZeroSize] autorelease]; + for (QSize size : qAsConst(availableSizes)) { QImage image = icon.pixmap(size).toImage(); if (image.isNull()) @@ -182,12 +182,15 @@ QT_END_NAMESPACE [nsImage addRepresentation:[imageRep autorelease]]; } + if (!nsImage.representations.count) + return nil; + [nsImage setTemplate:icon.isMask()]; if (size) nsImage.size = CGSizeMake(size, size); - return [nsImage autorelease]; + return nsImage; } @end -- cgit v1.2.3 From 164110f7bbea7345de709edd092afa84fdde232c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 17 Apr 2020 17:02:46 +0200 Subject: Warn when trying to load an icon without a matching icon engine A typical case is trying to load an SVG icon without the QtSvg module built. You want to know what's going on instead of trying to debug why the icon doesn't produce any valid images. Change-Id: I4418ad758a1232f1394058368c50e0d87235271e Reviewed-by: Volker Hilsheimer --- src/gui/image/qicon.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 41fe649fc5..562e5e9a3e 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1049,6 +1049,8 @@ static QIconEngine *iconEngineFromSuffix(const QString &fileName, const QString } } } + qWarning("Could not find icon engine for suffix '%s' of file '%s'", + qUtf8Printable(suffix), qUtf8Printable(fileName)); return nullptr; } -- cgit v1.2.3 From 86f228b819aba71f0d6cd89303d8226d6567209b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 17 Apr 2020 17:08:21 +0200 Subject: macOS: Restore fallback sizes when setting application or window icons We removed this logic in 059c3ae66a under the assumption that the icon would always provide a set of sizes, but for SVG icons this is not the case. Change-Id: Ib3cc5740bca32cf4068a71baf99b52fa536da2ca Reviewed-by: Volker Hilsheimer Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 4 +++- src/plugins/platforms/cocoa/qcocoawindow.mm | 9 ++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 245db429c5..9b57b89529 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -472,7 +472,9 @@ QList *QCocoaIntegration::popupWindowStack() void QCocoaIntegration::setApplicationIcon(const QIcon &icon) const { - NSApp.applicationIconImage = [NSImage imageFromQIcon:icon]; + // Fall back to a size that looks good on the highest resolution screen available + auto fallbackSize = NSApp.dockTile.size.width * qGuiApp->devicePixelRatio(); + NSApp.applicationIconImage = [NSImage imageFromQIcon:icon withSize:fallbackSize]; } void QCocoaIntegration::beep() const diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 2cbe1b8684..069e9ce845 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -904,10 +904,13 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon) QMacAutoReleasePool pool; - if (icon.isNull()) + if (icon.isNull()) { iconButton.image = [NSWorkspace.sharedWorkspace iconForFile:m_view.window.representedFilename]; - else - iconButton.image = [NSImage imageFromQIcon:icon]; + } else { + // Fall back to a size that looks good on the highest resolution screen available + auto fallbackSize = iconButton.frame.size.height * qGuiApp->devicePixelRatio(); + iconButton.image = [NSImage imageFromQIcon:icon withSize:fallbackSize]; + } } void QCocoaWindow::setAlertState(bool enabled) -- cgit v1.2.3 From 864f18ba2f21a0eb1977acc53ebe733acdfc8d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 24 Mar 2020 09:39:06 +0100 Subject: widgets: Re-calculate focus frame style option after setting new geometry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: QTBUG-83019 Change-Id: I75d3d93732cb0c5a5b7350f19f0227998bda4791 Reviewed-by: Friedemann Kleint (cherry picked from commit bd78753d625c573eef587fc0b8e767cffb99c2bf) Reviewed-by: Tor Arne Vestbø --- src/widgets/widgets/qfocusframe.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/widgets/widgets/qfocusframe.cpp b/src/widgets/widgets/qfocusframe.cpp index 4e793d7a29..aa9de7c35f 100644 --- a/src/widgets/widgets/qfocusframe.cpp +++ b/src/widgets/widgets/qfocusframe.cpp @@ -99,6 +99,8 @@ void QFocusFramePrivate::updateSize() return; q->setGeometry(geom); + + opt.rect = q->rect(); QStyleHintReturnMask mask; if (q->style()->styleHint(QStyle::SH_FocusFrame_Mask, &opt, q, &mask)) q->setMask(mask.region); -- cgit v1.2.3 From fdea55cb9832a194b5ec1262e216f12ae644ba6b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 15 Apr 2020 18:52:49 -0300 Subject: QCborValue: fix double-accounting of the usedData when decoding strings We can only update usedData at the end, after we've decoded all chunks. The update inside the lambda was double-accounting for the first chunk, which could lead to signed integer overflows in usedData. Not unit-testable since the usedData value is not visible in the API. Change-Id: Ibdc95e9af7bd456a94ecfffd16061cc955208859 Reviewed-by: Ulf Hermann Reviewed-by: Edward Welbourne --- src/corelib/serialization/qcborvalue.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index c45a09ad99..90b45fb853 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -1561,8 +1561,6 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader) if (newSize > MaxByteArraySize) return -1; - // since usedData <= data.size(), this can't overflow - usedData += increment; data.resize(newSize); return offset; }; -- cgit v1.2.3 From c197615bd99ec76ebb3ca9aff959826b4e7ff43b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 15 Apr 2020 19:10:01 -0300 Subject: QCborValue: don't update internal states if decoding a string failed Change-Id: Ibdc95e9af7bd456a94ecfffd16061db982ad3fa7 Reviewed-by: Ulf Hermann Reviewed-by: Edward Welbourne --- src/corelib/serialization/qcborvalue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 90b45fb853..a3729b4ef9 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -1633,7 +1633,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader) } // update size - if (e.flags & Element::HasByteData) { + if (r.status == QCborStreamReader::EndOfString && e.flags & Element::HasByteData) { auto b = new (dataPtr() + e.value) ByteData; b->len = data.size() - e.value - int(sizeof(*b)); usedData += b->len; -- cgit v1.2.3 From 9802b93cc76de8a033a9806383c1631f36225931 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Mon, 20 Apr 2020 16:12:26 +0300 Subject: note QFileDialog::setNameFilters() is not supported on Android Task-number: QTBUG-83089 Change-Id: I134917476548f9756a14975be6b1b20312a8ca40 Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qfiledialog.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index bace311924..b406333fef 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -1370,6 +1370,9 @@ QStringList qt_make_filter_list(const QString &filter) \snippet code/src_gui_dialogs_qfiledialog.cpp 6 + \note This is not supported on Android's native file dialog. Use + \l{setMimeTypeFilters()} instead. + \sa setMimeTypeFilters(), setNameFilters() */ void QFileDialog::setNameFilter(const QString &filter) @@ -1441,6 +1444,9 @@ QStringList qt_strip_filters(const QStringList &filters) filters for each file type. For example, JPEG images have three possible extensions; if your application can open such files, selecting the \c image/jpeg mime type as a filter will allow you to open all of them. + + \note This is not supported on Android's native file dialog. Use + \l{setMimeTypeFilters()} instead. */ void QFileDialog::setNameFilters(const QStringList &filters) { -- cgit v1.2.3 From 10acfec765d2c947a180f52437b8df77dfc0658d Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 22 Apr 2020 09:06:31 +0200 Subject: Doc: Fix compilation issue with QVERIFY2 example Fixes error C2124: divide or mod by zero when compiling the test code (enabled by 713cd83200f3c60eac5d389dfabc44be1446e2ac). Pick-to: 5.15 Change-Id: I2ae39426fc0012f79714ff3d6484d792cab4bd92 Reviewed-by: Edward Welbourne --- src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp index eda0f430a1..cfa999a6f4 100644 --- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp +++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp @@ -84,7 +84,7 @@ class TestQString : public QObject void wrapInFunction() { //! [1] -QVERIFY2(qIsNaN(0.0 / 0.0), "Ill-defined division produced unambiguous result."); +QVERIFY2(QFileInfo("file.txt").exists(), "file.txt does not exist."); //! [1] //! [2] -- cgit v1.2.3 From 9e83d268d6e0bd492fafad823a47cef57b7916c5 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Wed, 22 Apr 2020 20:06:16 +0200 Subject: Fix data corruption regression in QJsonObject::erase() The internal removeAt(index) method was implemented as taking cbor indexes directly, in contrast to the other ...At(index) methods. Fixes: QTBUG-83695 Change-Id: I16597eb6db1cf71e1585c041caa81bf8f7a75303 Reviewed-by: Thiago Macieira --- src/corelib/serialization/qjsonobject.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp index 850e878571..36429662fc 100644 --- a/src/corelib/serialization/qjsonobject.cpp +++ b/src/corelib/serialization/qjsonobject.cpp @@ -577,7 +577,7 @@ void QJsonObject::removeImpl(T key) if (!keyExists) return; - removeAt(index); + removeAt(index / 2); } #if QT_STRINGVIEW_LEVEL < 2 @@ -629,7 +629,7 @@ QJsonValue QJsonObject::takeImpl(T key) return QJsonValue(QJsonValue::Undefined); const QJsonValue v = QJsonPrivate::Value::fromTrustedCbor(o->extractAt(index + 1)); - removeAt(index); + removeAt(index / 2); return v; } @@ -1486,8 +1486,8 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val) void QJsonObject::removeAt(int index) { detach2(); - o->removeAt(index + 1); - o->removeAt(index); + o->removeAt(2 * index + 1); + o->removeAt(2 * index); } uint qHash(const QJsonObject &object, uint seed) -- cgit v1.2.3 From 37bd3fbccd2d414b17d2b6cf14b2b976afc5810a Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 26 Mar 2020 12:34:55 +0100 Subject: Doc: Describe updating fonts with substitutes Fixes: QTBUG-82577 Change-Id: I40662240da69c0d93d0386172c10f375fbb5fefc Reviewed-by: Paul Wicking --- src/gui/text/qfont.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index bf130fa0b7..1b33693ed8 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -420,7 +420,9 @@ QFontEngineData::~QFontEngineData() be removed with removeSubstitutions(). Use substitute() to retrieve a family's first substitute, or the family name itself if it has no substitutes. Use substitutes() to retrieve a list of a family's - substitutes (which may be empty). + substitutes (which may be empty). After substituting a font, you must + trigger the updating of the font by destroying and re-creating all + QFont objects. Every QFont has a key() which you can use, for example, as the key in a cache or dictionary. If you want to store a user's font @@ -1864,6 +1866,9 @@ QStringList QFont::substitutes(const QString &familyName) Inserts \a substituteName into the substitution table for the family \a familyName. + After substituting a font, trigger the updating of the font by destroying + and re-creating all QFont objects. + \sa insertSubstitutions(), removeSubstitutions(), substitutions(), substitute(), substitutes() */ void QFont::insertSubstitution(const QString &familyName, @@ -1882,6 +1887,10 @@ void QFont::insertSubstitution(const QString &familyName, Inserts the list of families \a substituteNames into the substitution list for \a familyName. + After substituting a font, trigger the updating of the font by destroying + and re-creating all QFont objects. + + \sa insertSubstitution(), removeSubstitutions(), substitutions(), substitute() */ void QFont::insertSubstitutions(const QString &familyName, -- cgit v1.2.3 From 7c7b09dbac7d1921efb305cb7843b88a5247f17e Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 21 Apr 2020 10:20:28 +0200 Subject: Cocoa: If the grabRect is null then add in a null image for the area MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If it is null then it has nothing to grab, so a null QImage and QRect is added to the lists so that there is still a representation in some form for that display. This additionally ensures that it does take up space for the display in the final image too. Fixes: QTBUG-63086 Change-Id: I6e80ecc1170642025f6930e2211017c114e25c16 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoascreen.mm | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm index e4dd4cf6c6..6a3172fb19 100644 --- a/src/plugins/platforms/cocoa/qcocoascreen.mm +++ b/src/plugins/platforms/cocoa/qcocoascreen.mm @@ -614,7 +614,11 @@ QPixmap QCocoaScreen::grabWindow(WId view, int x, int y, int width, int height) QRect windowRect; for (uint i = 0; i < displayCount; ++i) { QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(displays[i])).toRect(); - windowRect = windowRect.united(displayBounds); + // Only include the screen if it is positioned past the x/y position + if ((displayBounds.x() >= x || displayBounds.right() > x) && + (displayBounds.y() >= y || displayBounds.bottom() > y)) { + windowRect = windowRect.united(displayBounds); + } } if (grabRect.width() < 0) grabRect.setWidth(windowRect.width()); @@ -631,6 +635,11 @@ QPixmap QCocoaScreen::grabWindow(WId view, int x, int y, int width, int height) auto display = displays[i]; QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(display)).toRect(); QRect grabBounds = displayBounds.intersected(grabRect); + if (grabBounds.isNull()) { + destinations.append(QRect()); + images.append(QImage()); + continue; + } QRect displayLocalGrabBounds = QRect(QPoint(grabBounds.topLeft() - displayBounds.topLeft()), grabBounds.size()); QImage displayImage = qt_mac_toQImage(QCFType(CGDisplayCreateImageForRect(display, displayLocalGrabBounds.toCGRect()))); displayImage.setDevicePixelRatio(displayImage.size().width() / displayLocalGrabBounds.size().width()); -- cgit v1.2.3 From 6fa50601ab7c55946eecc33453e7d694b5940d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 23 Apr 2020 11:04:58 +0200 Subject: Don't warn when loading icons via the image loaders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 9d5ae9f26c98 introduced a warning when a matching icon engine was not found for a given file suffix, under the assumption that all formats would go through icon engine plugins. Unfortunately QIcon itself falls back to a direct use of QPixmapIconEngine when no icon engine plugin is found, which would lead to the warning being emitted for built in formats such as PNG. Until this code can be moved properly into QPixmapIconEngine we'll remove it. Change-Id: I14d1d33a0f0c29e4b4604ef3b53c05cb8e02f867 Reviewed-by: Tor Arne Vestbø Reviewed-by: Simon Hausmann --- src/gui/image/qicon.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 562e5e9a3e..41fe649fc5 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1049,8 +1049,6 @@ static QIconEngine *iconEngineFromSuffix(const QString &fileName, const QString } } } - qWarning("Could not find icon engine for suffix '%s' of file '%s'", - qUtf8Printable(suffix), qUtf8Printable(fileName)); return nullptr; } -- cgit v1.2.3 From d433d0e089698bb2c3153360c583f5ad540a6566 Mon Sep 17 00:00:00 2001 From: Paul Wicking Date: Mon, 27 Apr 2020 07:31:46 +0200 Subject: Doc: add since for QWheelEvent::position Fixes: QTBUG-83779 Change-Id: Icd39c6e3b65e17a51d04ea3c0718f2957948aaa4 Reviewed-by: Nico Vertriest --- src/gui/kernel/qevent.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 466e70db30..68f2d0392f 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -951,6 +951,7 @@ QWheelEvent::~QWheelEvent() /*! \fn QPoint QWheelEvent::position() const + \since 5.14 Returns the position of the mouse cursor relative to the widget that received the event. -- cgit v1.2.3 From 41387bb330bb694f7e423f180bdbf88c7200985b Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 27 Apr 2020 10:58:39 +0200 Subject: Fix 8bit image conversions with non-default bytes_per_line Copy line by line when bytes per line doesn't match between input and output. Fixes: QTBUG-83777 Change-Id: I44ca75963df6188c1de76196d9c12fd8bb081688 Reviewed-by: Eirik Aavitsland --- src/gui/image/qimage_conversions.cpp | 44 +++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 34d2b8d8c7..506ebc797f 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -2016,6 +2016,21 @@ static void convert_Mono_to_Indexed8(QImageData *dest, const QImageData *src, Qt } } +static void copy_8bit_pixels(QImageData *dest, const QImageData *src) +{ + if (src->bytes_per_line == dest->bytes_per_line) { + memcpy(dest->data, src->data, src->bytes_per_line * src->height); + } else { + const uchar *sdata = src->data; + uchar *ddata = dest->data; + for (int y = 0; y < src->height; ++y) { + memcpy(ddata, sdata, src->width); + sdata += src->bytes_per_line; + ddata += dest->bytes_per_line; + } + } +} + static void convert_Indexed8_to_Alpha8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { Q_ASSERT(src->format == QImage::Format_Indexed8); @@ -2031,11 +2046,15 @@ static void convert_Indexed8_to_Alpha8(QImageData *dest, const QImageData *src, } if (simpleCase) - memcpy(dest->data, src->data, src->bytes_per_line * src->height); + copy_8bit_pixels(dest, src); else { - qsizetype size = src->bytes_per_line * src->height; - for (qsizetype i = 0; i < size; ++i) { - dest->data[i] = translate[src->data[i]]; + const uchar *sdata = src->data; + uchar *ddata = dest->data; + for (int y = 0; y < src->height; ++y) { + for (int x = 0; x < src->width; ++x) + ddata[x] = translate[sdata[x]]; + sdata += src->bytes_per_line; + ddata += dest->bytes_per_line; } } } @@ -2055,11 +2074,15 @@ static void convert_Indexed8_to_Grayscale8(QImageData *dest, const QImageData *s } if (simpleCase) - memcpy(dest->data, src->data, src->bytes_per_line * src->height); + copy_8bit_pixels(dest, src); else { - qsizetype size = src->bytes_per_line * src->height; - for (qsizetype i = 0; i < size; ++i) { - dest->data[i] = translate[src->data[i]]; + const uchar *sdata = src->data; + uchar *ddata = dest->data; + for (int y = 0; y < src->height; ++y) { + for (int x = 0; x < src->width; ++x) + ddata[x] = translate[sdata[x]]; + sdata += src->bytes_per_line; + ddata += dest->bytes_per_line; } } } @@ -2107,7 +2130,7 @@ static void convert_Alpha8_to_Indexed8(QImageData *dest, const QImageData *src, Q_ASSERT(src->format == QImage::Format_Alpha8); Q_ASSERT(dest->format == QImage::Format_Indexed8); - memcpy(dest->data, src->data, src->bytes_per_line * src->height); + copy_8bit_pixels(dest, src); dest->colortable = defaultColorTables->alpha; } @@ -2117,8 +2140,7 @@ static void convert_Grayscale8_to_Indexed8(QImageData *dest, const QImageData *s Q_ASSERT(src->format == QImage::Format_Grayscale8); Q_ASSERT(dest->format == QImage::Format_Indexed8); - memcpy(dest->data, src->data, src->bytes_per_line * src->height); - + copy_8bit_pixels(dest, src); dest->colortable = defaultColorTables->gray; } -- cgit v1.2.3 From a1f9729b740e410f818864588d4829275c4d5f52 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 7 Apr 2020 15:48:46 +0200 Subject: Fix 32bit int overflow Do not continue if the conversion to 32bit int would cause an overflow. Change-Id: I8a198dce5962e7ebd248b9baa92aba8730bfd3b0 Reviewed-by: Edward Welbourne --- src/network/ssl/qasn1element.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/network/ssl/qasn1element.cpp b/src/network/ssl/qasn1element.cpp index 6558643386..5634332a67 100644 --- a/src/network/ssl/qasn1element.cpp +++ b/src/network/ssl/qasn1element.cpp @@ -45,6 +45,7 @@ #include #include +#include #include QT_BEGIN_NAMESPACE @@ -120,7 +121,7 @@ bool QAsn1Element::read(QDataStream &stream) return false; // length - qint64 length = 0; + quint64 length = 0; quint8 first; stream >> first; if (first & 0x80) { @@ -139,11 +140,13 @@ bool QAsn1Element::read(QDataStream &stream) length = (first & 0x7f); } + if (length > quint64(std::numeric_limits::max())) + return false; // value QByteArray tmpValue; tmpValue.resize(length); int count = stream.readRawData(tmpValue.data(), tmpValue.size()); - if (count != length) + if (count != int(length)) return false; mType = tmpType; -- cgit v1.2.3 From c068edcecf6876c7b57abbe302ad8b1347e4445e Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 24 Apr 2020 10:17:05 +0200 Subject: Always open a submenu on the same screen where the parent menu is We've seen submenus opening on different screens in different scenarios, but probably there's never a sensible reason to do that. QWidgetPrivate::setScreenForPoint() can often give incorrect results in multi-screen desktop configurations; this is a way of avoiding that. Task-number: QTBUG-76162 Change-Id: I895696c6858ad953258c84b21117beea4c4fc01d Reviewed-by: Andy Shaw --- src/widgets/widgets/qmenu.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 865e3b2fb6..38fdbf2184 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -40,6 +40,7 @@ #include "qmenu.h" #include +#include #include "qdebug.h" #include "qstyle.h" @@ -2343,15 +2344,23 @@ void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction po // Use d->popupScreen to remember, because initialScreenIndex will be reset after the first showing. // However if eventLoop exists, then exec() already did this by calling createWinId(); so leave it alone. (QTBUG-76162) if (!eventLoop) { + bool screenSet = false; const int screenIndex = topData()->initialScreenIndex; if (screenIndex >= 0) popupScreen = screenIndex; if (auto s = QGuiApplication::screens().value(popupScreen)) { if (setScreen(s)) itemsDirty = true; - } else if (setScreenForPoint(p)) { - itemsDirty = true; + screenSet = true; + } else if (QMenu *parentMenu = qobject_cast(parent)) { + // a submenu is always opened from an open parent menu, + // so show it on the same screen where the parent is. (QTBUG-76162) + if (setScreen(QMenuPrivate::get(parentMenu)->windowHandle()->screen())) + itemsDirty = true; + screenSet = true; } + if (!screenSet && setScreenForPoint(p)) + itemsDirty = true; } const bool contextMenu = isContextMenu(); -- cgit v1.2.3 From 084525a034fa9306247eec2005fa9e8279753829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Thu, 16 Apr 2020 17:40:54 +0200 Subject: QNAM/QNetConMon: emit networkAccessibleChanged on changes For compatibility with the bearer functionality. Change-Id: I26ba6bad046b3f99c8ee13e709a26ddcbd868e25 Reviewed-by: Timur Pocheptsov --- src/network/access/qnetworkaccessmanager.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 6f6aa73f62..d36cb46ce1 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -2116,7 +2116,10 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) Q_Q(QNetworkAccessManager); if (statusMonitor.isEnabled()) { + auto previous = networkAccessible; networkAccessible = isOnline ? QNetworkAccessManager::Accessible : QNetworkAccessManager::NotAccessible; + if (previous != networkAccessible) + emit q->networkAccessibleChanged(networkAccessible); return; } -- cgit v1.2.3 From 562d7ded3b23f7aa92cbe4f3132bec0053ed7163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 28 Apr 2020 10:52:01 +0200 Subject: macOS: draw toolbar separator line in unfifed mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 836a2fb8 changed the contentBorderThickness property to also include the title bar height, in order to position sheets correctly when unified toolbar mode is enabled. As an accidental side effect this made Qt stop drawing the toolbar separator line. Account for the added title bar height also in testContentBorderAreaPosition(). Task-number: QTBUG-78110 Change-Id: I4ecfd010a6784bbb592646affc676d8cbfd9b6da Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoawindow.mm | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 79dfe58a4e..2cbdb3c873 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1815,8 +1815,17 @@ void QCocoaWindow::updateNSToolbar() bool QCocoaWindow::testContentBorderAreaPosition(int position) const { - return isContentView() && m_drawContentBorderGradient && - 0 <= position && position < [m_view.window contentBorderThicknessForEdge:NSMaxYEdge]; + if (!m_drawContentBorderGradient || !isContentView()) + return false; + + // Determine if the given y postion (relative to the content area) is inside the + // unified toolbar area. Note that the value returned by contentBorderThicknessForEdge + // includes the title bar height; subtract it. + const int contentBorderThickness = [m_view.window contentBorderThicknessForEdge:NSMaxYEdge]; + const NSRect frameRect = m_view.window.frame; + const NSRect contentRect = [m_view.window contentRectForFrameRect:frameRect]; + const CGFloat titlebarHeight = frameRect.size.height - contentRect.size.height; + return 0 <= position && position < (contentBorderThickness - titlebarHeight); } qreal QCocoaWindow::devicePixelRatio() const -- cgit v1.2.3 From e6a39c13bfe44719ee345419e98638e5f38fe7ee Mon Sep 17 00:00:00 2001 From: Paul Wicking Date: Thu, 23 Apr 2020 19:28:38 +0200 Subject: Doc: Remove manual duplicate alias descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the introduction of the \typealias command to QDoc, QDoc generates a standardized line for aliased types. This patch removes duplication caused by the change in QDoc. Change-Id: I1a01c378f85b0decb7c0400a3b21146f0898c6ec Reviewed-by: Topi Reiniö --- src/corelib/text/qstring.cpp | 32 -------------------------------- src/network/ssl/qdtls.cpp | 2 -- 2 files changed, 34 deletions(-) (limited to 'src') diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 210a8afc53..54a2f9cdd2 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -1803,57 +1803,39 @@ const QString::Null QString::null = { }; /*! \typedef QString::const_iterator - This typedef provides an STL-style const iterator for QString. - \sa QString::iterator */ /*! \typedef QString::iterator - The QString::iterator typedef provides an STL-style non-const - iterator for QString. - \sa QString::const_iterator */ /*! \typedef QString::const_reverse_iterator \since 5.6 - This typedef provides an STL-style const reverse iterator for QString. - \sa QString::reverse_iterator, QString::const_iterator */ /*! \typedef QString::reverse_iterator \since 5.6 - This typedef provides an STL-style non-const reverse iterator for QString. - \sa QString::const_reverse_iterator, QString::iterator */ /*! \typedef QString::size_type - - The QString::size_type typedef provides an STL-style type for sizes (int). */ /*! \typedef QString::difference_type - - The QString::size_type typedef provides an STL-style type for difference between pointers. */ /*! \typedef QString::const_reference - - This typedef provides an STL-style const reference for a QString element (QChar). */ /*! \typedef QString::reference - - This typedef provides an STL-style - reference for a QString element (QChar). */ /*! @@ -1871,8 +1853,6 @@ const QString::Null QString::null = { }; /*! \typedef QString::value_type - - This typedef provides an STL-style value type for QString. */ /*! \fn QString::iterator QString::begin() @@ -9537,8 +9517,6 @@ QString &QString::setRawData(const QChar *unicode, int size) \typedef QLatin1String::iterator \since 5.10 - This typedef provides an STL-style const iterator for QLatin1String. - QLatin1String does not support mutable iterators, so this is the same as const_iterator. @@ -9549,8 +9527,6 @@ QString &QString::setRawData(const QChar *unicode, int size) \typedef QLatin1String::const_iterator \since 5.10 - This typedef provides an STL-style const iterator for QLatin1String. - \sa iterator, const_reverse_iterator */ @@ -9558,8 +9534,6 @@ QString &QString::setRawData(const QChar *unicode, int size) \typedef QLatin1String::reverse_iterator \since 5.10 - This typedef provides an STL-style const reverse iterator for QLatin1String. - QLatin1String does not support mutable reverse iterators, so this is the same as const_reverse_iterator. @@ -9570,8 +9544,6 @@ QString &QString::setRawData(const QChar *unicode, int size) \typedef QLatin1String::const_reverse_iterator \since 5.10 - This typedef provides an STL-style const reverse iterator for QLatin1String. - \sa reverse_iterator, const_iterator */ @@ -10472,8 +10444,6 @@ QDataStream &operator>>(QDataStream &in, QString &str) \typedef QStringRef::const_iterator \since 5.4 - This typedef provides an STL-style const iterator for QStringRef. - \sa QStringRef::const_reverse_iterator */ @@ -10481,8 +10451,6 @@ QDataStream &operator>>(QDataStream &in, QString &str) \typedef QStringRef::const_reverse_iterator \since 5.7 - This typedef provides an STL-style const reverse iterator for QStringRef. - \sa QStringRef::const_iterator */ diff --git a/src/network/ssl/qdtls.cpp b/src/network/ssl/qdtls.cpp index a2280a7d10..74fb691dde 100644 --- a/src/network/ssl/qdtls.cpp +++ b/src/network/ssl/qdtls.cpp @@ -278,8 +278,6 @@ /*! \typedef QDtls::GeneratorParameters - - This is a synonym for QDtlsClientVerifier::GeneratorParameters. */ /*! -- cgit v1.2.3 From 5e8bd204e2af4fb53ef64c9e385223b52c26006e Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Tue, 28 Apr 2020 08:21:47 +1000 Subject: wasm: fix network download crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems it was defaulting to the indexdb filesystem, but it is not mounted. Fixes: QTBUG-83827 Change-Id: I1f81d790e5786fe41b59c0f41ca7f6025732c9b2 Reviewed-by: Morten Johan Sørvig --- src/network/access/qnetworkreplywasmimpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp index af8b39bab6..5b84014789 100644 --- a/src/network/access/qnetworkreplywasmimpl.cpp +++ b/src/network/access/qnetworkreplywasmimpl.cpp @@ -245,7 +245,7 @@ void QNetworkReplyWasmImplPrivate::doSendRequest() attr.password = request.url().password().toUtf8(); } - attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_PERSIST_FILE | EMSCRIPTEN_FETCH_REPLACE; + attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; QNetworkRequest::CacheLoadControl CacheLoadControlAttribute = (QNetworkRequest::CacheLoadControl)request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(); -- cgit v1.2.3 From 15026f309b3c69b94de39e0cbeba09dd8bdd5e29 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Mon, 27 Apr 2020 15:28:10 +0200 Subject: QMacStyle - change the arrow type only for 'OnlyOneTab' option It appears the hack was not needed when we have several tabs (popup button works as expected). Otherwise, this button suddenly has a different size: it's bigger when selected and smaller if not (and the holes clipped under the tab shape are becoming quite visible in the dark mode to the left and right of a tabbar). For the single tab we need some adjustment in the size not to have visible difference between inactive/selected tab. Fixes: QTBUG-83216 Change-Id: I52511e610ae7b36f261e0218b7e432e747bc9491 Reviewed-by: Volker Hilsheimer --- src/plugins/styles/mac/qmacstyle_mac.mm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 8e4aaa19c7..84233d6521 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -3977,13 +3977,19 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // which makes no sense on tabs. NSPopUpArrowPosition oldPosition = NSPopUpArrowAtCenter; NSPopUpButtonCell *pbCell = nil; - if (isPopupButton) { + auto rAdjusted = r; + if (isPopupButton && tp == QStyleOptionTab::OnlyOneTab) { pbCell = static_cast(pb.cell); oldPosition = pbCell.arrowPosition; pbCell.arrowPosition = NSPopUpNoArrow; + if (pb.state == NSOffState) { + // NSPopUpButton in this state is smaller. + rAdjusted.origin.x -= 3; + rAdjusted.size.width += 6; + } } - [pb.cell drawBezelWithFrame:r inView:pb.superview]; + [pb.cell drawBezelWithFrame:rAdjusted inView:pb.superview]; if (pbCell) // Restore, we may reuse it for a ComboBox. pbCell.arrowPosition = oldPosition; -- cgit v1.2.3 From 042b118cafc68c677e9eafa7f718a025a34940da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 29 Apr 2020 19:14:06 +0200 Subject: macOS: Avoid modifying hash while iterating it QCocoaTouch sneakily updated the list of active touches in the destructor, causing problems when we switched from Q_FOREACH to ranged-for. Fixes: QTBUG-83876 Change-Id: If7ec9e9116b7eb581580b461ae12ad70c739906d Reviewed-by: Simon Hausmann --- src/plugins/platforms/cocoa/qmultitouch_mac.mm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm index 95256657fe..ac2317b217 100644 --- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm +++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm @@ -184,7 +184,10 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch) if (_touchCount != _currentTouches.size()) { // Remove all instances, and basically start from scratch: touchPoints.clear(); - for (QCocoaTouch *qcocoaTouch : _currentTouches) { + // Deleting touch points will remove them from current touches, + // so we make a copy of the touches before iterating them. + const auto currentTouchesSnapshot = _currentTouches; + for (QCocoaTouch *qcocoaTouch : currentTouchesSnapshot) { if (!_updateInternalStateOnly) { qcocoaTouch->_touchPoint.state = Qt::TouchPointReleased; touchPoints.insert(qcocoaTouch->_touchPoint.id, qcocoaTouch->_touchPoint); -- cgit v1.2.3 From f9d219b92636fc279a3dc0c0e667b6668d0943db Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 27 Apr 2020 14:55:01 +0200 Subject: iOS: Teach edit menu popover to have a readonly mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should have foreseen the need for customizing this menu in 2014 when Controls 1 needed it, but here we are: Qt 5 is "done", this still wasn't done, and it's too late for new enum values in 5.15. So the workaround is to add a property on the focus object that the iOS plugin can query, and give us a menu that has Copy instead of Paste. Task-number: QTBUG-83811 Change-Id: Id8d18260002952fe7aa77aa5608cf7d0e440dacb Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index a3350bda87..19e476a064 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -416,6 +416,17 @@ if (unknownAction) return [super canPerformAction:action withSender:sender]; + + QObject *focusObject = QGuiApplication::focusObject(); + if (focusObject && focusObject->property("qt_im_readonly").toBool()) { + // exceptional menu items for read-only views: do include Copy, do not include Paste etc. + if (action == @selector(cut:) + || action == @selector(paste:) + || action == @selector(delete:)) + return NO; + if (action == @selector(copy:)) + return YES; + } return (hasSelection && isEditAction) || (!hasSelection && isSelectAction); } -- cgit v1.2.3 From 91d18c646443c812addf6d1cdada99d3c2d3a3ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 24 Apr 2020 15:36:23 +0200 Subject: iOS: Pick up theme palette from system colors For now we just fill out the system palette, and react to the system changing theme from dark to light. A further improvement would be to fill in the control-specific palettes. Change-Id: I764db4415f5b55ccb193dae43e9f4386c765b30b Fixes: QTBUG-42944 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosscreen.mm | 13 +++++++++++ src/plugins/platforms/ios/qiostheme.h | 5 ++++- src/plugins/platforms/ios/qiostheme.mm | 38 +++++++++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 9aba658479..c3376c08e8 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -45,6 +45,7 @@ #include "qiosapplicationdelegate.h" #include "qiosviewcontroller.h" #include "quiview.h" +#include "qiostheme.h" #include @@ -207,6 +208,18 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) [super sendEvent:event]; } +- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection +{ + [super traitCollectionDidChange:previousTraitCollection]; + + if (self.screen == UIScreen.mainScreen) { + if (previousTraitCollection.userInterfaceStyle != self.traitCollection.userInterfaceStyle) { + QIOSTheme::initializeSystemPalette(); + QWindowSystemInterface::handleThemeChange(nullptr); + } + } +} + @end // ------------------------------------------------------------------------- diff --git a/src/plugins/platforms/ios/qiostheme.h b/src/plugins/platforms/ios/qiostheme.h index c917679a91..c9d833713d 100644 --- a/src/plugins/platforms/ios/qiostheme.h +++ b/src/plugins/platforms/ios/qiostheme.h @@ -65,9 +65,12 @@ public: static const char *name; + static void initializeSystemPalette(); + private: mutable QHash m_fonts; - QPalette m_systemPalette; + + static QPalette s_systemPalette; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm index 5534264a60..626fbb66fe 100644 --- a/src/plugins/platforms/ios/qiostheme.mm +++ b/src/plugins/platforms/ios/qiostheme.mm @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -63,10 +64,8 @@ QT_BEGIN_NAMESPACE const char *QIOSTheme::name = "ios"; QIOSTheme::QIOSTheme() - : m_systemPalette(*QPlatformTheme::palette(QPlatformTheme::SystemPalette)) { - m_systemPalette.setBrush(QPalette::Highlight, QColor(204, 221, 237)); - m_systemPalette.setBrush(QPalette::HighlightedText, Qt::black); + initializeSystemPalette(); } QIOSTheme::~QIOSTheme() @@ -74,10 +73,41 @@ QIOSTheme::~QIOSTheme() qDeleteAll(m_fonts); } +QPalette QIOSTheme::s_systemPalette; + +void QIOSTheme::initializeSystemPalette() +{ + Q_DECL_IMPORT QPalette qt_fusionPalette(void); + s_systemPalette = qt_fusionPalette(); + + if (@available(ios 13.0, *)) { + s_systemPalette.setBrush(QPalette::Window, qt_mac_toQBrush(UIColor.systemGroupedBackgroundColor.CGColor)); + s_systemPalette.setBrush(QPalette::Active, QPalette::WindowText, qt_mac_toQBrush(UIColor.labelColor.CGColor)); + + s_systemPalette.setBrush(QPalette::Base, qt_mac_toQBrush(UIColor.secondarySystemGroupedBackgroundColor.CGColor)); + s_systemPalette.setBrush(QPalette::Active, QPalette::Text, qt_mac_toQBrush(UIColor.labelColor.CGColor)); + + s_systemPalette.setBrush(QPalette::Button, qt_mac_toQBrush(UIColor.secondarySystemBackgroundColor.CGColor)); + s_systemPalette.setBrush(QPalette::Active, QPalette::ButtonText, qt_mac_toQBrush(UIColor.labelColor.CGColor)); + + s_systemPalette.setBrush(QPalette::Active, QPalette::BrightText, qt_mac_toQBrush(UIColor.lightTextColor.CGColor)); + s_systemPalette.setBrush(QPalette::Active, QPalette::PlaceholderText, qt_mac_toQBrush(UIColor.placeholderTextColor.CGColor)); + + s_systemPalette.setBrush(QPalette::Active, QPalette::Link, qt_mac_toQBrush(UIColor.linkColor.CGColor)); + s_systemPalette.setBrush(QPalette::Active, QPalette::LinkVisited, qt_mac_toQBrush(UIColor.linkColor.CGColor)); + + s_systemPalette.setBrush(QPalette::Highlight, QColor(11, 70, 150, 60)); + s_systemPalette.setBrush(QPalette::HighlightedText, qt_mac_toQBrush(UIColor.labelColor.CGColor)); + } else { + s_systemPalette.setBrush(QPalette::Highlight, QColor(204, 221, 237)); + s_systemPalette.setBrush(QPalette::HighlightedText, Qt::black); + } +} + const QPalette *QIOSTheme::palette(QPlatformTheme::Palette type) const { if (type == QPlatformTheme::SystemPalette) - return &m_systemPalette; + return &s_systemPalette; return 0; } -- cgit v1.2.3 From 1eeabc6652220ff263eaa63872cd52c1693cbf69 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 30 Apr 2020 09:39:16 +0200 Subject: Don't output a warning that can trigger before Qt has fully initialized If a warning is outputted before Qt has had a chance to initialize the logging rules then it will cause it to hang as it will be stuck trying to initialize but can't continue because it needs to output the warning which triggered during that initialization. Therefore the warning should not be outputted to avoid this from happening. Change-Id: I202752c377bf69def2f7fb76be71b78d00ad3fd5 Reviewed-by: Volker Hilsheimer --- src/corelib/text/qlocale.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp index 60bfac62ab..e74b825774 100644 --- a/src/corelib/text/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -763,8 +763,6 @@ static void updateSystemPrivate() const ushort group = res.toString().at(0).unicode(); if (group != globalLocaleData.m_decimal) globalLocaleData.m_group = group; - else if (group == globalLocaleData.m_group) - qWarning("System-supplied decimal and grouping character are both 0x%hx", group); } res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant()); -- cgit v1.2.3 From 52a2505672cbb1ca8b5b32f7bc1259485c65483b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 15 Apr 2020 13:58:33 -0300 Subject: QCborValue: avoid signed integer oveflows when decoding time_t QDateTime::fromSecsSinceEpoch() multiplies by 1000 but does not check for overflow. That means we must do so in QCborValue validation. We can't use mul_overflow on 32-bit platforms, so we do a compare- and-branch there. For 64-bit platforms, we prefer to do the multiplication with checked overflow, as the common case is that it will not overflow and we'll need the multiplication anyway. Change-Id: Ibdc95e9af7bd456a94ecfffd16060cba6f1c86b8 Reviewed-by: Edward Welbourne --- src/corelib/serialization/qcborvalue.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index a3729b4ef9..f5cccf1be1 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -788,10 +788,25 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d) // The data is supposed to be US-ASCII. If it isn't (contains UTF-8), // QDateTime::fromString will fail anyway. dt = QDateTime::fromString(b->asLatin1(), Qt::ISODateWithMs); - } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Integer) { - dt = QDateTime::fromSecsSinceEpoch(e.value, Qt::UTC); - } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Double) { - dt = QDateTime::fromMSecsSinceEpoch(qint64(e.fpvalue() * 1000), Qt::UTC); + } else if (tag == qint64(QCborKnownTags::UnixTime_t)) { + qint64 msecs; + bool ok = false; + if (e.type == QCborValue::Integer) { +#if QT_POINTER_SIZE == 8 + // we don't have a fast 64-bit mul_overflow implementation on + // 32-bit architectures. + ok = !mul_overflow(e.value, qint64(1000), &msecs); +#else + static const qint64 Limit = std::numeric_limits::max() / 1000; + ok = (e.value > -Limit && e.value < Limit); + if (ok) + msecs = e.value * 1000; +#endif + } else if (e.type == QCborValue::Double) { + ok = convertDoubleTo(round(e.fpvalue() * 1000), &msecs); + } + if (ok) + dt = QDateTime::fromMSecsSinceEpoch(msecs, Qt::UTC); } if (dt.isValid()) { QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1(); -- cgit v1.2.3 From 2a53017df488b3cedbfbf5a56bf105b9fc5392fa Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 15 Apr 2020 14:00:05 -0300 Subject: QCborValue: add an extra check against producing invalid ISO dates By QCborValue design, we store the textual representation in ISO format, equivalent of CBOR tag 0, which isn't allowed to have negative years or beyond year 10000. Change-Id: Ibdc95e9af7bd456a94ecfffd16060ccff359c296 Reviewed-by: Ulf Hermann --- src/corelib/serialization/qcborvalue.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index f5cccf1be1..30bfa367ed 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -810,10 +810,12 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d) } if (dt.isValid()) { QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1(); - replaceByteData(text, text.size(), Element::StringIsAscii); - e.type = QCborValue::String; - d->elements[0].value = qint64(QCborKnownTags::DateTimeString); - return QCborValue::DateTime; + if (!text.isEmpty()) { + replaceByteData(text, text.size(), Element::StringIsAscii); + e.type = QCborValue::String; + d->elements[0].value = qint64(QCborKnownTags::DateTimeString); + return QCborValue::DateTime; + } } break; } -- cgit v1.2.3 From 821e71fded090d815b5cd396057ac9823874fe1f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 15 Apr 2020 15:16:06 -0300 Subject: QCborValue: check parsing of invalid URL QUrl will reject invalid URLs for us, so we don't get normalization. The original junk should be retrievable, of course. Change-Id: Ibdc95e9af7bd456a94ecfffd160610f5b2c8e1a2 Reviewed-by: Ulf Hermann Reviewed-by: Edward Welbourne --- src/corelib/serialization/qcborvalue.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 30bfa367ed..3bca15d562 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -827,9 +827,11 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d) // normalize to a short (decoded) form, so as to save space QUrl url(e.flags & Element::StringIsUtf16 ? b->asQStringRaw() : - b->toUtf8String()); - QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8(); - replaceByteData(encoded, encoded.size(), {}); + b->toUtf8String(), QUrl::StrictMode); + if (url.isValid()) { + QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8(); + replaceByteData(encoded, encoded.size(), {}); + } } return QCborValue::Url; } -- cgit v1.2.3 From c78a960198d59fb9a9ddd83ad7098b1db396edfd Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 15 Apr 2020 13:10:31 +0200 Subject: QCOMPARE: treat values as equal if qFuzzyIsNull(each) We hope this shall avoid some flaky failures noticed in quick tests, e.g. tst_QQuickMenu::Material::subMenuPosition(cascading,flip) was recently seen failing with 3.88e-11 != 0. This required some revision to test data in the testlib selftest for floats; the resulting expected output differs in details but not in which tests pass or fail. QEMU, naturally, made life difficult, requiring special-case code in the test-driver. [ChangeLog][QtTestLib][QCOMPARE] QCOMPARE() now treats its values as equal when qFuzzyIsNull() is true for both of them. Change-Id: Icc6ad5164b609937eddbe39cc69120f0abf0f3b4 Reviewed-by: Qt CI Bot Reviewed-by: Mitch Curtis --- src/testlib/qtestcase.cpp | 17 +++++++++++------ src/testlib/qtestcase.qdoc | 21 ++++++++++----------- 2 files changed, 21 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index f45999c7fa..74507c11e1 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -2525,16 +2525,21 @@ bool QTest::compare_helper(bool success, const char *failureMsg, } template -static bool floatingCompare(const T &t1, const T &t2) +static bool floatingCompare(const T &actual, const T &expected) { - switch (qFpClassify(t1)) + switch (qFpClassify(expected)) { case FP_INFINITE: - return (t1 < 0) == (t2 < 0) && qFpClassify(t2) == FP_INFINITE; + return (expected < 0) == (actual < 0) && qFpClassify(actual) == FP_INFINITE; case FP_NAN: - return qFpClassify(t2) == FP_NAN; + return qFpClassify(actual) == FP_NAN; default: - return qFuzzyCompare(t1, t2); + if (!qFuzzyIsNull(expected)) + return qFuzzyCompare(actual, expected); + Q_FALLTHROUGH(); + case FP_SUBNORMAL: // subnormal is always fuzzily null + case FP_ZERO: + return qFuzzyIsNull(actual); } } diff --git a/src/testlib/qtestcase.qdoc b/src/testlib/qtestcase.qdoc index e4e1825bb5..72f8cdaf8c 100644 --- a/src/testlib/qtestcase.qdoc +++ b/src/testlib/qtestcase.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -109,19 +109,18 @@ continues. If not, a failure is recorded in the test log and the test function returns without attempting any later checks. - Always respect QCOMPARE() parameter semantics. The first parameter passed to it - should always be the actual value produced by the code-under-test, while the - second parameter should always be the expected value. When the values don't - match, QCOMPARE() prints them with the labels \e Actual and \e Expected. - If the parameter order is swapped, debugging a failing test can be confusing. + Always respect QCOMPARE() parameter semantics. The first parameter passed to + it should always be the actual value produced by the code-under-test, while + the second parameter should always be the expected value. When the values + don't match, QCOMPARE() prints them with the labels \e Actual and \e + Expected. If the parameter order is swapped, debugging a failing test can be + confusing and tests expecting zero may fail due to rounding errors. When comparing floating-point types (\c float, \c double, and \c qfloat16), - \l qFuzzyCompare() is used for finite values. Infinities match if they have + \l qFuzzyCompare() is used for finite values. If qFuzzyIsNull() is true for + both values, they are also considered equal. Infinities match if they have the same sign, and any NaN as actual value matches with any NaN as expected - value (even though NaN != NaN, even when they're identical). This means that - expecting 0 can fail when the actual value may be affected by rounding errors. - One solution to this is to offset both actual and expected values by adding - some suitable constant (such as 1). + value (even though NaN != NaN, even when they're identical). QCOMPARE() tries to output the contents of the values if the comparison fails, so it is visible from the test log why the comparison failed. -- cgit v1.2.3 From 8e4c32857de277c36a4876d5d4e5df8e3b84f18c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 14 Apr 2020 17:54:24 +0200 Subject: QAuthenticator: make sure we load the SSPI library Change-Id: Iac371065dfc20ad5920889be66c8282a45c5805e Reviewed-by: Timur Pocheptsov --- src/network/kernel/qauthenticator.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index c95b1280b0..3ac54605e4 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE static QByteArray qNtlmPhase1(); static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phase2data); #if QT_CONFIG(sspi) // SSPI +static bool q_SSPI_library_load(); static QByteArray qSspiStartup(QAuthenticatorPrivate *ctx, QAuthenticatorPrivate::Method method, const QString& host); static QByteArray qSspiContinue(QAuthenticatorPrivate *ctx, QAuthenticatorPrivate::Method method, @@ -503,8 +504,13 @@ QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMet if (challenge.isEmpty()) { #if QT_CONFIG(sspi) // SSPI QByteArray phase1Token; - if (user.isEmpty()) // Only pull from system if no user was specified in authenticator + if (user.isEmpty()) { // Only pull from system if no user was specified in authenticator phase1Token = qSspiStartup(this, method, host); + } else if (!q_SSPI_library_load()) { + // Since we're not running qSspiStartup we have to make sure the library is loaded + qWarning("Failed to load the SSPI libraries"); + return ""; + } if (!phase1Token.isEmpty()) { response = phase1Token.toBase64(); phase = Phase2; -- cgit v1.2.3 From 90012f12b0fd7a6f9d2554fb2027e5f8c08d95ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Thu, 2 Apr 2020 17:16:47 +0200 Subject: QNAM: Don't check if a session is needed for a cache lookup QNetworkAccessCacheBackend didn't override the virtual start() function which then deferred to QNetworkAccessBackend::start() which conditions its success on whether or not a network session is available. Override the function and reimplement it without the network session check. Fixes: QTBUG-83205 Change-Id: I45d98a6f5da8ad04bb9da551a131f109e83074d7 Reviewed-by: Timur Pocheptsov --- src/network/access/qnetworkaccesscachebackend.cpp | 6 ++++++ src/network/access/qnetworkaccesscachebackend_p.h | 1 + 2 files changed, 7 insertions(+) (limited to 'src') diff --git a/src/network/access/qnetworkaccesscachebackend.cpp b/src/network/access/qnetworkaccesscachebackend.cpp index 22fdc5bb0b..4986b36ab1 100644 --- a/src/network/access/qnetworkaccesscachebackend.cpp +++ b/src/network/access/qnetworkaccesscachebackend.cpp @@ -123,6 +123,12 @@ bool QNetworkAccessCacheBackend::sendCacheContents() return true; } +bool QNetworkAccessCacheBackend::start() +{ + open(); + return true; +} + void QNetworkAccessCacheBackend::closeDownstreamChannel() { } diff --git a/src/network/access/qnetworkaccesscachebackend_p.h b/src/network/access/qnetworkaccesscachebackend_p.h index dfb0ce84d9..ceb02946dc 100644 --- a/src/network/access/qnetworkaccesscachebackend_p.h +++ b/src/network/access/qnetworkaccesscachebackend_p.h @@ -68,6 +68,7 @@ public: void open() override; void closeDownstreamChannel() override; void closeUpstreamChannel(); + bool start() override; void upstreamReadyRead(); void downstreamReadyWrite() override; -- cgit v1.2.3 From a426326e99a76a92c8d0c870e19c67311a434483 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Mon, 3 Feb 2020 15:49:30 +0100 Subject: Doc: Make snippets Qt Widgets compilable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed mainwindowsnippet.cpp and widgetdelegate.cpp from snippets.pro Task-number: QTBUG-81497 Change-Id: I40d1f34e64d958d2fb857dc8e468b9c40fff527c Reviewed-by: Paul Wicking Reviewed-by: Kai Koehne Reviewed-by: Topi Reiniö --- src/widgets/doc/snippets/customviewstyle.cpp | 7 +-- src/widgets/doc/snippets/filedialogurls.cpp | 8 +-- .../doc/snippets/graphicssceneadditemsnippet.cpp | 17 ++---- src/widgets/doc/snippets/graphicsview.cpp | 64 ++++++++++++++-------- src/widgets/doc/snippets/graphicsview_snippet.cpp | 63 +++++++++++++++++++++ src/widgets/doc/snippets/mdiareasnippets.cpp | 3 +- src/widgets/doc/snippets/myscrollarea.cpp | 23 ++------ src/widgets/doc/snippets/snippets.pro | 16 ++++++ src/widgets/doc/src/graphicsview.qdoc | 2 +- 9 files changed, 138 insertions(+), 65 deletions(-) create mode 100644 src/widgets/doc/snippets/graphicsview_snippet.cpp create mode 100644 src/widgets/doc/snippets/snippets.pro (limited to 'src') diff --git a/src/widgets/doc/snippets/customviewstyle.cpp b/src/widgets/doc/snippets/customviewstyle.cpp index b9c10cb31d..1e4cf2b711 100644 --- a/src/widgets/doc/snippets/customviewstyle.cpp +++ b/src/widgets/doc/snippets/customviewstyle.cpp @@ -50,11 +50,10 @@ #include -#include "customviewstyle.h" +#include "./customstyle/customstyle.h" - - -void CustomViewStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +void CustomStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const { //![0] diff --git a/src/widgets/doc/snippets/filedialogurls.cpp b/src/widgets/doc/snippets/filedialogurls.cpp index cd91e797e7..4b73a6c818 100644 --- a/src/widgets/doc/snippets/filedialogurls.cpp +++ b/src/widgets/doc/snippets/filedialogurls.cpp @@ -49,11 +49,10 @@ ****************************************************************************/ #include +#include -int main(int argv, char **args) +int loadFileDialog() { - QApplication app(argv, args); - //![0] QList urls; urls << QUrl::fromLocalFile("/Users/foo/Code/qt5") @@ -66,6 +65,5 @@ int main(int argv, char **args) // ... } //![0] - - return app.exec(); + return 1; } diff --git a/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp b/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp index 96e6bd650c..0ce135dc63 100644 --- a/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp +++ b/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp @@ -49,6 +49,9 @@ ****************************************************************************/ #include +#include +#include +#include class CustomScene : public QGraphicsScene { @@ -70,21 +73,9 @@ void CustomScene::drawItems(QPainter *painter, int numItems, for (int i = 0; i < numItems; ++i) { // Draw the item painter->save(); - painter->setMatrix(items[i]->sceneMatrix(), true); + painter->setTransform(items[i]->sceneTransform(), true); items[i]->paint(painter, &options[i], widget); painter->restore(); } } //! [0] - -int main(int argv, char **args) -{ - QApplication app(argv, args); - - CustomScene scene; - QGraphicsView view(&scene); - - view.show(); - - return app.exec(); -} diff --git a/src/widgets/doc/snippets/graphicsview.cpp b/src/widgets/doc/snippets/graphicsview.cpp index 9578f91eec..6262137c90 100644 --- a/src/widgets/doc/snippets/graphicsview.cpp +++ b/src/widgets/doc/snippets/graphicsview.cpp @@ -47,53 +47,70 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ //! [0] QGraphicsScene scene; QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100)); -QGraphicsItem *item = scene.itemAt(50, 50); -// item == rect +QGraphicsItem *item = scene.itemAt(50, 50, QTransform()); //! [0] +Q_UNUSED(rect); +Q_UNUSED(item); +} +void myPopulateScene(QGraphicsScene *) +{ + // Intentionally left empty +} +void snippetThatUsesMyPopulateScene() +{ //! [1] QGraphicsScene scene; myPopulateScene(&scene); - QGraphicsView view(&scene); view.show(); //! [1] +} - -//! [2] -class View : public QGraphicsView +class CustomItem : public QStandardItem { -Q_OBJECT - ... -public slots: - void zoomIn() { scale(1.2, 1.2); } - void zoomOut() { scale(1 / 1.2, 1 / 1.2); } - void rotateLeft() { rotate(-10); } - void rotateRight() { rotate(10); } - ... +public: + using QStandardItem::QStandardItem; + + int type() const override { return UserType; } + void mousePressEvent(QGraphicsSceneMouseEvent *event); + QStandardItem *clone() const override { return new CustomItem; } }; -//! [2] +void printScene() +{ //! [3] QGraphicsScene scene; +QPrinter printer; scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green)); -QPrinter printer; if (QPrintDialog(&printer).exec() == QDialog::Accepted) { QPainter painter(&printer); painter.setRenderHint(QPainter::Antialiasing); scene.render(&painter); } //! [3] +} - +void pixmapScene() +{ //! [4] QGraphicsScene scene; scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green)); @@ -106,21 +123,21 @@ painter.end(); pixmap.save("scene.png"); //! [4] - +} //! [5] void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { QMimeData *data = new QMimeData; - data->setColor(Qt::green); - QDrag *drag = new QDrag(event->widget()); drag->setMimeData(data); - drag->start(); + drag->exec(); } //! [5] - +void viewScene() +{ +QGraphicsScene scene; //! [6] QGraphicsView view(&scene); QOpenGLWidget *gl = new QOpenGLWidget(); @@ -129,3 +146,4 @@ format.setSamples(4); gl->setFormat(format); view.setViewport(gl); //! [6] +} diff --git a/src/widgets/doc/snippets/graphicsview_snippet.cpp b/src/widgets/doc/snippets/graphicsview_snippet.cpp new file mode 100644 index 0000000000..9d058d0f6a --- /dev/null +++ b/src/widgets/doc/snippets/graphicsview_snippet.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [2] +class View : public QGraphicsView +{ +Q_OBJECT + ... +public slots: + void zoomIn() { scale(1.2, 1.2); } + void zoomOut() { scale(1 / 1.2, 1 / 1.2); } + void rotateLeft() { rotate(-10); } + void rotateRight() { rotate(10); } + ... +}; +//! [2] diff --git a/src/widgets/doc/snippets/mdiareasnippets.cpp b/src/widgets/doc/snippets/mdiareasnippets.cpp index dec7aaa1e7..c1e2d37ccb 100644 --- a/src/widgets/doc/snippets/mdiareasnippets.cpp +++ b/src/widgets/doc/snippets/mdiareasnippets.cpp @@ -85,6 +85,7 @@ void addingSubWindowsExample() mdiArea.show(); } +/* int main(int argv, char **args) { QApplication app(argv, args); @@ -103,5 +104,5 @@ int main(int argv, char **args) return app.exec(); } - +*/ diff --git a/src/widgets/doc/snippets/myscrollarea.cpp b/src/widgets/doc/snippets/myscrollarea.cpp index dbf8da1603..8afe4a6834 100644 --- a/src/widgets/doc/snippets/myscrollarea.cpp +++ b/src/widgets/doc/snippets/myscrollarea.cpp @@ -48,7 +48,7 @@ ** ****************************************************************************/ -#include +#include class MyScrollArea : public QAbstractScrollArea { @@ -97,8 +97,10 @@ void MyScrollArea::updateWidgetPosition() //! [0] } -void MyScrollArea::scrollContentsBy(int /*dx*/, int /*dy*/) +void MyScrollArea::scrollContentsBy(int dx, int dy) { + Q_UNUSED(dx); + Q_UNUSED(dy); updateWidgetPosition(); } @@ -118,21 +120,6 @@ void MyScrollArea::updateArea() void MyScrollArea::resizeEvent(QResizeEvent *event) { + Q_UNUSED(event); updateArea(); } - -int main(int argv, char **args) -{ - QApplication app(argv, args); - - QPixmap pixmap("mypixmap.png"); - QLabel label; - label.setPixmap(pixmap); - MyScrollArea area(&label); - area.resize(300, 300); - area.show(); - - area.setWidget(&label); - - return app.exec(); -} diff --git a/src/widgets/doc/snippets/snippets.pro b/src/widgets/doc/snippets/snippets.pro new file mode 100644 index 0000000000..f1d3596f9d --- /dev/null +++ b/src/widgets/doc/snippets/snippets.pro @@ -0,0 +1,16 @@ +requires(qtHaveModule(widgets)) +requires(qtHaveModule(printsupport)) + +TEMPLATE = app + +TARGET = widgets_snippets + +QT += widgets printsupport + +SOURCES += customviewstyle.cpp \ + filedialogurls.cpp \ + graphicssceneadditemsnippet.cpp \ + graphicsview.cpp \ + mdiareasnippets.cpp \ + myscrollarea.cpp + diff --git a/src/widgets/doc/src/graphicsview.qdoc b/src/widgets/doc/src/graphicsview.qdoc index 94c824c2ed..46a68adc56 100644 --- a/src/widgets/doc/src/graphicsview.qdoc +++ b/src/widgets/doc/src/graphicsview.qdoc @@ -327,7 +327,7 @@ Here is an example of how to implement zoom and rotate slots in a subclass of QGraphicsView: - \snippet graphicsview.cpp 2 + \snippet graphicsview_snippet.cpp 2 The slots could be connected to \l{QToolButton}{QToolButtons} with \l{QAbstractButton::autoRepeat}{autoRepeat} enabled. -- cgit v1.2.3 From f0ea852d4dd6b3139869a952ee92e74cd367866d Mon Sep 17 00:00:00 2001 From: David Faure Date: Thu, 30 Apr 2020 20:44:11 +0200 Subject: QCommandLineParser: Wrap very long option names to leave room for descriptions Fixes: QTBUG-79926 Change-Id: I3302e0ed5b58949a35ccb001c71b22a6400a6c81 Reviewed-by: Thiago Macieira --- src/corelib/tools/qcommandlineparser.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index 48501f5271..a3d2a2f7c0 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -1063,18 +1063,23 @@ QString QCommandLineParser::helpText() const return d->helpText(false); } -static QString wrapText(const QString &names, int longestOptionNameString, const QString &description) +static QString wrapText(const QString &names, int optionNameMaxWidth, const QString &description) { const QLatin1Char nl('\n'); const QLatin1String indentation(" "); - if (description.isEmpty()) - return indentation + names + nl; - QString text = indentation + names.leftJustified(longestOptionNameString) + QLatin1Char(' '); - const int indent = text.length(); + // In case the list of option names is very long, wrap it as well + int nameIndex = 0; + auto nextNameSection = [&]() { + QString section = names.mid(nameIndex, optionNameMaxWidth); + nameIndex += section.size(); + return section; + }; + + QString text; int lineStart = 0; int lastBreakable = -1; - const int max = 79 - indent; + const int max = 79 - (indentation.size() + optionNameMaxWidth + 1); int x = 0; const int len = description.length(); @@ -1103,8 +1108,7 @@ static QString wrapText(const QString &names, int longestOptionNameString, const if (breakAt != -1) { const int numChars = breakAt - lineStart; //qDebug() << "breakAt=" << description.at(breakAt) << "breakAtSpace=" << breakAtSpace << lineStart << "to" << breakAt << description.mid(lineStart, numChars); - if (lineStart > 0) - text += QString(indent, QLatin1Char(' ')); + text += indentation + nextNameSection().leftJustified(optionNameMaxWidth) + QLatin1Char(' '); text += description.midRef(lineStart, numChars) + nl; x = 0; lastBreakable = -1; @@ -1115,6 +1119,10 @@ static QString wrapText(const QString &names, int longestOptionNameString, const } } + while (nameIndex < names.size()) { + text += indentation + nextNameSection() + nl; + } + return text; } @@ -1158,11 +1166,12 @@ QString QCommandLineParserPrivate::helpText(bool includeQtOptions) const longestOptionNameString = qMax(longestOptionNameString, optionNamesString.length()); } ++longestOptionNameString; + const int optionNameMaxWidth = qMin(50, longestOptionNameString); auto optionNameIterator = optionNameList.cbegin(); for (const QCommandLineOption &option : qAsConst(options)) { if (option.flags() & QCommandLineOption::HiddenFromHelp) continue; - text += wrapText(*optionNameIterator, longestOptionNameString, option.description()); + text += wrapText(*optionNameIterator, optionNameMaxWidth, option.description()); ++optionNameIterator; } if (!positionalArgumentDefinitions.isEmpty()) { @@ -1170,7 +1179,7 @@ QString QCommandLineParserPrivate::helpText(bool includeQtOptions) const text += nl; text += QCommandLineParser::tr("Arguments:") + nl; for (const PositionalArgumentDefinition &arg : positionalArgumentDefinitions) - text += wrapText(arg.name, longestOptionNameString, arg.description); + text += wrapText(arg.name, optionNameMaxWidth, arg.description); } return text; } -- cgit v1.2.3