From bc410cc706e107881d3ee982287441993cabb8a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Mon, 1 Feb 2016 11:49:02 +0100 Subject: [PATCH 001/173] QtWidgets: Reduce paint events when resizing native widget This patch reduces paint events by removing code which sets native widgets dirty in QWidgetWindow::handleExposeEvent. Native widgets are also marked dirty in QWidgetPrivate::drawWidget, so it is enough for proper painting. This restores Qt4 behavior when one resize means one repaint for native widgets. Without this patch the native widget is marked as dirty on every expose event, so one repaint is from syncBackingStore and second (or more) is from marking the widget dirty explicitly. This patch improves performance of native widgets and it also reduces locks when paint event is v-synced, e.g. on OpenGL swap buffers or on any other technology like VDPAU, VA-API, etc. Added autotest for checking number of paint events for native widgets. Task-number: QTBUG-50796 Change-Id: I4e1649069e2e73d15b038fd1834d0551915252ee Reviewed-by: Friedemann Kleint --- src/widgets/kernel/qwidgetwindow.cpp | 8 +------ .../qwidget_window/tst_qwidget_window.cpp | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 5290d79d9e8..872572a7e26 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -873,14 +873,8 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event) { if (isExposed()) { m_widget->setAttribute(Qt::WA_Mapped); - if (!event->region().isNull()) { - // Exposed native widgets need to be marked dirty to get them repainted correctly. - if (m_widget->internalWinId() && !m_widget->isWindow() && m_widget->isVisible() && m_widget->updatesEnabled()) { - if (QWidgetBackingStore *bs = m_widget->d_func()->maybeBackingStore()) - bs->markDirty(event->region(), m_widget); - } + if (!event->region().isNull()) m_widget->d_func()->syncBackingStore(event->region()); - } } else { m_widget->setAttribute(Qt::WA_Mapped, false); } diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index 27be0633334..3a4b563a6c4 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -88,6 +88,7 @@ private slots: void tst_showWithoutActivating(); void tst_paintEventOnSecondShow(); + void tst_paintEventOnResize_QTBUG50796(); #ifndef QT_NO_DRAGANDDROP void tst_dnd(); @@ -369,6 +370,29 @@ void tst_QWidget_window::tst_paintEventOnSecondShow() QTRY_VERIFY(w.paintEventCount > 0); } +void tst_QWidget_window::tst_paintEventOnResize_QTBUG50796() +{ + const QRect availableGeo = QGuiApplication::primaryScreen()->availableGeometry(); + + QWidget root; + root.setGeometry(availableGeo.width()/2 - 100, availableGeo.height()/2 - 100, + 200, 200); + + PaintTestWidget *native = new PaintTestWidget(&root); + native->winId(); // We're testing native widgets + native->setGeometry(10, 10, 50, 50); + + root.show(); + QVERIFY(QTest::qWaitForWindowExposed(&root)); + QVERIFY(QTest::qWaitForWindowActive(&root)); + QVERIFY(native->isVisible()); + + native->paintEventCount = 0; + native->resize(native->width() + 10, native->height() + 10); + QTest::qWait(50); // Wait for paint events + QTRY_COMPARE(native->paintEventCount, 1); // Only one paint event must occur +} + #ifndef QT_NO_DRAGANDDROP /* DnD test for QWidgetWindow (handleDrag*Event() functions). From dd8745e1d4beedfb8ef2e42fc10050287d3975f3 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Thu, 19 May 2016 07:27:39 +0200 Subject: [PATCH 002/173] Remove linux only-dependency from devicediscovery As libudev and libevdev have their config.tests and do work on other operating systems as well (FreeBSD, evdev), there is no need to make this exclusive for linux only. Thus, use the checks only; the else-section can go with that at the end, too. Change-Id: I2a5175a154b4f3e001bb42d187d8c7640c014049 Reviewed-by: Thiago Macieira --- .../devicediscovery/devicediscovery.pri | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/platformsupport/devicediscovery/devicediscovery.pri b/src/platformsupport/devicediscovery/devicediscovery.pri index 1ac25da901c..9829ae88ba4 100644 --- a/src/platformsupport/devicediscovery/devicediscovery.pri +++ b/src/platformsupport/devicediscovery/devicediscovery.pri @@ -1,18 +1,14 @@ HEADERS += $$PWD/qdevicediscovery_p.h -linux { - contains(QT_CONFIG, libudev) { - SOURCES += $$PWD/qdevicediscovery_udev.cpp - HEADERS += $$PWD/qdevicediscovery_udev_p.h - INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV - LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV - } else: contains(QT_CONFIG, evdev) { - SOURCES += $$PWD/qdevicediscovery_static.cpp - HEADERS += $$PWD/qdevicediscovery_static_p.h - } else { - SOURCES += $$PWD/qdevicediscovery_dummy.cpp - HEADERS += $$PWD/qdevicediscovery_dummy_p.h - } +contains(QT_CONFIG, libudev) { + SOURCES += $$PWD/qdevicediscovery_udev.cpp + HEADERS += $$PWD/qdevicediscovery_udev_p.h + INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV + LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV +} else: contains(QT_CONFIG, evdev) { + SOURCES += $$PWD/qdevicediscovery_static.cpp + HEADERS += $$PWD/qdevicediscovery_static_p.h } else { SOURCES += $$PWD/qdevicediscovery_dummy.cpp + HEADERS += $$PWD/qdevicediscovery_dummy_p.h } From e9628fbd391972d4ffe5882d283d512df7fa705c Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Mon, 16 May 2016 23:24:36 -0700 Subject: [PATCH 003/173] Fix dynamic librariy support detection for platforms without libdl Some platforms (e.g. FreeBSD) do not have libdl, but dlopen and related functions are part of libc. So first check for dlopen in libc, and only if that fails, look for it in libdl. Task-number: QTBUG-52951 Change-Id: I65a8ed18fce157da32f4e1ffeba30d7513385a8f Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- config.tests/unix/{libdl/libdl.cpp => dlopen/dlopen.cpp} | 0 config.tests/unix/dlopen/dlopen.pro | 2 ++ config.tests/unix/libdl/libdl.pro | 5 ++--- configure | 8 ++++++-- 4 files changed, 10 insertions(+), 5 deletions(-) rename config.tests/unix/{libdl/libdl.cpp => dlopen/dlopen.cpp} (100%) create mode 100644 config.tests/unix/dlopen/dlopen.pro diff --git a/config.tests/unix/libdl/libdl.cpp b/config.tests/unix/dlopen/dlopen.cpp similarity index 100% rename from config.tests/unix/libdl/libdl.cpp rename to config.tests/unix/dlopen/dlopen.cpp diff --git a/config.tests/unix/dlopen/dlopen.pro b/config.tests/unix/dlopen/dlopen.pro new file mode 100644 index 00000000000..1d343143325 --- /dev/null +++ b/config.tests/unix/dlopen/dlopen.pro @@ -0,0 +1,2 @@ +SOURCES = $$PWD/dlopen.cpp +CONFIG -= qt dylib diff --git a/config.tests/unix/libdl/libdl.pro b/config.tests/unix/libdl/libdl.pro index 8ed5231a8f3..4016395d35d 100644 --- a/config.tests/unix/libdl/libdl.pro +++ b/config.tests/unix/libdl/libdl.pro @@ -1,3 +1,2 @@ -SOURCES = libdl.cpp -CONFIG -= qt dylib -!qnx: LIBS += -ldl +include(../dlopen/dlopen.pro) +LIBS += -ldl diff --git a/configure b/configure index 7c65fbd8b51..109c0bbbac0 100755 --- a/configure +++ b/configure @@ -4743,9 +4743,13 @@ if [ "$CFG_LIBPNG" = "auto" ]; then fi # detect dl -if ! compileTest unix/libdl "libdl"; then - QMakeVar add DEFINES QT_NO_DYNAMIC_LIBRARY +if compileTest unix/dlopen "dlopen"; then QMAKE_CONFIG="$QMAKE_CONFIG no-libdl" +else + if ! compileTest unix/libdl "libdl"; then + QMAKE_CONFIG="$QMAKE_CONFIG no-libdl" + QMakeVar add DEFINES QT_NO_DYNAMIC_LIBRARY + fi fi if [ "$CFG_EGLFS" = "yes" ]; then From 6086c81e4d999d88ce4d412a20d250a219ab3c2c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 18 May 2016 11:07:04 +0200 Subject: [PATCH 004/173] Windows QPA: Improve workaround for non-Areo theme GL rendering. Reportedly, clearing the clip region is sufficient to fix the issue. InvalidateRect() should be avoided when handling WM_PAINT as it may cause events. Task-number: QTBUG-7865 Change-Id: Id9a7c280fcc2c8242bb34c34e73e53c3146e7a6e Reviewed-by: Andy Shaw Reviewed-by: Oliver Wolff Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowswindow.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index cf13de427ec..9c6cb53365a 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1568,12 +1568,13 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message, return false; PAINTSTRUCT ps; - // Observed painting problems with Aero style disabled (QTBUG-7865). - if (testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered)) - InvalidateRect(hwnd, 0, false); - BeginPaint(hwnd, &ps); + // Observed painting problems with Aero style disabled (QTBUG-7865). + // 5.8: Consider making it dependent on !DwmIsCompositionEnabled(). + if (testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered)) + SelectClipRgn(ps.hdc, NULL); + // If the a window is obscured by another window (such as a child window) // we still need to send isExposed=true, for compatibility. // Our tests depend on it. From eff3a7ded138e5f73fe716efae9e4bf74c71a8a4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 17 May 2016 10:45:43 +0200 Subject: [PATCH 005/173] delay application of -D/-I/-L/-l on windows as well clearly, "the windows configure does not have any of this magic to start with" was flat-out wrong. Task-number: QTBUG-53312 Change-Id: I80ac10bc8b1581e61c57fcd97f25626990d120ec Reviewed-by: Konstantin Tokarev Reviewed-by: Simon Hausmann --- tools/configure/configureapp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index a03be4df0a6..0909ff8aabf 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -2987,7 +2987,7 @@ void Configure::generateOutputVars() qtConfig += "accessibility"; if (!qmakeLibs.isEmpty()) - qmakeVars += "LIBS += " + formatPaths(qmakeLibs); + qmakeVars += "EXTRA_LIBS += " + formatPaths(qmakeLibs); if (!dictionary["QT_LFLAGS_SQLITE"].isEmpty()) qmakeVars += "QT_LFLAGS_SQLITE += " + dictionary["QT_LFLAGS_SQLITE"]; @@ -3105,9 +3105,9 @@ void Configure::generateOutputVars() qtConfig += "rpath"; if (!qmakeDefines.isEmpty()) - qmakeVars += QString("DEFINES += ") + qmakeDefines.join(' '); + qmakeVars += QString("EXTRA_DEFINES += ") + qmakeDefines.join(' '); if (!qmakeIncludes.isEmpty()) - qmakeVars += QString("INCLUDEPATH += ") + formatPaths(qmakeIncludes); + qmakeVars += QString("EXTRA_INCLUDEPATH += ") + formatPaths(qmakeIncludes); if (!opensslLibs.isEmpty()) qmakeVars += opensslLibs; if (dictionary[ "OPENSSL" ] == "linked") { From b2e9c680e3e3f446e84748fc5068d527daf10b62 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 19 May 2016 12:37:10 +0200 Subject: [PATCH 006/173] qpa: Use LIBS_PRIVATE, not LIBS when linking in font database bits. LIBS_PRIVATE is more correct (these shouldn't be part of the public API), and additionally, using LIBS_PRIVATE also ensures these libraries come last on the link command, which fixes builds using -Wl,--as-needed. Change-Id: I9f2e4e78855a30a53ce9013623597b840a2832bd Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qpa/basicunixfontdatabase.prf | 2 +- mkspecs/features/qpa/genericunixfontdatabase.prf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/qpa/basicunixfontdatabase.prf b/mkspecs/features/qpa/basicunixfontdatabase.prf index 261eadb5d02..f2e4016c997 100644 --- a/mkspecs/features/qpa/basicunixfontdatabase.prf +++ b/mkspecs/features/qpa/basicunixfontdatabase.prf @@ -1,3 +1,3 @@ contains(QT_CONFIG, system-freetype) { - LIBS += -lfreetype + LIBS_PRIVATE += -lfreetype } diff --git a/mkspecs/features/qpa/genericunixfontdatabase.prf b/mkspecs/features/qpa/genericunixfontdatabase.prf index fc11bea4707..b0d81e5571e 100644 --- a/mkspecs/features/qpa/genericunixfontdatabase.prf +++ b/mkspecs/features/qpa/genericunixfontdatabase.prf @@ -1,7 +1,7 @@ CONFIG += qpa/basicunixfontdatabase contains(QT_CONFIG, fontconfig) { DEFINES += Q_FONTCONFIGDATABASE - LIBS += -lfontconfig + LIBS_PRIVATE += -lfontconfig } else:!android { fonts.path = $$[QT_INSTALL_LIBS]/fonts fonts.files = $$QT_SOURCE_TREE/lib/fonts/* From 9c0a7cac83a511141e8dc91825dc5f9da64a1d69 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 17 May 2016 17:32:41 +0200 Subject: [PATCH 007/173] Doc: Fix references to QGuiApplication::clipboard() QClipboard's documentation still referred to QApplication::clipboard(), where the method was located in Qt4. Change-Id: I7fc31bacf5afa783f8ca38723773f24cd0bda347 Reviewed-by: Friedemann Kleint Reviewed-by: Leena Miettinen --- src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp | 2 +- src/gui/kernel/qclipboard.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp index 25968452750..decfee26f63 100644 --- a/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp +++ b/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp @@ -39,7 +39,7 @@ ****************************************************************************/ //! [0] -QClipboard *clipboard = QApplication::clipboard(); +QClipboard *clipboard = QGuiApplication::clipboard(); QString originalText = clipboard->text(); ... clipboard->setText(newText); diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp index 922c7fb8d9b..817c50d9b21 100644 --- a/src/gui/kernel/qclipboard.cpp +++ b/src/gui/kernel/qclipboard.cpp @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE Drop}. There is a single QClipboard object in an application, accessible - as QApplication::clipboard(). + as QGuiApplication::clipboard(). Example: \snippet code/src_gui_kernel_qclipboard.cpp 0 @@ -131,7 +131,7 @@ QT_BEGIN_NAMESPACE \endlist - \sa QApplication + \sa QGuiApplication */ /*! @@ -141,7 +141,7 @@ QT_BEGIN_NAMESPACE Do not call this function. - Call QApplication::clipboard() instead to get a pointer to the + Call QGuiApplication::clipboard() instead to get a pointer to the application's global clipboard object. There is only one clipboard in the window system, and creating @@ -159,7 +159,7 @@ QClipboard::QClipboard(QObject *parent) Destroys the clipboard. - You should never delete the clipboard. QApplication will do this + You should never delete the clipboard. QGuiApplication will do this when the application terminates. */ QClipboard::~QClipboard() From cdf1e67de1c462a59b71ee0b14bab73dc3391b65 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Mar 2016 10:40:32 +0100 Subject: [PATCH 008/173] QDesktopWidget: fix tracking QScreens. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old code failed to reliably detect new QScreens and connect their signals to its own slots. For example, if the QApplication added a new screen at the beginning of the screen list (which happens if the new screen is primary), the signal-connecting loop would actually instead add the now second screen to QDesktopWidget's list *again*, and connect its signals, but not connect any signal to the new, first screen. Furthermore, QDesktopWidget would miss geometry changes because QWidget (and hence QDesktopScreenWidget) automatically shrinks when the screen it is on gets smaller. To fix all of this, QDesktopScreenWidget now keeps its own record of the screen and its geometry, and it always scans over the entire screen list without relying on any ordering guarantees on behalf of QApplication. Change-Id: I2ee8361adf643849f43b7dd9a95966920fd13528 Task-number: QTBUG-52101 Reviewed-by: Błażej Szczygieł Reviewed-by: Marc Mutz --- src/widgets/kernel/qdesktopwidget.cpp | 99 ++++++++++++++++++--------- src/widgets/kernel/qdesktopwidget_p.h | 16 +++-- 2 files changed, 80 insertions(+), 35 deletions(-) diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp index d1b37bc03aa..e87b13c6300 100644 --- a/src/widgets/kernel/qdesktopwidget.cpp +++ b/src/widgets/kernel/qdesktopwidget.cpp @@ -40,6 +40,21 @@ QT_BEGIN_NAMESPACE +QDesktopScreenWidget::QDesktopScreenWidget(QScreen *screen, const QRect &geometry) + : QWidget(Q_NULLPTR, Qt::Desktop), m_screen(screen) +{ + setVisible(false); + if (QWindow *winHandle = windowHandle()) + winHandle->setScreen(screen); + setScreenGeometry(geometry); +} + +void QDesktopScreenWidget::setScreenGeometry(const QRect &geometry) +{ + m_geometry = geometry; + setGeometry(geometry); +} + int QDesktopScreenWidget::screenNumber() const { const QDesktopWidgetPrivate *desktopWidgetP @@ -74,54 +89,76 @@ const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const return rect; } +QDesktopScreenWidget *QDesktopWidgetPrivate::widgetForScreen(QScreen *qScreen) const +{ + foreach (QDesktopScreenWidget *widget, screens) { + if (widget->screen() == qScreen) + return widget; + } + return Q_NULLPTR; +} + void QDesktopWidgetPrivate::_q_updateScreens() { Q_Q(QDesktopWidget); const QList screenList = QGuiApplication::screens(); const int targetLength = screenList.length(); - const int oldLength = screens.length(); - - // Add or remove screen widgets as necessary - while (screens.size() > targetLength) - delete screens.takeLast(); - - for (int currentLength = screens.size(); currentLength < targetLength; ++currentLength) { - QScreen *qScreen = screenList.at(currentLength); - QDesktopScreenWidget *screenWidget = new QDesktopScreenWidget; - screenWidget->setGeometry(qScreen->geometry()); - QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)), - q, SLOT(_q_updateScreens()), Qt::QueuedConnection); - QObject::connect(qScreen, SIGNAL(availableGeometryChanged(QRect)), - q, SLOT(_q_availableGeometryChanged()), Qt::QueuedConnection); - QObject::connect(qScreen, SIGNAL(destroyed()), - q, SLOT(_q_updateScreens()), Qt::QueuedConnection); - screens.append(screenWidget); - } + bool screenCountChanged = false; + // Re-build our screens list. This is the easiest way to later compute which signals to emit. + // Create new screen widgets as necessary. While iterating, keep the old list in place so + // that widgetForScreen works. + // Furthermore, we note which screens have changed, and compute the overall virtual geometry. + QList newScreens; + QList changedScreens; QRegion virtualGeometry; - // update the geometry of each screen widget, determine virtual geometry, - // set the new screen for window handle and emit change signals afterwards. - QList changedScreens; - for (int i = 0; i < screens.length(); i++) { - QDesktopScreenWidget *screenWidget = screens.at(i); + for (int i = 0; i < targetLength; ++i) { QScreen *qScreen = screenList.at(i); - QWindow *winHandle = screenWidget->windowHandle(); - if (winHandle && winHandle->screen() != qScreen) - winHandle->setScreen(qScreen); const QRect screenGeometry = qScreen->geometry(); - if (screenGeometry != screenWidget->geometry()) { - screenWidget->setGeometry(screenGeometry); - changedScreens.push_back(i); + QDesktopScreenWidget *screenWidget = widgetForScreen(qScreen); + if (screenWidget) { + // an old screen. update geometry and remember the index in the *new* list + if (screenGeometry != screenWidget->screenGeometry()) { + screenWidget->setScreenGeometry(screenGeometry); + changedScreens.push_back(i); + } + } else { + // a new screen, create a widget and connect the signals. + screenWidget = new QDesktopScreenWidget(qScreen, screenGeometry); + QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)), + q, SLOT(_q_updateScreens()), Qt::QueuedConnection); + QObject::connect(qScreen, SIGNAL(availableGeometryChanged(QRect)), + q, SLOT(_q_availableGeometryChanged()), Qt::QueuedConnection); + QObject::connect(qScreen, SIGNAL(destroyed()), + q, SLOT(_q_updateScreens()), Qt::QueuedConnection); + screenCountChanged = true; } + // record all the screens and the overall geometry. + newScreens.push_back(screenWidget); virtualGeometry += screenGeometry; } + // Now we apply the accumulated updates. + screens.swap(newScreens); // now [newScreens] is the old screen list + Q_ASSERT(screens.size() == targetLength); q->setGeometry(virtualGeometry.boundingRect()); - if (oldLength != targetLength) - emit q->screenCountChanged(targetLength); + // Delete the QDesktopScreenWidget that are not used any more. + foreach (QDesktopScreenWidget *screen, newScreens) { + if (!screens.contains(screen)) { + delete screen; + screenCountChanged = true; + } + } + // Finally, emit the signals. + if (screenCountChanged) { + // Notice that we trigger screenCountChanged even if a screen was removed and another one added, + // in which case the total number of screens did not change. This is the only way for applications + // to notice that a screen was swapped out against another one. + emit q->screenCountChanged(targetLength); + } foreach (int changedScreen, changedScreens) emit q->resized(changedScreen); } diff --git a/src/widgets/kernel/qdesktopwidget_p.h b/src/widgets/kernel/qdesktopwidget_p.h index 1fcad7fa65a..d5ae629c640 100644 --- a/src/widgets/kernel/qdesktopwidget_p.h +++ b/src/widgets/kernel/qdesktopwidget_p.h @@ -55,12 +55,19 @@ QT_BEGIN_NAMESPACE class QDesktopScreenWidget : public QWidget { Q_OBJECT public: - QDesktopScreenWidget() : QWidget(Q_NULLPTR, Qt::Desktop) - { - setVisible(false); - } + explicit QDesktopScreenWidget(QScreen *screen, const QRect &geometry); int screenNumber() const; + void setScreenGeometry(const QRect &geometry); + + QScreen *screen() const { return m_screen.data(); } + QRect screenGeometry() const { return m_geometry; } + +private: + // The widget updates its screen and geometry automatically. We need to save them separately + // to detect changes, and trigger the appropriate signals. + const QPointer m_screen; + QRect m_geometry; }; class QDesktopWidgetPrivate : public QWidgetPrivate { @@ -70,6 +77,7 @@ public: ~QDesktopWidgetPrivate() { qDeleteAll(screens); } void _q_updateScreens(); void _q_availableGeometryChanged(); + QDesktopScreenWidget *widgetForScreen(QScreen *qScreen) const; QList screens; }; From 1acb29c3dd53fe675c71b05a5364e5b77ec0fe2a Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 29 Apr 2016 15:58:46 -0700 Subject: [PATCH 009/173] QMenu auto-test: Add test for two-level tearable menus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This has been fixed in 5.6.1 but we can afford the extra test to guard against regressions. The setup for this test is two menus, one parent of the other. The submenu is tearable. We open the parent menu, open its submenu and then move the mouse cursor straight over the submenu's tear-off area. The submenu should stay open even after a short delay. Change-Id: Ia8ad326d78dde31b6dd91b0ebacf0db1898715d4 Task-number: QTBUG-53068 Reviewed-by: Błażej Szczygieł Reviewed-by: Gabriel de Dietrich --- .../auto/widgets/widgets/qmenu/tst_qmenu.cpp | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index 20f17f6e9e4..4deade0b4d9 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -90,6 +90,7 @@ private slots: void mouseActivation(); #endif void tearOff(); + void submenuTearOffDontClose(); void layoutDirection(); void task208001_stylesheet(); @@ -631,6 +632,51 @@ void tst_QMenu::tearOff() QVERIFY(!torn->isVisible()); } +void tst_QMenu::submenuTearOffDontClose() +{ + QWidget widget; + QMenu *menu = new QMenu(&widget); + QVERIFY(!menu->isTearOffEnabled()); //default value + menu->setTearOffEnabled(true); + QVERIFY(menu->isTearOffEnabled()); + QMenu *submenu = new QMenu(&widget); + submenu->addAction("aaa"); + submenu->addAction("bbb"); + QVERIFY(!submenu->isTearOffEnabled()); //default value + submenu->setTearOffEnabled(true); + QVERIFY(submenu->isTearOffEnabled()); + menu->addMenu(submenu); + + widget.resize(300, 200); + centerOnScreen(&widget); + widget.show(); + widget.activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(&widget)); + // Show parent menu + menu->popup(widget.geometry().topRight() + QPoint(50, 0)); + QVERIFY(QTest::qWaitForWindowActive(menu)); + // Then its submenu + const QRect submenuRect = menu->actionGeometry(menu->actions().at(0)); + const QPoint submenuPos(submenuRect.topLeft() + QPoint(3, 3)); + // Move then click to avoid the submenu moves from causing it to close + QTest::mouseMove(menu, submenuPos, 100); + QTest::mouseClick(menu, Qt::LeftButton, 0, submenuPos, 100); + QTRY_VERIFY(QTest::qWaitForWindowActive(submenu)); + // Make sure we enter the submenu frame directly on the tear-off area + QTest::mouseMove(submenu, QPoint(10, 3), 100); + if (submenu->style()->styleHint(QStyle::SH_Menu_SubMenuDontStartSloppyOnLeave)) { + qWarning("Sloppy menu timer disabled by the style: %s", qPrintable(QApplication::style()->objectName())); + // Submenu must get the enter event + QTRY_VERIFY(submenu->underMouse()); + } else { + const int closeTimeout = submenu->style()->styleHint(QStyle::SH_Menu_SubMenuSloppyCloseTimeout); + QTest::qWait(closeTimeout + 100); + // Menu must not disappear and it must get the enter event + QVERIFY(submenu->isVisible()); + QVERIFY(submenu->underMouse()); + } +} + void tst_QMenu::layoutDirection() { QMainWindow win; From a1dccd0708ae805b014489b5b16cc055d3001c50 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 19 May 2016 09:37:22 +0200 Subject: [PATCH 010/173] WinRT: Do not assert on socket close If no read was established before (no IO pending) the function will fail. In this case there is no need to assert though. Change-Id: Iaa18e4124389783fc2b8363a85c60a308903a713 Task-number: QTBUG-53424 Reviewed-by: Maurice Kalinowski --- src/network/socket/qnativesocketengine_winrt.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index ecd364b84b7..aae0dd835be 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -469,7 +469,10 @@ void QNativeSocketEngine::close() hr = socket3->CancelIOAsync(&action); Q_ASSERT_SUCCEEDED(hr); hr = QWinRTFunctions::await(action); - Q_ASSERT_SUCCEEDED(hr); + // If there is no pending IO (no read established before) the function will fail with + // "function was called at an unexpected time" which is fine. + if (hr != E_ILLEGAL_METHOD_CALL) + Q_ASSERT_SUCCEEDED(hr); } #endif // _MSC_VER >= 1900 From 9e3e98759028dc6b6452c8fd426dd00622ffc7ae Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 16 May 2016 16:28:24 -0700 Subject: [PATCH 011/173] QNSView: Pass on the responder chain if deletion is pending MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I7d098b61f6feb2ac38582c0efb1bbdf25a83e967 Task-number: QTBUG-53398 Reviewed-by: René J.V. Bertin Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 0d58faa5bf0..e78cc411a88 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -653,7 +653,9 @@ QT_WARNING_POP - (BOOL)becomeFirstResponder { - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) + if (!m_window || !m_platformWindow) + return NO; + if (m_window->flags() & Qt::WindowTransparentForInput) return NO; if (!m_platformWindow->windowIsPopupType() && !m_isMenuView) QWindowSystemInterface::handleWindowActivated([self topLevelWindow]); @@ -662,11 +664,13 @@ QT_WARNING_POP - (BOOL)acceptsFirstResponder { + if (!m_window || !m_platformWindow) + return NO; if (m_isMenuView) return NO; if (m_platformWindow->shouldRefuseKeyWindowAndFirstResponder()) return NO; - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) + if (m_window->flags() & Qt::WindowTransparentForInput) return NO; if ((m_window->flags() & Qt::ToolTip) == Qt::ToolTip) return NO; @@ -676,7 +680,9 @@ QT_WARNING_POP - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { Q_UNUSED(theEvent) - if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) + if (!m_window || !m_platformWindow) + return NO; + if (m_window->flags() & Qt::WindowTransparentForInput) return NO; return YES; } From 8e8bd90e4445415df7b7f516444e594d3e678c1a Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 19 May 2016 10:47:27 +0200 Subject: [PATCH 012/173] Fix compilation without process support Change-Id: I88ef96bf15f40e459bacc4b2abe4dfe84e257495 Reviewed-by: Friedemann Kleint --- tests/auto/gui/image/qicon/tst_qicon.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp index 3c4610a892a..a0914b7700f 100644 --- a/tests/auto/gui/image/qicon/tst_qicon.cpp +++ b/tests/auto/gui/image/qicon/tst_qicon.cpp @@ -717,6 +717,7 @@ void tst_QIcon::fromThemeCache() QIcon::setThemeSearchPaths(QStringList()); QSKIP("gtk-update-icon-cache not run (binary not found)"); } +#ifndef QT_NO_PROCESS QProcess process; process.start(gtkUpdateIconCache, QStringList() << QStringLiteral("-f") << QStringLiteral("-t") << (dir.path() + QLatin1String("/testcache"))); @@ -726,6 +727,7 @@ void tst_QIcon::fromThemeCache() QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); +#endif // QT_NO_PROCESS QVERIFY(QFileInfo(cacheName).lastModified() >= QFileInfo(dir.path() + QLatin1String("/testcache/16x16/actions")).lastModified()); QIcon::setThemeSearchPaths(QStringList() << dir.path()); // reload themes QVERIFY(!QIcon::fromTheme("button-open").isNull()); From d2af1d71c11ee937a6796eca0057d4052b0220af Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Fri, 20 May 2016 20:38:06 +0200 Subject: [PATCH 013/173] Remove obsolete freebsd-icc mkspecs The freebsd-icc mkspec was intended to be used with the Intel compiler, which nowadays is still only available in version 8.1.038 (https://www.freshports.org/lang/icc/) and for i386 only while the current version is around 17. On FreeBSD the port was actually never supported by Intel anyway. Change-Id: I03b1939be63eef4363bd6b074a6b739365f495ac Reviewed-by: Thiago Macieira --- mkspecs/freebsd-icc/qmake.conf | 95 ----------------------------- mkspecs/freebsd-icc/qplatformdefs.h | 34 ----------- 2 files changed, 129 deletions(-) delete mode 100644 mkspecs/freebsd-icc/qmake.conf delete mode 100644 mkspecs/freebsd-icc/qplatformdefs.h diff --git a/mkspecs/freebsd-icc/qmake.conf b/mkspecs/freebsd-icc/qmake.conf deleted file mode 100644 index d72ea732786..00000000000 --- a/mkspecs/freebsd-icc/qmake.conf +++ /dev/null @@ -1,95 +0,0 @@ -# -# qmake configuration for freebsd-icc -# -# Written for Intel C++ 7.1 and 8.0 on FreeBSD -# -# Note: Some of the remarks from the Intel compiler are disabled (even -# with 'warn_on' specified): -# -# remark #171: invalid type conversion: "int" to "void *" -# remark #193: zero used for undefined preprocessing identifier -# remark #279: controlling expression is constant -# remark #304: access control not specified ("public" by default) -# remark #310: old-style parameter list (anachronism) -# remark #383: value copied to temporary, reference to temporary used -# remark #424: extra ";" ignored -# remark #444: destructor for base class "Class" is not virtual -# remark #488: template parameter "T" is not used in declaring the parameter -# types of function template "function" -# remark #810: conversion from "type1" to "type2" may loose significant bits -# remark #858: type qualifier on return type is meaningless -# remark #967: conversion from "type1" to "type2"; sizes do not match -# remark #981: operands are evaluated in unspecified order -# remark #1418: external definition with no prior declaration -# remark #1419: external declaration in primary source file -# warning #1476: field uses tail padding of a base class -# warning #1477: GNU C++ compilers may use bit field padding -# warning #1572: floating-point equality and inequality comparisons are unreliable -# - -MAKEFILE_GENERATOR = UNIX -QMAKE_PLATFORM = freebsd bsd - -include(../common/unix.conf) - -QMAKE_COMPILER = gcc intel_icc # icc pretends to be gcc - -QMAKE_CC = icc -QMAKE_LEX = flex -QMAKE_LEXFLAGS = -QMAKE_YACC = yacc -QMAKE_YACCFLAGS = -d -QMAKE_CFLAGS = -wd858,1572 -QMAKE_CFLAGS_DEPS = -M -QMAKE_CFLAGS_WARN_ON = -w2 -wd171,193,279,304,310,383,424,444,488,810,967,981,1418,1419,1476,1477 -QMAKE_CFLAGS_WARN_OFF = -w -QMAKE_CFLAGS_RELEASE = -QMAKE_CFLAGS_DEBUG = -g -QMAKE_CFLAGS_SHLIB = -fpic -QMAKE_CFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_SHLIB -QMAKE_CFLAGS_YACC = -QMAKE_CFLAGS_THREAD = -D_THREAD_SAFE - -QMAKE_CXX = icpc -QMAKE_CXXFLAGS = $$QMAKE_CFLAGS -QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS -QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF -QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE -QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG -QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB -QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB -QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD - -# Addon software goes into /usr/local on the BSDs, by default we will look there -QMAKE_INCDIR = /usr/local/include -QMAKE_LIBDIR = /usr/local/lib -QMAKE_INCDIR_X11 = /usr/X11R6/include -QMAKE_LIBDIR_X11 = /usr/X11R6/lib -QMAKE_INCDIR_OPENGL = /usr/X11R6/include -QMAKE_LIBDIR_OPENGL = /usr/X11R6/lib - -QMAKE_LINK = icpc -QMAKE_LINK_SHLIB = icpc -QMAKE_LFLAGS = -QMAKE_LFLAGS_RELEASE = -QMAKE_LFLAGS_DEBUG = -QMAKE_LFLAGS_SHLIB = -shared -QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB -QMAKE_LFLAGS_SONAME = -Qoption,ld,-soname, -QMAKE_LFLAGS_THREAD = -mt -QMAKE_LFLAGS_RPATH = -Qoption,ld,-rpath, - -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = -QMAKE_LIBS_X11 = -lXext -lX11 -lm -QMAKE_LIBS_OPENGL = -lGL -QMAKE_LIBS_THREAD = - -QMAKE_AR = ar cqs -QMAKE_OBJCOPY = objcopy -QMAKE_NM = nm -P -QMAKE_RANLIB = - -load(qt_config) diff --git a/mkspecs/freebsd-icc/qplatformdefs.h b/mkspecs/freebsd-icc/qplatformdefs.h deleted file mode 100644 index 48dc4d64fb0..00000000000 --- a/mkspecs/freebsd-icc/qplatformdefs.h +++ /dev/null @@ -1,34 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the qmake spec of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "../freebsd-g++/qplatformdefs.h" From c18b802e337c1a58a687a0e9f1b23465c9036b0a Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Fri, 20 May 2016 09:55:05 +0200 Subject: [PATCH 014/173] Fixed variable type A port was being assigned to qint16 instead of quint16. Change-Id: I9414e2dcca52beab1bc17ef61cfff56db8ab83a0 Reviewed-by: Edward Welbourne Reviewed-by: Timur Pocheptsov --- src/network/access/qhttpnetworkconnectionchannel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index f591abc28b4..dfa5d0e74ad 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -325,7 +325,7 @@ bool QHttpNetworkConnectionChannel::ensureConnection() priv->phase = QAuthenticatorPrivate::Start; QString connectHost = connection->d_func()->hostName; - qint16 connectPort = connection->d_func()->port; + quint16 connectPort = connection->d_func()->port; #ifndef QT_NO_NETWORKPROXY // HTTPS always use transparent proxy. From b8a0c6e7c52ebf56d0895f798946d1f1dbb00c35 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 23 May 2016 10:34:08 +0200 Subject: [PATCH 015/173] Windows QPA: Format window title correctly when creating a window. Add convenience QWindowsWindow::formatWindowTitle() and use that in QWindowsIntegration::createPlatformWindow(). Task-number: QTBUG-53394 Change-Id: I76ebade97c5af71ffa3d11075511b94a54a3dbf8 Reviewed-by: J-P Nurmi --- src/plugins/platforms/windows/qwindowsintegration.cpp | 4 +++- src/plugins/platforms/windows/qwindowswindow.cpp | 7 ++++++- src/plugins/platforms/windows/qwindowswindow.h | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 7419118878f..6142aac92ed 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -331,7 +331,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons if (customMarginsV.isValid()) requested.customMargins = qvariant_cast(customMarginsV); - QWindowsWindowData obtained = QWindowsWindowData::create(window, requested, window->title()); + QWindowsWindowData obtained = + QWindowsWindowData::create(window, requested, + QWindowsWindow::formatWindowTitle(window->title())); qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << ' ' << window << "\n Requested: " << requested.geometry << " frame incl.=" diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index f76b3bb2d22..31c99845596 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1696,7 +1696,7 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message, void QWindowsWindow::setWindowTitle(const QString &title) { - setWindowTitle_sys(QWindowsWindow::formatWindowTitle(title, QStringLiteral(" - "))); + setWindowTitle_sys(QWindowsWindow::formatWindowTitle(title)); } void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags) @@ -2534,4 +2534,9 @@ void QWindowsWindow::setHasBorderInFullScreen(bool border) clearFlag(HasBorderInFullScreen); } +QString QWindowsWindow::formatWindowTitle(const QString &title) +{ + return QPlatformWindow::formatWindowTitle(title, QStringLiteral(" - ")); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 999761f3c68..df7d2295a97 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -327,6 +327,8 @@ public: void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch); static void setHasBorderInFullScreenStatic(QWindow *window, bool border); void setHasBorderInFullScreen(bool border); + static QString formatWindowTitle(const QString &title); + private: inline void show_sys() const; inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const; From 11f14a0442883a2446116dc5c91c3e10ef339555 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 23 May 2016 09:55:13 +0200 Subject: [PATCH 016/173] Turn off optimization for checkForAlphaPixels on Windows ARM This function is optimized in a way that it returns bad results with the arm msvc compiler. Task-number: QTBUG-52007 Change-Id: Ica4517dfb7dde5a78d563f9253c4c907090c9459 Reviewed-by: Andreas Holzammer Reviewed-by: Kevin Funk Reviewed-by: Friedemann Kleint --- src/gui/image/qimage.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 29a688099b9..59a83a6750c 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -170,6 +170,9 @@ QImageData::~QImageData() data = 0; } +#if defined(_M_ARM) +#pragma optimize("", off) +#endif bool QImageData::checkForAlphaPixels() const { @@ -277,6 +280,9 @@ bool QImageData::checkForAlphaPixels() const return has_alpha_pixels; } +#if defined(_M_ARM) +#pragma optimize("", on) +#endif /*! \class QImage From eda29451e958cb4981c254d48a20125988a04a45 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 12 May 2016 17:16:51 +0200 Subject: [PATCH 017/173] Enable -separate-debug-info for mingw toolchains Having the debug info in separate files is very helpful, especially on memory constrained 32bit systems. When the debug info is compiled into the object files, processes can run out of memory when trying to load them. Change-Id: I1808a32e855d6a62e17e1b734c511b31db5f03f1 Reviewed-by: Oswald Buddenhagen --- config.tests/unix/objcopy/objcopy.pro | 5 ++++- mkspecs/features/win32/separate_debug_info.prf | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 mkspecs/features/win32/separate_debug_info.prf diff --git a/config.tests/unix/objcopy/objcopy.pro b/config.tests/unix/objcopy/objcopy.pro index 3c28b89ef37..3c76ae92efa 100644 --- a/config.tests/unix/objcopy/objcopy.pro +++ b/config.tests/unix/objcopy/objcopy.pro @@ -1,4 +1,7 @@ SOURCES = objcopy.cpp CONFIG -= qt +TARGET = objcopytest -QMAKE_POST_LINK += $$QMAKE_OBJCOPY --only-keep-debug objcopy objcopy.debug && $$QMAKE_OBJCOPY --strip-debug objcopy && $$QMAKE_OBJCOPY --add-gnu-debuglink=objcopy.debug objcopy +load(resolve_target) + +QMAKE_POST_LINK += $$QMAKE_OBJCOPY --only-keep-debug $$QMAKE_RESOLVED_TARGET objcopytest.debug && $$QMAKE_OBJCOPY --strip-debug $$QMAKE_RESOLVED_TARGET && $$QMAKE_OBJCOPY --add-gnu-debuglink=objcopytest.debug $$QMAKE_RESOLVED_TARGET diff --git a/mkspecs/features/win32/separate_debug_info.prf b/mkspecs/features/win32/separate_debug_info.prf new file mode 100644 index 00000000000..2838020f016 --- /dev/null +++ b/mkspecs/features/win32/separate_debug_info.prf @@ -0,0 +1,18 @@ +have_target:!static:!isEmpty(QMAKE_OBJCOPY) { + load(resolve_target) + QMAKE_TARGET_DEBUG_INFO = $${QMAKE_RESOLVED_TARGET}.debug + + shell_target = $$shell_quote($$relative_path($$QMAKE_RESOLVED_TARGET, $$OUT_PWD)) + shell_target_debug_info = $$shell_quote($$relative_path($$QMAKE_TARGET_DEBUG_INFO, $$OUT_PWD)) + copy_debug_info = $$QMAKE_OBJCOPY --only-keep-debug $$shell_target $$shell_target_debug_info + link_debug_info = $$QMAKE_OBJCOPY --add-gnu-debuglink=$$shell_target_debug_info $$shell_target + strip_debug_info = $$QMAKE_OBJCOPY --strip-debug $$shell_target + + !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK = $$escape_expand(\\n\\t)$$QMAKE_POST_LINK + + QMAKE_POST_LINK = $$copy_debug_info && $$strip_debug_info && $$link_debug_info $$QMAKE_POST_LINK + silent:QMAKE_POST_LINK = @echo creating $@.debug && $$QMAKE_POST_LINK + + target.targets += $$QMAKE_TARGET_DEBUG_INFO + QMAKE_DISTCLEAN += $$QMAKE_TARGET_DEBUG_INFO +} From e28d31dbfaca7f870240fe414ccfedceb16731d7 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Fri, 20 May 2016 21:50:36 +0200 Subject: [PATCH 018/173] Move freebsd-g++ mkspecs back for supported FreeBSD 9.3 and up FreeBSD 9.3 is still supported and uses gcc as the default compiler, therefore FreeBSD ports require patching the mkspecs back. To avoid patching, move the mkspecs back to the right place and adapt the path in the qmake.conf/qplatformdefs.h [ChangeLog][FreeBSD] The freebsd-g++ mkspec was moved back and no longer requires the "unsupported/" prefix, matching the FreeBSD ports tree, as FreeBSD 9.3 still defaults to using GCC. Users of GCC that did not previously use the ports patch will need to adapt their build scripts and drop the "unsupported/" prefix. Change-Id: Ideda4a33cccf5381000f6f50b6ae92a5c24ba9d4 Reviewed-by: Thiago Macieira --- configure | 2 +- mkspecs/{unsupported => }/freebsd-g++/qmake.conf | 6 +++--- mkspecs/{unsupported => }/freebsd-g++/qplatformdefs.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename mkspecs/{unsupported => }/freebsd-g++/qmake.conf (87%) rename mkspecs/{unsupported => }/freebsd-g++/qplatformdefs.h (97%) diff --git a/configure b/configure index 109c0bbbac0..9d75668452d 100755 --- a/configure +++ b/configure @@ -2872,7 +2872,7 @@ if [ -z "$PLATFORM" ]; then FreeBSD:*) PLATFORM=freebsd-clang PLATFORM_NOTES=" - - Also available for FreeBSD: freebsd-icc + - Also available for FreeBSD: freebsd-g++ " ;; OpenBSD:*) diff --git a/mkspecs/unsupported/freebsd-g++/qmake.conf b/mkspecs/freebsd-g++/qmake.conf similarity index 87% rename from mkspecs/unsupported/freebsd-g++/qmake.conf rename to mkspecs/freebsd-g++/qmake.conf index 527a94870c9..282b6bdfa7c 100644 --- a/mkspecs/unsupported/freebsd-g++/qmake.conf +++ b/mkspecs/freebsd-g++/qmake.conf @@ -5,7 +5,7 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = freebsd bsd -include(../../common/unix.conf) +include(../common/unix.conf) QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE @@ -29,6 +29,6 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../../common/gcc-base-unix.conf) -include(../../common/g++-unix.conf) +include(../common/gcc-base-unix.conf) +include(../common/g++-unix.conf) load(qt_config) diff --git a/mkspecs/unsupported/freebsd-g++/qplatformdefs.h b/mkspecs/freebsd-g++/qplatformdefs.h similarity index 97% rename from mkspecs/unsupported/freebsd-g++/qplatformdefs.h rename to mkspecs/freebsd-g++/qplatformdefs.h index b52be38b4ed..aa51e08990d 100644 --- a/mkspecs/unsupported/freebsd-g++/qplatformdefs.h +++ b/mkspecs/freebsd-g++/qplatformdefs.h @@ -31,4 +31,4 @@ ** ****************************************************************************/ -#include "../../freebsd-clang/qplatformdefs.h" +#include "../freebsd-clang/qplatformdefs.h" From defec688d20d32c1d3bc21067968c0c521da47c1 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 01:08:10 +0200 Subject: [PATCH 019/173] Use -liconv on OpenBSD as well in config.tests OpenBSD iconv is in -liconv, so it needs to be added here. NetBSD has iconv in libc, so only OpenBSD is affected. Patch obtained from Vadim Zhukov , OpenBSD qt ports maintainer. Change-Id: Icce25d154857f0ce161b5f6b7ddac3c150a02bb8 Reviewed-by: Thiago Macieira --- config.tests/unix/iconv/iconv.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.tests/unix/iconv/iconv.pro b/config.tests/unix/iconv/iconv.pro index ca12e519470..65273ccc941 100644 --- a/config.tests/unix/iconv/iconv.pro +++ b/config.tests/unix/iconv/iconv.pro @@ -1,3 +1,3 @@ SOURCES = iconv.cpp CONFIG -= qt dylib -mac|mingw|qnx|haiku:LIBS += -liconv +mac|mingw|openbsd|qnx|haiku:LIBS += -liconv From e91be71ef04c22e478a3e98256ded87b28d0d767 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 01:32:30 +0200 Subject: [PATCH 020/173] Add OpenBSD to list of BSD systems defines using kqueue too Besides FreeBSD and NetBSD, OpenBSD uses kqueue too, so add the according Q_OS_OPENBSD define here to make that work. Patch obtained via OpenBSD qt ports maintainer Vadim Zhukov from OpenBSD qt ports patches. Change-Id: Ib9e6f6303b661beb88666bd3c2bf36a77e929f9d Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemwatcher.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 354e4931b96..d8564c4c40f 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -52,7 +52,7 @@ # include "qfilesystemwatcher_win_p.h" #elif defined(USE_INOTIFY) # include "qfilesystemwatcher_inotify_p.h" -#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_IOS) +#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_IOS) # include "qfilesystemwatcher_kqueue_p.h" #elif defined(Q_OS_OSX) # include "qfilesystemwatcher_fsevents_p.h" @@ -68,7 +68,7 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject // there is a chance that inotify may fail on Linux pre-2.6.13 (August // 2005), so we can't just new inotify directly. return QInotifyFileSystemWatcherEngine::create(parent); -#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_IOS) +#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_IOS) return QKqueueFileSystemWatcherEngine::create(parent); #elif defined(Q_OS_OSX) return QFseventsFileSystemWatcherEngine::create(parent); From 14ae00dd50ed4a75c2efa0b34da971b0e252e124 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 13:31:27 +0200 Subject: [PATCH 021/173] Compile fix: undefine types before defining them On NetBSD, the types uint64_t, uint32_t and uint8_t are already defined in sys/types.h which leads to compile errors. Those types need to be properly undefined before defining them with the Qt code. Change-Id: Icd58f421619f15b899cf5c5de1cfb22a519a4e4b Reviewed-by: Thiago Macieira --- src/corelib/tools/qcryptographichash.cpp | 20 +++++++++++++++++++ .../tools/qmessageauthenticationcode.cpp | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index 1c74a602c69..ab549f071e1 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -89,9 +89,29 @@ static SHA3Final * const sha3Final = Final; available on all platforms (MSVC 2008, for example), we #define them to the Qt equivalents. */ + +#ifdef uint64_t +#undef uint64_t +#endif + #define uint64_t QT_PREPEND_NAMESPACE(quint64) + +#ifdef uint32_t +#undef uint32_t +#endif + #define uint32_t QT_PREPEND_NAMESPACE(quint32) + +#ifdef uint8_t +#undef uint8_t +#endif + #define uint8_t QT_PREPEND_NAMESPACE(quint8) + +#ifdef int_least16_t +#undef int_least16_t +#endif + #define int_least16_t QT_PREPEND_NAMESPACE(qint16) // Header from rfc6234 with 1 modification: diff --git a/src/corelib/tools/qmessageauthenticationcode.cpp b/src/corelib/tools/qmessageauthenticationcode.cpp index 5e7f1fc4313..f25a76d4506 100644 --- a/src/corelib/tools/qmessageauthenticationcode.cpp +++ b/src/corelib/tools/qmessageauthenticationcode.cpp @@ -40,9 +40,29 @@ available on all platforms (MSVC 2008, for example), we #define them to the Qt equivalents. */ + +#ifdef uint64_t +#undef uint64_t +#endif + #define uint64_t QT_PREPEND_NAMESPACE(quint64) + +#ifdef uint32_t +#undef uint32_t +#endif + #define uint32_t QT_PREPEND_NAMESPACE(quint32) + +#ifdef uint8_t +#undef uint8_t +#endif + #define uint8_t QT_PREPEND_NAMESPACE(quint8) + +#ifdef int_least16_t +#undef int_least16_t +#endif + #define int_least16_t QT_PREPEND_NAMESPACE(qint16) // Header from rfc6234 with 1 modification: From 9b153f989bcc40fed85d5cbd8a489c6e0eb5c9c7 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 13:59:27 +0200 Subject: [PATCH 022/173] Compile fix: convert argument to long to match parameter comparison GCC creates a warning "enumeral and non-enumeral type in conditional expression" as the types of the two arguments don't match. Fix the compile warning by converting the first argument to (long) to match the type of the second parameter. Fix confirmed to work on NetBSD and FreeBSD, obtained from Kamil Rytarowski , NetBSD qt ports maintainer. Change-Id: I777dd066a0a8cc8a46e34bd39b256882080a7773 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 491ed993018..29c8dbb2ea5 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2159,7 +2159,7 @@ static int qt_timezone() // number of seconds west of UTC. // - It also takes DST into account, so we need to adjust it to always // get the Standard Time offset. - return -t.tm_gmtoff + (t.tm_isdst ? SECS_PER_HOUR : 0L); + return -t.tm_gmtoff + (t.tm_isdst ? (long)SECS_PER_HOUR : 0L); #else return timezone; #endif // Q_OS_WIN From 725a9c27021bef1ac3828a4eafc013a2f50e6f22 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 14:06:08 +0200 Subject: [PATCH 023/173] Compile fix: add NetBSD define for ffsll usage On NetBSD, ffsll needs to be defined to compile. The fix adds the according Q_OS_NETBSD define to the list of operating systems needing the define. Fix obtained from NetBSD port maintainer Kamil Rytarowski via IRC. Change-Id: I966a7b3fba43fb56e72f19f6b7f7cacc19c3c6cf Reviewed-by: Thiago Macieira --- src/corelib/tools/qsimd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index a1ee5b6348c..0e3359ab813 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -636,7 +636,7 @@ int ffsll(quint64 i) #endif } #endif -#elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU) +#elif defined(Q_OS_NETBSD) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU) # define ffsll __builtin_ffsll #endif From f8c3820de789a2c08dab2ddb7bf18728cdbd7028 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 15:04:01 +0200 Subject: [PATCH 024/173] Compile fix: remove unused variable bool isEmpty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The local variable isEmpty triggers a compile warning with GCC: variable ‘isEmpty’ set but not used [-Werror=unused-but-set-variable], so remove the variable assignment and declaration. Error is triggered on FreeBSD and NetBSD with gcc. Change-Id: I37bdb3408ad69093708f2d4bdb04392da66e04e5 Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemwatcher_kqueue.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index 80cbcb26cc2..9b574cbdfb5 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -166,7 +166,6 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths QStringList *files, QStringList *directories) { - bool isEmpty; QStringList p = paths; if (pathToID.isEmpty()) return p; @@ -187,7 +186,6 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths else files->removeAll(path); } - isEmpty = pathToID.isEmpty(); return p; } From e3d1058ae9de6eee4d64ea1af66571497208d8c5 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 20:15:03 +0200 Subject: [PATCH 025/173] Compile fix for NetBSD: only BSD using statvfs, disable f_flags define Compile fix for NetBSD's use of statvfs having f_flags.All other BSDs use statfs instead of statvfs, so the f_flags define needs to be prevented on NetBSD. Fix obtained from Kamil Rytarowski , NetBSD qt ports maintainer. Change-Id: Ifbd7ba0cba7f6cf280f5984c64abd7649f667332 Reviewed-by: Thiago Macieira --- src/corelib/io/qstorageinfo_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 1d1b2907b7d..c02d82a7117 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -78,7 +78,7 @@ # if !defined(ST_RDONLY) # define ST_RDONLY MNT_RDONLY # endif -# if !defined(_STATFS_F_FLAGS) +# if !defined(_STATFS_F_FLAGS) && !defined(Q_OS_NETBSD) # define _STATFS_F_FLAGS 1 # endif #elif defined(Q_OS_ANDROID) From 5f02feae05a63dbd447e491b7518b1ed45c8b711 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 22 May 2016 20:39:24 +0200 Subject: [PATCH 026/173] Compile fix: add -lexecinfo on NetBSD and OpenBSD Add -lexecinfo for backtrace(3) on NetBSD and OpenBSD. Without, qlogging.cpp linking will result in undefined references to backtrace and backtrace_symbols. The behavior required is identical to FreeBSD so no additional fixes are required (see src/corelib/global/global.pri:41) Change-Id: I3cfd1d75f1fb5b8505c08a880f91e7b39a5a650d Reviewed-by: Thiago Macieira --- mkspecs/netbsd-g++/qmake.conf | 1 + mkspecs/openbsd-g++/qmake.conf | 1 + 2 files changed, 2 insertions(+) diff --git a/mkspecs/netbsd-g++/qmake.conf b/mkspecs/netbsd-g++/qmake.conf index 04c675da24c..b470c9d08ad 100644 --- a/mkspecs/netbsd-g++/qmake.conf +++ b/mkspecs/netbsd-g++/qmake.conf @@ -61,6 +61,7 @@ QMAKE_LFLAGS_RPATH = -Wl,-rpath, QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = +QMAKE_LIBS_EXECINFO = -lexecinfo QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_THREAD = diff --git a/mkspecs/openbsd-g++/qmake.conf b/mkspecs/openbsd-g++/qmake.conf index 10330bc0815..6a66f086ed4 100644 --- a/mkspecs/openbsd-g++/qmake.conf +++ b/mkspecs/openbsd-g++/qmake.conf @@ -62,6 +62,7 @@ QMAKE_LFLAGS_NOUNDEF = -Wl,-no_unresolved QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = +QMAKE_LIBS_EXECINFO = -lexecinfo QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_THREAD = From 932cce18f72d9af99629f1bad8bd1b6114de0300 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 8 Mar 2016 12:36:14 +0100 Subject: [PATCH 027/173] QSocks5SocketEngine: connect after auth fail as if connecting afresh. If the client has responded to an earlier auth fail sensibly, further use of the socks connection probably means we have fresh credentials. So treat AuthenticatingError like Uninitialized. This makes tst_QNetworkReply::authenticationCacheAfterCancel(*+socksauth) work again. Task-number: QTBUG-51545 Change-Id: I237ca5a3194b093cc6480dd33aa7709b7b584941 Reviewed-by: Timur Pocheptsov --- src/network/socket/qsocks5socketengine.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index 6868e8c73a3..c0398a81056 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -1112,7 +1112,9 @@ bool QSocks5SocketEngine::connectInternal() } if (d->socketState != QAbstractSocket::ConnectingState) { - if (d->socks5State == QSocks5SocketEnginePrivate::Uninitialized) { + if (d->socks5State == QSocks5SocketEnginePrivate::Uninitialized + // We may have new auth credentials since an earlier failure: + || d->socks5State == QSocks5SocketEnginePrivate::AuthenticatingError) { setState(QAbstractSocket::ConnectingState); //limit buffer in internal socket, data is buffered in the external socket under application control d->data->controlSocket->setReadBufferSize(65536); From 5c6d27b8dfa695ab04766a1711b00421dba9c7d0 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 17 May 2016 12:38:44 +0200 Subject: [PATCH 028/173] Make eglfs-egldevice check work with pkgconfig as well Until now the check didn't use pkgconfig at all, but using pkgconfig alone does not work for some devices (special cases), so we have to use a combination of both here. Change-Id: Ia19a279d80a65352c467661d91a3762448c23ae6 Reviewed-by: Laszlo Agocs --- config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro b/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro index 521a9112199..d0945465a05 100644 --- a/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro +++ b/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro @@ -6,7 +6,10 @@ for(p, QMAKE_LIBDIR_EGL) { INCLUDEPATH += $$QMAKE_INCDIR_EGL LIBS += $$QMAKE_LIBS_EGL - -LIBS += -ldrm - +CONFIG += link_pkgconfig +!contains(QT_CONFIG, no-pkg-config) { + PKGCONFIG += libdrm +} else { + LIBS += -ldrm +} CONFIG -= qt From bdb1c18e411a1660f038e4f0e219d363d38e987a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 22 Mar 2016 15:32:36 +0100 Subject: [PATCH 029/173] windows: Fall back to D3D9 when 11 fails It is assumed that this happens automatically but that is not always the case. Do not become stuck with a non-functional D3D11-backed EGL environment. Instead, try again as if QT_ANGLE_PLATFORM=d3d9 was requested. Task-number: QTBUG-52056 Change-Id: I12ac6ca5f1d06f9504d05120d8e1053e97edfab3 Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowseglcontext.cpp | 71 ++++++++++++------- .../platforms/windows/qwindowseglcontext.h | 2 + 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 787a072a7a1..9ae1ca8acbe 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -347,6 +347,45 @@ QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display) { } +bool QWindowsEGLStaticContext::initializeAngle(QWindowsOpenGLTester::Renderers preferredType, HDC dc, + EGLDisplay *display, EGLint *major, EGLint *minor) +{ +#ifdef EGL_ANGLE_platform_angle + if (libEGL.eglGetPlatformDisplayEXT + && (preferredType & QWindowsOpenGLTester::AngleBackendMask)) { + const EGLint anglePlatformAttributes[][5] = { + { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE }, + { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE }, + { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, EGL_NONE } + }; + const EGLint *attributes = 0; + if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11) + attributes = anglePlatformAttributes[0]; + else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d9) + attributes = anglePlatformAttributes[1]; + else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11Warp) + attributes = anglePlatformAttributes[2]; + if (attributes) { + *display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes); + if (!libEGL.eglInitialize(*display, major, minor)) { + libEGL.eglTerminate(*display); + *display = EGL_NO_DISPLAY; + *major = *minor = 0; + return false; + } + } + } +#else // EGL_ANGLE_platform_angle + Q_UNUSED(preferredType); + Q_UNUSED(dc); + Q_UNUSED(display); + Q_UNUSED(major); + Q_UNUSED(minor); +#endif + return true; +} + QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester::Renderers preferredType) { const HDC dc = QWindowsContext::instance()->displayContext(); @@ -367,33 +406,13 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: EGLDisplay display = EGL_NO_DISPLAY; EGLint major = 0; EGLint minor = 0; -#ifdef EGL_ANGLE_platform_angle - if (libEGL.eglGetPlatformDisplayEXT - && (preferredType & QWindowsOpenGLTester::AngleBackendMask)) { - const EGLint anglePlatformAttributes[][5] = { - { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE }, - { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE }, - { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, - EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, EGL_NONE } - }; - const EGLint *attributes = 0; - if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11) - attributes = anglePlatformAttributes[0]; - else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d9) - attributes = anglePlatformAttributes[1]; - else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11Warp) - attributes = anglePlatformAttributes[2]; - if (attributes) { - display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes); - if (!libEGL.eglInitialize(display, &major, &minor)) { - display = EGL_NO_DISPLAY; - major = minor = 0; - } - } + + if (!initializeAngle(preferredType, dc, &display, &major, &minor) + && (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)) { + preferredType &= ~QWindowsOpenGLTester::AngleRendererD3d11; + initializeAngle(preferredType, dc, &display, &major, &minor); } -#else // EGL_ANGLE_platform_angle - Q_UNUSED(preferredType) -#endif + if (display == EGL_NO_DISPLAY) display = libEGL.eglGetDisplay(dc); if (!display) { diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h index 6945939941d..1a6058c9210 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.h +++ b/src/plugins/platforms/windows/qwindowseglcontext.h @@ -271,6 +271,8 @@ public: private: explicit QWindowsEGLStaticContext(EGLDisplay display); + static bool initializeAngle(QWindowsOpenGLTester::Renderers preferredType, HDC dc, + EGLDisplay *display, EGLint *major, EGLint *minor); const EGLDisplay m_display; }; From 1937a4e8b9b729e62426ce3018cc0a96a0c40972 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 23 May 2016 12:41:01 +0200 Subject: [PATCH 030/173] Add a workaround for render-to-texture widgets in fullscreen windows The performance optimization of falling back to flushing windows the normal (raster) way once no render-to-texture widgets are visible has issues with fullscreen windows, presumably due to the compositor's special handling of such windows. Disable our smartness and stick with composeAndFlush for ever in case the window is fullscreen. Change-Id: Ifb31e0d36bd0a3933fcfe55a9a7d502513d6e3cf Task-number: QTBUG-53515 Reviewed-by: Friedemann Kleint --- src/widgets/kernel/qwidgetbackingstore.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 8269bd13f6c..049ed248de7 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -1000,8 +1000,18 @@ static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) static bool switchableWidgetComposition = QGuiApplicationPrivate::instance()->platformIntegration() ->hasCapability(QPlatformIntegration::SwitchableWidgetComposition); - if (!switchableWidgetComposition) + if (!switchableWidgetComposition +// The Windows compositor handles fullscreen OpenGL window specially. Besides +// having trouble with popups, it also has issues with flip-flopping between +// OpenGL-based and normal flushing. Therefore, stick with GL for fullscreen +// windows. (QTBUG-53515) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE) + || tlw->windowState().testFlag(Qt::WindowFullScreen) +#endif + ) + { return qt_dummy_platformTextureList(); + } } return 0; From f15c0b695aa851086fac04387ed336401e7a562f Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 13 May 2016 13:33:52 +0200 Subject: [PATCH 031/173] Optimize QImage checkForAlphaPixels This routine is often called to down-convert pixmaps and backing stores to RGB32. This patch replaces a comparison in each pixel, with a single AND in each pixel and a comparison at each line. The new form is also auto- vectorized by at least GCC. Change-Id: I3e07585a3ec12f888321d35da57ac99b561dbec4 Reviewed-by: Gunnar Sletta --- src/gui/image/qimage.cpp | 49 +++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 2911477d28d..82ad9b17385 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -193,74 +193,81 @@ bool QImageData::checkForAlphaPixels() const break; case QImage::Format_ARGB32: case QImage::Format_ARGB32_Premultiplied: { - uchar *bits = data; + const uchar *bits = data; for (int y=0; y(bits)[x]; + has_alpha_pixels = (alphaAnd != 0xff000000); bits += bytes_per_line; } } break; case QImage::Format_RGBA8888: case QImage::Format_RGBA8888_Premultiplied: { - uchar *bits = data; + const uchar *bits = data; for (int y=0; y(bits)[x]; + has_alpha_pixels = (alphaAnd != 0xc0000000); bits += bytes_per_line; } } break; case QImage::Format_ARGB8555_Premultiplied: case QImage::Format_ARGB8565_Premultiplied: { - uchar *bits = data; - uchar *end_bits = data + bytes_per_line; + const uchar *bits = data; + const uchar *end_bits = data + bytes_per_line; for (int y=0; y(bits)[x]; + has_alpha_pixels = (alphaAnd != 0xf000); + bits += bytes_per_line; } } break; From 644d0e75240811212ed9fd0c21e3bd05db3ba5db Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Fri, 20 May 2016 22:03:39 +0200 Subject: [PATCH 032/173] Cleanup NIS support leftover from Qt 3/4 Qt 3/4 had NIS configure options and tests for NIS defines, those were used in QPrintDialog at the time to support NIS-printers. As the implementation went away a long time ago and no NIS featueres are implemented anywhere in Qt, the configure options and config.tests for NIS can be removed. Change-Id: Ie920e6a422540bf938623265b6ee68c793aeff84 Reviewed-by: Thiago Macieira Reviewed-by: Oswald Buddenhagen --- config.tests/unix/nis/nis.cpp | 44 ----------------------------------- config.tests/unix/nis/nis.pro | 4 ---- configure | 31 ------------------------ 3 files changed, 79 deletions(-) delete mode 100644 config.tests/unix/nis/nis.cpp delete mode 100644 config.tests/unix/nis/nis.pro diff --git a/config.tests/unix/nis/nis.cpp b/config.tests/unix/nis/nis.cpp deleted file mode 100644 index f2d7f223e32..00000000000 --- a/config.tests/unix/nis/nis.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the config.tests of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include - -int main(int, char **) -{ - char *d; - yp_get_default_domain(&d); - return 0; -} diff --git a/config.tests/unix/nis/nis.pro b/config.tests/unix/nis/nis.pro deleted file mode 100644 index b7f5693b609..00000000000 --- a/config.tests/unix/nis/nis.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = nis.cpp -CONFIG -= qt dylib -solaris-*:LIBS += -lnsl -else:LIBS += $$QMAKE_LIBS_NIS diff --git a/configure b/configure index 9d75668452d..0e0a36b00fa 100755 --- a/configure +++ b/configure @@ -708,7 +708,6 @@ CFG_LIBINPUT=auto CFG_OBSOLETE_WAYLAND=no CFG_EVDEV=auto CFG_TSLIB=auto -CFG_NIS=auto CFG_CUPS=auto CFG_ICONV=auto CFG_DBUS=auto @@ -2033,13 +2032,6 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; - nis) - if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then - CFG_NIS="$VAL" - else - UNKNOWN_OPT=yes - fi - ;; largefile) if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then CFG_LARGEFILE="$VAL" @@ -2639,9 +2631,6 @@ Additional options: -silent ............ Reduce the build output so that warnings and errors can be seen more easily. - -no-nis ............ Do not compile NIS support. - * -nis ............... Compile NIS support. - -no-cups ........... Do not compile CUPS support. * -cups .............. Compile CUPS support. Requires cups/cups.h and libcups.so.2. @@ -5014,23 +5003,6 @@ for _SQLDR in $CFG_SQL_AVAILABLE; do esac done -# auto-detect NIS support -if [ "$CFG_NIS" != "no" ]; then - if compileTest unix/nis "NIS"; then - CFG_NIS=yes - else - if [ "$CFG_NIS" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then - echo "NIS support cannot be enabled due to functionality tests!" - echo " Turn on verbose messaging (-v) to $0 to see the final report." - echo " If you believe this message is in error you may use the continue" - echo " switch (-continue) to $0 to continue." - exit 101 - else - CFG_NIS=no - fi - fi -fi - # auto-detect CUPS support if [ "$CFG_CUPS" != "no" ]; then if compileTest unix/cups "Cups"; then @@ -6444,7 +6416,6 @@ elif [ "$CFG_ZLIB" = "system" ]; then fi [ "$CFG_MTDEV" = "yes" ] && QT_CONFIG="$QT_CONFIG mtdev" -[ "$CFG_NIS" = "yes" ] && QT_CONFIG="$QT_CONFIG nis" [ "$CFG_CUPS" = "yes" ] && QT_CONFIG="$QT_CONFIG cups" [ "$CFG_ICONV" = "yes" ] && QT_CONFIG="$QT_CONFIG iconv" [ "$CFG_ICONV" = "sun" ] && QT_CONFIG="$QT_CONFIG sun-libiconv" @@ -6869,7 +6840,6 @@ QMakeVar set sql-plugins "$SQL_PLUGINS" [ "$CFG_INOTIFY" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_INOTIFY" [ "$CFG_EVENTFD" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_EVENTFD" [ "$CFG_CLOEXEC" = "yes" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_THREADSAFE_CLOEXEC=1" -[ "$CFG_NIS" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_NIS" [ "$CFG_OPENSSL" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_OPENSSL" [ "$CFG_OPENSSL" = "linked" ]&& QCONFIG_FLAGS="$QCONFIG_FLAGS QT_LINKED_OPENSSL" [ "$CFG_OPENSSL" = "no" ] && [ "$CFG_SECURETRANSPORT" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_SSL" @@ -7341,7 +7311,6 @@ report_support " libproxy.............." "$CFG_LIBPROXY" report_support " OpenSSL .............." "$CFG_OPENSSL" yes "loading libraries at run-time" linked "linked to the libraries" [ "$XPLATFORM_MAC" = "yes" ] && \ report_support " SecureTransport ......" "$CFG_SECURETRANSPORT" -report_support " NIS ...................." "$CFG_NIS" report_support " OpenGL / OpenVG:" report_support " EGL .................." "$CFG_EGL" report_support " OpenGL ..............." "$CFG_OPENGL" yes "Desktop OpenGL" es2 "OpenGL ES 2.0+" From ffd99e1d1803a8b82eab8d8b6c1cd9e58af36ee5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 23 May 2016 14:27:05 +0200 Subject: [PATCH 033/173] Add section "Getting Started" to QPlatformHeader's documentation. Change-Id: Id57c65a5f5281ed0ff8f4e5876cf121781f2ae90 Reviewed-by: Andy Shaw --- src/platformheaders/doc/src/qtplatformheaders.qdoc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/platformheaders/doc/src/qtplatformheaders.qdoc b/src/platformheaders/doc/src/qtplatformheaders.qdoc index 89c2394bdc3..d2caa5b2124 100644 --- a/src/platformheaders/doc/src/qtplatformheaders.qdoc +++ b/src/platformheaders/doc/src/qtplatformheaders.qdoc @@ -80,6 +80,19 @@ \sa QXcbWindowFunctions QWindowsWindowFunctions + \section1 Getting Started + + To include the definitions of the module's functions and classes, use the following directives: + \code + #include + #include + \endcode + + As the module is header-only, no further modifications to the .pro files are required to use it. + + \note The module name (\c QtPlatformHeaders) must appear in the \c #include directive. + \note It is not necessary to enclose the code in \c #ifdef directives depending on platform. + \section1 API Reference \list \li \l{Qt Platform Headers C++ Classes}{C++ Classes} From 3cae115d6d6e8a1d4d0385e3cde16f59b25acad0 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 27 Apr 2016 11:53:16 +0200 Subject: [PATCH 034/173] Correct compositionMode documentation Most composition modes require an alpha-channel to be meaningful, but not all, and there is no requirements of specific formats. Change-Id: I11e930ccc07e9ff5df06dbda6745e4afb79f5e08 Reviewed-by: Leena Miettinen Reviewed-by: Gunnar Sletta --- src/gui/painting/qpainter.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 1acd84754af..51c0f3e22a9 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -2182,11 +2182,10 @@ void QPainter::setBrushOrigin(const QPointF &p) destination pixel in such a way that the alpha component of the source defines the translucency of the pixel. - When the paint device is a QImage, the image format must be set to - \l {QImage::Format}{Format_ARGB32_Premultiplied} or - \l {QImage::Format}{Format_ARGB32} for the composition modes to have - any effect. For performance the premultiplied version is the preferred - format. + Several composition modes require an alpha channel in the source or + target images to have an effect. For optimal performance the + image format \l {QImage::Format}{Format_ARGB32_Premultiplied} is + preferred. When a composition mode is set it applies to all painting operator, pens, brushes, gradients and pixmap/image drawing. From cf6a2e96175b7ec2be757ae247ffd86e28ac563b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 22 May 2016 11:18:34 -0700 Subject: [PATCH 035/173] forkfd: Make sure we handle SIGPIPE too We can't depend on the application/library ignoring the signal for us, so we do it. O_NOSIGPIPE exists on the BSDs and I'll add it to Linux. If it isn't supported, then we need to ignore SIGPIPE globally. Change-Id: I25d85d86649448d5b2b3fffd1450f6afeaea8b18 Reviewed-by: Ralf Nolden Reviewed-by: Rafael Roquetto --- src/3rdparty/forkfd/forkfd.c | 39 ++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index fef710a79e6..9284a67674a 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -410,6 +410,26 @@ chain_handler: old_sigaction.sa_handler(signum); } +static void ignore_sigpipe() +{ +#ifdef O_NOSIGPIPE + static ffd_atomic_int done = FFD_ATOMIC_INIT(0); + if (ffd_atomic_load(&done, FFD_ATOMIC_RELAXED)) + return; +#endif + + struct sigaction action; + memset(&action, 0, sizeof action); + sigemptyset(&action.sa_mask); + action.sa_handler = SIG_IGN; + action.sa_flags = 0; + sigaction(SIGPIPE, &action, NULL); + +#ifdef O_NOSIGPIPE + ffd_atomic_store(&done, 1, FFD_ATOMIC_RELAXED); +#endif +} + static void forkfd_initialize() { #if defined(HAVE_BROKEN_WAITID) @@ -446,6 +466,11 @@ static void forkfd_initialize() */ sigaction(SIGCHLD, &action, &old_sigaction); +#ifndef O_NOSIGPIPE + /* disable SIGPIPE too */ + ignore_sigpipe(); +#endif + #ifndef __GNUC__ atexit(cleanup); #endif @@ -486,13 +511,23 @@ static void cleanup() static int create_pipe(int filedes[], int flags) { - int ret; + int ret = -1; #ifdef HAVE_PIPE2 /* use pipe2(2) whenever possible, since it can thread-safely create a * cloexec pair of pipes. Without it, we have a race condition setting * FD_CLOEXEC */ - ret = pipe2(filedes, O_CLOEXEC); + +# ifdef O_NOSIGPIPE + /* try first with O_NOSIGPIPE */ + ret = pipe2(filedes, O_CLOEXEC | O_NOSIGPIPE); + if (ret == -1) { + /* O_NOSIGPIPE not supported, ignore SIGPIPE */ + ignore_sigpipe(); + } +# endif + if (ret == -1) + ret = pipe2(filedes, O_CLOEXEC); if (ret == -1) return ret; From f156c81d7fada47835f4ebce9f70f8b1bdb01201 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 May 2016 10:30:45 -0700 Subject: [PATCH 036/173] Restore the -fno-lto build of qversiontagging.cpp I'm not sure how one of my machines has this problem and the other doesn't (same distribution and same compiler version). Must be operator error. But this is required to compile QtGui when QtCore was compiled in LTO mode. qversiontagging.cpp used to be built with -fno-lto before commit 629ceec208ad5fe9f5d201fc42fce611e55c567d. This commit restores that functionality, but not the clang "-no-integrated-as" part. Change-Id: Ie9fd7afe060b4e4a8052fffd144fb9c1a1166854 Reviewed-by: Oswald Buddenhagen --- src/corelib/global/global.pri | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index dd846955f61..6a8948822c8 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -28,8 +28,9 @@ SOURCES += \ global/qmalloc.cpp \ global/qnumeric.cpp \ global/qlogging.cpp \ - global/qhooks.cpp \ - global/qversiontagging.cpp + global/qhooks.cpp + +VERSIONTAGGING_SOURCES = global/qversiontagging.cpp # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global @@ -63,3 +64,21 @@ journald { syslog { DEFINES += QT_USE_SYSLOG } + +gcc:ltcg { + versiontagging_compiler.commands = $$QMAKE_CXX -c $(CXXFLAGS) $(INCPATH) + + # Disable LTO, as the symbols disappear somehow under GCC + versiontagging_compiler.commands += -fno-lto + + versiontagging_compiler.commands += -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} + versiontagging_compiler.dependency_type = TYPE_C + versiontagging_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + versiontagging_compiler.input = VERSIONTAGGING_SOURCES + versiontagging_compiler.variable_out = OBJECTS + versiontagging_compiler.name = compiling[versiontagging] ${QMAKE_FILE_IN} + silent: versiontagging_compiler.commands = @echo compiling[versiontagging] ${QMAKE_FILE_IN} && $$versiontagging_compiler.commands + QMAKE_EXTRA_COMPILERS += versiontagging_compiler +} else { + SOURCES += $$VERSIONTAGGING_SOURCES +} From 40074bc985f1fa5c859dc48aed84b48d4c17fff3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 19 May 2016 13:26:29 +0200 Subject: [PATCH 037/173] Bump version Change-Id: I944b2a5e1b377fb2d39f9cbf549e1a9c01894cde Reviewed-by: Joerg Bornemann --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 50d27cf9ce1..1e64c2e238e 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ CONFIG += warning_clean QT_SOURCE_TREE = $$PWD QT_BUILD_TREE = $$shadowed($$PWD) -MODULE_VERSION = 5.6.1 +MODULE_VERSION = 5.6.2 From d6905b2ada509cbe2322f65b862af3b99b79b792 Mon Sep 17 00:00:00 2001 From: Venugopal Shivashankar Date: Thu, 12 May 2016 11:08:02 +0200 Subject: [PATCH 038/173] Add changelog for 5.6.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Done-with: Oswald Buddenhagen Change-Id: Ia29cc9b578ef0a6094d43759b504640c3843eb28 Reviewed-by: Topi Reiniö --- dist/changes-5.6.1 | 165 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 dist/changes-5.6.1 diff --git a/dist/changes-5.6.1 b/dist/changes-5.6.1 new file mode 100644 index 00000000000..c256f363052 --- /dev/null +++ b/dist/changes-5.6.1 @@ -0,0 +1,165 @@ +Qt 5.6.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.6.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + https://doc.qt.io/qt-5/ + +The Qt version 5.6 series is binary compatible with the 5.5.x series. +Applications compiled for 5.5 will continue to run with 5.6. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Important Behavior Changes * +**************************************************************************** + + - Support for DirectFB is disabled by default, due to lack of + development in upstream. To enable the platform plugin, pass the + -directfb option to configure. + - [QTBUG-44964] The new X event compression feature that was added in 5.6.0 + no longer applies to motion events from drawing tablets. + +configure & build system +------------------------ + + - The configure -D/-I/-L/-l/-R options do not affect the build of Qt's + host tools any more when cross-building. While this usually improves + the chances of a build succeeding, it may also require adjustments. + +qmake +----- + + - [Unix] Paths passed to configure -R are not automatically used by 3rd + party projects any more. Use QMAKE_RPATHDIR if your project explicitly + depends on external libraries. Note that this is not needed for Qt or + its transitive dependencies. + - Expansions of ${QMAKE_FILE_IN_BASE} and ${QMAKE_FILE_OUT_BASE} in extra + compilers are now automatically quoted. + +**************************************************************************** +* Library * +**************************************************************************** + +QtCore +------ + + - QObject: + * [QTBUG-52542] If the compiler supports variadic templates, functors + connected to signals will no longer be copied each time the signal is + emitted. + + - QRect: + * Fixed integer overflow in center(). This fixes the result for some + corner-cases such as a 1x1 rectangle at (INT_MIN, INT_MIN), for which the + previous implementation could return anything (due to invoking undefined + behavior), but commonly returned (0, 0). + + - QStringRef: + * Fixed relational operators against (const char*) to return the correct + result. + +QtGui +----- + + - [QTBUG-50199] QWheelEvent::phase() now returns zero rather than + Qt::ScrollUpdate when the wheel event comes from an actual non-emulated + mouse wheel, and the QT_ENABLE_MOUSE_WHEEL_TRACKING environment variable + is set. + +- Image: + * [QTBUG-50745] Fixed possible crash in QImage::pixel() for mono or indexed + images. + +QtWidgets +--------- + + - Dialogs: + * [QTBUG-51148] Fixed font dialog support for fonts with a non-existent + family name and/or pixel size. + + - QHeaderView: + * [QTBUG-50171] Fixed a repainting issue when items had been reordered. + + - QListWidget: + * [QTBUG-15741] Fixed a bug that caused the default drop action to be + ignored when using icon mode. + + +**************************************************************************** +* Platform-specific Changes * +**************************************************************************** + +Android +------- + + - The navigation bar is now hidden only on Android API level 19 and above. + +OS X +---- + - [QTBUG-50262] QStandardPaths now returns the correct display name for the + download folder. + - [QTBUG-7000] QMacPrintEngine now really sets the printer resolution. + - [QTBUG-48138] QPinchGesture on OS X now behaves like on other platforms: + totalScaleFactor is the magnitude of the pinch and scaleFactor is the delta + for the current event. + +Windows +------- + + - Text: + * [QTBUG-18711] Fixed disabling hints for application fonts. + For example, when automatic scaling by device pixel ratio is in effect. + * [QTBUG-47141] Made it possible to disable antialiasing for text when + drawing into images. + +X11/XCB +------- + + - [QTBUG-49071] Fixed failure to deliver focusIn events on hide/show. + +**************************************************************************** +* Tools * +**************************************************************************** + +configure & build system +------------------------ + + - [QTBUG-11545][Windows] Added missing -pch/-no-pch options to configure.exe. + - [QTBUG-37952][Apple] configure -separate-debug-info is now supported. + - [QTBUG-47313][QTBUG-47639] Fixed builds with "debug" and/or "release" in + the build path's name. + - [QTBUG-51621][Unix] Fixed transitive dependencies on non-Qt libraries. + - [QTBUG-51644][QTBUG-53017] Fixed cross-builds which use a host compiler + which is significantly different from the target compiler. + - [QTBUG-52578][QNX] Unified some defaults between the Unix and Windows + configures. + - [Unix] configure -R now supports paths relative to -libdir. + - [Android@Windows] Added missing -android-ndk-host option to configure.exe. + - [MinGW] Fixed -release -force-debug-info builds actually being neither. + - [WinCE] Fixed (Open)SSL detection. + - Fixed builds with static libc. + +qmake +----- + + - [QTBUG-34182] Fixed UTF-8 BOM breaking dependency calculation. + - [QTBUG-38802][WinRT] Capabilities needed by Qt are now automatically + added to the manifest. + - [QTBUG-50924][WEC7][VS] Fixed deployment of Qt. + - [QTBUG-51775][Unix@Windows] Fixed installation of target.targets when + cross-building. + - [QTBUG-51782] Fixed simultaneous use of the separate_debug_info and + no_plugin_name_prefix CONFIG flags. + - [QTBUG-52008] qmake-generated Visual Studio projects now automatically + invoke windeployqt by default. + - [QTBUG-52998] Restored use of -P option when invoking lex. + - The expansions ${QMAKE_FILE_IN_EXT}, ${QMAKE_FILE_IN_NAME}, and + ${QMAKE_FILE_OUT_PATH} are now understood in extra compilers. From a324194b5965b4232b01e38c32741eadc130e8d1 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 28 Apr 2016 16:18:15 +0200 Subject: [PATCH 039/173] QWidgetLineControl::Command - delete default ctor. While dealing with Coverity's CID 11424 ('missing initializer'), it was recommended (by Marc, thanks) to get rid of Command's default ctor, since it's apparently not needed at all (replacing QVector with std::vector also). Change-Id: Ibe9d2789c67431a9810feb7db4fa1bce0b61921c Reviewed-by: Marc Mutz --- src/widgets/widgets/qwidgetlinecontrol.cpp | 18 +++++++++--------- src/widgets/widgets/qwidgetlinecontrol_p.h | 5 +++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index 9097ad01a86..918b6e8c816 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -697,7 +697,7 @@ bool QWidgetLineControl::finishChange(int validateFromState, bool update, bool e if (m_transactions.count()) return false; internalUndo(validateFromState); - m_history.resize(m_undoState); + m_history.erase(m_history.begin() + m_undoState, m_history.end()); if (m_modifiedState > m_undoState) m_modifiedState = -1; m_validInput = true; @@ -776,14 +776,14 @@ void QWidgetLineControl::internalSetText(const QString &txt, int pos, bool edite */ void QWidgetLineControl::addCommand(const Command &cmd) { - if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) { - m_history.resize(m_undoState + 2); - m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend); - } else { - m_history.resize(m_undoState + 1); - } + m_history.erase(m_history.begin() + m_undoState, m_history.end()); + + if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) + m_history.push_back(Command(Separator, m_cursor, 0, m_selstart, m_selend)); + m_separator = false; - m_history[m_undoState++] = cmd; + m_history.push_back(cmd); + m_undoState = int(m_history.size()); } /*! @@ -1914,7 +1914,7 @@ bool QWidgetLineControl::isRedoAvailable() const // Same as with undo. Disabled for password modes. return !m_readOnly && m_echoMode == QLineEdit::Normal - && m_undoState < m_history.size(); + && m_undoState < int(m_history.size()); } QT_END_NAMESPACE diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h index 039453f0d56..3d8df9e3ff4 100644 --- a/src/widgets/widgets/qwidgetlinecontrol_p.h +++ b/src/widgets/widgets/qwidgetlinecontrol_p.h @@ -61,6 +61,8 @@ #include "qplatformdefs.h" +#include + #ifdef DrawText # undef DrawText #endif @@ -461,7 +463,6 @@ private: // undo/redo handling enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection }; struct Command { - inline Command() {} inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {} uint type : 4; QChar uc; @@ -469,7 +470,7 @@ private: }; int m_modifiedState; int m_undoState; - QVector m_history; + std::vector m_history; void addCommand(const Command& cmd); inline void separate() { m_separator = true; } From b092f681cf571a1c3068007d1a46633e5ab8b52f Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 19 May 2016 16:49:45 -0700 Subject: [PATCH 040/173] QNSView: Reset the internal buttons state after dragging ends We only track left and right mouse buttons when dragging. But some applications may do this with other mouse buttons. In this case, instead of tracking which button was pressed and which one was released, we just ask Cocoa for the current state. Change-Id: I0df7799b7ae6d7816377f881bc0ede867737d245 Task-number: QTBUG-53374 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qnsview.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 0d58faa5bf0..6117e3f2e9e 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -2070,7 +2070,11 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin // keep our state, and QGuiApplication state (buttons member) in-sync, // or future mouse events will be processed incorrectly - m_buttons &= ~(m_sendUpAsRightButton ? Qt::RightButton : Qt::LeftButton); + NSUInteger pmb = [NSEvent pressedMouseButtons]; + for (int buttonNumber = 0; buttonNumber < 32; buttonNumber++) { // see cocoaButton2QtButton() for the 32 value + if (!(pmb & (1 << buttonNumber))) + m_buttons &= ~cocoaButton2QtButton(buttonNumber); + } NSPoint windowPoint = [self convertPoint: point fromView: nil]; QPoint qtWindowPoint(windowPoint.x, windowPoint.y); From 17a4384d120e8bc242f2f0d6c3559609e7547030 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 23 May 2016 15:35:17 +0200 Subject: [PATCH 041/173] iOS: ensure we don't break UIKit IM state when sending key events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to be careful about calling textDidChange on the input delegate, since that will reset the internal IM state in UIKit and stop any ongoing text composition or spell checking. For that reason we set m_inSendEventToFocusObject to true whenever we send an IM event to Qt, to not call the abovementioned method when callbacks from UIKit is the reason for changing the text. But until now we never applied the same protection for key events. This lead to ligatures not working correctly (e.g when using Korean IM), since UIKit composes ligatures by first selecting the characters that can be truncated, then do a deleteBackwards, then insert the ligature. And deleteBackwards leads us to send backspace key events, which ends up in a textDidChange call, which confuses UIKit. This patch will ensure we don't call textDidChange as a result of sending key events. Task-number: QTBUG-52486 Change-Id: Ida268edae517f55a5b5f975340a5d3821f7b8f52 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 320b1cac61d..0cf505930f6 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -353,6 +353,7 @@ - (void)sendKeyPressRelease:(Qt::Key)key modifiers:(Qt::KeyboardModifiers)modifiers { + QScopedValueRollback rollback(m_inSendEventToFocusObject, true); QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyPress, key, modifiers); QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyRelease, key, modifiers); QWindowSystemInterface::flushWindowSystemEvents(); From 9ebe146feec91756280d03b08deaa2b17044cf48 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 4 May 2016 16:19:15 +0200 Subject: [PATCH 042/173] build qt-png as a proper helper library it ends up in QtGui via two different routes (freetype and the png handler), and we really don't want to have two copies of it in there. Change-Id: I40760bcb6c615b90ed9f402450bb657c77884613 Reviewed-by: Simon Hausmann --- src/3rdparty/freetype/freetype.pro | 9 ++------- src/3rdparty/libpng.pri | 21 --------------------- src/3rdparty/libpng/libpng.pro | 30 ++++++++++++++++++++++++++++++ src/3rdparty/png_dependency.pri | 3 ++- src/src.pro | 9 +++++++++ 5 files changed, 43 insertions(+), 29 deletions(-) delete mode 100644 src/3rdparty/libpng.pri create mode 100644 src/3rdparty/libpng/libpng.pro diff --git a/src/3rdparty/freetype/freetype.pro b/src/3rdparty/freetype/freetype.pro index e85ed1699bb..41ca4695769 100644 --- a/src/3rdparty/freetype/freetype.pro +++ b/src/3rdparty/freetype/freetype.pro @@ -68,12 +68,7 @@ DEFINES += FT2_BUILD_LIBRARY DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB include(../zlib_dependency.pri) -contains(QT_CONFIG, system-png) { - DEFINES += FT_CONFIG_OPTION_USE_PNG - include($$PWD/../png_dependency.pri) -} else:!contains(QT_CONFIG, no-png):!win32 { - DEFINES += FT_CONFIG_OPTION_USE_PNG - include($$PWD/../libpng.pri) -} +DEFINES += FT_CONFIG_OPTION_USE_PNG +include($$PWD/../png_dependency.pri) DEFINES += TT_CONFIG_OPTION_SUBPIXEL_HINTING diff --git a/src/3rdparty/libpng.pri b/src/3rdparty/libpng.pri deleted file mode 100644 index a5fe32f867a..00000000000 --- a/src/3rdparty/libpng.pri +++ /dev/null @@ -1,21 +0,0 @@ -DEFINES += PNG_ARM_NEON_OPT=0 -INCLUDEPATH += $$PWD/libpng -SOURCES += $$PWD/libpng/png.c \ - $$PWD/libpng/pngerror.c \ - $$PWD/libpng/pngget.c \ - $$PWD/libpng/pngmem.c \ - $$PWD/libpng/pngpread.c \ - $$PWD/libpng/pngread.c \ - $$PWD/libpng/pngrio.c \ - $$PWD/libpng/pngrtran.c \ - $$PWD/libpng/pngrutil.c \ - $$PWD/libpng/pngset.c \ - $$PWD/libpng/pngtrans.c \ - $$PWD/libpng/pngwio.c \ - $$PWD/libpng/pngwrite.c \ - $$PWD/libpng/pngwtran.c \ - $$PWD/libpng/pngwutil.c - -TR_EXCLUDE += $$PWD/* - -include($$PWD/zlib_dependency.pri) diff --git a/src/3rdparty/libpng/libpng.pro b/src/3rdparty/libpng/libpng.pro new file mode 100644 index 00000000000..7d51c30cb4d --- /dev/null +++ b/src/3rdparty/libpng/libpng.pro @@ -0,0 +1,30 @@ +TARGET = qtpng + +CONFIG += \ + static \ + hide_symbols \ + exceptions_off rtti_off warn_off + +load(qt_helper_lib) + +DEFINES += PNG_ARM_NEON_OPT=0 +SOURCES += \ + png.c \ + pngerror.c \ + pngget.c \ + pngmem.c \ + pngpread.c \ + pngread.c \ + pngrio.c \ + pngrtran.c \ + pngrutil.c \ + pngset.c \ + pngtrans.c \ + pngwio.c \ + pngwrite.c \ + pngwtran.c \ + pngwutil.c + +TR_EXCLUDE += $$PWD/* + +include(../zlib_dependency.pri) diff --git a/src/3rdparty/png_dependency.pri b/src/3rdparty/png_dependency.pri index 78da861f775..eb32432b49e 100644 --- a/src/3rdparty/png_dependency.pri +++ b/src/3rdparty/png_dependency.pri @@ -2,5 +2,6 @@ contains(QT_CONFIG, system-png) { unix|mingw: LIBS_PRIVATE += -lpng else: LIBS += libpng.lib } else: contains(QT_CONFIG, png) { - include($$PWD/libpng.pri) + INCLUDEPATH += $$PWD/libpng + LIBS_PRIVATE += -L$$QT_BUILD_TREE/lib -lqtpng$$qtPlatformTargetSuffix() } diff --git a/src/src.pro b/src/src.pro index 71347dc009c..585767361e7 100644 --- a/src/src.pro +++ b/src/src.pro @@ -88,6 +88,9 @@ src_3rdparty_harfbuzzng.subdir = $$PWD/3rdparty/harfbuzz-ng src_3rdparty_harfbuzzng.target = sub-3rdparty-harfbuzzng src_3rdparty_harfbuzzng.depends = src_corelib # for the Qt atomics +src_3rdparty_libpng.subdir = $$PWD/3rdparty/libpng +src_3rdparty_libpng.target = sub-3rdparty-libpng + src_3rdparty_freetype.subdir = $$PWD/3rdparty/freetype src_3rdparty_freetype.target = sub-3rdparty-freetype @@ -132,6 +135,7 @@ src_android.subdir = $$PWD/android contains(QT_CONFIG, zlib)|cross_compile { SUBDIRS += src_qtzlib contains(QT_CONFIG, zlib) { + src_3rdparty_libpng.depends += src_corelib src_3rdparty_freetype.depends += src_corelib } } @@ -163,6 +167,11 @@ contains(QT_CONFIG, concurrent):SUBDIRS += src_concurrent SUBDIRS += src_angle src_gui.depends += src_angle } + contains(QT_CONFIG, png) { + SUBDIRS += src_3rdparty_libpng + src_3rdparty_freetype.depends += src_3rdparty_libpng + src_plugins.depends += src_3rdparty_libpng + } contains(QT_CONFIG, freetype) { SUBDIRS += src_3rdparty_freetype src_platformsupport.depends += src_3rdparty_freetype From 459933708a2ead6bedb0e2a47fcea474edfa07b8 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 24 May 2016 15:53:04 +0200 Subject: [PATCH 043/173] Do an actual toString conversion for QVariant test failures A cast is not a conversion. If the value is not already a string type we are just getting an empty string for all metatypes that can be converted to string. Change-Id: I4643cc9fd509c21568fdc2133403c3ed8cb38a10 Reviewed-by: Simon Hausmann --- src/testlib/qtest.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index c35b7678758..6ab8d3d96bf 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -160,7 +160,7 @@ template<> inline char *toString(const QVariant &v) if (!v.isNull()) { vstring.append(','); if (v.canConvert(QVariant::String)) { - vstring.append(qvariant_cast(v).toLocal8Bit()); + vstring.append(v.toString().toLocal8Bit()); } else { vstring.append(""); From c96ddd9ee553b89bdd0073d273312d40771006bd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 23 May 2016 09:41:06 +0200 Subject: [PATCH 044/173] QWindowsTheme: Suppress error dialogs when calling SHGetFileInfo(). Set the error mode flag SEM_NOOPENFILEERRORBOX when calling Win32 API SHGetFileInfo() to prevent it from prompting to insert media as does QStorageInfoPrivate::mountedVolumes(). Task-number: QTBUG-32457 Task-number: QTBUG-48823 Change-Id: I01a2f99b5a75b39dd729509ca319f634e3dcd695 Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/windows/qwindowstheme.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 4a13f646f28..f673ce5c25e 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -132,7 +132,16 @@ public: explicit ShGetFileInfoFunction(const wchar_t *fn, DWORD a, SHFILEINFO *i, UINT f, bool *r) : m_fileName(fn), m_attributes(a), m_flags(f), m_info(i), m_result(r) {} - void operator()() const { *m_result = SHGetFileInfo(m_fileName, m_attributes, m_info, sizeof(SHFILEINFO), m_flags); } + void operator()() const + { +#ifndef Q_OS_WINCE + const UINT oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); +#endif + *m_result = SHGetFileInfo(m_fileName, m_attributes, m_info, sizeof(SHFILEINFO), m_flags); +#ifndef Q_OS_WINCE + SetErrorMode(oldErrorMode); +#endif + } private: const wchar_t *m_fileName; From 61521b64a4b9fc1046e0d16cb84c6181ae85493c Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 23 May 2016 13:32:59 +0200 Subject: [PATCH 045/173] Avoid missing paints when resizing GV with QOpenGLWidget viewport There is nothing guaranteeing there will be a paint request after resizeViewportFramebuffer() is called. However we must not be left with a framebuffer with uninitialized content. So trigger an update. Include also a half-hearted autotest. QOpenGLWidget (or QGLWidget) viewports have not been autotested at all. Try to verify that it is functional at least, even if we cannot check the actual output. Change-Id: I34d78fe32e94c39dad919216b5a4f4bb2aea3cc2 Task-number: QTBUG-52419 Reviewed-by: Friedemann Kleint Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qopenglwidget.cpp | 4 +- .../qgraphicsview/tst_qgraphicsview.cpp | 45 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index e5c5b1dbfd7..1d48be5198e 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -904,8 +904,10 @@ void QOpenGLWidgetPrivate::resizeViewportFramebuffer() if (!initialized) return; - if (!fbo || q->size() * q->devicePixelRatioF() != fbo->size()) + if (!fbo || q->size() * q->devicePixelRatioF() != fbo->size()) { recreateFbo(); + q->update(); + } } /*! diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 98473fb5cc1..f5083795c76 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -54,6 +54,9 @@ #include #include #include +#ifndef QT_NO_OPENGL +#include +#endif #include #include #include "../../../shared/platforminputcontext.h" @@ -161,6 +164,9 @@ private slots: void sceneRect_growing(); void setSceneRect(); void viewport(); +#ifndef QT_NO_OPENGL + void openGLViewport(); +#endif void dragMode_scrollHand(); void dragMode_rubberBand(); void rubberBandSelectionMode(); @@ -675,6 +681,45 @@ void tst_QGraphicsView::viewport() QTest::qWait(25); } +#ifndef QT_NO_OPENGL +void tst_QGraphicsView::openGLViewport() +{ + QGraphicsScene scene; + scene.setBackgroundBrush(Qt::white); + scene.addText("GraphicsView"); + scene.addEllipse(QRectF(400, 50, 50, 50)); + scene.addEllipse(QRectF(-100, -400, 50, 50)); + scene.addEllipse(QRectF(50, -100, 50, 50)); + scene.addEllipse(QRectF(-100, 50, 50, 50)); + + QGraphicsView view(&scene); + view.setSceneRect(-400, -400, 800, 800); + view.resize(400, 400); + + QOpenGLWidget *glw = new QOpenGLWidget; + QSignalSpy spy1(glw, SIGNAL(resized())); + QSignalSpy spy2(glw, SIGNAL(frameSwapped())); + + view.setViewport(glw); + + view.show(); + QTest::qWaitForWindowExposed(&view); + QTRY_VERIFY(spy1.count() > 0); + QTRY_VERIFY(spy2.count() >= spy1.count()); + spy1.clear(); + spy2.clear(); + + // Now test for resize (QTBUG-52419). This is special when the viewport is + // a QOpenGLWidget since the underlying FBO must also be maintained. + view.resize(300, 300); + QTRY_VERIFY(spy1.count() > 0); + QTRY_VERIFY(spy2.count() >= spy1.count()); + // There is no sane way to check if the framebuffer contents got updated + // (grabFramebuffer is no good for the viewport case as that does not go + // through paintGL). So skip the actual verification. +} +#endif + void tst_QGraphicsView::dragMode_scrollHand() { for (int j = 0; j < 2; ++j) { From e9041c7fc1052167f1ec2df0ea9623059e55d00f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 28 Apr 2016 22:09:01 -0700 Subject: [PATCH 046/173] Fix parsing of tzfile(5) POSIX rule zone names with bracket quotes POSIX.1-2001 allows quoting a zone name so that it can contain other characters besides letters, by enclosing it in angle brackets ('<' and '>'). This hadn't been used until recently (tzdata2016b), when the Asia/Barnaul rule started using a zone name "+07" (the name variable contained the value "<+07>-7"). Thanks to Paul Eggert for reporting and investigating the root cause. Task-number: QTBUG-53071 Change-Id: Id5480807d25e49e78b79ffff1449bc410776cb66 Reviewed-by: Edward Welbourne Reviewed-by: Lars Knoll --- src/corelib/tools/qtimezoneprivate_tz.cpp | 174 ++++++++++++------ .../corelib/tools/qtimezone/tst_qtimezone.cpp | 10 + 2 files changed, 129 insertions(+), 55 deletions(-) diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 85ed3458694..cb9581ab638 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -41,6 +41,8 @@ #include +#include "qlocale_tools_p.h" + #include QT_BEGIN_NAMESPACE @@ -384,25 +386,100 @@ static QTime parsePosixTime(const QByteArray &timeRule) return QTime(2, 0, 0); } -static int parsePosixOffset(const QByteArray &timeRule) +static int parsePosixOffset(const char *begin, const char *end) { // Format "[+|-]hh[:mm[:ss]]" - QList parts = timeRule.split(':'); - int count = parts.count(); - if (count == 3) { - int hour = parts.at(0).toInt(); - int sign = hour >= 0 ? -1 : 1; - return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60) + parts.at(2).toInt()); - } else if (count == 2) { - int hour = parts.at(0).toInt(); - int sign = hour >= 0 ? -1 : 1; - return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60)); - } else if (count == 1) { - int hour = parts.at(0).toInt(); - int sign = hour >= 0 ? -1 : 1; - return sign * (qAbs(hour) * 60 * 60); + int hour, min = 0, sec = 0; + + // note that the sign is inverted because POSIX counts in hours West of GMT + bool negate = true; + if (*begin == '+') { + ++begin; + } else if (*begin == '-') { + negate = false; + ++begin; } - return 0; + + bool ok = false; + hour = qstrtoll(begin, &begin, 10, &ok); + if (!ok) + return INT_MIN; + if (begin < end && *begin == ':') { + // minutes + ++begin; + min = qstrtoll(begin, &begin, 10, &ok); + if (!ok || min < 0) + return INT_MIN; + + if (begin < end && *begin == ':') { + // seconds + ++begin; + sec = qstrtoll(begin, &begin, 10, &ok); + if (!ok || sec < 0) + return INT_MIN; + } + } + + // we must have consumed everything + if (begin != end) + return INT_MIN; + + int value = (hour * 60 + min) * 60 + sec; + return negate ? -value : value; +} + +static inline bool asciiIsLetter(char ch) +{ + ch |= 0x20; // lowercases if it is a letter, otherwise just corrupts ch + return ch >= 'a' && ch <= 'z'; +} + +// Returns the zone name, the offset (in seconds) and advances \a begin to +// where the parsing ended. Returns a zone of INT_MIN in case an offset +// couldn't be read. +static QPair parsePosixZoneNameAndOffset(const char *&pos, const char *end) +{ + static const char offsetChars[] = "0123456789:"; + QPair result = qMakePair(QString(), INT_MIN); + + const char *nameBegin = pos; + const char *nameEnd; + Q_ASSERT(pos < end); + + if (*pos == '<') { + nameBegin = pos + 1; // skip the '<' + nameEnd = nameBegin; + while (nameEnd < end && *nameEnd != '>') { + // POSIX says only alphanumeric, but we allow anything + ++nameEnd; + } + pos = nameEnd + 1; // skip the '>' + } else { + nameBegin = pos; + nameEnd = nameBegin; + while (nameEnd < end && asciiIsLetter(*nameEnd)) + ++nameEnd; + pos = nameEnd; + } + if (nameEnd - nameBegin < 3) + return result; // name must be at least 3 characters long + + // zone offset, form [+-]hh:mm:ss + const char *zoneBegin = pos; + const char *zoneEnd = pos; + if (zoneEnd < end && (zoneEnd[0] == '+' || zoneEnd[0] == '-')) + ++zoneEnd; + while (zoneEnd < end) { + if (strchr(offsetChars, char(*zoneEnd)) == NULL) + break; + ++zoneEnd; + } + + result.first = QString::fromUtf8(nameBegin, nameEnd - nameBegin); + if (zoneEnd > zoneBegin) + result.second = parsePosixOffset(zoneBegin, zoneEnd); + pos = zoneEnd; + return result; } static QVector calculatePosixTransitions(const QByteArray &posixRule, @@ -419,51 +496,38 @@ static QVector calculatePosixTransitions(const QByteArra // POSIX Format is like "TZ=CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00" // i.e. "std offset dst [offset],start[/time],end[/time]" - // See http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + // See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html QList parts = posixRule.split(','); - QString name = QString::fromUtf8(parts.at(0)); - QString stdName; - QString stdOffsetString; - QString dstName; - QString dstOffsetString; - bool parsedStdName = false; - bool parsedStdOffset = false; - for (int i = 0; i < name.size(); ++i) { - if (name.at(i).isLetter()) { - if (parsedStdName) { - parsedStdOffset = true; - dstName.append(name.at(i)); - } else { - stdName.append(name.at(i)); + QPair stdZone, dstZone; + { + const QByteArray &zoneinfo = parts.at(0); + const char *begin = zoneinfo.constBegin(); + + stdZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd()); + if (stdZone.second == INT_MIN) { + stdZone.second = 0; // reset to UTC if we failed to parse + } else if (begin < zoneinfo.constEnd()) { + dstZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd()); + if (dstZone.second == INT_MIN) { + // if the dst offset isn't provided, it is 1 hour ahead of the standard offset + dstZone.second = stdZone.second + (60 * 60); } - } else { - parsedStdName = true; - if (parsedStdOffset) - dstOffsetString.append(name.at(i)); - else - stdOffsetString.append(name.at(i)); } } - int utcOffset = parsePosixOffset(stdOffsetString.toUtf8()); - // If only the name part then no transitions if (parts.count() == 1) { QTimeZonePrivate::Data data; data.atMSecsSinceEpoch = lastTranMSecs; - data.offsetFromUtc = utcOffset; - data.standardTimeOffset = utcOffset; + data.offsetFromUtc = stdZone.second; + data.standardTimeOffset = stdZone.second; data.daylightTimeOffset = 0; - data.abbreviation = stdName; + data.abbreviation = stdZone.first; result << data; return result; } - // If not populated the total dst offset is 1 hour - int dstOffset = utcOffset + (60 * 60); - if (!dstOffsetString.isEmpty()) - dstOffset = parsePosixOffset(dstOffsetString.toUtf8()); // Get the std to dst transtion details QList dstParts = parts.at(1).split('/'); @@ -486,18 +550,18 @@ static QVector calculatePosixTransitions(const QByteArra for (int year = startYear; year <= endYear; ++year) { QTimeZonePrivate::Data dstData; QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC); - dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (utcOffset * 1000); - dstData.offsetFromUtc = dstOffset; - dstData.standardTimeOffset = utcOffset; - dstData.daylightTimeOffset = dstOffset - utcOffset; - dstData.abbreviation = dstName; + dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.second * 1000); + dstData.offsetFromUtc = dstZone.second; + dstData.standardTimeOffset = stdZone.second; + dstData.daylightTimeOffset = dstZone.second - stdZone.second; + dstData.abbreviation = dstZone.first; QTimeZonePrivate::Data stdData; QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC); - stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstOffset * 1000); - stdData.offsetFromUtc = utcOffset; - stdData.standardTimeOffset = utcOffset; + stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.second * 1000); + stdData.offsetFromUtc = stdZone.second; + stdData.standardTimeOffset = stdZone.second; stdData.daylightTimeOffset = 0; - stdData.abbreviation = stdName; + stdData.abbreviation = stdZone.first; // Part of the high year will overflow if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) { if (dstData.atMSecsSinceEpoch > 0) { diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp index ea835108ee9..ce72e7ca7f3 100644 --- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp @@ -847,6 +847,16 @@ void tst_QTimeZone::tzTest() QTzTimeZonePrivate::Data datatz2 = tztz2.data(std); QTzTimeZonePrivate::Data datautc2 = tzutc2.data(std); QCOMPARE(datatz2.offsetFromUtc, datautc2.offsetFromUtc); + + // Test a timezone with a name that isn't all letters + QTzTimeZonePrivate tzBarnaul("Asia/Barnaul"); + if (tzBarnaul.isValid()) { + QCOMPARE(tzBarnaul.data(std).abbreviation, QString("+07")); + + // first full day of the new rule (tzdata2016b) + QDateTime dt(QDate(2016, 3, 28), QTime(0, 0, 0), Qt::UTC); + QCOMPARE(tzBarnaul.data(dt.toMSecsSinceEpoch()).abbreviation, QString("+07")); + } #endif // Q_OS_UNIX } From cd25866f6533923c208f52d58516f3725f69cefb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 May 2016 13:38:55 -0700 Subject: [PATCH 047/173] Use the code we already have for parsing the transition time too It's there and it's more efficient anyway. Change-Id: Ie9fd7afe060b4e4a8052fffd144fc40647430268 Reviewed-by: Edward Welbourne Reviewed-by: Brett Stottlemyer Reviewed-by: Lars Knoll --- src/corelib/tools/qtimezoneprivate_tz.cpp | 68 +++++++++++++---------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index cb9581ab638..bfa967e67bd 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -372,37 +372,21 @@ static QDate calculatePosixDate(const QByteArray &dateRule, int year) } } -static QTime parsePosixTime(const QByteArray &timeRule) +// returns the time in seconds, INT_MIN if we failed to parse +static int parsePosixTime(const char *begin, const char *end) { - // Format "HH:mm:ss", put check parts count just in case - QList parts = timeRule.split(':'); - int count = parts.count(); - if (count == 3) - return QTime(parts.at(0).toInt(), parts.at(1).toInt(), parts.at(2).toInt()); - else if (count == 2) - return QTime(parts.at(0).toInt(), parts.at(1).toInt(), 0); - else if (count == 1) - return QTime(parts.at(0).toInt(), 0, 0); - return QTime(2, 0, 0); -} - -static int parsePosixOffset(const char *begin, const char *end) -{ - // Format "[+|-]hh[:mm[:ss]]" + // Format "hh[:mm[:ss]]" int hour, min = 0, sec = 0; - // note that the sign is inverted because POSIX counts in hours West of GMT - bool negate = true; - if (*begin == '+') { - ++begin; - } else if (*begin == '-') { - negate = false; - ++begin; - } + // Note that the calls to qstrtoll do *not* check the end pointer, which + // means they proceed until they find a non-digit. We check that we're + // still in range at the end, but we may have read from past end. It's the + // caller's responsibility to ensure that begin is part of a + // null-terminated string. bool ok = false; hour = qstrtoll(begin, &begin, 10, &ok); - if (!ok) + if (!ok || hour < 0) return INT_MIN; if (begin < end && *begin == ':') { // minutes @@ -424,7 +408,35 @@ static int parsePosixOffset(const char *begin, const char *end) if (begin != end) return INT_MIN; - int value = (hour * 60 + min) * 60 + sec; + return (hour * 60 + min) * 60 + sec; +} + +static QTime parsePosixTransitionTime(const QByteArray &timeRule) +{ + // Format "hh[:mm[:ss]]" + int value = parsePosixTime(timeRule.constBegin(), timeRule.constEnd()); + if (value == INT_MIN) { + // if we failed to parse, return 02:00 + return QTime(2, 0, 0); + } + return QTime::fromMSecsSinceStartOfDay(value * 1000); +} + +static int parsePosixOffset(const char *begin, const char *end) +{ + // Format "[+|-]hh[:mm[:ss]]" + // note that the sign is inverted because POSIX counts in hours West of GMT + bool negate = true; + if (*begin == '+') { + ++begin; + } else if (*begin == '-') { + negate = false; + ++begin; + } + + int value = parsePosixTime(begin, end); + if (value == INT_MIN) + return value; return negate ? -value : value; } @@ -534,7 +546,7 @@ static QVector calculatePosixTransitions(const QByteArra QByteArray dstDateRule = dstParts.at(0); QTime dstTime; if (dstParts.count() > 1) - dstTime = parsePosixTime(dstParts.at(1)); + dstTime = parsePosixTransitionTime(dstParts.at(1)); else dstTime = QTime(2, 0, 0); @@ -543,7 +555,7 @@ static QVector calculatePosixTransitions(const QByteArra QByteArray stdDateRule = stdParts.at(0); QTime stdTime; if (stdParts.count() > 1) - stdTime = parsePosixTime(stdParts.at(1)); + stdTime = parsePosixTransitionTime(stdParts.at(1)); else stdTime = QTime(2, 0, 0); From 84ab88ce416fe5bb616ff64d26e5282e86f54cd8 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 24 May 2016 06:50:59 +0200 Subject: [PATCH 048/173] QWindowsPrintDevice: Handle return value of DocumentProperties correctly If the return value is less than 0 which signifies an error then trying to malloc that will cause an exception. Change-Id: Ia0153d4cb7aac1dacb509280b45be149a093b7c4 Reviewed-by: Friedemann Kleint --- .../windows/qwindowsprintdevice.cpp | 156 ++++++++---------- 1 file changed, 68 insertions(+), 88 deletions(-) diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp index d378ff31306..98978f4bbee 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2014 John Layt +** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -74,6 +75,22 @@ static QPrint::InputSlot paperBinToInputSlot(int windowsId, const QString &name) return slot; } +static LPDEVMODE getDevmode(HANDLE hPrinter, const QString &printerId) +{ + LPWSTR printerIdUtf16 = const_cast(reinterpret_cast(printerId.utf16())); + // Allocate the required DEVMODE buffer + LONG dmSize = DocumentProperties(NULL, hPrinter, printerIdUtf16, NULL, NULL, 0); + if (dmSize < 0) + return Q_NULLPTR; + LPDEVMODE pDevMode = reinterpret_cast(malloc(dmSize)); + // Get the default DevMode + LONG result = DocumentProperties(NULL, hPrinter, printerIdUtf16, pDevMode, NULL, DM_OUT_BUFFER); + if (result != IDOK) { + free(pDevMode); + pDevMode = Q_NULLPTR; + } + return pDevMode; +} QWindowsPrintDevice::QWindowsPrintDevice() : QPlatformPrintDevice(), @@ -191,26 +208,21 @@ QPageSize QWindowsPrintDevice::defaultPageSize() const QPageSize pageSize; - // Allocate the required DEVMODE buffer - DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0); - LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize); - - // Get the default DevMode - DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER); - - // Get the default paper size - if (result == IDOK && pDevMode->dmFields & DM_PAPERSIZE) { - // Find the supported page size that matches, in theory default should be one of them - foreach (const QPageSize &ps, m_pageSizes) { - if (ps.windowsId() == pDevMode->dmPaperSize) { - pageSize = ps; - break; + if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) { + // Get the default paper size + if (pDevMode->dmFields & DM_PAPERSIZE) { + // Find the supported page size that matches, in theory default should be one of them + foreach (const QPageSize &ps, m_pageSizes) { + if (ps.windowsId() == pDevMode->dmPaperSize) { + pageSize = ps; + break; + } } } + // Clean-up + free(pDevMode); } - // Clean-up - free(pDevMode); return pageSize; } @@ -226,20 +238,14 @@ QMarginsF QWindowsPrintDevice::printableMargins(const QPageSize &pageSize, QScopedArrayPointer buffer(new BYTE[needed]); if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) { PPRINTER_INFO_2 info = reinterpret_cast(buffer.data()); - DEVMODE *devMode = info->pDevMode; + LPDEVMODE devMode = info->pDevMode; bool separateDevMode = false; if (!devMode) { // GetPrinter() didn't include the DEVMODE. Get it a different way. - LONG result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), - NULL, NULL, 0); - devMode = (DEVMODE *)malloc(result); - separateDevMode = true; - result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), - devMode, NULL, DM_OUT_BUFFER); - if (result != IDOK) { - free(devMode); + devMode = getDevmode(m_hPrinter, m_id); + if (!devMode) return margins; - } + separateDevMode = true; } HDC pDC = CreateDC(NULL, (LPWSTR)m_id.utf16(), NULL, devMode); @@ -291,23 +297,17 @@ int QWindowsPrintDevice::defaultResolution() const { int resolution = 72; // TODO Set a sensible default? - // Allocate the required DEVMODE buffer - DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0); - LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize); - - // Get the default DevMode - DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER); - - // Get the default resolution - if (result == IDOK && pDevMode->dmFields & DM_YRESOLUTION) { - if (pDevMode->dmPrintQuality > 0) - resolution = pDevMode->dmPrintQuality; - else - resolution = pDevMode->dmYResolution; + if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) { + // Get the default resolution + if (pDevMode->dmFields & DM_YRESOLUTION) { + if (pDevMode->dmPrintQuality > 0) + resolution = pDevMode->dmPrintQuality; + else + resolution = pDevMode->dmYResolution; + } + // Clean-up + free(pDevMode); } - - // Clean-up - free(pDevMode); return resolution; } @@ -340,26 +340,20 @@ QPrint::InputSlot QWindowsPrintDevice::defaultInputSlot() const { QPrint::InputSlot inputSlot = QPlatformPrintDevice::defaultInputSlot();; - // Allocate the required DEVMODE buffer - DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0); - LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize); - - // Get the default DevMode - DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER); - - // Get the default input slot - if (result == IDOK && pDevMode->dmFields & DM_DEFAULTSOURCE) { - QPrint::InputSlot tempSlot = paperBinToInputSlot(pDevMode->dmDefaultSource, QString()); - foreach (const QPrint::InputSlot &slot, supportedInputSlots()) { - if (slot.key == tempSlot.key) { - inputSlot = slot; - break; + if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) { + // Get the default input slot + if (pDevMode->dmFields & DM_DEFAULTSOURCE) { + QPrint::InputSlot tempSlot = paperBinToInputSlot(pDevMode->dmDefaultSource, QString()); + foreach (const QPrint::InputSlot &slot, supportedInputSlots()) { + if (slot.key == tempSlot.key) { + inputSlot = slot; + break; + } } } + // Clean-up + free(pDevMode); } - - // Clean-up - free(pDevMode); return inputSlot; } @@ -386,23 +380,17 @@ QPrint::DuplexMode QWindowsPrintDevice::defaultDuplexMode() const { QPrint::DuplexMode duplexMode = QPrint::DuplexNone; - // Allocate the required DEVMODE buffer - DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0); - LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize); - - // Get the default DevMode - DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER); - - // Get the default duplex mode - if (result == IDOK && pDevMode->dmFields & DM_DUPLEX) { - if (pDevMode->dmDuplex == DMDUP_VERTICAL) - duplexMode = QPrint::DuplexLongSide; - else if (pDevMode->dmDuplex == DMDUP_HORIZONTAL) - duplexMode = QPrint::DuplexShortSide; + if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) { + // Get the default duplex mode + if (pDevMode->dmFields & DM_DUPLEX) { + if (pDevMode->dmDuplex == DMDUP_VERTICAL) + duplexMode = QPrint::DuplexLongSide; + else if (pDevMode->dmDuplex == DMDUP_HORIZONTAL) + duplexMode = QPrint::DuplexShortSide; + } + // Clean-up + free(pDevMode); } - - // Clean-up - free(pDevMode); return duplexMode; } @@ -424,21 +412,13 @@ QPrint::ColorMode QWindowsPrintDevice::defaultColorMode() const QPrint::ColorMode colorMode = QPrint::GrayScale; - // Allocate the required DEVMODE buffer - DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0); - LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize); - - // Get the default DevMode - DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER); - - // Get the default color mode - if (result == IDOK && pDevMode->dmFields & DM_COLOR) { - if (pDevMode->dmColor == DMCOLOR_COLOR) + if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) { + // Get the default color mode + if (pDevMode->dmFields & DM_COLOR && pDevMode->dmColor == DMCOLOR_COLOR) colorMode = QPrint::Color; + // Clean-up + free(pDevMode); } - - // Clean-up - free(pDevMode); return colorMode; } From 07667b439025a8bb47f6089673b11a479b21b72d Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 24 May 2016 14:37:44 +0200 Subject: [PATCH 049/173] tst_QNetworkReply: Un-blacklist recently fixed test. A recent fix now makes authenticationCacheAfterCancel(http+socksauth) work again, so un-blacklist it. Added a helpful comment while I was at it. Change-Id: I2d7eae8d80c12957d22659a82e5072301735c41f Reviewed-by: Timur Pocheptsov --- tests/auto/network/access/qnetworkreply/BLACKLIST | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST index 0605677e29c..1d56c78bbcb 100644 --- a/tests/auto/network/access/qnetworkreply/BLACKLIST +++ b/tests/auto/network/access/qnetworkreply/BLACKLIST @@ -1,3 +1,4 @@ +# See qtbase/src/testlib/qtestblacklist.cpp for format osx [ioGetFromBuiltinHttp:http+limited] ubuntu-14.04 @@ -7,7 +8,3 @@ ubuntu-14.04 * [backgroundRequestInterruption:ftp, bg, nobg] * -[authenticationCacheAfterCancel:http+socksauth] -rhel-7.1 -[authenticationCacheAfterCancel:https+socksauth] -rhel-7.1 From 832715a67908683241b8da524f6aa0c1a8a4267e Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 24 May 2016 16:13:02 +0200 Subject: [PATCH 050/173] qtestblacklist: only generate the distro and version once We were looking up distro and version, in order to conditionally add them to keywords if missing, on every keyword line of each BLACKLIST that we parsed. In particular, this meant the static holding the list of keywords couldn't be const. Move the distro-handling to an intemediary function that adds to the raw keywords and supplies one-off initialization for the list of conditions to match. Change-Id: Ia383ec060e24b7f72d2c8fd6ae65816318daafd0 Reviewed-by: Lars Knoll --- src/testlib/qtestblacklist.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index 04c6aa27175..da98b88989e 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -135,19 +135,26 @@ static QSet keywords() return set; } -static bool checkCondition(const QByteArray &condition) +static QSet activeConditions() { - static QSet matchedConditions = keywords(); - QList conds = condition.split(' '); + QSet result = keywords(); QByteArray distributionName = QSysInfo::productType().toLower().toUtf8(); QByteArray distributionRelease = QSysInfo::productVersion().toLower().toUtf8(); if (!distributionName.isEmpty()) { - if (matchedConditions.find(distributionName) == matchedConditions.end()) - matchedConditions.insert(distributionName); - matchedConditions.insert(distributionName + "-" + distributionRelease); + if (result.find(distributionName) == result.end()) + result.insert(distributionName); + result.insert(distributionName + "-" + distributionRelease); } + return result; +} + +static bool checkCondition(const QByteArray &condition) +{ + static const QSet matchedConditions = activeConditions(); + QList conds = condition.split(' '); + for (int i = 0; i < conds.size(); ++i) { QByteArray c = conds.at(i); bool result = c.startsWith('!'); From 6f59926e670d68b27a387651a466f47ca9e8fd37 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 24 May 2016 16:16:56 +0200 Subject: [PATCH 051/173] qtestblacklist: check against duplicating versioned distro Also check the version is non-empty. Probably makes no difference, but it's obviously more correct. Change-Id: I05eee5623ac432d2ea02f7aad874513beeb2ceeb Reviewed-by: Lars Knoll --- src/testlib/qtestblacklist.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index da98b88989e..9300cb58af7 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -144,7 +144,11 @@ static QSet activeConditions() if (!distributionName.isEmpty()) { if (result.find(distributionName) == result.end()) result.insert(distributionName); - result.insert(distributionName + "-" + distributionRelease); + if (!distributionRelease.isEmpty()) { + QByteArray versioned = distributionName + "-" + distributionRelease; + if (result.find(versioned) == result.end()) + result.insert(versioned); + } } return result; From b057fdbb12341da9e972bcd16c5c4f1b751cac01 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 24 May 2016 15:32:43 +0200 Subject: [PATCH 052/173] Improve documentation of BLACKLIST file format. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In particular, make sure the word BLACKLIST appears in it so it can actually be *found*. Mention the comment format, mention version suffixes, mention negation; expand and clarify the description. Break it up into paragraphs for ease of reading. Corrected the example to use osx, not its old platform name. Gave it a comment that I wish I'd found in the BLACKLIST file that obliged me to come looking for this in the first place. Illustrated the use of comments to document reasons for ignoring tests. Change-Id: I78d49b4706c0f70b714f7a410f850fb42ebb77c0 Reviewed-by: Lars Knoll Reviewed-by: Timur Pocheptsov Reviewed-by: Jędrzej Nowacki --- src/testlib/qtestblacklist.cpp | 43 ++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index 9300cb58af7..9dfd5065ad4 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -46,21 +46,38 @@ QT_BEGIN_NAMESPACE /* - The file format is simply a grouped listing of keywords - Ungrouped entries at the beginning apply to the whole testcase - Groups define testfunctions or specific test data to ignore. - After the groups come a list of entries (one per line) that define - for which platform/os combination to ignore the test result. - All keys in a single line have to match to blacklist the test. + The BLACKLIST file format is a grouped listing of keywords. - mac - [testFunction] - linux - windows 64bit - [testfunction2:testData] - msvc + Blank lines and lines starting with # are simply ignored. An initial #-line + referring to this documentation is kind to readers. Comments can also be used + to indicate the reasons for ignoring particular cases. - The known keys are listed below: + A key names a platform, O/S, distribution, tool-chain or architecture; a ! + prefix reverses what it checks. A version, joined to a key (at present, only + for distributions and for msvc) with a hyphen, limits the key to the specific + version. A keyword line matches if every key on it applies to the present + run. Successive lines are alternate conditions for ignoring a test. + + Ungrouped lines at the beginning of a file apply to the whole testcase. + A group starts with a [square-bracketed] identification of a test function, + optionally with (after a colon, the name of) a specific data set, to ignore. + Subsequent lines give conditions for ignoring this test. + + # See qtbase/src/testlib/qtestblacklist.cpp for format + osx + + # QTBUG-12345 + [testFunction] + linux + windows 64bit + + # Needs basic C++11 support + [testfunction2:testData] + msvc-2010 + + Keys are lower-case. Distribution name and version are supported if + QSysInfo's productType() and productVersion() return them. + The other known keys are listed below: */ static QSet keywords() From 5c16b73243f56cc61bf199a8505a86f011405e98 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 24 May 2016 19:22:29 +0200 Subject: [PATCH 053/173] Compile Fix: unused variable in q_refreshRateFromFb() on non-linux To fix a compile warning under non-Linux systems, declare framebufferDevice in q_refreshRateFromFb() as Q_UNUSED like in the other functions. Change-Id: I31a4e788f07d27d3cff7f6ea7fd82813a7acc7d9 Reviewed-by: Laszlo Agocs --- src/platformsupport/eglconvenience/qeglconvenience.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp index 922455c96f1..be700dce01d 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience.cpp +++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp @@ -578,6 +578,10 @@ int q_screenDepthFromFb(int framebufferDevice) qreal q_refreshRateFromFb(int framebufferDevice) { +#ifndef Q_OS_LINUX + Q_UNUSED(framebufferDevice) +#endif + static qreal rate = 0; #ifdef Q_OS_LINUX From e0ab94b5251e732d4bea553f2d6e943f5d714720 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 24 May 2016 22:02:02 +0200 Subject: [PATCH 054/173] Compile fix: for OpenBSD: not included by On OpenBSD, isn't included in , so that leads to compile errors on files that include qcore_unix_p.h: qcore_unix_p.h:335:69: error: 'fd_set' has not been declared Just move the whole select include section from qcore_unix.cpp, no functional changes. The patch is adapted from OpenBSD ports maintainer Vadim Zhukov patch for qt ports. Change-Id: I35ba693440b1c1644bcfcdb69823e2b37870ad97 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcore_unix.cpp | 10 ---------- src/corelib/kernel/qcore_unix_p.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index 5695cb3ec50..1bcb4720c23 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -34,16 +34,6 @@ #include "qcore_unix_p.h" #include "qelapsedtimer.h" -#ifdef Q_OS_NACL -#elif !defined (Q_OS_VXWORKS) -# if !defined(Q_OS_HPUX) || defined(__ia64) -# include -# endif -# include -#else -# include -#endif - #include #ifdef Q_OS_MAC diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index f80dcb5a505..05711354ffa 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -58,6 +58,16 @@ #include #include +#ifdef Q_OS_NACL +#elif !defined (Q_OS_VXWORKS) +# if !defined(Q_OS_HPUX) || defined(__ia64) +# include +# endif +# include +#else +# include +#endif + #include #include #include From f75b78a92a689b90124c79e50525bbc78540c576 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Wed, 18 May 2016 16:31:52 +0200 Subject: [PATCH 055/173] Cocoa integration - fix QCocoaWindow::setContentView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - QCocoaWindow::setContentView calls -removeFromSuperView and this is not valid for a view that is a content view for a NSWindow: using it will release the view but not clear the window.contentView pointer. Set contentView to nil instead. Fixing this makes visible the second problem: - QNSWindowHelper in its -handleWindowEvent: can access content view and assumes it's QNSView - it is not always guaranteed and can result in invalid message sent to a view, we can use m_qtView instead (it will be nil if it has a type different from QNSView, the call will be noop then). Task-number: QTBUG-53325 Change-Id: I0472eba8165a04b6a3f81b2171b3bb9827ff5681 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index c5519995b66..c0d59043672 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -148,7 +148,7 @@ static bool isMouseEvent(NSEvent *ev) if (NSMouseInRect(loc, windowFrame, NO) && !NSMouseInRect(loc, contentFrame, NO)) { - QNSView *contentView = (QNSView *)pw->contentView(); + QNSView *contentView = pw->m_qtView; [contentView handleFrameStrutMouseEvent: theEvent]; } } @@ -1173,7 +1173,11 @@ NSView *QCocoaWindow::contentView() const void QCocoaWindow::setContentView(NSView *contentView) { // Remove and release the previous content view - [m_contentView removeFromSuperview]; + if (m_nsWindow) + [m_nsWindow setContentView:nil]; + else + [m_contentView removeFromSuperview]; + [m_contentView release]; // Insert and retain the new content view From 8c428376891727fd4e5caf343bde6697dde29478 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 4 May 2016 14:45:58 +0200 Subject: [PATCH 056/173] QIOSTextInputOverlay: fade-out handles upon focus transfer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Small adjustment to a76d709. Instead of removing the selection handles immediately when an object loses focus, we choose to animate them out the same way we do when we lose selection. We do this by setting the handle visibility to false, which will trigger the fade-out animation. Then we wait a for the animation to finish before we remove and delete them fully. Change-Id: Iaa93969af086000d9e1cf8a39bd12c6a8b70c89e Reviewed-by: Tor Arne Vestbø --- .../platforms/ios/qiostextinputoverlay.mm | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm index 3fa9341540f..733367f3be5 100644 --- a/src/plugins/platforms/ios/qiostextinputoverlay.mm +++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm @@ -45,6 +45,7 @@ #include "qiostextinputoverlay.h" typedef QPair SelectionPair; +typedef void (^Block)(void); static const CGFloat kKnobWidth = 10; @@ -68,7 +69,7 @@ static bool hasSelection() return selection.first != selection.second; } -static void executeBlockWithoutAnimation(void (^block)(void)) +static void executeBlockWithoutAnimation(Block block) { [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; @@ -306,6 +307,7 @@ static void executeBlockWithoutAnimation(void (^block)(void)) @property (nonatomic, assign) CGRect cursorRectangle; @property (nonatomic, assign) CGFloat handleScale; @property (nonatomic, assign) BOOL visible; +@property (nonatomic, copy) Block onAnimationDidStop; @end @implementation QIOSHandleLayer @@ -359,7 +361,8 @@ static void executeBlockWithoutAnimation(void (^block)(void)) [NSNumber numberWithFloat:1], nil]; return animation; } else { - CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:key]; + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key]; + [animation setDelegate:self]; animation.fromValue = [self valueForKey:key]; [animation setDuration:0.2]; return animation; @@ -368,6 +371,14 @@ static void executeBlockWithoutAnimation(void (^block)(void)) return [super actionForKey:key]; } +- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag +{ + Q_UNUSED(animation); + Q_UNUSED(flag); + if (self.onAnimationDidStop) + self.onAnimationDidStop(); +} + - (void)setVisible:(BOOL)visible { if (visible == _visible) @@ -679,7 +690,7 @@ static void executeBlockWithoutAnimation(void (^block)(void)) if (enabled) { // Create a layer that clips the handles inside the input field - _clipRectLayer = [[CALayer new] autorelease]; + _clipRectLayer = [CALayer new]; _clipRectLayer.masksToBounds = YES; [self.focusView.layer addSublayer:_clipRectLayer]; @@ -705,7 +716,26 @@ static void executeBlockWithoutAnimation(void (^block)(void)) [self updateSelection]; } else { - [_clipRectLayer removeFromSuperlayer]; + // Fade out the handles by setting visible to NO, and wait for the animations + // to finish before removing the clip rect layer, including the handles. + // Create a local variable to hold the clipRectLayer while the animation is + // ongoing to ensure that any subsequent calls to setEnabled does not interfere. + // Also, declare it as __block to stop it from being automatically retained, which + // would cause a cyclic dependency between clipRectLayer and the block. + __block CALayer *clipRectLayer = _clipRectLayer; + __block int handleCount = 2; + Block block = ^{ + if (--handleCount == 0) { + [clipRectLayer removeFromSuperlayer]; + [clipRectLayer release]; + } + }; + + _cursorLayer.onAnimationDidStop = block; + _anchorLayer.onAnimationDidStop = block; + _cursorLayer.visible = NO; + _anchorLayer.visible = NO; + _clipRectLayer = 0; _cursorLayer = 0; _anchorLayer = 0; From 421aa422af2f6b147ad076ad1736b3747abc4317 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Wed, 25 May 2016 10:27:51 +0200 Subject: [PATCH 057/173] Really fix crash on certain malformed bmp images This is an improvement of e4f71b0c. By using the QImageReader::read() overload taking a QImage pointer, and ignoring the return value, one could still end up with a corrupt QImage object. Avoid the subsequent crashes by closing that hole. Change-Id: I5dca10e4808ac3365e3ddba6689edecb7444948f Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Lars Knoll Reviewed-by: Richard J. Moore --- src/gui/image/qbmphandler.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 27bab10196c..bb238d3eb34 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -283,6 +283,12 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int format = QImage::Format_Mono; } + if (depth != 32) { + ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; + if (ncols < 1 || ncols > 256) // sanity check - don't run out of mem if color table is broken + return false; + } + if (bi.biHeight < 0) h = -h; // support images with negative height @@ -290,19 +296,15 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int image = QImage(w, h, format); if (image.isNull()) // could not create image return false; - } - - if (depth != 32) { - ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; - if (ncols < 1 || ncols > 256) // sanity check - don't run out of mem if color table is broken - return false; - image.setColorCount(ncols); + if (ncols) + image.setColorCount(ncols); // Ensure valid QImage } image.setDotsPerMeterX(bi.biXPelsPerMeter); image.setDotsPerMeterY(bi.biYPelsPerMeter); if (ncols > 0) { // read color table + image.setColorCount(ncols); uchar rgb[4]; int rgb_len = t == BMP_OLD ? 3 : 4; for (int i=0; i Date: Tue, 15 Mar 2016 10:10:12 -0700 Subject: [PATCH 058/173] Replace qUnaligned{Load,Store} with the existing q{To,From}Unaligned Move the Q_ALWAYS_INLINE and forcing of __builtin_memcpy to the existing functions. Change-Id: Icaa7fb2a490246bda156ffff143c137e520eea79 Reviewed-by: Lars Knoll --- src/corelib/global/qendian.h | 30 ++++++++++++------- src/corelib/global/qendian.qdoc | 23 +++++++++++++++ src/corelib/json/qjson_p.h | 2 +- src/corelib/mimetypes/qmimemagicrule.cpp | 3 +- src/corelib/tools/qbitarray.cpp | 26 +++-------------- src/corelib/tools/qhash.cpp | 9 +++--- src/corelib/tools/qsimd.cpp | 22 -------------- src/corelib/tools/qsimd_p.h | 37 ------------------------ src/corelib/tools/qstring.cpp | 2 +- 9 files changed, 55 insertions(+), 99 deletions(-) diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index 2ddefaec8b2..23dda270e39 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -42,6 +42,11 @@ QT_BEGIN_NAMESPACE +#ifdef __has_builtin +# define QT_HAS_BUILTIN(x) __has_builtin(x) +#else +# define QT_HAS_BUILTIN(x) 0 +#endif /* * ENDIAN FUNCTIONS @@ -64,18 +69,29 @@ template inline void qbswap(const T src, uchar *dest) // Used to implement a type-safe and alignment-safe copy operation // If you want to avoid the memcpy, you must write specializations for these functions -template inline void qToUnaligned(const T src, uchar *dest) +template Q_ALWAYS_INLINE void qToUnaligned(const T src, uchar *dest) { // Using sizeof(T) inside memcpy function produces internal compiler error with // MSVC2008/ARM in tst_endian -> use extra indirection to resolve size of T. const size_t size = sizeof(T); - memcpy(dest, &src, size); +#if QT_HAS_BUILTIN(__builtin_memcpy) + __builtin_memcpy +#else + memcpy +#endif + (dest, &src, size); } -template inline T qFromUnaligned(const uchar *src) + +template Q_ALWAYS_INLINE T qFromUnaligned(const uchar *src) { T dest; const size_t size = sizeof(T); - memcpy(&dest, src, size); +#if QT_HAS_BUILTIN(__builtin_memcpy) + __builtin_memcpy +#else + memcpy +#endif + (&dest, src, size); return dest; } @@ -87,12 +103,6 @@ template inline T qFromUnaligned(const uchar *src) */ template T qbswap(T source); -#ifdef __has_builtin -# define QT_HAS_BUILTIN(x) __has_builtin(x) -#else -# define QT_HAS_BUILTIN(x) 0 -#endif - // GCC 4.3 implemented all the intrinsics, but the 16-bit one only got implemented in 4.8; // Clang 2.6 implemented the 32- and 64-bit but waited until 3.2 to implement the 16-bit one #if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32) diff --git a/src/corelib/global/qendian.qdoc b/src/corelib/global/qendian.qdoc index e110461f8b0..b7494c9a217 100644 --- a/src/corelib/global/qendian.qdoc +++ b/src/corelib/global/qendian.qdoc @@ -33,6 +33,29 @@ little and big endian representations of numbers. */ +/*! + \internal + \fn T qFromUnaligned(const uchar *ptr) + \since 5.5 + + Loads a \c{T} from address \a ptr, which may be misaligned. + + Use of this function avoids the undefined behavior that the C++ standard + otherwise attributes to unaligned loads. +*/ + +/*! + \internal + \fn void qToUnaligned(T t, uchar *ptr) + \since 4.5 + + Stores \a t to address \a ptr, which may be misaligned. + + Use of this function avoids the undefined behavior that the C++ standard + otherwise attributes to unaligned stores. +*/ + + /*! \fn T qFromBigEndian(const uchar *src) \since 4.3 diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index 59d0c91785c..c52a37ba2b0 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -402,7 +402,7 @@ public: // pack with itself, we'll discard the high part anyway chunk = _mm_packus_epi16(chunk, chunk); // unaligned 64-bit store - qUnalignedStore(l + i, _mm_cvtsi128_si64(chunk)); + qToUnaligned(_mm_cvtsi128_si64(chunk), l + i); i += 8; } # endif diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp index 44834420fe0..398a6705445 100644 --- a/src/corelib/mimetypes/qmimemagicrule.cpp +++ b/src/corelib/mimetypes/qmimemagicrule.cpp @@ -42,7 +42,6 @@ #include #include #include -#include // for qUnalignedLoad QT_BEGIN_NAMESPACE @@ -177,7 +176,7 @@ static bool matchNumber(const QMimeMagicRulePrivate *d, const QByteArray &data) const char *p = data.constData() + d->startPos; const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), d->endPos + 1); for ( ; p <= e; ++p) { - if ((qUnalignedLoad(p) & mask) == (value & mask)) + if ((qFromUnaligned(reinterpret_cast(p)) & mask) == (value & mask)) return true; } diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp index a64edea77e9..8e6b1203f89 100644 --- a/src/corelib/tools/qbitarray.cpp +++ b/src/corelib/tools/qbitarray.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -162,25 +163,6 @@ QBitArray::QBitArray(int size, bool value) Same as size(). */ -template T qUnalignedLoad(const uchar *ptr) -{ - /* - * Testing with different compilers shows that they all optimize the memcpy - * call away and replace with direct loads whenever possible. On x86 and PPC, - * GCC does direct unaligned loads; on MIPS, it generates a pair of load-left - * and load-right instructions. ICC and Clang do the same on x86. This is both - * 32- and 64-bit. - * - * On ARM cores without unaligned loads, the compiler leaves a call to - * memcpy. - */ - - T u; - memcpy(&u, ptr, sizeof(u)); - return u; -} - - /*! If \a on is true, this function returns the number of 1-bits stored in the bit array; otherwise the number @@ -196,17 +178,17 @@ int QBitArray::count(bool on) const const quint8 *const end = reinterpret_cast(d.end()); while (bits + 7 <= end) { - quint64 v = qUnalignedLoad(bits); + quint64 v = qFromUnaligned(bits); bits += 8; numBits += int(qPopulationCount(v)); } if (bits + 3 <= end) { - quint32 v = qUnalignedLoad(bits); + quint32 v = qFromUnaligned(bits); bits += 4; numBits += int(qPopulationCount(v)); } if (bits + 1 < end) { - quint16 v = qUnalignedLoad(bits); + quint16 v = qFromUnaligned(bits); bits += 2; numBits += int(qPopulationCount(v)); } diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index d40570d347e..c5669babd9a 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #ifndef QT_BOOTSTRAPPED @@ -105,24 +106,24 @@ static uint crc32(const Char *ptr, size_t len, uint h) p += 8; for ( ; p <= e; p += 8) - h2 = _mm_crc32_u64(h2, qUnalignedLoad(p - 8)); + h2 = _mm_crc32_u64(h2, qFromUnaligned(p - 8)); h = h2; p -= 8; len = e - p; if (len & 4) { - h = _mm_crc32_u32(h, qUnalignedLoad(p)); + h = _mm_crc32_u32(h, qFromUnaligned(p)); p += 4; } # else p += 4; for ( ; p <= e; p += 4) - h = _mm_crc32_u32(h, qUnalignedLoad(p - 4)); + h = _mm_crc32_u32(h, qFromUnaligned(p - 4)); p -= 4; len = e - p; # endif if (len & 2) { - h = _mm_crc32_u16(h, qUnalignedLoad(p)); + h = _mm_crc32_u16(h, qFromUnaligned(p)); p += 2; } if (sizeof(Char) == 1 && len & 1) diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 5ca2ce4c6f7..f07eb098f2c 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -716,26 +716,4 @@ void qDumpCPUFeatures() puts(""); } -/*! - \internal - \fn T qUnalignedLoad(const void *ptr) - \since 5.6.1 - - Loads a \c{T} from address \a ptr, which may be misaligned. - - Use of this function avoid the undefined behavior that the C++ standard - otherwise attributes to unaligned loads. -*/ - -/*! - \internal - \fn void qUnalignedStore(void *ptr, T t) - \since 5.6.1 - - Stores \a t to address \a ptr, which may be misaligned. - - Use of this function avoid the undefined behavior that the C++ standard - otherwise attributes to unaligned stores. -*/ - QT_END_NAMESPACE diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index ca53908cf50..d689654b297 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -476,43 +476,6 @@ unsigned _bit_scan_forward(unsigned val) #define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \ for (; i < static_cast(qMin(static_cast(length), ((4 - ((reinterpret_cast(ptr) >> 2) & 0x3)) & 0x3))); ++i) -// these defines are copied from qendian.h -// in Qt 5.7, they have been moved to qglobal.h -// drop them when merging this to 5.7 -#ifdef __has_builtin -# define QT_HAS_BUILTIN(x) __has_builtin(x) -#else -# define QT_HAS_BUILTIN(x) 0 -#endif - -template -Q_ALWAYS_INLINE -T qUnalignedLoad(const void *ptr) Q_DECL_NOTHROW -{ - T result; -#if QT_HAS_BUILTIN(__builtin_memcpy) - __builtin_memcpy -#else - memcpy -#endif - /*memcpy*/(&result, ptr, sizeof result); - return result; -} - -template -Q_ALWAYS_INLINE -void qUnalignedStore(void *ptr, T t) Q_DECL_NOTHROW -{ -#if QT_HAS_BUILTIN(__builtin_memcpy) - __builtin_memcpy -#else - memcpy -#endif - /*memcpy*/(ptr, &t, sizeof t); -} - -#undef QT_HAS_BUILTIN - QT_END_NAMESPACE #endif // QSIMD_P_H diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 6bbaf05fefc..be1ca8ba95a 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -577,7 +577,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l) // we'll read uc[offset..offset+7] (16 bytes) and c[offset..offset+7] (8 bytes) if (uc + offset + 7 < e) { // same, but we're using an 8-byte load - __m128i chunk = _mm_cvtsi64_si128(qUnalignedLoad(c + offset)); + __m128i chunk = _mm_cvtsi64_si128(qFromUnaligned(c + offset)); __m128i secondHalf = _mm_unpacklo_epi8(chunk, nullmask); __m128i ucdata = _mm_loadu_si128((const __m128i*)(uc + offset)); From 11353ea6a50682d5877baf4c356de56f7ab89376 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Wed, 25 May 2016 17:57:21 +0200 Subject: [PATCH 059/173] Compile fix: C++11 usage: Replace nullptr with Q_NULLPTR Another compile fix when compiling qt with -stdc++ c++98 option. Replace nullptr with Q_NULLPTR. Change-Id: I7765905031fa91250dbbcc9768b9e8b109e7594d Reviewed-by: Thiago Macieira --- .../eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp index 830e270eeb6..bcc908905cd 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp @@ -125,7 +125,7 @@ void QEglFSKmsCursor::updateMouseStatus() m_state = visible ? CursorPendingVisible : CursorPendingHidden; #ifndef QT_NO_CURSOR - changeCursor(nullptr, m_screen->topLevelAt(pos())); + changeCursor(Q_NULLPTR, m_screen->topLevelAt(pos())); #endif } From 37a0e9c180e6dd670b5ba722218df00d88d8ad3b Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Fri, 25 Mar 2016 18:30:35 +0200 Subject: [PATCH 060/173] QNetworkReply: remove double buffering Since 5.7 we can write downloaded byte arrays directly to the QIODevice's internal read buffer without any memcpy/alloc overhead. This makes various other buffers redundant, so remove them. Task-number: QTBUG-45926 Change-Id: I577af70f856c9b852b7569a0070ae2bcbb4faaae Reviewed-by: Oswald Buddenhagen Reviewed-by: Edward Welbourne Reviewed-by: Markus Goetz (Woboq GmbH) --- src/network/access/qnetworkreplyhttpimpl.cpp | 46 +++++++------------- src/network/access/qnetworkreplyhttpimpl_p.h | 5 +-- src/network/access/qnetworkreplyimpl.cpp | 40 +++++------------ src/network/access/qnetworkreplyimpl_p.h | 5 +-- 4 files changed, 29 insertions(+), 67 deletions(-) diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 5c403250aba..6bf3c56db24 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -296,7 +296,7 @@ qint64 QNetworkReplyHttpImpl::bytesAvailable() const // if we load from cache device if (d->cacheLoadDevice) { - return QNetworkReply::bytesAvailable() + d->cacheLoadDevice->bytesAvailable() + d->downloadMultiBuffer.byteAmount(); + return QNetworkReply::bytesAvailable() + d->cacheLoadDevice->bytesAvailable(); } // zerocopy buffer @@ -305,7 +305,7 @@ qint64 QNetworkReplyHttpImpl::bytesAvailable() const } // normal buffer - return QNetworkReply::bytesAvailable() + d->downloadMultiBuffer.byteAmount(); + return QNetworkReply::bytesAvailable(); } bool QNetworkReplyHttpImpl::isSequential () const @@ -329,12 +329,6 @@ qint64 QNetworkReplyHttpImpl::readData(char* data, qint64 maxlen) if (d->cacheLoadDevice) { // FIXME bytesdownloaded, position etc? - // There is something already in the buffer we buffered before because the user did not read() - // anything, so we read there first: - if (!d->downloadMultiBuffer.isEmpty()) { - return d->downloadMultiBuffer.read(data, maxlen); - } - qint64 ret = d->cacheLoadDevice->read(data, maxlen); return ret; } @@ -351,25 +345,14 @@ qint64 QNetworkReplyHttpImpl::readData(char* data, qint64 maxlen) } // normal buffer - if (d->downloadMultiBuffer.isEmpty()) { - if (d->state == d->Finished || d->state == d->Aborted) - return -1; - return 0; - } + if (d->state == d->Finished || d->state == d->Aborted) + return -1; - if (maxlen == 1) { - // optimization for getChar() - *data = d->downloadMultiBuffer.getChar(); - if (readBufferSize()) - emit readBufferFreed(1); - return 1; - } - - maxlen = qMin(maxlen, d->downloadMultiBuffer.byteAmount()); - qint64 bytesRead = d->downloadMultiBuffer.read(data, maxlen); + qint64 wasBuffered = d->bytesBuffered; + d->bytesBuffered = 0; if (readBufferSize()) - emit readBufferFreed(bytesRead); - return bytesRead; + emit readBufferFreed(wasBuffered); + return 0; } void QNetworkReplyHttpImpl::setReadBufferSize(qint64 size) @@ -387,12 +370,12 @@ bool QNetworkReplyHttpImpl::canReadLine () const return true; if (d->cacheLoadDevice) - return d->cacheLoadDevice->canReadLine() || d->downloadMultiBuffer.canReadLine(); + return d->cacheLoadDevice->canReadLine(); if (d->downloadZerocopyBuffer) return memchr(d->downloadZerocopyBuffer + d->downloadBufferReadPosition, '\n', d->downloadBufferCurrentSize - d->downloadBufferReadPosition); - return d->downloadMultiBuffer.canReadLine(); + return false; } #ifndef QT_NO_SSL @@ -444,6 +427,7 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate() , resumeOffset(0) , preMigrationDownloaded(-1) , bytesDownloaded(0) + , bytesBuffered(0) , downloadBufferReadPosition(0) , downloadBufferCurrentSize(0) , downloadZerocopyBuffer(0) @@ -1054,10 +1038,11 @@ void QNetworkReplyHttpImplPrivate::replyDownloadData(QByteArray d) cacheSaveDevice->write(item.constData(), item.size()); if (!isHttpRedirectResponse()) - downloadMultiBuffer.append(item); + buffer.append(item); bytesWritten += item.size(); } + bytesBuffered += bytesWritten; pendingDownloadDataCopy.clear(); QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); @@ -1830,9 +1815,8 @@ void QNetworkReplyHttpImplPrivate::_q_cacheLoadReadyRead() // If there are still bytes available in the cacheLoadDevice then the user did not read // in response to the readyRead() signal. This means we have to load from the cacheLoadDevice // and buffer that stuff. This is needed to be able to properly emit finished() later. - while (cacheLoadDevice->bytesAvailable() && !isHttpRedirectResponse()) { - downloadMultiBuffer.append(cacheLoadDevice->readAll()); - } + while (cacheLoadDevice->bytesAvailable() && !isHttpRedirectResponse()) + buffer.append(cacheLoadDevice->readAll()); if (cacheLoadDevice->isSequential()) { // check if end and we can read the EOF -1 diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index 669258f15b9..4aba915c7d6 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -240,12 +240,11 @@ public: quint64 resumeOffset; qint64 preMigrationDownloaded; - // Used for normal downloading. For "zero copy" the downloadZerocopyBuffer is used - QByteDataBuffer downloadMultiBuffer; QByteDataBuffer pendingDownloadData; // For signal compression qint64 bytesDownloaded; + qint64 bytesBuffered; - // only used when the "zero copy" style is used. Else downloadMultiBuffer is used. + // Only used when the "zero copy" style is used. // Please note that the whole "zero copy" download buffer API is private right now. Do not use it. qint64 downloadBufferReadPosition; qint64 downloadBufferCurrentSize; diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index d69d5983cb6..54930a351ac 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -184,17 +184,13 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() break; bytesToRead = qBound(1, bytesToRead, copyDevice->bytesAvailable()); - QByteArray byteData; - byteData.resize(bytesToRead); - qint64 bytesActuallyRead = copyDevice->read(byteData.data(), byteData.size()); + qint64 bytesActuallyRead = copyDevice->read(buffer.reserve(bytesToRead), bytesToRead); if (bytesActuallyRead == -1) { - byteData.clear(); + buffer.chop(bytesToRead); backendNotify(NotifyCopyFinished); break; } - - byteData.resize(bytesActuallyRead); - readBuffer.append(byteData); + buffer.chop(bytesToRead - bytesActuallyRead); if (!copyDevice->isSequential() && copyDevice->atEnd()) { backendNotify(NotifyCopyFinished); @@ -582,7 +578,7 @@ qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const if (readBufferMaxSize == 0) return DesiredBufferSize; - return qMax(0, readBufferMaxSize - readBuffer.byteAmount()); + return qMax(0, readBufferMaxSize - buffer.size()); } void QNetworkReplyImplPrivate::initCacheSaveDevice() @@ -624,7 +620,7 @@ void QNetworkReplyImplPrivate::initCacheSaveDevice() } // we received downstream data and send this to the cache -// and to our readBuffer (which in turn gets read by the user of QNetworkReply) +// and to our buffer (which in turn gets read by the user of QNetworkReply) void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data) { Q_Q(QNetworkReplyImpl); @@ -641,7 +637,7 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data) if (cacheSaveDevice) cacheSaveDevice->write(item.constData(), item.size()); - readBuffer.append(item); + buffer.append(item); bytesWritten += item.size(); } @@ -975,13 +971,6 @@ void QNetworkReplyImpl::close() d->finished(); } -bool QNetworkReplyImpl::canReadLine () const -{ - Q_D(const QNetworkReplyImpl); - return QNetworkReply::canReadLine() || d->readBuffer.canReadLine(); -} - - /*! Returns the number of bytes available for reading with QIODevice::read(). The number of bytes available may grow until @@ -996,14 +985,14 @@ qint64 QNetworkReplyImpl::bytesAvailable() const return QNetworkReply::bytesAvailable() + maxAvail; } - return QNetworkReply::bytesAvailable() + d_func()->readBuffer.byteAmount(); + return QNetworkReply::bytesAvailable(); } void QNetworkReplyImpl::setReadBufferSize(qint64 size) { Q_D(QNetworkReplyImpl); if (size > d->readBufferMaxSize && - size > d->readBuffer.byteAmount()) + size > d->buffer.size()) d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); QNetworkReply::setReadBufferSize(size); @@ -1061,19 +1050,12 @@ qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen) } - if (d->readBuffer.isEmpty()) - return d->state == QNetworkReplyPrivate::Finished ? -1 : 0; // FIXME what about "Aborted" state? + if (d->state == QNetworkReplyPrivate::Finished) + return -1; d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); - if (maxlen == 1) { - // optimization for getChar() - *data = d->readBuffer.getChar(); - return 1; - } - - maxlen = qMin(maxlen, d->readBuffer.byteAmount()); - return d->readBuffer.read(data, maxlen); + return 0; } /*! diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 156cb411c70..054cbcc3a78 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -81,7 +81,6 @@ public: virtual void close() Q_DECL_OVERRIDE; virtual qint64 bytesAvailable() const Q_DECL_OVERRIDE; virtual void setReadBufferSize(qint64 size) Q_DECL_OVERRIDE; - virtual bool canReadLine () const Q_DECL_OVERRIDE; virtual qint64 readData(char *data, qint64 maxlen) Q_DECL_OVERRIDE; virtual bool event(QEvent *) Q_DECL_OVERRIDE; @@ -187,8 +186,6 @@ public: QList proxyList; #endif - // Used for normal downloading. For "zero copy" the downloadBuffer is used - QByteDataBuffer readBuffer; qint64 bytesDownloaded; qint64 lastBytesDownloaded; qint64 bytesUploaded; @@ -199,7 +196,7 @@ public: State state; - // only used when the "zero copy" style is used. Else readBuffer is used. + // Only used when the "zero copy" style is used. // Please note that the whole "zero copy" download buffer API is private right now. Do not use it. qint64 downloadBufferReadPosition; qint64 downloadBufferCurrentSize; From 4605ca20130170757c2cbe6f69eb7fcfbc9f9101 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Mon, 23 May 2016 17:17:14 -0700 Subject: [PATCH 061/173] Remove QNetworkReplyNSURLConnectionImpl. This class is no longer needed now that SecureTransport is the default SSL backend on iOS. It also uses NSURLConnection, which is deprecated on iOS and tvOS and completely prohibited on watchOS (in favor of NSURLSession). [ChangeLog][Important Behavior Changes] The NSURLConnection backend of QNetworkAccessManager has been removed, since SecureTransport is the default SSL backend on iOS and is enabled by default. This means that building with -no-openssl -no-securetransport will no longer provide SSL capabilities on iOS. Task-number: QTBUG-45031 Change-Id: I86b774fa369c7d76197bfc0504d5ad234bb47e5c Reviewed-by: Richard J. Moore --- src/network/access/access.pri | 8 - src/network/access/qnetworkaccessmanager.cpp | 10 - .../qnetworkreplynsurlconnectionimpl.mm | 451 ------------------ .../qnetworkreplynsurlconnectionimpl_p.h | 81 ---- 4 files changed, 550 deletions(-) delete mode 100644 src/network/access/qnetworkreplynsurlconnectionimpl.mm delete mode 100644 src/network/access/qnetworkreplynsurlconnectionimpl_p.h diff --git a/src/network/access/access.pri b/src/network/access/access.pri index e829d52cbee..38e9c252698 100644 --- a/src/network/access/access.pri +++ b/src/network/access/access.pri @@ -72,12 +72,4 @@ SOURCES += \ mac: LIBS_PRIVATE += -framework Security -ios { - HEADERS += \ - access/qnetworkreplynsurlconnectionimpl_p.h - - OBJECTIVE_SOURCES += \ - access/qnetworkreplynsurlconnectionimpl.mm -} - include($$PWD/../../3rdparty/zlib_dependency.pri) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index d023228fd2d..b649aba4a8a 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -50,10 +50,6 @@ #include "qnetworkreplydataimpl_p.h" #include "qnetworkreplyfileimpl_p.h" -#if defined(Q_OS_IOS) && defined(QT_NO_SSL) -#include "qnetworkreplynsurlconnectionimpl_p.h" -#endif - #include "QtCore/qbuffer.h" #include "QtCore/qurl.h" #include "QtCore/qvector.h" @@ -1201,12 +1197,6 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera } } -// Use NSURLConnection for https on iOS when OpenSSL is disabled. -#if defined(Q_OS_IOS) && defined(QT_NO_SSL) - if (scheme == QLatin1String("https")) - return new QNetworkReplyNSURLConnectionImpl(this, request, op, outgoingData); -#endif - #ifndef QT_NO_HTTP // Since Qt 5 we use the new QNetworkReplyHttpImpl if (scheme == QLatin1String("http") || scheme == QLatin1String("preconnect-http") diff --git a/src/network/access/qnetworkreplynsurlconnectionimpl.mm b/src/network/access/qnetworkreplynsurlconnectionimpl.mm deleted file mode 100644 index f4f494560ca..00000000000 --- a/src/network/access/qnetworkreplynsurlconnectionimpl.mm +++ /dev/null @@ -1,451 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qnetworkreplynsurlconnectionimpl_p.h" - -#include "QtCore/qdatetime.h" -#include -#include -#include - -QT_BEGIN_NAMESPACE - -// Network reply implementation using NSUrlConnection. -// -// Class/object structure: -// -// QNetworkReplyNSURLConnectionImpl -// |- QNetworkReplyNSURLConnectionImplPrivate -// |- (bytes read) -// |- (QIODevice and CFStream for async POST data transfer) -// |- NSURLConnection -// |- QtNSURLConnectionDelegate -// |- NSURLResponse/NSHTTPURLResponse -// |- (response data) -// -// The main entry point is the QNetworkReplyNSURLConnectionImpl constructor, which -// receives a network request from QNetworkAccessManager. The constructor -// creates a NSURLRequest and initiates a NSURLConnection with a QtNSURLConnectionDelegate. -// The delegate callbacks are then called asynchronously as the request completes. -// - -@class QtNSURLConnectionDelegate; -class QNetworkReplyNSURLConnectionImplPrivate: public QNetworkReplyPrivate -{ -public: - QNetworkReplyNSURLConnectionImplPrivate(); - virtual ~QNetworkReplyNSURLConnectionImplPrivate(); - - Q_DECLARE_PUBLIC(QNetworkReplyNSURLConnectionImpl) - NSURLConnection * urlConnection; - QtNSURLConnectionDelegate *urlConnectionDelegate; - qint64 bytesRead; - - // Sequental outgiong data streaming - QIODevice *outgoingData; - CFReadStreamRef readStream; - CFWriteStreamRef writeStream; - CFIndex transferBufferSize; - - // Forwarding functions to the public class. - void setFinished(); - void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value); - void setRawHeader(const QByteArray &headerName, const QByteArray &value); - void setError(QNetworkReply::NetworkError errorCode, const QString &errorString); - void setAttribute(QNetworkRequest::Attribute code, const QVariant &value); -}; - -@interface QtNSURLConnectionDelegate : NSObject -{ - NSURLResponse *response; - NSMutableData *responseData; - QNetworkReplyNSURLConnectionImplPrivate * replyprivate; -} - -- (id)initWithQNetworkReplyNSURLConnectionImplPrivate:(QNetworkReplyNSURLConnectionImplPrivate *)a_replyPrivate ; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_3_0) -- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge; -#endif -- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError*)error; -- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response; -- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data; -- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten - totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite; -- (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse; -- (NSURLRequest*)connection:(NSURLConnection*)connection willSendRequest:(NSURLRequest*)request redirectResponse:(NSURLResponse*)redirectResponse; -- (void)connectionDidFinishLoading:(NSURLConnection*)connection; -- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection*)connection; - -@end - -QNetworkReplyNSURLConnectionImplPrivate::QNetworkReplyNSURLConnectionImplPrivate() - : QNetworkReplyPrivate() - , urlConnection(0) - , urlConnectionDelegate(0) - , bytesRead(0) - , readStream(0) - , writeStream(0) - , transferBufferSize(4096) -{ -} - -QNetworkReplyNSURLConnectionImplPrivate::~QNetworkReplyNSURLConnectionImplPrivate() -{ - [urlConnection cancel]; - [urlConnection release]; - [urlConnectionDelegate release]; - if (readStream) - CFRelease(readStream); - if (writeStream) - CFRelease(writeStream); -} - -void QNetworkReplyNSURLConnectionImplPrivate::setFinished() -{ - q_func()->setFinished(true); - QMetaObject::invokeMethod(q_func(), "finished", Qt::QueuedConnection); -} - -void QNetworkReplyNSURLConnectionImplPrivate::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value) -{ - q_func()->setHeader(header, value); -} - -void QNetworkReplyNSURLConnectionImplPrivate::setRawHeader(const QByteArray &headerName, const QByteArray &value) -{ - q_func()->setRawHeader(headerName, value); -} - -void QNetworkReplyNSURLConnectionImplPrivate::setError(QNetworkReply::NetworkError errorCode, const QString &errorString) -{ - q_func()->setError(errorCode, errorString); -} - -void QNetworkReplyNSURLConnectionImplPrivate::setAttribute(QNetworkRequest::Attribute code, const QVariant &value) -{ - q_func()->setAttribute(code, value); -} - -void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData() -{ - Q_D(QNetworkReplyNSURLConnectionImpl); - int bytesRead = 0; - do { - char data[d->transferBufferSize]; - bytesRead = d->outgoingData->read(data, d->transferBufferSize); - if (bytesRead <= 0) - break; - CFIndex bytesWritten = CFWriteStreamWrite(d->writeStream, reinterpret_cast(data), bytesRead); - if (bytesWritten != bytesRead) { - CFErrorRef err = CFWriteStreamCopyError(d->writeStream); - qWarning() << "QNetworkReplyNSURLConnectionImpl: CFWriteStreamWrite error" - << (err ? QString::number(CFErrorGetCode(err)) : QStringLiteral("")); - } - } while (bytesRead > 0); - - if (d->outgoingData->atEnd()) - CFWriteStreamClose(d->writeStream); -} - -@interface QtNSURLConnectionDelegate () - -@property (nonatomic, retain) NSURLResponse* response; -@property (nonatomic, retain) NSMutableData* responseData; - -@end - -@implementation QtNSURLConnectionDelegate - -@synthesize response; -@synthesize responseData; - -- (id)initWithQNetworkReplyNSURLConnectionImplPrivate:(QNetworkReplyNSURLConnectionImplPrivate *)a_replyPrivate -{ - if (self = [super init]) - replyprivate = a_replyPrivate; - return self; -} - -- (void)dealloc -{ - [response release]; - [responseData release]; - [super dealloc]; -} - -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_3_0) -- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge -{ - Q_UNUSED(connection) - Q_UNUSED(challenge) - - if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { - SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; - SecTrustResultType resultType; - SecTrustEvaluate(serverTrust, &resultType); - if (resultType == kSecTrustResultUnspecified) { - // All good - [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; - } else if (resultType == kSecTrustResultRecoverableTrustFailure) { - // Certificate verification error, ask user - // ### TODO actually ask user - // (test site: https://testssl-expire.disig.sk/index.en.html) - qWarning() << "QNetworkReplyNSURLConnection: Certificate verification error handlig is" - << "not implemented. Connection will time out."; - } else { - // other error, which the default handler will handle - [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; - } - } - - [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; -} -#endif - -- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error -{ - Q_UNUSED(connection) - - QNetworkReply::NetworkError qtError = QNetworkReply::UnknownNetworkError; - if ([[error domain] isEqualToString:NSURLErrorDomain]) { - switch ([error code]) { - case NSURLErrorTimedOut: qtError = QNetworkReply::TimeoutError; break; - case NSURLErrorUnsupportedURL: qtError = QNetworkReply::ProtocolUnknownError; break; - case NSURLErrorCannotFindHost: qtError = QNetworkReply::HostNotFoundError; break; - case NSURLErrorCannotConnectToHost: qtError = QNetworkReply::ConnectionRefusedError; break; - case NSURLErrorNetworkConnectionLost: qtError = QNetworkReply::NetworkSessionFailedError; break; - case NSURLErrorDNSLookupFailed: qtError = QNetworkReply::HostNotFoundError; break; - case NSURLErrorNotConnectedToInternet: qtError = QNetworkReply::NetworkSessionFailedError; break; - case NSURLErrorUserAuthenticationRequired: qtError = QNetworkReply::AuthenticationRequiredError; break; - default: break; - } - } - - replyprivate->setError(qtError, QString::fromNSString([error localizedDescription])); - replyprivate->setFinished(); -} - -- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)aResponse -{ - Q_UNUSED(connection) - self.response = aResponse; - self.responseData = [NSMutableData data]; - - // copy headers - if ([aResponse isKindOfClass:[NSHTTPURLResponse class]]) { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)aResponse; - NSDictionary *headers = [httpResponse allHeaderFields]; - for (NSString *key in headers) { - NSString *value = [headers objectForKey:key]; - replyprivate->setRawHeader(QString::fromNSString(key).toUtf8(), QString::fromNSString(value).toUtf8()); - } - - int code = [httpResponse statusCode]; - replyprivate->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, code); - } else { - if ([aResponse expectedContentLength] != NSURLResponseUnknownLength) - replyprivate->setHeader(QNetworkRequest::ContentLengthHeader, [aResponse expectedContentLength]); - } - - QMetaObject::invokeMethod(replyprivate->q_func(), "metaDataChanged", Qt::QueuedConnection); -} - -- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data -{ - Q_UNUSED(connection) - [responseData appendData:data]; - - if ([response expectedContentLength] != NSURLResponseUnknownLength) { - QMetaObject::invokeMethod(replyprivate->q_func(), "downloadProgress", Qt::QueuedConnection, - Q_ARG(qint64, qint64([responseData length] + replyprivate->bytesRead)), - Q_ARG(qint64, qint64([response expectedContentLength]))); - } - - QMetaObject::invokeMethod(replyprivate->q_func(), "readyRead", Qt::QueuedConnection); -} - -- (void)connection:(NSURLConnection*)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten - totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite -{ - Q_UNUSED(connection) - Q_UNUSED(bytesWritten) - QMetaObject::invokeMethod(replyprivate->q_func(), "uploadProgress", Qt::QueuedConnection, - Q_ARG(qint64, qint64(totalBytesWritten)), - Q_ARG(qint64, qint64(totalBytesExpectedToWrite))); -} - -- (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse -{ - Q_UNUSED(connection) - return cachedResponse; -} - -- (NSURLRequest*)connection:(NSURLConnection*)connection willSendRequest:(NSURLRequest*)request redirectResponse:(NSURLResponse*)redirectResponse -{ - Q_UNUSED(connection) - Q_UNUSED(redirectResponse) - return request; -} - -- (void)connectionDidFinishLoading:(NSURLConnection*)connection -{ - Q_UNUSED(connection) - replyprivate->setFinished(); -} - -- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection*)connection -{ - Q_UNUSED(connection) - return YES; -} - -@end - -QNetworkReplyNSURLConnectionImpl::~QNetworkReplyNSURLConnectionImpl() -{ -} - -QNetworkReplyNSURLConnectionImpl::QNetworkReplyNSURLConnectionImpl(QObject *parent, - const QNetworkRequest &request, const QNetworkAccessManager::Operation operation, QIODevice* outgoingData) - : QNetworkReply(*new QNetworkReplyNSURLConnectionImplPrivate(), parent) -{ - setRequest(request); - setUrl(request.url()); - setOperation(operation); - QNetworkReply::open(QIODevice::ReadOnly); - - QNetworkReplyNSURLConnectionImplPrivate *d = (QNetworkReplyNSURLConnectionImplPrivate*) d_func(); - - QUrl url = request.url(); - if (url.host() == QLatin1String("localhost")) - url.setHost(QString()); - - if (url.path().isEmpty()) - url.setPath(QLatin1String("/")); - setUrl(url); - - // Create a NSMutableURLRequest from QNetworkRequest - NSMutableURLRequest *nsRequest = [NSMutableURLRequest requestWithURL:request.url().toNSURL() - cachePolicy:NSURLRequestUseProtocolCachePolicy - timeoutInterval:60.0]; - // copy headers - foreach (const QByteArray &header, request.rawHeaderList()) { - QByteArray headerValue = request.rawHeader(header); - [nsRequest addValue:QString::fromUtf8(headerValue).toNSString() - forHTTPHeaderField:QString::fromUtf8(header).toNSString()]; - } - - if (operation == QNetworkAccessManager::GetOperation) - [nsRequest setHTTPMethod:@"GET"]; - else if (operation == QNetworkAccessManager::PostOperation) - [nsRequest setHTTPMethod:@"POST"]; - else if (operation == QNetworkAccessManager::PutOperation) - [nsRequest setHTTPMethod:@"PUT"]; - else if (operation == QNetworkAccessManager::DeleteOperation) - [nsRequest setHTTPMethod:@"DELETE"]; - else - qWarning() << "QNetworkReplyNSURLConnection: Unsupported netork operation" << operation; - - if (outgoingData) { - d->outgoingData = outgoingData; - if (outgoingData->isSequential()) { - // set up streaming from outgoingData iodevice to request - CFStreamCreateBoundPair(kCFAllocatorDefault, &d->readStream, &d->writeStream, d->transferBufferSize); - CFWriteStreamOpen(d->writeStream); - [nsRequest setHTTPBodyStream:reinterpret_cast(d->readStream)]; - connect(outgoingData, SIGNAL(readyRead()), this, SLOT(readyReadOutgoingData())); - readyReadOutgoingData(); - } else { - // move all data at once - QByteArray data = outgoingData->readAll(); - [nsRequest setHTTPBody:[NSData dataWithBytes:data.constData() length:data.length()]]; - } - } - - // Create connection - d->urlConnectionDelegate = [[QtNSURLConnectionDelegate alloc] initWithQNetworkReplyNSURLConnectionImplPrivate:d]; - d->urlConnection = [[NSURLConnection alloc] initWithRequest:nsRequest delegate:d->urlConnectionDelegate]; - if (!d->urlConnection) { - // ### what type of error is an initWithRequest fail? - setError(QNetworkReply::ProtocolUnknownError, QStringLiteral("QNetworkReplyNSURLConnection internal error")); - } -} - -void QNetworkReplyNSURLConnectionImpl::close() -{ - // No-op? Network ops should continue (especially POSTs) - QNetworkReply::close(); -} - -void QNetworkReplyNSURLConnectionImpl::abort() -{ - Q_D(QNetworkReplyNSURLConnectionImpl); - [d->urlConnection cancel]; - QNetworkReply::close(); -} - -qint64 QNetworkReplyNSURLConnectionImpl::bytesAvailable() const -{ - Q_D(const QNetworkReplyNSURLConnectionImpl); - qint64 available = QNetworkReply::bytesAvailable() + - [[d->urlConnectionDelegate responseData] length]; - return available; -} - -bool QNetworkReplyNSURLConnectionImpl::isSequential() const -{ - return true; -} - -qint64 QNetworkReplyNSURLConnectionImpl::size() const -{ - Q_D(const QNetworkReplyNSURLConnectionImpl); - return [[d->urlConnectionDelegate responseData] length] + d->bytesRead; -} - -/*! - \internal -*/ -qint64 QNetworkReplyNSURLConnectionImpl::readData(char *data, qint64 maxlen) -{ - Q_D(QNetworkReplyNSURLConnectionImpl); - qint64 dataSize = [[d->urlConnectionDelegate responseData] length]; - qint64 canRead = qMin(maxlen, dataSize); - const char *sourceBase = static_cast([[d->urlConnectionDelegate responseData] bytes]); - memcpy(data, sourceBase, canRead); - [[d->urlConnectionDelegate responseData] replaceBytesInRange:NSMakeRange(0, canRead) withBytes:NULL length:0]; - d->bytesRead += canRead; - return canRead; -} - -QT_END_NAMESPACE diff --git a/src/network/access/qnetworkreplynsurlconnectionimpl_p.h b/src/network/access/qnetworkreplynsurlconnectionimpl_p.h deleted file mode 100644 index 8eacaf67129..00000000000 --- a/src/network/access/qnetworkreplynsurlconnectionimpl_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QNETWORKREPLYNSURLCONNECTIONIMPL_H -#define QNETWORKREPLYNSURLCONNECTIONIMPL_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the Network Access API. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include "qnetworkreply.h" -#include "qnetworkreply_p.h" -#include "qnetworkaccessmanager.h" -#include -#include - -QT_BEGIN_NAMESPACE - - -class QNetworkReplyNSURLConnectionImplPrivate; -class QNetworkReplyNSURLConnectionImpl: public QNetworkReply -{ - Q_OBJECT -public: - QNetworkReplyNSURLConnectionImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op, QIODevice* outgoingData); - virtual ~QNetworkReplyNSURLConnectionImpl(); - virtual void abort(); - - // reimplemented from QNetworkReply - virtual void close(); - virtual qint64 bytesAvailable() const; - virtual bool isSequential () const; - qint64 size() const; - - virtual qint64 readData(char *data, qint64 maxlen); -public Q_SLOTS: - void readyReadOutgoingData(); - - Q_DECLARE_PRIVATE(QNetworkReplyNSURLConnectionImpl) -}; - -QT_END_NAMESPACE - -#endif // QNetworkReplyNSURLConnectionImpl_H From 2ceacd537279e735025a2c74a7a1b73ea8c4fc06 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Mon, 23 May 2016 17:42:49 -0700 Subject: [PATCH 062/173] Fix httpwindow example. DownloadLocation is not writable on some platforms (iOS) in Qt 5.6, and qt-project.org HTTPS does not work anymore. Change-Id: I78bfbee1472cd39cd05ec7f846d1195d4fbb1b2c Reviewed-by: Timur Pocheptsov --- examples/network/http/httpwindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/network/http/httpwindow.cpp b/examples/network/http/httpwindow.cpp index 301431fd5e4..41563dc235d 100644 --- a/examples/network/http/httpwindow.cpp +++ b/examples/network/http/httpwindow.cpp @@ -46,9 +46,9 @@ #include "ui_authenticationdialog.h" #ifndef QT_NO_SSL -static const char defaultUrl[] = "https://qt-project.org/"; +static const char defaultUrl[] = "https://www.qt.io/"; #else -static const char defaultUrl[] = "http://qt-project.org/"; +static const char defaultUrl[] = "http://www.qt.io/"; #endif static const char defaultFileName[] = "index.html"; @@ -96,7 +96,7 @@ HttpWindow::HttpWindow(QWidget *parent) connect(urlLineEdit, &QLineEdit::textChanged, this, &HttpWindow::enableDownloadButton); formLayout->addRow(tr("&URL:"), urlLineEdit); - QString downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); + QString downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::TempLocation); if (downloadDirectory.isEmpty() || !QFileInfo(downloadDirectory).isDir()) downloadDirectory = QDir::currentPath(); downloadDirectoryLineEdit->setText(QDir::toNativeSeparators(downloadDirectory)); From 84f8203e3888fb116cf9ff46d5976a314fdbecad Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 26 May 2016 10:43:07 +0200 Subject: [PATCH 063/173] tst_qsslsocket - re-structure the code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setEmptyDefaultConfiguration - this test (and this was stated explicitly in comments!) must be the last test to run, otherwise, it can make subsequent tests fail. -exitLoop must be in 'protected slots' section not to be executed as a test, since ... it's aux function, not a test. Task-number: QTBUG-53608 Task-number: QTBUG-53603 Change-Id: I49d6d57ba927ecc4f20ae2d9325ad02fa46b0922 Reviewed-by: Tony Sarajärvi --- tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index f8c5b8b67bd..17a3f3a4d00 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -222,7 +222,6 @@ private slots: void ecdhServer(); void verifyClientCertificate_data(); void verifyClientCertificate(); - void setEmptyDefaultConfiguration(); // this test should be last #ifndef QT_NO_OPENSSL void simplePskConnect_data(); @@ -231,6 +230,10 @@ private slots: void ephemeralServerKey(); #endif + void setEmptyDefaultConfiguration(); // this test should be last + +protected slots: + static void exitLoop() { // Safe exit - if we aren't in an event loop, don't @@ -241,7 +244,6 @@ private slots: } } -protected slots: void ignoreErrorSlot() { socket->ignoreSslErrors(); From f9b7385e24a319536506b95ceb70ba0e5dc6d5c3 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 26 May 2016 10:59:37 +0200 Subject: [PATCH 064/173] tst_qsslsocket::protocolServerSide - blacklist on RHEL 7.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit protocolServerSide test fails with 'ssl3-any' and 'tls1.0-any' combo on RHEL 7.2 with OpenSSL v1.0.1e-fips, it would work as OPENSSL_NO_SSL2 code-path, but OPENSSL_NO_SSL2 is not defined, so socket is in state connected while it's expected to be unconnected. Task-number: QTBUG-53608 Change-Id: Ib321b95129a6ab5b0691b40cb4acc612125633b2 Reviewed-by: Tony Sarajärvi --- tests/auto/network/ssl/qsslsocket/BLACKLIST | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/auto/network/ssl/qsslsocket/BLACKLIST b/tests/auto/network/ssl/qsslsocket/BLACKLIST index 4146a352e98..52c023b78fe 100644 --- a/tests/auto/network/ssl/qsslsocket/BLACKLIST +++ b/tests/auto/network/ssl/qsslsocket/BLACKLIST @@ -1,3 +1,7 @@ windows [waitForConnectedEncryptedReadyRead:WithSocks5ProxyAuth] * +[protocolServerSide:ssl3-any] +rhel-7.2 +[protocolServerSide:tls1.0-any] +rhel-7.2 From 5fe16358bbbcd1a6fdd4904b01ffcec4a9eee5d8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 25 May 2016 09:47:57 -0700 Subject: [PATCH 065/173] Fix use of QMutex on Linux before FUTEX_PRIVATE_FLAG was added It was added in 2.6.22. If we pass it to 2.6.21, we'll get -ENOSYS, which is bad for QMutex. This fix simply defines it to 0 if the header doesn't define it. But as a consequence: if Qt is built with newer kernel headers, it won't run on older versions. It's not likely that someone is still using Qt 5.7 on a 2.6.21 kernel (v2.6.21.7 was released on 2007-08-04). Change-Id: Icb178bb113bb437c9b67fffd1451dd7bb964f0c8 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/thread/qmutex_linux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp index 25444ffff6b..17072f44d40 100644 --- a/src/corelib/thread/qmutex_linux.cpp +++ b/src/corelib/thread/qmutex_linux.cpp @@ -57,7 +57,7 @@ #endif #ifndef FUTEX_PRIVATE_FLAG -# define FUTEX_PRIVATE_FLAG 128 +# define FUTEX_PRIVATE_FLAG 0 #endif From 9224255f13952e5b4092208c8cae1a31ab5c6a19 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 27 May 2016 07:22:40 +0200 Subject: [PATCH 066/173] QVector: silence clang warning about memmove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also made a small comment fix Task-number: QTBUG-53605 Change-Id: Ica9a06fe7a70f92f2a19a6df3ffdeaf1985e2eb6 Reviewed-by: Jędrzej Nowacki --- src/corelib/tools/qvector.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index fea50f4c345..b68ca87063d 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -736,7 +736,7 @@ typename QVector::iterator QVector::erase(iterator abegin, iterator aend) const int itemsUntouched = abegin - d->begin(); // FIXME we could do a proper realloc, which copy constructs only needed data. - // FIXME we ara about to delete data maybe it is good time to shrink? + // FIXME we are about to delete data - maybe it is good time to shrink? // FIXME the shrink is also an issue in removeLast, that is just a copy + reduce of this. if (d->alloc) { detach(); @@ -756,7 +756,11 @@ typename QVector::iterator QVector::erase(iterator abegin, iterator aend) } } else { destruct(abegin, aend); - memmove(abegin, aend, (d->size - itemsToErase - itemsUntouched) * sizeof(T)); + // QTBUG-53605: static_cast masks clang errors of the form + // error: destination for this 'memmove' call is a pointer to class containing a dynamic class + // FIXME maybe use std::is_polymorphic (as soon as allowed) to avoid the memmove + memmove(static_cast(abegin), static_cast(aend), + (d->size - itemsToErase - itemsUntouched) * sizeof(T)); } d->size -= itemsToErase; } From 0e70d35f151c52a8821be987e4cd1aef3d40b010 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Thu, 26 May 2016 15:06:11 +0200 Subject: [PATCH 067/173] iOS: Return correct QLocale from QIOSInputContext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure we return a correct QLocale on iOS by overriding QPlatformInputContext::locale(). A broader implementation involving subclassing QSystemLocale will be done in dev. Task-number: QTBUG-48772 Change-Id: I5250bdad320cbe66d63456926f6eab6fc2865424 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosinputcontext.h | 5 +++ src/plugins/platforms/ios/qiosinputcontext.mm | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h index 40ddbfce289..923c87b07bb 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.h +++ b/src/plugins/platforms/ios/qiosinputcontext.h @@ -36,6 +36,7 @@ #include +#include #include #include #include @@ -46,6 +47,7 @@ const char kImePlatformDataReturnKeyType[] = "returnKeyType"; QT_BEGIN_NAMESPACE +@class QIOSLocaleListener; @class QIOSKeyboardListener; @class QIOSTextInputResponder; @protocol KeyboardState; @@ -92,6 +94,8 @@ public: void reset() Q_DECL_OVERRIDE; void commit() Q_DECL_OVERRIDE; + QLocale locale() const Q_DECL_OVERRIDE; + void clearCurrentFocusObject(); void setFocusObject(QObject *object) Q_DECL_OVERRIDE; @@ -112,6 +116,7 @@ public: private: UIView* scrollableRootView(); + QIOSLocaleListener *m_localeListener; QIOSKeyboardListener *m_keyboardHideGesture; QIOSTextInputResponder *m_textResponder; KeyboardState m_keyboardState; diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index d03c589b2a9..c9463087c71 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -56,6 +56,39 @@ static QUIView *focusView() // ------------------------------------------------------------------------- +@interface QIOSLocaleListener : NSObject +@end + +@implementation QIOSLocaleListener + +- (id)init +{ + if (self = [super init]) { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(localeDidChange:) + name:NSCurrentLocaleDidChangeNotification object:nil]; + } + + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (void)localeDidChange:(NSNotification *)notification +{ + Q_UNUSED(notification); + QIOSInputContext::instance()->emitLocaleChanged(); +} + +@end + +// ------------------------------------------------------------------------- + @interface QIOSKeyboardListener : UIGestureRecognizer { @private QIOSInputContext *m_context; @@ -285,6 +318,7 @@ QIOSInputContext *QIOSInputContext::instance() QIOSInputContext::QIOSInputContext() : QPlatformInputContext() + , m_localeListener([QIOSLocaleListener new]) , m_keyboardHideGesture([[QIOSKeyboardListener alloc] initWithQIOSInputContext:this]) , m_textResponder(0) { @@ -298,6 +332,7 @@ QIOSInputContext::QIOSInputContext() QIOSInputContext::~QIOSInputContext() { + [m_localeListener release]; [m_keyboardHideGesture.view removeGestureRecognizer:m_keyboardHideGesture]; [m_keyboardHideGesture release]; @@ -657,3 +692,8 @@ void QIOSInputContext::commit() [m_textResponder unmarkText]; [m_textResponder notifyInputDelegate:Qt::ImSurroundingText]; } + +QLocale QIOSInputContext::locale() const +{ + return QLocale(QString::fromNSString([[NSLocale currentLocale] objectForKey:NSLocaleIdentifier])); +} From 0fbedac2efba15b6791f641d2e4fea1e40d262bd Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Fri, 27 May 2016 16:34:11 +0300 Subject: [PATCH 068/173] Andriod: API-16 is the minimum API that we support Change-Id: I0aa79a584b1a4aef92d9ee1a2930a23dc6a8d236 Reviewed-by: Eskil Abrahamsen Blomfeldt --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 3e455c61639..caa4cda28d8 100755 --- a/configure +++ b/configure @@ -857,7 +857,7 @@ QT_QPA_DEFAULT_PLATFORM= # Android vars CFG_DEFAULT_ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT CFG_DEFAULT_ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT -CFG_DEFAULT_ANDROID_PLATFORM=android-9 +CFG_DEFAULT_ANDROID_PLATFORM=android-16 CFG_DEFAULT_ANDROID_TARGET_ARCH=armeabi-v7a CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION=4.9 CFG_DEFAULT_ANDROID_NDK_HOST=$ANDROID_NDK_HOST From c85f988fc785690ade283305181de8e7256d4040 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Wed, 25 May 2016 11:51:52 +0200 Subject: [PATCH 069/173] Disable thread_local on clang for FreeBSD FreeBSD's clang currently is not able to handle thread_local calls due to linker errors on __cxa_thread_atexit. The patch disables the define Q_COMPILER_THREAD_LOCAL for clang __FreeBSD__ only, no functional change. Otherwise, linking the tst_compiler autotest will fail. For details, see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=192320 Change-Id: I2395c06499d4821213e2154769ccbeed3dcf1ffe Reviewed-by: Thiago Macieira --- src/corelib/global/qcompilerdetection.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 8574059616b..ad881ef4c94 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -699,7 +699,9 @@ # define Q_COMPILER_TEMPLATE_ALIAS # endif # if __has_feature(cxx_thread_local) -# define Q_COMPILER_THREAD_LOCAL +# if !defined(__FreeBSD__) /* FreeBSD clang fails on __cxa_thread_atexit */ +# define Q_COMPILER_THREAD_LOCAL +# endif # endif # if __has_feature(cxx_user_literals) # define Q_COMPILER_UDL From 614e86f564450fd31de39d3288866332298802c0 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Thu, 26 May 2016 08:36:57 +0200 Subject: [PATCH 070/173] Platform detection: Use freebsd-g++ on systems < 10, otherwise -clang FreeBSD uses gcc as the default compiler until FreeBSD 10 where it was switched to clang for the whole system. Choose freebsd-clang for any system release > 10, otherwise choose freebsd-g++ by default. Change-Id: I2bf38aa027453c25ed2a29d587c2962ded5fcd4a Reviewed-by: Oswald Buddenhagen --- configure | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 0e0a36b00fa..d175ed32b52 100755 --- a/configure +++ b/configure @@ -2859,10 +2859,17 @@ if [ -z "$PLATFORM" ]; then PLATFORM=ultrix-g++ ;; FreeBSD:*) - PLATFORM=freebsd-clang - PLATFORM_NOTES=" - - Also available for FreeBSD: freebsd-g++ - " + if [ "$(uname -r | cut -d. -f1)" -ge 10 ]; then + PLATFORM=freebsd-clang + PLATFORM_NOTES=" + - Also available for FreeBSD: freebsd-g++ + " + else + PLATFORM=freebsd-g++ + PLATFORM_NOTES=" + - Also available for FreeBSD: freebsd-clang + " + fi ;; OpenBSD:*) PLATFORM=openbsd-g++ From 965b5b7ae07f8abec580729001abd61e8db729e5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 26 May 2016 16:31:02 +0200 Subject: [PATCH 071/173] OpenGL legacy example: Fix compilation in namespaced builds. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I6b2f3e8c240e105c73008fa61f9ed50cc9d982ac Reviewed-by: Alexandru Croitor Reviewed-by: Laszlo Agocs Reviewed-by: Topi Reiniö --- examples/opengl/legacy/shared/qtlogo.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/opengl/legacy/shared/qtlogo.h b/examples/opengl/legacy/shared/qtlogo.h index 9bd15a14310..c5d8db9f9fc 100644 --- a/examples/opengl/legacy/shared/qtlogo.h +++ b/examples/opengl/legacy/shared/qtlogo.h @@ -44,7 +44,8 @@ #include #include -class QOpenGLFunctions_1_1; +QT_FORWARD_DECLARE_CLASS(QOpenGLFunctions_1_1) + class Patch; struct Geometry; From b59cf8a1b4384bebc3d14fd7ce69db74b5f60e1d Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 25 May 2016 12:55:24 +0300 Subject: [PATCH 072/173] Android: Removed super old NDK checks Change-Id: I8c16dca1272f0413ac486fd1d54b6c678a8c9dd8 Reviewed-by: Oswald Buddenhagen Reviewed-by: Eskil Abrahamsen Blomfeldt --- mkspecs/android-g++/qmake.conf | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mkspecs/android-g++/qmake.conf b/mkspecs/android-g++/qmake.conf index fc14eeae5a8..28f5638463a 100644 --- a/mkspecs/android-g++/qmake.conf +++ b/mkspecs/android-g++/qmake.conf @@ -188,14 +188,6 @@ QMAKE_LFLAGS = --sysroot=$$ANDROID_PLATFORM_ROOT_PATH QMAKE_RPATHLINK = $$QMAKE_ANDROID_PLATFORM_LIBDIR QMAKE_LFLAGS_APP = -Wl,--no-undefined -Wl,-z,noexecstack -shared QMAKE_LFLAGS_SHLIB = -Wl,--no-undefined -Wl,-z,noexecstack -shared - -contains(NDK_ROOT, ".*r6")|contains(NDK_ROOT, ".*r5.*") { - !equals(ANDROID_PLATFORM, android-4):!equals(ANDROID_PLATFORM, android-5):!equals(ANDROID_PLATFORM, android-8) { - warning("Your NDK version is outdated. A workaround is enabled. Consider updating your NDK (workarounds are required until r6(a))") - QMAKE_LFLAGS_SHLIB += $$QMAKE_ANDROID_PLATFORM_LIBDIR/crtbegin_so.o $$QMAKE_ANDROID_PLATFORM_LIBDIR/crtend_so.o - } -} - QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined QMAKE_LFLAGS_RPATH = -Wl,-rpath= From 9e9888f69aa0b78d10b16f85235918f9d41db152 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 25 May 2016 12:22:21 +0300 Subject: [PATCH 073/173] Initialize the value before using it. LIBGCC_PATH was used before we initialized it, somehow it magically worked ... Change-Id: I0a9a748ffbfc641f60736b0cf85d23f499b64e66 Reviewed-by: Oswald Buddenhagen --- mkspecs/android-g++/qmake.conf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mkspecs/android-g++/qmake.conf b/mkspecs/android-g++/qmake.conf index 28f5638463a..ef78c42de9f 100644 --- a/mkspecs/android-g++/qmake.conf +++ b/mkspecs/android-g++/qmake.conf @@ -168,13 +168,6 @@ QMAKE_STRIP = QMAKE_RANLIB = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-ranlib -QMAKE_INCDIR = $$ANDROID_SOURCES_CXX_STL_INCDIR $$QMAKE_ANDROID_PLATFORM_INCDIR -QMAKE_LIBDIR = $$ANDROID_SOURCES_CXX_STL_LIBDIR $$QMAKE_ANDROID_PLATFORM_LIBDIR $$LIBGCC_PATH -QMAKE_INCDIR_X11 = -QMAKE_LIBDIR_X11 = -QMAKE_INCDIR_OPENGL = $$QMAKE_ANDROID_PLATFORM_INCDIR -QMAKE_LIBDIR_OPENGL = $$QMAKE_ANDROID_PLATFORM_LIBDIR - equals(ANDROID_TARGET_ARCH, armeabi)|equals(ANDROID_TARGET_ARCH, armeabi-v7a): \ LIBGCC_PATH_FULL = $$system("$$QMAKE_CC -mthumb-interwork -print-libgcc-file-name") else: \ @@ -182,6 +175,13 @@ else: \ LIBGCC_PATH = $$dirname(LIBGCC_PATH_FULL) +QMAKE_INCDIR = $$ANDROID_SOURCES_CXX_STL_INCDIR $$QMAKE_ANDROID_PLATFORM_INCDIR +QMAKE_LIBDIR = $$ANDROID_SOURCES_CXX_STL_LIBDIR $$QMAKE_ANDROID_PLATFORM_LIBDIR $$LIBGCC_PATH +QMAKE_INCDIR_X11 = +QMAKE_LIBDIR_X11 = +QMAKE_INCDIR_OPENGL = $$QMAKE_ANDROID_PLATFORM_INCDIR +QMAKE_LIBDIR_OPENGL = $$QMAKE_ANDROID_PLATFORM_LIBDIR + QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK_SHLIB = $$QMAKE_CXX QMAKE_LFLAGS = --sysroot=$$ANDROID_PLATFORM_ROOT_PATH From 0f559a2d998d7ff5b7dec83a1c7e8a9996cbaa26 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 25 Apr 2016 10:59:31 -0700 Subject: [PATCH 074/173] Force the use of the C++11 alignof keyword instead of an extension If the compiler supports C++11 alignof, let's use it. No point in perpetuating the use of __alignof__ or __alignof. There's a fallback implementation in qglobal.h that works even without compiler extensions. We can't drop it just yet (alignas is not a required C++11 feature), but at this point I doubt that fallback is used anywhere anymore. The tst_compiler test was wrong to use alignof(variable). That's not permitted by the standard nor would it work with our fallback implementation. MSVC 2015 enforces this, but ICC, GCC and Clang don't. Change-Id: Ifea6e497f11a461db432ffff1448abfa86672c63 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/global/qcompilerdetection.h | 3 ++- tests/auto/other/compiler/tst_compiler.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index ad881ef4c94..01b3a298af6 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1053,7 +1053,8 @@ # define Q_DECL_NOTHROW Q_DECL_NOEXCEPT #endif -#if defined(Q_COMPILER_ALIGNOF) && !defined(Q_ALIGNOF) +#if defined(Q_COMPILER_ALIGNOF) +# undef Q_ALIGNOF # define Q_ALIGNOF(x) alignof(x) #endif diff --git a/tests/auto/other/compiler/tst_compiler.cpp b/tests/auto/other/compiler/tst_compiler.cpp index 540c155fd8d..8cd25bf1645 100644 --- a/tests/auto/other/compiler/tst_compiler.cpp +++ b/tests/auto/other/compiler/tst_compiler.cpp @@ -636,9 +636,10 @@ void tst_Compiler::cxx11_alignas() #ifndef Q_COMPILER_ALIGNAS QSKIP("Compiler does not support C++11 feature"); #else - alignas(double) char c; - Q_UNUSED(c); - QCOMPARE(Q_ALIGNOF(c), Q_ALIGNOF(double)); + struct S { + alignas(double) char c; + }; + QCOMPARE(Q_ALIGNOF(S), Q_ALIGNOF(double)); #endif } From 261f9101dd8b03019251cf9aa58382de0fbde2e7 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 15 May 2016 14:53:38 +0300 Subject: [PATCH 075/173] QLockFile: Use a more robust stale file detection When a process that locked a lockfile crashes on Windows, sometimes a new instance of the process fails to lock. Unfortunately, I can't find a way to reproduce the problem consistently, but it happens from time to time with Qt Creator and Qbs. There are several ways to detect a dead process on Windows. Some of them can be found in stackoverflow[1]. The current implementation of stale lock detection is based on the second answer (using WaitForSingleObject), but apparently it doesn't work in 100% of the cases. The most voted answer[2] (using GetProcessExitCode) proves to work also on this case. [1] http://stackoverflow.com/q/1591342/764870 [2] http://stackoverflow.com/a/1591379/764870 Task-number: QTBUG-53392 Change-Id: Ied7bf00985d0f12e833b887a0143f7bdeee3e772 Reviewed-by: Kai Koehne Reviewed-by: Thiago Macieira --- src/corelib/io/qlockfile_win.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index 5bd1ba04c91..e72e486cce0 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -137,9 +137,11 @@ bool QLockFilePrivate::isApparentlyStale() const if (!procHandle) return true; // We got a handle but check if process is still alive - DWORD dwR = ::WaitForSingleObject(procHandle, 0); + DWORD exitCode = 0; + if (!::GetExitCodeProcess(procHandle, &exitCode)) + exitCode = 0; ::CloseHandle(procHandle); - if (dwR == WAIT_TIMEOUT) + if (exitCode != STILL_ACTIVE) return true; const QString processName = processNameByPid(pid); if (!processName.isEmpty() && processName != appname) From 16864c42d6bc0ee6b3e3fa03123ef5884557ceea Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 May 2016 14:40:20 -0700 Subject: [PATCH 076/173] Fix linking of the minimal platform plugin on OS X platformsupport/fontdatabases/fontdatabases.pri disables all font databases except CoreText on OS X, so this is required for linking. Otherwise, we get undefined reference linker errors: Undefined symbols for architecture x86_64: "vtable for QBasicFontDatabase", referenced from: QMinimalIntegration::fontDatabase() const in qminimalintegration.o Change-Id: I31298e973803b4d6eedbf61607056114d1556584 Reviewed-by: Jake Petroules --- src/plugins/platforms/minimal/minimal.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/minimal/minimal.pro b/src/plugins/platforms/minimal/minimal.pro index 0d31d6605b3..bd6f2d8e6fe 100644 --- a/src/plugins/platforms/minimal/minimal.pro +++ b/src/plugins/platforms/minimal/minimal.pro @@ -11,6 +11,7 @@ HEADERS = qminimalintegration.h \ OTHER_FILES += minimal.json CONFIG += qpa/genericunixfontdatabase +darwin: DEFINES += QT_NO_FONTCONFIG PLUGIN_TYPE = platforms PLUGIN_CLASS_NAME = QMinimalIntegrationPlugin From 6d31d3e7effabcc998792283249d46f5c0d73b3d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 May 2016 20:28:33 -0700 Subject: [PATCH 077/173] Fix build with ICC on OS X: __Z18qt_getQtMetaObjectv was undefiend It's inline, but the compiler did not inline it properly from Objective C++ sources. Undefined symbols for architecture x86_64: "__Z18qt_getQtMetaObjectv", referenced from: __ZN2Qt20qt_getEnumMetaObjectENS_15ScrollBarPolicyE in qlocale_mac.o ... Change-Id: Ie9fd7afe060b4e4a8052fffd144fda60c50a9779 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobject.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 771d2f5ea04..b39eefa7959 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -444,8 +444,7 @@ protected: QScopedPointer d_ptr; static const QMetaObject staticQtMetaObject; - friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT - { return &staticQtMetaObject; } + friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT; friend struct QMetaObject; friend struct QMetaObjectPrivate; @@ -476,6 +475,9 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch const char *amember, Qt::ConnectionType atype) const { return connect(asender, asignal, this, amember, atype); } +inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT +{ return &QObject::staticQtMetaObject; } + #ifndef QT_NO_USERDATA class Q_CORE_EXPORT QObjectUserData { public: From 32c301e2296c5b3ba31528e6d92b521d43a216e9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 29 May 2016 17:45:05 -0300 Subject: [PATCH 078/173] Fix crash when connecting a non-PMF with Qt::UniqueConnection... ...if a PMF connection had already happened. Since UniqueConnection isn't implemented for non-PMFs (functors and lambdas aren't comparable, even if static member functions or non-member functions are), we pass a null pointer for comparison argument. The disconnect() code already protected against a null pointer there, but not the connect code path with Qt::UniqueConnection Change-Id: I87e17314d8b24ae983b1fffd145324beced0494d Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Dario Freddi --- src/corelib/kernel/qobject.cpp | 2 +- .../auto/corelib/kernel/qobject/tst_qobject.cpp | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index d97f8d0ef1d..a21dbffad5f 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4683,7 +4683,7 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); - if (type & Qt::UniqueConnection) { + if (type & Qt::UniqueConnection && slot) { QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; if (connectionLists && connectionLists->count() > signal_index) { const QObjectPrivate::Connection *c2 = diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 5b89ef37929..46889225ebb 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -139,6 +139,7 @@ private slots: void connectFunctorOverloads(); void connectFunctorQueued(); void connectFunctorWithContext(); + void connectFunctorWithContextUnique(); void connectFunctorDeadlock(); void connectStaticSlotWithObject(); void disconnectDoesNotLeakFunctor(); @@ -5800,6 +5801,22 @@ void tst_QObject::connectFunctorWithContext() context->deleteLater(); } +void tst_QObject::connectFunctorWithContextUnique() +{ + // Qt::UniqueConnections currently don't work for functors, but we need to + // be sure that they don't crash. If that is implemented, change this test. + + SenderObject sender; + ReceiverObject receiver; + QObject::connect(&sender, &SenderObject::signal1, &receiver, &ReceiverObject::slot1); + receiver.count_slot1 = 0; + + QObject::connect(&sender, &SenderObject::signal1, &receiver, SlotFunctor(), Qt::UniqueConnection); + + sender.emitSignal1(); + QCOMPARE(receiver.count_slot1, 1); +} + class MyFunctor { public: From fae8ee8b428ae7a406199e504b2d0eedd5059dbd Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 19 May 2016 18:46:39 -0700 Subject: [PATCH 079/173] Update the high scaling settings after an XCB screen is added Without this, the newly-added screen will still have the scaleFactorProperty unset, which means QScreen::devicePixelRatio will return 1.0. That differs from what happens if the screen had been detected when the application started. This is part of the fix for the bug report, but insufficient. Task-number: QTBUG-53500 Change-Id: Id3aab65533904562a6cbfffd14502365d86bd36d Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 669ef3a98e3..b5c50289956 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -32,6 +32,7 @@ ****************************************************************************/ #include +#include #include #include "qxcbconnection.h" @@ -257,6 +258,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) } else { screen = createScreen(virtualDesktop, output, outputInfo.data()); qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled"; + QHighDpiScaling::updateHighDpiScaling(); } } } else if (screen) { From b403b8c094a1bf59b70368e28cbd454b6872498f Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Thu, 26 May 2016 23:09:36 +0200 Subject: [PATCH 080/173] Add Interix OS system detection defines NetBSD (pkgsrc) ports are building qt on Interix as well, where the necessary defines are missing for in qsystemdetection.h. Patch for adding them provided by NetBSD ports maintainer Kamil Rytarowski Change-Id: I769c47f623317efda3130a7061307e84d3350fac Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/global/qsystemdetection.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index f1abc88b990..b6a7835ef23 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -60,6 +60,7 @@ NETBSD - NetBSD OPENBSD - OpenBSD BSDI - BSD/OS + INTERIX - Interix IRIX - SGI Irix OSF - HP Tru64 UNIX SCO - SCO OpenServer 5 @@ -147,6 +148,9 @@ #elif defined(__bsdi__) # define Q_OS_BSDI # define Q_OS_BSD4 +#elif defined(__INTERIX) +# define Q_OS_INTERIX +# define Q_OS_BSD4 #elif defined(__sgi) # define Q_OS_IRIX #elif defined(__osf__) From 1d9d16515853932205d4ca82a385dfb9c2221394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Tue, 24 May 2016 16:30:02 +0200 Subject: [PATCH 081/173] QAbstractItemView: Reset the drop indicator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always reset the drop indicator position and rect when drag action will be finished. This can prevent drawing the indicator in bad place when the next drag will be performed. Task-number: QTBUG-53541 Change-Id: I420207a0ede6f19f48472a8f0f723afe948de1c6 Reviewed-by: Friedemann Kleint Reviewed-by: Thorbjørn Lund Martsum --- src/widgets/itemviews/qabstractitemview.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index 9dbe5c6c543..057718cdba6 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -3620,6 +3620,9 @@ void QAbstractItemView::startDrag(Qt::DropActions supportedActions) defaultDropAction = Qt::CopyAction; if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction) d->clearOrRemove(); + // Reset the drop indicator + d->dropIndicatorRect = QRect(); + d->dropIndicatorPosition = OnItem; } } #endif // QT_NO_DRAGANDDROP From 886086f5d39a317443018689f817e8eb8ecb0be8 Mon Sep 17 00:00:00 2001 From: Aleksei Timofeyev Date: Fri, 22 Apr 2016 12:57:17 +0500 Subject: [PATCH 082/173] QWindowsPipeWriter: Discard queued signals in stop() The _q_queueBytesWritten signal may be already queued from the event loop at the time when stop() is called. We do not want to emit signals once stopped, so reset all respective state variables. Change-Id: I343e1702955e0bbc1d11930d19e75dab6e129b4c Reviewed-by: Alex Trotsenko Reviewed-by: Joerg Bornemann --- src/corelib/io/qwindowspipewriter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index 839dc8a19ca..3731aba97bc 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -202,6 +202,8 @@ bool QWindowsPipeWriter::write(const QByteArray &ba) void QWindowsPipeWriter::stop() { stopped = true; + bytesWrittenPending = false; + pendingBytesWrittenValue = 0; if (writeSequenceStarted) { if (!qt_cancelIo(handle, &overlapped)) { const DWORD dwError = GetLastError(); From 00061b968d23d34cdbd43e0930463be06a2775b3 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 25 Apr 2016 15:43:57 +0200 Subject: [PATCH 083/173] Fix opaque texture-based widgets not being always shown. Whenever a regular QWidget contains a child render-to-texture widget (like a QOpenGLWidget) that is opaque (attribute Qt::WA_OpaquePaintEvent is set) and completely covers the parent geometry, the child widget would not be shown. This happens because QWidgetBackingStore::doSync contains a check to see if an opaque child completely covers its parent, in which case it does not draw the parent, and only draws the child. This is an issue if the widget is actually a texture-based one, because for it to be seen on screen, the parent widget has to be redrawn with a proper blending mask, so that the rtt widget gets properly composed into the place where the mask is. The fix consists in keeping the parent widget being marked dirty, in case it has an opaque texture-based child that completely covers it. This will force a redraw of the parent widget with a proper blending mask. Change-Id: If1feec04b86bff2c49158b8d72f175cec252dea1 Task-number: QTBUG-52123 Reviewed-by: Allan Sandfeld Jensen --- src/widgets/kernel/qwidgetbackingstore.cpp | 10 ++ .../qopenglwidget/tst_qopenglwidget.cpp | 133 ++++++++++++++++++ 2 files changed, 143 insertions(+) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 049ed248de7..5d13fb926b3 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -1211,10 +1211,20 @@ void QWidgetBackingStore::doSync() // We know for sure that the widget isn't overlapped if 'isMoved' is true. if (!wd->isMoved) wd->subtractOpaqueSiblings(wd->dirty, &hasDirtySiblingsAbove); + + // Make a copy of the widget's dirty region, to restore it in case there is an opaque + // render-to-texture child that completely covers the widget, because otherwise the + // render-to-texture child won't be visible, due to its parent widget not being redrawn + // with a proper blending mask. + const QRegion dirtyBeforeSubtractedOpaqueChildren = wd->dirty; + // Scrolled and moved widgets must draw all children. if (!wd->isScrolled && !wd->isMoved) wd->subtractOpaqueChildren(wd->dirty, w->rect()); + if (wd->dirty.isEmpty() && wd->textureChildSeen) + wd->dirty = dirtyBeforeSubtractedOpaqueChildren; + if (wd->dirty.isEmpty()) { resetWidget(w); continue; diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp index a4a00452650..f5c127a0639 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp +++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp @@ -34,11 +34,14 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include @@ -59,6 +62,7 @@ private slots: void fboRedirect(); void showHide(); void nativeWindow(); + void stackWidgetOpaqueChildIsVisible(); }; void tst_QOpenGLWidget::create() @@ -425,6 +429,135 @@ void tst_QOpenGLWidget::nativeWindow() QVERIFY(image.pixel(30, 40) == qRgb(0, 255, 0)); } +static inline QString msgRgbMismatch(unsigned actual, unsigned expected) +{ + return QString::asprintf("Color mismatch, %#010x != %#010x", actual, expected); +} + +static QPixmap grabWidgetWithoutRepaint(const QWidget *widget, QRect clipArea) +{ + const QWidget *targetWidget = widget; +#ifdef Q_OS_WIN + // OpenGL content is not properly grabbed on Windows when passing a top level widget window, + // because GDI functions can't grab OpenGL layer content. + // Instead the whole screen should be captured, with an adjusted clip area, which contains + // the final composited content. + QDesktopWidget *desktopWidget = QApplication::desktop(); + const QWidget *mainScreenWidget = desktopWidget->screen(); + targetWidget = mainScreenWidget; + clipArea = QRect(widget->mapToGlobal(clipArea.topLeft()), + widget->mapToGlobal(clipArea.bottomRight())); +#endif + + const QWindow *window = targetWidget->window()->windowHandle(); + Q_ASSERT(window); + WId windowId = window->winId(); + + QScreen *screen = window->screen(); + Q_ASSERT(screen); + + const QSize size = clipArea.size(); + const QPixmap result = screen->grabWindow(windowId, + clipArea.x(), + clipArea.y(), + size.width(), + size.height()); + return result; +} + +#define VERIFY_COLOR(child, region, color) verifyColor(child, region, color, __LINE__) + +bool verifyColor(const QWidget *widget, const QRect &clipArea, const QColor &color, int callerLine) +{ + for (int t = 0; t < 6; t++) { + const QPixmap pixmap = grabWidgetWithoutRepaint(widget, clipArea); + if (!QTest::qCompare(pixmap.size(), + clipArea.size(), + "pixmap.size()", + "rect.size()", + __FILE__, + callerLine)) + return false; + + + const QImage image = pixmap.toImage(); + QPixmap expectedPixmap(pixmap); /* ensure equal formats */ + expectedPixmap.detach(); + expectedPixmap.fill(color); + + uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; + uint firstPixel = image.pixel(0,0) | alphaCorrection; + + // Retry a couple of times. Some window managers have transparency animation, or are + // just slow to render. + if (t < 5) { + if (firstPixel == QColor(color).rgb() + && image == expectedPixmap.toImage()) + return true; + else + QTest::qWait(200); + } else { + if (!QTest::qVerify(firstPixel == QColor(color).rgb(), + "firstPixel == QColor(color).rgb()", + qPrintable(msgRgbMismatch(firstPixel, QColor(color).rgb())), + __FILE__, callerLine)) { + return false; + } + if (!QTest::qVerify(image == expectedPixmap.toImage(), + "image == expectedPixmap.toImage()", + "grabbed pixmap differs from expected pixmap", + __FILE__, callerLine)) { + return false; + } + } + } + + return false; +} + +void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible() +{ +#ifdef Q_OS_OSX + QSKIP("QScreen::grabWindow() doesn't work properly on OSX HighDPI screen: QTBUG-46803"); + return; +#endif + + QStackedWidget stack; + + QWidget* emptyWidget = new QWidget(&stack); + stack.addWidget(emptyWidget); + + // Create an opaque red QOpenGLWidget. + const int dimensionSize = 400; + ClearWidget* clearWidget = new ClearWidget(&stack, dimensionSize, dimensionSize); + clearWidget->setAttribute(Qt::WA_OpaquePaintEvent); + stack.addWidget(clearWidget); + + // Show initial QWidget. + stack.setCurrentIndex(0); + stack.resize(dimensionSize, dimensionSize); + stack.show(); + QTest::qWaitForWindowExposed(&stack); + QTest::qWaitForWindowActive(&stack); + + // Switch to the QOpenGLWidget. + stack.setCurrentIndex(1); + QTRY_COMPARE(clearWidget->m_paintCalled, true); + + // Resize the tested region to be half size in the middle, because some OSes make the widget + // have rounded corners (e.g. OSX), and the grabbed window pixmap will not coincide perfectly + // with what was actually painted. + QRect clipArea = stack.rect(); + clipArea.setSize(clipArea.size() / 2); + const int translationOffsetToMiddle = dimensionSize / 4; + clipArea.translate(translationOffsetToMiddle, translationOffsetToMiddle); + + // Verify that the QOpenGLWidget was actually painted AND displayed. + const QColor red(255, 0, 0, 255); + VERIFY_COLOR(&stack, clipArea, red); + #undef VERIFY_COLOR +} + QTEST_MAIN(tst_QOpenGLWidget) #include "tst_qopenglwidget.moc" From dc7538441a21b4810005a6556dc3a9e32399b20c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sat, 28 May 2016 16:31:23 +0200 Subject: [PATCH 084/173] install the qtpng library it's used outside qtbase (by qtimageformats), so this is needed for modular builds to work. Change-Id: I3dffa76178502894bd063af366bd9a74be3b316a Reviewed-by: Joerg Bornemann --- src/3rdparty/libpng/libpng.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/libpng/libpng.pro b/src/3rdparty/libpng/libpng.pro index 7d51c30cb4d..ab6dd51e2b4 100644 --- a/src/3rdparty/libpng/libpng.pro +++ b/src/3rdparty/libpng/libpng.pro @@ -3,7 +3,8 @@ TARGET = qtpng CONFIG += \ static \ hide_symbols \ - exceptions_off rtti_off warn_off + exceptions_off rtti_off warn_off \ + installed load(qt_helper_lib) From 2cf099e9f6bd482e9f7e938ccd949c5b5e6aea95 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 3 May 2016 23:07:17 -0700 Subject: [PATCH 085/173] tst_Moc: restore signals/slots/emit to the Q_UPPERCASE values The previous definition of signals does not need to be "public". It may have been something else. Change-Id: Id69569111e7d4e619e22ffff144b4855e6acdbef Reviewed-by: Olivier Goffart (Woboq GmbH) --- tests/auto/tools/moc/no-keywords.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/tools/moc/no-keywords.h b/tests/auto/tools/moc/no-keywords.h index 56a906e6a93..d31063665b9 100644 --- a/tests/auto/tools/moc/no-keywords.h +++ b/tests/auto/tools/moc/no-keywords.h @@ -70,9 +70,9 @@ private: double slots; }; -#define signals public -#define slots -#define emit +#define signals Q_SIGNALS +#define slots Q_SLOTS +#define emit Q_EMIT #undef QT_NO_KEYWORDS #endif // NO_KEYWORDS_H From e4d838ff9d7bedfd88d45fd833f13f0976265b3a Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Fri, 29 Apr 2016 15:40:46 +0300 Subject: [PATCH 086/173] QDateTimeParser: adapt to make good use of QStringRef. Avoid unnecessary allocations. Create QString from QStringRef only where necessary. Change-Id: I8f2a7dce51430162c84328e23ab3cc071227d6ae Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetimeparser.cpp | 23 ++++++++++++----------- src/corelib/tools/qdatetimeparser_p.h | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index cc8c08d5b1c..9c9009d6366 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -708,17 +708,18 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde } const int sectionmaxsize = sectionMaxSize(sectionIndex); - QString sectiontext = text.mid(index, sectionmaxsize); - int sectiontextSize = sectiontext.size(); + QStringRef sectionTextRef = text.midRef(index, sectionmaxsize); + int sectiontextSize = sectionTextRef.size(); QDTPDEBUG << "sectionValue for" << sn.name() - << "with text" << text << "and st" << sectiontext + << "with text" << text << "and st" << sectionTextRef << text.midRef(index, sectionmaxsize) << index; int used = 0; switch (sn.type) { case AmPmSection: { + QString sectiontext = sectionTextRef.toString(); const int ampm = findAmPm(sectiontext, sectionIndex, &used); switch (ampm) { case AM: // sectiontext == AM @@ -750,6 +751,7 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde case DayOfWeekSectionShort: case DayOfWeekSectionLong: if (sn.count >= 3) { + QString sectiontext = sectionTextRef.toString(); if (sn.type == MonthSection) { int min = 1; const QDate minDate = getMinimum().date(); @@ -788,7 +790,7 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde int last = -1; used = -1; - QString digitsStr(sectiontext); + QStringRef digitsStr = sectionTextRef; for (int i = 0; i < sectiontextSize; ++i) { if (digitsStr.at(i).isSpace()) { sectiontextSize = i; @@ -809,7 +811,7 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde } } if (ok && tmp <= absMax) { - QDTPDEBUG << sectiontext.leftRef(digits) << tmp << digits; + QDTPDEBUG << sectionTextRef.left(digits) << tmp << digits; last = tmp; used = digits; break; @@ -817,13 +819,13 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde } if (last == -1) { - QChar first(sectiontext.at(0)); + QChar first(sectionTextRef.at(0)); if (separators.at(sectionIndex + 1).startsWith(first)) { used = 0; state = Intermediate; } else { state = Invalid; - QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok; + QDTPDEBUG << "invalid because" << sectionTextRef << "can't become a uint" << last << ok; } } else { num += last; @@ -1565,7 +1567,7 @@ QString QDateTimeParser::SectionNode::format() const number that is within min and max. */ -bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index, +bool QDateTimeParser::potentialValue(const QStringRef &str, int min, int max, int index, const QDateTime ¤tValue, int insert) const { if (str.isEmpty()) { @@ -1592,8 +1594,7 @@ bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int i if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) { return true; } else if (insert >= 0) { - QString tmp = str; - tmp.insert(insert, QLatin1Char('0' + j)); + const QString tmp = str.left(insert) + QLatin1Char('0' + j) + str.mid(insert); if (potentialValue(tmp, min, max, index, currentValue, insert)) return true; } @@ -1603,7 +1604,7 @@ bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int i return false; } -bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QString &text) const +bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QStringRef &text) const { Q_ASSERT(current >= getMinimum() && current <= getMaximum()); diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h index 9689d88616e..01a2f208023 100644 --- a/src/corelib/tools/qdatetimeparser_p.h +++ b/src/corelib/tools/qdatetimeparser_p.h @@ -214,9 +214,19 @@ public: QString *dayName = 0, int *used = 0) const; #endif AmPmFinder findAmPm(QString &str, int index, int *used = 0) const; - bool potentialValue(const QString &str, int min, int max, int index, + bool potentialValue(const QStringRef &str, int min, int max, int index, const QDateTime ¤tValue, int insert) const; - bool skipToNextSection(int section, const QDateTime ¤t, const QString §ionText) const; + bool potentialValue(const QString &str, int min, int max, int index, + const QDateTime ¤tValue, int insert) const + { + return potentialValue(QStringRef(&str), min, max, index, currentValue, insert); + } + + bool skipToNextSection(int section, const QDateTime ¤t, const QStringRef §ionText) const; + bool skipToNextSection(int section, const QDateTime ¤t, const QString §ionText) const + { + return skipToNextSection(section, current, QStringRef(§ionText)); + } QString stateName(State s) const; From 08f0253c4afc352aadf8b138c04d6c55e4e91167 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Mon, 14 Mar 2016 12:33:45 +0100 Subject: [PATCH 087/173] Add manual test for shortcut using implicit AltGr In German layout, "Ctrl+]" is "Ctrl+AltGr+9". Task-number: QTBUG-51848 Change-Id: I8c05c13a4d46c0818ce4f56ce476c5310a677af2 Reviewed-by: Frederik Gladhorn --- tests/manual/shortcuts/main.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/manual/shortcuts/main.cpp b/tests/manual/shortcuts/main.cpp index 91477d5146b..55ade1040ad 100644 --- a/tests/manual/shortcuts/main.cpp +++ b/tests/manual/shortcuts/main.cpp @@ -92,16 +92,20 @@ protected: QPushButton *b12 = new QPushButton(sq12.toString()); b12->setShortcut(sq12); - // LATIN SMALL LETTER O WITH STROKE - QKeySequence sq13(QString(QChar(ushort(0xf8)))); + QKeySequence sq13(Qt::ControlModifier + Qt::Key_BracketRight); QPushButton *b13 = new QPushButton(sq13.toString()); b13->setShortcut(sq13); - // CYRILLIC SMALL LETTER ZHE - QKeySequence sq14(QString(QChar(ushort(0x436)))); + // LATIN SMALL LETTER O WITH STROKE + QKeySequence sq14(QString(QChar(ushort(0xf8)))); QPushButton *b14 = new QPushButton(sq14.toString()); b14->setShortcut(sq14); + // CYRILLIC SMALL LETTER ZHE + QKeySequence sq15(QString(QChar(ushort(0x436)))); + QPushButton *b15 = new QPushButton(sq15.toString()); + b15->setShortcut(sq15); + QLabel *testPurpose = new QLabel(); testPurpose->setWordWrap(true); testPurpose->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding); @@ -120,10 +124,11 @@ protected: layout->addWidget(b10); layout->addWidget(b11); layout->addWidget(b12); - layout->addWidget(new QLabel("Norwegian layout")); layout->addWidget(b13); - layout->addWidget(new QLabel("Russian layout")); + layout->addWidget(new QLabel("Norwegian layout")); layout->addWidget(b14); + layout->addWidget(new QLabel("Russian layout")); + layout->addWidget(b15); setLayout(layout); } From 2f0ffba638bdb868a810bc0349c240b6b6e172cd Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 30 May 2016 14:15:49 +0200 Subject: [PATCH 088/173] Fix emission of QProcess:errorOccurred Consistently use setErrorAndEmit to emit errorOccurred and the deprecated error signal. Change-Id: I8bc7634a72d4d13f74bbf76547de08271dfcbb59 Reviewed-by: Kai Koehne --- src/corelib/io/qprocess.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 502628489dc..6e1a7712587 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -2090,10 +2090,7 @@ void QProcess::start(const QString &program, const QStringList &arguments, OpenM return; } if (program.isEmpty()) { - Q_D(QProcess); - d->processError = QProcess::FailedToStart; - setErrorString(tr("No program defined")); - emit error(d->processError); + d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined")); return; } @@ -2120,10 +2117,7 @@ void QProcess::start(OpenMode mode) return; } if (d->program.isEmpty()) { - Q_D(QProcess); - d->processError = QProcess::FailedToStart; - setErrorString(tr("No program defined")); - emit error(d->processError); + d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined")); return; } From eb50193136c7c73be864e3232d01e98ddc24e539 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 26 Apr 2016 14:33:17 +0200 Subject: [PATCH 089/173] QDialog::adjustPosition(): Manually set target screen before moving. QDialog::adjustPosition() can move the dialog across screens. A call to QWindow::resize() later in the show sequence might then see the wrong scaling factor if the screen changed notification is still stuck in an event queue. Prevent that by setting the target screen early on. Task-number: QTBUG-52735 Change-Id: I17bb3490b660f8f17c36524457cb87adbb7851e9 Reviewed-by: Andy Shaw --- src/widgets/dialogs/qdialog.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp index 5124960ab49..45d2279ed52 100644 --- a/src/widgets/dialogs/qdialog.cpp +++ b/src/widgets/dialogs/qdialog.cpp @@ -860,6 +860,12 @@ void QDialog::adjustPosition(QWidget* w) if (p.y() < desk.y()) p.setY(desk.y()); + // QTBUG-52735: Manually set the correct target screen since scaling in a + // subsequent call to QWindow::resize() may otherwise use the wrong factor + // if the screen changed notification is still in an event queue. + if (QWindow *window = windowHandle()) + window->setScreen(QGuiApplication::screens().at(scrn)); + move(p); } From 28db26f6917174d787bd4c6eadbecebc952d59dc Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 30 May 2016 15:25:06 +0200 Subject: [PATCH 090/173] qtestcase: Fix buffer over-run, '\0' appended beyond buffer end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Noticed by Coverity (CID 161673). If the file being read contains enough to fill the buffer, read() shall do that and return the nbytes it was passed; as this was the size of the buffer, subsequently writing a '\0' at this index in buffer is out of bounds. Fortunately, /proc/self/status is typically < 1k so fits well inside the 2k buffer. All the same, we can safely pass sizeof(buffer) - 1 as nbytes and *be sure* of not getting a buffer over-run. Change-Id: Ib620a330fbc94f0579c953737f7c4417ca449968 Reviewed-by: Jędrzej Nowacki --- src/testlib/qtestcase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 62649441dbc..eae490e278b 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2514,7 +2514,7 @@ static bool debuggerPresent() if (fd == -1) return false; char buffer[2048]; - ssize_t size = read(fd, buffer, sizeof(buffer)); + ssize_t size = read(fd, buffer, sizeof(buffer) - 1); if (size == -1) { close(fd); return false; From a9bef62ec216a4c0c4f95ca45e1e98ef96ca42f3 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 31 May 2016 13:15:56 +0200 Subject: [PATCH 091/173] Compile fix for OpenBSD using Q_OS_OPENBSD defines OpenBSD does not have EPROTO and LLINDEX.. LLINDEX is only a macro pointing at sdl_index so use the FreeBSD macro from as a a workaround. Change-Id: Ic3ccecc1b671bb28d14da83ba915ec3fcad2657d Reviewed-by: Richard J. Moore --- src/network/socket/qnativesocketengine_unix.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 6a740f4c30e..e92123e10cc 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -573,7 +573,9 @@ int QNativeSocketEnginePrivate::nativeAccept() setError(QAbstractSocket::SocketResourceError, NotSocketErrorString); break; case EPROTONOSUPPORT: +#if !defined(Q_OS_OPENBSD) case EPROTO: +#endif case EAFNOSUPPORT: case EINVAL: setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString); @@ -904,7 +906,9 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(sockaddr_dl))) { sockaddr_dl *sdl = reinterpret_cast(CMSG_DATA(cmsgptr)); - +# if defined(Q_OS_OPENBSD) +# define LLINDEX(s) ((s)->sdl_index) +# endif header->ifindex = LLINDEX(sdl); } # endif From ed08e3be340ff0592ea6e11435d9546db4a9366f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 31 May 2016 13:21:58 +0200 Subject: [PATCH 092/173] tst_QPlainTextEdit/tst_QTextEdit: Do not output unprintable characters. The test selectWordsFromStringsContainingSeparators() duplicated in boths tests caused tab and Nbsp characters to be output to the log, which upsets editors. Use an array of ushort instead of a wasteful QStringList and output the hex codes for the unprintable characters. Change-Id: I08724268f376b4c0da492b4109570e44f7d4a3fb Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qplaintextedit/tst_qplaintextedit.cpp | 17 ++++++++++++----- .../widgets/widgets/qtextedit/tst_qtextedit.cpp | 17 ++++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp index d466489acb0..8c86056ad3e 100644 --- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp +++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp @@ -1184,12 +1184,19 @@ void tst_QPlainTextEdit::selectWordsFromStringsContainingSeparators_data() QTest::addColumn("testString"); QTest::addColumn("selectedWord"); - QStringList wordSeparators; - wordSeparators << "." << "," << "?" << "!" << ":" << ";" << "-" << "<" << ">" << "[" - << "]" << "(" << ")" << "{" << "}" << "=" << "\t"<< QString(QChar::Nbsp); + const ushort wordSeparators[] = + {'.', ',', '?', '!', ':', ';', '-', '<', '>', '[', ']', '(', ')', '{', '}', + '=', '\t', ushort(QChar::Nbsp)}; - foreach (QString s, wordSeparators) - QTest::newRow(QString("separator: " + s).toLocal8Bit()) << QString("foo") + s + QString("bar") << QString("foo"); + for (size_t i = 0, count = sizeof(wordSeparators) / sizeof(wordSeparators[0]); i < count; ++i) { + const ushort u = wordSeparators[i]; + QByteArray rowName = QByteArrayLiteral("separator: "); + if (u >= 32 && u < 128) + rowName += char(u); + else + rowName += QByteArrayLiteral("0x") + QByteArray::number(u, 16); + QTest::newRow(rowName.constData()) << QString("foo") + QChar(u) + QString("bar") << QString("foo"); + } } void tst_QPlainTextEdit::selectWordsFromStringsContainingSeparators() diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp index b81e4df1230..690a25a87de 100644 --- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp @@ -1530,12 +1530,19 @@ void tst_QTextEdit::selectWordsFromStringsContainingSeparators_data() QTest::addColumn("testString"); QTest::addColumn("selectedWord"); - QStringList wordSeparators; - wordSeparators << "." << "," << "?" << "!" << ":" << ";" << "-" << "<" << ">" << "[" - << "]" << "(" << ")" << "{" << "}" << "=" << "\t"<< QString(QChar::Nbsp); + const ushort wordSeparators[] = + {'.', ',', '?', '!', ':', ';', '-', '<', '>', '[', ']', '(', ')', '{', '}', + '=', '\t', ushort(QChar::Nbsp)}; - foreach (QString s, wordSeparators) - QTest::newRow(QString("separator: " + s).toLocal8Bit()) << QString("foo") + s + QString("bar") << QString("foo"); + for (size_t i = 0, count = sizeof(wordSeparators) / sizeof(wordSeparators[0]); i < count; ++i) { + const ushort u = wordSeparators[i]; + QByteArray rowName = QByteArrayLiteral("separator: "); + if (u >= 32 && u < 128) + rowName += char(u); + else + rowName += QByteArrayLiteral("0x") + QByteArray::number(u, 16); + QTest::newRow(rowName.constData()) << QString("foo") + QChar(u) + QString("bar") << QString("foo"); + } } void tst_QTextEdit::selectWordsFromStringsContainingSeparators() From 0ff45fbf1b9a6ab6da2541bb70533e49dc892954 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 30 Mar 2016 09:42:34 +0200 Subject: [PATCH 093/173] winrt: Enable drop support Allow Qt applications to receive drops. Dragging is not supported yet and will be handled in a separate commit. Task-number: QTBUG-50827 Change-Id: I684e3d5685ce73f74805691f6ac7bbc45e2d19ec Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtdrag.cpp | 672 ++++++++++++++++++ src/plugins/platforms/winrt/qwinrtdrag.h | 113 +++ .../platforms/winrt/qwinrtintegration.cpp | 10 + .../platforms/winrt/qwinrtintegration.h | 4 + src/plugins/platforms/winrt/qwinrtscreen.cpp | 12 + src/plugins/platforms/winrt/winrt.pro | 7 + 6 files changed, 818 insertions(+) create mode 100644 src/plugins/platforms/winrt/qwinrtdrag.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtdrag.h diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp new file mode 100644 index 00000000000..a52ed917496 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp @@ -0,0 +1,672 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qwinrtdrag.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace ABI::Windows::ApplicationModel::DataTransfer; +using namespace ABI::Windows::ApplicationModel::DataTransfer::DragDrop; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Storage; +using namespace ABI::Windows::Storage::Streams; +using namespace ABI::Windows::UI::Xaml; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime") + +class DragThreadTransferData : public QObject +{ + Q_OBJECT +public slots: + void handleDrag(); +public: + explicit DragThreadTransferData(QObject *parent = Q_NULLPTR); + QWindow *window; + QWinRTInternalMimeData *mime; + QPoint point; + Qt::DropActions actions; + bool dropAction; + ComPtr nativeArgs; + ComPtr deferral; +}; + +inline QString hStringToQString(const HString &hString) +{ + quint32 l; + const wchar_t *raw = hString.GetRawBuffer(&l); + return (QString::fromWCharArray(raw, l)); +} + +namespace NativeFormatStrings { + static ComPtr dataStatics; + static HSTRING text; // text/plain + static HSTRING html; // text/html + static HSTRING storage; // text/uri-list +} + +static inline DataPackageOperation translateFromQDragDropActions(const Qt::DropAction action) +{ + switch (action) { + case Qt::CopyAction: + return DataPackageOperation_Copy; + case Qt::MoveAction: + return DataPackageOperation_Move; + case Qt::LinkAction: + return DataPackageOperation_Link; + case Qt::IgnoreAction: + default: + return DataPackageOperation_None; + } +} + +static inline Qt::DropActions translateToQDragDropActions(const DataPackageOperation op) +{ + Qt::DropActions actions = Qt::IgnoreAction; + // None needs to be interpreted as the sender being able to handle + // anything and let the receiver decide + if (op == DataPackageOperation_None) + actions = Qt::LinkAction | Qt::CopyAction | Qt::MoveAction; + if (op & DataPackageOperation_Link) + actions |= Qt::LinkAction; + if (op & DataPackageOperation_Copy) + actions |= Qt::CopyAction; + if (op & DataPackageOperation_Move) + actions |= Qt::MoveAction; + return actions; +} + +QWinRTInternalMimeData::QWinRTInternalMimeData() + : QInternalMimeData() +{ + qCDebug(lcQpaMime) << __FUNCTION__; + if (!NativeFormatStrings::dataStatics) { + HRESULT hr; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_StandardDataFormats).Get(), + IID_PPV_ARGS(&NativeFormatStrings::dataStatics)); + Q_ASSERT_SUCCEEDED(hr); + hr = NativeFormatStrings::dataStatics->get_Text(&NativeFormatStrings::text); + Q_ASSERT_SUCCEEDED(hr); + hr = NativeFormatStrings::dataStatics->get_Html(&NativeFormatStrings::html); + Q_ASSERT_SUCCEEDED(hr); + hr = NativeFormatStrings::dataStatics->get_StorageItems(&NativeFormatStrings::storage); + Q_ASSERT_SUCCEEDED(hr); + } +} + +QWinRTInternalMimeData::~QWinRTInternalMimeData() +{ +} + +bool QWinRTInternalMimeData::hasFormat_sys(const QString &mimetype) const +{ + qCDebug(lcQpaMime) << __FUNCTION__ << mimetype; + + if (!dataView) + return false; + + return formats_sys().contains(mimetype); +} + +QStringList QWinRTInternalMimeData::formats_sys() const +{ + qCDebug(lcQpaMime) << __FUNCTION__; + + if (!dataView) + return QStringList(); + + if (!formats.isEmpty()) + return formats; + + boolean contains; + HRESULT hr; + hr = dataView->Contains(NativeFormatStrings::text, &contains); + if (SUCCEEDED(hr) && contains) + formats.append(QLatin1String("text/plain")); + + hr = dataView->Contains(NativeFormatStrings::html, &contains); + if (SUCCEEDED(hr) && contains) + formats.append(QLatin1String("text/html")); + + hr = dataView->Contains(NativeFormatStrings::storage, &contains); + if (SUCCEEDED(hr) && contains) + formats.append(QLatin1String("text/uri-list")); + + // We need to add any additional format as well, for legacy windows + // reasons, but also in case someone adds custom formats. + ComPtr> availableFormats; + hr = dataView->get_AvailableFormats(&availableFormats); + RETURN_IF_FAILED("Could not query available formats.", return formats); + + quint32 size; + hr = availableFormats->get_Size(&size); + RETURN_IF_FAILED("Could not query format vector size.", return formats); + for (quint32 i = 0; i < size; ++i) { + HString str; + hr = availableFormats->GetAt(i, str.GetAddressOf()); + if (FAILED(hr)) + continue; + formats.append(hStringToQString(str)); + } + qDebug() << __FUNCTION__ << "Available formats:" << formats; + return formats; +} + +QVariant QWinRTInternalMimeData::retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const +{ + qCDebug(lcQpaMime) << __FUNCTION__ << mimetype << preferredType; + + if (!dataView || !formats.contains(mimetype)) + return QVariant(); + + QVariant result; + HRESULT hr; + if (mimetype == QLatin1String("text/plain")) { + hr = QEventDispatcherWinRT::runOnXamlThread([this, &result]() { + HRESULT hr; + ComPtr> op; + HString res; + hr = dataView->GetTextAsync(&op); + Q_ASSERT_SUCCEEDED(hr); + hr = QWinRTFunctions::await(op, res.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(hStringToQString(res)); + return S_OK; + }); + } else if (mimetype == QLatin1String("text/uri-list")) { + hr = QEventDispatcherWinRT::runOnXamlThread([this, &result]() { + HRESULT hr; + ComPtr*>> op; + hr = dataView->GetStorageItemsAsync(&op); + Q_ASSERT_SUCCEEDED(hr); + ComPtr> nativeItems; + hr = QWinRTFunctions::await(op, nativeItems.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + QList items; + quint32 count; + hr = nativeItems->get_Size(&count); + for (quint32 i = 0; i < count; ++i) { + ComPtr item; + hr = nativeItems->GetAt(i, &item); + Q_ASSERT_SUCCEEDED(hr); + HString path; + hr = item->get_Path(path.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + items.append(QUrl::fromLocalFile(hStringToQString(path))); + } + result.setValue(items); + return S_OK; + }); + } else if (mimetype == QLatin1String("text/html")) { + hr = QEventDispatcherWinRT::runOnXamlThread([this, &result]() { + HRESULT hr; + ComPtr> op; + HString res; + hr = dataView->GetHtmlFormatAsync(&op); + Q_ASSERT_SUCCEEDED(hr); + hr = QWinRTFunctions::await(op, res.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(hStringToQString(res)); + return S_OK; + }); + } else if (mimetype.startsWith(QLatin1String("image/"))) { + Q_UNIMPLEMENTED(); + } else { + // Asking for custom data + hr = QEventDispatcherWinRT::runOnXamlThread([this, &result, mimetype]() { + HRESULT hr; + ComPtr> op; + ComPtr res; + HString type; + type.Set(reinterpret_cast(mimetype.utf16()), mimetype.size()); + hr = dataView->GetDataAsync(type.Get(), &op); + RETURN_OK_IF_FAILED("Could not query custom drag data."); + hr = QWinRTFunctions::await(op, res.GetAddressOf()); + if (FAILED(hr) || !res) { + qCDebug(lcQpaMime) << "Custom drop data operation returned no results or failed."; + return S_OK; + } + + // Test for properties + ComPtr propertyValue; + hr = res.As(&propertyValue); + if (SUCCEEDED(hr)) { + // We need to check which type of custom data we are receiving + PropertyType type; + propertyValue->get_Type(&type); + switch (type) { + case PropertyType_UInt8: { + quint8 v; + hr = propertyValue->GetUInt8(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(v); + return S_OK; + } + case PropertyType_Int16: { + qint16 v; + hr = propertyValue->GetInt16(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(v); + return S_OK; + } + case PropertyType_UInt16: { + quint16 v; + hr = propertyValue->GetUInt16(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(v); + return S_OK; + } + case PropertyType_Int32: { + qint32 v; + hr = propertyValue->GetInt32(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(v); + return S_OK; + } + case PropertyType_UInt32: { + quint32 v; + hr = propertyValue->GetUInt32(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(v); + return S_OK; + } + case PropertyType_Int64: { + qint64 v; + hr = propertyValue->GetInt64(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(v); + return S_OK; + } + case PropertyType_UInt64: { + quint64 v; + hr = propertyValue->GetUInt64(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(v); + return S_OK; + } + case PropertyType_Single: { + float v; + hr = propertyValue->GetSingle(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(v); + return S_OK; + } + case PropertyType_Double: { + double v; + hr = propertyValue->GetDouble(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(v); + return S_OK; + } + case PropertyType_Char16: { + wchar_t v; + hr = propertyValue->GetChar16(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(QString::fromWCharArray(&v, 1)); + return S_OK; + } + case PropertyType_Boolean: { + boolean v; + hr = propertyValue->GetBoolean(&v); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(v); + return S_OK; + } + case PropertyType_String: { + HString stringProperty; + hr = propertyValue->GetString(stringProperty.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + result.setValue(hStringToQString(stringProperty)); + return S_OK; + } + default: + qCDebug(lcQpaMime) << "Unknown property type dropped:" << type; + } + return S_OK; + } + + // Custom data can be read via input streams + ComPtr randomAccessStream; + hr = res.As(&randomAccessStream); + if (SUCCEEDED(hr)) { + UINT64 size; + hr = randomAccessStream->get_Size(&size); + Q_ASSERT_SUCCEEDED(hr); + ComPtr stream; + hr = randomAccessStream.As(&stream); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr bufferFactory; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), + IID_PPV_ARGS(&bufferFactory)); + Q_ASSERT_SUCCEEDED(hr); + + UINT32 length = qBound(quint64(0), quint64(size), quint64(UINT_MAX)); + ComPtr buffer; + hr = bufferFactory->Create(length, &buffer); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr> readOp; + hr = stream->ReadAsync(buffer.Get(), length, InputStreamOptions_None, &readOp); + + ComPtr effectiveBuffer; + hr = QWinRTFunctions::await(readOp, effectiveBuffer.GetAddressOf()); + + hr = effectiveBuffer->get_Length(&length); + + ComPtr byteArrayAccess; + hr = effectiveBuffer.As(&byteArrayAccess); + + byte *bytes; + hr = byteArrayAccess->Buffer(&bytes); + QByteArray array((char *)bytes, length); + result.setValue(array); + return S_OK; + } + + HSTRING runtimeClass; + hr = res->GetRuntimeClassName(&runtimeClass); + Q_ASSERT_SUCCEEDED(hr); + HString converted; + converted.Set(runtimeClass); + qCDebug(lcQpaMime) << "Unknown drop data type received (" << hStringToQString(converted) + << "). Ignoring..."; + return S_OK; + }); + } + return result; +} + +void QWinRTInternalMimeData::setDataView(const Microsoft::WRL::ComPtr &d) +{ + dataView = d; + formats.clear(); +} + +static HRESULT qt_drag_enter(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e) +{ + QWinRTDrag::instance()->handleNativeDragEvent(sender, e); + return S_OK; +} + +static HRESULT qt_drag_over(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e) +{ + QWinRTDrag::instance()->handleNativeDragEvent(sender, e); + return S_OK; +} + +static HRESULT qt_drag_leave(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e) +{ + // Qt internally checks for new drags and auto sends leave events + // Also there is no QPA function for handling leave + Q_UNUSED(sender); + Q_UNUSED(e); + return S_OK; +} + +static HRESULT qt_drop(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e) +{ + QWinRTDrag::instance()->handleNativeDragEvent(sender, e, true); + return S_OK; +} + +#define Q_DECLARE_DRAGHANDLER(name,func) \ +class QtDragEventHandler##name : public IDragEventHandler \ +{ \ +public: \ + virtual HRESULT STDMETHODCALLTYPE Invoke(IInspectable *sender, \ + ABI::Windows::UI::Xaml::IDragEventArgs *e) \ + { \ + return qt_##func(sender, e);\ + } \ + \ + STDMETHODIMP \ + QueryInterface(REFIID riid, void FAR* FAR* ppvObj) \ + { \ + if (riid == IID_IUnknown || riid == IID_IDragEventHandler) { \ + *ppvObj = this; \ + AddRef(); \ + return NOERROR; \ + } \ + *ppvObj = NULL; \ + return ResultFromScode(E_NOINTERFACE); \ + } \ + \ + STDMETHODIMP_(ULONG) \ + AddRef(void) \ + { \ + return ++m_refs; \ + } \ + \ + STDMETHODIMP_(ULONG) \ + Release(void) \ + { \ + if (--m_refs == 0) { \ + delete this; \ + return 0; \ + } \ + return m_refs; \ + } \ +private: \ +ULONG m_refs{0}; \ +}; + +Q_DECLARE_DRAGHANDLER(Enter, drag_enter) +Q_DECLARE_DRAGHANDLER(Over, drag_over) +Q_DECLARE_DRAGHANDLER(Leave, drag_leave) +Q_DECLARE_DRAGHANDLER(Drop, drop) + +#define Q_INST_DRAGHANDLER(name) QtDragEventHandler##name() + +Q_GLOBAL_STATIC(QWinRTDrag, gDrag); + +QWinRTDrag::QWinRTDrag() + : QPlatformDrag() + , m_dragTarget(0) +{ + qCDebug(lcQpaMime) << __FUNCTION__; + m_enter = new Q_INST_DRAGHANDLER(Enter); + m_over = new Q_INST_DRAGHANDLER(Over); + m_leave = new Q_INST_DRAGHANDLER(Leave); + m_drop = new Q_INST_DRAGHANDLER(Drop); + m_mimeData = new QWinRTInternalMimeData; +} + +QWinRTDrag::~QWinRTDrag() +{ + qCDebug(lcQpaMime) << __FUNCTION__; + delete m_enter; + delete m_over; + delete m_leave; + delete m_drop; + delete m_mimeData; +} + +QWinRTDrag *QWinRTDrag::instance() +{ + return gDrag; +} + +Qt::DropAction QWinRTDrag::drag(QDrag *drag) +{ + qCDebug(lcQpaMime) << __FUNCTION__ << drag; + // ### TODO: Add dragging from Window + return Qt::IgnoreAction; +} + +void QWinRTDrag::setDropTarget(QWindow *target) +{ + qCDebug(lcQpaMime) << __FUNCTION__ << target; + m_dragTarget = target; +} + +QMimeData *QWinRTDrag::platformDropData() +{ + qCDebug(lcQpaMime) << __FUNCTION__; + return m_mimeData; +} + +void QWinRTDrag::setUiElement(ComPtr &element) +{ + qCDebug(lcQpaMime) << __FUNCTION__; + m_ui = element; + // We set the element to always accept drops and then evaluate during + // runtime + HRESULT hr = element->put_AllowDrop(TRUE); + EventRegistrationToken tok; + hr = element->add_DragEnter(m_enter, &tok); + RETURN_VOID_IF_FAILED("Failed to add DragEnter handler."); + hr = element->add_DragOver(m_over, &tok); + RETURN_VOID_IF_FAILED("Failed to add DragOver handler."); + hr = element->add_DragLeave(m_leave, &tok); + RETURN_VOID_IF_FAILED("Failed to add DragLeave handler."); + hr = element->add_Drop(m_drop, &tok); + RETURN_VOID_IF_FAILED("Failed to add Drop handler."); +} + +void QWinRTDrag::handleNativeDragEvent(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e, bool drop) +{ + Q_UNUSED(sender); + + if (!m_dragTarget) + return; + + HRESULT hr; + Point relativePoint; + hr = e->GetPosition(m_ui.Get(), &relativePoint); + RETURN_VOID_IF_FAILED("Could not query drag position."); + const QPoint p(relativePoint.X, relativePoint.Y); + qDebug() << "Point received:" << relativePoint.X << "/" << relativePoint.Y; + + ComPtr e2; + hr = e->QueryInterface(IID_PPV_ARGS(&e2)); + RETURN_VOID_IF_FAILED("Could not convert drag event args"); + + DragDropModifiers modifiers; + hr = e2->get_Modifiers(&modifiers); + + ComPtr e3; + hr = e->QueryInterface(IID_PPV_ARGS(&e3)); + Q_ASSERT_SUCCEEDED(hr); + + DataPackageOperation dataOp; + hr = e3->get_AllowedOperations(&dataOp); + if (FAILED(hr)) + qCDebug(lcQpaMime) << __FUNCTION__ << "Could not query drag operations"; + + const Qt::DropActions actions = translateToQDragDropActions(dataOp); + + ComPtr dataView; + hr = e2->get_DataView(&dataView); + Q_ASSERT_SUCCEEDED(hr); + + m_mimeData->setDataView(dataView); + + // We use deferral as we need to jump to the Qt thread to handle + // the drag event + ComPtr deferral; + hr = e2->GetDeferral(&deferral); + Q_ASSERT_SUCCEEDED(hr); + + DragThreadTransferData *transferData = new DragThreadTransferData; + transferData->moveToThread(qGuiApp->thread()); + transferData->window = m_dragTarget; + transferData->point = p; + transferData->mime = m_mimeData; + transferData->actions = actions; + transferData->dropAction = drop; + transferData->nativeArgs = e; + transferData->deferral = deferral; + QMetaObject::invokeMethod(transferData, "handleDrag", Qt::QueuedConnection); +} + +DragThreadTransferData::DragThreadTransferData(QObject *parent) + : QObject(parent) + , dropAction(false) +{ +} + +void DragThreadTransferData::handleDrag() +{ + bool accepted = false; + Qt::DropAction acceptedAction; + if (dropAction) { + QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(window, mime, point, actions); + accepted = response.isAccepted(); + acceptedAction = response.acceptedAction(); + } else { + QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(window, mime, point, actions); + accepted = response.isAccepted(); + acceptedAction = response.acceptedAction(); + } + + HRESULT hr; + hr = QEventDispatcherWinRT::runOnXamlThread([accepted, acceptedAction, this]() { + HRESULT hr; + hr = nativeArgs->put_Handled(accepted); + if (acceptedAction != Qt::IgnoreAction) { + ComPtr e2; + hr = nativeArgs.As(&e2); + if (SUCCEEDED(hr)) + hr = e2->put_AcceptedOperation(translateFromQDragDropActions(acceptedAction)); + } + deferral->Complete(); + return S_OK; + }); + Q_ASSERT_SUCCEEDED(hr); + deleteLater(); +} + +QT_END_NAMESPACE + +#include "qwinrtdrag.moc" diff --git a/src/plugins/platforms/winrt/qwinrtdrag.h b/src/plugins/platforms/winrt/qwinrtdrag.h new file mode 100644 index 00000000000..97079d831bb --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtdrag.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include +#include // QInternalMime + +#include + +namespace ABI { + namespace Windows { + namespace ApplicationModel { + namespace DataTransfer { + struct IDataPackageView; + } + } + namespace UI { + namespace Xaml { + struct IUIElement; + struct IDragEventArgs; + struct IDragOperationDeferral; + //struct IDataPackageView; + } + } + } +} + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcQpaMime) + +class QtDragEventHandlerEnter; +class QtDragEventHandlerOver; +class QtDragEventHandlerLeave; +class QtDragEventHandlerDrop; +class QWinRTInternalMimeData; + +class QWinRTInternalMimeData : public QInternalMimeData { +public: + QWinRTInternalMimeData(); + virtual ~QWinRTInternalMimeData(); + + bool hasFormat_sys(const QString &mimetype) const Q_DECL_OVERRIDE; + QStringList formats_sys() const Q_DECL_OVERRIDE; + QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + + void setDataView(const Microsoft::WRL::ComPtr &d); +private: + Microsoft::WRL::ComPtr dataView; + mutable QStringList formats; +}; + +class QWinRTDrag : public QPlatformDrag { +public: + QWinRTDrag(); + virtual ~QWinRTDrag(); + static QWinRTDrag *instance(); + + QMimeData *platformDropData(void) Q_DECL_OVERRIDE; + Qt::DropAction drag(QDrag *) Q_DECL_OVERRIDE; + + void setDropTarget(QWindow *target); + + // Native integration and registration + void setUiElement(Microsoft::WRL::ComPtr &element); + + void handleNativeDragEvent(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e, bool drop = false); +private: + Microsoft::WRL::ComPtr m_ui; + QWindow *m_dragTarget; + QtDragEventHandlerEnter *m_enter; + QtDragEventHandlerOver *m_over; + QtDragEventHandlerLeave *m_leave; + QtDragEventHandlerDrop *m_drop; + QWinRTInternalMimeData *m_mimeData; +}; + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 30c0e81e216..01e8a42b8e1 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -45,6 +45,7 @@ #include "qwinrtfontdatabase.h" #include "qwinrttheme.h" #include "qwinrtclipboard.h" +#include "qwinrtdrag.h" #include #include @@ -309,6 +310,15 @@ QPlatformClipboard *QWinRTIntegration::clipboard() const return d->clipboard; } +QPlatformDrag *QWinRTIntegration::drag() const +{ +#if _MSC_VER >= 1900 + return QWinRTDrag::instance(); +#else + return QPlatformIntegration::drag(); +#endif +} + Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const { Q_D(const QWinRTIntegration); diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index 1ed286ab2e0..ffdfa55e497 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -94,6 +94,10 @@ public: QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE; QPlatformServices *services() const Q_DECL_OVERRIDE; QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE; +#ifndef QT_NO_DRAGANDDROP + QPlatformDrag *drag() const Q_DECL_OVERRIDE; +#endif + Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE; QStringList themeNames() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 0255527e91c..3d9baf555dc 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -39,6 +39,7 @@ #include "qwinrtbackingstore.h" #include "qwinrtinputcontext.h" #include "qwinrtcursor.h" +#include "qwinrtdrag.h" #include "qwinrtwindow.h" #include @@ -553,6 +554,9 @@ QWinRTScreen::QWinRTScreen() ComPtr uiElement; hr = canvas.As(&uiElement); Q_ASSERT_SUCCEEDED(hr); +#if _MSC_VER >= 1900 + QWinRTDrag::instance()->setUiElement(uiElement); +#endif hr = window->put_Content(uiElement.Get()); Q_ASSERT_SUCCEEDED(hr); hr = canvas.As(&d->canvas); @@ -761,6 +765,10 @@ void QWinRTScreen::addWindow(QWindow *window) QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); QWindowSystemInterface::flushWindowSystemEvents(); + +#if _MSC_VER >= 1900 + QWinRTDrag::instance()->setDropTarget(window); +#endif } void QWinRTScreen::removeWindow(QWindow *window) @@ -775,6 +783,10 @@ void QWinRTScreen::removeWindow(QWindow *window) QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); QWindowSystemInterface::flushWindowSystemEvents(); +#if _MSC_VER >= 1900 + if (wasTopWindow) + QWinRTDrag::instance()->setDropTarget(topWindow()); +#endif } void QWinRTScreen::raise(QWindow *window) diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index 261295ef0b9..5c62b5718b4 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -14,6 +14,7 @@ SOURCES = \ qwinrtbackingstore.cpp \ qwinrtclipboard.cpp \ qwinrtcursor.cpp \ + qwinrtdrag.cpp \ qwinrteglcontext.cpp \ qwinrteventdispatcher.cpp \ qwinrtfiledialoghelper.cpp \ @@ -32,6 +33,7 @@ HEADERS = \ qwinrtbackingstore.h \ qwinrtclipboard.h \ qwinrtcursor.h \ + qwinrtdrag.h \ qwinrteglcontext.h \ qwinrteventdispatcher.h \ qwinrtfiledialoghelper.h \ @@ -47,6 +49,11 @@ HEADERS = \ OTHER_FILES += winrt.json +*-msvc2013 { + SOURCES -= qwinrtdrag.cpp + HEADERS -= qwinrtdrag.h +} + PLUGIN_TYPE = platforms PLUGIN_CLASS_NAME = QWinRTIntegrationPlugin !equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - From 94f319a2bb191b24498a7575d3b9e186eb772d4d Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 26 May 2016 10:19:28 +0200 Subject: [PATCH 094/173] winrt: enable drag support Allow applications to initiate drag operations. Task-number: QTBUG-50827 Change-Id: I3c29b54756af1af24544f49803305f0c95d8b7f9 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtdrag.cpp | 188 ++++++++++++++++++- src/plugins/platforms/winrt/qwinrtscreen.cpp | 4 + 2 files changed, 188 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp index a52ed917496..8ccb211e4fa 100644 --- a/src/plugins/platforms/winrt/qwinrtdrag.cpp +++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp @@ -88,6 +88,13 @@ inline QString hStringToQString(const HString &hString) return (QString::fromWCharArray(raw, l)); } +inline HString qStringToHString(const QString &qString) +{ + HString h; + h.Set(reinterpret_cast(qString.utf16()), qString.size()); + return h; +} + namespace NativeFormatStrings { static ComPtr dataStatics; static HSTRING text; // text/plain @@ -198,7 +205,6 @@ QStringList QWinRTInternalMimeData::formats_sys() const continue; formats.append(hStringToQString(str)); } - qDebug() << __FUNCTION__ << "Available formats:" << formats; return formats; } @@ -510,6 +516,8 @@ Q_DECLARE_DRAGHANDLER(Drop, drop) Q_GLOBAL_STATIC(QWinRTDrag, gDrag); +extern ComPtr qt_winrt_lastPointerPoint; // qwinrtscreen.cpp + QWinRTDrag::QWinRTDrag() : QPlatformDrag() , m_dragTarget(0) @@ -537,11 +545,184 @@ QWinRTDrag *QWinRTDrag::instance() return gDrag; } +inline HRESULT resetUiElementDrag(ComPtr &elem3, EventRegistrationToken startingToken) +{ + return QEventDispatcherWinRT::runOnXamlThread([elem3, startingToken]() { + HRESULT hr; + hr = elem3->put_CanDrag(false); + Q_ASSERT_SUCCEEDED(hr); + hr = elem3->remove_DragStarting(startingToken); + Q_ASSERT_SUCCEEDED(hr); + return S_OK; + }); +} + Qt::DropAction QWinRTDrag::drag(QDrag *drag) { qCDebug(lcQpaMime) << __FUNCTION__ << drag; - // ### TODO: Add dragging from Window - return Qt::IgnoreAction; + + if (!qt_winrt_lastPointerPoint) { + Q_ASSERT_X(qt_winrt_lastPointerPoint, Q_FUNC_INFO, "No pointerpoint known"); + return Qt::IgnoreAction; + } + + ComPtr elem3; + HRESULT hr = m_ui.As(&elem3); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr> op; + EventRegistrationToken startingToken; + + hr = QEventDispatcherWinRT::runOnXamlThread([drag, &op, &hr, elem3, &startingToken, this]() { + + hr = elem3->put_CanDrag(true); + Q_ASSERT_SUCCEEDED(hr); + + auto startingCallback = Callback> ([drag](IInspectable *, IDragStartingEventArgs *args) { + qCDebug(lcQpaMime) << "Drag starting" << args; + + ComPtr dataPackage; + HRESULT hr; + hr = args->get_Data(dataPackage.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + Qt::DropAction action = drag->defaultAction(); + hr = dataPackage->put_RequestedOperation(translateFromQDragDropActions(action)); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr args2; + hr = args->QueryInterface(IID_PPV_ARGS(&args2)); + Q_ASSERT_SUCCEEDED(hr); + + Qt::DropActions actions = drag->supportedActions(); + DataPackageOperation allowedOperations = DataPackageOperation_None; + if (actions & Qt::CopyAction) + allowedOperations |= DataPackageOperation_Copy; + if (actions & Qt::MoveAction) + allowedOperations |= DataPackageOperation_Move; + if (actions & Qt::LinkAction) + allowedOperations |= DataPackageOperation_Link; + hr = args2->put_AllowedOperations(allowedOperations); + Q_ASSERT_SUCCEEDED(hr); + + QMimeData *mimeData = drag->mimeData(); + if (mimeData->hasText()) { + hr = dataPackage->SetText(qStringToHString(mimeData->text()).Get()); + Q_ASSERT_SUCCEEDED(hr); + } + if (mimeData->hasHtml()) { + hr = dataPackage->SetHtmlFormat(qStringToHString(mimeData->html()).Get()); + Q_ASSERT_SUCCEEDED(hr); + } + // ### TODO: Missing: weblink, image + + const QStringList formats = mimeData->formats(); + for (auto item : formats) { + QByteArray data = mimeData->data(item); + + ComPtr bufferFactory; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), + IID_PPV_ARGS(&bufferFactory)); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr buffer; + const UINT32 length = data.size(); + hr = bufferFactory->Create(length, &buffer); + Q_ASSERT_SUCCEEDED(hr); + hr = buffer->put_Length(length); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr byteArrayAccess; + hr = buffer.As(&byteArrayAccess); + Q_ASSERT_SUCCEEDED(hr); + + byte *bytes; + hr = byteArrayAccess->Buffer(&bytes); + Q_ASSERT_SUCCEEDED(hr); + memcpy(bytes, data.constData(), length); + + // We cannot push the buffer to the data package as the result on + // recipient side is different from native events. It still sends a + // buffer, but that potentially cannot be parsed. Hence we need to create + // a IRandomAccessStream which gets forwarded as is to the drop side. + ComPtr ras; + hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream).Get(), &ras); + Q_ASSERT_SUCCEEDED(hr); + + hr = ras->put_Size(length); + ComPtr outputStream; + hr = ras->GetOutputStreamAt(0, &outputStream); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr> writeOp; + hr = outputStream->WriteAsync(buffer.Get(), &writeOp); + Q_ASSERT_SUCCEEDED(hr); + + UINT32 result; + hr = QWinRTFunctions::await(writeOp, &result); + Q_ASSERT_SUCCEEDED(hr); + + unsigned char flushResult; + ComPtr> flushOp; + hr = outputStream.Get()->FlushAsync(&flushOp); + Q_ASSERT_SUCCEEDED(hr); + + hr = QWinRTFunctions::await(flushOp, &flushResult); + Q_ASSERT_SUCCEEDED(hr); + + hr = dataPackage->SetData(qStringToHString(item).Get(), ras.Get()); + Q_ASSERT_SUCCEEDED(hr); + + } + return S_OK; + }); + + hr = elem3->add_DragStarting(startingCallback.Get(), &startingToken); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr pointStatics; + + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Input_PointerPoint).Get(), + IID_PPV_ARGS(&pointStatics)); + Q_ASSERT_SUCCEEDED(hr); + + hr = elem3->StartDragAsync(qt_winrt_lastPointerPoint.Get(), &op); + Q_ASSERT_SUCCEEDED(hr); + + return hr; + }); + if (!op || FAILED(hr)) { + qCDebug(lcQpaMime) << "Drag failed:" << hr; + hr = resetUiElementDrag(elem3, startingToken); + Q_ASSERT_SUCCEEDED(hr); + return Qt::IgnoreAction; + } + + DataPackageOperation nativeOperationType; + // Do not yield, as that can cause deadlocks when dropping inside the same app + hr = QWinRTFunctions::await(op, &nativeOperationType, QWinRTFunctions::ProcessThreadEvents); + Q_ASSERT_SUCCEEDED(hr); + + hr = resetUiElementDrag(elem3, startingToken); + Q_ASSERT_SUCCEEDED(hr); + + Qt::DropAction resultAction; + switch (nativeOperationType) { + case DataPackageOperation_Link: + resultAction = Qt::LinkAction; + break; + case DataPackageOperation_Copy: + resultAction = Qt::CopyAction; + break; + case DataPackageOperation_Move: + resultAction = Qt::MoveAction; + break; + case DataPackageOperation_None: + default: + resultAction = Qt::IgnoreAction; + break; + } + + return resultAction; } void QWinRTDrag::setDropTarget(QWindow *target) @@ -586,7 +767,6 @@ void QWinRTDrag::handleNativeDragEvent(IInspectable *sender, ABI::Windows::UI::X hr = e->GetPosition(m_ui.Get(), &relativePoint); RETURN_VOID_IF_FAILED("Could not query drag position."); const QPoint p(relativePoint.X, relativePoint.Y); - qDebug() << "Point received:" << relativePoint.X << "/" << relativePoint.Y; ComPtr e2; hr = e->QueryInterface(IID_PPV_ARGS(&e2)); diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 3d9baf555dc..43847e1ecc8 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -982,6 +982,9 @@ HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args) return S_OK; } +// Required for qwinrtdrag.cpp +ComPtr qt_winrt_lastPointerPoint; + HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args) { Q_D(QWinRTScreen); @@ -989,6 +992,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args) if (FAILED(args->get_CurrentPoint(&pointerPoint))) return E_INVALIDARG; + qt_winrt_lastPointerPoint = pointerPoint; // Common traits - point, modifiers, properties Point point; pointerPoint->get_Position(&point); From e8ff3c8cbc8a66c344e2c974ae92f2cea7a2e5fe Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Fri, 27 May 2016 13:13:40 +0200 Subject: [PATCH 095/173] winrt: fix drag pixmap support Previously dragging only displayed the type of operation provided by the system. Now, in case a pixmap is specified, an image is shown. Also incorporated some cleanups. Task-number: QTBUG-50827 Change-Id: I471e2081eabfed014b08d189538d1d62cdb7248e Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtdrag.cpp | 148 +++++++++++++-------- 1 file changed, 92 insertions(+), 56 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp index 8ccb211e4fa..14bea7ab30d 100644 --- a/src/plugins/platforms/winrt/qwinrtdrag.cpp +++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,7 @@ using namespace ABI::Windows::ApplicationModel::DataTransfer; using namespace ABI::Windows::ApplicationModel::DataTransfer::DragDrop; using namespace ABI::Windows::Foundation; using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Graphics::Imaging; using namespace ABI::Windows::Storage; using namespace ABI::Windows::Storage::Streams; using namespace ABI::Windows::UI::Xaml; @@ -65,6 +67,34 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime") +ComPtr createIBufferFromData(const char *data, qint32 size) +{ + static ComPtr bufferFactory; + HRESULT hr; + if (!bufferFactory) { + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), + IID_PPV_ARGS(&bufferFactory)); + Q_ASSERT_SUCCEEDED(hr); + } + + ComPtr buffer; + const UINT32 length = size; + hr = bufferFactory->Create(length, &buffer); + Q_ASSERT_SUCCEEDED(hr); + hr = buffer->put_Length(length); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr byteArrayAccess; + hr = buffer.As(&byteArrayAccess); + Q_ASSERT_SUCCEEDED(hr); + + byte *bytes; + hr = byteArrayAccess->Buffer(&bytes); + Q_ASSERT_SUCCEEDED(hr); + memcpy(bytes, data, length); + return buffer; +} + class DragThreadTransferData : public QObject { Q_OBJECT @@ -175,36 +205,42 @@ QStringList QWinRTInternalMimeData::formats_sys() const if (!formats.isEmpty()) return formats; - boolean contains; HRESULT hr; - hr = dataView->Contains(NativeFormatStrings::text, &contains); - if (SUCCEEDED(hr) && contains) - formats.append(QLatin1String("text/plain")); + hr = QEventDispatcherWinRT::runOnXamlThread([this]() { + boolean contains; + HRESULT hr; + hr = dataView->Contains(NativeFormatStrings::text, &contains); + if (SUCCEEDED(hr) && contains) + formats.append(QLatin1String("text/plain")); - hr = dataView->Contains(NativeFormatStrings::html, &contains); - if (SUCCEEDED(hr) && contains) - formats.append(QLatin1String("text/html")); + hr = dataView->Contains(NativeFormatStrings::html, &contains); + if (SUCCEEDED(hr) && contains) + formats.append(QLatin1String("text/html")); - hr = dataView->Contains(NativeFormatStrings::storage, &contains); - if (SUCCEEDED(hr) && contains) - formats.append(QLatin1String("text/uri-list")); + hr = dataView->Contains(NativeFormatStrings::storage, &contains); + if (SUCCEEDED(hr) && contains) + formats.append(QLatin1String("text/uri-list")); - // We need to add any additional format as well, for legacy windows - // reasons, but also in case someone adds custom formats. - ComPtr> availableFormats; - hr = dataView->get_AvailableFormats(&availableFormats); - RETURN_IF_FAILED("Could not query available formats.", return formats); + // We need to add any additional format as well, for legacy windows + // reasons, but also in case someone adds custom formats. + ComPtr> availableFormats; + hr = dataView->get_AvailableFormats(&availableFormats); + RETURN_OK_IF_FAILED("Could not query available formats."); + + quint32 size; + hr = availableFormats->get_Size(&size); + RETURN_OK_IF_FAILED("Could not query format vector size."); + for (quint32 i = 0; i < size; ++i) { + HString str; + hr = availableFormats->GetAt(i, str.GetAddressOf()); + if (FAILED(hr)) + continue; + formats.append(hStringToQString(str)); + } + return S_OK; + }); + Q_ASSERT_SUCCEEDED(hr); - quint32 size; - hr = availableFormats->get_Size(&size); - RETURN_IF_FAILED("Could not query format vector size.", return formats); - for (quint32 i = 0; i < size; ++i) { - HString str; - hr = availableFormats->GetAt(i, str.GetAddressOf()); - if (FAILED(hr)) - continue; - formats.append(hStringToQString(str)); - } return formats; } @@ -265,8 +301,6 @@ QVariant QWinRTInternalMimeData::retrieveData_sys(const QString &mimetype, QVari result.setValue(hStringToQString(res)); return S_OK; }); - } else if (mimetype.startsWith(QLatin1String("image/"))) { - Q_UNIMPLEMENTED(); } else { // Asking for custom data hr = QEventDispatcherWinRT::runOnXamlThread([this, &result, mimetype]() { @@ -615,30 +649,39 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag) } // ### TODO: Missing: weblink, image + if (!drag->pixmap().isNull()) { + const QImage image2 = drag->pixmap().toImage(); + const QImage image = image2.convertToFormat(QImage::Format_ARGB32); + if (!image.isNull()) { + // Create IBuffer containing image + ComPtr imageBuffer = createIBufferFromData(reinterpret_cast(image.bits()), image.byteCount()); + + ComPtr bitmapFactory; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Imaging_SoftwareBitmap).Get(), + IID_PPV_ARGS(&bitmapFactory)); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr bitmap; + hr = bitmapFactory->Create(BitmapPixelFormat_Rgba8, image.width(), image.height(), &bitmap); + Q_ASSERT_SUCCEEDED(hr); + + hr = bitmap->CopyFromBuffer(imageBuffer.Get()); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr dragUi; + hr = args->get_DragUI(dragUi.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + + hr = dragUi->SetContentFromSoftwareBitmap(bitmap.Get()); + Q_ASSERT_SUCCEEDED(hr); + } + } + const QStringList formats = mimeData->formats(); for (auto item : formats) { QByteArray data = mimeData->data(item); - ComPtr bufferFactory; - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), - IID_PPV_ARGS(&bufferFactory)); - Q_ASSERT_SUCCEEDED(hr); - - ComPtr buffer; - const UINT32 length = data.size(); - hr = bufferFactory->Create(length, &buffer); - Q_ASSERT_SUCCEEDED(hr); - hr = buffer->put_Length(length); - Q_ASSERT_SUCCEEDED(hr); - - ComPtr byteArrayAccess; - hr = buffer.As(&byteArrayAccess); - Q_ASSERT_SUCCEEDED(hr); - - byte *bytes; - hr = byteArrayAccess->Buffer(&bytes); - Q_ASSERT_SUCCEEDED(hr); - memcpy(bytes, data.constData(), length); + ComPtr buffer = createIBufferFromData(data.constData(), data.size()); // We cannot push the buffer to the data package as the result on // recipient side is different from native events. It still sends a @@ -648,7 +691,7 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag) hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream).Get(), &ras); Q_ASSERT_SUCCEEDED(hr); - hr = ras->put_Size(length); + hr = ras->put_Size(data.size()); ComPtr outputStream; hr = ras->GetOutputStreamAt(0, &outputStream); Q_ASSERT_SUCCEEDED(hr); @@ -663,7 +706,7 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag) unsigned char flushResult; ComPtr> flushOp; - hr = outputStream.Get()->FlushAsync(&flushOp); + hr = outputStream->FlushAsync(&flushOp); Q_ASSERT_SUCCEEDED(hr); hr = QWinRTFunctions::await(flushOp, &flushResult); @@ -671,7 +714,6 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag) hr = dataPackage->SetData(qStringToHString(item).Get(), ras.Get()); Q_ASSERT_SUCCEEDED(hr); - } return S_OK; }); @@ -679,12 +721,6 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag) hr = elem3->add_DragStarting(startingCallback.Get(), &startingToken); Q_ASSERT_SUCCEEDED(hr); - ComPtr pointStatics; - - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Input_PointerPoint).Get(), - IID_PPV_ARGS(&pointStatics)); - Q_ASSERT_SUCCEEDED(hr); - hr = elem3->StartDragAsync(qt_winrt_lastPointerPoint.Get(), &op); Q_ASSERT_SUCCEEDED(hr); From bb30da895eca5a80265317db1fc7a0d151005e30 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 31 May 2016 13:46:51 +0200 Subject: [PATCH 096/173] winrt: fix compilation without drag and drop support Change-Id: Ifd0d2238e8dacffe34753d95e12cccfd13519c55 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtintegration.cpp | 4 ++++ src/plugins/platforms/winrt/qwinrtscreen.cpp | 8 +++++--- src/plugins/platforms/winrt/winrt.pro | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 01e8a42b8e1..8c419dcdbcb 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -45,7 +45,9 @@ #include "qwinrtfontdatabase.h" #include "qwinrttheme.h" #include "qwinrtclipboard.h" +#ifndef QT_NO_DRAGANDDROP #include "qwinrtdrag.h" +#endif #include #include @@ -310,6 +312,7 @@ QPlatformClipboard *QWinRTIntegration::clipboard() const return d->clipboard; } +#ifndef QT_NO_DRAGANDDROP QPlatformDrag *QWinRTIntegration::drag() const { #if _MSC_VER >= 1900 @@ -318,6 +321,7 @@ QPlatformDrag *QWinRTIntegration::drag() const return QPlatformIntegration::drag(); #endif } +#endif // QT_NO_DRAGANDDROP Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const { diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 43847e1ecc8..c1118cd0b84 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -39,7 +39,9 @@ #include "qwinrtbackingstore.h" #include "qwinrtinputcontext.h" #include "qwinrtcursor.h" +#ifndef QT_NO_DRAGANDDROP #include "qwinrtdrag.h" +#endif #include "qwinrtwindow.h" #include @@ -554,7 +556,7 @@ QWinRTScreen::QWinRTScreen() ComPtr uiElement; hr = canvas.As(&uiElement); Q_ASSERT_SUCCEEDED(hr); -#if _MSC_VER >= 1900 +#if _MSC_VER >= 1900 && !defined(QT_NO_DRAGANDDROP) QWinRTDrag::instance()->setUiElement(uiElement); #endif hr = window->put_Content(uiElement.Get()); @@ -766,7 +768,7 @@ void QWinRTScreen::addWindow(QWindow *window) handleExpose(); QWindowSystemInterface::flushWindowSystemEvents(); -#if _MSC_VER >= 1900 +#if _MSC_VER >= 1900 && !defined(QT_NO_DRAGANDDROP) QWinRTDrag::instance()->setDropTarget(window); #endif } @@ -783,7 +785,7 @@ void QWinRTScreen::removeWindow(QWindow *window) QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); QWindowSystemInterface::flushWindowSystemEvents(); -#if _MSC_VER >= 1900 +#if _MSC_VER >= 1900 && !defined(QT_NO_DRAGANDDROP) if (wasTopWindow) QWinRTDrag::instance()->setDropTarget(topWindow()); #endif diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index 5c62b5718b4..dd1e051c332 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -49,7 +49,7 @@ HEADERS = \ OTHER_FILES += winrt.json -*-msvc2013 { +*-msvc2013|contains(DEFINES, QT_NO_DRAGANDDROP) { SOURCES -= qwinrtdrag.cpp HEADERS -= qwinrtdrag.h } From 2e4191eadce4cfe944afd0baf37f06bbcb65c5f4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 30 May 2016 12:31:48 -0300 Subject: [PATCH 097/173] QObject::connect: reduce generated code size for statics and functors Instead of placing the assignment of false in the impl() function, move it to the inline QSlotObjectBase::compare() function. That means it's assigned in one place (two, actually, inside qobject.cpp), instead of for every static member, non-member or functor we connect or disconnect. Change-Id: I87e17314d8b24ae983b1fffd1453623ad4c4dcb2 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject_impl.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index 6140ae775eb..b4091a4f1c6 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -126,7 +126,7 @@ namespace QtPrivate { inline void destroyIfLastRef() Q_DECL_NOTHROW { if (!m_ref.deref()) m_impl(Destroy, this, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR); } - inline bool compare(void **a) { bool ret; m_impl(Compare, this, Q_NULLPTR, a, &ret); return ret; } + inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, Q_NULLPTR, a, &ret); return ret; } inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, Q_NULLPTR); } protected: ~QSlotObjectBase() {} @@ -172,10 +172,9 @@ namespace QtPrivate { case Call: FuncType::template call(static_cast(this_)->function, r, a); break; - case Compare: - *ret = false; // not implemented - break; - case NumOperations: ; + case Compare: // not implemented + case NumOperations: + Q_UNUSED(ret); } } public: @@ -197,10 +196,9 @@ namespace QtPrivate { case Call: FuncType::template call(static_cast(this_)->function, r, a); break; - case Compare: - *ret = false; // not implemented - break; - case NumOperations: ; + case Compare: // not implemented + case NumOperations: + Q_UNUSED(ret); } } public: From a160bd4fccaebafb5453a642f43bdefafc1e2565 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Thu, 5 May 2016 02:17:56 -0700 Subject: [PATCH 098/173] Fix bugs causing Thin font weights to be ignored or mishandled. Task-number: QTBUG-53196 Change-Id: If12b3cab3d8de5e0e452fca844b0a484c29e9e86 Reviewed-by: Allan Sandfeld Jensen --- src/gui/text/qfontdatabase.cpp | 3 +-- src/gui/text/qfontengine.cpp | 3 +-- src/gui/text/qtextformat.cpp | 7 ++++--- src/gui/text/qtextformat.h | 4 ++-- src/plugins/platforms/windows/qwindowsfontengine.cpp | 6 ++---- tests/auto/gui/text/qfontcache/tst_qfontcache.cpp | 2 -- 6 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 928d1e4eb52..c4b849878c7 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -2730,8 +2730,7 @@ void QFontDatabase::load(const QFontPrivate *d, int script) } if (req.pointSize < 0) req.pointSize = req.pixelSize*72.0/d->dpi; - if (req.weight == 0) - req.weight = QFont::Normal; + req.weight = QFont::Normal; if (req.stretch == 0) req.stretch = 100; diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 39348a52b0c..5e8aac82b88 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1840,8 +1840,7 @@ QFontEngine *QFontEngineMulti::loadEngine(int at) request.family = fallbackFamilyAt(at - 1); if (QFontEngine *engine = QFontDatabase::findFont(request, m_script)) { - if (request.weight > QFont::Normal) - engine->fontDef.weight = request.weight; + engine->fontDef.weight = request.weight; if (request.style > QFont::StyleNormal) engine->fontDef.style = request.style; return engine; diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 7dcd060ba1e..4b31b49df2d 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -357,9 +357,10 @@ void QTextFormatPrivate::recalcFont() const f.setPixelSize(props.at(i).value.toInt()); break; case QTextFormat::FontWeight: { - int weight = props.at(i).value.toInt(); - if (weight == 0) weight = QFont::Normal; - f.setWeight(weight); + const QVariant weightValue = props.at(i).value; + int weight = weightValue.toInt(); + if (weight >= 0 && weightValue.isValid()) + f.setWeight(weight); break; } case QTextFormat::FontItalic: f.setItalic(props.at(i).value.toBool()); diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h index 6c1b75aa359..dbc50f70f93 100644 --- a/src/gui/text/qtextformat.h +++ b/src/gui/text/qtextformat.h @@ -424,9 +424,9 @@ public: { return doubleProperty(FontPointSize); } inline void setFontWeight(int weight) - { if (weight == QFont::Normal) weight = 0; setProperty(FontWeight, weight); } + { setProperty(FontWeight, weight); } inline int fontWeight() const - { int weight = intProperty(FontWeight); if (weight == 0) weight = QFont::Normal; return weight; } + { return hasProperty(FontWeight) ? intProperty(FontWeight) : QFont::Normal; } inline void setFontItalic(bool italic) { setProperty(FontItalic, italic); } inline bool fontItalic() const diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index 660c1380972..3ac7e6c9ec7 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -1342,8 +1342,7 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at) QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace, fontEngine->fontDef.pixelSize, data); - if (fontEngine->fontDef.weight > QFont::Normal) - fedw->fontDef.weight = fontEngine->fontDef.weight; + fedw->fontDef.weight = fontEngine->fontDef.weight; if (fontEngine->fontDef.style > QFont::StyleNormal) fedw->fontDef.style = fontEngine->fontDef.style; fedw->fontDef.family = fam; @@ -1360,8 +1359,7 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at) // reason QFontEngine *fe = new QWindowsFontEngine(fam, lf, data); - if (fontEngine->fontDef.weight > QFont::Normal) - fe->fontDef.weight = fontEngine->fontDef.weight; + fe->fontDef.weight = fontEngine->fontDef.weight; if (fontEngine->fontDef.style > QFont::StyleNormal) fe->fontDef.style = fontEngine->fontDef.style; fe->fontDef.family = fam; diff --git a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp index 4d5ddfd523c..a0bb1ebef92 100644 --- a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp +++ b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp @@ -106,8 +106,6 @@ void tst_QFontCache::engineData() } if (req.pointSize < 0) req.pointSize = req.pixelSize*72.0/d->dpi; - if (req.weight == 0) - req.weight = QFont::Normal; if (req.stretch == 0) req.stretch = 100; From 7cbafa8de7bc516f089503d12cab397e7965b8a5 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Fri, 27 May 2016 23:47:49 -0700 Subject: [PATCH 099/173] Call a function in the MySQL configure test to make sure it links. This fixes a problem where the configure test may produce a false positive on iOS if a copy of libmysql for OS X is located, due to the fact that linking to a dynamic library of a different architecture than expected is not (yet) an error. Change-Id: Id41765f49e31d9c9c3becc3436ff5a69b160b8e0 Reviewed-by: Oswald Buddenhagen --- config.tests/unix/mysql/mysql.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/config.tests/unix/mysql/mysql.cpp b/config.tests/unix/mysql/mysql.cpp index 9cc2db03d94..3d51c612dab 100644 --- a/config.tests/unix/mysql/mysql.cpp +++ b/config.tests/unix/mysql/mysql.cpp @@ -35,5 +35,6 @@ int main(int, char **) { + mysql_get_client_version(); return 0; } From 0b401d74e6ee40d87755a781b199c5ea6ad3e566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 1 Sep 2015 15:52:39 +0200 Subject: [PATCH 100/173] Platformsupport: Don't include dbus on darwin. This created a false dependency from the cocoa platform plugin to QtDBus, which caused macdeployqt to deploy it. This change is for libplatformsupport only, and has no effect on QtDBus usage in general. Change-Id: I35f342574a6497ff88a785e93eef1acdea8b1452 Task-number: QTBUG-48015 Reviewed-by: Jake Petroules --- src/platformsupport/platformsupport.pro | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro index 1ea6d0eb698..c5894c4f989 100644 --- a/src/platformsupport/platformsupport.pro +++ b/src/platformsupport/platformsupport.pro @@ -21,7 +21,11 @@ include(accessibility/accessibility.pri) include(linuxaccessibility/linuxaccessibility.pri) include(clipboard/clipboard.pri) include(platformcompositor/platformcompositor.pri) -contains(QT_CONFIG, dbus) { + +# dbus convenience, but not for darwin: the platform +# plugins for these platforms do not use dbus and we +# don't want to create a false dependency. +!darwin: contains(QT_CONFIG, dbus) { include(dbusmenu/dbusmenu.pri) include(dbustray/dbustray.pri) } From 58408ffa1b9c0b42a1719d3c8a4d4c62dec4fce6 Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Tue, 31 May 2016 14:46:17 +0200 Subject: [PATCH 101/173] Add install target to mac widget examples Change-Id: I524ba3fcc82a6ef015241d90f212059ae7772443 Reviewed-by: Jake Petroules Reviewed-by: Timur Pocheptsov Reviewed-by: Oswald Buddenhagen --- .../mac/qmaccocoaviewcontainer/qmaccocoaviewcontainer.pro | 3 +++ examples/widgets/mac/qmacnativewidget/qmacnativewidget.pro | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/examples/widgets/mac/qmaccocoaviewcontainer/qmaccocoaviewcontainer.pro b/examples/widgets/mac/qmaccocoaviewcontainer/qmaccocoaviewcontainer.pro index c8c2195cb88..183e3078773 100644 --- a/examples/widgets/mac/qmaccocoaviewcontainer/qmaccocoaviewcontainer.pro +++ b/examples/widgets/mac/qmaccocoaviewcontainer/qmaccocoaviewcontainer.pro @@ -5,3 +5,6 @@ LIBS += -framework Cocoa QT += widgets +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/mac/qmaccocoaviewcontainer +INSTALLS += target diff --git a/examples/widgets/mac/qmacnativewidget/qmacnativewidget.pro b/examples/widgets/mac/qmacnativewidget/qmacnativewidget.pro index cafff9f035a..b39792e6dd3 100644 --- a/examples/widgets/mac/qmacnativewidget/qmacnativewidget.pro +++ b/examples/widgets/mac/qmacnativewidget/qmacnativewidget.pro @@ -5,3 +5,7 @@ LIBS += -framework Cocoa QT += widgets #QT += widgets-private gui-private core-private + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/mac/qmacnativewidget +INSTALLS += target From d11abc8bd7ac10da4bfd548b3d1d9d4e0dd6a264 Mon Sep 17 00:00:00 2001 From: Milla Pohjanheimo Date: Tue, 31 May 2016 15:56:43 +0300 Subject: [PATCH 102/173] Blacklisting a flaky tst_QGL::clipTest test on OpenSUSE 13.1 Based on discussion with Laszlo, we are blacklisting this test. Task-number: QTBUG-53133 Change-Id: I08a5192ebcefd7b093c79872e0dfaddb794cab57 Reviewed-by: Laszlo Agocs --- tests/auto/opengl/qgl/BLACKLIST | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/opengl/qgl/BLACKLIST b/tests/auto/opengl/qgl/BLACKLIST index fa7c829b30e..a7aaa049001 100644 --- a/tests/auto/opengl/qgl/BLACKLIST +++ b/tests/auto/opengl/qgl/BLACKLIST @@ -10,6 +10,7 @@ windows windows [clipTest] windows +opensuse-13.1 [graphicsViewClipping] windows [glFBOUseInGLWidget] From a24b90a21c4f2feb61630ca6a1684312556a6bc7 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 14 Apr 2016 14:55:44 +0300 Subject: [PATCH 103/173] Gui: use const (and const APIs) more For CoW types, prefer const methods to avoid needless detach()ing. Change-Id: I88d08d499e1be72c1f6d983fecdcee513df18aa2 Reviewed-by: Edward Welbourne --- src/gui/image/qicon.cpp | 2 +- src/gui/image/qiconloader.cpp | 2 +- src/gui/image/qimagepixmapcleanuphooks.cpp | 18 +++++------ src/gui/image/qxpmhandler.cpp | 2 +- src/gui/itemmodels/qstandarditemmodel.cpp | 9 ++---- src/gui/kernel/qguiapplication.cpp | 4 +-- src/gui/kernel/qkeysequence.cpp | 6 ++-- src/gui/kernel/qopenglcontext.cpp | 4 +-- src/gui/kernel/qplatformintegration.cpp | 4 +-- src/gui/kernel/qplatformscreen.cpp | 2 +- src/gui/kernel/qwindow.cpp | 8 ++--- src/gui/opengl/qopenglframebufferobject.cpp | 7 +++-- src/gui/opengl/qopenglgradientcache.cpp | 33 +++++++++------------ src/gui/painting/qpainter.cpp | 2 +- src/gui/painting/qpainterpath.cpp | 31 +++++++++---------- src/gui/painting/qpathclipper.cpp | 16 +++++----- src/gui/painting/qpdf.cpp | 4 +-- src/gui/text/qcssparser.cpp | 3 +- src/gui/text/qtextdocument_p.cpp | 21 ++++++------- src/gui/text/qtextdocumentfragment.cpp | 6 ++-- src/gui/text/qtextdocumentlayout.cpp | 24 +++++++-------- src/gui/text/qtextengine.cpp | 4 +-- src/gui/text/qtextformat.cpp | 2 +- src/gui/text/qtexthtmlparser.cpp | 2 +- src/gui/text/qtextodfwriter.cpp | 8 ++--- src/gui/text/qtexttable.cpp | 20 +++++++------ src/gui/util/qgridlayoutengine.cpp | 19 ++++++------ 27 files changed, 130 insertions(+), 133 deletions(-) diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 620cbde25dd..0dec4b512d1 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -284,7 +284,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St if (pm.isNull()) { int idx = pixmaps.count(); while (--idx >= 0) { - if (pe == &pixmaps[idx]) { + if (pe == &pixmaps.at(idx)) { pixmaps.remove(idx); break; } diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 7b6bfc60b37..2f24165069e 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -296,7 +296,7 @@ QIconTheme::QIconTheme(const QString &themeName) { QFile themeIndex; - QStringList iconDirs = QIcon::themeSearchPaths(); + const QStringList iconDirs = QIcon::themeSearchPaths(); for ( int i = 0 ; i < iconDirs.size() ; ++i) { QDir iconDir(iconDirs[i]); QString themeDir = iconDir.path() + QLatin1Char('/') + themeName; diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp index 10fa4303b2e..f383e7a60e5 100644 --- a/src/gui/image/qimagepixmapcleanuphooks.cpp +++ b/src/gui/image/qimagepixmapcleanuphooks.cpp @@ -84,38 +84,38 @@ void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook) void QImagePixmapCleanupHooks::executePlatformPixmapModificationHooks(QPlatformPixmap* pmd) { - QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks(); + const QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks(); // the global destructor for the pixmap and image hooks might have // been called already if the app is "leaking" global // pixmaps/images if (!h) return; - for (int i = 0; i < h->pixmapModificationHooks.count(); ++i) - h->pixmapModificationHooks[i](pmd); + for (auto hook : h->pixmapModificationHooks) + hook(pmd); } void QImagePixmapCleanupHooks::executePlatformPixmapDestructionHooks(QPlatformPixmap* pmd) { - QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks(); + const QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks(); // the global destructor for the pixmap and image hooks might have // been called already if the app is "leaking" global // pixmaps/images if (!h) return; - for (int i = 0; i < h->pixmapDestructionHooks.count(); ++i) - h->pixmapDestructionHooks[i](pmd); + for (auto hook : h->pixmapDestructionHooks) + hook(pmd); } void QImagePixmapCleanupHooks::executeImageHooks(qint64 key) { - QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks(); + const QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks(); // the global destructor for the pixmap and image hooks might have // been called already if the app is "leaking" global // pixmaps/images if (!h) return; - for (int i = 0; i < h->imageHooks.count(); ++i) - h->imageHooks[i](key); + for (auto hook : h->imageHooks) + hook(key); } diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index 5ae8e893cb8..c8dd589673f 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -1154,7 +1154,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const int cc = 0; for(x=0; x 1) { line[cc++] = QLatin1Char(chars[1]); diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp index 6f30f0ea258..3861eb8b40f 100644 --- a/src/gui/itemmodels/qstandarditemmodel.cpp +++ b/src/gui/itemmodels/qstandarditemmodel.cpp @@ -3027,10 +3027,7 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const for (int i = 0; i < childList.count(); ++i) { QStandardItem *chi = childList.at(i); if (chi) { - QSet::iterator it = itemsSet.find(chi); - if (it != itemsSet.end()) { - itemsSet.erase(it); - } + itemsSet.erase(itemsSet.constFind(chi)); stack.push(chi); } } @@ -3139,13 +3136,13 @@ bool QStandardItemModel::dropMimeData(const QMimeData *data, Qt::DropAction acti for (int i = 0; i < rows.count(); ++i) rowsToInsert[rows.at(i)] = 1; for (int i = 0; i < rowsToInsert.count(); ++i) { - if (rowsToInsert[i] == 1){ + if (rowsToInsert.at(i) == 1){ rowsToInsert[i] = dragRowCount; ++dragRowCount; } } for (int i = 0; i < rows.count(); ++i) - rows[i] = top + rowsToInsert[rows[i]]; + rows[i] = top + rowsToInsert.at(rows.at(i)); QBitArray isWrittenTo(dragRowCount * dragColumnCount); diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index a9f0ab04a16..137310ffbd1 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1024,7 +1024,7 @@ QWindow *QGuiApplication::topLevelAt(const QPoint &pos) // may repeat. Find only when there is more than one virtual desktop. if (!windowScreen && screens.count() != primaryScreens.count()) { for (int i = 1; i < screens.size(); ++i) { - QScreen *screen = screens[i]; + QScreen *screen = screens.at(i); if (screen->geometry().contains(pos)) { windowScreen = screen; break; @@ -2617,7 +2617,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To if (b == Qt::NoButton) self->synthesizedMousePoints.clear(); - QList touchPoints = touchEvent.touchPoints(); + const QList &touchPoints = touchEvent.touchPoints(); if (eventType == QEvent::TouchBegin) m_fakeMouseSourcePointId = touchPoints.first().id(); diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 8ccd85795b1..f7771c252fc 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -1160,15 +1160,15 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence int fnum = 0; if (accel.length() == 1) { #if defined(Q_OS_MACX) - int qtKey = qtkeyForMacSymbol(accel[0]); + int qtKey = qtkeyForMacSymbol(accel.at(0)); if (qtKey != -1) { ret |= qtKey; } else #endif { - ret |= accel[0].toUpper().unicode(); + ret |= accel.at(0).toUpper().unicode(); } - } else if (accel[0] == QLatin1Char('f') && (fnum = accel.mid(1).toInt()) && (fnum >= 1) && (fnum <= 35)) { + } else if (accel.at(0) == QLatin1Char('f') && (fnum = accel.mid(1).toInt()) >= 1 && fnum <= 35) { ret |= Qt::Key_F1 + fnum - 1; } else { // For NativeText, check the traslation table first, diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 59bf2bb065b..0f7bbfd2e15 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -1409,7 +1409,7 @@ void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx) m_shares.removeOne(ctx); if (ctx == m_context && !m_shares.isEmpty()) - m_context = m_shares.first(); + m_context = m_shares.constFirst(); if (!m_refs.deref()) { cleanup(); @@ -1573,7 +1573,7 @@ QOpenGLMultiGroupSharedResource::~QOpenGLMultiGroupSharedResource() #endif for (int i = 0; i < m_groups.size(); ++i) { if (!m_groups.at(i)->shares().isEmpty()) { - QOpenGLContext *context = m_groups.at(i)->shares().first(); + QOpenGLContext *context = m_groups.at(i)->shares().constFirst(); QOpenGLSharedResource *resource = value(context); if (resource) resource->free(); diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index a0e65654a6d..3490e786a83 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -474,11 +474,11 @@ void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary) void QPlatformIntegration::removeScreen(QScreen *screen) { - const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list[0] == screen); + const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list.at(0) == screen); QGuiApplicationPrivate::screen_list.removeOne(screen); if (wasPrimary && qGuiApp && !QGuiApplicationPrivate::screen_list.isEmpty()) - emit qGuiApp->primaryScreenChanged(QGuiApplicationPrivate::screen_list[0]); + emit qGuiApp->primaryScreenChanged(QGuiApplicationPrivate::screen_list.at(0)); } /*! diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp index 8450c6a0834..3c1552c31e4 100644 --- a/src/gui/kernel/qplatformscreen.cpp +++ b/src/gui/kernel/qplatformscreen.cpp @@ -93,7 +93,7 @@ QPixmap QPlatformScreen::grabWindow(WId window, int x, int y, int width, int hei */ QWindow *QPlatformScreen::topLevelAt(const QPoint & pos) const { - QWindowList list = QGuiApplication::topLevelWindows(); + const QWindowList list = QGuiApplication::topLevelWindows(); for (int i = list.size()-1; i >= 0; --i) { QWindow *w = list[i]; if (w->isVisible() && QHighDpi::toNativePixels(w->geometry(), w).contains(pos)) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 81310ae2a2f..fa26fd77a36 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1688,11 +1688,9 @@ void QWindow::destroy() if (QGuiApplicationPrivate::currentMousePressWindow == this) QGuiApplicationPrivate::currentMousePressWindow = parent(); - for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i) { - QGuiApplicationPrivate::TabletPointData &pointData = QGuiApplicationPrivate::tabletDevicePoints[i]; - if (pointData.target == this) - pointData.target = parent(); - } + for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i) + if (QGuiApplicationPrivate::tabletDevicePoints.at(i).target == this) + QGuiApplicationPrivate::tabletDevicePoints[i].target = parent(); bool wasVisible = isVisible(); d->visibilityOnDestroy = wasVisible && d->platformWindow; diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index 597d3479153..aa0520f6950 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -1078,7 +1078,7 @@ bool QOpenGLFramebufferObject::bind() if (d->format.samples() == 0) { // Create new textures to replace the ones stolen via takeTexture(). for (int i = 0; i < d->colorAttachments.count(); ++i) { - if (!d->colorAttachments[i].guard) + if (!d->colorAttachments.at(i).guard) d->initTexture(i); } } @@ -1211,10 +1211,11 @@ GLuint QOpenGLFramebufferObject::takeTexture(int colorAttachmentIndex) QOpenGLContext *current = QOpenGLContext::currentContext(); if (current && current->shareGroup() == d->fbo_guard->group() && isBound()) release(); - id = d->colorAttachments[colorAttachmentIndex].guard ? d->colorAttachments[colorAttachmentIndex].guard->id() : 0; + auto &guard = d->colorAttachments[colorAttachmentIndex].guard; + id = guard ? guard->id() : 0; // Do not call free() on texture_guard, just null it out. // This way the texture will not be deleted when the guard is destroyed. - d->colorAttachments[colorAttachmentIndex].guard = 0; + guard = 0; } return id; } diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp index c1354893796..58dcbed50a0 100644 --- a/src/gui/opengl/qopenglgradientcache.cpp +++ b/src/gui/opengl/qopenglgradientcache.cpp @@ -108,7 +108,7 @@ GLuint QOpenGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity { quint64 hash_val = 0; - QGradientStops stops = gradient.stops(); + const QGradientStops stops = gradient.stops(); for (int i = 0; i < stops.size() && i <= 2; i++) hash_val += stops[i].second.rgba(); @@ -170,16 +170,12 @@ GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, qreal opacity) const { int pos = 0; - QGradientStops s = gradient.stops(); - QVector colors(s.size()); - - for (int i = 0; i < s.size(); ++i) - colors[i] = s[i].second.rgba64(); + const QGradientStops s = gradient.stops(); bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); uint alpha = qRound(opacity * 256); - QRgba64 current_color = combineAlpha256(colors[0], alpha); + QRgba64 current_color = combineAlpha256(s[0].second.rgba64(), alpha); qreal incr = 1.0 / qreal(size); qreal fpos = 1.5 * incr; colorTable[pos++] = qPremultiply(current_color); @@ -193,9 +189,10 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient if (colorInterpolation) current_color = qPremultiply(current_color); - for (int i = 0; i < s.size() - 1; ++i) { + const int sLast = s.size() - 1; + for (int i = 0; i < sLast; ++i) { qreal delta = 1/(s[i+1].first - s[i].first); - QRgba64 next_color = combineAlpha256(colors[i+1], alpha); + QRgba64 next_color = combineAlpha256(s[i + 1].second.rgba64(), alpha); if (colorInterpolation) next_color = qPremultiply(next_color); @@ -214,7 +211,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient Q_ASSERT(s.size() > 0); - QRgba64 last_color = qPremultiply(combineAlpha256(colors[s.size() - 1], alpha)); + QRgba64 last_color = qPremultiply(combineAlpha256(s[sLast].second.rgba64(), alpha)); for (;pos < size; ++pos) colorTable[pos] = last_color; @@ -225,16 +222,13 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const { int pos = 0; - QGradientStops s = gradient.stops(); - QVector colors(s.size()); - - for (int i = 0; i < s.size(); ++i) - colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB (on little-endian AND on big-endian) + const QGradientStops s = gradient.stops(); bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); uint alpha = qRound(opacity * 256); - uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha); + // Qt LIES! It returns ARGB (on little-endian AND on big-endian) + uint current_color = ARGB_COMBINE_ALPHA(s[0].second.rgba(), alpha); qreal incr = 1.0 / qreal(size); qreal fpos = 1.5 * incr; colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color)); @@ -248,9 +242,10 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient if (colorInterpolation) current_color = qPremultiply(current_color); - for (int i = 0; i < s.size() - 1; ++i) { + const int sLast = s.size() - 1; + for (int i = 0; i < sLast; ++i) { qreal delta = 1/(s[i+1].first - s[i].first); - uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha); + uint next_color = ARGB_COMBINE_ALPHA(s[i + 1].second.rgba(), alpha); if (colorInterpolation) next_color = qPremultiply(next_color); @@ -269,7 +264,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient Q_ASSERT(s.size() > 0); - uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); + uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(s[sLast].second.rgba(), alpha))); for (;pos < size; ++pos) colorTable[pos] = last_color; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 8bc15bf777b..9cad9e0a1d0 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -2469,7 +2469,7 @@ void QPainter::setClipping(bool enable) // we can't enable clipping if we don't have a clip if (enable - && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip)) + && (d->state->clipInfo.isEmpty() || d->state->clipInfo.constLast().operation == Qt::NoClip)) return; d->state->clipEnabled = enable; diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index ba14a45d4a2..5b91266b645 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -690,7 +690,7 @@ void QPainterPath::moveTo(const QPointF &p) d->require_moveTo = false; - if (d->elements.last().type == MoveToElement) { + if (d->elements.constLast().type == MoveToElement) { d->elements.last().x = p.x(); d->elements.last().y = p.y(); } else { @@ -738,7 +738,7 @@ void QPainterPath::lineTo(const QPointF &p) QPainterPathData *d = d_func(); Q_ASSERT(!d->elements.isEmpty()); d->maybeMoveTo(); - if (p == QPointF(d->elements.last())) + if (p == QPointF(d->elements.constLast())) return; Element elm = { p.x(), p.y(), LineToElement }; d->elements.append(elm); @@ -801,7 +801,7 @@ void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF & // Abort on empty curve as a stroker cannot handle this and the // curve is irrelevant anyway. - if (d->elements.last() == c1 && c1 == c2 && c2 == e) + if (d->elements.constLast() == c1 && c1 == c2 && c2 == e) return; d->maybeMoveTo(); @@ -984,7 +984,7 @@ QPointF QPainterPath::currentPosition() const { return !d_ptr || d_func()->elements.isEmpty() ? QPointF() - : QPointF(d_func()->elements.last().x, d_func()->elements.last().y); + : QPointF(d_func()->elements.constLast().x, d_func()->elements.constLast().y); } @@ -1073,7 +1073,7 @@ void QPainterPath::addPolygon(const QPolygonF &polygon) d_func()->elements.reserve(d_func()->elements.size() + polygon.size()); - moveTo(polygon.first()); + moveTo(polygon.constFirst()); for (int i=1; ielements << elm; @@ -1178,12 +1178,12 @@ void QPainterPath::addText(const QPointF &point, const QFont &f, const QString & QVarLengthArray visualOrder(nItems); QVarLengthArray levels(nItems); for (int i = 0; i < nItems; ++i) - levels[i] = eng->layoutData->items[i].analysis.bidiLevel; + levels[i] = eng->layoutData->items.at(i).analysis.bidiLevel; QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data()); for (int i = 0; i < nItems; ++i) { int item = visualOrder[i]; - QScriptItem &si = eng->layoutData->items[item]; + const QScriptItem &si = eng->layoutData->items.at(item); if (si.analysis.flags < QScriptAnalysis::TabOrObject) { QGlyphLayout glyphs = eng->shapedGlyphs(&si); @@ -1230,7 +1230,7 @@ void QPainterPath::addPath(const QPainterPath &other) QPainterPathData *d = reinterpret_cast(d_func()); // Remove last moveto so we don't get multiple moveto's - if (d->elements.last().type == MoveToElement) + if (d->elements.constLast().type == MoveToElement) d->elements.remove(d->elements.size()-1); // Locate where our own current subpath will start after the other path is added. @@ -1261,7 +1261,7 @@ void QPainterPath::connectPath(const QPainterPath &other) QPainterPathData *d = reinterpret_cast(d_func()); // Remove last moveto so we don't get multiple moveto's - if (d->elements.last().type == MoveToElement) + if (d->elements.constLast().type == MoveToElement) d->elements.remove(d->elements.size()-1); // Locate where our own current subpath will start after the other path is added. @@ -1273,7 +1273,7 @@ void QPainterPath::connectPath(const QPainterPath &other) d->elements[first].type = LineToElement; // avoid duplicate points - if (first > 0 && QPointF(d->elements[first]) == QPointF(d->elements[first - 1])) { + if (first > 0 && QPointF(d->elements.at(first)) == QPointF(d->elements.at(first - 1))) { d->elements.remove(first--); --cStart; } @@ -1686,8 +1686,9 @@ QList QPainterPath::toFillPolygons(const QTransform &matrix) const int isect_j = current_isects.at(j); if (isect_j == i) continue; - for (int k=0; k &isects_j = isects.at(isect_j); + for (int k = 0, size = isects_j.size(); k < size; ++k) { + int isect_k = isects_j.at(k); if (isect_k != i && !isects.at(i).contains(isect_k)) { isects[i] += isect_k; } @@ -1709,7 +1710,7 @@ QList QPainterPath::toFillPolygons(const QTransform &matrix) const // Join the intersected subpaths as rewinded polygons for (int i=0; i &subpath_list = isects[i]; + const QVector &subpath_list = isects.at(i); if (!subpath_list.isEmpty()) { QPolygonF buildUp; for (int j=0; j QPainterPath::toFillPolygons(const QTransform &matrix) const if (!subpath.isClosed()) buildUp += subpath.first(); if (!buildUp.isClosed()) - buildUp += buildUp.first(); + buildUp += buildUp.constFirst(); } polys += buildUp; } @@ -2790,7 +2791,7 @@ void QPainterPathStroker::setDashOffset(qreal offset) QPolygonF QPainterPath::toFillPolygon(const QTransform &matrix) const { - QList flats = toSubpathPolygons(matrix); + const QList flats = toSubpathPolygons(matrix); QPolygonF polygon; if (flats.isEmpty()) return polygon; diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp index 48ae3cfc808..4f2b59c775e 100644 --- a/src/gui/painting/qpathclipper.cpp +++ b/src/gui/painting/qpathclipper.cpp @@ -1648,7 +1648,7 @@ bool QPathClipper::doClip(QWingedEdge &list, ClipperMode mode) #ifdef QDEBUG_CLIPPER printf("sorted y coords:\n"); for (int i = 0; i < y_coords.size(); ++i) { - printf("%.9f\n", y_coords[i]); + printf("%.9f\n", y_coords.at(i)); } #endif @@ -1686,23 +1686,23 @@ bool QPathClipper::doClip(QWingedEdge &list, ClipperMode mode) QPathVertex *b = list.vertex(edge->second); // FIXME: this can be optimized by using binary search - const int first = qFuzzyFind(y_coords.begin(), y_coords.end(), qMin(a->y, b->y)) - y_coords.begin(); - const int last = qFuzzyFind(y_coords.begin() + first, y_coords.end(), qMax(a->y, b->y)) - y_coords.begin(); + const int first = qFuzzyFind(y_coords.cbegin(), y_coords.cend(), qMin(a->y, b->y)) - y_coords.cbegin(); + const int last = qFuzzyFind(y_coords.cbegin() + first, y_coords.cend(), qMax(a->y, b->y)) - y_coords.cbegin(); Q_ASSERT(first < y_coords.size() - 1); Q_ASSERT(last < y_coords.size()); - qreal bestY = 0.5 * (y_coords[first] + y_coords[first+1]); - qreal biggestGap = y_coords[first+1] - y_coords[first]; - + qreal biggestGap = y_coords.at(first + 1) - y_coords.at(first); + int bestIdx = first; for (int i = first + 1; i < last; ++i) { - qreal gap = y_coords[i+1] - y_coords[i]; + qreal gap = y_coords.at(i + 1) - y_coords.at(i); if (gap > biggestGap) { - bestY = 0.5 * (y_coords[i] + y_coords[i+1]); + bestIdx = i; biggestGap = gap; } } + const qreal bestY = 0.5 * (y_coords.at(bestIdx) + y_coords.at(bestIdx + 1)); #ifdef QDEBUG_CLIPPER printf("y: %.9f, gap: %.9f\n", bestY, biggestGap); diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 9e38c5272f6..d568dca6b93 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1675,7 +1675,7 @@ void QPdfEnginePrivate::writePage() uint resources = requestObject(); uint annots = requestObject(); - addXrefEntry(pages.last()); + addXrefEntry(pages.constLast()); xprintf("<<\n" "/Type /Page\n" "/Parent %d 0 R\n" @@ -1768,7 +1768,7 @@ void QPdfEnginePrivate::writeTail() ">>\n" "startxref\n%d\n" "%%%%EOF\n", - xrefPositions.size()-1, info, catalog, xrefPositions.last()); + xrefPositions.size()-1, info, catalog, xrefPositions.constLast()); } int QPdfEnginePrivate::addXrefEntry(int object, bool printostr) diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index 53d4e3fa362..d455a74d964 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -1507,7 +1507,7 @@ QRect Declaration::rectValue() const const QCss::Value &v = d->values.at(0); if (v.type != Value::Function) return QRect(); - QStringList func = v.variant.toStringList(); + const QStringList func = v.variant.toStringList(); if (func.count() != 2 || func.at(0).compare(QLatin1String("rect")) != 0) return QRect(); QStringList args = func[1].split(QLatin1Char(' '), QString::SkipEmptyParts); @@ -1653,6 +1653,7 @@ Qt::Alignment Declaration::alignmentValue() const void Declaration::borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const { + const DeclarationData *d = this->d.data(); // make it const and shadow d *image = uriValue(); for (int i = 0; i < 4; i++) cuts[i] = -1; diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 93071aaf59a..ffc5d7418bf 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -1006,9 +1006,9 @@ int QTextDocumentPrivate::undoRedo(bool undo) bool inBlock = ( undoState > 0 && undoState < undoStack.size() - && undoStack[undoState].block_part - && undoStack[undoState-1].block_part - && !undoStack[undoState-1].block_end + && undoStack.at(undoState).block_part + && undoStack.at(undoState - 1).block_part + && !undoStack.at(undoState - 1).block_end ); if (!inBlock) break; @@ -1074,12 +1074,13 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c) if (!undoStack.isEmpty() && modified) { - QTextUndoCommand &last = undoStack[undoState - 1]; + const int lastIdx = undoState - 1; + const QTextUndoCommand &last = undoStack.at(lastIdx); if ( (last.block_part && c.block_part && !last.block_end) // part of the same block => can merge || (!c.block_part && !last.block_part)) { // two single undo items => can merge - if (last.tryMerge(c)) + if (undoStack[lastIdx].tryMerge(c)) return; } } @@ -1101,7 +1102,7 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle bool redoCommandsAvailable = undoState != undoStack.size(); if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) { for (int i = 0; i < undoState; ++i) { - QTextUndoCommand c = undoStack[undoState]; + QTextUndoCommand c = undoStack.at(undoState); if (c.command & QTextUndoCommand::Custom) delete c.custom; } @@ -1113,7 +1114,7 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle } else if (stacksToClear == QTextDocument::RedoStack && redoCommandsAvailable) { for (int i = undoState; i < undoStack.size(); ++i) { - QTextUndoCommand c = undoStack[i]; + QTextUndoCommand c = undoStack.at(i); if (c.command & QTextUndoCommand::Custom) delete c.custom; } @@ -1123,7 +1124,7 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle } else if (stacksToClear == QTextDocument::UndoAndRedoStacks && !undoStack.isEmpty()) { for (int i = 0; i < undoStack.size(); ++i) { - QTextUndoCommand c = undoStack[i]; + QTextUndoCommand c = undoStack.at(i); if (c.command & QTextUndoCommand::Custom) delete c.custom; } @@ -1186,8 +1187,8 @@ void QTextDocumentPrivate::endEditBlock() return; if (undoEnabled && undoState > 0) { - const bool wasBlocking = !undoStack[undoState - 1].block_end; - if (undoStack[undoState - 1].block_part) { + const bool wasBlocking = !undoStack.at(undoState - 1).block_end; + if (undoStack.at(undoState - 1).block_part) { undoStack[undoState - 1].block_end = true; if (wasBlocking) emit document()->undoCommandAdded(); diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp index f8f4e454e00..a1a562c8390 100644 --- a/src/gui/text/qtextdocumentfragment.cpp +++ b/src/gui/text/qtextdocumentfragment.cpp @@ -882,7 +882,7 @@ QTextHtmlImporter::Table QTextHtmlImporter::scanTable(int tableNodeIdx) if (at(cell).isTableCell()) { // skip all columns with spans from previous rows while (colsInRow < rowColSpanForColumn.size()) { - const RowColSpanInfo &spanInfo = rowColSpanForColumn[colsInRow]; + const RowColSpanInfo &spanInfo = rowColSpanForColumn.at(colsInRow); if (spanInfo.row + spanInfo.rowSpan > effectiveRow) { Q_ASSERT(spanInfo.col == colsInRow); @@ -1081,8 +1081,8 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processBlockNode() && indent != 0 && (lists.isEmpty() || !hasBlock - || !lists.last().list - || lists.last().list->itemNumber(cursor.block()) == -1 + || !lists.constLast().list + || lists.constLast().list->itemNumber(cursor.block()) == -1 ) ) { block.setIndent(indent); diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index 9863955a559..b6cbd9617f5 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -265,7 +265,7 @@ void QTextTableData::updateTableSize() const QFixed effectiveLeftMargin = this->leftMargin + border + padding; const QFixed effectiveRightMargin = this->rightMargin + border + padding; size.height = contentsHeight == -1 - ? rowPositions.last() + heights.last() + padding + border + cellSpacing + effectiveBottomMargin + ? rowPositions.constLast() + heights.constLast() + padding + border + cellSpacing + effectiveBottomMargin : effectiveTopMargin + contentsHeight + effectiveBottomMargin; size.width = effectiveLeftMargin + contentsWidth + effectiveRightMargin; } @@ -1238,7 +1238,7 @@ void QTextDocumentLayoutPrivate::drawFlow(const QPointF &offset, QPainter *paint // if we're past what is already laid out then we're better off // not trying to draw things that may not be positioned correctly yet - if (currentPosInDoc >= checkPoints.last().positionInFrame) + if (currentPosInDoc >= checkPoints.constLast().positionInFrame) break; if (lastVisibleCheckPoint != checkPoints.end() @@ -1798,7 +1798,7 @@ recalc_minmax_widths: td->columnPositions[i] = td->columnPositions.at(i-1) + td->widths.at(i-1) + 2 * td->border + cellSpacing; // - margin to compensate the + margin in columnPositions[0] - const QFixed contentsWidth = td->columnPositions.last() + td->widths.last() + td->padding + td->border + cellSpacing - leftMargin; + const QFixed contentsWidth = td->columnPositions.constLast() + td->widths.constLast() + td->padding + td->border + cellSpacing - leftMargin; // if the table is too big and causes an overflow re-do the layout with WrapAnywhere as wrap // mode @@ -1845,14 +1845,14 @@ recalc_minmax_widths: td->calcRowPosition(r); const int tableStartPage = (absoluteTableY / pageHeight).truncate(); - const int currentPage = ((td->rowPositions[r] + absoluteTableY) / pageHeight).truncate(); + const int currentPage = ((td->rowPositions.at(r) + absoluteTableY) / pageHeight).truncate(); const QFixed pageBottom = (currentPage + 1) * pageHeight - td->effectiveBottomMargin - absoluteTableY - cellSpacing - td->border; const QFixed pageTop = currentPage * pageHeight + td->effectiveTopMargin - absoluteTableY + cellSpacing + td->border; const QFixed nextPageTop = pageTop + pageHeight; - if (td->rowPositions[r] > pageBottom) + if (td->rowPositions.at(r) > pageBottom) td->rowPositions[r] = nextPageTop; - else if (td->rowPositions[r] < pageTop) + else if (td->rowPositions.at(r) < pageTop) td->rowPositions[r] = pageTop; bool dropRowToNextPage = true; @@ -1863,7 +1863,7 @@ recalc_minmax_widths: QFixed dropDistance = 0; relayout: - const int rowStartPage = ((td->rowPositions[r] + absoluteTableY) / pageHeight).truncate(); + const int rowStartPage = ((td->rowPositions.at(r) + absoluteTableY) / pageHeight).truncate(); // if any of the header rows or the first non-header row start on the next page // then the entire header should be dropped if (r <= headerRowCount && rowStartPage > tableStartPage && !hasDroppedTable) { @@ -1927,13 +1927,13 @@ relayout: } if (rowCellCount > 0 && dropRowToNextPage) { - dropDistance = nextPageTop - td->rowPositions[r]; + dropDistance = nextPageTop - td->rowPositions.at(r); td->rowPositions[r] = nextPageTop; td->heights[r] = 0; dropRowToNextPage = false; cellHeights.resize(cellCountBeforeRow); if (r > headerRowCount) - td->heights[r-1] = pageBottom - td->rowPositions[r-1]; + td->heights[r - 1] = pageBottom - td->rowPositions.at(r - 1); goto relayout; } @@ -1944,7 +1944,7 @@ relayout: } if (r == headerRowCount - 1) { - td->headerHeight = td->rowPositions[r] + td->heights[r] - td->rowPositions[0] + td->cellSpacing + 2 * td->border; + td->headerHeight = td->rowPositions.at(r) + td->heights.at(r) - td->rowPositions.at(0) + td->cellSpacing + 2 * td->border; td->headerHeight -= td->headerHeight * (td->headerHeight / pageHeight).truncate(); td->effectiveTopMargin += td->headerHeight; } @@ -2304,7 +2304,7 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout docPos = it.currentBlock().position(); if (inRootFrame) { - if (qAbs(layoutStruct->y - checkPoints.last().y) > 2000) { + if (qAbs(layoutStruct->y - checkPoints.constLast().y) > 2000) { QFixed left, right; floatMargins(layoutStruct->y, layoutStruct, &left, &right); if (left == layoutStruct->x_left && right == layoutStruct->x_right) { @@ -2554,7 +2554,7 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout checkPoints.append(cp); checkPoints.reserve(checkPoints.size()); } else { - currentLazyLayoutPosition = checkPoints.last().positionInFrame; + currentLazyLayoutPosition = checkPoints.constLast().positionInFrame; // ####### //checkPoints.last().positionInFrame = q->document()->docHandle()->length(); } diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 78649750919..7ee02b71c95 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -3274,7 +3274,7 @@ int QTextEngine::endOfLine(int lineNum) insertionPointsForLine(lineNum, insertionPoints); if (insertionPoints.size() > 0) - return insertionPoints.last(); + return insertionPoints.constLast(); return 0; } @@ -3284,7 +3284,7 @@ int QTextEngine::beginningOfLine(int lineNum) insertionPointsForLine(lineNum, insertionPoints); if (insertionPoints.size() > 0) - return insertionPoints.first(); + return insertionPoints.constFirst(); return 0; } diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 49ec9ca768b..402bd75a769 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -3462,7 +3462,7 @@ void QTextFormatCollection::setDefaultFont(const QFont &f) { defaultFnt = f; for (int i = 0; i < formats.count(); ++i) - if (formats[i].d) + if (formats.at(i).d) formats[i].d->resolveFont(defaultFnt); } diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index 576ff7d9350..103a208c26f 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -665,7 +665,7 @@ void QTextHtmlParser::parseTag() if (hasPrefix(QLatin1Char('/'))) { if (nodes.last().id == Html_style) { #ifndef QT_NO_CSSPARSER - QCss::Parser parser(nodes.last().text); + QCss::Parser parser(nodes.constLast().text); QCss::StyleSheet sheet; sheet.origin = QCss::StyleSheetOrigin_Author; parser.parse(&sheet, Qt::CaseInsensitive); diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index bd2a9d5183c..ad537b7126d 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -812,10 +812,10 @@ bool QTextOdfWriter::writeAll() } // add objects for lists, frames and tables - QVector allFormats = m_document->allFormats(); - QList copy = formats.toList(); - for (QList::Iterator iter = copy.begin(); iter != copy.end(); ++iter) { - QTextObject *object = m_document->objectForFormat(allFormats[*iter]); + const QVector allFormats = m_document->allFormats(); + const QList copy = formats.toList(); + for (auto index : copy) { + QTextObject *object = m_document->objectForFormat(allFormats[index]); if (object) formats << object->formatIndex(); } diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp index 2d5636e1d93..e4a3c2b915d 100644 --- a/src/gui/text/qtexttable.cpp +++ b/src/gui/text/qtexttable.cpp @@ -824,7 +824,7 @@ void QTextTable::insertColumns(int pos, int num) QVector columnWidths = tfmt.columnWidthConstraints(); if (! columnWidths.isEmpty()) { for (int i = num; i > 0; --i) - columnWidths.insert(pos, columnWidths[qMax(0, pos-1)]); + columnWidths.insert(pos, columnWidths.at(qMax(0, pos - 1))); } tfmt.setColumnWidthConstraints (columnWidths); QTextObject::setFormat(tfmt); @@ -1046,11 +1046,12 @@ void QTextTable::mergeCells(int row, int column, int numRows, int numCols) // find the position at which to insert the contents of the merged cells QFragmentFindHelper helper(origCellPosition, p->fragmentMap()); - const auto it = std::lower_bound(d->cells.begin(), d->cells.end(), helper); + const auto begin = d->cells.cbegin(); + const auto it = std::lower_bound(begin, d->cells.cend(), helper); Q_ASSERT(it != d->cells.end()); Q_ASSERT(!(helper < *it)); Q_ASSERT(*it == cellFragment); - const int insertCellIndex = it - d->cells.begin(); + const int insertCellIndex = it - begin; int insertFragment = d->cells.value(insertCellIndex + 1, d->fragment_end); uint insertPos = p->fragmentMap().position(insertFragment); @@ -1079,11 +1080,12 @@ void QTextTable::mergeCells(int row, int column, int numRows, int numCols) if (firstCellIndex == -1) { QFragmentFindHelper helper(pos, p->fragmentMap()); - const auto it = std::lower_bound(d->cells.begin(), d->cells.end(), helper); + const auto begin = d->cells.cbegin(); + const auto it = std::lower_bound(begin, d->cells.cend(), helper); Q_ASSERT(it != d->cells.end()); Q_ASSERT(!(helper < *it)); Q_ASSERT(*it == fragment); - firstCellIndex = cellIndex = it - d->cells.begin(); + firstCellIndex = cellIndex = it - begin; } ++cellIndex; @@ -1136,7 +1138,7 @@ void QTextTable::mergeCells(int row, int column, int numRows, int numCols) } } - d->fragment_start = d->cells.first(); + d->fragment_start = d->cells.constFirst(); fmt.setTableCellRowSpan(numRows); fmt.setTableCellColumnSpan(numCols); @@ -1212,9 +1214,9 @@ void QTextTable::splitCell(int row, int column, int numRows, int numCols) for (int r = row + 1; r < row + rowSpan; ++r) { // find the cell before which to insert the new cell markers int gridIndex = r * d->nCols + column; - QVector::iterator it = std::upper_bound(d->cellIndices.begin(), d->cellIndices.end(), gridIndex); - int cellIndex = it - d->cellIndices.begin(); - int fragment = d->cells.value(cellIndex, d->fragment_end); + const auto begin = d->cellIndices.cbegin(); + const auto it = std::upper_bound(begin, d->cellIndices.cend(), gridIndex); + int fragment = d->cells.value(it - begin, d->fragment_end); rowPositions[r - row] = p->fragmentMap().position(fragment); } diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp index 20bc7166aba..8ff2a3eeeca 100644 --- a/src/gui/util/qgridlayoutengine.cpp +++ b/src/gui/util/qgridlayoutengine.cpp @@ -218,8 +218,9 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz qreal sumAvailable; for (int i = 0; i < n; ++i) { - if (stretches[start + i] > 0) - sumStretches += stretches[start + i]; + const int stretch = stretches.at(start + i); + if (stretch > 0) + sumStretches += stretch; } if (targetSize < totalBox.q_preferredSize) { @@ -1034,19 +1035,19 @@ void QGridLayoutEngine::setGeometries(const QRectF &contentsGeometry, const QAbs for (int i = q_items.count() - 1; i >= 0; --i) { QGridLayoutItem *item = q_items.at(i); - qreal x = q_xx[item->firstColumn()]; - qreal y = q_yy[item->firstRow()]; - qreal width = q_widths[item->lastColumn()]; - qreal height = q_heights[item->lastRow()]; + qreal x = q_xx.at(item->firstColumn()); + qreal y = q_yy.at(item->firstRow()); + qreal width = q_widths.at(item->lastColumn()); + qreal height = q_heights.at(item->lastRow()); if (item->columnSpan() != 1) - width += q_xx[item->lastColumn()] - x; + width += q_xx.at(item->lastColumn()) - x; if (item->rowSpan() != 1) - height += q_yy[item->lastRow()] - y; + height += q_yy.at(item->lastRow()) - y; const Qt::Alignment align = effectiveAlignment(item); QRectF geom = item->geometryWithin(contentsGeometry.x() + x, contentsGeometry.y() + y, - width, height, q_descents[item->lastRow()], align, m_snapToPixelGrid); + width, height, q_descents.at(item->lastRow()), align, m_snapToPixelGrid); if (m_snapToPixelGrid) { // x and y should already be rounded, but the call to geometryWithin() above might // result in a geom with x,y at half-pixels (due to centering within the cell) From 8fb29ed259393a83e8fb5545c419543a85fc7bc9 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 31 May 2016 10:56:25 +0200 Subject: [PATCH 104/173] Don't alter input string in QTextLayout with ShowLineAndParagraphSeparators When ShowLineAndParagraphSeparators was set, we would replace the separator character in the user's string in some cases, since we never detached from the input string and just const_cast the pointer to the shared buffer. [ChangeLog][QtGui][Text] Fixed bug where a QTextLayout with ShowLineAndParagraphSeparators would modify the layout's input string. Task-number: QTBUG-42033 Change-Id: I92f9100b750f16e52b38b718245c13e5c4a0ebb9 Reviewed-by: Lars Knoll Reviewed-by: Konstantin Ritt --- src/gui/text/qtextengine.cpp | 8 ++++- .../gui/text/qtextlayout/tst_qtextlayout.cpp | 33 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index d0c2779a65d..17a91f5a6a5 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1635,8 +1635,14 @@ void QTextEngine::itemize() const if (analysis->bidiLevel % 2) --analysis->bidiLevel; analysis->flags = QScriptAnalysis::LineOrParagraphSeparator; - if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) + if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) { + const int offset = uc - string; + layoutData->string.detach(); + string = reinterpret_cast(layoutData->string.unicode()); + uc = string + offset; + e = uc + length; *const_cast(uc) = 0x21B5; // visual line separator + } break; case QChar::Tabulation: analysis->flags = QScriptAnalysis::Tab; diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index de0c2d6dbed..e778232461c 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -142,6 +142,7 @@ private slots: void xToCursorForLigatures(); void cursorInNonStopChars(); void nbsp(); + void noModificationOfInputString(); private: QFont testFont; @@ -2176,5 +2177,37 @@ void tst_QTextLayout::layoutWithCustomTabStops() QVERIFY(longWidth > shortWidth); } +void tst_QTextLayout::noModificationOfInputString() +{ + QString s = QString(QChar(QChar::LineSeparator)); + { + QTextLayout layout; + layout.setText(s); + + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QCOMPARE(s.size(), 1); + QCOMPARE(s.at(0), QChar(QChar::LineSeparator)); + } + + { + QTextLayout layout; + layout.setText(s); + + QTextOption option; + option.setFlags(QTextOption::ShowLineAndParagraphSeparators); + layout.setTextOption(option); + + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QCOMPARE(s.size(), 1); + QCOMPARE(s.at(0), QChar(QChar::LineSeparator)); + } +} + QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc" From 3432742caa5171ceddee0e75adefda9310c3b1eb Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Mon, 23 May 2016 22:00:05 +0200 Subject: [PATCH 105/173] Merge BSD implementations of QLockFilePrivate::processNameByPid() Until now, several solutions for the implementations of processNameByPid() on BSD systems existed: - one for FreeBSD using libutil through kinfo_getproc() using sysctl() implicitly - one for GNU/kFreeBSD using sysctl() explicitly added in commit a8f4fa217daa1b6f7b13cc48c1e5ee8d2d76b008 OpenBSD and NetBSD also had different approaches in their ports patches using kvm() and sysctl(). The code unifies this for all BSDs using sysctl(). Change-Id: Iced9ef01e5966d8688f464f51024a7ed562e26a3 Reviewed-by: Thiago Macieira Reviewed-by: Dmitry Shachnev --- src/corelib/io/io.pri | 1 - src/corelib/io/qlockfile_unix.cpp | 43 ++++++++++++++++--------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 8d9908cd905..553c9964586 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -147,7 +147,6 @@ win32 { SOURCES += io/qsettings_mac.cpp OBJECTIVE_SOURCES += io/qurl_mac.mm } - freebsd: LIBS_PRIVATE += -lutil # qlockfile_unix.cpp requires this mac { osx { OBJECTIVE_SOURCES += io/qfilesystemwatcher_fsevents.mm diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index f23a232fb8c..eed3158fbe7 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -59,14 +59,12 @@ # include # include #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) +# if !defined(Q_OS_NETBSD) # include -# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) +# endif # include # include # include -# else -# include -# endif #endif QT_BEGIN_NAMESPACE @@ -269,30 +267,33 @@ QString QLockFilePrivate::processNameByPid(qint64 pid) buf[len] = 0; return QFileInfo(QFile::decodeName(buf)).fileName(); #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) -# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; - size_t len = 0; - if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) - return QString(); - kinfo_proc *proc = static_cast(malloc(len)); +# if defined(Q_OS_NETBSD) + struct kinfo_proc2 kp; + int mib[6] = { CTL_KERN, KERN_PROC2, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc2), 1 }; +# elif defined(Q_OS_OPENBSD) + struct kinfo_proc kp; + int mib[6] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc), 1 }; # else - kinfo_proc *proc = kinfo_getproc(pid); + struct kinfo_proc kp; + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid }; # endif - if (!proc) + size_t len = sizeof(kp); + u_int mib_len = sizeof(mib)/sizeof(u_int); + + if (sysctl(mib, mib_len, &kp, &len, NULL, 0) < 0) return QString(); -# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) - if (sysctl(mib, 4, proc, &len, NULL, 0) < 0) { - free(proc); + +# if defined(Q_OS_OPENBSD) || defined(Q_OS_NETBSD) + if (kp.p_pid != pid) return QString(); - } - if (proc->ki_pid != pid) { - free(proc); + QString name = QFile::decodeName(kp.p_comm); +# else + if (kp.ki_pid != pid) return QString(); - } + QString name = QFile::decodeName(kp.ki_comm); # endif - QString name = QFile::decodeName(proc->ki_comm); - free(proc); return name; + #else Q_UNUSED(pid); return QString(); From d96057328aae28a27a46492a310d9a05e250631c Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 31 May 2016 06:13:50 +0200 Subject: [PATCH 106/173] Compile fix: add OpenBSD define for ffsll usage On OpenBSD, ffsll needs to be defined to compile. This is the same change as in commit 725a9c27021bef1ac3828a4eafc013a2f50e6f22 for NetBSD. Change-Id: I3060caa10950a9419084a12de8c88a2f98b34d07 Reviewed-by: Thiago Macieira --- src/corelib/tools/qsimd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 0e3359ab813..ac28832c31e 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -636,7 +636,7 @@ int ffsll(quint64 i) #endif } #endif -#elif defined(Q_OS_NETBSD) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU) +#elif defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU) # define ffsll __builtin_ffsll #endif From 9dd58c6239a28a558e110309beb86d6ea3f2dec2 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 31 May 2016 12:14:24 +0200 Subject: [PATCH 107/173] Compile fix: OpenBSD does not have Fix compiling under OpenBSD by using Q_OS_OPENBSD define for missing include file and adding required typedef. Obtained from OpenBSD ports patches for qt-5.5.1 at http://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/x11/qt5/patches/ Change-Id: Ide223bffb6b116e8341d0eb39329af4d7a0be6a0 Reviewed-by: Thiago Macieira --- src/network/kernel/qdnslookup_unix.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index cb3bdfe8ff2..584f0b0f0ef 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -40,7 +40,9 @@ #include #include #include -#include +#if !defined(Q_OS_OPENBSD) +# include +#endif #include #if defined(__GNU_LIBRARY__) && !defined(__UCLIBC__) @@ -51,6 +53,9 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_LIBRARY +#if defined(Q_OS_OPENBSD) +typedef struct __res_state* res_state; +#endif typedef int (*dn_expand_proto)(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); static dn_expand_proto local_dn_expand = 0; typedef void (*res_nclose_proto)(res_state); From 0720569b151efd59cb253025d66ec9982b5d797a Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 31 May 2016 14:00:10 +0200 Subject: [PATCH 108/173] OpenBSD: add /etc/ssl as cert dir Add the /etc/ssl default path to the list of certificate directories for OpenBSD. Change-Id: I13dff6a219e2c848501ec9bf191160a48f919515 Reviewed-by: Richard J. Moore --- src/network/ssl/qsslsocket.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 805adc734ff..25a471dda8f 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -2590,7 +2590,8 @@ QList QSslSocketPrivate::unixRootCertDirectories() << "/var/ssl/certs/" // AIX << "/usr/local/ssl/certs/" // Solaris << "/etc/openssl/certs/" // BlackBerry - << "/opt/openssl/certs/"; // HP-UX + << "/opt/openssl/certs/" // HP-UX + << "/etc/ssl/"; // OpenBSD } /*! From a1de7c40f4a22f996fcf922e69315c1f2cea6e96 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Wed, 1 Jun 2016 13:14:01 +0200 Subject: [PATCH 109/173] Blacklist tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible test. It fails randomly on Windows, possibly due to timing issues. Change-Id: I0ef74f203455eb4ea8aeee4c8fc9bf1fbf6fb8ff Reviewed-by: Eskil Abrahamsen Blomfeldt --- tests/auto/widgets/widgets/qopenglwidget/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST index 725b8e93b42..cdff75ba655 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST +++ b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST @@ -1,2 +1,4 @@ [clearAndGrab] opensuse-13.1 +[stackWidgetOpaqueChildIsVisible] +windows From 9fdeaf602e44377226d5c1b23e111c3454e42843 Mon Sep 17 00:00:00 2001 From: Volker Krause Date: Tue, 31 May 2016 19:03:27 +0200 Subject: [PATCH 110/173] Add Q_ENUM for QNetworkAccessManager::NetworkAccessibility. This is needed for generic property access to work correctly. Change-Id: I88cd40238a8caf8df6c71b22e2fa0c4d5655a88a Reviewed-by: Richard J. Moore --- src/network/access/qnetworkaccessmanager.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 4ce47577c85..cba5cc09d64 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -94,6 +94,7 @@ public: NotAccessible = 0, Accessible = 1 }; + Q_ENUM(NetworkAccessibility) #endif explicit QNetworkAccessManager(QObject *parent = Q_NULLPTR); From bbb440bab261fecc7c9baf779dadf36659d3cf6f Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 20 May 2016 06:28:26 +0200 Subject: [PATCH 111/173] QJsonValue: fix use-after-free in assignment operator The assignment operator of a String QJsonValue that holds the only remaining reference to the QString::Data block was freeing the block before obtaining its own reference, leading to a use-after-free in the case where *this was passed as 'other' (self-assignment). Fixed by reformulating the assignment operator in terms of the copy ctor, using the copy-swap idiom, with the twist that QJsonValue doesn't, yet, have a swap member function, so we use three per-member qSwap()s. Change-Id: I3c5ccc4d9f32c7593af3fc6a0edbf12b7feb1391 Reviewed-by: Lars Knoll --- src/corelib/json/qjsonvalue.cpp | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp index 76e5ae562fb..c9f3ec35fe3 100644 --- a/src/corelib/json/qjsonvalue.cpp +++ b/src/corelib/json/qjsonvalue.cpp @@ -269,25 +269,11 @@ QJsonValue::QJsonValue(const QJsonValue &other) */ QJsonValue &QJsonValue::operator =(const QJsonValue &other) { - if (t == String && stringData && !stringData->ref.deref()) - free(stringData); - - t = other.t; - dbl = other.dbl; - - if (d != other.d) { - - if (d && !d->ref.deref()) - delete d; - d = other.d; - if (d) - d->ref.ref(); - - } - - if (t == String && stringData) - stringData->ref.ref(); - + QJsonValue copy(other); + // swap(copy); + qSwap(dbl, copy.dbl); + qSwap(d, copy.d); + qSwap(t, copy.t); return *this; } From e81877218b2c5f5321a2032e602e7255f370e72a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 1 Jun 2016 09:58:48 +0000 Subject: [PATCH 112/173] Revert "QObject::connect: reduce generated code size for statics and functors" This reverts commit 2e4191eadce4cfe944afd0baf37f06bbcb65c5f4. The change is backwards compatible but not forwards, so it can't appear past the .0 release. Change-Id: I390c5e80795a9b3b27f6edcab79f7892a79c3564 Reviewed-by: Marc Mutz --- src/corelib/kernel/qobject_impl.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index b4091a4f1c6..6140ae775eb 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -126,7 +126,7 @@ namespace QtPrivate { inline void destroyIfLastRef() Q_DECL_NOTHROW { if (!m_ref.deref()) m_impl(Destroy, this, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR); } - inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, Q_NULLPTR, a, &ret); return ret; } + inline bool compare(void **a) { bool ret; m_impl(Compare, this, Q_NULLPTR, a, &ret); return ret; } inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, Q_NULLPTR); } protected: ~QSlotObjectBase() {} @@ -172,9 +172,10 @@ namespace QtPrivate { case Call: FuncType::template call(static_cast(this_)->function, r, a); break; - case Compare: // not implemented - case NumOperations: - Q_UNUSED(ret); + case Compare: + *ret = false; // not implemented + break; + case NumOperations: ; } } public: @@ -196,9 +197,10 @@ namespace QtPrivate { case Call: FuncType::template call(static_cast(this_)->function, r, a); break; - case Compare: // not implemented - case NumOperations: - Q_UNUSED(ret); + case Compare: + *ret = false; // not implemented + break; + case NumOperations: ; } } public: From 90988a2c6713e41937241e0848043a2e28973d68 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 2 Jun 2016 11:36:44 +0300 Subject: [PATCH 113/173] QFontDatabase: append substitutes directly to the family list Don't create tmp list. Change-Id: I1aa80f1fb5589eb01ad2a41cf028b920a618a636 Reviewed-by: Edward Welbourne --- src/gui/text/qfontdatabase.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index e4c9b45dc2c..359c461ad3a 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -709,13 +709,8 @@ static QStringList familyList(const QFontDef &req) } // append the substitute list for each family in family_list - QStringList subs_list; - QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd(); - for (; it != end; ++it) - subs_list += QFont::substitutes(*it); -// qDebug() << "adding substs: " << subs_list; - - family_list += subs_list; + for (int i = 0, size = family_list.size(); i < size; ++i) + family_list += QFont::substitutes(family_list.at(i)); return family_list; } From 6030e63037cdc09d43ad372ecbcfeece72b6e353 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 31 Mar 2016 17:34:32 +0300 Subject: [PATCH 114/173] QtGui: use QStringRef to optimize memory allocation Replace substring functions that return QString with corresponding functions that return QStringRef where it's possible. Create QString from QStringRef only where necessary. Change-Id: Id83c60cc7568b20ef008b51c582cfdf466a47e35 Reviewed-by: Edward Welbourne --- src/gui/image/qpnghandler.cpp | 2 +- src/gui/kernel/qkeysequence.cpp | 13 +++++++------ src/gui/text/qcssparser.cpp | 7 +++---- src/gui/text/qfont.cpp | 4 ++-- src/gui/text/qfontdatabase.cpp | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index c84f429e463..d021e6f09f4 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -761,7 +761,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt QMap::ConstIterator it = text.constBegin(); int i = 0; while (it != text.constEnd()) { - text_ptr[i].key = qstrdup(it.key().left(79).toLatin1().constData()); + text_ptr[i].key = qstrdup(it.key().leftRef(79).toLatin1().constData()); bool noCompress = (it.value().length() < 40); #ifdef PNG_iTXt_SUPPORTED diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index f7771c252fc..e7b1f9e073b 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -1154,21 +1154,22 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence } int p = accel.lastIndexOf(QLatin1Char('+'), str.length() - 2); // -2 so that Ctrl++ works + QStringRef accelRef(&accel); if(p > 0) - accel = accel.mid(p + 1); + accelRef = accelRef.mid(p + 1); int fnum = 0; - if (accel.length() == 1) { + if (accelRef.length() == 1) { #if defined(Q_OS_MACX) - int qtKey = qtkeyForMacSymbol(accel.at(0)); + int qtKey = qtkeyForMacSymbol(accelRef.at(0)); if (qtKey != -1) { ret |= qtKey; } else #endif { - ret |= accel.at(0).toUpper().unicode(); + ret |= accelRef.at(0).toUpper().unicode(); } - } else if (accel.at(0) == QLatin1Char('f') && (fnum = accel.mid(1).toInt()) >= 1 && fnum <= 35) { + } else if (accelRef.at(0) == QLatin1Char('f') && (fnum = accelRef.mid(1).toInt()) >= 1 && fnum <= 35) { ret |= Qt::Key_F1 + fnum - 1; } else { // For NativeText, check the traslation table first, @@ -1182,7 +1183,7 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence QString keyName(tran == 0 ? QCoreApplication::translate("QShortcut", keyname[i].name) : QString::fromLatin1(keyname[i].name)); - if (accel == keyName.toLower()) { + if (accelRef == keyName.toLower()) { ret |= keyname[i].key; found = true; break; diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index d455a74d964..c237d80d343 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -1510,7 +1510,7 @@ QRect Declaration::rectValue() const const QStringList func = v.variant.toStringList(); if (func.count() != 2 || func.at(0).compare(QLatin1String("rect")) != 0) return QRect(); - QStringList args = func[1].split(QLatin1Char(' '), QString::SkipEmptyParts); + const auto args = func[1].splitRef(QLatin1Char(' '), QString::SkipEmptyParts); if (args.count() != 4) return QRect(); QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()); @@ -1915,9 +1915,8 @@ bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node) return false; if (a.valueMatchCriterium == QCss::AttributeSelector::MatchContains) { - - QStringList lst = attrValue.split(QLatin1Char(' ')); - if (!lst.contains(a.value)) + const auto lst = attrValue.splitRef(QLatin1Char(' ')); + if (!lst.contains(QStringRef(&a.value))) return false; } else if ( (a.valueMatchCriterium == QCss::AttributeSelector::MatchEqual diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index f92e4ab457e..828dbc318c0 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2033,7 +2033,7 @@ uint qHash(const QFont &font, uint seed) Q_DECL_NOTHROW */ bool QFont::fromString(const QString &descrip) { - QStringList l(descrip.split(QLatin1Char(','))); + const auto l = descrip.splitRef(QLatin1Char(',')); int count = l.count(); if (!count || (count > 2 && count < 9) || count > 11) { @@ -2042,7 +2042,7 @@ bool QFont::fromString(const QString &descrip) return false; } - setFamily(l[0]); + setFamily(l[0].toString()); if (count > 1 && l[1].toDouble() > 0.0) setPointSizeF(l[1].toDouble()); if (count == 9) { diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 359c461ad3a..9b50581bea8 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -697,15 +697,15 @@ static QStringList familyList(const QFontDef &req) if (req.family.isEmpty()) return family_list; - QStringList list = req.family.split(QLatin1Char(',')); + const auto list = req.family.splitRef(QLatin1Char(',')); const int numFamilies = list.size(); family_list.reserve(numFamilies); for (int i = 0; i < numFamilies; ++i) { - QString str = list.at(i).trimmed(); + QStringRef str = list.at(i).trimmed(); if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"'))) || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\'')))) str = str.mid(1, str.length() - 2); - family_list << str; + family_list << str.toString(); } // append the substitute list for each family in family_list From f046205526031fd42f4492ada28194cedcda1a4c Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 2 Jun 2016 12:14:44 +0300 Subject: [PATCH 115/173] QTextDocument: use QL1S::size() to get size of internal string ... instead of call of qstrlen(), because of ctor of QL1S already do this work for us. The old code is Qt4 legacy. Change-Id: I449ce7ea481af0efeade258d2cd5652db1f1a8b1 Reviewed-by: Edward Welbourne Reviewed-by: Konstantin Ritt --- src/gui/text/qtextdocument.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index febd5da488c..bb4f0314154 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2430,7 +2430,7 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format) html += QLatin1Char(';'); attributesEmitted = true; } else { - html.chop(qstrlen(decorationTag.latin1())); + html.chop(decorationTag.size()); } if (format.foreground() != defaultCharFormat.foreground() @@ -2665,7 +2665,7 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment) if (attributesEmitted) html += QLatin1String("\">"); else - html.chop(qstrlen(styleTag.latin1())); + html.chop(styleTag.size()); if (isObject) { for (int i = 0; isImage && i < txt.length(); ++i) { @@ -3227,7 +3227,7 @@ void QTextHtmlExporter::emitFrameStyle(const QTextFrameFormat &format, FrameType QString::number(format.rightMargin())); if (html.length() == originalHtmlLength) // nothing emitted? - html.chop(qstrlen(styleAttribute.latin1())); + html.chop(styleAttribute.size()); else html += QLatin1Char('\"'); } From 84bd6a83a02f6357978dbf3e8b3a553a96d22772 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 2 Jun 2016 10:53:38 +0300 Subject: [PATCH 116/173] QTextDocument: use QString::replace() for replacing ... instead of homebrew algorithm. Saves some memory allocations and some text size. Change-Id: I3abb49d3b247dbb132688ea99e6eae731e31615c Reviewed-by: Edward Welbourne --- src/gui/text/qtextdocument.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index bb4f0314154..723918ae69c 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2700,13 +2700,8 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment) // split for [\n{LineSeparator}] QString forcedLineBreakRegExp = QString::fromLatin1("[\\na]"); forcedLineBreakRegExp[3] = QChar::LineSeparator; - - const QStringList lines = txt.split(QRegExp(forcedLineBreakRegExp)); - for (int i = 0; i < lines.count(); ++i) { - if (i > 0) - html += QLatin1String("
"); // space on purpose for compatibility with Netscape, Lynx & Co. - html += lines.at(i); - } + // space in BR on purpose for compatibility with old-fashioned browsers + html += txt.replace(QRegExp(forcedLineBreakRegExp), QLatin1String("
")); } if (attributesEmitted) From 7b8a553a130125ef4cf2592879ea8c438aa3d966 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 30 May 2016 13:18:21 -0300 Subject: [PATCH 117/173] Remove the code for QObject::connect for non-C++11 compilers It's required now in Qt 5.7 (at least the required features of rvalue references and variadic templates) Change-Id: I87e17314d8b24ae983b1fffd145364c52f9bb6c3 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.h | 23 -- src/corelib/kernel/qobject_impl.h | 29 -- src/corelib/kernel/qobjectdefs_impl.h | 381 -------------------------- 3 files changed, 433 deletions(-) diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 1f3d3dcfc72..e99c8f35f3b 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -299,7 +299,6 @@ public: connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, const QObject *context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { -#if defined (Q_COMPILER_VARIADIC_TEMPLATES) typedef QtPrivate::FunctionPointer SignalType; const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount::Value; @@ -307,28 +306,6 @@ public: "Signal and slot arguments are not compatible."); const int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0; typedef typename QtPrivate::FunctorReturnType::Value>::Value SlotReturnType; -#else - // Without variadic template, we don't detect the best overload of operator(). We just - // assume there is only one simple operator() and connect to &Func2::operator() - - /* If you get an error such as: - couldn't deduce template parameter 'Func2Operator' - or - cannot resolve address of overloaded function - It means the functor does not have a single operator(). - Functors with overloaded or templated operator() are only supported if the compiler supports - C++11 variadic templates - */ - typedef QtPrivate::FunctionPointer SlotType ; - typedef QtPrivate::FunctionPointer SignalType; - typedef typename SlotType::ReturnType SlotReturnType; - const int SlotArgumentCount = SlotType::ArgumentCount; - - Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= SlotArgumentCount, - "The slot requires more arguments than the signal provides."); - Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments::value), - "Signal and slot arguments are not compatible."); -#endif Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible::value), "Return type of the slot is not compatible with the return type of the signal."); diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index 6140ae775eb..aa68c9c1add 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -62,34 +62,6 @@ namespace QtPrivate { If one of the type is not declared, the function return 0 and the signal cannot be used in queued connection. */ -#ifndef Q_COMPILER_VARIADIC_TEMPLATES - template struct TypesAreDeclaredMetaType { enum { Value = false }; }; - template <> struct TypesAreDeclaredMetaType { enum { Value = true }; }; - template struct TypesAreDeclaredMetaType > { enum { Value = QMetaTypeId2::Defined && TypesAreDeclaredMetaType::Value }; }; - - template ::Value > struct ConnectionTypes - { static const int *types() { return 0; } }; - template <> struct ConnectionTypes - { static const int *types() { static const int t[1] = { 0 }; return t; } }; - template struct ConnectionTypes, true> - { static const int *types() { static const int t[2] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; - template struct ConnectionTypes >, true> - { static const int *types() { static const int t[3] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; - template struct ConnectionTypes > >, true> - { static const int *types() { static const int t[4] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; - template struct ConnectionTypes > > >, true> - { static const int *types() { static const int t[5] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; - template struct ConnectionTypes > > > >, true> - { static const int *types() { static const int t[6] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; - template - struct ConnectionTypes > > > > >, true> - { static const int *types() { static const int t[7] = { QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), - QtPrivate::QMetaTypeIdHelper::qt_metatype_id(), 0 }; return t; } }; -#else template struct TypesAreDeclaredMetaType { enum { Value = false }; }; template <> struct TypesAreDeclaredMetaType> { enum { Value = true }; }; template struct TypesAreDeclaredMetaType > @@ -101,7 +73,6 @@ namespace QtPrivate { { static const int *types() { return Q_NULLPTR; } }; template struct ConnectionTypes, true> { static const int *types() { static const int t[sizeof...(Args) + 1] = { (QtPrivate::QMetaTypeIdHelper::qt_metatype_id())..., 0 }; return t; } }; -#endif // internal base class (interface) containing functions required to call a slot managed by a pointer to function. class QSlotObjectBase { diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index 6ef83a6eb56..5eae70ecc56 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -65,11 +65,6 @@ namespace QtPrivate { List_Left take a list and a number as a parameter and returns (via the Value typedef, the list composed of the first N element of the list */ -#ifndef Q_COMPILER_VARIADIC_TEMPLATES - template struct List { typedef Head Car; typedef Tail Cdr; }; - template struct List_Left { typedef List::Value > Value; }; - template struct List_Left { typedef void Value; }; -#else // With variadic template, lists are represented using a variadic template argument instead of the lisp way template struct List {}; template struct List { typedef Head Car; typedef List Cdr; }; @@ -79,7 +74,6 @@ namespace QtPrivate { typedef typename List_Append,typename List_Left::Value>::Value Value; }; template struct List_Left { typedef List<> Value; }; -#endif // List_Select returns (via typedef Value) the Nth element of the list L template struct List_Select { typedef typename List_Select::Value Value; }; template struct List_Select { typedef typename L::Car Value; }; @@ -100,13 +94,11 @@ namespace QtPrivate { if (container.data) *reinterpret_cast(container.data) = value; } -#ifdef Q_COMPILER_RVALUE_REFS template void operator,(T &&value, const ApplyReturnValue &container) { if (container.data) *reinterpret_cast(container.data) = value; } -#endif template void operator,(T, const ApplyReturnValue &) {} @@ -127,364 +119,6 @@ namespace QtPrivate { The Functor struct is the helper to call a functor of N argument. its call function is the same as the FunctionPointer::call function. */ -#ifndef Q_COMPILER_VARIADIC_TEMPLATES - template struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; }; - //Pointers to member functions - template struct FunctionPointer - { - typedef Obj Object; - typedef void Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (); - enum {ArgumentCount = 0, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue(arg[0]); } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1); - enum {ArgumentCount = 1, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)((*reinterpret_cast::Type *>(arg[1]))), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2); - enum {ArgumentCount = 2, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3); - enum {ArgumentCount = 3, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4); - enum {ArgumentCount = 4, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); - enum {ArgumentCount = 5, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); - } - }; - template - struct FunctionPointer - { - typedef Obj Object; - typedef List > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); - enum {ArgumentCount = 6, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5]), - *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); - } - }; - - //Pointers to const member functions - template struct FunctionPointer - { - typedef Obj Object; - typedef void Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) () const; - enum {ArgumentCount = 0, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue(arg[0]); } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1) const; - enum {ArgumentCount = 1, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)((*reinterpret_cast::Type *>(arg[1]))), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2) const; - enum {ArgumentCount = 2, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3) const; - enum {ArgumentCount = 3, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4) const; - enum {ArgumentCount = 4, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef Obj Object; - typedef List > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5) const; - enum {ArgumentCount = 5, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); - } - }; - template - struct FunctionPointer - { - typedef Obj Object; - typedef List > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const; - enum {ArgumentCount = 6, IsPointerToMemberFunction = true}; - template - static void call(Function f, Obj *o, void **arg) { - (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5]), - *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); - } - }; - - //Static functions - template struct FunctionPointer - { - typedef void Arguments; - typedef Ret (*Function) (); - typedef Ret ReturnType; - enum {ArgumentCount = 0, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { f(), ApplyReturnValue(arg[0]); } - }; - template struct FunctionPointer - { - typedef List Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1); - enum {ArgumentCount = 1, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) - { f(*reinterpret_cast::Value>::Type *>(arg[1])), ApplyReturnValue(arg[0]); } - }; - template struct FunctionPointer - { - typedef List > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2); - enum {ArgumentCount = 2, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { - f(*reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); } - }; - template struct FunctionPointer - { - typedef List > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3); - enum {ArgumentCount = 3, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef List > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4); - enum {ArgumentCount = 4, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef List > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); - enum {ArgumentCount = 5, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); - } - }; - template struct FunctionPointer - { - typedef List > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); - enum {ArgumentCount = 6, IsPointerToMemberFunction = false}; - template - static void call(Function f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5]), - *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); - } - }; - - //Functors - template struct Functor; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { f(), ApplyReturnValue(arg[0]); } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f(*reinterpret_cast::Value>::Type *>(arg[1])), ApplyReturnValue(arg[0]); - } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); - } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); - } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); - } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); - } - }; - template struct Functor - { - template - static void call(Function &f, void *, void **arg) { - f( *reinterpret_cast::Value>::Type *>(arg[1]), - *reinterpret_cast::Value>::Type *>(arg[2]), - *reinterpret_cast::Value>::Type *>(arg[3]), - *reinterpret_cast::Value>::Type *>(arg[4]), - *reinterpret_cast::Value>::Type *>(arg[5]), - *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); - } - }; -#else template struct IndexesList {}; template struct IndexesAppend; template struct IndexesAppend, Right> @@ -558,7 +192,6 @@ namespace QtPrivate { FunctorCall::Value, SignalArgs, R, Function>::call(f, arg); } }; -#endif /* Logic that check if the arguments of the slot matches the argument of the signal. @@ -578,16 +211,6 @@ namespace QtPrivate { template struct AreArgumentsCompatible { enum { value = true }; }; template<> struct AreArgumentsCompatible { enum { value = true }; }; -#ifndef Q_COMPILER_VARIADIC_TEMPLATES - template struct CheckCompatibleArguments { enum { value = false }; }; - template <> struct CheckCompatibleArguments { enum { value = true }; }; - template struct CheckCompatibleArguments { enum { value = true }; }; - template struct CheckCompatibleArguments, List > - { - enum { value = AreArgumentsCompatible::Type, typename RemoveConstRef::Type>::value - && CheckCompatibleArguments::value }; - }; -#else template struct CheckCompatibleArguments { enum { value = false }; }; template <> struct CheckCompatibleArguments, List<>> { enum { value = true }; }; template struct CheckCompatibleArguments> { enum { value = true }; }; @@ -597,9 +220,7 @@ namespace QtPrivate { enum { value = AreArgumentsCompatible::Type, typename RemoveConstRef::Type>::value && CheckCompatibleArguments, List>::value }; }; -#endif -#if defined(Q_COMPILER_VARIADIC_TEMPLATES) /* Find the maximum number of arguments a functor object can take and be still compatible with the arguments from the signal. @@ -631,8 +252,6 @@ namespace QtPrivate { template static D dummy(); typedef decltype(dummy().operator()((dummy())...)) Value; }; -#endif - } QT_END_NAMESPACE From 3b3ca5deadcc5f414b5ca158f599eb321683aee1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 31 May 2016 11:01:30 -0300 Subject: [PATCH 118/173] tst_QObject: Test if the new connect style works with virtual bases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I87e17314d8b24ae983b1fffd1453abe1e395bbd1 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Jędrzej Nowacki --- .../corelib/kernel/qobject/tst_qobject.cpp | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 1902687eef3..e38dbad7d7a 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -129,6 +129,7 @@ private slots: void returnValue2_data(); void returnValue2(); void connectVirtualSlots(); + void connectSlotsVMIClass(); // VMI = Virtual or Multiple Inheritance void connectPrivateSlots(); void connectFunctorArgDifference(); void connectFunctorOverloads(); @@ -5606,6 +5607,112 @@ void tst_QObject::connectVirtualSlots() */ } +struct VirtualBase +{ + int virtual_base_count; + VirtualBase() : virtual_base_count(0) {} + virtual ~VirtualBase() {} + virtual void slot2() = 0; +}; + +class ObjectWithVirtualBase : public VirtualSlotsObject, public virtual VirtualBase +{ + Q_OBJECT +public: + ObjectWithVirtualBase() : regular_call_count(0), derived_counter2(0) {} + int regular_call_count; + int derived_counter2; + +public slots: + void regularSlot() { ++regular_call_count; } + virtual void slot1() { ++derived_counter2; } + virtual void slot2() { ++virtual_base_count; } +}; + +// VMI = Virtual or Multiple Inheritance +// (in this case, both) +void tst_QObject::connectSlotsVMIClass() +{ + // test connecting by the base + { + ObjectWithVirtualBase obj; + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.virtual_base_count, 0); + + QVERIFY(QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.virtual_base_count, 0); + } + + // test connecting with the actual class + { + ObjectWithVirtualBase obj; + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot, Qt::UniqueConnection)); + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.regular_call_count, 1); + QCOMPARE(obj.virtual_base_count, 0); + + QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot)); + QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.regular_call_count, 1); + QCOMPARE(obj.virtual_base_count, 0); + + /* the C++ standard say the comparison between pointer to virtual member function is unspecified + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); + */ + } + + // test connecting a slot that is virtual from the virtual base + { + ObjectWithVirtualBase obj; + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2, Qt::UniqueConnection)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 0); + QCOMPARE(obj.virtual_base_count, 1); + QCOMPARE(obj.regular_call_count, 0); + + QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 0); + QCOMPARE(obj.virtual_base_count, 1); + QCOMPARE(obj.regular_call_count, 0); + } +} + #ifndef QT_BUILD_INTERNAL void tst_QObject::connectPrivateSlots() {QSKIP("Needs QT_BUILD_INTERNAL");} From 86b612d037da59edf482d8a7d4df5ef97f47fb42 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 2 Jun 2016 14:28:34 +0300 Subject: [PATCH 119/173] QXmlStreamWriter: don't call virtual QTextCodec::name() twice Just cache and reuse result. Change-Id: I2ada2eced7c272c041013d35b59eeb176ed04659 Reviewed-by: Edward Welbourne --- src/corelib/xml/qxmlstream.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 8e628040252..df5f3711ccc 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -3790,7 +3790,8 @@ void QXmlStreamWriter::writeStartDocument(const QString &version) #ifdef QT_NO_TEXTCODEC d->write("iso-8859-1"); #else - d->write(d->codec->name().constData(), d->codec->name().length()); + const QByteArray name = d->codec->name(); + d->write(name.constData(), name.length()); #endif } d->write("\"?>"); @@ -3813,7 +3814,8 @@ void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalon #ifdef QT_NO_TEXTCODEC d->write("iso-8859-1"); #else - d->write(d->codec->name().constData(), d->codec->name().length()); + const QByteArray name = d->codec->name(); + d->write(name.constData(), name.length()); #endif } if (standalone) From 492cfe7002a41d5eb542f467bc8ce4a281dc11c6 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 1 Jun 2016 11:48:08 +0300 Subject: [PATCH 120/173] Android: remove unused plugins These plugins can't be used on Android, but they are built, installed and also bundled into every .apk file. Change-Id: I3326c913282af5bd43e1c732de9ae2f255711414 Reviewed-by: Christian Stromme --- configure | 3 +++ src/plugins/platforms/platforms.pro | 4 ++-- src/plugins/plugins.pro | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/configure b/configure index d175ed32b52..be89b22291a 100755 --- a/configure +++ b/configure @@ -3216,6 +3216,9 @@ if [ "$XPLATFORM_ANDROID" = "yes" ]; then if [ "$CFG_DBUS" = "auto" ]; then CFG_DBUS="no" fi + if [ "$CFG_EGLFS" = "auto" ]; then + CFG_EGLFS="no" + fi if [ -z "$CFG_DEFAULT_ANDROID_NDK_HOST" ]; then case $PLATFORM in linux-*) diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 43bb04e3184..9b4b6c518a9 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -2,9 +2,9 @@ TEMPLATE = subdirs android:!android-no-sdk: SUBDIRS += android -SUBDIRS += minimal +!android: SUBDIRS += minimal -!win32|contains(QT_CONFIG, freetype):SUBDIRS += offscreen +!android:if(!win32|contains(QT_CONFIG, freetype)): SUBDIRS += offscreen contains(QT_CONFIG, xcb) { SUBDIRS += xcb diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 03b7dc266bb..5e180904c75 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -6,7 +6,7 @@ qtHaveModule(network):!contains(QT_DISABLED_FEATURES, bearermanagement): SUBDIRS qtHaveModule(gui) { SUBDIRS *= platforms platforminputcontexts platformthemes !contains(QT_DISABLED_FEATURES, imageformatplugin): SUBDIRS *= imageformats - !contains(QT_DISABLED_FEATURES, library): SUBDIRS *= generic + !android:!contains(QT_DISABLED_FEATURES, library): SUBDIRS *= generic } qtHaveModule(widgets): SUBDIRS *= styles From 06f7f3fd36f0faec3f7fda559af3bea66d4df47e Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 27 May 2016 17:28:26 +0200 Subject: [PATCH 121/173] Doc: Describe QMAKE_EXTENSION_STATICLIB in qmake Manual Task-number: QTBUG-44176 Change-Id: I6f7ad50793b05585ba661cbe187d7619a36cafe5 Reviewed-by: Tim Jenssen Reviewed-by: Oswald Buddenhagen --- qmake/doc/src/qmake-manual.qdoc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index e59b0ddcbe4..9cd4ab98aa5 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -1616,6 +1616,13 @@ \note Platform-specific variables that change the extension override the contents of this variable. + \target QMAKE_EXTENSION_STATICLIB + \section1 QMAKE_EXTENSION_STATICLIB + + Contains the extension for shared static libraries. The value of + this variable is typically handled by qmake or + \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. + \section1 QMAKE_EXT_MOC Contains the extension used on included moc files. From 0a8d3f914c54b057b59942a25d1b76b82e1fa64d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 2 Jun 2016 13:00:57 +0200 Subject: [PATCH 122/173] evdev: Stop reading on ENODEV Touch does this correctly for some time already. Keyboard and mouse do not, leading to flooding the console with the Could not read from ... warning for ever when using the 'static' device discovery (no libudev) and unplugging a mouse or keyboard. Change-Id: I6bef44fbed4bc21cc2736b28d1166bf2b7d90edc Reviewed-by: Andy Nichols --- .../input/evdevkeyboard/qevdevkeyboardhandler.cpp | 15 +++++++++++---- .../input/evdevkeyboard/qevdevkeyboardhandler_p.h | 3 +++ .../input/evdevmouse/qevdevmousehandler.cpp | 13 ++++++++++--- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp index 06751de0ef7..089cc130327 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp @@ -53,7 +53,7 @@ Q_LOGGING_CATEGORY(qLcEvdevKeyMap, "qt.qpa.input.keymap") #include "qevdevkeyboard_defaultmap_p.h" QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool disableZap, bool enableCompose, const QString &keymapFile) - : m_device(device), m_fd(fd), + : m_device(device), m_fd(fd), m_notify(Q_NULLPTR), m_modifiers(0), m_composing(0), m_dead_unicode(0xffff), m_no_zap(disableZap), m_do_compose(enableCompose), m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0) @@ -68,9 +68,8 @@ QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool unloadKeymap(); // socket notifier for events on the keyboard device - QSocketNotifier *notifier; - notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); - connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode())); + m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(m_notify, SIGNAL(activated(int)), this, SLOT(readKeycode())); } QEvdevKeyboardHandler::~QEvdevKeyboardHandler() @@ -155,6 +154,14 @@ void QEvdevKeyboardHandler::readKeycode() } else if (result < 0) { if (errno != EINTR && errno != EAGAIN) { qErrnoWarning(errno, "evdevkeyboard: Could not read from input device"); + // If the device got disconnected, stop reading, otherwise we get flooded + // by the above error over and over again. + if (errno == ENODEV) { + delete m_notify; + m_notify = Q_NULLPTR; + qt_safe_close(m_fd); + m_fd = -1; + } return; } } else { diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h index 90142c68379..84c251c3c2b 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h @@ -51,6 +51,8 @@ QT_BEGIN_NAMESPACE +class QSocketNotifier; + namespace QEvdevKeyboardMap { const quint32 FileMagic = 0x514d4150; // 'QMAP' @@ -180,6 +182,7 @@ private: QString m_device; int m_fd; + QSocketNotifier *m_notify; // keymap handling quint8 m_modifiers; diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp index 76d8aab8f26..23bf0b3c30c 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp @@ -105,9 +105,8 @@ QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool abs, m_abs = getHardwareMaximum(); // socket notifier for events on the mouse device - QSocketNotifier *notifier; - notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); - connect(notifier, SIGNAL(activated(int)), this, SLOT(readMouseData())); + m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData())); } QEvdevMouseHandler::~QEvdevMouseHandler() @@ -196,6 +195,14 @@ void QEvdevMouseHandler::readMouseData() } else if (result < 0) { if (errno != EINTR && errno != EAGAIN) { qErrnoWarning(errno, "evdevmouse: Could not read from input device"); + // If the device got disconnected, stop reading, otherwise we get flooded + // by the above error over and over again. + if (errno == ENODEV) { + delete m_notify; + m_notify = Q_NULLPTR; + qt_safe_close(m_fd); + m_fd = -1; + } return; } } else { From c2d4c3588c8b0f65923c1b3dd98826a99c589495 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 2 Jun 2016 16:03:02 +0200 Subject: [PATCH 123/173] Doc: Fix examples install path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The example directory name for Qt Test module is qtestlib. Without this change, Qt Creator cannot find the tutorial files and tags them "broken" in the Welcome mode. Change-Id: Ib2de0cd2263aa1651abb697f9f03ecd8eb871ca2 Reviewed-by: Topi Reiniö --- src/testlib/doc/qttestlib.qdocconf | 2 +- src/testlib/doc/src/qttestlib-manual.qdoc | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf index 0fafc733b18..899f94ec534 100644 --- a/src/testlib/doc/qttestlib.qdocconf +++ b/src/testlib/doc/qttestlib.qdocconf @@ -4,7 +4,7 @@ project = QtTestLib description = Qt Test Reference Documentation version = $QT_VERSION -examplesinstallpath = testlib +examplesinstallpath = qtestlib qhp.projects = QtTestLib diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc index 82651d5cbaa..781eec05604 100644 --- a/src/testlib/doc/src/qttestlib-manual.qdoc +++ b/src/testlib/doc/src/qttestlib-manual.qdoc @@ -484,6 +484,7 @@ \nextpage {Chapter 2: Data Driven Testing}{Chapter 2} \title Chapter 1: Writing a Unit Test + \brief How to write a unit test. In this first chapter we will see how to write a simple unit test for a class, and how to execute it. @@ -559,6 +560,7 @@ \nextpage {Chapter 3: Simulating Gui Events}{Chapter 3} \title Chapter 2: Data Driven Testing + \brief How to create data driven tests. In this chapter we will demonstrate how to execute a test multiple times with different test data. @@ -664,6 +666,7 @@ \nextpage {Chapter 4: Replaying GUI Events}{Chapter 4} \title Chapter 3: Simulating GUI Events + \brief Howe to simulate GUI events. Qt Test features some mechanisms to test graphical user interfaces. Instead of simulating native window system events, @@ -724,6 +727,7 @@ \nextpage {Chapter 5: Writing a Benchmark}{Chapter 5} \title Chapter 4: Replaying GUI Events + \brief How to replay GUI events. In this chapter, we will show how to simulate a GUI event, and how to store a series of GUI events as well as replay them on @@ -803,6 +807,7 @@ \contentspage {Qt Test Tutorial}{Contents} \title Chapter 5: Writing a Benchmark + \brief How to write a benchmark. In this final chapter we will demonstrate how to write benchmarks using Qt Test. From 9c01fdb2badd0cbc5369cc31b6626718e5b4c23c Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 2 Jun 2016 11:12:29 +0200 Subject: [PATCH 124/173] winrt: Fix compilation for 10586 SDK The current implementation of drag and drop requires Redstone 2 Update (SDK version 14322) to be fully functional. The API is limited for previous versions. However, this mostly affects passing allowed operations between sender and receiver, the rest is mostly functional still. Once RedStone 2 is out (estimated July 2016) we can bump the minimum SDK version to 14322. Task-number: QTBUG-50827 Change-Id: I5bab9d36a228d68c1809c241a64168d48c353335 Reviewed-by: Simon Hausmann Reviewed-by: Friedemann Kleint Reviewed-by: Liang Qi Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtdrag.cpp | 7 ++++++- src/plugins/platforms/winrt/winrt.pro | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp index 14bea7ab30d..2ef50aa4e20 100644 --- a/src/plugins/platforms/winrt/qwinrtdrag.cpp +++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp @@ -623,6 +623,7 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag) hr = dataPackage->put_RequestedOperation(translateFromQDragDropActions(action)); Q_ASSERT_SUCCEEDED(hr); +#ifndef QT_WINRT_LIMITED_DRAGANDDROP ComPtr args2; hr = args->QueryInterface(IID_PPV_ARGS(&args2)); Q_ASSERT_SUCCEEDED(hr); @@ -637,7 +638,7 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag) allowedOperations |= DataPackageOperation_Link; hr = args2->put_AllowedOperations(allowedOperations); Q_ASSERT_SUCCEEDED(hr); - +#endif // QT_WINRT_LIMITED_DRAGANDDROP QMimeData *mimeData = drag->mimeData(); if (mimeData->hasText()) { hr = dataPackage->SetText(qStringToHString(mimeData->text()).Get()); @@ -811,6 +812,7 @@ void QWinRTDrag::handleNativeDragEvent(IInspectable *sender, ABI::Windows::UI::X DragDropModifiers modifiers; hr = e2->get_Modifiers(&modifiers); +#ifndef QT_WINRT_LIMITED_DRAGANDDROP ComPtr e3; hr = e->QueryInterface(IID_PPV_ARGS(&e3)); Q_ASSERT_SUCCEEDED(hr); @@ -821,6 +823,9 @@ void QWinRTDrag::handleNativeDragEvent(IInspectable *sender, ABI::Windows::UI::X qCDebug(lcQpaMime) << __FUNCTION__ << "Could not query drag operations"; const Qt::DropActions actions = translateToQDragDropActions(dataOp); +#else // !QT_WINRT_LIMITED_DRAGANDDROP + const Qt::DropActions actions = Qt::LinkAction | Qt::CopyAction | Qt::MoveAction;; +#endif // !QT_WINRT_LIMITED_DRAGANDDROP ComPtr dataView; hr = e2->get_DataView(&dataView); diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index dd1e051c332..f5591934f5a 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -49,6 +49,10 @@ HEADERS = \ OTHER_FILES += winrt.json +WINRT_SDK_VERSION_STRING = $$(UCRTVersion) +WINRT_SDK_VERSION = $$member($$list($$split(WINRT_SDK_VERSION_STRING, .)), 2) +lessThan(WINRT_SDK_VERSION, 14322): DEFINES += QT_WINRT_LIMITED_DRAGANDDROP + *-msvc2013|contains(DEFINES, QT_NO_DRAGANDDROP) { SOURCES -= qwinrtdrag.cpp HEADERS -= qwinrtdrag.h From 4fc797147821b4ef3372d4db9253d3cb1ed0704e Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Thu, 2 Jun 2016 13:46:52 +0200 Subject: [PATCH 125/173] NetBSD/OpenBSD: Compile fix and proper detection of pipe2 Add the necessary defines for HAVE_PIPE2 for NetBSD and OpenBSD depending on OS version when pipe2(2) was added. This also fixes the compile error on NetBSD if -Werror=unused-function for ignore_sigpipe() as the HAVE_PIPE2 tree is prior to O_NOSIGPIPE in create_pipe(). Change-Id: Ic8f875e34ef826a7bf046c77588afecaa097deca Reviewed-by: Thiago Macieira --- src/3rdparty/forkfd/forkfd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index 9284a67674a..7d2115abb6d 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -30,6 +30,9 @@ #include "forkfd.h" #include +#if defined(__OpenBSD__) || defined(__NetBSD__) +# include +#endif #include #include #include @@ -65,7 +68,9 @@ # undef HAVE_WAITID #endif -#if defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version >= 1000032 +#if (defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version >= 1000032) || \ + (defined(__OpenBSD__) && OpenBSD >= 201505) || \ + (defined(__NetBSD__) && __NetBSD_Version__ >= 600000000) # define HAVE_PIPE2 1 #endif #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || \ From 8c7d6b94d5e1e28c0352c5ae6ac52d4d1ea9b681 Mon Sep 17 00:00:00 2001 From: "Richard J. Moore" Date: Tue, 31 May 2016 17:10:07 +0100 Subject: [PATCH 126/173] Detect if the 'openssl' is really libressl at configure time. Qt does not support libressl which reports itself as openssl but uses a high version number. This means that we expect it to have features that it doesn't and will fail to build. Instead detect this situation at configure time and disable the ssl support. Change-Id: I73cca4d1544df2aaca0723c38ba63758c287ec41 Reviewed-by: Ralf Nolden Reviewed-by: Timur Pocheptsov Reviewed-by: Oswald Buddenhagen --- config.tests/unix/openssl/openssl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config.tests/unix/openssl/openssl.cpp b/config.tests/unix/openssl/openssl.cpp index 6282bfa3285..d0b6cca5625 100644 --- a/config.tests/unix/openssl/openssl.cpp +++ b/config.tests/unix/openssl/openssl.cpp @@ -37,6 +37,12 @@ # error "OpenSSL >= 0.9.7 is required" #endif +#include + +#if OPENSSL_VERSION_NUMBER-0 >= 0x10002000L && !defined(OPENSSL_NO_EC) && !defined(SSL_CTRL_SET_CURVES) +# error "OpenSSL was reported as >= 1.0.2 but is missing required features, possibly it's libressl which is unsupported" +#endif + int main() { } From 372e3c8592f80358942ddc1cadb2b76bb401ab56 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 2 Jun 2016 14:29:57 +0200 Subject: [PATCH 127/173] WinRT: Early return in case of network error Change-Id: I7c410732f41b86f39b41fd1dccd07815e5ca4e45 Reviewed-by: Maurice Kalinowski --- src/network/socket/qnativesocketengine_winrt.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 7077fefa65a..03c9327958a 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -1224,21 +1224,21 @@ void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *actio case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); socketState = QAbstractSocket::UnconnectedState; - break; + return; case 0x80072751: // A socket operation was attempted to an unreachable host. setError(QAbstractSocket::HostNotFoundError, HostUnreachableErrorString); socketState = QAbstractSocket::UnconnectedState; - break; + return; case 0x8007274d: // No connection could be made because the target machine actively refused it. setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); socketState = QAbstractSocket::UnconnectedState; - break; + return; default: if (FAILED(hr)) { setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString); socketState = QAbstractSocket::UnconnectedState; + return; } - break; } // The callback might be triggered several times if we do not cancel/reset it here From 265d91da0dfa1712823ea38c28af1326a0368f6f Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 2 Jun 2016 14:34:28 +0200 Subject: [PATCH 128/173] WinRT: Rename connectToHost/handleConnectionEstablished The two functions are merged and also renamed. handleConnectionEstablished indicates that the operation succeeded, but that is not necessarily the case. Change-Id: I66a4181a5693353fc9507785a6e6bbb8d5300a4b Reviewed-by: Maurice Kalinowski --- .../socket/qnativesocketengine_winrt.cpp | 25 ++++++++----------- .../socket/qnativesocketengine_winrt_p.h | 3 +-- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 03c9327958a..3a4ef4b4001 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -331,7 +331,7 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) d->socketState = QAbstractSocket::ConnectingState; hr = QEventDispatcherWinRT::runOnXamlThread([d]() { return d->connectOp->put_Completed(Callback( - d, &QNativeSocketEnginePrivate::handleConnectToHost).Get()); + d, &QNativeSocketEnginePrivate::handleConnectOpFinished).Get()); }); Q_ASSERT_SUCCEEDED(hr); @@ -755,7 +755,7 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut) if (d->socketState == QAbstractSocket::ConnectingState) { HRESULT hr = QWinRTFunctions::await(d->connectOp, QWinRTFunctions::ProcessMainThreadEvents); if (SUCCEEDED(hr)) { - d->handleConnectionEstablished(d->connectOp.Get()); + d->handleConnectOpFinished(d->connectOp.Get(), Completed); return true; } } @@ -1207,37 +1207,31 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener return S_OK; } -HRESULT QNativeSocketEnginePrivate::handleConnectToHost(IAsyncAction *action, AsyncStatus) -{ - handleConnectionEstablished(action); - return S_OK; -} - -void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *action) +HRESULT QNativeSocketEnginePrivate::handleConnectOpFinished(IAsyncAction *action, AsyncStatus) { Q_Q(QNativeSocketEngine); if (wasDeleted || !connectOp) // Protect against a late callback - return; + return S_OK; HRESULT hr = action->GetResults(); switch (hr) { case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); socketState = QAbstractSocket::UnconnectedState; - return; + return S_OK; case 0x80072751: // A socket operation was attempted to an unreachable host. setError(QAbstractSocket::HostNotFoundError, HostUnreachableErrorString); socketState = QAbstractSocket::UnconnectedState; - return; + return S_OK; case 0x8007274d: // No connection could be made because the target machine actively refused it. setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); socketState = QAbstractSocket::UnconnectedState; - return; + return S_OK; default: if (FAILED(hr)) { setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString); socketState = QAbstractSocket::UnconnectedState; - return; + return S_OK; } } @@ -1260,13 +1254,14 @@ void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *actio emit q->connectionReady(); if (socketType != QAbstractSocket::TcpSocket) - return; + return S_OK; // Delay the reader so that the SSL socket can upgrade if (sslSocket) QObject::connect(qobject_cast(sslSocket), &QSslSocket::encrypted, q, &QNativeSocketEngine::establishRead); else q->establishRead(); + return S_OK; } HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index 2c1c42ecbca..c1fbcf70fa6 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -214,8 +214,7 @@ private: ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args); HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); - HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); - void handleConnectionEstablished(ABI::Windows::Foundation::IAsyncAction *action); + HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress *asyncInfo, ABI::Windows::Foundation::AsyncStatus); }; From 22667483e1da3da2de5def9a1ee8aa6b22ee50d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 3 Jun 2016 12:37:20 +0200 Subject: [PATCH 129/173] Blacklist modalDialogClosingOneOfTwoModal on OS X Passes locally (on 10.10), but seems to have become unstable on the CI system. Task-number: QTBUG-53790 Change-Id: I0432fca4121b97bcdd6cec529fc4e148dfb8c1ab Reviewed-by: Timur Pocheptsov --- tests/auto/gui/kernel/qwindow/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index a34066dd7ce..427d63b845d 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -6,3 +6,5 @@ ubuntu-14.04 ubuntu-14.04 [modalWindowEnterEventOnHide_QTBUG35109] ubuntu-14.04 +[modalDialogClosingOneOfTwoModal] +osx From cf19b06f221430db7eba00e792237abe14df4a3d Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 18 Mar 2016 16:50:28 -0700 Subject: [PATCH 130/173] Cocoa QPA: Mute mouse dragging warnings While probably valid, these warnings are beyond the user's control, and more likely a sign of Qt's own expectations or misbehavior. So, we should not annoy the users with them. This change introduces the same logging category as 3ee01f74031d9e1d0 in 5.7 as is a partial backport to simplify a subsequent 5.6 to 5.7 merge. Change-Id: Ica2e3b1c5bc372923fd823b5d7d537d319835685 Task-number: QTBUG-42846 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoahelpers.h | 2 ++ src/plugins/platforms/cocoa/qcocoahelpers.mm | 2 ++ src/plugins/platforms/cocoa/qnsview.mm | 6 +++--- src/plugins/platforms/cocoa/qt_mac_p.h | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 89f8bc2f6a7..c2abe4e2457 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaCocoaWindow) + class QPixmap; class QString; diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 29a204d5796..58d29611117 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaCocoaWindow, "qt.qpa.cocoa.window"); + // // Conversion Functions // diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 4009c13ad5c..4e482fb146a 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -880,7 +880,7 @@ QT_WARNING_POP if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) return [super mouseDragged:theEvent]; if (!(m_buttons & (m_sendUpAsRightButton ? Qt::RightButton : Qt::LeftButton))) - qWarning("QNSView mouseDragged: Internal mouse button tracking invalid (missing Qt::LeftButton)"); + qCDebug(lcQpaCocoaWindow, "QNSView mouseDragged: Internal mouse button tracking invalid (missing Qt::LeftButton)"); [self handleMouseEvent:theEvent]; } @@ -1019,7 +1019,7 @@ QT_WARNING_POP if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) return [super rightMouseDragged:theEvent]; if (!(m_buttons & Qt::RightButton)) - qWarning("QNSView rightMouseDragged: Internal mouse button tracking invalid (missing Qt::RightButton)"); + qCDebug(lcQpaCocoaWindow, "QNSView rightMouseDragged: Internal mouse button tracking invalid (missing Qt::RightButton)"); [self handleMouseEvent:theEvent]; } @@ -1045,7 +1045,7 @@ QT_WARNING_POP if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) ) return [super otherMouseDragged:theEvent]; if (!(m_buttons & ~(Qt::LeftButton | Qt::RightButton))) - qWarning("QNSView otherMouseDragged: Internal mouse button tracking invalid (missing Qt::MiddleButton or Qt::ExtraButton*)"); + qCDebug(lcQpaCocoaWindow, "QNSView otherMouseDragged: Internal mouse button tracking invalid (missing Qt::MiddleButton or Qt::ExtraButton*)"); [self handleMouseEvent:theEvent]; } diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h index 576e0f97290..299678eee86 100644 --- a/src/plugins/platforms/cocoa/qt_mac_p.h +++ b/src/plugins/platforms/cocoa/qt_mac_p.h @@ -58,6 +58,7 @@ #include "QtCore/qvariant.h" #include "QtCore/qmimedata.h" #include "QtCore/qpointer.h" +#include "QtCore/qloggingcategory.h" #include "private/qcore_mac_p.h" From 23bed9f8203bb6d475622c02ea9a96efdea78108 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 1 Jun 2016 11:07:22 +0200 Subject: [PATCH 131/173] Remove tst_QWidget::immediateRepaintAfterShow(). It tested whether a paint event was received when calling QWidget::repaint() right after QWidget::show() without waiting for the window to be exposed. This caused a QEvent::UpdateRequest to be sent, which ended up in QWidgetBackingStore::sync() which returns after checking QWidgetBackingStore::discardSyncRequest(), since Qt::WA_Mapped is not set on the non-exposed widget. The test passed on Windows since it contains one call to QCoreApplication::processEvents() which causes the the initial WM_PAINT message to be processed in QWindowsWindow::handleWmPaint() which calls QWindowSystemInterface::flushWindowSystemEvents() and causes Qt::WA_Mapped to be set. This seems counter to the intention of the test. Remove the test since it won't pass anymore in Qt 5 unless Qt::WA_Mapped is set. Task-number: QTBUG-26424 Task-number: QTBUG-38327 Task-number: QTBUG-39842 Change-Id: Iede026d52825dcf1f2e9014a316d26d260309214 Reviewed-by: Joerg Bornemann --- .../widgets/kernel/qwidget/tst_qwidget.cpp | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 10d32472be3..b7c152603cc 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -378,7 +378,6 @@ private slots: void setMaskInResizeEvent(); void moveInResizeEvent(); - void immediateRepaintAfterShow(); void immediateRepaintAfterInvalidateBuffer(); void effectiveWinId(); @@ -8145,25 +8144,6 @@ void tst_QWidget::moveInResizeEvent() QTRY_COMPARE(testWidget.geometry(), expectedGeometry); } -void tst_QWidget::immediateRepaintAfterShow() -{ - if (m_platform == QStringLiteral("xcb")) - QSKIP("QTBUG-26424"); - if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows")) - QSKIP("We don't support immediate repaint right after show on other platforms."); - - UpdateWidget widget; - centerOnScreen(&widget); - widget.show(); - qApp->processEvents(); - // On X11 in particular, we are now waiting for a MapNotify event before - // syncing the backing store. However, if someone request a repaint() - // we must repaint immediately regardless of the current state. - widget.numPaintEvents = 0; - widget.repaint(); - QCOMPARE(widget.numPaintEvents, 1); -} - void tst_QWidget::immediateRepaintAfterInvalidateBuffer() { if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows")) From 95f1f6f719858bcb2429acee855c82a5e8164b4e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 2 Jun 2016 11:31:23 +0200 Subject: [PATCH 132/173] tst_QTemporaryFile: Run in temporary directory. The test leaks a file (named qt_...xxx) in QDir::tempPath(). Moreover, when tests fail, it can happen that more files are leaked and subsequent runs do not recover since the check for non-existence of those files fails. Change-Id: Iaea6d09ee7c271903a1b9c63e263c19f9e90bba9 Reviewed-by: David Faure --- .../auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp index 6e461cae17e..7b063559900 100644 --- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp +++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -86,13 +87,15 @@ private slots: void QTBUG_4796(); void guaranteeUnique(); private: + QTemporaryDir m_temporaryDir; QString m_previousCurrent; }; void tst_QTemporaryFile::initTestCase() { + QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); m_previousCurrent = QDir::currentPath(); - QDir::setCurrent(QDir::tempPath()); + QVERIFY(QDir::setCurrent(m_temporaryDir.path())); // For QTBUG_4796 QVERIFY(QDir("test-XXXXXX").exists() || QDir().mkdir("test-XXXXXX")); @@ -119,9 +122,6 @@ void tst_QTemporaryFile::initTestCase() void tst_QTemporaryFile::cleanupTestCase() { - // From QTBUG_4796 - QVERIFY(QDir().rmdir("test-XXXXXX")); - QDir::setCurrent(m_previousCurrent); } From fd70978693bd92761e9989bc1c76bf83c1e8c987 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 3 Jun 2016 11:27:39 +0200 Subject: [PATCH 133/173] Diaglib: Extend class information for QWidget dumps. Output the class hierarchy until a base class within QtWidgets is found. Change-Id: I0ecee22e2ead1dea8b39cce8ca2f0739290aac22 Reviewed-by: Alexandru Croitor --- tests/manual/diaglib/qwidgetdump.cpp | 46 ++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/tests/manual/diaglib/qwidgetdump.cpp b/tests/manual/diaglib/qwidgetdump.cpp index e5fdfaeb71d..0795bec37f3 100644 --- a/tests/manual/diaglib/qwidgetdump.cpp +++ b/tests/manual/diaglib/qwidgetdump.cpp @@ -45,11 +45,50 @@ namespace QtDiag { +static const char *qtWidgetClasses[] = { + "QAbstractItemView", "QAbstractScrollArea", "QAbstractSlider", "QAbstractSpinBox", + "QCalendarWidget", "QCheckBox", "QColorDialog", "QColumnView", "QComboBox", + "QCommandLinkButton", "QDateEdit", "QDateTimeEdit", "QDesktopWidget", "QDial", + "QDialog", "QDialogButtonBox", "QDockWidget", "QDoubleSpinBox", "QErrorMessage", + "QFileDialog", "QFontComboBox", "QFontDialog", "QFrame", "QGraphicsView", + "QGroupBox", "QHeaderView", "QInputDialog", "QLCDNumber", "QLabel", "QLineEdit", + "QListView", "QListWidget", "QMainWindow", "QMdiArea", "QMdiSubWindow", "QMenu", + "QMenuBar", "QMessageBox", "QOpenGLWidget", "QPlainTextEdit", "QProgressBar", + "QProgressDialog", "QPushButton", "QRadioButton", "QRubberBand", "QScrollArea", + "QScrollBar", "QSlider", "QSpinBox", "QSplashScreen", "QSplitter", + "QStackedWidget", "QStatusBar", "QTabBar", "QTabWidget", "QTableView", + "QTableWidget", "QTextBrowser", "QTextEdit", "QTimeEdit", "QToolBar", + "QToolBox", "QToolButton", "QTreeView", "QTreeWidget", "QWidget", + "QWizard", "QWizardPage" +}; + +static bool isQtWidget(const char *className) +{ + for (size_t i = 0, count = sizeof(qtWidgetClasses) / sizeof(qtWidgetClasses[0]); i < count; ++i) { + if (!qstrcmp(className, qtWidgetClasses[i])) + return true; + } + return false; +} + +static void formatWidgetClass(QTextStream &str, const QWidget *w) +{ + const QMetaObject *mo = w->metaObject(); + str << mo->className(); + while (!isQtWidget(mo->className())) { + mo = mo->superClass(); + str << ':' << mo->className(); + } + const QString on = w->objectName(); + if (!on.isEmpty()) + str << "/\"" << on << '"'; +} + static void dumpWidgetRecursion(QTextStream &str, const QWidget *w, FormatWindowOptions options, int depth = 0) { indentStream(str, 2 * depth); - formatObject(str, w); + formatWidgetClass(str, w); str << ' ' << (w->isVisible() ? "[visible] " : "[hidden] "); if (const WId nativeWinId = w->internalWinId()) str << "[native: " << hex << showbase << nativeWinId << dec << noshowbase << "] "; @@ -114,7 +153,10 @@ void dumpAllWidgets(FormatWindowOptions options, const QWidget *root) foreach (QWidget *tw, topLevels) dumpWidgetRecursion(str, tw, options); #if QT_VERSION >= 0x050400 - qDebug().noquote() << d; + { + foreach (const QString &line, d.split(QLatin1Char('\n'))) + qDebug().noquote() << line; + } #else qDebug("%s", qPrintable(d)); #endif From d5ac97e36fb35761576f25c84372d5c477189a0f Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 2 Jun 2016 11:22:32 +0200 Subject: [PATCH 134/173] Fix font-weight regression Do not override the requested font-weight. This was a wrong rewrite of a now redundant if-statement. Change-Id: I20a745cac02d896fdeaa853f20c6b6647084fceb Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontdatabase.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index c4b849878c7..7b88a73c61c 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -2730,7 +2730,6 @@ void QFontDatabase::load(const QFontPrivate *d, int script) } if (req.pointSize < 0) req.pointSize = req.pixelSize*72.0/d->dpi; - req.weight = QFont::Normal; if (req.stretch == 0) req.stretch = 100; From dc0ae02ebc8e221f952829230c0301a718a6f10b Mon Sep 17 00:00:00 2001 From: Volker Krause Date: Wed, 1 Jun 2016 20:46:07 +0200 Subject: [PATCH 135/173] CMake: Add imported target for qdoc. Change-Id: Ic950a4171830c83fb44cab13f79e593e5ea1ed52 Reviewed-by: Stephen Kelly --- src/corelib/Qt5CoreConfigExtras.cmake.in | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in index a5ed8b2ea36..f492148a509 100644 --- a/src/corelib/Qt5CoreConfigExtras.cmake.in +++ b/src/corelib/Qt5CoreConfigExtras.cmake.in @@ -46,6 +46,21 @@ if (NOT TARGET Qt5::rcc) ) endif() +if (NOT TARGET Qt5::qdoc) + add_executable(Qt5::qdoc IMPORTED) + +!!IF isEmpty(CMAKE_BIN_DIR_IS_ABSOLUTE) + set(imported_location \"${_qt5Core_install_prefix}/$${CMAKE_BIN_DIR}qdoc$$CMAKE_BIN_SUFFIX\") +!!ELSE + set(imported_location \"$${CMAKE_BIN_DIR}qdoc$$CMAKE_BIN_SUFFIX\") +!!ENDIF + _qt5_Core_check_file_exists(${imported_location}) + + set_target_properties(Qt5::qdoc PROPERTIES + IMPORTED_LOCATION ${imported_location} + ) +endif() + set(Qt5Core_QMAKE_EXECUTABLE Qt5::qmake) set(Qt5Core_MOC_EXECUTABLE Qt5::moc) set(Qt5Core_RCC_EXECUTABLE Qt5::rcc) From f8b5142e3068d210393e7e4544c2e63577a313ac Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 2 Jun 2016 10:46:36 -0300 Subject: [PATCH 136/173] Fix race condition in tst_QDBusConnection::pendingCallWhenDisconnected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test sent a message and hoped that the "delete server" would cause the server object in the QDBusConnectionManager thread be deleted before it could receive and process the message. That's racy, because on some CI machines, it did and then sent back an error reply indicating the object sought was not found. Instead, let's use a child process that we can kill to make it exit at the right time. I've chosen to use dbus-daemon itself, because that lets us test the actual conditions that triggered the original bug: the daemon getting killed during a desktop session shutdown on Linux. Change-Id: I87e17314d8b24ae983b1fffd1454483aea87c921 Reviewed-by: Tony Sarajärvi --- .../qdbusconnection/tst_qdbusconnection.cpp | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index 9b16cf74a55..8dc94d3e073 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -40,6 +40,11 @@ #include #include +#ifdef Q_OS_UNIX +# include +# include +#endif + void MyObject::method(const QDBusMessage &msg) { path = msg.path(); @@ -1357,23 +1362,39 @@ void tst_QDBusConnection::callVirtualObjectLocal() void tst_QDBusConnection::pendingCallWhenDisconnected() { +#ifdef QT_NO_PROCESS + QSKIP("Test requires QProcess"); +#else if (!QCoreApplication::instance()) QSKIP("Test requires a QCoreApplication"); - QDBusServer *server = new QDBusServer; - QDBusConnection con = QDBusConnection::connectToPeer(server->address(), "disconnect"); - QTestEventLoop::instance().enterLoop(2); - QVERIFY(con.isConnected()); - QDBusMessage message = QDBusMessage::createMethodCall("", "/", QString(), "method"); + QProcess daemon; + daemon.start("dbus-daemon", QStringList() << "--session" << "--nofork" << "--print-address"); + QVERIFY2(daemon.waitForReadyRead(2000), + "Daemon didn't print its address in time; error: \"" + daemon.errorString().toLocal8Bit() + + "\"; stderr:\n" + daemon.readAllStandardError()); + + QString address = QString::fromLocal8Bit(daemon.readAll().trimmed()); + QDBusConnection con = QDBusConnection::connectToBus(address, "disconnect"); + QVERIFY2(con.isConnected(), (con.lastError().name() + ": " + con.lastError().message()).toLocal8Bit()); + + // confirm we're connected and we're alone in this bus + QCOMPARE(con.baseService(), QString(":1.0")); + + // kill the bus + daemon.terminate(); + daemon.waitForFinished(); + + // send something, which we should get an error with + QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", QString(), "ListNames"); QDBusPendingCall reply = con.asyncCall(message); - delete server; - - QTestEventLoop::instance().enterLoop(2); + reply.waitForFinished(); QVERIFY(!con.isConnected()); QVERIFY(reply.isFinished()); QVERIFY(reply.isError()); - QVERIFY(reply.error().type() == QDBusError::Disconnected); + QCOMPARE(reply.error().type(), QDBusError::Disconnected); +#endif } QString MyObject::path; From 62091be85ccfc0d967c73b881d9134a75cb939c9 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 25 May 2016 17:20:23 +0200 Subject: [PATCH 137/173] Fix zero-as-null-pointer-constant in wayland compositor api This gets included by Qt Wayland and will cause warnings there. Change-Id: I3bb470d42ace4e6195d33019f81fa72f3006fc7f Reviewed-by: Alex Blasche Reviewed-by: Joerg Bornemann --- src/gui/kernel/qwindowsysteminterface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 20d560f82eb..69c850ad3e9 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -110,7 +110,7 @@ public: static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier); struct TouchPoint { - TouchPoint() : id(0), pressure(0), state(Qt::TouchPointStationary), flags(0) { } + TouchPoint() : id(0), pressure(0), state(Qt::TouchPointStationary) { } int id; // for application use QPointF normalPosition; // touch device coordinates, (0 to 1, 0 to 1) QRectF area; // the touched area, centered at position in screen coordinates @@ -132,7 +132,7 @@ public: // rect is relative to parent static void handleGeometryChange(QWindow *w, const QRect &newRect, const QRect &oldRect = QRect()); - static void handleCloseEvent(QWindow *w, bool *accepted = 0); + static void handleCloseEvent(QWindow *w, bool *accepted = Q_NULLPTR); static void handleEnterEvent(QWindow *w, const QPointF &local = QPointF(), const QPointF& global = QPointF()); static void handleLeaveEvent(QWindow *w); static void handleEnterLeaveEvent(QWindow *enter, QWindow *leave, const QPointF &local = QPointF(), const QPointF& global = QPointF()); From ca434d0c209c692441e775528e657a1ba9c4648d Mon Sep 17 00:00:00 2001 From: Hannah von Reth Date: Fri, 29 Apr 2016 12:42:37 +0200 Subject: [PATCH 138/173] Enable testStyleOptionInit for all styles and fix affected styles. Change-Id: I7cb759445342ecb58d5187ddd4a22e41fdea084a Reviewed-by: Marc Mutz --- src/widgets/styles/qfusionstyle.cpp | 3 +-- src/widgets/styles/qgtkstyle.cpp | 7 ++----- src/widgets/styles/qmacstyle_mac.mm | 4 +--- src/widgets/styles/qwindowscestyle.cpp | 6 ++---- src/widgets/styles/qwindowsmobilestyle.cpp | 13 ++++--------- src/widgets/styles/qwindowsstyle.cpp | 3 +-- src/widgets/styles/qwindowsxpstyle.cpp | 3 +-- tests/auto/widgets/styles/qstyle/tst_qstyle.cpp | 9 +++------ 8 files changed, 15 insertions(+), 33 deletions(-) diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 5978140f6c3..e9e1f349c58 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -2385,8 +2385,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption if (!titleBar->icon.isNull()) { titleBar->icon.paint(painter, iconRect); } else { - QStyleOption tool(0); - tool.palette = titleBar->palette; + QStyleOption tool = *titleBar; QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16); tool.rect = iconRect; painter->save(); diff --git a/src/widgets/styles/qgtkstyle.cpp b/src/widgets/styles/qgtkstyle.cpp index 7ed0dce91de..8597e7c20cc 100644 --- a/src/widgets/styles/qgtkstyle.cpp +++ b/src/widgets/styles/qgtkstyle.cpp @@ -1765,8 +1765,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom if (!titleBar->icon.isNull()) { titleBar->icon.paint(painter, iconRect); } else { - QStyleOption tool(0); - tool.palette = titleBar->palette; + QStyleOption tool = *titleBar; QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16); tool.rect = iconRect; painter->save(); @@ -2071,9 +2070,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom mflags |= State_MouseOver; } - QStyleOption tool(0); - - tool.palette = toolbutton->palette; + QStyleOption tool = *toolbutton; if (toolbutton->subControls & SC_ToolButton) { if (bflags & (State_Sunken | State_On | State_Raised | State_MouseOver)) { diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 9f241b6e67a..18ba2f45f59 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -5978,12 +5978,10 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex #ifndef QT_NO_ACCESSIBILITY if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) { if (tb->subControls & SC_ToolButtonMenu) { - QStyleOption arrowOpt(0); + QStyleOption arrowOpt = *tb; arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2); arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2); - arrowOpt.state = tb->state; - arrowOpt.palette = tb->palette; proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); } else if ((tb->features & QStyleOptionToolButton::HasMenu) && (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) { diff --git a/src/widgets/styles/qwindowscestyle.cpp b/src/widgets/styles/qwindowscestyle.cpp index e26925807ff..4817bfde3e7 100644 --- a/src/widgets/styles/qwindowscestyle.cpp +++ b/src/widgets/styles/qwindowscestyle.cpp @@ -1437,8 +1437,7 @@ void QWindowsCEStyle::drawComplexControl(ComplexControl control, const QStyleOpt if (toolbutton->activeSubControls & SC_ToolButtonMenu) mflags |= State_Sunken; - QStyleOption tool(0); - tool.palette = toolbutton->palette; + QStyleOption tool = *toolbutton; if (toolbutton->subControls & SC_ToolButton) { tool.rect = button; tool.state = bflags; @@ -1620,9 +1619,8 @@ void QWindowsCEStyle::drawComplexControl(ComplexControl control, const QStyleOpt if (cmb->activeSubControls == SC_ComboBoxArrow) flags |= State_Sunken; - QStyleOption arrowOpt(0); + QStyleOption arrowOpt = *cmb; arrowOpt.rect = ar; - arrowOpt.palette = cmb->palette; arrowOpt.state = flags; drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget); } diff --git a/src/widgets/styles/qwindowsmobilestyle.cpp b/src/widgets/styles/qwindowsmobilestyle.cpp index e34c2dfe00a..b91e647c4b1 100644 --- a/src/widgets/styles/qwindowsmobilestyle.cpp +++ b/src/widgets/styles/qwindowsmobilestyle.cpp @@ -6105,8 +6105,7 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl buttonFlags |= State_Sunken; if (toolbutton->activeSubControls & SC_ToolButtonMenu) menuFlags |= State_On; - QStyleOption tool(0); - tool.palette = toolbutton->palette; + QStyleOption tool = *toolbutton; if (toolbutton->subControls & SC_ToolButton) { tool.rect = button; tool.state = buttonFlags; @@ -6115,14 +6114,11 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl if (toolbutton->subControls & SC_ToolButtonMenu) { tool.rect = menuarea; tool.state = buttonFlags & State_Enabled; - QStyleOption toolMenu(0); - toolMenu = *toolbutton; + QStyleOption toolMenu = *toolbutton; toolMenu.state = menuFlags; if (buttonFlags & State_Sunken) proxy()->drawPrimitive(PE_PanelButtonTool, &toolMenu, painter, widget); - QStyleOption arrowOpt(0); - arrowOpt.rect = tool.rect; - arrowOpt.palette = tool.palette; + QStyleOption arrowOpt = toolMenu; State flags = State_None; if (menuFlags & State_Enabled) flags |= State_Enabled; @@ -6244,9 +6240,8 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl flags |= State_Enabled; if (option->state & State_On) flags |= State_Sunken; - QStyleOption arrowOpt(0); + QStyleOption arrowOpt = *cmb; arrowOpt.rect = ar; - arrowOpt.palette = cmb->palette; arrowOpt.state = flags; proxy()->drawPrimitive(PrimitiveElement(PE_IndicatorArrowDownBig), &arrowOpt, painter, widget); if (cmb->subControls & SC_ComboBoxEditField) { diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index ab3c8df2569..536ef2d49a7 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -2164,9 +2164,8 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp if (sunkenArrow) flags |= State_Sunken; - QStyleOption arrowOpt(0); + QStyleOption arrowOpt = *cmb; arrowOpt.rect = ar.adjusted(1, 1, -1, -1); - arrowOpt.palette = cmb->palette; arrowOpt.state = flags; proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); } diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index e9415f42922..a850787af04 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -3044,8 +3044,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } } - QStyleOption tool(0); - tool.palette = toolbutton->palette; + QStyleOption tool = *toolbutton; if (toolbutton->subControls & SC_ToolButton) { if (flags & (State_Sunken | State_On | State_Raised) || !autoRaise) { if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup && autoRaise) { diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp index 46b6fcca821..361a7e7ed49 100644 --- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp +++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp @@ -949,17 +949,14 @@ private: void tst_QStyle::testStyleOptionInit() { QStringList keys = QStyleFactory::keys(); - QVector styles; - styles.reserve(keys.size() + 1); + keys.prepend(QString()); // QCommonStyle marker - styles << new QCommonStyle(); - - Q_FOREACH (QStyle *style, styles) { + Q_FOREACH (const QString &key, keys) { + QStyle* style = key.isEmpty() ? new QCommonStyle : QStyleFactory::create(key); TestStyleOptionInitProxy testStyle; testStyle.setBaseStyle(style); testAllFunctions(style); QVERIFY(!testStyle.invalidOptionsDetected); - delete style; } } From cd21da392216f7af6680695dd1b02e6397b72cb3 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 6 Jun 2016 14:59:14 -0700 Subject: [PATCH 139/173] examples/corelib/mimetypebrowser: Fix no-widgets build Change-Id: Iea8cbc791bc2bb990c4d550c890ccd5f5ca17bd6 Reviewed-by: Friedemann Kleint --- examples/corelib/mimetypes/mimetypes.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/corelib/mimetypes/mimetypes.pro b/examples/corelib/mimetypes/mimetypes.pro index 5eaa816871d..6c7e0eab13e 100644 --- a/examples/corelib/mimetypes/mimetypes.pro +++ b/examples/corelib/mimetypes/mimetypes.pro @@ -1,3 +1,4 @@ TEMPLATE = subdirs -SUBDIRS = mimetypebrowser +qtHaveModule(widgets): SUBDIRS += \ + mimetypebrowser From 15a76e571926b94de74caa536975327949a14fd7 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Wed, 4 May 2016 19:46:50 +0200 Subject: [PATCH 140/173] QLineEdit: move to the beginning when receiving a MoveToStartOfLine The code dealing with shortcut overrides omitted this value from the checks. If the user had a shortcut installed with a key sequence matching MoveToStartOfLine, then that would result in the line edit not moving the cursor at the beginning of the line (unlike other similar sequences). Change-Id: If2e780068b3139390c79285d2205cc89285ba8b5 Task-number: QTBUG-52796 Reviewed-by: Friedemann Kleint Reviewed-by: Alex Blasche --- src/widgets/widgets/qwidgetlinecontrol.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index 918b6e8c816..daf9f00c464 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -1533,6 +1533,7 @@ void QWidgetLineControl::processShortcutOverrideEvent(QKeyEvent *ke) || ke == QKeySequence::Undo || ke == QKeySequence::MoveToNextWord || ke == QKeySequence::MoveToPreviousWord + || ke == QKeySequence::MoveToStartOfLine || ke == QKeySequence::MoveToEndOfLine || ke == QKeySequence::MoveToStartOfDocument || ke == QKeySequence::MoveToEndOfDocument From ae0a2fe0410a9574c51d278f8993adaad4f06a33 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 6 Jun 2016 16:17:57 +0200 Subject: [PATCH 141/173] Rewrite test tst_QDir::cdBelowRoot() to be data-driven. Limit the macro #ifdefery and allow for more test cases. Task-number: QTBUG-53712 Change-Id: I2c185efc7c3b8fcd0217d2021bd98ab6044b5aee Reviewed-by: Joerg Bornemann --- tests/auto/corelib/io/qdir/tst_qdir.cpp | 63 ++++++++++++++----------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index ad496782458..90c5a4d9078 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -213,6 +213,7 @@ private slots: void cdNonreadable(); + void cdBelowRoot_data(); void cdBelowRoot(); private: @@ -2264,31 +2265,37 @@ void tst_QDir::cdNonreadable() #endif } +void tst_QDir::cdBelowRoot_data() +{ + QTest::addColumn("rootPath"); + QTest::addColumn("cdInto"); + QTest::addColumn("targetPath"); + +#if defined(Q_OS_ANDROID) + QTest::newRow("android") << "/" << "system" << "/system"; +#elif defined(Q_OS_UNIX) + QTest::newRow("unix") << "/" << "tmp" << "/tmp"; +#elif defined(Q_OS_WINRT) + QTest::newRow("winrt") << QDir::rootPath() << QDir::rootPath() << QDir::rootPath(); +#else // Windows+CE + const QString systemDrive = QString::fromLocal8Bit(qgetenv("SystemDrive")) + QLatin1Char('/'); + const QString systemRoot = QString::fromLocal8Bit(qgetenv("SystemRoot")); + QTest::newRow("windows-drive") + << systemDrive << systemRoot.mid(3) << QDir::cleanPath(systemRoot); +#endif // Windows +} + void tst_QDir::cdBelowRoot() { -#if defined (Q_OS_ANDROID) -#define ROOT QString("/") -#define DIR QString("/system") -#define CD_INTO "system" -#elif defined (Q_OS_UNIX) -#define ROOT QString("/") -#define DIR QString("/tmp") -#define CD_INTO "tmp" -#elif defined (Q_OS_WINRT) -#define ROOT QDir::rootPath() -#define DIR QDir::rootPath() -#define CD_INTO QDir::rootPath() -#else -#define ROOT QString::fromLocal8Bit(qgetenv("SystemDrive"))+"/" -#define DIR QString::fromLocal8Bit(qgetenv("SystemRoot")).replace('\\', '/') -#define CD_INTO QString::fromLocal8Bit(qgetenv("SystemRoot")).mid(3) -#endif + QFETCH(QString, rootPath); + QFETCH(QString, cdInto); + QFETCH(QString, targetPath); - QDir root(ROOT); - QVERIFY(!root.cd("..")); - QCOMPARE(root.path(), ROOT); - QVERIFY(root.cd(CD_INTO)); - QCOMPARE(root.path(), DIR); + QDir root(rootPath); + QVERIFY2(!root.cd(".."), qPrintable(root.absolutePath())); + QCOMPARE(root.path(), rootPath); + QVERIFY(root.cd(cdInto)); + QCOMPARE(root.path(), targetPath); #ifdef Q_OS_UNIX if (::getuid() == 0) QSKIP("Running this test as root doesn't make sense"); @@ -2296,13 +2303,13 @@ void tst_QDir::cdBelowRoot() #ifdef Q_OS_WINRT QSKIP("WinRT has no concept of system root"); #endif - QDir dir(DIR); - QVERIFY(!dir.cd("../..")); - QCOMPARE(dir.path(), DIR); - QVERIFY(!dir.cd("../abs/../..")); - QCOMPARE(dir.path(), DIR); + QDir dir(targetPath); + QVERIFY2(!dir.cd("../.."), qPrintable(dir.absolutePath())); + QCOMPARE(dir.path(), targetPath); + QVERIFY2(!dir.cd("../abs/../.."), qPrintable(dir.absolutePath())); + QCOMPARE(dir.path(), targetPath); QVERIFY(dir.cd("..")); - QCOMPARE(dir.path(), ROOT); + QCOMPARE(dir.path(), rootPath); } QTEST_MAIN(tst_QDir) From df3f685826d0baf8b68e9a01ee44749abbac8ecf Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 7 Jun 2016 11:18:00 +0200 Subject: [PATCH 142/173] tst_QFileSystemModel: Remove Win32LongFileName(). Modern SSD drives no longer have short file names enabled, causing the test to fail. Task-number: QTBUG-29403 Change-Id: I2e9866d8f8a6ed3df9d2dc6630b8cfa47ade0728 Reviewed-by: Joerg Bornemann --- .../qfilesystemmodel/tst_qfilesystemmodel.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index b27943f071c..af92f0735d2 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -109,10 +109,6 @@ private slots: void caseSensitivity(); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - void Win32LongFileName(); -#endif - void drives_data(); void drives(); void dirsBeforeFiles(); @@ -932,20 +928,6 @@ void tst_QFileSystemModel::caseSensitivity() } } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) -void tst_QFileSystemModel::Win32LongFileName() -{ - QString tmp = flatDirTestPath; - QStringList files; - files << "aaaaaaaaaa" << "bbbbbbbbbb" << "cccccccccc"; - QVERIFY(createFiles(tmp, files)); - QModelIndex root = model->setRootPath(tmp); - QTRY_VERIFY(model->index(tmp + QLatin1String("/aaaaaa~1")).isValid()); - QTRY_VERIFY(model->index(tmp + QLatin1String("/bbbbbb~1")).isValid()); - QTRY_VERIFY(model->index(tmp + QLatin1String("/cccccc~1")).isValid()); -} -#endif - void tst_QFileSystemModel::drives_data() { QTest::addColumn("path"); From 8339b557e48c17104c0ef2214130c2c0ade068b2 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 7 Jun 2016 15:00:46 +0200 Subject: [PATCH 143/173] NetBSD: simplify mkspec and match supported OS versions (6.x-7.x) By using common/gcc-base-unix.conf and common/g++-unix.conf most of the mkspec details can go, leaving us with a minimized qmake.conf. Change the default X11 location to point to /usr/X11R7 after NetBSD switched to X.org in Release 5.0 by default. Also change the default location for addon software on NetBSD, it uses pkgsrc as its ports system which installs to /usr/pkg by default (the default value for $LOCALBASE of pkgsrc on NetBSD), see https://www.netbsd.org/docs/pkgsrc/using.html chapter 4.1. These default values mirror the current state of NetBSD usage to get the prerequisites to compile Qt with a minimum amount of configure parameters. Tested with NetBSD 7.0 using gcc 4.8.4-nb2 (system compiler) Change-Id: Ic50757af9f070c0383c7356302e7e7686f031740 Reviewed-by: Thiago Macieira --- mkspecs/netbsd-g++/qmake.conf | 55 ++++++----------------------------- 1 file changed, 9 insertions(+), 46 deletions(-) diff --git a/mkspecs/netbsd-g++/qmake.conf b/mkspecs/netbsd-g++/qmake.conf index b470c9d08ad..ddd82326af8 100644 --- a/mkspecs/netbsd-g++/qmake.conf +++ b/mkspecs/netbsd-g++/qmake.conf @@ -6,58 +6,21 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = netbsd bsd include(../common/unix.conf) +include(../common/gcc-base-unix.conf) +include(../common/g++-unix.conf) -QMAKE_COMPILER = gcc - -QMAKE_CC = gcc -QMAKE_LEX = flex -QMAKE_LEXFLAGS = -QMAKE_YACC = yacc -QMAKE_YACCFLAGS = -d -QMAKE_CFLAGS = -pipe -QMAKE_CFLAGS_DEPS = -M -QMAKE_CFLAGS_WARN_ON = -Wall -W -QMAKE_CFLAGS_WARN_OFF = -w -QMAKE_CFLAGS_RELEASE = -O2 -QMAKE_CFLAGS_DEBUG = -g -QMAKE_CFLAGS_SHLIB = -fPIC -QMAKE_CFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_SHLIB -QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses QMAKE_CFLAGS_THREAD = -pthread -QMAKE_CXX = g++ -QMAKE_CXXFLAGS = $$QMAKE_CFLAGS -QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS -QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF -QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE -QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG -QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB -QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB -QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD -QMAKE_INCDIR = /usr/local/include -QMAKE_LIBDIR = /usr/local/lib -QMAKE_INCDIR_X11 = /usr/X11R6/include -QMAKE_LIBDIR_X11 = /usr/X11R6/lib -QMAKE_INCDIR_OPENGL = /usr/X11R6/include -QMAKE_LIBDIR_OPENGL = /usr/X11R6/lib +QMAKE_INCDIR = /usr/pkg/include +QMAKE_LIBDIR = /usr/pkg/lib +QMAKE_INCDIR_X11 = /usr/X11R7/include +QMAKE_LIBDIR_X11 = /usr/X11R7/lib +QMAKE_INCDIR_OPENGL = /usr/X11R7/include +QMAKE_LIBDIR_OPENGL = /usr/X11R7/lib -QMAKE_LINK = g++ -QMAKE_LINK_SHLIB = g++ -QMAKE_LINK_C = gcc -QMAKE_LINK_C_SHLIB = gcc -QMAKE_LINK_SHLIB_CMD = $$QMAKE_LINK_SHLIB $$QMAKE_LFLAGS_SHLIB $(LFLAGS) $$QMAKE_LFLAGS -o $(TARGETD) $(OBJECTS) $(OBJMOC) $(LIBS) -QMAKE_LFLAGS = -QMAKE_LFLAGS_RELEASE = -QMAKE_LFLAGS_DEBUG = -QMAKE_LFLAGS_SHLIB = -shared -QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB -QMAKE_LFLAGS_SONAME = -Wl,-soname, QMAKE_LFLAGS_THREAD = -pthread -QMAKE_LFLAGS_NOUNDEF = -Wl,-no_unresolved -QMAKE_LFLAGS_RPATH = -Wl,-rpath, QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = @@ -69,6 +32,6 @@ QMAKE_LIBS_THREAD = QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P -QMAKE_RANLIB = ranlib +QMAKE_RANLIB = load(qt_config) From 1b22aeda5bfac43ac37d835adb60eeb3cc01aab6 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 7 Jun 2016 14:51:11 +0200 Subject: [PATCH 144/173] OpenBSD: simplify mkspec and match ports By using commmon/gcc-base-unix.conf and common/g++-unix.conf most of the contents of the qmake.conf for OpenBSD can go. The QMAKE_LFLAGS_UNDEF are reset because the linker can't handle environ in libraries, which is only added to libc in OpenBSD 6 (http://www.openbsd.org/faq/current.html) even when explicitly adding -lc to QMAKE_LIBS. See http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20151102/309783.html for similar questions on using -Wl,-z,defs instead. Change-Id: I6c725fb3bc7ae63270912b07f230a480c9157dfd Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- mkspecs/openbsd-g++/qmake.conf | 47 ++++------------------------------ 1 file changed, 5 insertions(+), 42 deletions(-) diff --git a/mkspecs/openbsd-g++/qmake.conf b/mkspecs/openbsd-g++/qmake.conf index 6a66f086ed4..9b280891dfd 100644 --- a/mkspecs/openbsd-g++/qmake.conf +++ b/mkspecs/openbsd-g++/qmake.conf @@ -6,35 +6,11 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = openbsd bsd include(../common/unix.conf) +include(../common/gcc-base-unix.conf) +include(../common/g++-unix.conf) -QMAKE_COMPILER = gcc - -QMAKE_CC = gcc -QMAKE_LEX = flex -QMAKE_LEXFLAGS = -QMAKE_YACC = yacc -QMAKE_YACCFLAGS = -d -QMAKE_CFLAGS = -pipe -QMAKE_CFLAGS_DEPS = -M -QMAKE_CFLAGS_WARN_ON = -Wall -W -QMAKE_CFLAGS_WARN_OFF = -w -QMAKE_CFLAGS_RELEASE = -O2 -QMAKE_CFLAGS_DEBUG = -g -QMAKE_CFLAGS_SHLIB = -fPIC -QMAKE_CFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_SHLIB -QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses QMAKE_CFLAGS_THREAD = -pthread -QMAKE_CXX = g++ -QMAKE_CXXFLAGS = $$QMAKE_CFLAGS -QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS -QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF -QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE -QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG -QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB -QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB -QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD QMAKE_INCDIR = /usr/local/include @@ -44,21 +20,8 @@ QMAKE_LIBDIR_X11 = /usr/X11R6/lib QMAKE_INCDIR_OPENGL = /usr/X11R6/include QMAKE_LIBDIR_OPENGL = /usr/X11R6/lib -QMAKE_LINK = g++ -QMAKE_LINK_SHLIB = g++ -QMAKE_LINK_C = gcc -QMAKE_LINK_C_SHLIB = gcc -QMAKE_LINK_SHLIB_CMD = $$QMAKE_LINK_SHLIB $(LFLAGS) \ - $$QMAKE_CFLAGS_SHLIB $$QMAKE_LFLAGS \ - -o $(TARGETD) $(OBJECTS) $(OBJMOC) $(LIBS) -QMAKE_LFLAGS = -QMAKE_LFLAGS_RELEASE = -QMAKE_LFLAGS_DEBUG = -QMAKE_LFLAGS_SHLIB = -shared -QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB -QMAKE_LFLAGS_SONAME = -Wl,-soname, QMAKE_LFLAGS_THREAD = -pthread -QMAKE_LFLAGS_NOUNDEF = -Wl,-no_unresolved +QMAKE_LFLAGS_NOUNDEF = QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = @@ -67,9 +30,9 @@ QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_THREAD = -QMAKE_AR = ar q +QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P -QMAKE_RANLIB = ranlib +QMAKE_RANLIB = load(qt_config) From 4ea95609ccd9694dac466cae689412024c87e56e Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Tue, 7 Jun 2016 11:02:10 +0200 Subject: [PATCH 145/173] FreeBSD: remove -D_THREAD_SAFE from pthread usage On FreeBSD, the gcc manpages until Release 5.1 mentioned using the -D_THREAD_SAFE define when using -pthread. This has been obsoleted and the gcc manpages from Release 5.2 onwards have this removed. Now we finally remove this historic relic here, too. Change-Id: I00a5b688c56f46b938c0806fb44b72d5afe5079e Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- mkspecs/freebsd-clang/qmake.conf | 2 +- mkspecs/freebsd-g++/qmake.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/freebsd-clang/qmake.conf b/mkspecs/freebsd-clang/qmake.conf index 7f18bbb7211..0d6401f2f5f 100644 --- a/mkspecs/freebsd-clang/qmake.conf +++ b/mkspecs/freebsd-clang/qmake.conf @@ -7,7 +7,7 @@ QMAKE_PLATFORM = freebsd bsd include(../common/unix.conf) -QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE +QMAKE_CFLAGS_THREAD = -pthread QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD diff --git a/mkspecs/freebsd-g++/qmake.conf b/mkspecs/freebsd-g++/qmake.conf index 282b6bdfa7c..56529389f65 100644 --- a/mkspecs/freebsd-g++/qmake.conf +++ b/mkspecs/freebsd-g++/qmake.conf @@ -7,7 +7,7 @@ QMAKE_PLATFORM = freebsd bsd include(../common/unix.conf) -QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE +QMAKE_CFLAGS_THREAD = -pthread QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD From 37ef6b4968b93859df0af13b228b4abb3a0ef2c1 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Mon, 6 Jun 2016 12:00:11 +0200 Subject: [PATCH 146/173] OpenBSD: use clock_gettime() provided by OS The use of clock_gettime() is limited to systems having _POSIX_TIMERS defined, however OpenBSD implements clock_gettime() but does not have the posix define. Enable using clock_gettime() on OpenBSD as well. Change-Id: I785954fe61b42b15755ca625a766c9a95179ae8d Reviewed-by: Thiago Macieira --- config.tests/unix/clock-gettime/clock-gettime.cpp | 2 +- src/concurrent/qtconcurrentiteratekernel.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.tests/unix/clock-gettime/clock-gettime.cpp b/config.tests/unix/clock-gettime/clock-gettime.cpp index 4ba05f70f52..a49359d24c8 100644 --- a/config.tests/unix/clock-gettime/clock-gettime.cpp +++ b/config.tests/unix/clock-gettime/clock-gettime.cpp @@ -36,7 +36,7 @@ int main(int, char **) { -#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) +#if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)) || defined(__OpenBSD__) timespec ts; clock_gettime(CLOCK_REALTIME, &ts); #else diff --git a/src/concurrent/qtconcurrentiteratekernel.cpp b/src/concurrent/qtconcurrentiteratekernel.cpp index 3b9b186b397..1925f71c8bd 100644 --- a/src/concurrent/qtconcurrentiteratekernel.cpp +++ b/src/concurrent/qtconcurrentiteratekernel.cpp @@ -71,7 +71,7 @@ static qint64 getticks() static qint64 getticks() { -#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) +#if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)) || defined(Q_OS_OPENBSD) clockid_t clockId; #ifndef _POSIX_THREAD_CPUTIME From 6db053139ef1dfedd1bcec613be9f691bc8d9470 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 5 Jun 2016 21:41:02 +0200 Subject: [PATCH 147/173] Delete unsupported/freebsd-g++-46 mkspec The freebsd-g++46 mkspec was intended to specifically use gcc 4.6 from FreeBSD ports collection. However, the ports collection moves its "standard" gcc version and uses symlinks to the standard commands (e.g. gcc -> gcc48) on installing gcc. The current gcc in ports is 4.8.5, so the mkspec is not useful at all. Change-Id: I041325d05c7dc3f47f4a774d6f46ba24a601bf3e Reviewed-by: Thiago Macieira --- mkspecs/unsupported/freebsd-g++46/qmake.conf | 44 ------------------- .../unsupported/freebsd-g++46/qplatformdefs.h | 34 -------------- 2 files changed, 78 deletions(-) delete mode 100644 mkspecs/unsupported/freebsd-g++46/qmake.conf delete mode 100644 mkspecs/unsupported/freebsd-g++46/qplatformdefs.h diff --git a/mkspecs/unsupported/freebsd-g++46/qmake.conf b/mkspecs/unsupported/freebsd-g++46/qmake.conf deleted file mode 100644 index 11041dee3d2..00000000000 --- a/mkspecs/unsupported/freebsd-g++46/qmake.conf +++ /dev/null @@ -1,44 +0,0 @@ -# -# qmake configuration for freebsd-g++46 (using g++46 from ports/lang/gcc) -# - -MAKEFILE_GENERATOR = UNIX -QMAKE_PLATFORM = freebsd bsd - -include(../../common/unix.conf) - -QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE - -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD - -# Addon software goes into /usr/local on the BSDs, by default we will look there -QMAKE_INCDIR = /usr/local/include -QMAKE_LIBDIR = /usr/local/lib - -QMAKE_LFLAGS_THREAD = -pthread - -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = -QMAKE_LIBS_EXECINFO = -lexecinfo -QMAKE_LIBS_X11 = -lXext -lX11 -lm -QMAKE_LIBS_OPENGL = -lGL -QMAKE_LIBS_THREAD = - -QMAKE_AR = ar cqs -QMAKE_OBJCOPY = objcopy -QMAKE_NM = nm -P -QMAKE_RANLIB = - -include(../../common/gcc-base-unix.conf) -include(../../common/g++-unix.conf) - -# Redefined here because g++-base.conf sets QMAKE_CC and QMAKE_CXX -# to gcc and g++, respectively. -QMAKE_CC = gcc46 -QMAKE_CXX = g++46 -QMAKE_LINK_C = $$QMAKE_CC -QMAKE_LINK_C_SHLIB = $$QMAKE_CC -QMAKE_LINK = $$QMAKE_CXX -QMAKE_LINK_SHLIB = $$QMAKE_CXX - -load(qt_config) diff --git a/mkspecs/unsupported/freebsd-g++46/qplatformdefs.h b/mkspecs/unsupported/freebsd-g++46/qplatformdefs.h deleted file mode 100644 index b52be38b4ed..00000000000 --- a/mkspecs/unsupported/freebsd-g++46/qplatformdefs.h +++ /dev/null @@ -1,34 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the qmake spec of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "../../freebsd-clang/qplatformdefs.h" From a914003c8286c5145f437723d8d280cc854d4275 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 5 Jun 2016 21:19:17 +0200 Subject: [PATCH 148/173] Remove OpenBSD _POSIX_THREAD_SAFE_FUNCTIONS undefine The qplatformdefs.h for OpenBSD included an undefine of _POSIX_THREAD_SAFE_FUNCTIONS because of (at the time) missing implementations of the required _r() functions. After checking these functions http://www.unix.org/whitepapers/reentrant.html against the OpenBSD man pages http://man.openbsd.org/OpenBSD-4.4/cat3/getpwuid_r.0 they are all complete with OpenBSD 4.4 released in 2008. As OpenBSD only supports the current and the last release before (5.8 and 5.9 now), it is safe to assume that this undefine can go away now for sure. Change-Id: I341bcae77d1bd7249ac3fdeaefce9c5eb595eca7 Reviewed-by: Thiago Macieira --- mkspecs/openbsd-g++/qplatformdefs.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/mkspecs/openbsd-g++/qplatformdefs.h b/mkspecs/openbsd-g++/qplatformdefs.h index 4ec9c6bb2f3..bd6996c242a 100644 --- a/mkspecs/openbsd-g++/qplatformdefs.h +++ b/mkspecs/openbsd-g++/qplatformdefs.h @@ -80,21 +80,6 @@ #define QT_SNPRINTF ::snprintf #define QT_VSNPRINTF ::vsnprintf -// 1003.1c-1995 says on page 38 (2.9.3, paragraph 3) that if _POSIX_THREADS -// is defined, then _POSIX_THREAD_SAFE_FUNCTIONS must also be defined. -// However this looks like a well-known typo (reversed dependency). -// -// On the other hand _POSIX_THREAD_SAFE_FUNCTIONS should be defined only -// if the Thread-Safe Functions option is implemented. OpenBSD does not -// support all of the required _r() interfaces, especially getpwuid_r(), -// which means it should not define _POSIX_THREAD_SAFE_FUNCTIONS. -// -// Since OpenBSD does define _POSIX_THREAD_SAFE_FUNCTIONS, we have to -// undefine it behind its back. -#ifdef _POSIX_THREAD_SAFE_FUNCTIONS -#undef _POSIX_THREAD_SAFE_FUNCTIONS -#endif - // Older OpenBSD versions may still use the a.out format instead of ELF. #ifndef __ELF__ #define QT_AOUT_UNDERSCORE From 76810e1495b65a09e9abd6164639e0caf34d61b8 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 20 May 2016 14:52:18 +0200 Subject: [PATCH 149/173] xcb: Disable GLX pbuffers with Chromium in VMs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I474e4a4ce424a92b46381eb26aeda811ed059819 Task-number: QTCREATORBUG-16252 Task-number: QTCREATORBUG-14937 Reviewed-by: Błażej Szczygieł Reviewed-by: Gatis Paeglis --- .../xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index a3a8aa259b9..55d0ff38b7b 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -201,8 +201,10 @@ QPlatformOffscreenSurface *QXcbGlxIntegration::createPlatformOffscreenSurface(QO display = static_cast(m_connection->xlib_display()); #endif const char *glxvendor = glXGetClientString(display, GLX_VENDOR); - if (glxvendor && !strcmp(glxvendor, "ATI")) - glxPbufferUsable = false; + if (glxvendor) { + if (!strcmp(glxvendor, "ATI") || !strcmp(glxvendor, "Chromium")) + glxPbufferUsable = false; + } } if (glxPbufferUsable) return new QGLXPbuffer(surface); From f9c60038bf098015172998c2a216dd02672cd96b Mon Sep 17 00:00:00 2001 From: Alejandro Exojo Date: Sun, 8 May 2016 17:34:26 +0200 Subject: [PATCH 150/173] Fix QVariantAnimation documentation Since 5.0, this class is not abstract. Only the documentation of updateCurrentValue was updated at that time. Fix the class reference and the mentions of the class being abstract in the Animation Framework overview. Change-Id: I8ef9accb0b870dc8eb75bfc74361c7f2ad8d1d8b Reviewed-by: Venugopal Shivashankar Reviewed-by: Frederik Gladhorn --- src/corelib/animation/qvariantanimation.cpp | 6 ++---- src/corelib/doc/src/animation.qdoc | 11 ++++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 1322b8c8101..d2545bfb887 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -48,15 +48,13 @@ QT_BEGIN_NAMESPACE \class QVariantAnimation \inmodule QtCore \ingroup animation - \brief The QVariantAnimation class provides an abstract base class for animations. + \brief The QVariantAnimation class provides a base class for animations. \since 4.6 This class is part of \l{The Animation Framework}. It serves as a base class for property and item animations, with functions for shared functionality. - QVariantAnimation cannot be used directly as it is an abstract - class; it has a pure virtual method called updateCurrentValue(). The class performs interpolation over \l{QVariant}s, but leaves using the interpolated values to its subclasses. Currently, Qt provides QPropertyAnimation, which @@ -69,7 +67,7 @@ QT_BEGIN_NAMESPACE start the animation. QVariantAnimation will interpolate the property of the target object and emit valueChanged(). To react to a change in the current value you have to reimplement the - updateCurrentValue() virtual function. + updateCurrentValue() virtual function or connect to said signal. It is also possible to set values at specified steps situated between the start and end value. The interpolation will then diff --git a/src/corelib/doc/src/animation.qdoc b/src/corelib/doc/src/animation.qdoc index e5e67cf5038..304eb9d112c 100644 --- a/src/corelib/doc/src/animation.qdoc +++ b/src/corelib/doc/src/animation.qdoc @@ -118,11 +118,12 @@ \section1 Animating Qt Properties - As mentioned in the previous section, the QPropertyAnimation class - can interpolate over Qt properties. It is this class that should - be used for animation of values; in fact, its superclass, - QVariantAnimation, is an abstract class, and cannot be used - directly. + As mentioned in the previous section, the QPropertyAnimation class can + interpolate over Qt properties. It is often this class that should be used + for animation of values; in fact, its superclass, QVariantAnimation, has an + empty implementation of \l{QAbstractAnimation::}{updateCurrentValue()}, and + does not change any value unless we change it ourselves on the + \l{QVariantAnimation::valueChanged()}{valueChanged signal}. A major reason we chose to animate Qt properties is that it presents us with freedom to animate already existing classes in From 862fa24179505ef725ff78bb64bdabd54bd00c95 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 20 May 2016 23:56:19 +0200 Subject: [PATCH 151/173] Optimize QJsonObject::operator== The old code iterated through one QJsonObject and looked up the key in the other, comparing the values. It had linearithmic complexity, and created one QString 'key' per element. Since the entries in a QJsonObject are lexicographically ordered, we can, however, just walk through the two objects in lock-step and compare corresponding entries (at the same index) with each other. Doing so saves O(N) QString creations and QJsonObject::value() calls, and makes operator== linear in the number of elements. Change-Id: Ib46ee0c1008b7f114454e282b6bd2bfcdbe59e2a Reviewed-by: Thiago Macieira Reviewed-by: Lars Knoll --- src/corelib/json/qjson_p.h | 2 ++ src/corelib/json/qjsonobject.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index c52a37ba2b0..b7de24d1652 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -670,6 +670,8 @@ public: bool operator >=(const Entry &other) const; }; +inline bool operator!=(const Entry &lhs, const Entry &rhs) { return !(lhs == rhs); } + inline bool Entry::operator >=(const QString &key) const { if (value.latinKey) diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index b83c8dd19a2..f5fd76eac05 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -545,8 +545,8 @@ bool QJsonObject::operator==(const QJsonObject &other) const for (uint i = 0; i < o->length; ++i) { QJsonPrivate::Entry *e = o->entryAt(i); - QJsonValue v(d, o, e->value); - if (other.value(e->key()) != v) + QJsonPrivate::Entry *oe = other.o->entryAt(i); + if (*e != *oe || QJsonValue(d, o, e->value) != QJsonValue(other.d, other.o, oe->value)) return false; } From 7a4ce3cbccbdce920f3e0d0f82fe9d707d50f393 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Wed, 30 Mar 2016 13:19:03 +0300 Subject: [PATCH 152/173] QString: remove unnecessary copy in replace() When a copy is needed, replace_helper() takes care of that for us. Change-Id: I9e5c89cb70b2902c96062a9edaf77fedda6ddb2c Reviewed-by: Edward Welbourne --- src/corelib/tools/qstring.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 940fd5817b9..cf36be1f7c8 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -2346,8 +2346,7 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs) */ QString &QString::replace(int pos, int len, const QString &after) { - QString copy = after; - return replace(pos, len, copy.constData(), copy.length()); + return replace(pos, len, after.constData(), after.length()); } /*! From 5f3a262a7377c33383594d4ab52e66b987316d70 Mon Sep 17 00:00:00 2001 From: Martin Porcelli Date: Tue, 1 Mar 2016 12:10:04 -0800 Subject: [PATCH 153/173] QSslSocket: Data is sent after a certificate is downloaded on Windows. QSslSocket was not transmitting existing data after finishing its handshake if it had to download a certificate on Windows. Task-number: QTBUG-48816 Change-Id: Ie35b5f4ca0f6c3c40fe2394166eb31f9f72dac55 Reviewed-by: Timur Pocheptsov Reviewed-by: Edward Welbourne Reviewed-by: Richard J. Moore --- src/network/ssl/qsslsocket_openssl.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 9df0c693ab3..57cedf2c226 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1368,8 +1368,12 @@ void QSslSocketBackendPrivate::_q_caRootLoaded(QSslCertificate cert, QSslCertifi if (plainSocket) plainSocket->resume(); paused = false; - if (checkSslErrors() && ssl) + if (checkSslErrors() && ssl) { + bool willClose = (autoStartHandshake && pendingClose); continueHandshake(); + if (!willClose) + transmit(); + } } class QWindowsCaRootFetcherThread : public QThread From 4fb2b7411994852b742f944eba9d71d7d851aca5 Mon Sep 17 00:00:00 2001 From: Ralf Nolden Date: Sun, 5 Jun 2016 20:12:28 +0200 Subject: [PATCH 154/173] Remove a.out defines in OpenBSD and NetBSD mkspec OpenBSD made the switch from a.out to ELF with release 3.4, published 2003, see http://www.openbsd.org/34.html. In preparation to cleaning up the mkspecs for OpenBSD, remove the a.out defines as only recent versions of OpenBSD (5.8 onward) will be supported. NetBSD switched from a.out to ELF file format with release 1.5, see https://www.netbsd.org/releases/formal-1.5/NetBSD-1.5.html in the year 2000. Remove the defines for older a.out systems now as we are at release 7.0 and only 6.0 onwards releases are currently supported anyway. While cleaning up, remove the old comments for QT_SOCKLEN_T values of outdated OpenBSD and NetBSD releases as well. Change-Id: I8519eab7bcd4af19c0e9f628657878f32b2bd602 Reviewed-by: Thiago Macieira --- mkspecs/netbsd-g++/qplatformdefs.h | 9 --------- mkspecs/openbsd-g++/qplatformdefs.h | 9 --------- 2 files changed, 18 deletions(-) diff --git a/mkspecs/netbsd-g++/qplatformdefs.h b/mkspecs/netbsd-g++/qplatformdefs.h index b6639b97c2c..bcba448e2c2 100644 --- a/mkspecs/netbsd-g++/qplatformdefs.h +++ b/mkspecs/netbsd-g++/qplatformdefs.h @@ -72,16 +72,7 @@ #undef QT_OPEN_LARGEFILE #define QT_OPEN_LARGEFILE 0 -// QT_SOCKLEN_T -// NetBSD 1.0 - 1.3.3 int -// NetBSD 1.4 - 1.5 socklen_t - #define QT_SNPRINTF ::snprintf #define QT_VSNPRINTF ::vsnprintf -// Older NetBSD versions may still use the a.out format instead of ELF. -#ifndef __ELF__ -#define QT_AOUT_UNDERSCORE -#endif - #endif // QPLATFORMDEFS_H diff --git a/mkspecs/openbsd-g++/qplatformdefs.h b/mkspecs/openbsd-g++/qplatformdefs.h index bd6996c242a..57766541216 100644 --- a/mkspecs/openbsd-g++/qplatformdefs.h +++ b/mkspecs/openbsd-g++/qplatformdefs.h @@ -73,16 +73,7 @@ #undef QT_OPEN_LARGEFILE #define QT_OPEN_LARGEFILE 0 -// QT_SOCKLEN_T -// OpenBSD 2.2 - 2.4 int -// OpenBSD 2.5 - 2.8 socklen_t - #define QT_SNPRINTF ::snprintf #define QT_VSNPRINTF ::vsnprintf -// Older OpenBSD versions may still use the a.out format instead of ELF. -#ifndef __ELF__ -#define QT_AOUT_UNDERSCORE -#endif - #endif // QPLATFORMDEFS_H From 5a15545ee274a9caa33014755a3fdb7022c7ea8c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 8 Jun 2016 10:01:51 +0200 Subject: [PATCH 155/173] QDebug: fix streaming of QChars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 9ef3ff30 introduced a new function, putUcs4(), to output QChar, char16_t, char32_t as a, possibly escaped, character literal, but got the order of stream modifiers wrong. Instead of applying the field width to the 'ucs' streaming, it applied it to the prefix '\u'. The same problem exists for the pad char, leading to the result '00\ue4' for a QChar containing ä (LATIN SMALL LETTER A WITH DIAERESIS) Fix by reordering the elements streamed so that the prefixes come last. Added a test. Change-Id: I6eaa0586501b9e780aaa3bb5dcec0e5c2f86a219 Reviewed-by: Thiago Macieira --- src/corelib/io/qdebug.cpp | 9 ++++----- tests/auto/corelib/io/qdebug/tst_qdebug.cpp | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 81af96b96bf..a1d7d9806de 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -160,16 +160,15 @@ void QDebug::putUcs4(uint ucs4) { maybeQuote('\''); if (ucs4 < 0x20) { - stream->ts << hex << "\\x" << ucs4 << reset; + stream->ts << "\\x" << hex << ucs4 << reset; } else if (ucs4 < 0x80) { stream->ts << char(ucs4); } else { - stream->ts << hex << qSetPadChar(QLatin1Char('0')); if (ucs4 < 0x10000) - stream->ts << qSetFieldWidth(4) << "\\u"; + stream->ts << "\\u" << qSetFieldWidth(4); else - stream->ts << qSetFieldWidth(8) << "\\U"; - stream->ts << ucs4 << reset; + stream->ts << "\\U" << qSetFieldWidth(8); + stream->ts << hex << qSetPadChar(QLatin1Char('0')) << ucs4 << reset; } maybeQuote('\''); } diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index db2805ebf01..0c04c5058b2 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -363,14 +363,14 @@ void tst_QDebug::qDebugQChar() const MessageHandlerSetter mhs(myMessageHandler); { QDebug d = qDebug(); - d << QChar('f'); - d.nospace().noquote() << QChar('o') << QChar('o'); + d << QChar('f') << QChar(QLatin1Char('\xE4')); // f, ä + d.nospace().noquote() << QChar('o') << QChar('o') << QChar(QLatin1Char('\xC4')); // o, o, Ä } #ifndef QT_NO_MESSAGELOGCONTEXT file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO; #endif QCOMPARE(s_msgType, QtDebugMsg); - QCOMPARE(s_msg, QString::fromLatin1("'f' oo")); + QCOMPARE(s_msg, QString::fromLatin1("'f' '\\u00e4' oo\\u00c4")); QCOMPARE(QString::fromLatin1(s_file), file); QCOMPARE(s_line, line); QCOMPARE(QString::fromLatin1(s_function), function); From 767319a5aac2462df84431917b3724f884091036 Mon Sep 17 00:00:00 2001 From: Luca Bellonda Date: Wed, 1 Jun 2016 00:06:13 +0200 Subject: [PATCH 156/173] Add support for 8bit encodings not ASCII compatible in QXMLStreamWriter. When using a 8 bit encoding to write a file, a test discovers if the encoding is really ASCII compatible by examining a letter and one of the XML reserved characters. EBCDIC, in the current base, was not well handled. [ChangeLog][QtCore][QXmlStreamWriter] Fixed a bug that prevented the generation of valid XML files when using encoding with 8 bit per character but not ASCII compatible. QXMLStreamWriter generated XML markup using always ASCII in this case. Change-Id: I9c86a122dd91b2290d50c358638442f99777d4ae Reviewed-by: Thiago Macieira --- src/corelib/xml/qxmlstream.cpp | 12 ++++-- .../corelib/xml/qxmlstream/tst_qxmlstream.cpp | 39 +++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 64a130e45a4..a235145669c 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -3019,10 +3019,14 @@ void QXmlStreamWriterPrivate::checkIfASCIICompatibleCodec() { #ifndef QT_NO_TEXTCODEC Q_ASSERT(encoder); - // assumes ASCII-compatibility for all 8-bit encodings - QChar space = QLatin1Char(' '); - const QByteArray bytes = encoder->fromUnicode(&space, 1); - isCodecASCIICompatible = (bytes.count() == 1); + // test ASCII-compatibility using the letter 'a' + QChar letterA = QLatin1Char('a'); + const QByteArray bytesA = encoder->fromUnicode(&letterA, 1); + const bool isCodecASCIICompatibleA = (bytesA.count() == 1) && (bytesA[0] == 0x61) ; + QChar letterLess = QLatin1Char('<'); + const QByteArray bytesLess = encoder->fromUnicode(&letterLess, 1); + const bool isCodecASCIICompatibleLess = (bytesLess.count() == 1) && (bytesLess[0] == 0x3C) ; + isCodecASCIICompatible = isCodecASCIICompatibleA && isCodecASCIICompatibleLess ; #else isCodecASCIICompatible = true; #endif diff --git a/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp index 1da29ac3bd5..b0fd1187f55 100644 --- a/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp @@ -561,6 +561,7 @@ private slots: void checkCommentIndentation() const; void checkCommentIndentation_data() const; void crashInXmlStreamReader() const; + void write8bitCodec() const; void hasError() const; private: @@ -1578,5 +1579,43 @@ void tst_QXmlStream::hasError() const } +void tst_QXmlStream::write8bitCodec() const +{ + QBuffer outBuffer; + QVERIFY(outBuffer.open(QIODevice::WriteOnly)); + QXmlStreamWriter writer(&outBuffer); + writer.setAutoFormatting(false); + + QTextCodec *codec = QTextCodec::codecForName("IBM500"); + if (!codec) { + QSKIP("Encoding IBM500 not available."); + } + writer.setCodec(codec); + + writer.writeStartDocument(); + writer.writeStartElement("root"); + writer.writeAttribute("attrib", "1"); + writer.writeEndElement(); + writer.writeEndDocument(); + outBuffer.close(); + + // test 8 bit encoding + QByteArray values = outBuffer.data(); + QVERIFY(values.size() > 1); + // check '<' + QCOMPARE(values[0] & 0x00FF, 0x4c); + // check '?' + QCOMPARE(values[1] & 0x00FF, 0x6F); + + // convert the start of the XML + const QString expected = (""); + QTextDecoder *decoder = codec->makeDecoder(); + QVERIFY(decoder); + QString decodedText = decoder->toUnicode(values); + delete decoder; + QVERIFY(decodedText.startsWith(expected)); +} + + #include "tst_qxmlstream.moc" // vim: et:ts=4:sw=4:sts=4 From 4762fabce16c611f12542a48b0dd31b3cec8e530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Thu, 14 Apr 2016 13:20:23 +0200 Subject: [PATCH 157/173] xcb: Fix transient parent and "Qt::Window" flag Don't set transient parent property when Qt::Window flag is set. Delete transient parent property if a window doesn't have a transient parent. Force setting standard window flags for Qt::Window only if there are no other flags. Amends 98c10a02c5b77e023471ad6993dc66b013889cfb Task-number: QTBUG-52550 Change-Id: I68ee715b632487e9dd0e7ffbbfc0c2cdd0f0e151 Reviewed-by: Dmitry Shachnev Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbwindow.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 429ba8df717..0c2f0d7c4da 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -821,9 +821,9 @@ void QXcbWindow::show() propagateSizeHints(); // update WM_TRANSIENT_FOR - const QWindow *tp = window()->transientParent(); - if (isTransient(window()) || tp != 0) { - xcb_window_t transientXcbParent = 0; + xcb_window_t transientXcbParent = 0; + if (isTransient(window())) { + const QWindow *tp = window()->transientParent(); if (tp && tp->handle()) transientXcbParent = static_cast(tp->handle())->winId(); // Default to client leader if there is no transient parent, else modal dialogs can @@ -836,6 +836,8 @@ void QXcbWindow::show() 1, &transientXcbParent)); } } + if (!transientXcbParent) + Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR)); // update _MOTIF_WM_HINTS updateMotifWmHintsBeforeMap(); @@ -1195,9 +1197,11 @@ void QXcbWindow::setMotifWindowFlags(Qt::WindowFlags flags) mwmhints.flags |= MWM_HINTS_DECORATIONS; bool customize = flags & Qt::CustomizeWindowHint; - if (type == Qt::Window && !customize) - flags |= Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint; - + if (type == Qt::Window && !customize) { + const Qt::WindowFlags defaultFlags = Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint; + if (!(flags & defaultFlags)) + flags |= defaultFlags; + } if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) { mwmhints.decorations |= MWM_DECOR_BORDER; mwmhints.decorations |= MWM_DECOR_RESIZEH; From afa0e9bf6a53d20dbb9820c7fce1bb67de0e616f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Wed, 4 May 2016 18:24:48 +0200 Subject: [PATCH 158/173] QtWidgets: Open submenus also on left mouse button press MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch allows to open submenus also on left mouse button press. Previously submenus could be opened only on right mouse button press as ContextMenu event which was inconvenient especially for long submenu popup timeout. Task-number: QTBUG-53054 Change-Id: I1bd78ed4436f738c8838f7f4687ffebb94b66725 Reviewed-by: Félix Bourbonnais Reviewed-by: Gabriel de Dietrich Reviewed-by: Shawn Rutledge --- src/widgets/widgets/qmenu.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 744fecb3f37..184dd42fe6e 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -2697,10 +2697,15 @@ QMenu::event(QEvent *e) return true; } } break; - case QEvent::ContextMenu: - if (d->delayState.timer.isActive()) { - d->delayState.stop(); - internalDelayedPopup(); + case QEvent::MouseButtonPress: + case QEvent::ContextMenu: { + bool canPopup = true; + if (e->type() == QEvent::MouseButtonPress) + canPopup = (static_cast(e)->button() == Qt::LeftButton); + if (canPopup && d->delayState.timer.isActive()) { + d->delayState.stop(); + internalDelayedPopup(); + } } break; case QEvent::Resize: { From 36ffe18f05594c6bacddb90a13d3dc727875b629 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 8 Jun 2016 08:47:58 +0200 Subject: [PATCH 159/173] Re-enable tst_QDir on Windows. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partially revert f3939d943ed132eaf3daead797d961c3ffbc31a5. Change-Id: I67e4d8973bc18d9cd77750c6379221d34e9484b3 Reviewed-by: Jędrzej Nowacki --- tests/auto/corelib/io/qdir/qdir.pro | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auto/corelib/io/qdir/qdir.pro b/tests/auto/corelib/io/qdir/qdir.pro index 65cfd3faa93..9cbc4918001 100644 --- a/tests/auto/corelib/io/qdir/qdir.pro +++ b/tests/auto/corelib/io/qdir/qdir.pro @@ -13,5 +13,3 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 android:!android-no-sdk { RESOURCES += android_testdata.qrc } - -win32: CONFIG += insignificant_test # Crashes on Windows in release builds From 19def3d8f14c42a930e1f7bb9d6c1a0872ea59b8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 8 Jun 2016 13:37:50 +0200 Subject: [PATCH 160/173] Revert "Insignifify qdiriterator test" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b373d183de4249c938935ff357c50c415b69f247. The crashes in release mode cannot be locally reproduced. Change-Id: I38ff5e9e045cff0e94e24ca07fb6e18e88b677c7 Reviewed-by: Jędrzej Nowacki --- tests/auto/corelib/io/qdiriterator/qdiriterator.pro | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auto/corelib/io/qdiriterator/qdiriterator.pro b/tests/auto/corelib/io/qdiriterator/qdiriterator.pro index 51bfcb36a58..ade9b66afef 100644 --- a/tests/auto/corelib/io/qdiriterator/qdiriterator.pro +++ b/tests/auto/corelib/io/qdiriterator/qdiriterator.pro @@ -9,5 +9,3 @@ contains(CONFIG, builtin_testdata): DEFINES += BUILTIN_TESTDATA wince*mips*|wincewm50smart-msvc200*: DEFINES += WINCE_BROKEN_ITERATE=1 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 - -win32: CONFIG += insignificant_test # Crashes on Windows in release builds From 6c0783d1073d67e16381ca2812b57f4626bd75f1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 8 Jun 2016 13:33:12 +0200 Subject: [PATCH 161/173] Revert "Insignifify qfileinfo on Windows, like QDir". MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 55655abfaf1fbe09af2eedfde413e862bc6c85e2. The crashes in release mode cannot be locally reproduced. Change-Id: I4e7b1defbeac5d5512b2fa82a367d2e04e3c37a4 Reviewed-by: Jędrzej Nowacki --- tests/auto/corelib/io/qfileinfo/qfileinfo.pro | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro index 571637be373..de99447404e 100644 --- a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro +++ b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro @@ -7,5 +7,3 @@ RESOURCES += qfileinfo.qrc \ win32:!wince:!winrt:LIBS += -ladvapi32 -lnetapi32 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 - -win32: CONFIG += insignificant_test # Crashes on Windows in release builds From bd4344a0bd5cb15abc2742c9c380afc635e2049f Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 2 Jun 2016 16:56:31 +0200 Subject: [PATCH 162/173] Fix qplugin autotest on Windows Since Qt 5.0.0 we never built the test plugins on Windows, because we checked for the existence of QtCore[d]4.dll, and the actual test does not complain if it cannot find any plugins. Use the right conditions to check for debug/release Qt builds on Windows. Use subdirs dependencies on every platform and then actually pass the right variable to SUBDIRS. Clean up the pro file while we're at it. Change-Id: I099f30afd445fbf43dc5677d256ffe55b27639b3 Reviewed-by: Simon Hausmann --- tests/auto/corelib/plugin/qplugin/qplugin.pro | 35 +++++++------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/tests/auto/corelib/plugin/qplugin/qplugin.pro b/tests/auto/corelib/plugin/qplugin/qplugin.pro index e8840a0fb28..5283c2d52be 100644 --- a/tests/auto/corelib/plugin/qplugin/qplugin.pro +++ b/tests/auto/corelib/plugin/qplugin/qplugin.pro @@ -1,28 +1,17 @@ -QT = core TEMPLATE = subdirs +TESTPLUGINS = + win32 { - exists($$[QT_INSTALL_LIBS/get]/QtCore4.dll) { - SUBDIRS = releaseplugin - } - exists($$[QT_INSTALL_LIBS/get]/QtCored4.dll) { - SUBDIRS += debugplugin - } + contains(QT_CONFIG, debug): TESTPLUGINS += debugplugin + contains(QT_CONFIG, release): TESTPLUGINS += releaseplugin +} else:osx { + CONFIG(debug, debug|release): TESTPLUGINS += debugplugin + CONFIG(release, debug|release): TESTPLUGINS += releaseplugin +} else { + TESTPLUGINS = debugplugin releaseplugin } -mac { - CONFIG(debug, debug|release): { - SUBDIRS += debugplugin - tst_qplugin_pro.depends += debugplugin - } - CONFIG(release, debug|release): { - SUBDIRS += releaseplugin - tst_qplugin_pro.depends += releaseplugin - } -} -!win32:!mac:{ - SUBDIRS = debugplugin releaseplugin - tst_qplugin_pro.depends += debugplugin releaseplugin -} -SUBDIRS += tst_qplugin.pro +SUBDIRS += main $$TESTPLUGINS +main.file = tst_qplugin.pro +main.depends = $$TESTPLUGINS -CONFIG += parallel_test From 43ff604f9453edb24154c2ab5ea72bafe0fc501d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 8 Jun 2016 19:03:19 -0700 Subject: [PATCH 163/173] x86: Fix build with BMI but no LZCNT extensions The GCC builtins for clzs and ctzs are enabled when the x86 extension for LZCNT and TZCNT are enabled. The use of only __BMI__ in commit f5f47987ce369aa3f7553e6c0da509461a1ddf1a was incorrect. But GCC needs both BMI and LZCNT enabled to enable this builtin. Change-Id: I1cc7601489634e96833cfffd145647e9fc9f2f51 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/tools/qalgorithms.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index 14465240b45..4f704d6764d 100644 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -626,7 +626,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint8 v) Q_DECL_NOT Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint16 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) -# if QT_HAS_BUILTIN(__builtin_ctzs) || defined(__BMI__) +# if QT_HAS_BUILTIN(__builtin_ctzs) || (defined(__LZCNT__) && defined(__BMI__)) return v ? __builtin_ctzs(v) : 16U; # else return v ? __builtin_ctz(v) : 16U; @@ -689,7 +689,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTH Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) -# if QT_HAS_BUILTIN(__builtin_clzs) || defined(__BMI__) +# if QT_HAS_BUILTIN(__builtin_clzs) || (defined(__LZCNT__) && defined(__BMI__)) return v ? __builtin_clzs(v) : 16U; # else return v ? __builtin_clz(v)-16U : 16U; From 0a78d918f0f411e0da2242a84a396f169154f5d6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 5 Jun 2015 00:41:36 +0200 Subject: [PATCH 164/173] Replace qAllocMore with a pair of more useful functions The first is "exact", not "more": qCalculateBlockSize. It ensures that there's no overflow in multiplying, adding the header size or when converting back to an int. The second is the replacement for qAllocMore: it calculates the block size like the first, but increases the block size to accommodate future appends. The number of elements that fit in the block is also returned. Task-number: QTBUG-41230 Change-Id: I52dd43c12685407bb9a6ffff13f5da09f816e667 Reviewed-by: Lars Knoll --- src/corelib/tools/qarraydata.cpp | 34 ++---- src/corelib/tools/qbytearray.cpp | 112 ++++++++++++++++-- src/corelib/tools/qlist.cpp | 29 ++--- src/corelib/tools/qstring.cpp | 11 +- src/corelib/tools/qtools_p.h | 14 ++- src/gui/text/qfragmentmap_p.h | 9 +- .../tools/qbytearray/tst_qbytearray.cpp | 84 ++++++++++--- .../corelib/tools/qvector/outofline.cpp | 2 +- 8 files changed, 215 insertions(+), 80 deletions(-) diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 36f1997a6c2..55af7256be0 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -87,29 +88,20 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, if (!(options & RawData)) headerSize += (alignment - Q_ALIGNOF(QArrayData)); - // Allocate additional space if array is growing - if (options & Grow) { - - // Guard against integer overflow when multiplying. - if (capacity > std::numeric_limits::max() / objectSize) - return 0; - - size_t alloc; - if (mul_overflow(objectSize, capacity, &alloc)) - return 0; - - // Make sure qAllocMore won't overflow qAllocMore. - if (headerSize > size_t(MaxAllocSize) || alloc > size_t(MaxAllocSize) - headerSize) - return 0; - - capacity = qAllocMore(int(alloc), int(headerSize)) / int(objectSize); - } + if (headerSize > size_t(MaxAllocSize)) + return 0; + // Calculate the byte size + // allocSize = objectSize * capacity + headerSize, but checked for overflow + // plus padded to grow in size size_t allocSize; - if (mul_overflow(objectSize, capacity, &allocSize)) - return 0; - if (add_overflow(allocSize, headerSize, &allocSize)) - return 0; + if (options & Grow) { + auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize); + capacity = r.elementCount; + allocSize = r.size; + } else { + allocSize = qCalculateBlockSize(capacity, objectSize, headerSize); + } QArrayData *header = static_cast(::malloc(allocSize)); if (header) { diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 2efe3c1a861..c9d6f4e4119 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -46,6 +46,7 @@ #include "qlocale.h" #include "qlocale_p.h" #include "qlocale_tools_p.h" +#include "private/qnumeric_p.h" #include "qstringalgorithms_p.h" #include "qscopedpointer.h" #include "qbytearray_p.h" @@ -128,17 +129,104 @@ int qFindByteArray( const char *haystack0, int haystackLen, int from, const char *needle0, int needleLen); +/* + * This pair of functions is declared in qtools_p.h and is used by the Qt + * containers to allocate memory and grow the memory block during append + * operations. + * + * They take size_t parameters and return size_t so they will change sizes + * according to the pointer width. However, knowing Qt containers store the + * container size and element indexes in ints, these functions never return a + * size larger than INT_MAX. This is done by casting the element count and + * memory block size to int in several comparisons: the check for negative is + * very fast on most platforms as the code only needs to check the sign bit. + * + * These functions return SIZE_MAX on overflow, which can be passed to malloc() + * and will surely cause a NULL return (there's no way you can allocate a + * memory block the size of your entire VM space). + */ -int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW +/*! + \internal + \since 5.7 + + Returns the memory block size for a container containing \a elementCount + elements, each of \a elementSize bytes, plus a header of \a headerSize + bytes. That is, this function returns \c + {elementCount * elementSize + headerSize} + + but unlike the simple calculation, it checks for overflows during the + multiplication and the addition. + + Both \a elementCount and \a headerSize can be zero, but \a elementSize + cannot. + + This function returns SIZE_MAX (~0) on overflow or if the memory block size + would not fit an int. +*/ +size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) Q_DECL_NOTHROW { - Q_ASSERT(alloc >= 0 && extra >= 0 && extra <= MaxAllocSize); - Q_ASSERT_X(alloc <= MaxAllocSize - extra, "qAllocMore", "Requested size is too large!"); + unsigned count = unsigned(elementCount); + unsigned size = unsigned(elementSize); + unsigned header = unsigned(headerSize); + Q_ASSERT(elementSize); + Q_ASSERT(size == elementSize); + Q_ASSERT(header == headerSize); - unsigned nalloc = qNextPowerOfTwo(alloc + extra); + if (Q_UNLIKELY(count != elementCount)) + return std::numeric_limits::max(); - Q_ASSERT(nalloc > unsigned(alloc + extra)); + unsigned bytes; + if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) || + Q_UNLIKELY(add_overflow(bytes, header, &bytes))) + return std::numeric_limits::max(); + if (Q_UNLIKELY(int(bytes) < 0)) // catches bytes >= 2GB + return std::numeric_limits::max(); - return nalloc - extra; + return bytes; +} + +/*! + \internal + \since 5.7 + + Returns the memory block size and the number of elements that will fit in + that block for a container containing \a elementCount elements, each of \a + elementSize bytes, plus a header of \a headerSize bytes. This function + assumes the container will grow and pre-allocates a growth factor. + + Both \a elementCount and \a headerSize can be zero, but \a elementSize + cannot. + + This function returns SIZE_MAX (~0) on overflow or if the memory block size + would not fit an int. + + \note The memory block may contain up to \a elementSize - 1 bytes more than + needed. +*/ +CalculateGrowingBlockSizeResult +qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) Q_DECL_NOTHROW +{ + CalculateGrowingBlockSizeResult result = { + std::numeric_limits::max(),std::numeric_limits::max() + }; + + unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize)); + if (int(bytes) < 0) // catches std::numeric_limits::max() + return result; + + unsigned morebytes = qNextPowerOfTwo(bytes); + if (Q_UNLIKELY(int(morebytes) < 0)) { + // catches morebytes == 2GB + // grow by half the difference between bytes and morebytes + bytes += (morebytes - bytes) / 2; + } else { + bytes = morebytes; + } + + result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize); + result.size = bytes; + return result; } /***************************************************************************** @@ -1618,12 +1706,16 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options) Data::deallocate(d); d = x; } else { + size_t blockSize; if (options & Data::Grow) { - if (alloc > MaxByteArraySize) - qBadAlloc(); - alloc = qAllocMore(alloc, sizeof(Data)); + auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data)); + blockSize = r.size; + alloc = uint(r.elementCount); + } else { + blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data)); } - Data *x = static_cast(::realloc(d, sizeof(Data) + alloc)); + + Data *x = static_cast(::realloc(d, blockSize)); Q_CHECK_PTR(x); x->alloc = alloc; x->capacityReserved = (options & Data::CapacityReserved) ? 1 : 0; diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 7dd02bf9549..1762da2c8f7 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -60,15 +60,6 @@ QT_BEGIN_NAMESPACE const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, { 0 } }; -static int grow(int size) -{ - if (size_t(size) > (MaxAllocSize - QListData::DataHeaderSize) / sizeof(void *)) - qBadAlloc(); - // dear compiler: don't optimize me out. - volatile int x = qAllocMore(size * sizeof(void *), QListData::DataHeaderSize) / sizeof(void *); - return x; -} - /*! * Detaches the QListData by allocating new memory for a list which will be bigger * than the copied one and is expected to grow further. @@ -84,12 +75,12 @@ QListData::Data *QListData::detach_grow(int *idx, int num) Data *x = d; int l = x->end - x->begin; int nl = l + num; - int alloc = grow(nl); - Data* t = static_cast(::malloc(DataHeaderSize + alloc * sizeof(void *))); + auto blockInfo = qCalculateGrowingBlockSize(nl, sizeof(void *), DataHeaderSize); + Data* t = static_cast(::malloc(blockInfo.size)); Q_CHECK_PTR(t); + t->alloc = int(uint(blockInfo.elementCount)); t->ref.initializeOwned(); - t->alloc = alloc; // The space reservation algorithm's optimization is biased towards appending: // Something which looks like an append will put the data at the beginning, // while something which looks like a prepend will put it in the middle @@ -99,12 +90,12 @@ QListData::Data *QListData::detach_grow(int *idx, int num) int bg; if (*idx < 0) { *idx = 0; - bg = (alloc - nl) >> 1; + bg = (t->alloc - nl) >> 1; } else if (*idx > l) { *idx = l; bg = 0; } else if (*idx < (l >> 1)) { - bg = (alloc - nl) >> 1; + bg = (t->alloc - nl) >> 1; } else { bg = 0; } @@ -126,7 +117,7 @@ QListData::Data *QListData::detach_grow(int *idx, int num) QListData::Data *QListData::detach(int alloc) { Data *x = d; - Data* t = static_cast(::malloc(DataHeaderSize + alloc * sizeof(void *))); + Data* t = static_cast(::malloc(qCalculateBlockSize(alloc, sizeof(void*), DataHeaderSize))); Q_CHECK_PTR(t); t->ref.initializeOwned(); @@ -146,7 +137,7 @@ QListData::Data *QListData::detach(int alloc) void QListData::realloc(int alloc) { Q_ASSERT(!d->ref.isShared()); - Data *x = static_cast(::realloc(d, DataHeaderSize + alloc * sizeof(void *))); + Data *x = static_cast(::realloc(d, qCalculateBlockSize(alloc, sizeof(void *), DataHeaderSize))); Q_CHECK_PTR(x); d = x; @@ -158,12 +149,12 @@ void QListData::realloc(int alloc) void QListData::realloc_grow(int growth) { Q_ASSERT(!d->ref.isShared()); - int alloc = grow(d->alloc + growth); - Data *x = static_cast(::realloc(d, DataHeaderSize + alloc * sizeof(void *))); + auto r = qCalculateGrowingBlockSize(d->alloc + growth, sizeof(void *), DataHeaderSize); + Data *x = static_cast(::realloc(d, r.size)); Q_CHECK_PTR(x); d = x; - d->alloc = alloc; + d->alloc = int(uint(r.elementCount)); } void QListData::dispose(Data *d) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index cf36be1f7c8..85da1743660 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1760,10 +1760,13 @@ void QString::resize(int size, QChar fillChar) void QString::reallocData(uint alloc, bool grow) { + size_t blockSize; if (grow) { - if (alloc > (uint(MaxAllocSize) - sizeof(Data)) / sizeof(QChar)) - qBadAlloc(); - alloc = qAllocMore(alloc * sizeof(QChar), sizeof(Data)) / sizeof(QChar); + auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data)); + blockSize = r.size; + alloc = uint(r.elementCount); + } else { + blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data)); } if (d->ref.isShared() || IS_RAW_DATA(d)) { @@ -1777,7 +1780,7 @@ void QString::reallocData(uint alloc, bool grow) Data::deallocate(d); d = x; } else { - Data *p = static_cast(::realloc(d, sizeof(Data) + alloc * sizeof(QChar))); + Data *p = static_cast(::realloc(d, blockSize)); Q_CHECK_PTR(p); d = p; d->alloc = alloc; diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h index 5ec153c8180..09adee5586e 100644 --- a/src/corelib/tools/qtools_p.h +++ b/src/corelib/tools/qtools_p.h @@ -52,7 +52,7 @@ // #include "QtCore/qglobal.h" -#include +#include QT_BEGIN_NAMESPACE @@ -88,11 +88,19 @@ Q_DECL_CONSTEXPR inline int fromOct(uint c) Q_DECL_NOTHROW // We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size. enum { - MaxAllocSize = (1 << (std::numeric_limits::digits - 1)) - 1 + MaxAllocSize = INT_MAX +}; + +struct CalculateGrowingBlockSizeResult { + size_t size; + size_t elementCount; }; // implemented in qbytearray.cpp -int Q_CORE_EXPORT qAllocMore(int alloc, int extra) Q_DECL_NOTHROW; +size_t Q_CORE_EXPORT Q_DECL_CONST_FUNCTION +qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) Q_DECL_NOTHROW; +CalculateGrowingBlockSizeResult Q_CORE_EXPORT Q_DECL_CONST_FUNCTION +qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) Q_DECL_NOTHROW ; QT_END_NAMESPACE diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h index 4cf17aadc7c..b54d7261d0a 100644 --- a/src/gui/text/qfragmentmap_p.h +++ b/src/gui/text/qfragmentmap_p.h @@ -255,14 +255,11 @@ uint QFragmentMapData::createFragment() uint freePos = head->freelist; if (freePos == head->allocated) { // need to create some free space - if (freePos >= uint(MaxAllocSize) / fragmentSize) - qBadAlloc(); - uint needed = qAllocMore((freePos+1)*fragmentSize, 0); - Q_ASSERT(needed/fragmentSize > head->allocated); - Fragment *newFragments = (Fragment *)realloc(fragments, needed); + auto blockInfo = qCalculateGrowingBlockSize(freePos + 1, fragmentSize); + Fragment *newFragments = (Fragment *)realloc(fragments, blockInfo.size); Q_CHECK_PTR(newFragments); fragments = newFragments; - head->allocated = needed/fragmentSize; + head->allocated = quint32(blockInfo.elementCount); F(freePos).right = 0; } diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp index 910d7abf51c..a460afcfa2f 100644 --- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp @@ -107,7 +107,7 @@ private slots: void number(); void toInt_data(); void toInt(); - void qAllocMore(); + void blockSizeCalculations(); void resizeAfterFromRawData(); void appendAfterFromRawData(); @@ -1346,28 +1346,80 @@ void tst_QByteArray::toULongLong() QCOMPARE(b, ok); } -// global function defined in qbytearray.cpp -void tst_QByteArray::qAllocMore() +static bool checkSize(size_t value, uint min) { - using QT_PREPEND_NAMESPACE(qAllocMore); + return value >= min && value <= INT_MAX; +} +// global functions defined in qbytearray.cpp +void tst_QByteArray::blockSizeCalculations() +{ // Not very important, but please behave :-) - QVERIFY(qAllocMore(0, 0) >= 0); + QCOMPARE(qCalculateBlockSize(0, 1), size_t(0)); + QVERIFY(qCalculateGrowingBlockSize(0, 1).size <= MaxAllocSize); + QVERIFY(qCalculateGrowingBlockSize(0, 1).elementCount <= MaxAllocSize); - for (int i = 1; i < 1 << 8; i <<= 1) - QVERIFY(qAllocMore(i, 0) >= i); + // boundary condition + QCOMPARE(qCalculateBlockSize(MaxAllocSize, 1), size_t(MaxAllocSize)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/2, 2), size_t(MaxAllocSize) - 1); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/2, 2, 1), size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize, 1).size, size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize, 1).elementCount, size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize/2, 2, 1).size, size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize/2, 2, 1).elementCount, size_t(MaxAllocSize)/2); - for (int i = 1 << 8; i < 1 << 30; i <<= 1) { - const int alloc = qAllocMore(i, 0); + // error conditions + QCOMPARE(qCalculateBlockSize(uint(MaxAllocSize) + 1, 1), size_t(~0)); + QCOMPARE(qCalculateBlockSize(size_t(-1), 1), size_t(~0)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize, 1, 1), size_t(~0)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/2 + 1, 2), size_t(~0)); + QCOMPARE(qCalculateGrowingBlockSize(uint(MaxAllocSize) + 1, 1).size, size_t(~0)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize/2 + 1, 2).size, size_t(~0)); - QVERIFY(alloc >= i); - QCOMPARE(qAllocMore(i - 8, 8), alloc - 8); - QCOMPARE(qAllocMore(i - 16, 16), alloc - 16); - QCOMPARE(qAllocMore(i - 24, 24), alloc - 24); - QCOMPARE(qAllocMore(i - 32, 32), alloc - 32); + // overflow conditions + // on 32-bit platforms, (1 << 16) * (1 << 16) = (1 << 32) which is zero + QCOMPARE(qCalculateBlockSize(1 << 16, 1 << 16), size_t(~0)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/4, 16), size_t(~0)); + // on 32-bit platforms, (1 << 30) * 3 + (1 << 30) would overflow to zero + QCOMPARE(qCalculateBlockSize(1U << 30, 3, 1U << 30), size_t(~0)); - QVERIFY(qAllocMore(i - 1, 0) >= i - 1); - QVERIFY(qAllocMore(i + 1, 0) >= i + 1); + // exact block sizes + for (int i = 1; i < 1 << 31; i <<= 1) { + QCOMPARE(qCalculateBlockSize(0, 1, i), size_t(i)); + QCOMPARE(qCalculateBlockSize(i, 1), size_t(i)); + QCOMPARE(qCalculateBlockSize(i + i/2, 1), size_t(i + i/2)); + } + for (int i = 1; i < 1 << 30; i <<= 1) { + QCOMPARE(qCalculateBlockSize(i, 2), 2 * size_t(i)); + QCOMPARE(qCalculateBlockSize(i, 2, 1), 2 * size_t(i) + 1); + QCOMPARE(qCalculateBlockSize(i, 2, 16), 2 * size_t(i) + 16); + } + + // growing sizes + for (int i = 1; i < 1 << 31; i <<= 1) { + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1).size, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1).elementCount, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 16).size, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 16).elementCount, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 24).size, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 16).elementCount, i)); + } + + // growth should be limited + for (int elementSize = 1; elementSize < (1<<8); elementSize <<= 1) { + size_t alloc = 1; + forever { + QVERIFY(checkSize(qCalculateGrowingBlockSize(alloc, elementSize).size, alloc * elementSize)); + size_t newAlloc = qCalculateGrowingBlockSize(alloc, elementSize).elementCount; + QVERIFY(checkSize(newAlloc, alloc)); + if (newAlloc == alloc) + break; // no growth, we're at limit + alloc = newAlloc; + } + QVERIFY(checkSize(alloc, size_t(MaxAllocSize) / elementSize)); + + // the next allocation should be invalid + QCOMPARE(qCalculateGrowingBlockSize(alloc + 1, elementSize).size, size_t(~0)); } } diff --git a/tests/benchmarks/corelib/tools/qvector/outofline.cpp b/tests/benchmarks/corelib/tools/qvector/outofline.cpp index efd3df2308f..76a4edaa101 100644 --- a/tests/benchmarks/corelib/tools/qvector/outofline.cpp +++ b/tests/benchmarks/corelib/tools/qvector/outofline.cpp @@ -97,5 +97,5 @@ void QVectorData::free(QVectorData *x, int alignment) int QVectorData::grow(int sizeOfHeader, int size, int sizeOfT) { - return qAllocMore(size * sizeOfT, sizeOfHeader) / sizeOfT; + return qCalculateGrowingBlockSize(size, sizeOfT, sizeOfHeader).elementCount; } From 7835b260a9f60c98ee41468b040ac080782afe2f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 27 Oct 2015 19:48:04 -0700 Subject: [PATCH 165/173] configure: check whether std::atomic works for function pointers And ask the user to apply one of the patches we're carrying to their Standard Libraries. Change-Id: I7e6338336dd6468ead24ffff141139c79056922e Reviewed-by: Simon Hausmann --- config.tests/common/atomicfptr/atomicfptr.cpp | 58 +++++++++++++++++++ config.tests/common/atomicfptr/atomicfptr.pro | 3 + .../common/atomicfptr/icc2016_mac.diff | 18 ++++++ config.tests/common/atomicfptr/qnx66.txt | 3 + configure | 8 +++ tools/configure/configureapp.cpp | 12 ++++ 6 files changed, 102 insertions(+) create mode 100644 config.tests/common/atomicfptr/atomicfptr.cpp create mode 100644 config.tests/common/atomicfptr/atomicfptr.pro create mode 100644 config.tests/common/atomicfptr/icc2016_mac.diff create mode 100644 config.tests/common/atomicfptr/qnx66.txt diff --git a/config.tests/common/atomicfptr/atomicfptr.cpp b/config.tests/common/atomicfptr/atomicfptr.cpp new file mode 100644 index 00000000000..ce0193dbe4a --- /dev/null +++ b/config.tests/common/atomicfptr/atomicfptr.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Intel Corporation. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +typedef void (*fptr)(int); +typedef std::atomic atomicfptr; + +void testfunction(int) { } + +void test(volatile atomicfptr &a) +{ + fptr v = a.load(std::memory_order_acquire); + while (!a.compare_exchange_strong(v, &testfunction, + std::memory_order_acq_rel, + std::memory_order_acquire)) { + v = a.exchange(&testfunction); + } + + a.store(&testfunction, std::memory_order_release); +} + +int main(int, char **) +{ + atomicfptr fptr(testfunction); + test(fptr); + return 0; +} diff --git a/config.tests/common/atomicfptr/atomicfptr.pro b/config.tests/common/atomicfptr/atomicfptr.pro new file mode 100644 index 00000000000..5509862a304 --- /dev/null +++ b/config.tests/common/atomicfptr/atomicfptr.pro @@ -0,0 +1,3 @@ +SOURCES = atomicfptr.cpp +CONFIG += c++11 console +CONFIG -= qt app_bundle diff --git a/config.tests/common/atomicfptr/icc2016_mac.diff b/config.tests/common/atomicfptr/icc2016_mac.diff new file mode 100644 index 00000000000..5de3b6e19a6 --- /dev/null +++ b/config.tests/common/atomicfptr/icc2016_mac.diff @@ -0,0 +1,18 @@ +Patch for fixing std::atomic support for function pointers for the Intel +Composer XE 2016 (compiler version 16.0). + +To apply: + cd /opt/intel/compilers_and_libraries_2016/mac/include + sudo patch -p1 < /path-to-this-file/icc2016_mac.diff + +--- include/stdatomic.h.orig 2015-08-28 15:05:13.000000000 -0700 ++++ include/stdatomic.h 2015-08-28 15:19:25.000000000 -0700 +@@ -451,7 +451,7 @@ + } + _STRONG_INLINE atomic() _DEFAULTED + _STRONG_INLINE _CONSTEXPR atomic(T* _Ptr) +- : atomic_address(_Ptr) ++ : atomic_address((void*)_Ptr) + { + } + _STRONG_INLINE T* operator+=(ptrdiff_t _V) volatile diff --git a/config.tests/common/atomicfptr/qnx66.txt b/config.tests/common/atomicfptr/qnx66.txt new file mode 100644 index 00000000000..b4ea9d65b5c --- /dev/null +++ b/config.tests/common/atomicfptr/qnx66.txt @@ -0,0 +1,3 @@ +Patch is available from QNX. Please see + +http://www.qnx.com/download/feature.html?programid=27555 diff --git a/configure b/configure index 049d393e7f0..29b228f5bb0 100755 --- a/configure +++ b/configure @@ -4486,6 +4486,14 @@ else CFG_ATOMIC64=no fi +# Detect whether std::atomic works for function pointers -- some implementations are buggy +if ! compileTest common/atomicfptr "std::atomic for function pointers"; then + echo "ERROR: detected a std::atomic implementation that fails for function pointers." + echo "Please apply the patch corresponding to your Standard Library vendor, found in" + echo " $relpath/config.tests/common/atomicfptr" + exit 101 +fi + # detect sse2 support CFG_SSE_LIST= if [ "${CFG_SSE2}" = "auto" ]; then diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 6dc551ceb58..395c4a0b54d 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -2172,6 +2172,9 @@ bool Configure::checkAvailability(const QString &part) else if (part == "ATOMIC64-LIBATOMIC") available = tryCompileProject("common/atomic64", "LIBS+=-latomic"); + else if (part == "ATOMICFPTR") + available = tryCompileProject("common/atomicfptr"); + else if (part == "ZLIB") available = findFile("zlib.h"); @@ -2338,6 +2341,15 @@ void Configure::autoDetection() dictionary["ATOMIC64"] = checkAvailability("ATOMIC64") ? "yes" : checkAvailability("ATOMIC64-LIBATOMIC") ? "libatomic" : "no"; + // special case: + if (!checkAvailability("ATOMICFPTR")) { + dictionary["DONE"] = "error"; + cout << "ERROR: detected an std::atomic implementation that fails for function pointers." << endl + << "Please apply the patch corresponding to your Standard Library vendor, found in" << endl + << sourcePath << "/config.tests/common/atomicfptr" << endl; + return; + } + // Style detection if (dictionary["STYLE_WINDOWSXP"] == "auto") dictionary["STYLE_WINDOWSXP"] = checkAvailability("STYLE_WINDOWSXP") ? defaultTo("STYLE_WINDOWSXP") : "no"; From b05741937c2827c05d2160ccf98f389eb03b6f35 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 11 Nov 2015 19:22:43 -0800 Subject: [PATCH 166/173] Plug padding holes in QHostAddressPrivate On ABIs where quint64 is aligned on 8-byte boundaries (such 32-bit Windows and all 64-bit systems), there was a padding hole of 4 bytes between QHostAddressPrivate::a and the anonymous union. If we move the member to after the union, there is no hole anymore. That operation causes the tail padding to grow from 3 to 7 bytes. Since we also don't need full 32 bits for the protocol, we can shrink the structure by 8 bytes on those architectures and by 4 bytes on 32-bit Unix systems. Change-Id: I461e9fc7199748faa187ffff1415d6601a7bd777 Reviewed-by: hjk --- src/corelib/global/qhooks.cpp | 2 +- src/network/kernel/qhostaddress.cpp | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp index da401ffd78a..b91ec64786f 100644 --- a/src/corelib/global/qhooks.cpp +++ b/src/corelib/global/qhooks.cpp @@ -67,7 +67,7 @@ quintptr Q_CORE_EXPORT qtHookData[] = { // The required sizes and offsets are tested in tests/auto/other/toolsupport. // When this fails and the change was intentional, adjust the test and // adjust this value here. - 4 + 5 }; Q_STATIC_ASSERT(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0])); diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 0dbe1112cd2..2c09e63d6e0 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -115,14 +115,13 @@ public: QString ipString; QString scopeId; - quint32 a; // IPv4 address union { Q_IPV6ADDR a6; // IPv6 address struct { quint64 c[2]; } a6_64; struct { quint32 c[4]; } a6_32; }; - QAbstractSocket::NetworkLayerProtocol protocol; - + quint32 a; // IPv4 address + qint8 protocol; bool isParsed; friend class QHostAddress; @@ -701,7 +700,7 @@ quint32 QHostAddress::toIPv4Address(bool *ok) const QAbstractSocket::NetworkLayerProtocol QHostAddress::protocol() const { QT_ENSURE_PARSED(this); - return d->protocol; + return QAbstractSocket::NetworkLayerProtocol(d->protocol); } /*! From d2c6294bd5cc3c2e61aaa0c83bfd74941ced150e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 26 May 2016 09:11:28 +0200 Subject: [PATCH 167/173] Diaglib: Add class LogWidget. Add a class to display debug messages, providing convenience functions for installing and formatting parameters like indentation. It prints a startup message containing relevant information about Qt. Change-Id: Id0a19adbb5953a6ded1a8e692f242b63748e7273 Reviewed-by: Joerg Bornemann --- tests/manual/diaglib/README.txt | 11 ++ tests/manual/diaglib/diaglib.pri | 12 ++- tests/manual/diaglib/logwidget.cpp | 164 +++++++++++++++++++++++++++++ tests/manual/diaglib/logwidget.h | 94 +++++++++++++++++ 4 files changed, 277 insertions(+), 4 deletions(-) create mode 100644 tests/manual/diaglib/logwidget.cpp create mode 100644 tests/manual/diaglib/logwidget.h diff --git a/tests/manual/diaglib/README.txt b/tests/manual/diaglib/README.txt index fd199d09cbe..ab243da9aed 100644 --- a/tests/manual/diaglib/README.txt +++ b/tests/manual/diaglib/README.txt @@ -32,6 +32,17 @@ class DebugProxyStyle (debugproxystyle.h) the parameters and return values of its function calls, useful for debugging QStyle. +class LogWidget (logwidget.h) + A Log Widget inheriting QPlainTextEdit with convenience functions + to install as a message handler. + +class LogFunctionGuard + A guard class for use with LogWidget logging messages when a function + is entered/left (indenting the log messages). + Can be instantiated using: + LogFunctionGuard guard(__FUNCTION__) or + LogFunctionGuard guard(Q_FUNC_INFO) + function glInfo() (glinfo.h): Returns a string describing the Open GL configuration (obtained by querying GL_VENDOR and GL_RENDERER). Available only diff --git a/tests/manual/diaglib/diaglib.pri b/tests/manual/diaglib/diaglib.pri index a51d2f1201a..9bcf0317a6f 100644 --- a/tests/manual/diaglib/diaglib.pri +++ b/tests/manual/diaglib/diaglib.pri @@ -23,17 +23,21 @@ greaterThan(QT_MAJOR_VERSION, 4) { QT += gui-private core-private contains(QT, widgets) { HEADERS += \ - $$PWD/qwidgetdump.h + $$PWD/qwidgetdump.h \ + $$PWD/logwidget.h SOURCES += \ - $$PWD/qwidgetdump.cpp + $$PWD/qwidgetdump.cpp \ + $$PWD/logwidget.cpp } } else { HEADERS += \ - $$PWD/qwidgetdump.h + $$PWD/qwidgetdump.h \ + $$PWD/logwidget.h SOURCES += \ - $$PWD/qwidgetdump.cpp + $$PWD/qwidgetdump.cpp \ + $$PWD/logwidget.cpp } contains(QT, opengl) { diff --git a/tests/manual/diaglib/logwidget.cpp b/tests/manual/diaglib/logwidget.cpp new file mode 100644 index 00000000000..5dbefd8da99 --- /dev/null +++ b/tests/manual/diaglib/logwidget.cpp @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "logwidget.h" +#if QT_VERSION >= 0x050000 +# include +# include +#endif +#include +#include + +#include +#include +#include + +#include + +LogWidget *LogWidget::m_instance = 0; +bool LogWidget::m_lineNumberingEnabled = true; +bool LogWidget::m_showMessageType = true; +int LogWidget::m_indent = 0; + +LogWidget::LogWidget(QWidget *parent) + : QPlainTextEdit(parent) +{ + LogWidget::m_instance = this; + setReadOnly(true); +} + +LogWidget::~LogWidget() +{ + LogWidget::m_instance = 0; +} + +QString LogWidget::startupMessage() +{ + QString result; +#if QT_VERSION >= 0x050300 + result += QLatin1String(QLibraryInfo::build()); +#else + result += QLatin1String("Qt ") + QLatin1String(QT_VERSION_STR); +#endif + + const QCoreApplication *coreApp = QCoreApplication::instance(); +#if QT_VERSION >= 0x050000 + if (qobject_cast(coreApp)) { + result += QLatin1Char(' '); + result += QGuiApplication::platformName(); + } +#endif + if (qobject_cast(coreApp)) { + result += QLatin1Char(' '); + result += QApplication::style()->objectName(); + } + if (coreApp) { + QStringList arguments = QCoreApplication::arguments(); + arguments.pop_front(); + if (!arguments.isEmpty()) { + result += QLatin1Char('\n'); + result += arguments.join(QLatin1String(" ")); + } + } + return result; +} + +static const QVector &messageTypes() +{ + static QVector result; + if (result.isEmpty()) { + result << QLatin1String("debug") << QLatin1String("warn") + << QLatin1String("critical") << QLatin1String("fatal") + << QLatin1String("info"); + } + return result; +} + +static void messageHandler(QtMsgType type, const QString &text) +{ + static int n = 0; + QString message; + if (LogWidget::lineNumberingEnabled()) + message.append(QString::fromLatin1("%1 ").arg(n, 4, 10, QLatin1Char('0'))); + if (LogWidget::showMessageType()) { + message.append(messageTypes().at(type)); + message.append(QLatin1Char(' ')); + } + for (int i = 0, ie = LogWidget::indent(); i < ie; ++i) + message.append(QLatin1Char(' ')); + message.append(text); + if (LogWidget *logWindow = LogWidget::instance()) + logWindow->appendText(message); +#ifdef Q_OS_WIN + std::wcerr << reinterpret_cast(message.utf16()) << L'\n'; +#else + std::cerr << qPrintable(message) << '\n'; +#endif + n++; +} + +#if QT_VERSION >= 0x050000 + +static void qt5MessageHandler(QtMsgType type, const QMessageLogContext &, const QString &text) +{ messageHandler(type, text); } + +void LogWidget::install() +{ + qInstallMessageHandler(qt5MessageHandler); + qInfo("%s", qPrintable(LogWidget::startupMessage())); +} + +void LogWidget::uninstall() { qInstallMessageHandler(Q_NULLPTR); } + +#else // Qt 5 + +static QtMsgHandler oldHandler = 0; + +static void qt4MessageHandler(QtMsgType type, const char *text) +{ messageHandler(type, QString::fromLocal8Bit(text)); } + +void LogWidget::install() +{ + oldHandler = qInstallMsgHandler(qt4MessageHandler); + qDebug("%s", qPrintable(LogWidget::startupMessage())); +} + +void LogWidget::uninstall() { qInstallMsgHandler(oldHandler); } + +#endif // Qt 4 + +void LogWidget::appendText(const QString &message) +{ + appendPlainText(message); + ensureCursorVisible(); +} diff --git a/tests/manual/diaglib/logwidget.h b/tests/manual/diaglib/logwidget.h new file mode 100644 index 00000000000..1a85cc143d4 --- /dev/null +++ b/tests/manual/diaglib/logwidget.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LOGWIDGET_H +#define LOGWIDGET_H + +#include + +// Instantiate as follows: LogFunctionGuard guard(Q_FUNC_INFO) +class LogFunctionGuard { + Q_DISABLE_COPY(LogFunctionGuard) +public: + explicit LogFunctionGuard(const char *name); + ~LogFunctionGuard(); + +private: + const char *m_name; +}; + +class LogWidget : public QPlainTextEdit +{ + Q_OBJECT +public: + explicit LogWidget(QWidget *parent = 0); + ~LogWidget(); + + static LogWidget *instance() { return m_instance; } + + static QString startupMessage(); + static void install(); + static void uninstall(); + + static int indent() { return m_indent; } + static void setIndent(int i) { m_indent = i; } + + static bool lineNumberingEnabled() { return m_lineNumberingEnabled; } + static void setLineNumberingEnabled(bool l) { m_lineNumberingEnabled = l; } + + static bool showMessageType() { return m_showMessageType; } + static void setShowMessageType(bool s) { m_showMessageType = s; } + +public slots: + void appendText(const QString &); + +private: + static int m_indent; + static bool m_lineNumberingEnabled; + static bool m_showMessageType; + static LogWidget *m_instance; +}; + +inline LogFunctionGuard::LogFunctionGuard(const char *name) : m_name(name) +{ + qDebug(">%s", m_name); + LogWidget::setIndent(LogWidget::indent() + 2); +} + +inline LogFunctionGuard::~LogFunctionGuard() +{ + LogWidget::setIndent(LogWidget::indent() - 2); + qDebug("<%s", m_name); +} + +#endif // LOGWIDGET_H From 751143724a98d467509b7e5711a8d47dff97b7ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 1 Jun 2016 13:29:19 +0200 Subject: [PATCH 168/173] uikit: Call base class implementation of rotation callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Apple documentation explicitly says that you should call super when implementing these methods. Change-Id: I584bb140a4a5bde88927b379ab19158a78c6fea9 Reviewed-by: Jake Petroules Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosviewcontroller.mm | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index 94d894bba77..ed76161b876 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -324,17 +324,16 @@ - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration { - Q_UNUSED(orientation); - Q_UNUSED(duration); - self.changingOrientation = YES; + + [super willRotateToInterfaceOrientation:orientation duration:duration]; } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)orientation { - Q_UNUSED(orientation); - self.changingOrientation = NO; + + [super didRotateFromInterfaceOrientation:orientation]; } - (void)willChangeStatusBarFrame:(NSNotification*)notification From 196d55ba5c8d169d120f17ca1db3d85ea1e5b4dd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 9 Jun 2016 10:33:23 +0200 Subject: [PATCH 169/173] Output region in debug operator of QPaintEvent. This helps to analzye flicker/painting issues. Change-Id: I18e04598013c013386c3d019ff3098b1accec3f7 Reviewed-by: Alexandru Croitor Reviewed-by: Shawn Rutledge --- src/gui/kernel/qevent.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 9281744692c..43da81e8a6a 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3842,6 +3842,9 @@ QDebug operator<<(QDebug dbg, const QEvent *e) case QEvent::Expose: dbg << "QExposeEvent(" << static_cast(e)->region() << ')'; break; + case QEvent::Paint: + dbg << "QPaintEvent(" << static_cast(e)->region() << ')'; + break; case QEvent::MouseButtonPress: case QEvent::MouseMove: case QEvent::MouseButtonRelease: From e005e99005d83e89ef2499320306c46a14965e7a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 23 May 2016 18:07:22 +0200 Subject: [PATCH 170/173] fix ios device&simulator builds again the assumption stated in b67a0836d is actually invalid - configure sets build_all without debug_and_release there. debug_and_release does actually imply build_all, though. to make things less confusing, don't let configure inject iphonesimulator_and_iphoneos into all projects, but handle it like debug_and_release instead. Change-Id: Ib7acdc63308a538862fc603428f81aba60bca08e Reviewed-by: Jake Petroules --- configure | 3 +-- mkspecs/features/qml_plugin.prf | 4 +++- mkspecs/features/qt_helper_lib.prf | 4 +++- mkspecs/features/qt_module.prf | 4 +++- mkspecs/features/qt_plugin.prf | 4 +++- mkspecs/macx-ios-clang/features/default_pre.prf | 4 ++-- mkspecs/macx-ios-clang/features/sdk.prf | 4 ++-- 7 files changed, 17 insertions(+), 10 deletions(-) diff --git a/configure b/configure index be89b22291a..8f6c3801338 100755 --- a/configure +++ b/configure @@ -3422,8 +3422,7 @@ if [ "$XPLATFORM_IOS" = "yes" ]; then # If the user passes -sdk on the command line we build a SDK-specific Qt build. # Otherwise we build a joined simulator and device build, which is the default. if [ -z "$OPT_MAC_SDK" ]; then - QT_CONFIG="$QT_CONFIG build_all" - QTCONFIG_CONFIG="$QTCONFIG_CONFIG iphonesimulator_and_iphoneos" + QT_CONFIG="$QT_CONFIG build_all simulator_and_device" fi fi diff --git a/mkspecs/features/qml_plugin.prf b/mkspecs/features/qml_plugin.prf index 158bddf60c0..9661da9e8dc 100644 --- a/mkspecs/features/qml_plugin.prf +++ b/mkspecs/features/qml_plugin.prf @@ -15,7 +15,9 @@ TEMPLATE = lib CONFIG += plugin if(win32|mac):!macx-xcode { - contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release build_all + contains(QT_CONFIG, simulator_and_device): CONFIG += iphonesimulator_and_iphoneos + contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release + contains(QT_CONFIG, build_all): CONFIG += build_all } CONFIG += relative_qt_rpath # Qt's QML plugins should be relocatable diff --git a/mkspecs/features/qt_helper_lib.prf b/mkspecs/features/qt_helper_lib.prf index 33931544363..8e61316aa66 100644 --- a/mkspecs/features/qt_helper_lib.prf +++ b/mkspecs/features/qt_helper_lib.prf @@ -18,7 +18,9 @@ QT = # In case qt is re-added. CONFIG -= warning_clean # Don't presume 3rd party code to be clean load(qt_common) -contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release build_all +contains(QT_CONFIG, simulator_and_device): CONFIG += iphonesimulator_and_iphoneos +contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release +contains(QT_CONFIG, build_all): CONFIG += build_all DESTDIR = $$MODULE_BASE_OUTDIR/lib DLLDESTDIR = $$MODULE_BASE_OUTDIR/bin diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 5bd5101cdc5..22e2dd5ea28 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -89,7 +89,9 @@ INCLUDEPATH *= $$eval(QT.$${MODULE}.includes) $$eval(QT.$${MODULE}_private.inclu # If Qt was configured with -debug-and-release then build the module the same way # - unless this is a host library !host_build:if(win32|mac):!macx-xcode { - contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release build_all + contains(QT_CONFIG, simulator_and_device): CONFIG += iphonesimulator_and_iphoneos + contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release + contains(QT_CONFIG, build_all): CONFIG += build_all } QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF diff --git a/mkspecs/features/qt_plugin.prf b/mkspecs/features/qt_plugin.prf index 176159eff1a..3cf6c7349c1 100644 --- a/mkspecs/features/qt_plugin.prf +++ b/mkspecs/features/qt_plugin.prf @@ -26,7 +26,9 @@ win32:CONFIG(shared, static|shared) { tool_plugin { !build_pass:contains(QT_CONFIG, debug_and_release): CONFIG += release } else:if(win32|mac):!macx-xcode { - contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release build_all + contains(QT_CONFIG, simulator_and_device): CONFIG += iphonesimulator_and_iphoneos + contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release + contains(QT_CONFIG, build_all): CONFIG += build_all } CONFIG += relative_qt_rpath # Qt's plugins should be relocatable diff --git a/mkspecs/macx-ios-clang/features/default_pre.prf b/mkspecs/macx-ios-clang/features/default_pre.prf index dfede454b5e..b5c41cf43e4 100644 --- a/mkspecs/macx-ios-clang/features/default_pre.prf +++ b/mkspecs/macx-ios-clang/features/default_pre.prf @@ -2,14 +2,14 @@ load(default_pre) # In case Qt was built for a specific SDK -!iphonesimulator_and_iphoneos:contains(QMAKE_MAC_SDK, ^iphonesimulator.*): \ +!contains(QT_CONFIG, simulator_and_device):contains(QMAKE_MAC_SDK, ^iphonesimulator.*): \ CONFIG += iphonesimulator # Check for supported Xcode versions lessThan(QMAKE_XCODE_VERSION, "4.3"): \ error("This mkspec requires Xcode 4.3 or later") -iphonesimulator_and_iphoneos:iphonesimulator { +build_pass:iphonesimulator { # For a iphonesimulator_and_iphoneos build all the config tests # are based on the iPhoneOS ARM SDK, but we know that the simulator # is i386 and that we support SSE/SSE2. diff --git a/mkspecs/macx-ios-clang/features/sdk.prf b/mkspecs/macx-ios-clang/features/sdk.prf index 32fcbb72893..4d148f22fbf 100644 --- a/mkspecs/macx-ios-clang/features/sdk.prf +++ b/mkspecs/macx-ios-clang/features/sdk.prf @@ -1,12 +1,12 @@ # In case the user sets the SDK manually contains(QMAKE_MAC_SDK, ^iphonesimulator.*) { - iphonesimulator_and_iphoneos: \ + contains(QT_CONFIG, simulator_and_device): \ error("iOS simulator is handled automatically for iphonesimulator_and_iphoneos") CONFIG += iphonesimulator } -iphonesimulator_and_iphoneos:iphonesimulator: \ +build_pass:iphonesimulator: \ QMAKE_MAC_SDK ~= s,^iphoneos,iphonesimulator, load(sdk) From fa8d16d4762d0107308dce85acc9879e272ab8dd Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 6 Jun 2016 12:25:44 +0200 Subject: [PATCH 171/173] Fix QWidgetBackingStore::isDirty() for render-to-texture widgets The backing store would not report itself dirty if only render-to- texture widgets were dirty. This caused QOpenGLWidgets not be repainted after being remapped if they marked themselves dirty while unmapped. Task-number: QTBUG-50818 Task-number: QTBUG-51815 Change-Id: If43f7cbb6f4d44831b4c21b89f884d6bcaebf87c Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qwidgetbackingstore_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h index 564dc7f2456..5da2d515867 100644 --- a/src/widgets/kernel/qwidgetbackingstore_p.h +++ b/src/widgets/kernel/qwidgetbackingstore_p.h @@ -110,7 +110,7 @@ public: inline bool isDirty() const { - return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && !fullUpdatePending); + return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && !fullUpdatePending && dirtyRenderToTextureWidgets.isEmpty()); } // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore). From ea86f736404bab170ebfd75af6ee0f594e10f0f7 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 8 Jun 2016 16:14:04 +0200 Subject: [PATCH 172/173] Mention extension in QFileInfo's suffix-related documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it easier for users to find out how to get a file's extension when browsing docs. Change-Id: I08a1b620dea5432462133324824fae85754b9a09 Task-number: QTBUG-53380 Reviewed-by: Topi Reiniö --- src/corelib/io/qfileinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index dd194594c92..cb1ce6fd659 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -814,7 +814,7 @@ QString QFileInfo::completeBaseName() const } /*! - Returns the complete suffix of the file. + Returns the complete suffix (extension) of the file. The complete suffix consists of all characters in the file after (but not including) the first '.'. @@ -833,7 +833,7 @@ QString QFileInfo::completeSuffix() const } /*! - Returns the suffix of the file. + Returns the suffix (extension) of the file. The suffix consists of all characters in the file after (but not including) the last '.'. From 67ca72796e23269451795baf9adde02a184a7b9e Mon Sep 17 00:00:00 2001 From: Nico Rieck Date: Wed, 24 Feb 2016 21:46:10 +0100 Subject: [PATCH 173/173] Paint small progressbars correctly on Vista+ The animated glow always has a length of 120 but was previously drawn with the clipping rect of the bar's actual size. For sizes smaller than 120 the native theme part would be clipped and the black gradient would show. Change-Id: Id81e39c405ef81ae08af0f64249568016944bdf1 Task-number: QTBUG-51266 Reviewed-by: Friedemann Kleint Reviewed-by: Alessandro Portale --- src/widgets/styles/qwindowsvistastyle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 971fb1be7cd..2ce54fe2078 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -1059,7 +1059,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QPainter imagePainter(&image); theme.painter = &imagePainter; theme.partId = vertical ? PP_FILLVERT : PP_FILL; - theme.rect = QRect(QPoint(0,0), theme.rect.size()); + theme.rect = QRect(QPoint(0,0), animRect.size()); QLinearGradient alphaGradient(0, 0, vertical ? 0 : image.width(), vertical ? image.height() : 0); alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));