From 8948042bd049d08e7653f78b60951408603edb8c Mon Sep 17 00:00:00 2001 From: Julien Blanc Date: Thu, 13 Aug 2015 09:03:39 +0200 Subject: [PATCH 001/240] QString perf improvement : removal of useless test Removed a test in QStringAlgorithms trimmed_helper. That test is not needed because both null / empty QStrings are already handled by the previous test, other cases are handled just fine by the general case. Change-Id: I26db1142a656a7d06dfdd6b3b8f8a3ee6ca22302 Reviewed-by: Thiago Macieira --- src/corelib/tools/qstringalgorithms_p.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/corelib/tools/qstringalgorithms_p.h b/src/corelib/tools/qstringalgorithms_p.h index 65901b0286..a12874f567 100644 --- a/src/corelib/tools/qstringalgorithms_p.h +++ b/src/corelib/tools/qstringalgorithms_p.h @@ -101,8 +101,6 @@ template struct QStringAlgorithms if (begin == str.cbegin() && end == str.cend()) return str; - if (begin == end) - return StringType(); if (!isConst && str.isDetached()) return trimmed_helper_inplace(str, begin, end); return StringType(begin, end - begin); From b098f8344440e300544b5bca3358f6f2097d71ca Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 27 Aug 2015 13:46:53 +0200 Subject: [PATCH 002/240] Fix global modifiers state after triggering shortcuts When using for example alt-tab in Qt Creator, the list of recent documents is kept open as long as alt is pressed. The new tryHandleShortcutOverrideEvent(QWindow *w, QKeyEvent *ev) function failed to record the modifier state (contrary to the other overloads). Change-Id: Ia0fc5d1ff486aa5aac7e25b41acb972dcb6dbf7d Task-number: QTBUG-47122 Reviewed-by: Eike Ziller Reviewed-by: Gabriel de Dietrich --- src/gui/kernel/qwindowsysteminterface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 9a9eab2fe7..850b69d729 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -229,6 +229,7 @@ bool QWindowSystemInterface::tryHandleShortcutOverrideEvent(QWindow *w, QKeyEven { #ifndef QT_NO_SHORTCUT Q_ASSERT(ev->type() == QKeyEvent::ShortcutOverride); + QGuiApplicationPrivate::modifier_buttons = ev->modifiers(); QObject *focus = w->focusObject(); if (!focus) From 4dca8314c36f38ae9d6f0078f62996a8f1f477a5 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 27 Aug 2015 14:32:33 +0200 Subject: [PATCH 003/240] windows: Avoid __eglMustCast... in EGL WinCE headers do not have this type. Task-number: QTBUG-47964 Change-Id: I5573eaf754b825774576c55b7cb4acfbd9e8d8dd Reviewed-by: Andy Shaw Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowseglcontext.cpp | 2 +- src/plugins/platforms/windows/qwindowseglcontext.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 06c9985cac..f2547d5cdd 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -152,7 +152,7 @@ bool QWindowsLibEGL::init() eglGetCurrentSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLint )), eglGetCurrentSurface); eglGetCurrentDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(void)), eglGetCurrentDisplay); eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers); - eglGetProcAddress = RESOLVE((__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * )(const char *)), eglGetProcAddress); + eglGetProcAddress = RESOLVE((QFunctionPointer (EGLAPIENTRY * )(const char *)), eglGetProcAddress); if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress) return false; diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h index d8302c97a7..555d633a78 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.h +++ b/src/plugins/platforms/windows/qwindowseglcontext.h @@ -71,7 +71,7 @@ struct QWindowsLibEGL EGLSurface (EGLAPIENTRY * eglGetCurrentSurface)(EGLint readdraw); EGLDisplay (EGLAPIENTRY * eglGetCurrentDisplay)(void); EGLBoolean (EGLAPIENTRY * eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface); - __eglMustCastToProperFunctionPointerType (EGLAPIENTRY * eglGetProcAddress)(const char *procname); + QFunctionPointer (EGLAPIENTRY *eglGetProcAddress)(const char *procname); EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list); From a8f4fa217daa1b6f7b13cc48c1e5ee8d2d76b008 Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Sat, 22 Aug 2015 12:07:42 +0300 Subject: [PATCH 004/240] Add QLockFilePrivate::processNameByPid implementation for GNU/kFreeBSD GLIBC does not provide kinfo_getproc, so we need to call sysctl manually. Change-Id: I3bf22959ff74b3b6c34b5360738e52086a3ff1b4 Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qlockfile_unix.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 815c0f025b..5ff4b1cbe1 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -56,7 +56,13 @@ # include #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) # include +# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) +# include +# include +# include +# else # include +# endif #endif QT_BEGIN_NAMESPACE @@ -234,9 +240,27 @@ 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)); +# else kinfo_proc *proc = kinfo_getproc(pid); +# endif if (!proc) return QString(); +# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) + if (sysctl(mib, 4, proc, &len, NULL, 0) < 0) { + free(proc); + return QString(); + } + if (proc->ki_pid != pid) { + free(proc); + return QString(); + } +# endif QString name = QFile::decodeName(proc->ki_comm); free(proc); return name; From 064439eae4942e5aec1f1819d8f60fee9514baae Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 10 Aug 2015 15:07:42 +0200 Subject: [PATCH 005/240] Update KDE theme defaults for Plasma 5. Add fallback icon and widgets styles for Plasma 5 Change-Id: I3ca5ebe2388b43754afec141a64db8564153b545 Reviewed-by: David Faure --- .../themes/genericunix/qgenericunixthemes.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp index ba328bfb41..2963b0502d 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp @@ -240,8 +240,13 @@ void QKdeThemePrivate::refresh() toolButtonStyle = Qt::ToolButtonTextBesideIcon; toolBarIconSize = 0; styleNames.clear(); + if (kdeVersion >= 5) + styleNames << QStringLiteral("breeze"); styleNames << QStringLiteral("Oxygen") << QStringLiteral("fusion") << QStringLiteral("windows"); - iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen"); + if (kdeVersion >= 5) + iconFallbackThemeName = iconThemeName = QStringLiteral("breeze"); + else + iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen"); QHash kdeSettings; From 7010da2e6274febf71db40a535ce1d0c4858f143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 24 Aug 2015 16:37:34 +0200 Subject: [PATCH 006/240] iOS: Make setFrame in desktop view take superview transforms into account MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An assumption we do for the QIOSDesktopManagerView is that it should always cover the whole UIWindow. To achieve that, we override setFrame to be stop any attempt from UIKit to make our view smaller, e.g. when the statusbar changes height. In case the view is not a direct child of the window, we need to take any transformations into account when computing the new frame. This happens e.g. during presentation of other view-controllers, where our view is temporarily reparented into a UITransitionView that may have a transform set. Task-number: QTBUG-47506 Change-Id: I388143f2cbb566541ffb1068443ce21e62ea2b42 Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosviewcontroller.mm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index a7068b9246..62f5387979 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -185,7 +185,14 @@ - (void)setFrame:(CGRect)newFrame { - [super setFrame:CGRectMake(0, 0, CGRectGetWidth(newFrame), CGRectGetHeight(self.window.bounds))]; + Q_UNUSED(newFrame); + Q_ASSERT(!self.window || self.window.rootViewController.view == self); + + // When presenting view controllers our view may be temporarily reparented into a UITransitionView + // instead of the UIWindow, and the UITransitionView may have a transform set, so we need to do a + // mapping even if we still expect to always be the root view-controller. + CGRect transformedWindowBounds = [self.superview convertRect:self.window.bounds fromView:self.window]; + [super setFrame:transformedWindowBounds]; } - (void)setBounds:(CGRect)newBounds From 17aaaad653e08f566aabb26dfc6b6958fa79ca03 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Mon, 1 Jun 2015 15:40:41 +0200 Subject: [PATCH 007/240] Ensure sendPostedEvents() can be called independently MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If Qt is not running its own event loop (e.g. if Qt is a plugin running in a non-Qt host application with its own event loop, a call to sendPostedEvents() should process all events by default, and not depend on the flags passed to the last call to processEvents() We also modify sendPostedEvents() to call its base implementation instead of directly calling QCoreApplication::sendPostedEvents(). (The behavior of the base implementation is the same, so no behavior change there). This also adds a test for QWindow event handling without Qts event loop is running. This is a black box test, just to ensure that basic functionality is working. It can be extended later. Task-number: QTBUG-45956 Change-Id: I7d688c0c6dec5f133fb495f07526debdde5389af Reviewed-by: Jørgen Lind --- .../windows/qwindowsguieventdispatcher.cpp | 4 +- tests/auto/gui/kernel/kernel.pro | 2 + .../kernel/noqteventloop/noqteventloop.pro | 8 + .../noqteventloop/tst_noqteventloop.cpp | 271 ++++++++++++++++++ 4 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 tests/auto/gui/kernel/noqteventloop/noqteventloop.pro create mode 100644 tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp index 0dd2facd4d..0bfa0239aa 100644 --- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp +++ b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp @@ -67,18 +67,20 @@ QWindowsGuiEventDispatcher::QWindowsGuiEventDispatcher(QObject *parent) : bool QWindowsGuiEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) { + const QEventLoop::ProcessEventsFlags oldFlags = m_flags; m_flags = flags; if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled()) qCDebug(lcQpaEvents) << '>' << __FUNCTION__ << objectName() << flags; const bool rc = QEventDispatcherWin32::processEvents(flags); if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled()) qCDebug(lcQpaEvents) << '<' << __FUNCTION__ << "returns" << rc; + m_flags = oldFlags; return rc; } void QWindowsGuiEventDispatcher::sendPostedEvents() { - QCoreApplication::sendPostedEvents(); + QEventDispatcherWin32::sendPostedEvents(); QWindowSystemInterface::sendWindowSystemEvents(m_flags); } diff --git a/tests/auto/gui/kernel/kernel.pro b/tests/auto/gui/kernel/kernel.pro index 7d47a4167d..b03a117f83 100644 --- a/tests/auto/gui/kernel/kernel.pro +++ b/tests/auto/gui/kernel/kernel.pro @@ -24,6 +24,8 @@ SUBDIRS=\ qopenglwindow \ qrasterwindow +win32:!wince*:!winrt: SUBDIRS += noqteventloop + !qtHaveModule(widgets): SUBDIRS -= \ qmouseevent_modal \ qtouchevent diff --git a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro new file mode 100644 index 0000000000..de5715e147 --- /dev/null +++ b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro @@ -0,0 +1,8 @@ +CONFIG += testcase +TARGET = tst_noqteventloop + +QT += core-private gui-private testlib + +SOURCES += tst_noqteventloop.cpp + +contains(QT_CONFIG,dynamicgl):win32:!wince*:!winrt: LIBS += -luser32 diff --git a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp new file mode 100644 index 0000000000..d21569dcc0 --- /dev/null +++ b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 + +#include +#include +#include + +#include + +class tst_NoQtEventLoop : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void cleanup(); + void consumeMouseEvents(); + +}; + +void tst_NoQtEventLoop::initTestCase() +{ +} + +void tst_NoQtEventLoop::cleanup() +{ +} + +class Window : public QWindow +{ +public: + Window(QWindow *parentWindow = 0) : QWindow(parentWindow) + { + } + + void reset() + { + m_received.clear(); + } + + bool event(QEvent *event) + { + m_received[event->type()]++; + return QWindow::event(event); + } + + int received(QEvent::Type type) + { + return m_received.value(type, 0); + } + + + QHash m_received; +}; + +bool g_exit = false; + +extern "C" LRESULT QT_WIN_CALLBACK wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message == WM_SHOWWINDOW && wParam == 0) + g_exit = true; + return DefWindowProc(hwnd, message, wParam, lParam); +} + +class TestThread : public QThread +{ + Q_OBJECT +public: + TestThread(HWND parentWnd, Window *childWindow) : QThread(), m_hwnd(parentWnd), m_childWindow(childWindow) { + m_screenW = ::GetSystemMetrics(SM_CXSCREEN); + m_screenH = ::GetSystemMetrics(SM_CYSCREEN); + } + + enum { + MouseClick, + MouseMove + }; + + void mouseInput(int command, const QPoint &p = QPoint()) + { + INPUT mouseEvent; + mouseEvent.type = INPUT_MOUSE; + MOUSEINPUT &mi = mouseEvent.mi; + mi.mouseData = 0; + mi.time = 0; + mi.dwExtraInfo = 0; + mi.dx = 0; + mi.dy = 0; + switch (command) { + case MouseClick: + mi.dwFlags = MOUSEEVENTF_LEFTDOWN; + ::SendInput(1, &mouseEvent, sizeof(INPUT)); + ::Sleep(50); + mi.dwFlags = MOUSEEVENTF_LEFTUP; + ::SendInput(1, &mouseEvent, sizeof(INPUT)); + break; + case MouseMove: + mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; + mi.dx = p.x() * 65536 / m_screenW; + mi.dy = p.y() * 65536 / m_screenH; + ::SendInput(1, &mouseEvent, sizeof(INPUT)); + break; + } + } + + void mouseClick() + { + mouseInput(MouseClick); + } + + void mouseMove(const QPoint &pt) + { + mouseInput(MouseMove, pt); + } + + + void run() { + struct ScopedCleanup + { + /* This is in order to ensure that the window is hidden when returning from run(), + regardless of the return point (e.g. with QTRY_COMPARE) */ + ScopedCleanup(HWND hwnd) : m_hwnd(hwnd) { } + ~ScopedCleanup() { + ::ShowWindow(m_hwnd, SW_HIDE); + } + HWND m_hwnd; + } cleanup(m_hwnd); + + m_testPassed = false; + POINT pt; + pt.x = 0; + pt.y = 0; + if (!::ClientToScreen(m_hwnd, &pt)) + return; + m_windowPos = QPoint(pt.x, pt.y); + + + // First activate the parent window (which will also activate the child window) + m_windowPos += QPoint(5,5); + mouseMove(m_windowPos); + ::Sleep(150); + mouseClick(); + + + + // At this point the windows are activated, no further events will be send to the QWindow + // if we click on the native parent HWND + m_childWindow->reset(); + ::Sleep(150); + mouseClick(); + ::Sleep(150); + + QTRY_COMPARE(m_childWindow->received(QEvent::MouseButtonPress) + m_childWindow->received(QEvent::MouseButtonRelease), 0); + + // Now click in the QWindow. The QWindow should receive those events. + m_windowPos.ry() += 50; + mouseMove(m_windowPos); + ::Sleep(150); + mouseClick(); + QTRY_COMPARE(m_childWindow->received(QEvent::MouseButtonPress), 1); + QTRY_COMPARE(m_childWindow->received(QEvent::MouseButtonRelease), 1); + + m_testPassed = true; + + // ScopedCleanup will hide the window here + // Once the native window is hidden, it will exit the event loop. + } + + bool passed() const { return m_testPassed; } + +private: + int m_screenW; + int m_screenH; + bool m_testPassed; + HWND m_hwnd; + Window *m_childWindow; + QPoint m_windowPos; + +}; + + +void tst_NoQtEventLoop::consumeMouseEvents() +{ + int argc = 1; + char *argv[] = {const_cast("test")}; + QGuiApplication app(argc, argv); + QString clsName(QStringLiteral("tst_NoQtEventLoop_WINDOW")); + const HINSTANCE appInstance = (HINSTANCE)GetModuleHandle(0); + WNDCLASSEX wc; + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_DBLCLKS | CS_OWNDC; // CS_SAVEBITS + wc.lpfnWndProc = wndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = appInstance; + wc.hIcon = 0; + wc.hIconSm = 0; + wc.hCursor = 0; + wc.hbrBackground = ::GetSysColorBrush(COLOR_BTNFACE /*COLOR_WINDOW*/); + wc.lpszMenuName = 0; + wc.lpszClassName = (wchar_t*)clsName.utf16(); + + ATOM atom = ::RegisterClassEx(&wc); + QVERIFY2(atom, "RegisterClassEx failed"); + + DWORD dwExStyle = WS_EX_APPWINDOW; + DWORD dwStyle = WS_CAPTION | WS_HSCROLL | WS_TABSTOP | WS_VISIBLE; + + HWND mainWnd = ::CreateWindowEx(dwExStyle, (wchar_t*)clsName.utf16(), TEXT("tst_NoQtEventLoop"), dwStyle, 100, 100, 300, 300, 0, NULL, appInstance, NULL); + QVERIFY2(mainWnd, "CreateWindowEx failed"); + + ::ShowWindow(mainWnd, SW_SHOW); + + Window *childWindow = new Window; + childWindow->setParent(QWindow::fromWinId((WId)mainWnd)); + childWindow->setGeometry(0, 50, 200, 200); + childWindow->show(); + + TestThread *testThread = new TestThread(mainWnd, childWindow); + connect(testThread, SIGNAL(finished()), testThread, SLOT(deleteLater())); + testThread->start(); + + // Our own message loop... + MSG msg; + while (::GetMessage(&msg, NULL, 0, 0) > 0) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + if (g_exit) + break; + } + + QCOMPARE(testThread->passed(), true); + +} + +#include + +QTEST_APPLESS_MAIN(tst_NoQtEventLoop) + From fee16baca1e1db441c1d95952373aa324f704990 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Tue, 11 Aug 2015 14:13:51 +0200 Subject: [PATCH 008/240] Another fix of cosmetic QPainter::drawPolyline() At the edge of the view, a line segment could end up as not producing any pixels even if not clipped by the floating-point clip routine. Make sure the starting point for the next line is still updated correctly for any significant segment lengths. Change-Id: I381a4efb81ce6006f3da4c67abf279aea79e4663 Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qcosmeticstroker.cpp | 3 ++- tests/auto/gui/painting/qpainter/tst_qpainter.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index 8fb5f4fd3f..e9fada10a5 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -719,10 +719,11 @@ static inline void capAdjust(int caps, int &x1, int &x2, int &y, int yinc) template static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps) { + bool didDraw = qAbs(rx2 - rx1) + qAbs(ry2 - ry1) >= 1.0; + if (stroker->clipLine(rx1, ry1, rx2, ry2)) return true; - bool didDraw = false; const int half = stroker->legacyRounding ? 31 : 0; int x1 = toF26Dot6(rx1) + half; int y1 = toF26Dot6(ry1) + half; diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 6582755aec..752ab0fd8c 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -4885,6 +4885,7 @@ void tst_QPainter::drawPolyline_data() QTest::newRow("basic") << (QVector() << QPointF(10, 10) << QPointF(20, 10) << QPointF(20, 20) << QPointF(10, 20)); QTest::newRow("clipped") << (QVector() << QPoint(-10, 100) << QPoint(-1, 100) << QPoint(-1, -2) << QPoint(100, -2) << QPoint(100, 40)); // QTBUG-31579 QTest::newRow("shortsegment") << (QVector() << QPoint(20, 100) << QPoint(20, 99) << QPoint(21, 99) << QPoint(21, 104)); // QTBUG-42398 + QTest::newRow("edge") << (QVector() << QPointF(4.5, 121.6) << QPointF(9.4, 150.9) << QPointF(14.2, 184.8) << QPointF(19.1, 130.4)); } void tst_QPainter::drawPolyline() @@ -4894,7 +4895,7 @@ void tst_QPainter::drawPolyline() for (int r = 0; r < 2; r++) { images[r] = QImage(150, 150, QImage::Format_ARGB32); - images[r].fill(Qt::transparent); + images[r].fill(Qt::white); QPainter p(images + r); QPen pen(Qt::red, 0, Qt::SolidLine, Qt::FlatCap); p.setPen(pen); From b4ed054e2f6b4c460f64c33b61b8800dc78f9e6d Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Tue, 18 Aug 2015 14:06:07 +0200 Subject: [PATCH 009/240] PPM image format: avoid useless processing on truncated files For ascii formatted files, the handler would not stop processing on a premature EOF, but instead continue to fill the whole image memory area byte by byte. This could lead to unexpected CPU exhaustion in the case of a small image file declaring huge image dimensions, but having no content. Instead, check for EOF for each scanline and quit processing if found. Change-Id: I8dbcd7eb34553873e49706d61b5752f22e04eb6a Reviewed-by: Lars Knoll --- src/gui/image/qppmhandler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp index 0f4256b740..f460431c2b 100644 --- a/src/gui/image/qppmhandler.cpp +++ b/src/gui/image/qppmhandler.cpp @@ -182,7 +182,8 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q } else { // read ascii data uchar *p; int n; - for (y=0; ypeek(&buf, 1) == 1); y++) { p = outImage->scanLine(y); n = pbm_bpl; if (nbits == 1) { From 06be9f026f042f994d7c3548a331babca8d03545 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 19 Aug 2015 14:36:07 +0200 Subject: [PATCH 010/240] iOS: send key events through QPA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far we have chosen to send key events directly to the focus object since we do already do that for IM events. But Qt expects key events (especially control keys) to be sendt through QPA. This means that key events can end up somewhere else than at the focus object, which is expected and needed if shortcut propagation is to work. Change-Id: I160bf3309572719eda352cdb11b46c4b5a455e0d Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index be9c3b9e27..68364d3c77 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -324,10 +324,8 @@ - (void)sendKeyPressRelease:(Qt::Key)key modifiers:(Qt::KeyboardModifiers)modifiers { - QKeyEvent press(QEvent::KeyPress, key, modifiers); - QKeyEvent release(QEvent::KeyRelease, key, modifiers); - [self sendEventToFocusObject:press]; - [self sendEventToFocusObject:release]; + QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyPress, key, modifiers); + QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyRelease, key, modifiers); } - (void)cut:(id)sender @@ -711,10 +709,10 @@ - (void)deleteBackward { - // Since we're posting im events directly to the focus object, we should do the - // same for key events. Otherwise they might end up in a different place or out - // of sync with im events. + // UITextInput selects the text to be deleted before calling this method. To avoid + // drawing the selection, we flush after posting the key press/release. [self sendKeyPressRelease:Qt::Key_Backspace modifiers:Qt::NoModifier]; + QWindowSystemInterface::flushWindowSystemEvents(); } @end From 82538aebe4b22978a6f7735924f5451304c3e2a8 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 17 Aug 2015 12:36:14 +0200 Subject: [PATCH 011/240] iOS: send arrow keys to Qt to handle cursor movement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Controlling cursor position through input methods in Qt is very limited. You cannot e.g move the cursor vertically, or select text that spans several paragraphs. The reason for the latter is that Qt works with input methods on a per-paragraph basis, which effectively locks UIKit to only being able to move the cursor and select text within a single paragraph. Fixing up input methods to support more advanced navigation means changing the whole design (working on a whole document, instead of per paragraph), and is out of scope. Instead we choose to listen for arrow keys and forward them to Qt in the same fashing as we already do for backspace and enter. This will make the iOS port on-par with the other platforms, which also sends control characters like these on the side of IM events. Note that registering shortcuts and overriding default IM navigation behavior will only take effect when a hardware keyboard is connected. Only then will [UIresponder keyCommands] be called from UIKit. Change-Id: I634205e0578447c4aa6e9fdff342ee3b281901ea Reviewed-by: Tor Arne Vestbø --- .../platforms/ios/qiostextresponder.mm | 65 +++++++++++++++++++ src/plugins/platforms/ios/qiostheme.mm | 2 + 2 files changed, 67 insertions(+) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 68364d3c77..d16ad40414 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -328,6 +328,8 @@ QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyRelease, key, modifiers); } +#ifndef QT_NO_SHORTCUT + - (void)cut:(id)sender { Q_UNUSED(sender); @@ -360,6 +362,69 @@ // ------------------------------------------------------------------------- +- (void)keyCommandTriggered:(UIKeyCommand *)keyCommand +{ + Qt::Key key = Qt::Key_unknown; + Qt::KeyboardModifiers modifiers = Qt::NoModifier; + + if (keyCommand.input == UIKeyInputLeftArrow) + key = Qt::Key_Left; + else if (keyCommand.input == UIKeyInputRightArrow) + key = Qt::Key_Right; + else if (keyCommand.input == UIKeyInputUpArrow) + key = Qt::Key_Up; + else if (keyCommand.input == UIKeyInputDownArrow) + key = Qt::Key_Down; + else + Q_UNREACHABLE(); + + if (keyCommand.modifierFlags & UIKeyModifierAlternate) + modifiers |= Qt::AltModifier; + if (keyCommand.modifierFlags & UIKeyModifierShift) + modifiers |= Qt::ShiftModifier; + if (keyCommand.modifierFlags & UIKeyModifierCommand) + modifiers |= Qt::ControlModifier; + + [self sendKeyPressRelease:key modifiers:modifiers]; +} + +- (void)addKeyCommandsToArray:(NSMutableArray *)array key:(NSString *)key +{ + SEL s = @selector(keyCommandTriggered:); + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:0 action:s]]; + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierShift action:s]]; + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierAlternate action:s]]; + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierAlternate|UIKeyModifierShift action:s]]; + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierCommand action:s]]; + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierCommand|UIKeyModifierShift action:s]]; +} + +- (NSArray *)keyCommands +{ + // Since keyCommands is called for every key + // press/release, we cache the result + static dispatch_once_t once; + static NSMutableArray *array; + + dispatch_once(&once, ^{ + // We let Qt move the cursor around when the arrow keys are being used. This + // is normally implemented through UITextInput, but since IM in Qt have poor + // support for moving the cursor vertically, and even less support for selecting + // text across multiple paragraphs, we do this through key events. + array = [NSMutableArray new]; + [self addKeyCommandsToArray:array key:UIKeyInputUpArrow]; + [self addKeyCommandsToArray:array key:UIKeyInputDownArrow]; + [self addKeyCommandsToArray:array key:UIKeyInputLeftArrow]; + [self addKeyCommandsToArray:array key:UIKeyInputRightArrow]; + }); + + return array; +} + +#endif // QT_NO_SHORTCUT + +// ------------------------------------------------------------------------- + - (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties { // As documented, we should not report textWillChange/textDidChange unless the text diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm index edeabf66dc..bc40069670 100644 --- a/src/plugins/platforms/ios/qiostheme.mm +++ b/src/plugins/platforms/ios/qiostheme.mm @@ -107,6 +107,8 @@ QVariant QIOSTheme::themeHint(ThemeHint hint) const switch (hint) { case QPlatformTheme::StyleNames: return QStringList(QStringLiteral("fusion")); + case KeyboardScheme: + return QVariant(int(MacKeyboardScheme)); default: return QPlatformTheme::themeHint(hint); } From dbb24ce477702768534d64b260e269d2abc13e41 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 18 Aug 2015 15:21:30 +0200 Subject: [PATCH 012/240] iOS: listen for standard text edit shortcuts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Catch the missing shortcuts sent by UIKit, and forward them to Qt as key events so that the app can respond to them. Change-Id: If63c4b05466e64843982fce32fbd594d2a0ef312 Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index d16ad40414..fdcc703267 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -360,6 +360,24 @@ [self sendKeyPressRelease:Qt::Key_Delete modifiers:Qt::ControlModifier]; } +- (void)toggleBoldface:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_B modifiers:Qt::ControlModifier]; +} + +- (void)toggleItalics:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_I modifiers:Qt::ControlModifier]; +} + +- (void)toggleUnderline:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_U modifiers:Qt::ControlModifier]; +} + // ------------------------------------------------------------------------- - (void)keyCommandTriggered:(UIKeyCommand *)keyCommand From af5b62844ca62bf30b47a8ecc9ed1f8b24dbff3c Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 21 Aug 2015 15:39:35 +0200 Subject: [PATCH 013/240] iOS: add undo/redo support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable the undo/redo buttons on the keyboard, as well as the Cmd-Z/Cmd-Shift-Z shortcuts. For UIKit to support this, we need to add undo actions to first responders undo manager. Since we don't know if Qt has anything to undo/redo, we just enable the shortcuts all the time. To do that, we trick NSUndoManager to always have both an undo operation and a redo operation in the stack. Change-Id: I3294a962cc24f56585e7e515856142f3dda56d0a Reviewed-by: Tor Arne Vestbø --- .../platforms/ios/qiostextresponder.mm | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index fdcc703267..624411ebbc 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -209,6 +209,9 @@ if (UIView *accessoryView = static_cast(platformData.value(kImePlatformDataInputAccessoryView).value())) self.inputAccessoryView = [[[WrapperView alloc] initWithView:accessoryView] autorelease]; + self.undoManager.groupsByEvent = NO; + [self rebuildUndoStack]; + return self; } @@ -380,6 +383,56 @@ // ------------------------------------------------------------------------- +- (void)undo +{ + [self sendKeyPressRelease:Qt::Key_Z modifiers:Qt::ControlModifier]; + [self rebuildUndoStack]; +} + +- (void)redo +{ + [self sendKeyPressRelease:Qt::Key_Z modifiers:Qt::ControlModifier|Qt::ShiftModifier]; + [self rebuildUndoStack]; +} + +- (void)registerRedo +{ + NSUndoManager *undoMgr = self.undoManager; + [undoMgr beginUndoGrouping]; + [undoMgr registerUndoWithTarget:self selector:@selector(redo) object:nil]; + [undoMgr endUndoGrouping]; +} + +- (void)rebuildUndoStack +{ + dispatch_async(dispatch_get_main_queue (), ^{ + // Register dummy undo/redo operations to enable Cmd-Z and Cmd-Shift-Z + // Ensure we do this outside any undo/redo callback since NSUndoManager + // will treat registerUndoWithTarget as registering a redo when called + // from within a undo callback. + NSUndoManager *undoMgr = self.undoManager; + [undoMgr removeAllActions]; + [undoMgr beginUndoGrouping]; + [undoMgr registerUndoWithTarget:self selector:@selector(undo) object:nil]; + [undoMgr endUndoGrouping]; + + // Schedule an operation that we immediately pop off to be able to schedule a redo + [undoMgr beginUndoGrouping]; + [undoMgr registerUndoWithTarget:self selector:@selector(registerRedo) object:nil]; + [undoMgr endUndoGrouping]; + [undoMgr undo]; + + // Note that, perhaps because of a bug in UIKit, the buttons on the shortcuts bar ends up + // disabled if a undo/redo callback doesn't lead to a [UITextInputDelegate textDidChange]. + // And we only call that method if Qt made changes to the text. The effect is that the buttons + // become disabled when there is nothing more to undo (Qt didn't change anything upon receiving + // an undo request). This seems to be OK behavior, so we let it stay like that unless it shows + // to cause problems. + }); +} + +// ------------------------------------------------------------------------- + - (void)keyCommandTriggered:(UIKeyCommand *)keyCommand { Qt::Key key = Qt::Key_unknown; From 163158bf4f79bb6719ac3c39547ea31acc1cb506 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 28 Aug 2015 11:41:57 +0200 Subject: [PATCH 014/240] iOS: store shortcut sequence in menu item MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I4c99516fb98ce0da84b8690cc4c1fd71c0db9dca Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosmenu.h | 3 ++- src/plugins/platforms/ios/qiosmenu.mm | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/ios/qiosmenu.h b/src/plugins/platforms/ios/qiosmenu.h index 4fa0416df7..5bebcc3cc6 100644 --- a/src/plugins/platforms/ios/qiosmenu.h +++ b/src/plugins/platforms/ios/qiosmenu.h @@ -62,7 +62,7 @@ public: void setRole(MenuRole role) Q_DECL_OVERRIDE; void setCheckable(bool) Q_DECL_OVERRIDE {} void setChecked(bool) Q_DECL_OVERRIDE {} - void setShortcut(const QKeySequence&) Q_DECL_OVERRIDE {} + void setShortcut(const QKeySequence&) Q_DECL_OVERRIDE; void setEnabled(bool enabled) Q_DECL_OVERRIDE; void setIconSize(int) Q_DECL_OVERRIDE {} @@ -73,6 +73,7 @@ public: bool m_enabled; bool m_separator; QIOSMenu *m_menu; + QKeySequence m_shortcut; private: QString removeMnemonics(const QString &original); diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm index 08fc8a5e9c..9936296ae8 100644 --- a/src/plugins/platforms/ios/qiosmenu.mm +++ b/src/plugins/platforms/ios/qiosmenu.mm @@ -277,6 +277,11 @@ void QIOSMenuItem::setRole(QPlatformMenuItem::MenuRole role) m_role = role; } +void QIOSMenuItem::setShortcut(const QKeySequence &sequence) +{ + m_shortcut = sequence; +} + void QIOSMenuItem::setEnabled(bool enabled) { m_enabled = enabled; From b494d859a7fc18ac3e6d9a57194c1ac7dc1855ab Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 28 Aug 2015 10:57:44 +0200 Subject: [PATCH 015/240] iOS: filter first responder actions from edit menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UIResponderStandardEditActions found in first responder will be prepended to the edit menu automatically (or e.g made available as buttons on the virtual keyboard). So we filter them out to avoid duplicates, and let first responder handle the actions instead. In case of QIOSTextResponder, edit actions will be converted to key events that ends up triggering the shortcuts of the filtered menu items. Change-Id: I046c6cc5b358d8a6f7623e10579e2dcd92f75139 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosmenu.h | 1 + src/plugins/platforms/ios/qiosmenu.mm | 32 ++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/ios/qiosmenu.h b/src/plugins/platforms/ios/qiosmenu.h index 5bebcc3cc6..ec23b55507 100644 --- a/src/plugins/platforms/ios/qiosmenu.h +++ b/src/plugins/platforms/ios/qiosmenu.h @@ -135,6 +135,7 @@ private: void toggleShowUsingUIMenuController(bool show); void toggleShowUsingUIPickerView(bool show); QIOSMenuItemList visibleMenuItems() const; + QIOSMenuItemList filterFirstResponderActions(const QIOSMenuItemList &menuItems); void repositionMenu(); }; diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm index 9936296ae8..de77097bf8 100644 --- a/src/plugins/platforms/ios/qiosmenu.mm +++ b/src/plugins/platforms/ios/qiosmenu.mm @@ -474,7 +474,7 @@ void QIOSMenu::toggleShowUsingUIMenuController(bool show) { if (show) { Q_ASSERT(!m_menuController); - m_menuController = [[QUIMenuController alloc] initWithVisibleMenuItems:visibleMenuItems()]; + m_menuController = [[QUIMenuController alloc] initWithVisibleMenuItems:filterFirstResponderActions(visibleMenuItems())]; repositionMenu(); connect(qGuiApp->inputMethod(), &QInputMethod::keyboardRectangleChanged, this, &QIOSMenu::repositionMenu); } else { @@ -547,6 +547,36 @@ QIOSMenuItemList QIOSMenu::visibleMenuItems() const return visibleMenuItems; } +QIOSMenuItemList QIOSMenu::filterFirstResponderActions(const QIOSMenuItemList &menuItems) +{ + // UIResponderStandardEditActions found in first responder will be prepended to the edit + // menu automatically (or e.g made available as buttons on the virtual keyboard). So we + // filter them out to avoid duplicates, and let first responder handle the actions instead. + // In case of QIOSTextResponder, edit actions will be converted to key events that ends up + // triggering the shortcuts of the filtered menu items. + QIOSMenuItemList filteredMenuItems; + UIResponder *responder = [UIResponder currentFirstResponder]; + + for (int i = 0; i < menuItems.count(); ++i) { + QIOSMenuItem *menuItem = menuItems.at(i); + QKeySequence shortcut = menuItem->m_shortcut; + if ((shortcut == QKeySequence::Cut && [responder canPerformAction:@selector(cut:) withSender:nil]) + || (shortcut == QKeySequence::Copy && [responder canPerformAction:@selector(copy:) withSender:nil]) + || (shortcut == QKeySequence::Paste && [responder canPerformAction:@selector(paste:) withSender:nil]) + || (shortcut == QKeySequence::Delete && [responder canPerformAction:@selector(delete:) withSender:nil]) + || (shortcut == QKeySequence::SelectAll && [responder canPerformAction:@selector(selectAll:) withSender:nil]) + || (shortcut == QKeySequence::Undo && [responder canPerformAction:@selector(undo:) withSender:nil]) + || (shortcut == QKeySequence::Redo && [responder canPerformAction:@selector(redo:) withSender:nil]) + || (shortcut == QKeySequence::Bold && [responder canPerformAction:@selector(toggleBoldface:) withSender:nil]) + || (shortcut == QKeySequence::Italic && [responder canPerformAction:@selector(toggleItalics:) withSender:nil]) + || (shortcut == QKeySequence::Underline && [responder canPerformAction:@selector(toggleUnderline:) withSender:nil])) { + continue; + } + filteredMenuItems.append(menuItem); + } + return filteredMenuItems; +} + void QIOSMenu::repositionMenu() { switch (m_effectiveMenuType) { From 97b525e3bee99d8c5bb6ae3819c82d5144c08f1d Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 27 Aug 2015 10:31:06 +0200 Subject: [PATCH 016/240] Doc: Improve documentation for QAuthenticator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make it explicit what 'isNull()' is really about. and mention which data type is in the QVariant stored in the options. Fix the links to the Options section in the summary: So far they where pointing to the options() method. Fix capitalization and trailing dots. Change-Id: I030c0a273e784b28d642ae40b28e36b0d406c920 Reviewed-by: Topi Reiniö --- src/network/kernel/qauthenticator.cpp | 39 +++++++++++++++------------ 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index abb47e9e29..d626d0bcfc 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -85,6 +85,7 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& \li Digest-MD5 \endlist + \target qauthenticator-options \section1 Options In addition to the username and password required for authentication, a @@ -104,8 +105,8 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& \section2 Basic \table - \header \li Option \li Direction \li Description - \row \li \tt{realm} \li Incoming \li Contains the realm of the authentication, the same as realm() + \header \li Option \li Direction \li Type \li Description + \row \li \tt{realm} \li Incoming \li QString \li Contains the realm of the authentication, the same as realm() \endtable The Basic authentication mechanism supports no outgoing options. @@ -119,8 +120,8 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& \section2 Digest-MD5 \table - \header \li Option \li Direction \li Description - \row \li \tt{realm} \li Incoming \li Contains the realm of the authentication, the same as realm() + \header \li Option \li Direction \li Type \li Description + \row \li \tt{realm} \li Incoming \li QString \li Contains the realm of the authentication, the same as realm() \endtable The Digest-MD5 authentication mechanism supports no outgoing options. @@ -130,7 +131,7 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& /*! - Constructs an empty authentication object + Constructs an empty authentication object. */ QAuthenticator::QAuthenticator() : d(0) @@ -138,7 +139,7 @@ QAuthenticator::QAuthenticator() } /*! - Destructs the object + Destructs the object. */ QAuthenticator::~QAuthenticator() { @@ -207,7 +208,7 @@ bool QAuthenticator::operator==(const QAuthenticator &other) const */ /*! - returns the user used for authentication. + Returns the user used for authentication. */ QString QAuthenticator::user() const { @@ -227,7 +228,7 @@ void QAuthenticator::setUser(const QString &user) } /*! - returns the password used for authentication. + Returns the password used for authentication. */ QString QAuthenticator::password() const { @@ -260,7 +261,7 @@ void QAuthenticator::detach() } /*! - returns the realm requiring authentication. + Returns the realm requiring authentication. */ QString QAuthenticator::realm() const { @@ -279,10 +280,11 @@ void QAuthenticator::setRealm(const QString &realm) /*! \since 4.7 Returns the value related to option \a opt if it was set by the server. - See \l{QAuthenticator#Options} for more information on incoming options. + See the \l{QAuthenticator#qauthenticator-options}{Options section} for + more information on incoming options. If option \a opt isn't found, an invalid QVariant will be returned. - \sa options(), QAuthenticator#Options + \sa options(), {QAuthenticator#qauthenticator-options}{QAuthenticator options} */ QVariant QAuthenticator::option(const QString &opt) const { @@ -292,10 +294,10 @@ QVariant QAuthenticator::option(const QString &opt) const /*! \since 4.7 Returns all incoming options set in this QAuthenticator object by parsing - the server reply. See \l{QAuthenticator#Options} for more information - on incoming options. + the server reply. See the \l{QAuthenticator#qauthenticator-options}{Options section} + for more information on incoming options. - \sa option(), QAuthenticator#Options + \sa option(), {QAuthenticator#qauthenticator-options}{QAuthenticator options} */ QVariantHash QAuthenticator::options() const { @@ -306,9 +308,9 @@ QVariantHash QAuthenticator::options() const \since 4.7 Sets the outgoing option \a opt to value \a value. - See \l{QAuthenticator#Options} for more information on outgoing options. + See the \l{QAuthenticator#qauthenticator-options}{Options section} for more information on outgoing options. - \sa options(), option(), QAuthenticator#Options + \sa options(), option(), {QAuthenticator#qauthenticator-options}{QAuthenticator options} */ void QAuthenticator::setOption(const QString &opt, const QVariant &value) { @@ -318,7 +320,10 @@ void QAuthenticator::setOption(const QString &opt, const QVariant &value) /*! - Returns \c true if the authenticator is null. + Returns \c true if the object has not been initialized. Returns + \c false if non-const member functions have been called, or + the content was constructed or copied from another initialized + QAuthenticator object. */ bool QAuthenticator::isNull() const { From 21e1354d42d1bb3967dedb62facc684a8ab702ce Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 3 Aug 2015 12:59:01 +0200 Subject: [PATCH 017/240] iOS: handle all directions when calculating positionFromPosition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The method is currently a bit buggy, since it does not take UITextLayoutDirectionUp and UITextLayoutDirectionDown into account. This patch is mostly for fixing something "just in case", since we so far have not seen UIKit calling this method for those directions unless a hardware keyboard is connected. And in that case, we anyway override IM navigation by dealing with the arrow keys explicit. Since IM in Qt does not support getting the position above or below the current position, we just return the current position, making it a no-op. Change-Id: I4bcb9e2a00ab4e3d785058d7ff7f4855142dabbc Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 624411ebbc..685ff8ff47 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -652,7 +652,17 @@ - (UITextPosition *)positionFromPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset { int p = static_cast(position).index; - return [QUITextPosition positionWithIndex:(direction == UITextLayoutDirectionRight ? p + offset : p - offset)]; + + switch (direction) { + case UITextLayoutDirectionLeft: + return [QUITextPosition positionWithIndex:p - offset]; + case UITextLayoutDirectionRight: + return [QUITextPosition positionWithIndex:p + offset]; + default: + // Qt doesn't support getting the position above or below the current position, so + // for those cases we just return the current position, making it a no-op. + return position; + } } - (UITextPosition *)positionWithinRange:(UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction From b39c9011db62f154d255edeba9242463ad58e570 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 20 Aug 2015 17:12:14 +0200 Subject: [PATCH 018/240] QDBusPlatformMenu and Item: remove stored pointers when deleted Prevents memory leak and later access of dangling pointers. Change-Id: I6a1da1ec191ad5fa880c5884c37fd5582215e825 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/platformsupport/dbusmenu/qdbusplatformmenu.cpp | 6 ++++++ src/platformsupport/dbusmenu/qdbusplatformmenu_p.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp index a64e107e71..1dd2b462ed 100644 --- a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp +++ b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp @@ -59,6 +59,11 @@ QDBusPlatformMenuItem::QDBusPlatformMenuItem(quintptr tag) menuItemsByID.insert(m_dbusID, this); } +QDBusPlatformMenuItem::~QDBusPlatformMenuItem() +{ + menuItemsByID.remove(m_dbusID); +} + void QDBusPlatformMenuItem::setTag(quintptr tag) { m_tag = tag; @@ -155,6 +160,7 @@ QDBusPlatformMenu::QDBusPlatformMenu(quintptr tag) QDBusPlatformMenu::~QDBusPlatformMenu() { menusByID.remove(m_dbusID); + m_topLevelMenus.removeOne(this); } void QDBusPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) diff --git a/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h b/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h index 16bb4f195c..fdad7990e9 100644 --- a/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h +++ b/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h @@ -57,6 +57,7 @@ class QDBusPlatformMenuItem : public QPlatformMenuItem public: QDBusPlatformMenuItem(quintptr tag = 0LL); + ~QDBusPlatformMenuItem(); quintptr tag()const Q_DECL_OVERRIDE { return m_tag; } void setTag(quintptr tag) Q_DECL_OVERRIDE; From 6f9e845d9b02ed2becaab4af837535173dad2068 Mon Sep 17 00:00:00 2001 From: Alexander Soplyakov Date: Wed, 26 Aug 2015 13:58:10 +0300 Subject: [PATCH 019/240] Make tooltips transparent for mouse events. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This behavior is important because controls (widgets) under tooltips don't receive mouse events and don't update their state if it is really needed. [ChangeLog][QtWidgets][Important behavior changes] Tooltips on OS X are now transparent for mouse events. Change-Id: I06403db7b66c87fe53debb033f8a74aa1c93e26a Task-number: QTBUG-46379 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index f27335d752..1ec33df744 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -704,8 +704,12 @@ QT_WARNING_POP // Popups implicitly grap mouse events; forward to the active popup if there is one if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) { - if (QNSView *popupView = popup->qtView()) - targetView = popupView; + // Tooltips must be transparent for mouse events + // The bug reference is QTBUG-46379 + if (!popup->m_windowFlags.testFlag(Qt::ToolTip)) { + if (QNSView *popupView = popup->qtView()) + targetView = popupView; + } } [targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; From 111ee58c065602bfcde520b54f44809d854e73f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 18 Aug 2015 11:39:01 +0200 Subject: [PATCH 020/240] Prevent QGestureManager crash. Use QPointer to prevent dereferencing stale pointers stored in m_gestureTargets. Add null pointer tests in addition to the Q_ASSERTs on the pointers returned by m_gestureTargets.value(). The intention is to assert in debug mode but keep going in release mode. Change-Id: Icdef8cc02040bddc88f4bcb268e9ca0ac252557d Task-number: QTBUG-46264 Reviewed-by: Pawel Kurdybacha Reviewed-by: Gabriel de Dietrich --- src/widgets/kernel/qgesturemanager.cpp | 5 ++++- src/widgets/kernel/qgesturemanager_p.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index b5d3a56d3f..8b918a72a2 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -405,6 +405,8 @@ void QGestureManager::cancelGesturesForChildren(QGesture *original) Q_ASSERT(original); QWidget *originatingWidget = m_gestureTargets.value(original); Q_ASSERT(originatingWidget); + if (!originatingWidget) + return; // iterate over all active gestures and all maybe gestures // for each find the owner @@ -565,7 +567,8 @@ void QGestureManager::getGestureTargets(const QSet &gestures, foreach (QGesture *gesture, gestures) { QWidget *receiver = m_gestureTargets.value(gesture, 0); Q_ASSERT(receiver); - gestureByTypes[gesture->gestureType()].insert(receiver, gesture); + if (receiver) + gestureByTypes[gesture->gestureType()].insert(receiver, gesture); } // for each gesture type diff --git a/src/widgets/kernel/qgesturemanager_p.h b/src/widgets/kernel/qgesturemanager_p.h index 8ba253d17e..4e349ac731 100644 --- a/src/widgets/kernel/qgesturemanager_p.h +++ b/src/widgets/kernel/qgesturemanager_p.h @@ -117,7 +117,7 @@ private: QHash m_gestureToRecognizer; QHash m_gestureOwners; - QHash m_gestureTargets; + QHash > m_gestureTargets; int m_lastCustomGestureId; From 055cbaafd6c48ddfd00f918006c0a2ffe3a72f81 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 23 Jun 2015 12:59:34 +0200 Subject: [PATCH 021/240] Fixed connectToHost connectToHost is not meant to be synchronous, but waitForWrite is used internally to wait for the connection to be established. Thus the same logic that is used in the callback has to be applied in there. Task-number: QTBUG-46339 Change-Id: Ia1fb5c1ae609a9942ff4d8fe2f5fab2ef572da0c Reviewed-by: Andrew Knight --- .../socket/qnativesocketengine_winrt.cpp | 72 ++++++++++++------- .../socket/qnativesocketengine_winrt_p.h | 3 +- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 5e58ee3895..faea132b86 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -285,23 +285,11 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) return false; } d->socketState = QAbstractSocket::ConnectingState; - hr = QWinRTFunctions::await(d->connectOp); - RETURN_FALSE_IF_FAILED("Connection could not be established"); - bool connectionErrors = false; - d->handleConnectionErrors(d->connectOp.Get(), &connectionErrors); - if (connectionErrors) - return false; - d->connectOp.Reset(); + hr = d->connectOp->put_Completed(Callback( + d, &QNativeSocketEnginePrivate::handleConnectToHost).Get()); + Q_ASSERT_SUCCEEDED(hr); - d->socketState = QAbstractSocket::ConnectedState; - emit connectionReady(); - - // Delay the reader so that the SSL socket can upgrade - if (d->sslSocket) - connect(d->sslSocket, SIGNAL(encrypted()), SLOT(establishRead())); - else - establishRead(); - return true; + return d->socketState == QAbstractSocket::ConnectedState; } bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) @@ -687,6 +675,14 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut) { Q_UNUSED(msecs); Q_UNUSED(timedOut); + Q_D(QNativeSocketEngine); + if (d->socketState == QAbstractSocket::ConnectingState) { + HRESULT hr = QWinRTFunctions::await(d->connectOp, QWinRTFunctions::ProcessMainThreadEvents); + if (SUCCEEDED(hr)) { + d->handleConnectionEstablished(d->connectOp.Get()); + return true; + } + } return false; } @@ -727,7 +723,6 @@ void QNativeSocketEngine::setWriteNotificationEnabled(bool enable) if (bytesToWrite()) return; // will be emitted as a result of bytes written writeNotification(); - d->notifyOnWrite = false; } } @@ -1116,10 +1111,19 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener return S_OK; } -void QNativeSocketEnginePrivate::handleConnectionErrors(IAsyncAction *connectAction, bool *errorsOccured) +HRESULT QNativeSocketEnginePrivate::handleConnectToHost(IAsyncAction *action, AsyncStatus) { - bool error = true; - HRESULT hr = connectAction->GetResults(); + handleConnectionEstablished(action); + return S_OK; +} + +void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *action) +{ + Q_Q(QNativeSocketEngine); + if (wasDeleted || !connectOp) // Protect against a late callback + return; + + 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); @@ -1137,13 +1141,29 @@ void QNativeSocketEnginePrivate::handleConnectionErrors(IAsyncAction *connectAct if (FAILED(hr)) { setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString); socketState = QAbstractSocket::UnconnectedState; - } else { - error = false; } break; } - if (errorsOccured) - *errorsOccured = error; + + // The callback might be triggered several times if we do not cancel/reset it here + if (connectOp) { + ComPtr info; + connectOp.As(&info); + if (info) { + info->Cancel(); + info->Close(); + } + connectOp.Reset(); + } + + socketState = QAbstractSocket::ConnectedState; + emit q->connectionReady(); + + // 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(); } HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) @@ -1163,7 +1183,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async hr = buffer->get_Length(&bufferLength); Q_ASSERT_SUCCEEDED(hr); if (!bufferLength) { - if (q->isReadNotificationEnabled()) + if (notifyOnRead) emit q->readReady(); return S_OK; } @@ -1187,7 +1207,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async readBytes.seek(readPos); readMutex.unlock(); - if (q->isReadNotificationEnabled()) + if (notifyOnRead) emit q->readReady(); ComPtr stream; diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index eb032bc977..8e8448e6a8 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -216,7 +216,8 @@ private: ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args); HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); - void handleConnectionErrors(ABI::Windows::Foundation::IAsyncAction *connectAction, bool *errorsOccured); + HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); + void handleConnectionEstablished(ABI::Windows::Foundation::IAsyncAction *action); HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress *asyncInfo, ABI::Windows::Foundation::AsyncStatus); }; From d8130786b68b2b4188f6c0b7ad285899e1cbe778 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Fri, 31 Jul 2015 14:54:38 +0200 Subject: [PATCH 022/240] WinRT: Do not try to read from TCP inputstream in case of UDP Change-Id: I2cdf0f4c7642c420ccec0a3f6e05a1c5bc7da020 Reviewed-by: Samuel Nevala Reviewed-by: Andrew Knight --- src/network/socket/qnativesocketengine_winrt.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index faea132b86..a22bf61cb8 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -1159,6 +1159,9 @@ void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *actio socketState = QAbstractSocket::ConnectedState; emit q->connectionReady(); + if (socketType != QAbstractSocket::TcpSocket) + return; + // Delay the reader so that the SSL socket can upgrade if (sslSocket) QObject::connect(qobject_cast(sslSocket), &QSslSocket::encrypted, q, &QNativeSocketEngine::establishRead); From 1840cc982a3a8882728b586f8924c74a7b79767f Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Fri, 31 Jul 2015 14:55:14 +0200 Subject: [PATCH 023/240] WinRT: Unregister callbacks when socket engine is destroyed Change-Id: I66e8fff2556ce23a66db1148bdb68e9a448227b2 Reviewed-by: Andrew Knight --- src/network/socket/qnativesocketengine_winrt.cpp | 14 ++++++++++---- src/network/socket/qnativesocketengine_winrt_p.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index a22bf61cb8..378a539411 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -318,8 +318,7 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) return false; } - EventRegistrationToken token; - d->tcpListener->add_ConnectionReceived(Callback(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &token); + d->tcpListener->add_ConnectionReceived(Callback(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &d->connectionToken); hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); if (FAILED(hr)) { qErrnoWarning(hr, "Unable to bind socket."); // ### Set error message @@ -779,9 +778,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc qWarning("Failed to create stream socket"); return false; } - EventRegistrationToken token; socketDescriptor = qintptr(socket.Detach()); - udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &token); + udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); break; } default: @@ -807,11 +805,19 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() , closingDown(false) , socketDescriptor(-1) , sslSocket(Q_NULLPTR) + , connectionToken( { -1 } ) { } QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate() { + if (socketDescriptor == -1 || connectionToken.value == -1) + return; + + if (socketType == QAbstractSocket::UdpSocket) + udpSocket()->remove_MessageReceived(connectionToken); + else if (socketType == QAbstractSocket::TcpSocket) + tcpListener->remove_ConnectionReceived(connectionToken); } void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index 8e8448e6a8..79e1a3391e 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -210,6 +210,7 @@ private: QList currentConnections; QEventLoop eventLoop; QAbstractSocket *sslSocket; + EventRegistrationToken connectionToken; HRESULT handleBindCompleted(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket, From fbd0e4489c936394a55f8084af2aab4ef2456360 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 28 Aug 2015 10:34:43 +0200 Subject: [PATCH 024/240] Copy the state to the picture paintengine when updating the state When the state of the paint changes then the one used for the picture paintengine needs to be kept in sync. Otherwise the rendering will be incorrect. Task-number: QTBUG-43145 Change-Id: Ia55a4e940d109bedb7c2eff4d985d3b212da75a4 Reviewed-by: Lars Knoll --- src/printsupport/kernel/qpaintengine_alpha.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/printsupport/kernel/qpaintengine_alpha.cpp b/src/printsupport/kernel/qpaintengine_alpha.cpp index 010a628e4f..a81f3eae43 100644 --- a/src/printsupport/kernel/qpaintengine_alpha.cpp +++ b/src/printsupport/kernel/qpaintengine_alpha.cpp @@ -146,8 +146,16 @@ void QAlphaPaintEngine::updateState(const QPaintEngineState &state) d->m_hasalpha = d->m_alphaOpacity || d->m_alphaBrush || d->m_alphaPen; - if (d->m_picengine) + if (d->m_picengine) { + const QPainter *p = painter(); + d->m_picpainter->setPen(p->pen()); + d->m_picpainter->setBrush(p->brush()); + d->m_picpainter->setBrushOrigin(p->brushOrigin()); + d->m_picpainter->setFont(p->font()); + d->m_picpainter->setOpacity(p->opacity()); + d->m_picpainter->setTransform(p->combinedTransform()); d->m_picengine->updateState(state); + } } void QAlphaPaintEngine::drawPath(const QPainterPath &path) From 97de58db672fe0489faba856fcfd59a125609796 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Fri, 21 Aug 2015 12:43:36 +0200 Subject: [PATCH 025/240] Doc: Added link to Declarative State Machine Framework Added link in C++ documentation Task-number: QTBUG-46285 Change-Id: I0f330829f7df713d4f5292b2a300c5c9d3732bda Reviewed-by: Venugopal Shivashankar --- src/corelib/doc/qtcore.qdocconf | 3 +-- src/corelib/doc/src/statemachine.qdoc | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf index 502689e4c2..3d64708def 100644 --- a/src/corelib/doc/qtcore.qdocconf +++ b/src/corelib/doc/qtcore.qdocconf @@ -25,8 +25,7 @@ qhp.QtCore.subprojects.classes.sortPages = true tagfile = ../../../doc/qtcore/qtcore.tags -depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras -# depends += qtqml # Qt namespace collides with QtQml::Qt, see QTBUG-38630 +depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras qtqml headerdirs += .. diff --git a/src/corelib/doc/src/statemachine.qdoc b/src/corelib/doc/src/statemachine.qdoc index e44a603959..d50851d816 100644 --- a/src/corelib/doc/src/statemachine.qdoc +++ b/src/corelib/doc/src/statemachine.qdoc @@ -71,6 +71,8 @@ which are currently active. All the states in a valid configuration of the state machine will have a common ancestor. + \sa {The Declarative State Machine Framework} + \section1 Classes in the State Machine Framework These classes are provided by qt for creating event-driven state machines. From dfb55da5d67c21179ccef107351a90be2815e1e2 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Thu, 3 Sep 2015 14:40:21 +0200 Subject: [PATCH 026/240] Doc: Added enums in qnamespace.qdoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-43810 Change-Id: Ib756382833fabecaae2526a413d046646f3e443e Reviewed-by: Topi Reiniö Reviewed-by: Martin Smith --- src/corelib/global/qnamespace.qdoc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index c6098007d1..2323ee2cb0 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -1695,6 +1695,17 @@ \value Key_Sleep \value Key_Zoom \value Key_Cancel + \value Key_MicVolumeUp + \value Key_Find + \value Key_Open + \value Key_MicVolumeDown + \value Key_New + \value Key_Settings + \value Key_Redo + \value Key_Exit + \value Key_Info + \value Key_Undo + \value Key_Guide \sa QKeyEvent::key() */ From 9588e1bba348acf9aa0d023ebb5195aa1bf69909 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Tue, 7 Jul 2015 15:29:05 +0200 Subject: [PATCH 027/240] Doc: Corrected link issues in qtbase Task-number: QTBUG-43810 Change-Id: I0a019becc53b222cb6a7df1fafdccd57aca5b598 Reviewed-by: Martin Smith --- qmake/doc/src/qmake-manual.qdoc | 3 +-- src/corelib/io/qtextstream.cpp | 2 +- src/corelib/kernel/qmetaobject.cpp | 5 +++-- src/gui/doc/qtgui.qdocconf | 3 ++- src/gui/image/qimage.cpp | 2 +- src/gui/image/qimagereader.cpp | 2 +- src/gui/math3d/qmatrix4x4.cpp | 2 -- src/network/doc/qtnetwork.qdocconf | 2 +- src/network/ssl/qsslellipticcurve.cpp | 5 ++--- src/network/ssl/qsslpresharedkeyauthenticator.cpp | 2 -- src/opengl/doc/qtopengl.qdocconf | 2 +- src/sql/doc/qtsql.qdocconf | 2 +- src/tools/qdoc/doc/examples/examples.qdoc | 5 ++--- src/widgets/doc/qtwidgets.qdocconf | 2 +- src/xml/doc/qtxml.qdocconf | 2 +- 15 files changed, 18 insertions(+), 23 deletions(-) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index a2afeaf765..ccb8d95973 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -728,8 +728,7 @@ \section2 Creating and Moving Xcode Projects Developers on OS X can take advantage of the qmake support for Xcode - project files, as described in - \l{Qt is OS X Native#Development Tools}{Qt is OS X Native}, + project files, as described in \l{Additional Command-Line Options}, by running qmake to generate an Xcode project from an existing qmake project file. For example: diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index 8ad1c2852c..aa14f545ec 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -2858,7 +2858,7 @@ QTextStream &endl(QTextStream &stream) /*! \relates QTextStream - Calls \l{QTextStream::flush()}{flush()} on \a stream and returns \a stream. + Calls QTextStream::flush() on \a stream and returns \a stream. \sa endl(), reset(), {QTextStream manipulators} */ diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 6858209b12..1ef5ee0547 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1548,12 +1548,13 @@ bool QMetaObject::invokeMethod(QObject *obj, /*! \fn QMetaObject::Connection &QMetaObject::Connection::operator=(Connection &&other) - Move-assigns \a other to this object. + Move-assigns \a other to this object, and returns a reference. */ /*! \fn QMetaObject::Connection::Connection(Connection &&o) - Move-constructs a Connection instance, making it point to the same object that \a o was pointing to. + Move-constructs a Connection instance, making it point to the same object + that \a o was pointing to. */ /*! diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf index e2194839d2..436e2e0b34 100644 --- a/src/gui/doc/qtgui.qdocconf +++ b/src/gui/doc/qtgui.qdocconf @@ -37,7 +37,8 @@ depends += \ qtqml \ qtquick \ qtwidgets \ - qtdoc + qtdoc \ + qmake headerdirs += .. diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 176cdfe09f..c4691b5f5e 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -313,7 +313,7 @@ bool QImageData::checkForAlphaPixels() const sharing}. QImage objects can also be streamed and compared. \note If you would like to load QImage objects in a static build of Qt, - refer to the \l{How To Create Qt Plugins}{Plugin HowTo}. + refer to the \l{How to Create Qt Plugins}{Plugin HowTo}. \warning Painting on a QImage with the format QImage::Format_Indexed8 is not supported. diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index ba79bf40e5..a35442308f 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1170,7 +1170,7 @@ QImageIOHandler::Transformations QImageReader::transformation() const Sets if images returned by read() should have transformation metadata automatically applied. - \sa autoTransform(), transform(), read() + \sa autoTransform(), transformation(), read() */ void QImageReader::setAutoTransform(bool enabled) { diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index eb7c7f4b7a..9d363dc895 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -148,8 +148,6 @@ QMatrix4x4::QMatrix4x4(const float *values) top-most 4 rows of \a matrix. If \a matrix has less than 4 columns or rows, the remaining elements are filled with elements from the identity matrix. - - \sa QMatrix4x4(const QGenericMatrix &) */ /*! diff --git a/src/network/doc/qtnetwork.qdocconf b/src/network/doc/qtnetwork.qdocconf index 522d71fd27..2a8e577dda 100644 --- a/src/network/doc/qtnetwork.qdocconf +++ b/src/network/doc/qtnetwork.qdocconf @@ -26,7 +26,7 @@ qhp.QtNetwork.subprojects.classes.sortPages = true tagfile = ../../../doc/qtnetwork/qtnetwork.tags -depends += qtcore qtgui qtdoc +depends += qtcore qtgui qtdoc qmake headerdirs += .. diff --git a/src/network/ssl/qsslellipticcurve.cpp b/src/network/ssl/qsslellipticcurve.cpp index a16f726429..b4396d567b 100644 --- a/src/network/ssl/qsslellipticcurve.cpp +++ b/src/network/ssl/qsslellipticcurve.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE elliptic-curve cipher algorithms. Elliptic curves can be constructed from a "short name" (SN) (fromShortName()), - and by a call to QSslSocket::supportedEllipticCurves(). + and by a call to QSslConfiguration::supportedEllipticCurves(). QSslEllipticCurve instances can be compared for equality and can be used as keys in QHash and QSet. They cannot be used as key in a QMap. @@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE Constructs an invalid elliptic curve. - \sa isValid(), QSslSocket::supportedEllipticCurves() + \sa isValid(), QSslConfiguration::supportedEllipticCurves() */ /*! @@ -136,7 +136,6 @@ QT_BEGIN_NAMESPACE \relates QSslEllipticCurve Returns true if the curve \a lhs represents the same curve of \a rhs; - false otherwise. */ /*! diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.cpp b/src/network/ssl/qsslpresharedkeyauthenticator.cpp index 4a3b1aa807..ab78aea1cd 100644 --- a/src/network/ssl/qsslpresharedkeyauthenticator.cpp +++ b/src/network/ssl/qsslpresharedkeyauthenticator.cpp @@ -257,7 +257,6 @@ int QSslPreSharedKeyAuthenticator::maximumPreSharedKeyLength() const identity hint, identity, pre shared key, maximum length for the identity and maximum length for the pre shared key. - \sa operator!=(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs) */ bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs) { @@ -277,7 +276,6 @@ bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKey Returns true if the authenticator object \a lhs is different than \a rhs; false otherwise. - \sa operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs) */ QT_END_NAMESPACE diff --git a/src/opengl/doc/qtopengl.qdocconf b/src/opengl/doc/qtopengl.qdocconf index 5b6d09dfcd..6ff6cae2cb 100644 --- a/src/opengl/doc/qtopengl.qdocconf +++ b/src/opengl/doc/qtopengl.qdocconf @@ -19,7 +19,7 @@ exampledirs += ../../../examples/opengl \ imagedirs += images \ ../../../examples/opengl/doc/images -depends += qtdoc qtcore qtgui qtwidgets +depends += qtdoc qtcore qtgui qtwidgets qmake examplesinstallpath = opengl diff --git a/src/sql/doc/qtsql.qdocconf b/src/sql/doc/qtsql.qdocconf index b8632c5260..5a224adeb9 100644 --- a/src/sql/doc/qtsql.qdocconf +++ b/src/sql/doc/qtsql.qdocconf @@ -25,7 +25,7 @@ qhp.QtSql.subprojects.classes.selectors = class fake:headerfile qhp.QtSql.subprojects.classes.sortPages = true tagfile = ../../../doc/qtsql/qtsql.tags -depends += qtcore qtwidgets qtdoc +depends += qtcore qtwidgets qtdoc qmake headerdirs += .. diff --git a/src/tools/qdoc/doc/examples/examples.qdoc b/src/tools/qdoc/doc/examples/examples.qdoc index 777c869c65..28810e30da 100644 --- a/src/tools/qdoc/doc/examples/examples.qdoc +++ b/src/tools/qdoc/doc/examples/examples.qdoc @@ -90,9 +90,8 @@ \brief Basic set of UI components This is a listing of a list of UI components implemented by QML types. These - - files are available for general import and they are based off the \l{Qt - Quick Code Samples}. + files are available for general import and they are based on the + \l{Qt Quick Examples and Tutorials}{Qt Quick Code Samples}. This module is part of the \l{componentset}{UIComponents} example. */ diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf index 1f79d144bf..f307e9d3e4 100644 --- a/src/widgets/doc/qtwidgets.qdocconf +++ b/src/widgets/doc/qtwidgets.qdocconf @@ -26,7 +26,7 @@ qhp.QtWidgets.subprojects.classes.sortPages = true tagfile = ../../../doc/qtwidgets/qtwidgets.tags -depends += qtcore qtgui qtdoc qtsql qtdesigner qtquick +depends += qtcore qtgui qtdoc qtsql qtdesigner qtquick qmake qtsvg headerdirs += .. diff --git a/src/xml/doc/qtxml.qdocconf b/src/xml/doc/qtxml.qdocconf index 419859ac8b..a23915487f 100644 --- a/src/xml/doc/qtxml.qdocconf +++ b/src/xml/doc/qtxml.qdocconf @@ -26,7 +26,7 @@ qhp.QtXml.subprojects.classes.sortPages = true tagfile = ../../../doc/qtxml/qtxml.tags -depends += qtcore qtnetwork qtdoc qtwidgets +depends += qtcore qtnetwork qtdoc qtwidgets qmake headerdirs += .. From 5919edc5231f58d2d7c04ea875064a368f0df254 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Thu, 3 Sep 2015 15:52:55 +0300 Subject: [PATCH 028/240] forkfd: fix _POSIX_SPAWN feature check Change-Id: Ia44edbac3a1bd2da92ee8c92956abfe49d8763b8 Reviewed-by: Thiago Macieira --- src/3rdparty/forkfd/forkfd.c | 2 +- src/3rdparty/forkfd/forkfd.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index a61198a954..55dc92fe45 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -648,7 +648,7 @@ err_free: } #endif // FORKFD_NO_FORKFD -#if defined(_POSIX_SPAWN) && !defined(FORKFD_NO_SPAWNFD) +#if _POSIX_SPAWN > 0 && !defined(FORKFD_NO_SPAWNFD) int spawnfd(int flags, pid_t *ppid, const char *path, const posix_spawn_file_actions_t *file_actions, posix_spawnattr_t *attrp, char *const argv[], char *const envp[]) { diff --git a/src/3rdparty/forkfd/forkfd.h b/src/3rdparty/forkfd/forkfd.h index dcb36f9f33..38858c00fe 100644 --- a/src/3rdparty/forkfd/forkfd.h +++ b/src/3rdparty/forkfd/forkfd.h @@ -29,7 +29,7 @@ #include #include // to get the POSIX flags -#ifdef _POSIX_SPAWN +#if _POSIX_SPAWN > 0 # include #endif @@ -51,7 +51,7 @@ int forkfd(int flags, pid_t *ppid); int forkfd_wait(int ffd, forkfd_info *info, struct rusage *rusage); int forkfd_close(int ffd); -#ifdef _POSIX_SPAWN +#if _POSIX_SPAWN > 0 /* only for spawnfd: */ # define FFD_SPAWN_SEARCH_PATH O_RDWR From ee8c09f7c219ae9b55194408ba854f81b8086cb0 Mon Sep 17 00:00:00 2001 From: David Faure Date: Fri, 31 Jul 2015 14:16:53 +0200 Subject: [PATCH 029/240] qprintdialog_unix: small optimization, no need to extract a substring Change-Id: Ie5fdfd6aa3866c14b6fbfabf4533327f5c73c5a3 Reviewed-by: Friedemann Kleint Reviewed-by: Frederik Gladhorn Reviewed-by: Marc Mutz --- src/printsupport/dialogs/qprintdialog_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp index 502ff7d98a..880b233aef 100644 --- a/src/printsupport/dialogs/qprintdialog_unix.cpp +++ b/src/printsupport/dialogs/qprintdialog_unix.cpp @@ -805,7 +805,7 @@ void QUnixPrintWidgetPrivate::applyPrinterProperties() home += QLatin1Char('/'); if (!cur.isEmpty() && cur.at(cur.length()-1) != QLatin1Char('/')) cur += QLatin1Char('/'); - if (cur.left(home.length()) != home) + if (!cur.startsWith(home)) cur = home; if (QGuiApplication::platformName() == QLatin1String("xcb")) { if (printer->docName().isEmpty()) { From 69e1b1de935511e5513fb002e2df96ac08e433f6 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Mon, 17 Aug 2015 13:01:09 +0200 Subject: [PATCH 030/240] Doc: System Tray Icon example Moved from qtsvg to qtbase Task-number: QTBUG-47201 Change-Id: Iab185ea2e270893c0937d1ff87fdb544d226d603 Reviewed-by: Martin Smith --- .../systray/doc/images/systemtray-editor.png | Bin 0 -> 18147 bytes .../systray/doc/images/systemtray-example.png | Bin 0 -> 47588 bytes .../desktop/systray/doc/src/systray.qdoc | 183 ++++++++++++++++++ 3 files changed, 183 insertions(+) create mode 100644 examples/widgets/desktop/systray/doc/images/systemtray-editor.png create mode 100644 examples/widgets/desktop/systray/doc/images/systemtray-example.png create mode 100644 examples/widgets/desktop/systray/doc/src/systray.qdoc diff --git a/examples/widgets/desktop/systray/doc/images/systemtray-editor.png b/examples/widgets/desktop/systray/doc/images/systemtray-editor.png new file mode 100644 index 0000000000000000000000000000000000000000..fb15dea8cb56f6e2d3f8be214e8de05df3735b7e GIT binary patch literal 18147 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�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 Date: Fri, 28 Aug 2015 15:46:07 +0200 Subject: [PATCH 031/240] iOS: compose key events from QKeySequences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of hard-coding the key and modifier that should trigger a shortcut, we read it out from the QKeySequence that corresponds to a StandardKey instead. Change-Id: I6325534d3ff91c788d7e660d9009954e437b8534 Reviewed-by: Tor Arne Vestbø --- .../platforms/ios/qiostextresponder.mm | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 685ff8ff47..4e109f6921 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -333,65 +333,73 @@ #ifndef QT_NO_SHORTCUT +- (void)sendShortcut:(QKeySequence::StandardKey)standardKey +{ + const int keys = QKeySequence(standardKey)[0]; + Qt::Key key = Qt::Key(keys & 0x0000FFFF); + Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(keys & 0xFFFF0000); + [self sendKeyPressRelease:key modifiers:modifiers]; +} + - (void)cut:(id)sender { Q_UNUSED(sender); - [self sendKeyPressRelease:Qt::Key_X modifiers:Qt::ControlModifier]; + [self sendShortcut:QKeySequence::Cut]; } - (void)copy:(id)sender { Q_UNUSED(sender); - [self sendKeyPressRelease:Qt::Key_C modifiers:Qt::ControlModifier]; + [self sendShortcut:QKeySequence::Copy]; } - (void)paste:(id)sender { Q_UNUSED(sender); - [self sendKeyPressRelease:Qt::Key_V modifiers:Qt::ControlModifier]; + [self sendShortcut:QKeySequence::Paste]; } - (void)selectAll:(id)sender { Q_UNUSED(sender); - [self sendKeyPressRelease:Qt::Key_A modifiers:Qt::ControlModifier]; + [self sendShortcut:QKeySequence::SelectAll]; } - (void)delete:(id)sender { Q_UNUSED(sender); - [self sendKeyPressRelease:Qt::Key_Delete modifiers:Qt::ControlModifier]; + [self sendShortcut:QKeySequence::Delete]; } - (void)toggleBoldface:(id)sender { Q_UNUSED(sender); - [self sendKeyPressRelease:Qt::Key_B modifiers:Qt::ControlModifier]; + [self sendShortcut:QKeySequence::Bold]; } - (void)toggleItalics:(id)sender { Q_UNUSED(sender); - [self sendKeyPressRelease:Qt::Key_I modifiers:Qt::ControlModifier]; + [self sendShortcut:QKeySequence::Italic]; } - (void)toggleUnderline:(id)sender { Q_UNUSED(sender); - [self sendKeyPressRelease:Qt::Key_U modifiers:Qt::ControlModifier]; + [self sendShortcut:QKeySequence::Underline]; } // ------------------------------------------------------------------------- - (void)undo { - [self sendKeyPressRelease:Qt::Key_Z modifiers:Qt::ControlModifier]; + [self sendShortcut:QKeySequence::Undo]; [self rebuildUndoStack]; } - (void)redo { - [self sendKeyPressRelease:Qt::Key_Z modifiers:Qt::ControlModifier|Qt::ShiftModifier]; + [self sendShortcut:QKeySequence::Redo]; [self rebuildUndoStack]; } From feff56827b86ff00930a903944afe913a926a9a1 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 1 Sep 2015 13:06:07 +0200 Subject: [PATCH 032/240] iOS: filter responder actions from menu sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow up from b494d85. We need to filter the responder actions after a sync as well, otherwise they will be added back if a menu item e.g changes text. Change-Id: I2ecbcc292400ada97a8e29d4b97f087349d8a061 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosmenu.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm index de77097bf8..09395805bf 100644 --- a/src/plugins/platforms/ios/qiosmenu.mm +++ b/src/plugins/platforms/ios/qiosmenu.mm @@ -369,7 +369,7 @@ void QIOSMenu::syncMenuItem(QPlatformMenuItem *) switch (m_effectiveMenuType) { case EditMenu: - [m_menuController setVisibleMenuItems:visibleMenuItems()]; + [m_menuController setVisibleMenuItems:filterFirstResponderActions(visibleMenuItems())]; break; default: [m_pickerView setVisibleMenuItems:visibleMenuItems() selectItem:m_targetItem]; From 1a0384cb15f7a2194341ec4b102948fa9337f5cf Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Sun, 16 Aug 2015 15:09:51 +0100 Subject: [PATCH 033/240] Support device pixel ratio in QWidget graphic effects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ie20bd30328ae353ace82fbeee5808546f0568703 Reviewed-by: Christoph Cullmann Reviewed-by: Morten Johan Sørvig --- src/widgets/kernel/qwidget.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index ba0fcf75d0..49da4d1faf 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -5828,7 +5828,10 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * pixmapOffset -= effectRect.topLeft(); - QPixmap pixmap(effectRect.size()); + const qreal dpr = context->painter->device()->devicePixelRatio(); + QPixmap pixmap(effectRect.size() * dpr); + pixmap.setDevicePixelRatio(dpr); + pixmap.fill(Qt::transparent); m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren); return pixmap; From 880a8aa7e99bb91e7a815cadde72bb5230c815ea Mon Sep 17 00:00:00 2001 From: David Faure Date: Wed, 26 Aug 2015 13:27:49 +0200 Subject: [PATCH 034/240] QMimeType: add KDAB copyright to the code I contributed a lot to. Change-Id: I794259f28c7adbaad3cfb40f92a0ad2dc512e5b4 Reviewed-by: Thiago Macieira --- src/corelib/mimetypes/qmimedatabase.cpp | 1 + src/corelib/mimetypes/qmimedatabase.h | 1 + src/corelib/mimetypes/qmimedatabase_p.h | 1 + src/corelib/mimetypes/qmimeprovider.cpp | 1 + src/corelib/mimetypes/qmimeprovider_p.h | 1 + src/corelib/mimetypes/qmimetype.cpp | 1 + src/corelib/mimetypes/qmimetype.h | 1 + 7 files changed, 7 insertions(+) diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index bec7a79e8f..1ef890c46a 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimedatabase.h b/src/corelib/mimetypes/qmimedatabase.h index 912d9b8443..fd19636e27 100644 --- a/src/corelib/mimetypes/qmimedatabase.h +++ b/src/corelib/mimetypes/qmimedatabase.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h index e3cfe3443f..aa86f607c6 100644 --- a/src/corelib/mimetypes/qmimedatabase_p.h +++ b/src/corelib/mimetypes/qmimedatabase_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 887db51e5c..d26bfd0848 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h index eaf95942f7..c0517d69a4 100644 --- a/src/corelib/mimetypes/qmimeprovider_p.h +++ b/src/corelib/mimetypes/qmimeprovider_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp index a5f9cb70d5..5398f9358e 100644 --- a/src/corelib/mimetypes/qmimetype.cpp +++ b/src/corelib/mimetypes/qmimetype.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimetype.h b/src/corelib/mimetypes/qmimetype.h index 4ba3c53470..13184905b8 100644 --- a/src/corelib/mimetypes/qmimetype.h +++ b/src/corelib/mimetypes/qmimetype.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. From 5e41f4137dd42a9a639be8743ae95c8e159bd4e0 Mon Sep 17 00:00:00 2001 From: David Faure Date: Tue, 25 Aug 2015 14:30:07 +0200 Subject: [PATCH 035/240] QMimeDatabase: warn instead of asserting on bad magic. An invalid mime magic definition could lead to an assert. Replaced with a qWarning. Move all checking to the QMimeMagicRule constructor, and do keep invalid rules since they are need to parse child rules. Unit test added, with QTest::ignoreMessage when using the XML backend (there's no warning from update-mime-database when using the cache). Also make it easier to add more shared mime info files for tests. Task-number: QTBUG-44319 Done-with: Eike Ziller Change-Id: Ie39a160a106b650cdcee88778fa7eff9e932a988 Reviewed-by: Thiago Macieira --- src/corelib/mimetypes/qmimemagicrule.cpp | 68 +++++++++++--- src/corelib/mimetypes/qmimemagicrule_p.h | 3 +- src/corelib/mimetypes/qmimetypeparser.cpp | 40 ++------ src/corelib/mimetypes/qmimetypeparser_p.h | 2 + .../qmimedatabase/invalid-magic1.xml | 9 ++ .../qmimedatabase/invalid-magic2.xml | 9 ++ .../qmimedatabase/invalid-magic3.xml | 9 ++ .../mimetypes/qmimedatabase/testdata.qrc | 3 + .../qmimedatabase/tst_qmimedatabase.cpp | 92 ++++++++++++------- .../qmimedatabase/tst_qmimedatabase.h | 6 +- 10 files changed, 159 insertions(+), 82 deletions(-) create mode 100644 tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic1.xml create mode 100644 tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic2.xml create mode 100644 tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic3.xml diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp index c8508ac0d2..6a3a429179 100644 --- a/src/corelib/mimetypes/qmimemagicrule.cpp +++ b/src/corelib/mimetypes/qmimemagicrule.cpp @@ -38,6 +38,7 @@ #ifndef QT_NO_MIMETYPE +#include "qmimetypeparser_p.h" #include #include #include @@ -231,26 +232,53 @@ static inline QByteArray makePattern(const QByteArray &value) return pattern; } -QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType, +// Evaluate a magic match rule like +// +// + +QMimeMagicRule::QMimeMagicRule(const QString &typeStr, const QByteArray &theValue, - int theStartPos, - int theEndPos, - const QByteArray &theMask) : + const QString &offsets, + const QByteArray &theMask, + QString *errorString) : d(new QMimeMagicRulePrivate) { - Q_ASSERT(!theValue.isEmpty()); - - d->type = theType; d->value = theValue; - d->startPos = theStartPos; - d->endPos = theEndPos; d->mask = theMask; d->matchFunction = 0; + d->type = QMimeMagicRule::type(typeStr.toLatin1()); + if (d->type == Invalid) { + *errorString = QStringLiteral("Type %s is not supported").arg(typeStr); + } + + // Parse for offset as "1" or "1:10" + const int colonIndex = offsets.indexOf(QLatin1Char(':')); + const QString startPosStr = colonIndex == -1 ? offsets : offsets.mid(0, colonIndex); + const QString endPosStr = colonIndex == -1 ? offsets : offsets.mid(colonIndex + 1); + if (!QMimeTypeParserBase::parseNumber(startPosStr, &d->startPos, errorString) || + !QMimeTypeParserBase::parseNumber(endPosStr, &d->endPos, errorString)) { + d->type = Invalid; + return; + } + + if (d->value.isEmpty()) { + d->type = Invalid; + if (errorString) + *errorString = QLatin1String("Invalid empty magic rule value"); + return; + } + if (d->type >= Host16 && d->type <= Byte) { bool ok; d->number = d->value.toUInt(&ok, 0); // autodetect - Q_ASSERT(ok); + if (!ok) { + d->type = Invalid; + if (errorString) + *errorString = QString::fromLatin1("Invalid magic rule value \"%1\"").arg( + QString::fromLatin1(d->value)); + return; + } d->numberMask = !d->mask.isEmpty() ? d->mask.toUInt(&ok, 0) : 0; // autodetect } @@ -259,9 +287,23 @@ QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType, d->pattern = makePattern(d->value); d->pattern.squeeze(); if (!d->mask.isEmpty()) { - Q_ASSERT(d->mask.size() >= 4 && d->mask.startsWith("0x")); - d->mask = QByteArray::fromHex(QByteArray::fromRawData(d->mask.constData() + 2, d->mask.size() - 2)); - Q_ASSERT(d->mask.size() == d->pattern.size()); + if (d->mask.size() < 4 || !d->mask.startsWith("0x")) { + d->type = Invalid; + if (errorString) + *errorString = QString::fromLatin1("Invalid magic rule mask \"%1\"").arg( + QString::fromLatin1(d->mask)); + return; + } + const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData( + d->mask.constData() + 2, d->mask.size() - 2)); + if (tempMask.size() != d->pattern.size()) { + d->type = Invalid; + if (errorString) + *errorString = QString::fromLatin1("Invalid magic rule mask size \"%1\"").arg( + QString::fromLatin1(d->mask)); + return; + } + d->mask = tempMask; } else { d->mask.fill(char(-1), d->pattern.size()); } diff --git a/src/corelib/mimetypes/qmimemagicrule_p.h b/src/corelib/mimetypes/qmimemagicrule_p.h index 03ac1d1de9..6b64bfcc10 100644 --- a/src/corelib/mimetypes/qmimemagicrule_p.h +++ b/src/corelib/mimetypes/qmimemagicrule_p.h @@ -61,7 +61,8 @@ class QMimeMagicRule public: enum Type { Invalid = 0, String, Host16, Host32, Big16, Big32, Little16, Little32, Byte }; - QMimeMagicRule(Type type, const QByteArray &value, int startPos, int endPos, const QByteArray &mask = QByteArray()); + QMimeMagicRule(const QString &typeStr, const QByteArray &value, const QString &offsets, + const QByteArray &mask, QString *errorString); QMimeMagicRule(const QMimeMagicRule &other); ~QMimeMagicRule(); diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp index 9610162c4f..8a8b97655a 100644 --- a/src/corelib/mimetypes/qmimetypeparser.cpp +++ b/src/corelib/mimetypes/qmimetypeparser.cpp @@ -153,8 +153,8 @@ QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState curren return ParseError; } -// Parse int number from an (attribute) string) -static bool parseNumber(const QString &n, int *target, QString *errorMessage) +// Parse int number from an (attribute) string +bool QMimeTypeParserBase::parseNumber(const QString &n, int *target, QString *errorMessage) { bool ok; *target = n.toInt(&ok); @@ -165,37 +165,14 @@ static bool parseNumber(const QString &n, int *target, QString *errorMessage) return true; } -// Evaluate a magic match rule like -// -// #ifndef QT_NO_XMLSTREAMREADER -static bool createMagicMatchRule(const QXmlStreamAttributes &atts, - QString *errorMessage, QMimeMagicRule *&rule) +static QMimeMagicRule *createMagicMatchRule(const QXmlStreamAttributes &atts, QString *errorMessage) { const QString type = atts.value(QLatin1String(matchTypeAttributeC)).toString(); - QMimeMagicRule::Type magicType = QMimeMagicRule::type(type.toLatin1()); - if (magicType == QMimeMagicRule::Invalid) { - qWarning("%s: match type %s is not supported.", Q_FUNC_INFO, type.toUtf8().constData()); - return true; - } const QString value = atts.value(QLatin1String(matchValueAttributeC)).toString(); - if (value.isEmpty()) { - *errorMessage = QString::fromLatin1("Empty match value detected."); - return false; - } - // Parse for offset as "1" or "1:10" - int startPos, endPos; - const QString offsetS = atts.value(QLatin1String(matchOffsetAttributeC)).toString(); - const int colonIndex = offsetS.indexOf(QLatin1Char(':')); - const QString startPosS = colonIndex == -1 ? offsetS : offsetS.mid(0, colonIndex); - const QString endPosS = colonIndex == -1 ? offsetS : offsetS.mid(colonIndex + 1); - if (!parseNumber(startPosS, &startPos, errorMessage) || !parseNumber(endPosS, &endPos, errorMessage)) - return false; + const QString offsets = atts.value(QLatin1String(matchOffsetAttributeC)).toString(); const QString mask = atts.value(QLatin1String(matchMaskAttributeC)).toString(); - - rule = new QMimeMagicRule(magicType, value.toUtf8(), startPos, endPos, mask.toLatin1()); - - return true; + return new QMimeMagicRule(type, value.toUtf8(), offsets, mask.toLatin1(), errorMessage); } #endif @@ -283,9 +260,10 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString } break; case ParseMagicMatchRule: { - QMimeMagicRule *rule = 0; - if (!createMagicMatchRule(atts, errorMessage, rule)) - return false; + QString magicErrorMessage; + QMimeMagicRule *rule = createMagicMatchRule(atts, &magicErrorMessage); + if (!rule->isValid()) + qWarning("QMimeDatabase: Error parsing %s\n%s", qPrintable(fileName), qPrintable(magicErrorMessage)); QList *ruleList; if (currentRules.isEmpty()) ruleList = &rules; diff --git a/src/corelib/mimetypes/qmimetypeparser_p.h b/src/corelib/mimetypes/qmimetypeparser_p.h index 2be4380cee..3a2e6b8a14 100644 --- a/src/corelib/mimetypes/qmimetypeparser_p.h +++ b/src/corelib/mimetypes/qmimetypeparser_p.h @@ -66,6 +66,8 @@ public: bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage); + static bool parseNumber(const QString &n, int *target, QString *errorMessage); + protected: virtual bool process(const QMimeType &t, QString *errorMessage) = 0; virtual bool process(const QMimeGlobPattern &t, QString *errorMessage) = 0; diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic1.xml b/tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic1.xml new file mode 100644 index 0000000000..04204d8763 --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic1.xml @@ -0,0 +1,9 @@ + + + + wrong value for byte type + + + + + diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic2.xml b/tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic2.xml new file mode 100644 index 0000000000..f18075482e --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic2.xml @@ -0,0 +1,9 @@ + + + + mask doesn't start with 0x + + + + + diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic3.xml b/tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic3.xml new file mode 100644 index 0000000000..0e2508cc0f --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/invalid-magic3.xml @@ -0,0 +1,9 @@ + + + + mask has wrong size + + + + + diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc b/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc index 4654a61660..29666627a1 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc +++ b/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc @@ -4,5 +4,8 @@ qml-again.xml text-x-objcsrc.xml test.qml + invalid-magic1.xml + invalid-magic2.xml + invalid-magic3.xml diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp index 8bc90d917e..763bb58602 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp @@ -45,9 +45,16 @@ #include -static const char yastFileName[] ="yast2-metapackage-handler-mimetypes.xml"; -static const char qmlAgainFileName[] ="qml-again.xml"; -static const char textXObjCSrcFileName[] ="text-x-objcsrc.xml"; +static const char *const additionalMimeFiles[] = { + "yast2-metapackage-handler-mimetypes.xml", + "qml-again.xml", + "text-x-objcsrc.xml", + "invalid-magic1.xml", + "invalid-magic2.xml", + "invalid-magic3.xml", + 0 +}; + #define RESOURCE_PREFIX ":/qt-project.org/qmime/" void initializeLang() @@ -149,12 +156,12 @@ void tst_QMimeDatabase::initTestCase() qWarning("%s", qPrintable(testSuiteWarning())); errorMessage = QString::fromLatin1("Cannot find '%1'"); - m_yastMimeTypes = QLatin1String(RESOURCE_PREFIX) + yastFileName; - QVERIFY2(QFile::exists(m_yastMimeTypes), qPrintable(errorMessage.arg(yastFileName))); - m_qmlAgainFileName = QLatin1String(RESOURCE_PREFIX) + qmlAgainFileName; - QVERIFY2(QFile::exists(m_qmlAgainFileName), qPrintable(errorMessage.arg(qmlAgainFileName))); - m_textXObjCSrcFileName = QLatin1String(RESOURCE_PREFIX) + textXObjCSrcFileName; - QVERIFY2(QFile::exists(m_textXObjCSrcFileName), qPrintable(errorMessage.arg(textXObjCSrcFileName))); + for (uint i = 0; i < sizeof additionalMimeFiles / sizeof additionalMimeFiles[0] - 1; i++) { + const QString resourceFilePath = QString::fromLatin1(RESOURCE_PREFIX) + QLatin1String(additionalMimeFiles[i]); + QVERIFY2(QFile::exists(resourceFilePath), qPrintable(errorMessage.arg(resourceFilePath))); + m_additionalMimeFileNames.append(QLatin1String(additionalMimeFiles[i])); + m_additionalMimeFilePaths.append(resourceFilePath); + } initTestCaseInternal(); m_isUsingCacheProvider = !qEnvironmentVariableIsSet("QT_NO_MIME_CACHE"); @@ -859,6 +866,14 @@ static void checkHasMimeType(const QString &mimeType) QVERIFY(found); } +static void ignoreInvalidMimetypeWarnings(const QString &mimeDir) +{ + const QByteArray basePath = QFile::encodeName(mimeDir) + "/packages/"; + QTest::ignoreMessage(QtWarningMsg, ("QMimeDatabase: Error parsing " + basePath + "invalid-magic1.xml\nInvalid magic rule value \"foo\"").constData()); + QTest::ignoreMessage(QtWarningMsg, ("QMimeDatabase: Error parsing " + basePath + "invalid-magic2.xml\nInvalid magic rule mask \"ffff\"").constData()); + QTest::ignoreMessage(QtWarningMsg, ("QMimeDatabase: Error parsing " + basePath + "invalid-magic3.xml\nInvalid magic rule mask size \"0xffff\"").constData()); +} + QT_BEGIN_NAMESPACE extern Q_CORE_EXPORT int qmime_secondsBetweenChecks; // see qmimeprovider.cpp QT_END_NAMESPACE @@ -879,23 +894,21 @@ void tst_QMimeDatabase::installNewGlobalMimeType() const QString mimeDir = m_globalXdgDir + QLatin1String("/mime"); const QString destDir = mimeDir + QLatin1String("/packages/"); - const QString destFile = destDir + QLatin1String(yastFileName); - QFile::remove(destFile); - const QString destQmlFile = destDir + QLatin1String(qmlAgainFileName); - QFile::remove(destQmlFile); - const QString destTextXObjCSrcFile = destDir + QLatin1String(textXObjCSrcFileName); - QFile::remove(destTextXObjCSrcFile); - //qDebug() << destFile; - if (!QFileInfo(destDir).isDir()) QVERIFY(QDir(m_globalXdgDir).mkpath(destDir)); + QString errorMessage; - QVERIFY2(copyResourceFile(m_yastMimeTypes, destFile, &errorMessage), qPrintable(errorMessage)); - QVERIFY2(copyResourceFile(m_qmlAgainFileName, destQmlFile, &errorMessage), qPrintable(errorMessage)); - QVERIFY2(copyResourceFile(m_textXObjCSrcFileName, destTextXObjCSrcFile, &errorMessage), qPrintable(errorMessage)); + for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) { + const QString destFile = destDir + m_additionalMimeFileNames.at(i); + QFile::remove(destFile); + QVERIFY2(copyResourceFile(m_additionalMimeFilePaths.at(i), destFile, &errorMessage), qPrintable(errorMessage)); + } if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(mimeDir)) QSKIP("shared-mime-info not found, skipping mime.cache test"); + if (!m_isUsingCacheProvider) + ignoreInvalidMimetypeWarnings(mimeDir); + QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(), QString::fromLatin1("text/x-SuSE-ymu")); QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); @@ -916,10 +929,9 @@ void tst_QMimeDatabase::installNewGlobalMimeType() qDebug() << objcsrc.globPatterns(); } - // Now test removing it again - QVERIFY(QFile::remove(destFile)); - QVERIFY(QFile::remove(destQmlFile)); - QVERIFY(QFile::remove(destTextXObjCSrcFile)); + // Now test removing the mimetype definitions again + for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) + QFile::remove(destDir + m_additionalMimeFileNames.at(i)); if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(mimeDir)) QSKIP("shared-mime-info not found, skipping mime.cache test"); QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(), @@ -936,23 +948,35 @@ void tst_QMimeDatabase::installNewLocalMimeType() qmime_secondsBetweenChecks = 0; QMimeDatabase db; + + // Check that we're starting clean QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); + QVERIFY(!db.mimeTypeForName(QLatin1String("text/invalid-magic1")).isValid()); const QString destDir = m_localMimeDir + QLatin1String("/packages/"); - QDir().mkpath(destDir); - const QString destFile = destDir + QLatin1String(yastFileName); - QFile::remove(destFile); - const QString destQmlFile = destDir + QLatin1String(qmlAgainFileName); - QFile::remove(destQmlFile); + QVERIFY(QDir().mkpath(destDir)); QString errorMessage; - QVERIFY2(copyResourceFile(m_yastMimeTypes, destFile, &errorMessage), qPrintable(errorMessage)); - QVERIFY2(copyResourceFile(m_qmlAgainFileName, destQmlFile, &errorMessage), qPrintable(errorMessage)); - if (m_isUsingCacheProvider && !runUpdateMimeDatabase(m_localMimeDir)) { + for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) { + const QString destFile = destDir + m_additionalMimeFileNames.at(i); + QFile::remove(destFile); + QVERIFY2(copyResourceFile(m_additionalMimeFilePaths.at(i), destFile, &errorMessage), qPrintable(errorMessage)); + } + if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(m_localMimeDir)) { const QString skipWarning = QStringLiteral("shared-mime-info not found, skipping mime.cache test (") + QDir::toNativeSeparators(m_localMimeDir) + QLatin1Char(')'); QSKIP(qPrintable(skipWarning)); } + if (!m_isUsingCacheProvider) + ignoreInvalidMimetypeWarnings(m_localMimeDir); + + QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); + + // These mimetypes have invalid magic, but still do exist. + QVERIFY(db.mimeTypeForName(QLatin1String("text/invalid-magic1")).isValid()); + QVERIFY(db.mimeTypeForName(QLatin1String("text/invalid-magic2")).isValid()); + QVERIFY(db.mimeTypeForName(QLatin1String("text/invalid-magic3")).isValid()); + QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(), QString::fromLatin1("text/x-SuSE-ymu")); QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); @@ -968,8 +992,8 @@ void tst_QMimeDatabase::installNewLocalMimeType() QString::fromLatin1("text/x-qml")); // Now test removing the local mimetypes again (note, this leaves a mostly-empty mime.cache file) - QVERIFY(QFile::remove(destFile)); - QVERIFY(QFile::remove(destQmlFile)); + for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) + QFile::remove(destDir + m_additionalMimeFileNames.at(i)); if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(m_localMimeDir)) QSKIP("shared-mime-info not found, skipping mime.cache test"); QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(), diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h index f12beafe86..2827bd2dc4 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h @@ -36,6 +36,7 @@ #include #include +#include class tst_QMimeDatabase : public QObject { @@ -92,9 +93,8 @@ private: QString m_globalXdgDir; QString m_localMimeDir; - QString m_yastMimeTypes; - QString m_qmlAgainFileName; - QString m_textXObjCSrcFileName; + QStringList m_additionalMimeFileNames; + QStringList m_additionalMimeFilePaths; QTemporaryDir m_temporaryDir; QString m_testSuite; bool m_isUsingCacheProvider; From 750509c3d11324a8371aeefc389f8b6ba7ed8a2e Mon Sep 17 00:00:00 2001 From: David Faure Date: Wed, 12 Aug 2015 15:25:17 +0200 Subject: [PATCH 036/240] Fix compilation with QNETWORKACCESSHTTPBACKEND_DEBUG enabled Change-Id: I868e8ecdff6a503ee891a257121bf14a7da77fec Reviewed-by: Markus Goetz (Woboq GmbH) Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/network/access/qnetworkreplyhttpimpl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index c445677792..abc6603be2 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1152,7 +1152,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData if (statusCode == 304) { #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "Received a 304 from" << url(); + qDebug() << "Received a 304 from" << request.url(); #endif QAbstractNetworkCache *nc = managerPrivate->networkCache; if (nc) { @@ -1457,7 +1457,7 @@ QNetworkCacheMetaData QNetworkReplyHttpImplPrivate::fetchCacheMetaData(const QNe } #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - QByteArray n = rawHeader(header); + QByteArray n = q->rawHeader(header); QByteArray o; if (it != cacheHeaders.rawHeaders.constEnd()) o = (*it).second; From cb12da0387458fb63a80a4f59d5ddb24d33ad59b Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 2 Sep 2015 18:30:29 +0300 Subject: [PATCH 037/240] Android: Don't use predictive text when selecting file names Using predictive text will not refresh the selected files until a word is completed or the keyboard is hidden. Task-number: QTBUG-44337 Change-Id: I9e9f1e760fe5d5a69abd6e112af55b217ae6a16d Reviewed-by: Shawn Rutledge --- src/widgets/dialogs/qfiledialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 64e3f5069e..c9e6a199c4 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2851,6 +2851,9 @@ void QFileDialogPrivate::createWidgets() completer = new QFSCompleter(model, q); qFileDialogUi->fileNameEdit->setCompleter(completer); #endif // QT_NO_FSCOMPLETER + + qFileDialogUi->fileNameEdit->setInputMethodHints(Qt::ImhNoPredictiveText); + QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_autoCompleteFileName(QString))); QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)), From 6413ceeccff9078bc8ec2dcb63b445c031c420dd Mon Sep 17 00:00:00 2001 From: Kari Pihkala Date: Sat, 2 Aug 2014 09:59:18 +0300 Subject: [PATCH 038/240] Fix default hotspot of a hidpi QCursor The hotspot is defined in device independent coordinates, so the default coordinates need to be divided by device pixel ratio. Also, modify the scaling of cursor's pixmap to use SmoothTransformation to generate cleaner looking lodpi cursors from hidpi cursors. Change-Id: Ia938fd1e476e19e796f30712e23b06a5efed9964 Task-number: QTBUG-34116 Reviewed-by: Jake Petroules --- src/gui/kernel/qcursor.cpp | 10 +++++----- src/gui/kernel/qcursor_p.h | 3 ++- src/plugins/platforms/cocoa/qcocoacursor.mm | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp index 6ed750eda1..6b01952647 100644 --- a/src/gui/kernel/qcursor.cpp +++ b/src/gui/kernel/qcursor.cpp @@ -387,7 +387,7 @@ QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY) bmm.fill(Qt::color1); } - d = QCursorData::setBitmap(bm, bmm, hotX, hotY); + d = QCursorData::setBitmap(bm, bmm, hotX, hotY, pixmap.devicePixelRatio()); d->pixmap = pixmap; } @@ -430,7 +430,7 @@ QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY) QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) : d(0) { - d = QCursorData::setBitmap(bitmap, mask, hotX, hotY); + d = QCursorData::setBitmap(bitmap, mask, hotX, hotY, 1.0); } /*! @@ -650,7 +650,7 @@ void QCursorData::initialize() QCursorData::initialized = true; } -QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) +QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY, qreal devicePixelRatio) { if (!QCursorData::initialized) QCursorData::initialize(); @@ -664,8 +664,8 @@ QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, d->bm = new QBitmap(bitmap); d->bmm = new QBitmap(mask); d->cshape = Qt::BitmapCursor; - d->hx = hotX >= 0 ? hotX : bitmap.width() / 2; - d->hy = hotY >= 0 ? hotY : bitmap.height() / 2; + d->hx = hotX >= 0 ? hotX : bitmap.width() / 2 / devicePixelRatio; + d->hy = hotY >= 0 ? hotY : bitmap.height() / 2 / devicePixelRatio; return d; } diff --git a/src/gui/kernel/qcursor_p.h b/src/gui/kernel/qcursor_p.h index 0aaa62b891..188ea387b3 100644 --- a/src/gui/kernel/qcursor_p.h +++ b/src/gui/kernel/qcursor_p.h @@ -70,7 +70,8 @@ public: short hx, hy; static bool initialized; void update(); - static QCursorData *setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY); + static QCursorData *setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY, + qreal devicePixelRatio); }; extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index 922809f90d..f08386d18e 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -304,7 +304,7 @@ NSCursor *QCocoaCursor::createCursorFromPixmap(const QPixmap pixmap, const QPoin NSImage *nsimage; if (pixmap.devicePixelRatio() > 1.0) { QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio(); - QPixmap scaledPixmap = pixmap.scaled(layoutSize); + QPixmap scaledPixmap = pixmap.scaled(layoutSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); nsimage = static_cast(qt_mac_create_nsimage(scaledPixmap)); CGImageRef cgImage = qt_mac_toCGImage(pixmap.toImage()); NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage]; From 1a5cc2a868969f1b1e9278c4145b7af2fc4b8f69 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Mon, 24 Aug 2015 12:22:52 +0200 Subject: [PATCH 039/240] Cocoa: correct QDesktopWidget::availableGeometry() Since 10.9, System Preferences->Mission Control->Displays have separate Spaces settings needs to be followed. Task-number: QTBUG-47030 Change-Id: I1c1cf326246bd5609090ce5ac3212d963d562593 Reviewed-by: Jake Petroules --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index c8f6dd05db..8f84539e04 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -86,9 +86,17 @@ void QCocoaScreen::updateGeometry() NSRect frameRect = [nsScreen frame]; - if (m_screenIndex == 0) { + // Since Mavericks, there is a setting, System Preferences->Mission Control-> + // Displays have separate Spaces. + BOOL spansDisplays = NO; +#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9) + spansDisplays = [NSScreen screensHaveSeparateSpaces]; +#endif + if (spansDisplays || m_screenIndex == 0) { m_geometry = QRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); - // This is the primary screen, the one that contains the menubar. Its origin should be + // Displays have separate Spaces setting is on or this is the primary screen, + // the one that contains the menubar. Its origin should be // (0, 0), and it's the only one whose available geometry differs from its full geometry. NSRect visibleRect = [nsScreen visibleFrame]; m_availableGeometry = QRect(visibleRect.origin.x, From 0e895c47b049fffd58abff3f61681e94ba5515ec Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 25 Aug 2015 13:55:12 +0200 Subject: [PATCH 040/240] Doc: Update links to Qt Creator Manual MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're now at 3.5 level: - Fixed changed filenames and topic titles - Removed links to obsolete pages - Added links to new pages Task-number: QTBUG-47901 Change-Id: I3393555c86bf3cf58770f230e7a9c7fd7e258476 Reviewed-by: Topi Reiniö --- doc/global/externalsites/qtcreator.qdoc | 44 ++++++++++++++++--------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/doc/global/externalsites/qtcreator.qdoc b/doc/global/externalsites/qtcreator.qdoc index 200ef307ca..95200622f3 100644 --- a/doc/global/externalsites/qtcreator.qdoc +++ b/doc/global/externalsites/qtcreator.qdoc @@ -27,24 +27,16 @@ /*! \externalpage http://doc.qt.io/qtcreator/creator-deployment-qnx.html - \title Qt Creator: Deploying Applications to QNX Devices + \title Qt Creator: Deploying Applications to QNX Neutrino Devices */ /*! \externalpage http://doc.qt.io/qtcreator/creator-developing-baremetal.html \title Qt Creator: Connecting Bare Metal Devices */ -/*! - \externalpage http://doc.qt.io/qtcreator/creator-developing-bb10.html - \title Qt Creator: Connecting BlackBerry 10 Devices -*/ /*! \externalpage http://doc.qt.io/qtcreator/creator-developing-qnx.html \title Qt Creator: Connecting QNX Devices */ -/*! - \externalpage http://doc.qt.io/qtcreator/creator-deployment-bb10.html - \title Qt Creator: Deploying Applications to BlackBerry 10 Devices -*/ /*! \externalpage http://doc.qt.io/qtcreator/creator-developing-generic-linux.html \title Qt Creator: Connecting Embedded Linux Devices @@ -98,7 +90,19 @@ \title Qt Creator: Creating Screens */ /*! - \externalpage http://doc.qt.io/qtcreator/creator-qml-application.html + \externalpage http://doc.qt.io/qtcreator/creator-qtquick-designer-extensions.html + \title Qt Creator: Using Qt Quick Designer Extensions +*/ +/*! + \externalpage http://doc.qt.io/qtcreator/qmldesigner-pathview-editor.html + \title Qt Creator: Editing PathView Properties +*/ +/*! + \externalpage http://doc.qt.io/qtcreator/qmldesigner-connections.html + \title Qt Creator: Adding Connections +*/ +/*! + \externalpage http://doc.qt.io/qtcreator/qtcreator-transitions-example.html \title Qt Creator: Creating a Qt Quick Application */ /*! @@ -279,7 +283,7 @@ */ /*! \externalpage http://doc.qt.io/qtcreator/creator-testing.html - \title Qt Creator: Debugging and Analyzing + \title Qt Creator: Testing */ /*! \externalpage http://doc.qt.io/qtcreator/creator-deployment.html @@ -297,10 +301,6 @@ \externalpage http://doc.qt.io/qtcreator/creator-design-mode.html \title Qt Creator: Designing User Interfaces */ -/*! - \externalpage http://doc.qt.io/qtcreator/creator-publish-ovi.html - \title Qt Creator: Publishing -*/ /*! \externalpage http://doc.qt.io/qtcreator/creator-glossary.html \title Qt Creator: Glossary @@ -476,7 +476,7 @@ \title Qt Creator: Adding Debuggers */ /*! - \externalpage http://doc.qt.io/qtcreator/creator-mobile-app-tutorial.html + \externalpage http://doc.qt.io/qtcreator/qtcreator-accelbubble-example.html \title Qt Creator: Creating a Mobile Application */ /*! @@ -499,7 +499,19 @@ \externalpage http://doc.qt.io/qtcreator/creator-quick-ui-forms.html \title Qt Creator: Qt Quick UI Forms */ +/*! + \externalpage http://doc.qt.io/qtcreator/qtcreator-uiforms-example.html + \title Qt Creator: Using Qt Quick UI Forms +*/ /*! \externalpage http://doc.qt.io/qtcreator/creator-clang-static-analyzer.html \title Qt Creator: Using Clang Static Analyzer */ +/*! + \externalpage http://doc.qt.io/qtcreator/creator-cpu-usage-analyzer.html + \title Qt Creator: Analyzing CPU Usage +*/ +/*! + \externalpage http://doc.qt.io/qtcreator/creator-autotest.html + \title Qt Creator: Running Autotests +*/ From 0552331d0e42e7b73f36e31ffd3cc511b50d2ec0 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 3 Aug 2015 10:07:17 +0200 Subject: [PATCH 041/240] Do not install headers for private classes When merging the accessibility plugin into the widgets library, the headers were just moved. They should have gotten the _p at that time. Task-number: QTBUG-47569 Change-Id: I0a2290dae3a8187596e9d7541ccf69beeb603296 Reviewed-by: Dimitar Dobrev Reviewed-by: Thiago Macieira --- src/widgets/accessible/accessible.pri | 12 ++++++------ src/widgets/accessible/complexwidgets.cpp | 2 +- .../{complexwidgets.h => complexwidgets_p.h} | 11 +++++++++++ src/widgets/accessible/itemviews.cpp | 2 +- .../accessible/{itemviews.h => itemviews_p.h} | 11 +++++++++++ src/widgets/accessible/qaccessiblemenu.cpp | 2 +- .../{qaccessiblemenu.h => qaccessiblemenu_p.h} | 11 +++++++++++ src/widgets/accessible/qaccessiblewidgetfactory.cpp | 12 ++++++------ src/widgets/accessible/qaccessiblewidgetfactory_p.h | 11 +++++++++++ src/widgets/accessible/qaccessiblewidgets.cpp | 2 +- .../{qaccessiblewidgets.h => qaccessiblewidgets_p.h} | 11 +++++++++++ src/widgets/accessible/rangecontrols.cpp | 4 ++-- .../{rangecontrols.h => rangecontrols_p.h} | 11 +++++++++++ src/widgets/accessible/simplewidgets.cpp | 2 +- .../{simplewidgets.h => simplewidgets_p.h} | 11 +++++++++++ 15 files changed, 96 insertions(+), 19 deletions(-) rename src/widgets/accessible/{complexwidgets.h => complexwidgets_p.h} (94%) rename src/widgets/accessible/{itemviews.h => itemviews_p.h} (97%) rename src/widgets/accessible/{qaccessiblemenu.h => qaccessiblemenu_p.h} (94%) rename src/widgets/accessible/{qaccessiblewidgets.h => qaccessiblewidgets_p.h} (97%) rename src/widgets/accessible/{rangecontrols.h => rangecontrols_p.h} (96%) rename src/widgets/accessible/{simplewidgets.h => simplewidgets_p.h} (96%) diff --git a/src/widgets/accessible/accessible.pri b/src/widgets/accessible/accessible.pri index bcdfbd639c..ac8205b1e3 100644 --- a/src/widgets/accessible/accessible.pri +++ b/src/widgets/accessible/accessible.pri @@ -4,12 +4,12 @@ contains(QT_CONFIG, accessibility) { HEADERS += \ accessible/qaccessiblewidget.h \ accessible/qaccessiblewidgetfactory_p.h \ - accessible/complexwidgets.h \ - accessible/itemviews.h \ - accessible/qaccessiblemenu.h \ - accessible/qaccessiblewidgets.h \ - accessible/rangecontrols.h \ - accessible/simplewidgets.h + accessible/complexwidgets_p.h \ + accessible/itemviews_p.h \ + accessible/qaccessiblemenu_p.h \ + accessible/qaccessiblewidgets_p.h \ + accessible/rangecontrols_p.h \ + accessible/simplewidgets_p.h SOURCES += \ accessible/qaccessiblewidget.cpp \ diff --git a/src/widgets/accessible/complexwidgets.cpp b/src/widgets/accessible/complexwidgets.cpp index 60a1329d5e..6e985c86e8 100644 --- a/src/widgets/accessible/complexwidgets.cpp +++ b/src/widgets/accessible/complexwidgets.cpp @@ -31,7 +31,7 @@ ** ****************************************************************************/ -#include "complexwidgets.h" +#include "complexwidgets_p.h" #include #include diff --git a/src/widgets/accessible/complexwidgets.h b/src/widgets/accessible/complexwidgets_p.h similarity index 94% rename from src/widgets/accessible/complexwidgets.h rename to src/widgets/accessible/complexwidgets_p.h index bd063e7517..8edf996818 100644 --- a/src/widgets/accessible/complexwidgets.h +++ b/src/widgets/accessible/complexwidgets_p.h @@ -34,6 +34,17 @@ #ifndef COMPLEXWIDGETS_H #define COMPLEXWIDGETS_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #include #include diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp index 4f6cb56060..6534d51a45 100644 --- a/src/widgets/accessible/itemviews.cpp +++ b/src/widgets/accessible/itemviews.cpp @@ -31,7 +31,7 @@ ** ****************************************************************************/ -#include "itemviews.h" +#include "itemviews_p.h" #include #include diff --git a/src/widgets/accessible/itemviews.h b/src/widgets/accessible/itemviews_p.h similarity index 97% rename from src/widgets/accessible/itemviews.h rename to src/widgets/accessible/itemviews_p.h index c1bd70a390..a1b6a6db9f 100644 --- a/src/widgets/accessible/itemviews.h +++ b/src/widgets/accessible/itemviews_p.h @@ -34,6 +34,17 @@ #ifndef ACCESSIBLE_ITEMVIEWS_H #define ACCESSIBLE_ITEMVIEWS_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "QtCore/qpointer.h" #include #include diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp index 72eb82b2b7..a0a7852851 100644 --- a/src/widgets/accessible/qaccessiblemenu.cpp +++ b/src/widgets/accessible/qaccessiblemenu.cpp @@ -31,7 +31,7 @@ ** ****************************************************************************/ -#include "qaccessiblemenu.h" +#include "qaccessiblemenu_p.h" #include #include diff --git a/src/widgets/accessible/qaccessiblemenu.h b/src/widgets/accessible/qaccessiblemenu_p.h similarity index 94% rename from src/widgets/accessible/qaccessiblemenu.h rename to src/widgets/accessible/qaccessiblemenu_p.h index 9c7671072d..b42c852ff1 100644 --- a/src/widgets/accessible/qaccessiblemenu.h +++ b/src/widgets/accessible/qaccessiblemenu_p.h @@ -34,6 +34,17 @@ #ifndef QACCESSIBLEMENU_H #define QACCESSIBLEMENU_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #include diff --git a/src/widgets/accessible/qaccessiblewidgetfactory.cpp b/src/widgets/accessible/qaccessiblewidgetfactory.cpp index e8b325b93f..4fa7c89482 100644 --- a/src/widgets/accessible/qaccessiblewidgetfactory.cpp +++ b/src/widgets/accessible/qaccessiblewidgetfactory.cpp @@ -31,12 +31,12 @@ ** ****************************************************************************/ -#include "qaccessiblewidgets.h" -#include "qaccessiblemenu.h" -#include "simplewidgets.h" -#include "rangecontrols.h" -#include "complexwidgets.h" -#include "itemviews.h" +#include "qaccessiblewidgets_p.h" +#include "qaccessiblemenu_p.h" +#include "simplewidgets_p.h" +#include "rangecontrols_p.h" +#include "complexwidgets_p.h" +#include "itemviews_p.h" #include #include diff --git a/src/widgets/accessible/qaccessiblewidgetfactory_p.h b/src/widgets/accessible/qaccessiblewidgetfactory_p.h index b3f9d8a251..caa37dcf81 100644 --- a/src/widgets/accessible/qaccessiblewidgetfactory_p.h +++ b/src/widgets/accessible/qaccessiblewidgetfactory_p.h @@ -36,6 +36,17 @@ #ifndef QACCESSIBLEWIDGETFACTORY_H #define QACCESSIBLEWIDGETFACTORY_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + QT_BEGIN_NAMESPACE QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object); diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp index a2bf14b25b..604c754ea1 100644 --- a/src/widgets/accessible/qaccessiblewidgets.cpp +++ b/src/widgets/accessible/qaccessiblewidgets.cpp @@ -31,7 +31,7 @@ ** ****************************************************************************/ -#include "qaccessiblewidgets.h" +#include "qaccessiblewidgets_p.h" #include "qabstracttextdocumentlayout.h" #include "qapplication.h" #include "qclipboard.h" diff --git a/src/widgets/accessible/qaccessiblewidgets.h b/src/widgets/accessible/qaccessiblewidgets_p.h similarity index 97% rename from src/widgets/accessible/qaccessiblewidgets.h rename to src/widgets/accessible/qaccessiblewidgets_p.h index 53f8c2c603..4bdc229578 100644 --- a/src/widgets/accessible/qaccessiblewidgets.h +++ b/src/widgets/accessible/qaccessiblewidgets_p.h @@ -34,6 +34,17 @@ #ifndef QACCESSIBLEWIDGETS_H #define QACCESSIBLEWIDGETS_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #ifndef QT_NO_ACCESSIBILITY diff --git a/src/widgets/accessible/rangecontrols.cpp b/src/widgets/accessible/rangecontrols.cpp index 002d4a9ef4..0607a35269 100644 --- a/src/widgets/accessible/rangecontrols.cpp +++ b/src/widgets/accessible/rangecontrols.cpp @@ -31,7 +31,7 @@ ** ****************************************************************************/ -#include "rangecontrols.h" +#include "rangecontrols_p.h" #include #include @@ -47,7 +47,7 @@ #include #include -#include "simplewidgets.h" // let spinbox use line edit's interface +#include "simplewidgets_p.h" // let spinbox use line edit's interface QT_BEGIN_NAMESPACE diff --git a/src/widgets/accessible/rangecontrols.h b/src/widgets/accessible/rangecontrols_p.h similarity index 96% rename from src/widgets/accessible/rangecontrols.h rename to src/widgets/accessible/rangecontrols_p.h index 11d4435e9d..32c6d6985f 100644 --- a/src/widgets/accessible/rangecontrols.h +++ b/src/widgets/accessible/rangecontrols_p.h @@ -34,6 +34,17 @@ #ifndef RANGECONTROLS_H #define RANGECONTROLS_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include QT_BEGIN_NAMESPACE diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp index b08c21939a..065c618cf7 100644 --- a/src/widgets/accessible/simplewidgets.cpp +++ b/src/widgets/accessible/simplewidgets.cpp @@ -31,7 +31,7 @@ ** ****************************************************************************/ -#include "simplewidgets.h" +#include "simplewidgets_p.h" #include #include diff --git a/src/widgets/accessible/simplewidgets.h b/src/widgets/accessible/simplewidgets_p.h similarity index 96% rename from src/widgets/accessible/simplewidgets.h rename to src/widgets/accessible/simplewidgets_p.h index 0dfd9f79c8..c2e904273f 100644 --- a/src/widgets/accessible/simplewidgets.h +++ b/src/widgets/accessible/simplewidgets_p.h @@ -34,6 +34,17 @@ #ifndef SIMPLEWIDGETS_H #define SIMPLEWIDGETS_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #include From d05bb9ffb05be57b9ef8e961cc17111b1bdaffc8 Mon Sep 17 00:00:00 2001 From: Jonathan Meier Date: Sat, 5 Sep 2015 11:38:56 +0200 Subject: [PATCH 042/240] Fix qmake messing up headers of generated Visual Studio solution files While generating Visual Studio 2015 solution files for a project using the subdirs template qmake writes out both the header for version 2015 and version 2013. The problem is a case fall-through. Task-number: QTBUG-48110 Change-Id: Ib6ddc1ceb306be9b3098d7b7c66a8ffabbd86481 Reviewed-by: J-P Nurmi Reviewed-by: Andrew Knight Reviewed-by: Joerg Bornemann --- qmake/generators/win32/msvc_vcproj.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 8e08ab248e..9acfa6588b 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -655,6 +655,7 @@ void VcprojGenerator::writeSubDirs(QTextStream &t) switch (which_dotnet_version(project->first("MSVC_VER").toLatin1())) { case NET2015: t << _slnHeader140; + break; case NET2013: t << _slnHeader120; break; From 1b29ef627ce8e69dbe2daae73bc6a9f57b631b3d Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Wed, 29 Jul 2015 13:33:51 +1000 Subject: [PATCH 043/240] Fix hang in qnam when disconnecting Generate error for network requests when connection gets disconnected. Documentation states that QNAM requests will fail if network is not accessible, so we need to track session state. Task-number: QTBUG-47482 Change-Id: I2c2d348637f72b2a908b438a66aa543a878de1e5 Reviewed-by: Timo Jyrinki Reviewed-by: Richard J. Moore --- src/network/access/qnetworkreplyhttpimpl.cpp | 15 +++++++++++++++ src/network/access/qnetworkreplyhttpimpl_p.h | 2 ++ src/network/access/qnetworkreplyimpl.cpp | 15 +++++++++++++++ src/network/access/qnetworkreplyimpl_p.h | 2 ++ 4 files changed, 34 insertions(+) diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index abc6603be2..c1956ae99f 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1676,6 +1676,11 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "backend start error."))); QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection); return; +#endif + } else { +#ifndef QT_NO_BEARERMANAGEMENT + QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); #endif } @@ -1844,6 +1849,16 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected() } } +void QNetworkReplyHttpImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState) +{ + if (sessionState == QNetworkSession::Disconnected + && (state != Idle || state != Reconnecting)) { + error(QNetworkReplyImpl::NetworkSessionFailedError, + QCoreApplication::translate("QNetworkReply", "Network session error.")); + finished(); + } +} + void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed() { // Abort waiting and working replies. diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index b009092196..cfc05edbd8 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -95,6 +95,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) + Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)) #endif Q_PRIVATE_SLOT(d_func(), void _q_finished()) @@ -170,6 +171,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT void _q_networkSessionConnected(); void _q_networkSessionFailed(); + void _q_networkSessionStateChanged(QNetworkSession::State); void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies); #endif void _q_finished(); diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index f235adaee8..18f322f45d 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -126,6 +126,11 @@ void QNetworkReplyImplPrivate::_q_startOperation() finished(); #endif return; + } else { +#ifndef QT_NO_BEARERMANAGEMENT + QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); +#endif } #ifndef QT_NO_BEARERMANAGEMENT @@ -310,6 +315,16 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected() } } +void QNetworkReplyImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState) +{ + if (sessionState == QNetworkSession::Disconnected + && (state != Idle || state != Reconnecting)) { + error(QNetworkReplyImpl::NetworkSessionFailedError, + QCoreApplication::translate("QNetworkReply", "Network session error.")); + finished(); + } +} + void QNetworkReplyImplPrivate::_q_networkSessionFailed() { // Abort waiting and working replies. diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index d2e7d02408..5883c9d1c3 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -89,6 +89,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) + Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)) #endif @@ -124,6 +125,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT void _q_networkSessionConnected(); void _q_networkSessionFailed(); + void _q_networkSessionStateChanged(QNetworkSession::State); void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies); #endif From c258422cf9962b994505030b7cc9bb00d22b7bf8 Mon Sep 17 00:00:00 2001 From: Tuomas Heimonen Date: Tue, 8 Sep 2015 14:52:21 +0300 Subject: [PATCH 044/240] tst_QProcess_and_GuiEventLoop: Added flag QT_NO_PROCESS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I895b9c12de8734c20ec87ac30a9a9cca8f4242d7 Reviewed-by: Pasi Petäjäjärvi Reviewed-by: Thiago Macieira --- .../tst_qprocess_and_guieventloop.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp b/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp index 53459b13f6..b79b3aba28 100644 --- a/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp +++ b/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp @@ -45,9 +45,11 @@ private slots: void tst_QProcess_and_GuiEventLoop::waitForAndEventLoop() { -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) +#if defined(QT_NO_PROCESS) + QSKIP("QProcess not supported"); +#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) QSKIP("Not supported on Android"); -#endif +#else // based on testcase provided in QTBUG-39488 QByteArray msg = "Hello World"; @@ -78,6 +80,7 @@ void tst_QProcess_and_GuiEventLoop::waitForAndEventLoop() QCOMPARE(process.exitCode(), 0); QCOMPARE(spy.count(), 1); QCOMPARE(process.readAll().trimmed(), msg); +#endif } QTEST_MAIN(tst_QProcess_and_GuiEventLoop) From 4b2db07b42dc0be28beafbd20d005cc0b7b11fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pasi=20Pet=C3=A4j=C3=A4j=C3=A4rvi?= Date: Wed, 9 Sep 2015 15:45:18 +0300 Subject: [PATCH 045/240] Fix tst_QGuiApplication for embedded platforms using eglfs QPA Disable input and cursor for QGuiApplication instances used in autotest to initialize it properly. Change-Id: I78dc9b776269c082c20f244a51f858289129275d Reviewed-by: Laszlo Agocs --- .../qcoreapplication/tst_qcoreapplication.cpp | 5 ----- .../qguiapplication/tst_qguiapplication.cpp | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp index efecf31d66..60e358232e 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp +++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp @@ -41,12 +41,7 @@ #include #include -#ifdef QT_GUI_LIB -#include -typedef QGuiApplication TestApplication; -#else typedef QCoreApplication TestApplication; -#endif class EventSpy : public QObject { diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp index 19365bffdd..d573d97495 100644 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp @@ -60,6 +60,7 @@ class tst_QGuiApplication: public tst_QCoreApplication Q_OBJECT private slots: + void initTestCase(); void cleanup(); void displayName(); void firstWindowTitle(); @@ -84,6 +85,21 @@ private slots: void settableStyleHints(); // Needs to run last as it changes style hints. }; +void tst_QGuiApplication::initTestCase() +{ +#ifdef QT_QPA_DEFAULT_PLATFORM_NAME + if ((QString::compare(QStringLiteral(QT_QPA_DEFAULT_PLATFORM_NAME), + QStringLiteral("eglfs"), Qt::CaseInsensitive) == 0) || + (QString::compare(QString::fromLatin1(qgetenv("QT_QPA_PLATFORM")), + QStringLiteral("eglfs"), Qt::CaseInsensitive) == 0)) { + // Set env variables to disable input and cursor because eglfs is single fullscreen window + // and trying to initialize input and cursor will crash test. + qputenv("QT_QPA_EGLFS_DISABLE_INPUT", "1"); + qputenv("QT_QPA_EGLFS_HIDECURSOR", "1"); + } +#endif +} + void tst_QGuiApplication::cleanup() { QVERIFY(QGuiApplication::allWindows().isEmpty()); From d75505faccc9a86d9e76932ae022b660e01ad1a5 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 8 Sep 2015 13:38:41 +0200 Subject: [PATCH 046/240] iOS: silence compiler warning about unimplemented 'selectionRectsForRange' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement a dummy method to silence the compiler. After testing, this method seems to never be called. Which is good, since the current IM API in Qt have little to offer to resolve what is being asked. Until a need arise, we just return an empty array. Change-Id: I573eb8205a7e635a46d487ae175fb46e3a602001 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 4e109f6921..c9120e848c 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -738,6 +738,15 @@ return toCGRect(startRect.united(endRect)); } +- (NSArray *)selectionRectsForRange:(UITextRange *)range +{ + Q_UNUSED(range); + // This method is supposed to return a rectangle for each line with selection. Since we don't + // expose an API in Qt/IM for getting this information, and since we never seems to be getting + // a call from UIKit for this, we return an empty array until a need arise. + return [[NSArray new] autorelease]; +} + - (CGRect)caretRectForPosition:(UITextPosition *)position { Q_UNUSED(position); From 378e26dd14df808a55471330400984841ef414d4 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Wed, 11 Feb 2015 20:02:07 +0200 Subject: [PATCH 047/240] QUdpSocket: avoid infinite read notifier blocking There was a small amount of time between the last readDatagram() call and disabling a read notifier in case the socket had a pending datagram. If a new datagram arrived in this period, this qualified as absence of a datagram reader. Do not change the read notifier state because it is disabled on canReadNotification() entry and always enabled by the datagram reader. Thanks to Peter Seiderer, who investigated the same: "Querying hasPendingDatagrams() for enabling/disabling setReadNotificationEnabled() is racy (a new datagram could arrive after readDatagam() is called and before hasPendingDatagrams() is checked). But for unbuffered sockets the ReadNotification is already disabled before the readReady signal is emitted and should be re-enabled when calling read() or readDatagram() from the user." However, this patch does not completely solve the problem under Windows, as the socket notifier may emit spurious notifications. Task-number: QTBUG-46552 Change-Id: If7295d53ae2c788c39e86303502f38135c4d6180 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/network/socket/qabstractsocket.cpp | 12 ++--- .../socket/qudpsocket/tst_qudpsocket.cpp | 54 +++++++++++++++++++ 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index c42b4f520c..d93150799c 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -739,15 +739,9 @@ bool QAbstractSocketPrivate::canReadNotification() return true; } - if (socketEngine) { - // turn the socket engine off if we've either: - // - got pending datagrams - // - reached the buffer size limit - if (isBuffered) - socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable()); - else if (socketType != QAbstractSocket::TcpSocket) - socketEngine->setReadNotificationEnabled(!socketEngine->hasPendingDatagrams()); - } + // turn the socket engine off if we've reached the buffer size limit + if (socketEngine && isBuffered) + socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable()); // reset the read socket notifier state if we reentered inside the // readyRead() connected slot. diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index b6129bec08..a4695955af 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -116,10 +116,12 @@ private slots: void linkLocalIPv4(); void readyRead(); void readyReadForEmptyDatagram(); + void asyncReadDatagram(); protected slots: void empty_readyReadSlot(); void empty_connectedSlot(); + void async_readDatagramSlot(); private: #ifndef QT_NO_BEARERMANAGEMENT @@ -127,6 +129,8 @@ private: QNetworkConfiguration networkConfiguration; QSharedPointer networkSession; #endif + QUdpSocket *m_asyncSender; + QUdpSocket *m_asyncReceiver; }; static QHostAddress makeNonAny(const QHostAddress &address, QHostAddress::SpecialAddress preferForAny = QHostAddress::LocalHost) @@ -1671,5 +1675,55 @@ void tst_QUdpSocket::readyReadForEmptyDatagram() QCOMPARE(receiver.readDatagram(buf, sizeof buf), qint64(0)); } +void tst_QUdpSocket::async_readDatagramSlot() +{ + char buf[1]; + QVERIFY(m_asyncReceiver->hasPendingDatagrams()); + QCOMPARE(m_asyncReceiver->pendingDatagramSize(), qint64(1)); + QCOMPARE(m_asyncReceiver->bytesAvailable(), qint64(1)); + QCOMPARE(m_asyncReceiver->readDatagram(buf, sizeof(buf)), qint64(1)); + + if (buf[0] == '2') { + QTestEventLoop::instance().exitLoop(); + return; + } + + m_asyncSender->writeDatagram("2", makeNonAny(m_asyncReceiver->localAddress()), m_asyncReceiver->localPort()); + // wait a little to ensure that the datagram we've just sent + // will be delivered on receiver side. + QTest::qSleep(100); +} + +void tst_QUdpSocket::asyncReadDatagram() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + m_asyncSender = new QUdpSocket; + m_asyncReceiver = new QUdpSocket; +#ifdef FORCE_SESSION + m_asyncSender->setProperty("_q_networksession", QVariant::fromValue(networkSession)); + m_asyncReceiver->setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif + + QVERIFY(m_asyncReceiver->bind(QHostAddress(QHostAddress::AnyIPv4), 0)); + quint16 port = m_asyncReceiver->localPort(); + QVERIFY(port != 0); + + QSignalSpy spy(m_asyncReceiver, SIGNAL(readyRead())); + connect(m_asyncReceiver, SIGNAL(readyRead()), SLOT(async_readDatagramSlot())); + + m_asyncSender->writeDatagram("1", makeNonAny(m_asyncReceiver->localAddress()), port); + + QTestEventLoop::instance().enterLoop(1); + + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(spy.count(), 2); + + delete m_asyncSender; + delete m_asyncReceiver; +} + QTEST_MAIN(tst_QUdpSocket) #include "tst_qudpsocket.moc" From a6ec869211d67fed94e3513dc453a96717155121 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Tue, 11 Aug 2015 13:23:32 +0300 Subject: [PATCH 048/240] Fix the spurious socket notifications under Windows To handle network events, QEventDispatcherWin32 uses I/O model based on notifications through the window message queue. Having successfully posted notification of a particular event to an application window, no further messages for that network event will be posted to the application window until the application makes the function call that implicitly re-enables notification of that network event. With these semantics, an application need not read all available data in response to an FD_READ message: a single recv in response to each FD_READ message is appropriate. If an application issues multiple recv calls in response to a single FD_READ, it can receive multiple FD_READ messages (including spurious). To solve this issue, this patch always disables the notifier after getting a notification, and re-enables it only when the message queue is empty. Task-number: QTBUG-46552 Change-Id: I05df67032911cd1f5927fa7912f7864bfbf8711e Reviewed-by: Joerg Bornemann --- src/corelib/kernel/qeventdispatcher_win.cpp | 112 +++++++++++------- src/corelib/kernel/qeventdispatcher_win_p.h | 11 +- src/corelib/kernel/qsocketnotifier.cpp | 36 ------ .../qsocketnotifier/tst_qsocketnotifier.cpp | 73 ++++++++++++ 4 files changed, 153 insertions(+), 79 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 6da70cf0bd..695eb3d5d0 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -391,6 +391,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA QSockNot *sn = dict ? dict->value(wp) : 0; if (sn) { + d->doWsaAsyncSelect(sn->fd, 0); + d->active_fd[sn->fd].selected = false; if (type < 3) { QEvent event(QEvent::SockAct); QCoreApplication::sendEvent(sn->obj, &event); @@ -633,19 +635,12 @@ void QEventDispatcherWin32Private::sendTimerEvent(int timerId) } } -void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket) +void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event) { Q_ASSERT(internalHwnd); - int sn_event = 0; - if (sn_read.contains(socket)) - sn_event |= FD_READ | FD_CLOSE | FD_ACCEPT; - if (sn_write.contains(socket)) - sn_event |= FD_WRITE | FD_CONNECT; - if (sn_except.contains(socket)) - sn_event |= FD_OOB; - // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0 + // BoundsChecker may emit a warning for WSAAsyncSelect when event == 0 // This is a BoundsChecker bug and not a Qt bug - WSAAsyncSelect(socket, internalHwnd, sn_event ? int(WM_QT_SOCKETNOTIFIER) : 0, sn_event); + WSAAsyncSelect(socket, internalHwnd, event ? int(WM_QT_SOCKETNOTIFIER) : 0, event); } void QEventDispatcherWin32::createInternalHwnd() @@ -658,13 +653,6 @@ void QEventDispatcherWin32::createInternalHwnd() installMessageHook(); - // register all socket notifiers - QList sockets = (d->sn_read.keys().toSet() - + d->sn_write.keys().toSet() - + d->sn_except.keys().toSet()).toList(); - for (int i = 0; i < sockets.count(); ++i) - d->doWsaAsyncSelect(sockets.at(i)); - // start all normal timers for (int i = 0; i < d->timerVec.count(); ++i) d->registerTimer(d->timerVec.at(i)); @@ -749,28 +737,40 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) msg = d->queuedSocketEvents.takeFirst(); } else { haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE); - if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents) - && ((msg.message >= WM_KEYFIRST - && msg.message <= WM_KEYLAST) - || (msg.message >= WM_MOUSEFIRST - && msg.message <= WM_MOUSELAST) - || msg.message == WM_MOUSEWHEEL - || msg.message == WM_MOUSEHWHEEL - || msg.message == WM_TOUCH + if (haveMessage) { + if ((flags & QEventLoop::ExcludeUserInputEvents) + && ((msg.message >= WM_KEYFIRST + && msg.message <= WM_KEYLAST) + || (msg.message >= WM_MOUSEFIRST + && msg.message <= WM_MOUSELAST) + || msg.message == WM_MOUSEWHEEL + || msg.message == WM_MOUSEHWHEEL + || msg.message == WM_TOUCH #ifndef QT_NO_GESTURES - || msg.message == WM_GESTURE - || msg.message == WM_GESTURENOTIFY + || msg.message == WM_GESTURE + || msg.message == WM_GESTURENOTIFY #endif - || msg.message == WM_CLOSE)) { - // queue user input events for later processing - haveMessage = false; - d->queuedUserInputEvents.append(msg); - } - if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers) - && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) { - // queue socket events for later processing - haveMessage = false; - d->queuedSocketEvents.append(msg); + || msg.message == WM_CLOSE)) { + // queue user input events for later processing + d->queuedUserInputEvents.append(msg); + continue; + } + if ((flags & QEventLoop::ExcludeSocketNotifiers) + && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) { + // queue socket events for later processing + d->queuedSocketEvents.append(msg); + continue; + } + } else if (!(flags & QEventLoop::ExcludeSocketNotifiers)) { + // register all socket notifiers + for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end(); + it != end; ++it) { + QSockFd &sd = it.value(); + if (!sd.selected) { + d->doWsaAsyncSelect(it.key(), sd.event); + sd.selected = true; + } + } } } if (!haveMessage) { @@ -896,8 +896,25 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) sn->fd = sockfd; dict->insert(sn->fd, sn); - if (d->internalHwnd) - d->doWsaAsyncSelect(sockfd); + long event = 0; + if (d->sn_read.contains(sockfd)) + event |= FD_READ | FD_CLOSE | FD_ACCEPT; + if (d->sn_write.contains(sockfd)) + event |= FD_WRITE | FD_CONNECT; + if (d->sn_except.contains(sockfd)) + event |= FD_OOB; + + QSFDict::iterator it = d->active_fd.find(sockfd); + if (it != d->active_fd.end()) { + QSockFd &sd = it.value(); + if (sd.selected) { + d->doWsaAsyncSelect(sockfd, 0); + sd.selected = false; + } + sd.event |= event; + } else { + d->active_fd.insert(sockfd, QSockFd(event)); + } } void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) @@ -916,6 +933,19 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) #endif Q_D(QEventDispatcherWin32); + QSFDict::iterator it = d->active_fd.find(sockfd); + if (it != d->active_fd.end()) { + QSockFd &sd = it.value(); + if (sd.selected) + d->doWsaAsyncSelect(sockfd, 0); + const long event[3] = { FD_READ | FD_CLOSE | FD_ACCEPT, FD_WRITE | FD_CONNECT, FD_OOB }; + sd.event ^= event[type]; + if (sd.event == 0) + d->active_fd.erase(it); + else + sd.selected = false; + } + QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; QSNDict *dict = sn_vec[type]; QSockNot *sn = dict->value(sockfd); @@ -924,9 +954,6 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) dict->remove(sockfd); delete sn; - - if (d->internalHwnd) - d->doWsaAsyncSelect(sockfd); } void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) @@ -1165,6 +1192,7 @@ void QEventDispatcherWin32::closingDown() unregisterSocketNotifier((*(d->sn_write.begin()))->obj); while (!d->sn_except.isEmpty()) unregisterSocketNotifier((*(d->sn_except.begin()))->obj); + Q_ASSERT(d->active_fd.isEmpty()); // clean up any timers for (int i = 0; i < d->timerVec.count(); ++i) diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index e59e29f1ff..8578110ee4 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -115,6 +115,14 @@ struct QSockNot { }; typedef QHash QSNDict; +struct QSockFd { + long event; + bool selected; + + explicit inline QSockFd(long ev = 0) : event(ev), selected(false) { } +}; +typedef QHash QSFDict; + struct WinTimerInfo { // internal timer info QObject *dispatcher; int timerId; @@ -169,7 +177,8 @@ public: QSNDict sn_read; QSNDict sn_write; QSNDict sn_except; - void doWsaAsyncSelect(int socket); + QSFDict active_fd; + void doWsaAsyncSelect(int socket, long event); QList winEventNotifierList; void activateEventNotifier(QWinEventNotifier * wen); diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp index d789af2fd9..3a5eff0c19 100644 --- a/src/corelib/kernel/qsocketnotifier.cpp +++ b/src/corelib/kernel/qsocketnotifier.cpp @@ -98,42 +98,6 @@ public: QTcpSocket and QUdpSocket provide notification through signals, so there is normally no need to use a QSocketNotifier on them. - \section1 Notes for Windows Users - - The socket passed to QSocketNotifier will become non-blocking, even if - it was created as a blocking socket. - The activated() signal is sometimes triggered by high general activity - on the host, even if there is nothing to read. A subsequent read from - the socket can then fail, the error indicating that there is no data - available (e.g., \c{WSAEWOULDBLOCK}). This is an operating system - limitation, and not a bug in QSocketNotifier. - - To ensure that the socket notifier handles read notifications correctly, - follow these steps when you receive a notification: - - \list 1 - \li Disable the notifier. - \li Read data from the socket. - \li Re-enable the notifier if you are interested in more data (such as after - having written a new command to a remote server). - \endlist - - To ensure that the socket notifier handles write notifications correctly, - follow these steps when you receive a notification: - - \list 1 - \li Disable the notifier. - \li Write as much data as you can (before \c EWOULDBLOCK is returned). - \li Re-enable notifier if you have more data to write. - \endlist - - \b{Further information:} - On Windows, Qt always disables the notifier after getting a notification, - and only re-enables it if more data is expected. For example, if data is - read from the socket and it can be used to read more, or if reading or - writing is not possible because the socket would block, in which case - it is necessary to wait before attempting to read or write again. - \sa QFile, QProcess, QTcpSocket, QUdpSocket */ diff --git a/tests/auto/corelib/kernel/qsocketnotifier/tst_qsocketnotifier.cpp b/tests/auto/corelib/kernel/qsocketnotifier/tst_qsocketnotifier.cpp index 930a17c3a9..f49da1f5a8 100644 --- a/tests/auto/corelib/kernel/qsocketnotifier/tst_qsocketnotifier.cpp +++ b/tests/auto/corelib/kernel/qsocketnotifier/tst_qsocketnotifier.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #ifndef Q_OS_WINRT #include #else @@ -66,8 +67,29 @@ private slots: #ifdef Q_OS_UNIX void posixSockets(); #endif + void asyncMultipleDatagram(); + +protected slots: + void async_readDatagramSlot(); + void async_writeDatagramSlot(); + +private: + QUdpSocket *m_asyncSender; + QUdpSocket *m_asyncReceiver; }; +static QHostAddress makeNonAny(const QHostAddress &address, + QHostAddress::SpecialAddress preferForAny = QHostAddress::LocalHost) +{ + if (address == QHostAddress::Any) + return preferForAny; + if (address == QHostAddress::AnyIPv4) + return QHostAddress::LocalHost; + if (address == QHostAddress::AnyIPv6) + return QHostAddress::LocalHostIPv6; + return address; +} + class UnexpectedDisconnectTester : public QObject { Q_OBJECT @@ -299,5 +321,56 @@ void tst_QSocketNotifier::posixSockets() } #endif +void tst_QSocketNotifier::async_readDatagramSlot() +{ + char buf[1]; + QVERIFY(m_asyncReceiver->hasPendingDatagrams()); + do { + QCOMPARE(m_asyncReceiver->pendingDatagramSize(), qint64(1)); + QCOMPARE(m_asyncReceiver->readDatagram(buf, sizeof(buf)), qint64(1)); + if (buf[0] == '1') { + // wait for the second datagram message. + QTest::qSleep(100); + } + } while (m_asyncReceiver->hasPendingDatagrams()); + + if (buf[0] == '3') + QTestEventLoop::instance().exitLoop(); +} + +void tst_QSocketNotifier::async_writeDatagramSlot() +{ + m_asyncSender->writeDatagram("3", makeNonAny(m_asyncReceiver->localAddress()), + m_asyncReceiver->localPort()); +} + +void tst_QSocketNotifier::asyncMultipleDatagram() +{ + m_asyncSender = new QUdpSocket; + m_asyncReceiver = new QUdpSocket; + + QVERIFY(m_asyncReceiver->bind(QHostAddress(QHostAddress::AnyIPv4), 0)); + quint16 port = m_asyncReceiver->localPort(); + QVERIFY(port != 0); + + QSignalSpy spy(m_asyncReceiver, &QIODevice::readyRead); + connect(m_asyncReceiver, &QIODevice::readyRead, this, + &tst_QSocketNotifier::async_readDatagramSlot); + m_asyncSender->writeDatagram("1", makeNonAny(m_asyncReceiver->localAddress()), port); + m_asyncSender->writeDatagram("2", makeNonAny(m_asyncReceiver->localAddress()), port); + // wait a little to ensure that the datagrams we've just sent + // will be delivered on receiver side. + QTest::qSleep(100); + + QTimer::singleShot(500, this, &tst_QSocketNotifier::async_writeDatagramSlot); + + QTestEventLoop::instance().enterLoop(1); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(spy.count(), 2); + + delete m_asyncSender; + delete m_asyncReceiver; +} + QTEST_MAIN(tst_QSocketNotifier) #include From c86ca601edfde6e7b6a0769903d86bd48e26d70d Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Fri, 21 Aug 2015 13:00:55 +0300 Subject: [PATCH 049/240] Windows socket engine: do not discard datagram on critical failure On some network conditions, WSARecvFrom() may return WSAECONNRESET or WSAENETRESET error code to indicate that the connection has been broken and should be reset. According to MSDN documentation, WSAECONNRESET mean that the virtual circuit was reset by the remote side executing a hard or abortive close. Also, it would indicate that a previous send operation resulted in an ICMP "Port Unreachable" message. For a datagram socket, WSAENETRESET indicates that the time to live has expired. Previously, hasPendingDatagram() discarded datagrams with these errors and reported no data available. This behavior is incorrect and can lead to infinite "freezing" of the socket. This patch allows to handle these notifications as a result of the readDatagram() call. Task-number: QTBUG-46552 Change-Id: I7d84babe22d36736b928b4dd4841e30be53d16bd Reviewed-by: Kai Koehne Reviewed-by: Joerg Bornemann --- .../socket/qnativesocketengine_win.cpp | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 72f85c831f..708be2dea7 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -1090,8 +1090,11 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const buf.buf = &c; buf.len = sizeof(c); DWORD flags = MSG_PEEK; - if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR) - return 0; + if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR) { + int err = WSAGetLastError(); + if (err != WSAECONNRESET && err != WSAENETRESET) + return 0; + } } return nbytes; } @@ -1119,14 +1122,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const int err = WSAGetLastError(); if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) { WS_ERROR_DEBUG(err); - if (err == WSAECONNRESET || err == WSAENETRESET) { - // Discard error message to prevent QAbstractSocket from - // getting this message repeatedly after reenabling the - // notifiers. - flags = 0; - ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags, - &storage.a, &storageSize, 0, 0); - } + result = (err == WSAECONNRESET || err == WSAENETRESET); } else { // If there's no error, or if our buffer was too small, there must be // a pending datagram. @@ -1179,12 +1175,21 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const if (recvResult != SOCKET_ERROR) { ret = qint64(bytesRead); break; - } else if (recvResult == SOCKET_ERROR && err == WSAEMSGSIZE) { - bufferCount += 5; - delete[] buf; - } else if (recvResult == SOCKET_ERROR) { - WS_ERROR_DEBUG(err); - ret = -1; + } else { + switch (err) { + case WSAEMSGSIZE: + bufferCount += 5; + delete[] buf; + continue; + case WSAECONNRESET: + case WSAENETRESET: + ret = 0; + break; + default: + WS_ERROR_DEBUG(err); + ret = -1; + break; + } break; } } From 3f531512e859f78e22a775193f0832f4709c84ec Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 29 Jun 2015 14:26:07 +0200 Subject: [PATCH 050/240] Force GLES 2.0 on Android 4.2 devices reporting 3.0 Android does not support GLES 3.0 before 4.3 (API level 18). However some 4.2.2 devices are reported to return 3.0 in the version string and therefore choose the GLES 3+ code paths in Qt. This blows up sooner or later because the 3.0 specific functions are apparently not present at all. Task-number: QTBUG-46831 Change-Id: Ic3eeb7c55829cf36c6d142c01ff8a1e18e9ecc1a Reviewed-by: Kati Kankaanpaa Reviewed-by: Christian Stromme --- .../eglconvenience/qeglplatformcontext.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 5bee29afef..bffb0eb4e8 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -39,6 +39,10 @@ #include #include +#ifdef Q_OS_ANDROID +#include +#endif + QT_BEGIN_NAMESPACE /*! @@ -294,6 +298,14 @@ void QEGLPlatformContext::updateFormatFromGL() QByteArray version = QByteArray(reinterpret_cast(s)); int major, minor; if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) { +#ifdef Q_OS_ANDROID + // Some Android 4.2.2 devices report OpenGL ES 3.0 without the functions being available. + static int apiLevel = QtAndroidPrivate::androidSdkVersion(); + if (apiLevel <= 17 && major >= 3) { + major = 2; + minor = 0; + } +#endif m_format.setMajorVersion(major); m_format.setMinorVersion(minor); } From c12b5e07274acde364be98cd0de620d3a44c97b7 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 2 Sep 2015 17:35:53 +0200 Subject: [PATCH 051/240] QCocoaMenu: Manually reposition popups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the popup will show too close to the screen bottom, we need to help Cocoa a bit. The horizontal positioning hasn't shown any problems. Change-Id: I5f298529fbf4a902e39f686f368046a8d1c11760 Task-number: QTBUG-45063 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoamenu.mm | 41 +++++++++++++++++------ 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 6668080725..a6157bdc3a 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -464,6 +464,13 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, NSView *view = cocoaWindow ? cocoaWindow->contentView() : nil; NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil; + QScreen *screen = 0; + if (parentWindow) + screen = parentWindow->screen(); + if (!screen && !QGuiApplication::screens().isEmpty()) + screen = QGuiApplication::screens().at(0); + Q_ASSERT(screen); + // Ideally, we would call -popUpMenuPositioningItem:atLocation:inView:. // However, this showed not to work with modal windows where the menu items // would appear disabled. So, we resort to a more artisanal solution. Note @@ -480,6 +487,21 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, [popupCell setTransparent:YES]; [popupCell setMenu:m_nativeMenu]; [popupCell selectItem:nsItem]; + + int availableHeight = screen->availableSize().height(); + const QPoint &globalPos = parentWindow->mapToGlobal(pos); + int menuHeight = m_nativeMenu.size.height; + if (globalPos.y() + menuHeight > availableHeight) { + // Maybe we need to fix the vertical popup position but we don't know the + // exact popup height at the moment (and Cocoa is just guessing) nor its + // position. So, instead of translating by the popup's full height, we need + // to estimate where the menu will show up and translate by the remaining height. + float idx = ([m_nativeMenu indexOfItem:nsItem] + 1.0f) / m_nativeMenu.numberOfItems; + float heightBelowPos = (1.0 - idx) * menuHeight; + if (globalPos.y() + heightBelowPos > availableHeight) + pos.setY(pos.y() - globalPos.y() + availableHeight - heightBelowPos); + } + NSRect cellFrame = NSMakeRect(pos.x(), pos.y(), m_nativeMenu.minimumWidth, 10); [popupCell performClickWithFrame:cellFrame inView:view]; } else { @@ -488,22 +510,21 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, if (view) { // convert coordinates from view to the view's window nsPos = [view convertPoint:nsPos toView:nil]; - } else if (!QGuiApplication::screens().isEmpty()) { - QScreen *screen = QGuiApplication::screens().at(0); + } else { nsPos.y = screen->availableVirtualSize().height() - nsPos.y; } if (view) { // Finally, we need to synthesize an event. NSEvent *menuEvent = [NSEvent mouseEventWithType:NSRightMouseDown - location:nsPos - modifierFlags:0 - timestamp:0 - windowNumber:view ? view.window.windowNumber : 0 - context:nil - eventNumber:0 - clickCount:1 - pressure:1.0]; + location:nsPos + modifierFlags:0 + timestamp:0 + windowNumber:view ? view.window.windowNumber : 0 + context:nil + eventNumber:0 + clickCount:1 + pressure:1.0]; [NSMenu popUpContextMenu:m_nativeMenu withEvent:menuEvent forView:view]; } else { [m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:0]; From 6918c0a15ba049d7e0de2302846dfadce4866861 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 3 Sep 2015 19:07:18 -0700 Subject: [PATCH 052/240] Add Qt 5.5.1 changelog with updated 5.7 future direction notice We should carry this in all 5.5.x and 5.6.x releases, to make sure everyone gets the message. But for this release, we need to note the changes from what was announced for 5.5.0: Clang 3.2 cannot compile std::atomic properly, so it will not be supported. That means the minimum XCode version we'll require will be 5.1, which fortunately does not raise the minimum OS X version that can compile Qt. See http://llvm.org/bugs/show_bug.cgi?id=12670 for more information. ICC 14.x and 15.x on Windows miscompiles pointer-to-members across DLL boundaries, so signal-slot connections fail. See QTBUG-40281. Change-Id: I42e7ef1a481840699a8dffff1400a4377fcf4589 Reviewed-by: Lars Knoll --- dist/changes-5.5.1 | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 dist/changes-5.5.1 diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1 new file mode 100644 index 0000000000..23e6c95f44 --- /dev/null +++ b/dist/changes-5.5.1 @@ -0,0 +1,50 @@ +Qt 5.5.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.5.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://doc.qt.io/qt-5.5/ + +The Qt version 5.5 series is binary compatible with the 5.4.x series. +Applications compiled for 5.4 will continue to run with 5.5. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://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 * +**************************************************************************** + +**************************************************************************** +* Future Direction Notice * +**************************************************************************** + + - Qt 5.7 will begin requiring certain C++11 features in order to + compile. Due to bugs in the Clang compiler that comes with XCode 5.0, + that version will not be supported, despite what was noted in the Qt + 5.5.0 changelog. + The minimum compiler versions for Qt 5.7 release will be: + * Clang 3.3 (XCode 5.1 contains version 3.4) + * GCC 4.7 + * Intel C++ Composer XE 2013 SP1 (compiler version 14.0) on Linux and OS X + * Intel C++ Composer XE 2016 (compiler version 16.0) on Windows + * Microsoft Visual Studio 2012 (compiler version 17.0) + +**************************************************************************** +* Library * +**************************************************************************** + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + + +**************************************************************************** +* Tools * +**************************************************************************** From deb6b5032c8eed35021b3c697a770645d90b11ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89meric=20MASCHINO?= Date: Wed, 9 Sep 2015 22:56:32 +0200 Subject: [PATCH 053/240] Fixed compilation errors in qatomic_ia64.h QBasicAtomicOps::testAndSetRelaxed(T &, T, T) and QBasicAtomicOps::testAndSetOrdered(T &, T, T) bodies don't match any prototypes in qatomic_ia64.h: the optional parameter T *currentValue is missing. Task-number: QTBUG-48197 Change-Id: I0112c429b161b4a0ddb6e8a0400a436282ffb1c7 Reviewed-by: Thiago Macieira --- src/corelib/arch/qatomic_ia64.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/corelib/arch/qatomic_ia64.h b/src/corelib/arch/qatomic_ia64.h index c880e85209..2ba6d127d9 100644 --- a/src/corelib/arch/qatomic_ia64.h +++ b/src/corelib/arch/qatomic_ia64.h @@ -1035,16 +1035,16 @@ bool QBasicAtomicOps::deref(T &_q_value) Q_DECL_NOTHROW } template template inline -bool QBasicAtomicOps::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { - return testAndSetAcquire(_q_value, expectedValue, newValue); + return testAndSetAcquire(_q_value, expectedValue, newValue, currentValue); } template template inline -bool QBasicAtomicOps::testAndSetOrdered(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps::testAndSetOrdered(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { orderedMemoryFence(_q_value); - return testAndSetAcquire(_q_value, expectedValue, newValue); + return testAndSetAcquire(_q_value, expectedValue, newValue, currentValue); } template template inline From 9f452719f368816787e3640b84cb25f53149f15d Mon Sep 17 00:00:00 2001 From: Tuomas Heimonen Date: Wed, 20 May 2015 14:03:17 +0300 Subject: [PATCH 054/240] tst_QUndoGroup, tst_QUndoStack Fixed flag QT_NO_PROCESS Change-Id: I6c36475e343de72c954fcc917132977eb1f8d61a Reviewed-by: Tuomas Heimonen Reviewed-by: Marko Kangas Reviewed-by: Friedemann Kleint --- tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp | 8 ++++---- tests/auto/widgets/util/qundostack/tst_qundostack.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp b/tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp index f19ef391ff..781adeedad 100644 --- a/tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp +++ b/tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp @@ -193,9 +193,7 @@ private slots: void deleteStack(); void checkSignals(); void addStackAndDie(); -#ifndef QT_NO_PROCESS void commandTextFormat(); -#endif }; tst_QUndoGroup::tst_QUndoGroup() @@ -599,9 +597,11 @@ void tst_QUndoGroup::addStackAndDie() delete stack; } -#ifndef QT_NO_PROCESS void tst_QUndoGroup::commandTextFormat() { +#ifdef QT_NO_PROCESS + QSKIP("No QProcess available"); +#else QString binDir = QLibraryInfo::location(QLibraryInfo::BinariesPath); if (QProcess::execute(binDir + "/lrelease -version") != 0) @@ -643,8 +643,8 @@ void tst_QUndoGroup::commandTextFormat() QCOMPARE(redo_action->text(), QString("redo-prefix append redo-suffix")); qApp->removeTranslator(&translator); -} #endif +} #else class tst_QUndoGroup : public QObject diff --git a/tests/auto/widgets/util/qundostack/tst_qundostack.cpp b/tests/auto/widgets/util/qundostack/tst_qundostack.cpp index 29bc14f372..2c8a9a3ee5 100644 --- a/tests/auto/widgets/util/qundostack/tst_qundostack.cpp +++ b/tests/auto/widgets/util/qundostack/tst_qundostack.cpp @@ -239,9 +239,7 @@ private slots: void macroBeginEnd(); void compression(); void undoLimit(); -#ifndef QT_NO_PROCESS void commandTextFormat(); -#endif void separateUndoText(); }; @@ -2958,9 +2956,11 @@ void tst_QUndoStack::undoLimit() true); // redoChanged } -#ifndef QT_NO_PROCESS void tst_QUndoStack::commandTextFormat() { +#ifdef QT_NO_PROCESS + QSKIP("No QProcess available"); +#else QString binDir = QLibraryInfo::location(QLibraryInfo::BinariesPath); if (QProcess::execute(binDir + "/lrelease -version") != 0) @@ -2999,8 +2999,8 @@ void tst_QUndoStack::commandTextFormat() QCOMPARE(redo_action->text(), QString("redo-prefix append redo-suffix")); qApp->removeTranslator(&translator); -} #endif +} void tst_QUndoStack::separateUndoText() { From 020ddba56e8cf477d3c6c78d00e6137d7cc50355 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Mon, 14 Sep 2015 09:56:41 +0200 Subject: [PATCH 055/240] Revert "Cocoa: correct QDesktopWidget::availableGeometry()" Wrong calculation of flip. This reverts commit 1a5cc2a868969f1b1e9278c4145b7af2fc4b8f69. Task-number: QTBUG-47030 Change-Id: Ide178eb5e027c4ecec1e3952c973fb64987eb7ce Reviewed-by: Jake Petroules --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 8f84539e04..c8f6dd05db 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -86,17 +86,9 @@ void QCocoaScreen::updateGeometry() NSRect frameRect = [nsScreen frame]; - // Since Mavericks, there is a setting, System Preferences->Mission Control-> - // Displays have separate Spaces. - BOOL spansDisplays = NO; -#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9) - spansDisplays = [NSScreen screensHaveSeparateSpaces]; -#endif - if (spansDisplays || m_screenIndex == 0) { + if (m_screenIndex == 0) { m_geometry = QRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); - // Displays have separate Spaces setting is on or this is the primary screen, - // the one that contains the menubar. Its origin should be + // This is the primary screen, the one that contains the menubar. Its origin should be // (0, 0), and it's the only one whose available geometry differs from its full geometry. NSRect visibleRect = [nsScreen visibleFrame]; m_availableGeometry = QRect(visibleRect.origin.x, From 0de6c52bfe2433eca768a5f6fe9d5f08a545c254 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Fri, 28 Aug 2015 18:20:04 +0200 Subject: [PATCH 056/240] Fix QMYSQL plugin database connection setup check Opening a connection to an e.g. inactive server will return true regardless of the server accessibility. This patch aims to fix the current checks done. The first one is an allocation check which should only fail if there's not enough memory but is currently wrote as if the connection failed there. The second check that is "failing" is the connection setup. The return value should either be NULL or the same value provided as first parameter. That is now verified. [ChangeLog][QtSql][QSqlDatabase] Fixed a bug where opening a connection to a MySQL database using the QMYSQL plugin would always return true even if the server was unreachable. This bug could also lead to crashes depending on the platform used. Task-number: QTBUG-47784 Task-number: QTBUG-47452 Change-Id: I91651684b5a342eaa7305473e26d8371b35396c4 Reviewed-by: Andy Shaw --- src/sql/drivers/mysql/qsql_mysql.cpp | 41 ++++++++++++++++------------ 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index d901008e00..8ac7f765e2 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -1282,19 +1282,21 @@ bool QMYSQLDriver::open(const QString& db, if (writeTimeout != 0) mysql_options(d->mysql, MYSQL_OPT_WRITE_TIMEOUT, &writeTimeout); #endif - if (mysql_real_connect(d->mysql, - host.isNull() ? static_cast(0) - : host.toLocal8Bit().constData(), - user.isNull() ? static_cast(0) - : user.toLocal8Bit().constData(), - password.isNull() ? static_cast(0) - : password.toLocal8Bit().constData(), - db.isNull() ? static_cast(0) - : db.toLocal8Bit().constData(), - (port > -1) ? port : 0, - unixSocket.isNull() ? static_cast(0) - : unixSocket.toLocal8Bit().constData(), - optionFlags)) { + MYSQL *mysql = mysql_real_connect(d->mysql, + host.isNull() ? static_cast(0) + : host.toLocal8Bit().constData(), + user.isNull() ? static_cast(0) + : user.toLocal8Bit().constData(), + password.isNull() ? static_cast(0) + : password.toLocal8Bit().constData(), + db.isNull() ? static_cast(0) + : db.toLocal8Bit().constData(), + (port > -1) ? port : 0, + unixSocket.isNull() ? static_cast(0) + : unixSocket.toLocal8Bit().constData(), + optionFlags); + + if (mysql == d->mysql) { if (!db.isEmpty() && mysql_select_db(d->mysql, db.toLocal8Bit().constData())) { setLastError(qMakeError(tr("Unable to open database '%1'").arg(db), QSqlError::ConnectionError, d)); mysql_close(d->mysql); @@ -1305,12 +1307,17 @@ bool QMYSQLDriver::open(const QString& db, if (reconnect) mysql_options(d->mysql, MYSQL_OPT_RECONNECT, &reconnect); #endif + } else { + setLastError(qMakeError(tr("Unable to connect"), + QSqlError::ConnectionError, d)); + mysql_close(d->mysql); + d->mysql = NULL; + setOpenError(true); + return false; } } else { - setLastError(qMakeError(tr("Unable to connect"), - QSqlError::ConnectionError, d)); - mysql_close(d->mysql); - d->mysql = NULL; + setLastError(qMakeError(tr("Failed to allocated data"), + QSqlError::UnknownError, d)); setOpenError(true); return false; } From 07d4113f8f94bddf12437ac3205dce1b6d8fab7d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 15 Sep 2015 16:17:16 +0200 Subject: [PATCH 057/240] buildsystem changelog for 5.5.1 Change-Id: I310f9eff657e9730830cd5c302bdfc46fe67febc Reviewed-by: Joerg Bornemann --- dist/changes-5.5.1 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1 index 23e6c95f44..3b926bd7f2 100644 --- a/dist/changes-5.5.1 +++ b/dist/changes-5.5.1 @@ -48,3 +48,22 @@ information about a particular change. **************************************************************************** * Tools * **************************************************************************** + +configure & build system +------------------------ + + - [QTBUG-46125] Fixed misuse of target linker features for host tools. + - [QTBUG-46473] QML plugin DLLs now have version information. + +qmake +----- + + - [QTBUG-46824][Darwin] Characters in the bundle identifier which + the App Store considers invalid are now substituted. + - [QTBUG-47065][Unix] Fixed use of CONFIG+=separate_debug_info together + with CONFIG+=unversioned_libname. + - [QTBUG-47450][Xcode] Fixed Info.plist creation in shadow builds. + - [QTBUG-47775][Darwin] Fixed Info.plist creation when bundle name + contains spaces. + - [QTBUG-48110][VS] Fixed VS2015 solution file generation. + - [MSVC][nmake] Fixed use of VS2013 mkspecs from VS2015 shell. From e3fa2cb660b70d3b45a047bdb055959e36e8445f Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Fri, 22 May 2015 13:09:57 +0300 Subject: [PATCH 058/240] Fix regression with QStandardPaths::standardLocations on Windows Commit f3bc9f5c5cee9dac8a7815c2861a9945b5341390 broke standardLocations by replacing them with same paths as writeable locations would return. Task-number: QTBUG-46279 Change-Id: I43150e3af13320a707c7882dd0f0cdcb2c6e8a70 Reviewed-by: Friedemann Kleint Reviewed-by: David Faure --- src/corelib/io/qstandardpaths_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index b1d5821a97..615f85a279 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -200,7 +200,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) case AppDataLocation: case AppLocalDataLocation: case GenericDataLocation: - if (SHGetSpecialFolderPath(0, path, clsidForAppDataLocation(type), FALSE)) { + if (SHGetSpecialFolderPath(0, path, CSIDL_COMMON_APPDATA, FALSE)) { QString result = convertCharArray(path); if (type != GenericDataLocation && type != GenericConfigLocation) { #ifndef QT_BOOTSTRAPPED From d4ebbac1b3c6abbdbf5a67c75460c33998847233 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 17 Sep 2015 18:06:57 +0200 Subject: [PATCH 059/240] fix parsing of WinRT compiler options Set defaults before parsing compiler options. UsePrecompiledHeader, CompileAsWinRT and GenerateWindowsMetadata options were overwritten after parsing the options. Task-number: QTBUG-46978 Change-Id: I8c4e423cd13f575fa679b114108b693937908549 Reviewed-by: Oswald Buddenhagen Reviewed-by: Andrew Knight --- qmake/generators/win32/msvc_vcproj.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 9acfa6588b..895bfbaf0d 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -1037,6 +1037,17 @@ void VcprojGenerator::initConfiguration() conf.suppressUnknownOptionWarnings = project->isActiveConfig("suppress_vcproj_warnings"); conf.CompilerVersion = which_dotnet_version(project->first("MSVC_VER").toLatin1()); + if (conf.CompilerVersion >= NET2012) { + conf.WinRT = project->isActiveConfig("winrt"); + if (conf.WinRT) { + conf.WinPhone = project->isActiveConfig("winphone"); + // Saner defaults + conf.compiler.UsePrecompiledHeader = pchNone; + conf.compiler.CompileAsWinRT = _False; + conf.linker.GenerateWindowsMetadata = _False; + } + } + initCompilerTool(); // Only on configuration per build @@ -1083,17 +1094,6 @@ void VcprojGenerator::initConfiguration() conf.PrimaryOutputExtension = '.' + targetSuffix; } - if (conf.CompilerVersion >= NET2012) { - conf.WinRT = project->isActiveConfig("winrt"); - if (conf.WinRT) { - conf.WinPhone = project->isActiveConfig("winphone"); - // Saner defaults - conf.compiler.UsePrecompiledHeader = pchNone; - conf.compiler.CompileAsWinRT = _False; - conf.linker.GenerateWindowsMetadata = _False; - } - } - conf.Name = project->values("BUILD_NAME").join(' '); if (conf.Name.isEmpty()) conf.Name = isDebug ? "Debug" : "Release"; From 0e647aeb6a49a0fc9b5605031f246bb79dd6a6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Tue, 15 Sep 2015 18:17:06 +0200 Subject: [PATCH 060/240] Blacklist PowerVR Rogue G6200 (v1.3) from supporting BGRA. The drivers for PowerVR Rogue G6200 reports BGRA support, but reading from the FBO does not produce the correct result. Initially reported here: http://launchpad.net/bugs/1436074 Change-Id: Ia173817d557446818d08609d943eb3573b900cc3 Reviewed-by: Gunnar Sletta --- src/gui/opengl/qopenglframebufferobject.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index 8d298496df..1cf748d15f 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -43,6 +43,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -1141,9 +1142,19 @@ static inline QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool includ #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN // Without GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA only makes sense on little endian. - const bool supports_bgra = context->isOpenGLES() - ? context->hasExtension(QByteArrayLiteral("GL_EXT_read_format_bgra")) - : context->hasExtension(QByteArrayLiteral("GL_EXT_bgra")); + const bool has_bgra_ext = context->isOpenGLES() + ? context->hasExtension(QByteArrayLiteral("GL_EXT_read_format_bgra")) + : context->hasExtension(QByteArrayLiteral("GL_EXT_bgra")); + + const char *renderer = reinterpret_cast(funcs->glGetString(GL_RENDERER)); + const char *ver = reinterpret_cast(funcs->glGetString(GL_VERSION)); + + // Blacklist PowerVR Rogue G6200 as it has problems with its BGRA support. + const bool blackListed = (qstrcmp(renderer, "PowerVR Rogue G6200") == 0 + && ::strstr(ver, "1.3") != 0); + + const bool supports_bgra = has_bgra_ext && !blackListed; + if (supports_bgra) { QImage img(size, include_alpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, img.bits()); From 9b9f86985ff711838d9d1b486ed10823ba02a681 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 18 Sep 2015 15:05:37 +0200 Subject: [PATCH 061/240] Fix compilation with QT_NO_[DEBUG|WARNING]_OUTPUT Change-Id: I4b92ac6b917c9979449b4834764497003d6de087 Reviewed-by: Friedemann Kleint --- src/corelib/io/qiodevice.cpp | 6 ++++++ src/plugins/platforms/windows/qwindowsopengltester.cpp | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index b908ae3145..cd448ad9cf 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -82,6 +82,7 @@ void debugBinaryString(const char *data, qint64 maxlen) static void checkWarnMessage(const QIODevice *device, const char *function, const char *what) { +#ifndef QT_NO_WARNING_OUTPUT QDebug d = qWarning(); d.noquote(); d.nospace(); @@ -97,6 +98,11 @@ static void checkWarnMessage(const QIODevice *device, const char *function, cons Q_UNUSED(device) #endif // !QT_NO_QOBJECT d << ": " << what; +#else + Q_UNUSED(device); + Q_UNUSED(function); + Q_UNUSED(what); +#endif // QT_NO_WARNING_OUTPUT } #define CHECK_MAXLEN(function, returnType) \ diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index 810fddbca7..9ebd946ce4 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -276,7 +276,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedGlesRenderers() { const GpuDescription gpu = GpuDescription::detect(); const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, true); - qDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result; + qCDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result; return result; } @@ -284,7 +284,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers() { const GpuDescription gpu = GpuDescription::detect(); const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, false); - qDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result; + qCDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result; return result; } From d37643c4336ac87903647ed3cdad65a9e0357f82 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 17 Sep 2015 11:29:46 +0200 Subject: [PATCH 062/240] Cocoa integration - make tool window resizable again Tool window always had NSResizableWindowMask before dd02c1eb38c6dfc8367f2c692e11897b6c00b097, and this is broken, the new logic depends on WindowMaximizeButtonHint which is not set on, for example, un-docked widget. Bring the old behavior back, while not cancelling dd02c1e - make it resizable unconditionally, as it always was. Task-number: QTBUG-46882 Change-Id: Ib739a701d85aaadab83230deee808757de6b5e21 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoawindow.mm | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 3188463dbe..84667350d7 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -800,13 +800,10 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) return styleMask; if ((type & Qt::Popup) == Qt::Popup) { if (!windowIsPopupType(type)) { - styleMask = NSUtilityWindowMask; + styleMask = NSUtilityWindowMask | NSResizableWindowMask; if (!(flags & Qt::CustomizeWindowHint)) { - styleMask |= NSResizableWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | NSTitledWindowMask; + styleMask |= NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask; } else { - if (flags & Qt::WindowMaximizeButtonHint) - styleMask |= NSResizableWindowMask; if (flags & Qt::WindowTitleHint) styleMask |= NSTitledWindowMask; if (flags & Qt::WindowCloseButtonHint) From ff1275a3bed82ddec0904e07675794a7c242c935 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 19 Sep 2015 10:09:10 -0700 Subject: [PATCH 063/240] Fix detection of uClibc version numbers Major << 16 is 0x90000. Reported in QTBUG-45139 Change-Id: I42e7ef1a481840699a8dffff14057022bc4df8e9 Reviewed-by: Oswald Buddenhagen Reviewed-by: Rafael Roquetto --- src/3rdparty/forkfd/forkfd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index 55dc92fe45..ec24ba7b16 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -45,12 +45,12 @@ #ifdef __linux__ # if defined(__BIONIC__) || (defined(__GLIBC__) && (__GLIBC__ << 8) + __GLIBC_MINOR__ >= 0x207 && \ - (!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x921))) + (!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x90201))) # include # define HAVE_EVENTFD 1 # endif # if defined(__BIONIC__) || (defined(__GLIBC__) && (__GLIBC__ << 8) + __GLIBC_MINOR__ >= 0x209 && \ - (!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x921))) + (!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x90201))) # define HAVE_PIPE2 1 # endif #endif From bb6d57479c508e45ad781f07206d448cfcca8669 Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Fri, 14 Aug 2015 16:41:19 +0300 Subject: [PATCH 064/240] Remove confusing license information from torrent.qdoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The torrent example does not have its own code to work with SHA-1, it uses QCryptographicHash instead. Change-Id: Ided0e3dcded1096feb3366682c97530c4cec0a14 Reviewed-by: Lisandro Damián Nicanor Pérez Meyer Reviewed-by: Sami Makkonen Reviewed-by: Topi Reiniö --- examples/network/doc/src/torrent.qdoc | 33 --------------------------- 1 file changed, 33 deletions(-) diff --git a/examples/network/doc/src/torrent.qdoc b/examples/network/doc/src/torrent.qdoc index 08857f02d3..9576e08cfa 100644 --- a/examples/network/doc/src/torrent.qdoc +++ b/examples/network/doc/src/torrent.qdoc @@ -35,37 +35,4 @@ supported by the Qt Network APIs. \image torrent-example.png - - \section1 License Information - - The implementation of the US Secure Hash Algorithm 1 (SHA1) in this example is - derived from the original description in \l{http://www.rfc-editor.org/rfc/rfc3174.txt}{RFC 3174}. - - \legalese - Copyright (C) The Internet Society (2001). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - \endlegalese */ From 363e6e3d52ff7a048f0db9166f6e43137c92669c Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 21 Sep 2015 11:25:54 +0200 Subject: [PATCH 065/240] fix error message The error message mentioned a wrong function name. Change-Id: Ia2258744fd9268af6b00f54e74d40476ded3b0d2 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qwindowspipereader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index 14aad0e193..c1f5d2aace 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -187,7 +187,7 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode, pipeBroken = true; break; default: - emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead")); + emit winError(errorCode, QLatin1String("QWindowsPipeReader::notified")); pipeBroken = true; break; } From c7fa644c3880fada2e7047bcb46ec5e2c8d1b239 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 16 Sep 2015 15:18:24 +0200 Subject: [PATCH 066/240] QFileDialog: preserve window state after delayed widget dialog creation The widget UI for a QFileDialog is sometimes created lazily as a fallback when the dialog is about to show (the reson being that the platform reports that is has native dialogs, but fails showing it, perhaps because of unsupported configuration). In that case, the widget setup code will resize the dialog to default sizes, and as such, wipe out any explicitly set geometry or window states. This is especially visible on iOS, since there we show all windows maximized by default. If the fallback triggers, the dialog will loose the maximized state and be shown partially outside the screen without a way to close it. This patch will make sure that even if the widgets are created late, we still respect any geometry or window states set by the application. Note: The bug became visible after: 6468cf4e Change-Id: Ib2b87cd24e959c547208aa1cf76d683b9cbc283a Reviewed-by: Gabriel de Dietrich --- src/widgets/dialogs/qfiledialog.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index c9e6a199c4..2d4ba1aeb9 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2806,6 +2806,13 @@ void QFileDialogPrivate::createWidgets() if (qFileDialogUi) return; Q_Q(QFileDialog); + + // This function is sometimes called late (e.g as a fallback from setVisible). In that case we + // need to ensure that the following UI code (setupUI in particular) doesn't reset any explicitly + // set window state or geometry. + QSize preSize = q->testAttribute(Qt::WA_Resized) ? q->size() : QSize(); + Qt::WindowStates preState = q->windowState(); + model = new QFileSystemModel(q); model->setFilter(options->filter()); model->setObjectName(QLatin1String("qt_filesystem_model")); @@ -2967,7 +2974,8 @@ void QFileDialogPrivate::createWidgets() lineEdit()->selectAll(); _q_updateOkButton(); retranslateStrings(); - q->resize(q->sizeHint()); + q->resize(preSize.isValid() ? preSize : q->sizeHint()); + q->setWindowState(preState); } void QFileDialogPrivate::_q_showHeader(QAction *action) From a6161563e65b398b0e16ed35e97c8828a0ec0526 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 22 Sep 2015 14:39:52 +0200 Subject: [PATCH 067/240] Fixed pageLayout, pageSize, pageOrientation, pageMargins for QPdfWriter Task-number: QTBUG-46887 Change-Id: I8f1497a8b7ff13213879de01fcdfcabfdd471874 Reviewed-by: Gunnar Sletta Reviewed-by: Friedemann Kleint --- src/gui/painting/qpdfwriter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/painting/qpdfwriter.cpp b/src/gui/painting/qpdfwriter.cpp index ca411ebe08..a8c1d8297c 100644 --- a/src/gui/painting/qpdfwriter.cpp +++ b/src/gui/painting/qpdfwriter.cpp @@ -151,7 +151,8 @@ QPdfWriter::QPdfWriter(const QString &filename) Constructs a PDF writer that will write the pdf to \a device. */ QPdfWriter::QPdfWriter(QIODevice *device) - : QObject(*new QPdfWriterPrivate) + : QObject(*new QPdfWriterPrivate), + QPagedPaintDevice(new QPdfPagedPaintDevicePrivate(d_func())) { Q_D(QPdfWriter); From 71df75966db5f51c66bff1c436dd1cb5a895b51b Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Fri, 21 Aug 2015 18:03:46 +0100 Subject: [PATCH 068/240] Set positionAutomatic when using setX setY QWindow keeps track of whether a position has been explicitly set by use of a flag positionAutomatic which gets set in setGeometry. This is used to determine if position is passed to the window manager. However calls to setX, setY via properties did not update this flag if the caller is setting it to the default position 0,0. This patch fixes that by making sure the flag is always updated. Change-Id: I2c0c002fe57efa101b3ca79e6e8b3f36cc465761 Reviewed-by: Kai Uwe Broulik Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/gui/kernel/qwindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index b54e85a1d3..871437efb1 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1270,8 +1270,11 @@ void QWindow::setMinimumSize(const QSize &size) */ void QWindow::setX(int arg) { + Q_D(QWindow); if (x() != arg) setGeometry(QRect(arg, y(), width(), height())); + else + d->positionAutomatic = false; } /*! @@ -1280,8 +1283,11 @@ void QWindow::setX(int arg) */ void QWindow::setY(int arg) { + Q_D(QWindow); if (y() != arg) setGeometry(QRect(x(), arg, width(), height())); + else + d->positionAutomatic = false; } /*! From ec6556a2b99df373eb43ca009340a7f0f19bacbd Mon Sep 17 00:00:00 2001 From: David Faure Date: Sat, 1 Aug 2015 15:50:00 +0200 Subject: [PATCH 069/240] Fix two data races in QThread/QThreadData * theMainThread is written by the main thread and read by QThreadData::~QThreadData() (any managed thread) * QThreadData::thread is written by QThread::~QThread (in the parent thread) and read+written by QThreadData::~QThreadData (in the managed thread). This can happen because QThreadData is refcounted so the managed thread (which derefs it) races with the parent thread (which sets it to 0). Change-Id: I72de793716391a0937254cda6b4328fcad5060c7 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qcoreapplication.cpp | 12 ++++++------ src/corelib/kernel/qcoreapplication_p.h | 2 +- src/corelib/kernel/qobject.cpp | 2 +- src/corelib/thread/qthread_p.h | 2 +- src/corelib/thread/qthread_unix.cpp | 2 +- src/corelib/thread/qthread_win.cpp | 2 +- src/corelib/thread/qthreadstorage.cpp | 6 +++--- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 37a26cf556..24427bd1af 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -460,8 +460,8 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint qt_application_thread_id = QThread::currentThreadId(); # endif - // note: this call to QThread::currentThread() may end up setting theMainThread! - if (QThread::currentThread() != theMainThread) + QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread! + if (cur != theMainThread) qWarning("WARNING: QApplication was not created in the main() thread."); #endif } @@ -531,11 +531,11 @@ void QCoreApplicationPrivate::eventDispatcherReady() { } -QThread *QCoreApplicationPrivate::theMainThread = 0; +QBasicAtomicPointer QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(0); QThread *QCoreApplicationPrivate::mainThread() { - Q_ASSERT(theMainThread != 0); - return theMainThread; + Q_ASSERT(theMainThread.load() != 0); + return theMainThread.load(); } void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver) @@ -2671,7 +2671,7 @@ bool QCoreApplication::hasPendingEvents() QAbstractEventDispatcher *QCoreApplication::eventDispatcher() { if (QCoreApplicationPrivate::theMainThread) - return QCoreApplicationPrivate::theMainThread->eventDispatcher(); + return QCoreApplicationPrivate::theMainThread.load()->eventDispatcher(); return 0; } diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index 2646a28d71..e985f8d052 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -105,7 +105,7 @@ public: } void maybeQuit(); - static QThread *theMainThread; + static QBasicAtomicPointer theMainThread; static QThread *mainThread(); static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data); diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index bcc4e7f8e6..f2c67fb3a0 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1468,7 +1468,7 @@ void QObject::moveToThread(QThread *targetThread) } else if (d->threadData != currentData) { qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n" "Cannot move to target thread (%p)\n", - currentData->thread, d->threadData->thread, targetData ? targetData->thread : Q_NULLPTR); + currentData->thread.load(), d->threadData->thread.load(), targetData ? targetData->thread.load() : Q_NULLPTR); #ifdef Q_OS_MAC qWarning("You might be loading two sets of Qt binaries into the same process. " diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 1ecd682ad1..8331816729 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -269,7 +269,7 @@ public: QStack eventLoops; QPostEventList postEventList; - QThread *thread; + QAtomicPointer thread; Qt::HANDLE threadId; QAtomicPointer eventDispatcher; QVector tls; diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 77093c9cf1..5698a61326 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -225,7 +225,7 @@ QThreadData *QThreadData::current(bool createIfNecessary) data->isAdopted = true; data->threadId = (Qt::HANDLE)pthread_self(); if (!QCoreApplicationPrivate::theMainThread) - QCoreApplicationPrivate::theMainThread = data->thread; + QCoreApplicationPrivate::theMainThread = data->thread.load(); } return data; } diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index c16a2e958c..a4b853d62e 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -121,7 +121,7 @@ QThreadData *QThreadData::current(bool createIfNecessary) threadData->threadId = reinterpret_cast(GetCurrentThreadId()); if (!QCoreApplicationPrivate::theMainThread) { - QCoreApplicationPrivate::theMainThread = threadData->thread; + QCoreApplicationPrivate::theMainThread = threadData->thread.load(); // TODO: is there a way to reflect the branch's behavior using // WinRT API? } else { diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp index 05ab01cc54..37892233f3 100644 --- a/src/corelib/thread/qthreadstorage.cpp +++ b/src/corelib/thread/qthreadstorage.cpp @@ -121,7 +121,7 @@ void **QThreadStorageData::get() const DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p", id, *v, - data->thread); + data->thread.load()); return *v ? v : 0; } @@ -143,7 +143,7 @@ void **QThreadStorageData::set(void *p) DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p", id, value, - data->thread); + data->thread.load()); QMutexLocker locker(&destructorsMutex); DestructorMap *destr = destructors(); @@ -159,7 +159,7 @@ void **QThreadStorageData::set(void *p) // store new data value = p; - DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread, p); + DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread.load(), p); return &value; } From c28bc5f11361960da1bc94a5ea6566ee0fc8397c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20R=C3=B6ssler?= Date: Mon, 6 Jul 2015 17:51:15 +0200 Subject: [PATCH 070/240] QNativeSocketEngine: fix SO_REUSEPORT problems on Linux Commit d1cd75e81af809a46fcf40cd2b39858e238a4d97 introduced the usage of the SO_REUSEPORT socket flag on Unix systems if available. However, on Linux systems this socket option behaves differently from the previously used SO_REUSEADDR socket option. This patch disables the use of the SO_REUSEPORT option to fix rebinding problems on Linux. The option was introduced to improve support on OS X and other BSDs. It is not necessary on Linux. [ChangeLog][QtNetwork][QUdpSocket] Fixed a bug that caused the QAbstractSocket::ShareAddress option not to work on Linux. Change-Id: Ice04b8b9e78400dce193e2c1d73b67e33edf8840 Reviewed-by: Richard J. Moore --- src/network/socket/qnativesocketengine_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 4648a3cb5a..8869d75c8b 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -337,7 +337,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt int n, level; convertToLevelAndOption(opt, socketProtocol, level, n); -#if defined(SO_REUSEPORT) +#if defined(SO_REUSEPORT) && !defined(Q_OS_LINUX) if (opt == QNativeSocketEngine::AddressReusable) { // on OS X, SO_REUSEADDR isn't sufficient to allow multiple binds to the // same port (which is useful for multicast UDP). SO_REUSEPORT is, but From 63cf5d3d26a6f65938c3cdec1734eac9faaaf8cb Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 22 Sep 2015 14:26:24 -0400 Subject: [PATCH 071/240] QNAM: Assign proper channel before sslErrors() emission There can be a race condition where another channel connects and gets the sslErrors() from the socket first. Then the QSslConfiguration from the wrong socket (the default channel 0's socket) was used. Task-number: QTBUG-18722 Change-Id: Ibbfa48c27f181563745daf540fa792a57cc09682 Reviewed-by: Richard J. Moore --- src/network/access/qhttpnetworkconnectionchannel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 257aa13718..477cba267b 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -1066,6 +1066,8 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList &errors) connection->d_func()->pauseConnection(); if (pendingEncrypt && !reply) connection->d_func()->dequeueRequest(socket); + if (reply) // a reply was actually dequeued. + reply->d_func()->connectionChannel = this; // set correct channel like in sendRequest() and queueRequest(); if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP) { if (reply) emit reply->sslErrors(errors); From 8a0be4007d9c333a93dad04a3809166269cc78d8 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Fri, 21 Aug 2015 01:10:53 +0200 Subject: [PATCH 072/240] Doc: update QFileDialog::setSideBarUrls code snippet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The example code uses QDesktopServices::storageLocation which has been replaced by QStandardPaths. This patch fixes this. Change-Id: Ifff25fcb9d85b37ef8247cb4cd9c4c1c8d368780 Reviewed-by: Topi Reiniö --- src/widgets/doc/images/filedialogurls.png | Bin 29132 -> 26724 bytes src/widgets/doc/snippets/filedialogurls.cpp | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/widgets/doc/images/filedialogurls.png b/src/widgets/doc/images/filedialogurls.png index 7d22ef33aef3b4bd7d23ab785da72e3d71f60b9a..4e26bbfb6d69153e0939df5a8a1cc39d1e38d3f8 100644 GIT binary patch literal 26724 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

|IR1)(+WMuk4L=N{9O;Kdb&><-=CWQYBNB#$`V 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 literal 29132 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 diff --git a/src/widgets/doc/snippets/filedialogurls.cpp b/src/widgets/doc/snippets/filedialogurls.cpp index 9e2862b56f..ea771c2050 100644 --- a/src/widgets/doc/snippets/filedialogurls.cpp +++ b/src/widgets/doc/snippets/filedialogurls.cpp @@ -46,8 +46,8 @@ int main(int argv, char **args) //![0] QList urls; - urls << QUrl::fromLocalFile("/home/gvatteka/dev/qt-45") - << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation)); + urls << QUrl::fromLocalFile("/Users/foo/Code/qt5") + << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::MusicLocation).first()); QFileDialog dialog; dialog.setSidebarUrls(urls); From 843199f303652fa2208e50e03987436ca312b791 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Tue, 18 Aug 2015 00:02:24 +0200 Subject: [PATCH 073/240] Add shader files to examples documentation file list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the shader code is not accessible from the examples documentation page. This patch fixes this by adding .glsl to the file extensions list for examples Change-Id: Iafe327d1bd99b78641a89863f9dbaf8112651c45 Reviewed-by: Topi Reiniö --- doc/global/fileextensions.qdocconf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/global/fileextensions.qdocconf b/doc/global/fileextensions.qdocconf index 88e51595f1..ca036619f1 100644 --- a/doc/global/fileextensions.qdocconf +++ b/doc/global/fileextensions.qdocconf @@ -2,7 +2,7 @@ naturallanguage = en outputencoding = UTF-8 sourceencoding = UTF-8 -examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml *.css" +examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml *.css *.glsl" examples.imageextensions = "*.png *.jpg *.gif" headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx" From be2e0f75ae2e55f235b34b402b70628a839b7782 Mon Sep 17 00:00:00 2001 From: jian liang Date: Sun, 20 Sep 2015 23:08:59 +0800 Subject: [PATCH 074/240] Free the QFreeList object allocated memory on exit This memory allocation was introduced in 314c83c0c2f91532654f869b7dc6af1b7e8538da. With a compiler without thread safe statics support mutex.cpp use a function named freelist() to create the global QFreeList object. it will be created when the first time it was accessed, but will never be released. This patch use Q_DESTRUCTOR_FUNCTION to delete this object. Task-number: QTBUG-48359 Change-Id: I4e4716930930aa98630101a1f96de6a7672af9cb Reviewed-by: Thiago Macieira --- src/corelib/thread/qmutex.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 3269ee3ae8..742a572bef 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -571,19 +571,26 @@ FreeList *freelist() return &list; } #else +static QBasicAtomicPointer freeListPtr; + FreeList *freelist() { - static QAtomicPointer list; - FreeList *local = list.loadAcquire(); + FreeList *local = freeListPtr.loadAcquire(); if (!local) { local = new FreeList; - if (!list.testAndSetRelease(0, local)) { + if (!freeListPtr.testAndSetRelease(0, local)) { delete local; - local = list.loadAcquire(); + local = freeListPtr.loadAcquire(); } } return local; } + +static void qFreeListDeleter() +{ + delete freeListPtr.load(); +} +Q_DESTRUCTOR_FUNCTION(qFreeListDeleter) #endif } From c619d2daac9b1f61e8ad2320b59c648b6af6af90 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 22 Sep 2015 13:17:50 +0200 Subject: [PATCH 075/240] QDateTime: Ensure a valid timezone when using the "offset constructor". The timeZone() function used to assert when called on such an object (or, for a release build, return an invalid time zone). Change-Id: I6ae8316b2ad76f1f868e2498f7ce8aa3fcabf4a6 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.cpp | 1 + tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index eb4eff32b4..d6428920e5 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -3123,6 +3123,7 @@ QTimeZone QDateTime::timeZone() const case Qt::UTC: return QTimeZone::utc(); case Qt::OffsetFromUTC: + return QTimeZone(d->m_offsetFromUtc); case Qt::TimeZone: Q_ASSERT(d->m_timeZone.isValid()); return d->m_timeZone; diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 4ab79909e3..df9089057d 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -2170,6 +2170,7 @@ void tst_QDateTime::offsetFromUtc() // Offset constructor QDateTime dt1(QDate(2013, 1, 1), QTime(1, 0, 0), Qt::OffsetFromUTC, 60 * 60); QCOMPARE(dt1.offsetFromUtc(), 60 * 60); + QVERIFY(dt1.timeZone().isValid()); dt1 = QDateTime(QDate(2013, 1, 1), QTime(1, 0, 0), Qt::OffsetFromUTC, -60 * 60); QCOMPARE(dt1.offsetFromUtc(), -60 * 60); From dc716f2dc2df06c40b3709ded81a5b7588f53e7a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 18 Sep 2015 18:01:50 -0700 Subject: [PATCH 076/240] ICC on Windows: Disable ref-qualified member functions in MSVC <= 2013 Like MSVC, ICC on Windows in debug mode always makes calls to dllexported functions instead of inlining them. Since MSVC 2013 doesn't know about ref-qualification of member functions, this creates an incompatibility between DLL creation and DLL use. Task-number: QTBUG-48349 Change-Id: I42e7ef1a481840699a8dffff14053b594810fb42 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Lars Knoll --- src/corelib/global/qcompilerdetection.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 4828d8596a..9f79b3e70c 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -572,6 +572,9 @@ # if _MSC_VER < 1900 // ICC disables unicode string support when compatibility mode with MSVC 2013 or lower is active # undef Q_COMPILER_UNICODE_STRINGS +// Even though ICC knows about ref-qualified members, MSVC 2013 or lower doesn't, so +// certain member functions (like QString::toUpper) may be missing from the DLLs. +# undef Q_COMPILER_REF_QUALIFIERS // Disable constexpr unless the MS headers have constexpr in all the right places too // (like std::numeric_limits::max()) # undef Q_COMPILER_CONSTEXPR From 113a51b61540b1db74b78d30c04fb979b05f210c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 20 Sep 2015 21:33:40 -0700 Subject: [PATCH 077/240] Update the Qt 5.5.1 changelog for qtbase Change-Id: I42e7ef1a481840699a8dffff1405e4154dd6b5dc Reviewed-by: Lars Knoll --- dist/changes-5.5.1 | 73 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1 index 3b926bd7f2..0dd5d6c594 100644 --- a/dist/changes-5.5.1 +++ b/dist/changes-5.5.1 @@ -21,6 +21,11 @@ information about a particular change. * Important Behavior Changes * **************************************************************************** + - [QTBUG-47316] QDebug output for QStrings changed compared to Qt 5.5.0 to + more closely match the output of previous Qt versions. Like Qt 5.5.0, + QDebug will escape non-printable characters, the backslash and quote + characters, but will no longer escape the printable characters. + **************************************************************************** * Future Direction Notice * **************************************************************************** @@ -40,10 +45,76 @@ information about a particular change. * Library * **************************************************************************** +QtCore +------ + + - Logging framework: + * Fixed a bug that would cause a + "%{time boot}" field in the logging framework's pattern to always + display the same value, instead of the time since boot. + + - QDate/QTime: + * Fixed a minor source-incompatibility between Qt 5.4 and 5.5.0 + involving sets of functions overloaded on QTime and some integer or + QDate and some integer. + + - QDir: + * QDir::relativeFilePath() now returns "." instead of an empty string if + the given path is the same as the directory. + + - QLoggingCategory: + * Fixed behavior of default severity passed to constructor or + Q_LOGGING_CATEGORY with regards to QtInfoMsg, which was previously + treated as being more severe than QtFatalMsg. + + - QTimeZone: + * [QTBUG-47037] Fixed a wrong timezone conversion when the POSIX + timezone rule contains a fractional timezone (e.g. VET4:30). + +QtNetwork +--------- + + - [QTBUG-47048] Fix HTTP issues with "Unknown Error" and "Connection + Closed" + [ChangeLog][QtNetwork][Sockets] Read OS/encrypted read buffers when + connection closed by server. + +QtSql +----- + + - QSqlDatabase: + * [QTBUG-47784][QTBUG-47452] Fixed a bug where opening a connection to a + MySQL database using the QMYSQL plugin would always return true even + if the server was unreachable. This bug could also lead to crashes + depending on the platform used. + +QtWidgets +--------- + + - Important behavior changes: + * [QTBUG-46379] Tooltips on OS X are now transparent for mouse events. + **************************************************************************** -* Platform Specific Changes * +* Platform Specific Changes * **************************************************************************** +Windows +------- + + - Text: + * [QTBUG-46963] Fixed crash in DirectWrite engine when constructing a + QRawFont from raw font data. + +**************************************************************************** +* Compiler Specific Changes * +**************************************************************************** + +GCC +--- + + - Fixed a regression introduced Qt 5.5.0 that generated lots of + compiler warnings in Qt public headers when using the (deprecated) + version 4.5 of GCC. **************************************************************************** * Tools * From 3ea04c7d388a1790ff3eda9c67f1e224df48e5aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 21 Sep 2015 13:29:17 +0200 Subject: [PATCH 078/240] Cocoa: Support Qt::WindowTransparentForInput Map this to ignoresMouseEvents on NSWindow. Task-number: QTBUG-45498 Change-Id: I86e518bbf805647d9f12b1af1747355ef55cc167 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoawindow.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 84667350d7..809acdd87e 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1344,6 +1344,9 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) [m_contentView setHidden: YES]; } + m_nsWindow.ignoresMouseEvents = + (window()->flags() & Qt::WindowTransparentForInput) == Qt::WindowTransparentForInput; + const qreal opacity = qt_window_private(window())->opacity; if (!qFuzzyCompare(opacity, qreal(1.0))) setOpacity(opacity); From f0f9f309e03accf17ffcf0a7c8df8f458a73f9f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 23 Sep 2015 14:25:38 +0200 Subject: [PATCH 079/240] Support non-latin1 platform plugin paths Replace two instances of QLatin1String() conversion with QString::fromLocal8Bit() Change-Id: I04336c47b0c030c69e38db9aa4dcd208d7200b63 Task-number: QTBUG-48399 Reviewed-by: Liang Qi Reviewed-by: Thiago Macieira --- src/gui/kernel/qguiapplication.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 7dc8444163..64be8ee3d9 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1116,7 +1116,7 @@ void QGuiApplicationPrivate::createPlatformIntegration() QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, true); // Load the platform integration - QString platformPluginPath = QLatin1String(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH")); + QString platformPluginPath = QString::fromLocal8Bit(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH")); QByteArray platformName; @@ -1146,7 +1146,7 @@ void QGuiApplicationPrivate::createPlatformIntegration() arg.remove(0, 1); if (arg == "-platformpluginpath") { if (++i < argc) - platformPluginPath = QLatin1String(argv[i]); + platformPluginPath = QString::fromLocal8Bit(argv[i]); } else if (arg == "-platform") { if (++i < argc) platformName = argv[i]; From 5445eb35414437672715108a60d07dc413c504d6 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Mon, 21 Sep 2015 11:18:23 +0200 Subject: [PATCH 080/240] QStateMachine: make enterStates/exitStates virtual. This allows handling of state specific code when entering/exiting states during a micro-step. Change-Id: If2fa8dde9a1e209345950a93dee59414063d863e Reviewed-by: Simon Hausmann --- src/corelib/statemachine/qstatemachine_p.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index fe7a06d16b..45c6dfcb33 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -134,16 +134,16 @@ public: virtual void beginMacrostep(); virtual void endMacrostep(bool didChange); virtual void exitInterpreter(); - void exitStates(QEvent *event, const QList &statesToExit_sorted, - const QHash > &assignmentsForEnteredStates); + virtual void exitStates(QEvent *event, const QList &statesToExit_sorted, + const QHash > &assignmentsForEnteredStates); QList computeExitSet(const QList &enabledTransitions, CalculationCache *cache); QSet computeExitSet_Unordered(const QList &enabledTransitions, CalculationCache *cache); QSet computeExitSet_Unordered(QAbstractTransition *t, CalculationCache *cache); void executeTransitionContent(QEvent *event, const QList &transitionList); - void enterStates(QEvent *event, const QList &exitedStates_sorted, - const QList &statesToEnter_sorted, - const QSet &statesForDefaultEntry, - QHash > &propertyAssignmentsForState + virtual void enterStates(QEvent *event, const QList &exitedStates_sorted, + const QList &statesToEnter_sorted, + const QSet &statesForDefaultEntry, + QHash > &propertyAssignmentsForState #ifndef QT_NO_ANIMATION , const QList &selectedAnimations #endif From 58bed4cda98e8e25db8adc61c7db73b6853077dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Nystr=C3=B6m?= Date: Wed, 16 Sep 2015 11:32:57 +0200 Subject: [PATCH 081/240] eglfs: Support for alternative Mali driver packages In addition to the proprietary Mali Linux driver bundle from ARM, there are a couple of semi open source alternative bundles out in the wild, which are mostly derivatives from the sunxi-mali bundle. The non-ARM bundles lacks the proprietary header file fbdev_window.h which defines the fbdev_window struct. Instead, it has an equivalent mali_native_window struct in the EGL/eglplatform.h (which in turn is included by EGL/egl.h). This change adds an alternative configure test which detects the non-ARM bundles are used. It also removes the dependency on fbdev_window.h by defining the structure ourselves, which actually makes the plugin potentially compilable with *any* EGL SDK. Change-Id: I78ab4b618e8e9c774c889fe9896105cf2cf4228e Reviewed-by: Oswald Buddenhagen Reviewed-by: Laszlo Agocs --- .../qpa/eglfs-mali-2/eglfs-mali-2.cpp | 44 +++++++++++++++++++ .../qpa/eglfs-mali-2/eglfs-mali-2.pro | 5 +++ configure | 3 +- .../eglfs_mali/qeglfsmaliintegration.cpp | 6 ++- 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 config.tests/qpa/eglfs-mali-2/eglfs-mali-2.cpp create mode 100644 config.tests/qpa/eglfs-mali-2/eglfs-mali-2.pro diff --git a/config.tests/qpa/eglfs-mali-2/eglfs-mali-2.cpp b/config.tests/qpa/eglfs-mali-2/eglfs-mali-2.cpp new file mode 100644 index 0000000000..1914d6452b --- /dev/null +++ b/config.tests/qpa/eglfs-mali-2/eglfs-mali-2.cpp @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** 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 + +int main(int, char **) +{ + EGLDisplay dpy = 0; + EGLContext ctx = 0; + mali_native_window *w = 0; + eglDestroyContext(dpy, ctx); + return 0; +} diff --git a/config.tests/qpa/eglfs-mali-2/eglfs-mali-2.pro b/config.tests/qpa/eglfs-mali-2/eglfs-mali-2.pro new file mode 100644 index 0000000000..85bcf6484a --- /dev/null +++ b/config.tests/qpa/eglfs-mali-2/eglfs-mali-2.pro @@ -0,0 +1,5 @@ +SOURCES = eglfs-mali-2.cpp + +CONFIG -= qt + +LIBS += -lEGL -lGLESv2 diff --git a/configure b/configure index fcfe8b957f..1b7655d280 100755 --- a/configure +++ b/configure @@ -5729,7 +5729,8 @@ if [ "$CFG_EGLFS" != "no" ]; then else CFG_EGLFS_BRCM=no fi - if compileTest qpa/eglfs-mali "eglfs-mali"; then + if compileTest qpa/eglfs-mali "eglfs-mali" \ + || compileTest qpa/eglfs-mali-2 "eglfs-mali-2"; then CFG_EGLFS_MALI=yes else CFG_EGLFS_MALI=no diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp index 455d78035a..43decdf849 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp @@ -32,7 +32,6 @@ ****************************************************************************/ #include "qeglfsmaliintegration.h" -#include #include #include @@ -43,6 +42,11 @@ QT_BEGIN_NAMESPACE +struct fbdev_window { + unsigned short width; + unsigned short height; +}; + void QEglFSMaliIntegration::platformInit() { // Keep the non-overridden base class functions based on fb0 working. From 98c10a02c5b77e023471ad6993dc66b013889cfb Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Tue, 22 Sep 2015 15:51:52 +0300 Subject: [PATCH 082/240] xcb: Show buttons on the title bar for QWindow QWindow by default doesn't have the window flags to display buttons on the title bar and it's up to the window manager whether they will be shown. For example, fluxbox doesn't show the maximize button. The cocoa plugin and the windows plugin adjust the window flags in this special case of QWindow to show some buttons, so do the same in the xcb plugin. Change-Id: Idc2575cfeaced524dd67eb5ba99126663626e2b0 Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbwindow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index d751c6d48a..6575149d86 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1112,6 +1112,9 @@ 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 (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) { mwmhints.decorations |= MWM_DECOR_BORDER; mwmhints.decorations |= MWM_DECOR_RESIZEH; From 58664dbeb3db5840353c852801a346e1bd8abba2 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Mon, 14 Sep 2015 15:01:48 +0200 Subject: [PATCH 083/240] Doc: fixed links to qmake documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-43810 Change-Id: I56676d6f6f95ed79bd1719404b4e48c26490eea6 Reviewed-by: Topi Reiniö Reviewed-by: Martin Smith --- qmake/doc/src/qmake-manual.qdoc | 3 +-- src/gui/doc/qtgui.qdocconf | 3 ++- src/gui/image/qimage.cpp | 2 +- src/network/doc/qtnetwork.qdocconf | 2 +- src/opengl/doc/qtopengl.qdocconf | 2 +- src/printsupport/doc/qtprintsupport.qdocconf | 2 +- src/sql/doc/qtsql.qdocconf | 2 +- src/widgets/doc/qtwidgets.qdocconf | 2 +- src/xml/doc/qtxml.qdocconf | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index d54dc9569a..da6ce337d2 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -728,8 +728,7 @@ \section2 Creating and Moving Xcode Projects Developers on OS X can take advantage of the qmake support for Xcode - project files, as described in - \l{Qt is OS X Native#Development Tools}{Qt is OS X Native}, + project files, as described in \l{Qt for OS X#Additional Command-Line Options}{Qt for OS X} documentation. by running qmake to generate an Xcode project from an existing qmake project file. For example: diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf index e2194839d2..436e2e0b34 100644 --- a/src/gui/doc/qtgui.qdocconf +++ b/src/gui/doc/qtgui.qdocconf @@ -37,7 +37,8 @@ depends += \ qtqml \ qtquick \ qtwidgets \ - qtdoc + qtdoc \ + qmake headerdirs += .. diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 7f2504ddd9..a69aae87f1 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -313,7 +313,7 @@ bool QImageData::checkForAlphaPixels() const sharing}. QImage objects can also be streamed and compared. \note If you would like to load QImage objects in a static build of Qt, - refer to the \l{How To Create Qt Plugins}{Plugin HowTo}. + refer to the \l{How to Create Qt Plugins}{Plugin HowTo}. \warning Painting on a QImage with the format QImage::Format_Indexed8 is not supported. diff --git a/src/network/doc/qtnetwork.qdocconf b/src/network/doc/qtnetwork.qdocconf index 522d71fd27..2a8e577dda 100644 --- a/src/network/doc/qtnetwork.qdocconf +++ b/src/network/doc/qtnetwork.qdocconf @@ -26,7 +26,7 @@ qhp.QtNetwork.subprojects.classes.sortPages = true tagfile = ../../../doc/qtnetwork/qtnetwork.tags -depends += qtcore qtgui qtdoc +depends += qtcore qtgui qtdoc qmake headerdirs += .. diff --git a/src/opengl/doc/qtopengl.qdocconf b/src/opengl/doc/qtopengl.qdocconf index 5b6d09dfcd..6ff6cae2cb 100644 --- a/src/opengl/doc/qtopengl.qdocconf +++ b/src/opengl/doc/qtopengl.qdocconf @@ -19,7 +19,7 @@ exampledirs += ../../../examples/opengl \ imagedirs += images \ ../../../examples/opengl/doc/images -depends += qtdoc qtcore qtgui qtwidgets +depends += qtdoc qtcore qtgui qtwidgets qmake examplesinstallpath = opengl diff --git a/src/printsupport/doc/qtprintsupport.qdocconf b/src/printsupport/doc/qtprintsupport.qdocconf index 2ec33f6600..fbb6f8d1a9 100644 --- a/src/printsupport/doc/qtprintsupport.qdocconf +++ b/src/printsupport/doc/qtprintsupport.qdocconf @@ -26,7 +26,7 @@ qhp.QtPrintSupport.subprojects.classes.sortPages = true tagfile = ../../../doc/qtprintsupport/qtprintsupport.tags -depends += qtcore qtgui qtwidgets qtdoc +depends += qtcore qtgui qtwidgets qtdoc qmake headerdirs += .. diff --git a/src/sql/doc/qtsql.qdocconf b/src/sql/doc/qtsql.qdocconf index b8632c5260..5a224adeb9 100644 --- a/src/sql/doc/qtsql.qdocconf +++ b/src/sql/doc/qtsql.qdocconf @@ -25,7 +25,7 @@ qhp.QtSql.subprojects.classes.selectors = class fake:headerfile qhp.QtSql.subprojects.classes.sortPages = true tagfile = ../../../doc/qtsql/qtsql.tags -depends += qtcore qtwidgets qtdoc +depends += qtcore qtwidgets qtdoc qmake headerdirs += .. diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf index 1f79d144bf..ab20a8666c 100644 --- a/src/widgets/doc/qtwidgets.qdocconf +++ b/src/widgets/doc/qtwidgets.qdocconf @@ -26,7 +26,7 @@ qhp.QtWidgets.subprojects.classes.sortPages = true tagfile = ../../../doc/qtwidgets/qtwidgets.tags -depends += qtcore qtgui qtdoc qtsql qtdesigner qtquick +depends += qtcore qtgui qtdoc qtsql qtdesigner qtquick qmake headerdirs += .. diff --git a/src/xml/doc/qtxml.qdocconf b/src/xml/doc/qtxml.qdocconf index 419859ac8b..a23915487f 100644 --- a/src/xml/doc/qtxml.qdocconf +++ b/src/xml/doc/qtxml.qdocconf @@ -26,7 +26,7 @@ qhp.QtXml.subprojects.classes.sortPages = true tagfile = ../../../doc/qtxml/qtxml.tags -depends += qtcore qtnetwork qtdoc qtwidgets +depends += qtcore qtnetwork qtdoc qtwidgets qmake headerdirs += .. From 0f2da655ac05ff4d94e1f8171965aa13f22b1c21 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 11 Sep 2015 16:59:27 +0200 Subject: [PATCH 084/240] Remove wrong forward declaration It confuses auto complete Change-Id: Ida86f6c8dcca351339d2b41ad40cf5701f5bb2c4 Reviewed-by: Richard J. Moore --- src/corelib/mimetypes/qmimetype.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/corelib/mimetypes/qmimetype.h b/src/corelib/mimetypes/qmimetype.h index 3c153da21d..054a5841c4 100644 --- a/src/corelib/mimetypes/qmimetype.h +++ b/src/corelib/mimetypes/qmimetype.h @@ -44,7 +44,6 @@ QT_BEGIN_NAMESPACE class QMimeTypePrivate; -class QFileinfo; class QStringList; class QMimeType; From 4954ad6dbc9c37ac4f8b9cae8808c31f1d55c698 Mon Sep 17 00:00:00 2001 From: Takao Fujiwara Date: Wed, 16 Sep 2015 19:33:25 +0900 Subject: [PATCH 085/240] Qt IBus plugin connects to IBus Bus again if ibus-daemon does not run Qt5 applications do not enable IBus when the applications are saved in the session and launched automatically in the next login. This patch checks the IBus socket path and connect to the bus when it's available. Task-number QTBUG-47657 Change-Id: I0883eaa2438fd27455da93f78f392ea3c1abe6b8 Reviewed-by: Lars Knoll --- .../ibus/qibusplatforminputcontext.cpp | 106 +++++++++++++++--- .../ibus/qibusplatforminputcontext.h | 8 ++ 2 files changed, 97 insertions(+), 17 deletions(-) diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index 27fca7c6ed..dca21245aa 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -73,13 +73,18 @@ public: delete connection; } + static QString getSocketPath(); static QDBusConnection *createConnection(); + void initBus(); + void createBusProxy(); + QDBusConnection *connection; QIBusProxy *bus; QIBusInputContextProxy *context; bool valid; + bool busConnected; QString predit; bool needsSurroundingText; }; @@ -88,12 +93,21 @@ public: QIBusPlatformInputContext::QIBusPlatformInputContext () : d(new QIBusPlatformInputContextPrivate()) { - if (d->context) { - connect(d->context, SIGNAL(CommitText(QDBusVariant)), SLOT(commitText(QDBusVariant))); - connect(d->context, SIGNAL(UpdatePreeditText(QDBusVariant,uint,bool)), this, SLOT(updatePreeditText(QDBusVariant,uint,bool))); - connect(d->context, SIGNAL(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint))); - connect(d->context, SIGNAL(RequireSurroundingText()), this, SLOT(surroundingTextRequired())); + QString socketPath = QIBusPlatformInputContextPrivate::getSocketPath(); + QFile file(socketPath); + if (file.open(QFile::ReadOnly)) { + // If KDE session save is used or restart ibus-daemon, + // the applications could run before ibus-daemon runs. + // We watch the getSocketPath() to get the launching ibus-daemon. + m_socketWatcher.addPath(socketPath); + connect(&m_socketWatcher, SIGNAL(fileChanged(QString)), this, SLOT(socketChanged(QString))); } + + m_timer.setSingleShot(true); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(connectToBus())); + + connectToContextSignals(); + QInputMethod *p = qApp->inputMethod(); connect(p, SIGNAL(cursorRectangleChanged()), this, SLOT(cursorRectChanged())); m_eventFilterUseSynchronousMode = false; @@ -117,7 +131,7 @@ bool QIBusPlatformInputContext::isValid() const void QIBusPlatformInputContext::invokeAction(QInputMethod::Action a, int) { - if (!d->valid) + if (!d->busConnected) return; if (a == QInputMethod::Click) @@ -128,7 +142,7 @@ void QIBusPlatformInputContext::reset() { QPlatformInputContext::reset(); - if (!d->valid) + if (!d->busConnected) return; d->context->Reset(); @@ -139,7 +153,7 @@ void QIBusPlatformInputContext::commit() { QPlatformInputContext::commit(); - if (!d->valid) + if (!d->busConnected) return; QObject *input = qApp->focusObject(); @@ -193,7 +207,7 @@ void QIBusPlatformInputContext::update(Qt::InputMethodQueries q) void QIBusPlatformInputContext::cursorRectChanged() { - if (!d->valid) + if (!d->busConnected) return; QRect r = qApp->inputMethod()->cursorRectangle().toRect(); @@ -211,7 +225,7 @@ void QIBusPlatformInputContext::cursorRectChanged() void QIBusPlatformInputContext::setFocusObject(QObject *object) { - if (!d->valid) + if (!d->busConnected) return; if (debug) @@ -291,7 +305,7 @@ void QIBusPlatformInputContext::deleteSurroundingText(int offset, uint n_chars) bool QIBusPlatformInputContext::filterEvent(const QEvent *event) { - if (!d->valid) + if (!d->busConnected) return false; if (!inputMethodAccepted()) @@ -398,12 +412,65 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal call->deleteLater(); } +void QIBusPlatformInputContext::socketChanged(const QString &str) +{ + qCDebug(qtQpaInputMethods) << "socketChanged"; + Q_UNUSED (str); + + m_timer.stop(); + + if (d->context) + disconnect(d->context); + if (d->connection) + d->connection->disconnectFromBus(QLatin1String("QIBusProxy")); + + m_timer.start(100); +} + +// When getSocketPath() is modified, the bus is not established yet +// so use m_timer. +void QIBusPlatformInputContext::connectToBus() +{ + qCDebug(qtQpaInputMethods) << "QIBusPlatformInputContext::connectToBus"; + d->initBus(); + connectToContextSignals(); + + if (m_socketWatcher.files().size() == 0) + m_socketWatcher.addPath(QIBusPlatformInputContextPrivate::getSocketPath()); +} + +void QIBusPlatformInputContext::connectToContextSignals() +{ + if (d->context) { + connect(d->context, SIGNAL(CommitText(QDBusVariant)), SLOT(commitText(QDBusVariant))); + connect(d->context, SIGNAL(UpdatePreeditText(QDBusVariant,uint,bool)), this, SLOT(updatePreeditText(QDBusVariant,uint,bool))); + connect(d->context, SIGNAL(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint))); + connect(d->context, SIGNAL(RequireSurroundingText()), this, SLOT(surroundingTextRequired())); + } +} + QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate() - : connection(createConnection()), + : connection(0), bus(0), context(0), valid(false), + busConnected(false), needsSurroundingText(false) +{ + valid = !QStandardPaths::findExecutable(QString::fromLocal8Bit("ibus-daemon"), QStringList()).isEmpty(); + if (!valid) + return; + initBus(); +} + +void QIBusPlatformInputContextPrivate::initBus() +{ + connection = createConnection(); + busConnected = false; + createBusProxy(); +} + +void QIBusPlatformInputContextPrivate::createBusProxy() { if (!connection || !connection->isConnected()) return; @@ -440,11 +507,11 @@ QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate() context->SetCapabilities(IBUS_CAP_PREEDIT_TEXT|IBUS_CAP_FOCUS|IBUS_CAP_SURROUNDING_TEXT); if (debug) - qDebug(">>>> valid!"); - valid = true; + qDebug(">>>> bus connected!"); + busConnected = true; } -QDBusConnection *QIBusPlatformInputContextPrivate::createConnection() +QString QIBusPlatformInputContextPrivate::getSocketPath() { QByteArray display(qgetenv("DISPLAY")); QByteArray host = "unix"; @@ -462,9 +529,14 @@ QDBusConnection *QIBusPlatformInputContextPrivate::createConnection() if (debug) qDebug() << "host=" << host << "displayNumber" << displayNumber; - QFile file(QDir::homePath() + QLatin1String("/.config/ibus/bus/") + + return QDir::homePath() + QLatin1String("/.config/ibus/bus/") + QLatin1String(QDBusConnection::localMachineId()) + - QLatin1Char('-') + QString::fromLocal8Bit(host) + QLatin1Char('-') + QString::fromLocal8Bit(displayNumber)); + QLatin1Char('-') + QString::fromLocal8Bit(host) + QLatin1Char('-') + QString::fromLocal8Bit(displayNumber); +} + +QDBusConnection *QIBusPlatformInputContextPrivate::createConnection() +{ + QFile file(getSocketPath()); if (!file.open(QFile::ReadOnly)) return 0; diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h index 127db7df8b..a8efd9deb3 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h @@ -37,7 +37,9 @@ #include #include +#include #include +#include #include QT_BEGIN_NAMESPACE @@ -96,10 +98,16 @@ public Q_SLOTS: void deleteSurroundingText(int offset, uint n_chars); void surroundingTextRequired(); void filterEventFinished(QDBusPendingCallWatcher *call); + void socketChanged(const QString &str); + void connectToBus(); private: QIBusPlatformInputContextPrivate *d; bool m_eventFilterUseSynchronousMode; + QFileSystemWatcher m_socketWatcher; + QTimer m_timer; + + void connectToContextSignals(); }; QT_END_NAMESPACE From f322e2aa08d7d2c1e65c50b6e3c10a336c2f2959 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 25 Sep 2015 11:29:10 +0200 Subject: [PATCH 086/240] tst_qprocess: Port to Qt 5 connection syntax. Task-number: QTBUG-47370 Change-Id: I09489a6fb4598238fa5e0120bf751fe5af6f31af Reviewed-by: Joerg Bornemann --- .../auto/corelib/io/qprocess/tst_qprocess.cpp | 100 ++++++++++-------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index caefc3fc21..b66551b524 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -62,6 +62,10 @@ if (ret == false) \ QVERIFY(ret); \ } +typedef void (QProcess::*QProcessFinishedSignal1)(int); +typedef void (QProcess::*QProcessFinishedSignal2)(int, QProcess::ExitStatus); +typedef void (QProcess::*QProcessErrorSignal)(QProcess::ProcessError); + class tst_QProcess : public QObject { Q_OBJECT @@ -260,7 +264,7 @@ void tst_QProcess::simpleStart() process = new QProcess; QSignalSpy spy(process, &QProcess::stateChanged); QVERIFY(spy.isValid()); - connect(process, SIGNAL(readyRead()), this, SLOT(readFromProcess())); + connect(process, &QIODevice::readyRead, this, &tst_QProcess::readFromProcess); /* valgrind dislike SUID binaries(those that have the `s'-flag set), which * makes it fail to start the process. For this reason utilities like `ping' won't @@ -356,8 +360,8 @@ void tst_QProcess::crashTest() qRegisterMetaType("QProcess::ExitStatus"); QSignalSpy spy(process, &QProcess::errorOccurred); - QSignalSpy spy2(process, static_cast(&QProcess::error)); - QSignalSpy spy3(process, static_cast(&QProcess::finished)); + QSignalSpy spy2(process, static_cast(&QProcess::error)); + QSignalSpy spy3(process, static_cast(&QProcess::finished)); QVERIFY(spy.isValid()); QVERIFY(spy2.isValid()); @@ -394,13 +398,14 @@ void tst_QProcess::crashTest2() qRegisterMetaType("QProcess::ProcessError"); qRegisterMetaType("QProcess::ExitStatus"); - QSignalSpy spy(process, static_cast(&QProcess::errorOccurred)); - QSignalSpy spy2(process, static_cast(&QProcess::finished)); + QSignalSpy spy(process, static_cast(&QProcess::errorOccurred)); + QSignalSpy spy2(process, static_cast(&QProcess::finished)); QVERIFY(spy.isValid()); QVERIFY(spy2.isValid()); - QObject::connect(process, SIGNAL(finished(int)), this, SLOT(exitLoopSlot())); + QObject::connect(process, static_cast(&QProcess::finished), + this, &tst_QProcess::exitLoopSlot); QTestEventLoop::instance().enterLoop(30); if (QTestEventLoop::instance().timeout()) @@ -439,7 +444,7 @@ void tst_QProcess::echoTest() QFETCH(QByteArray, input); process = new QProcess; - connect(process, SIGNAL(readyRead()), this, SLOT(exitLoopSlot())); + connect(process, &QIODevice::readyRead, this, &tst_QProcess::exitLoopSlot); process->start("testProcessEcho/testProcessEcho"); QVERIFY(process->waitForStarted(5000)); @@ -489,7 +494,7 @@ void tst_QProcess::echoTest2() { process = new QProcess; - connect(process, SIGNAL(readyRead()), this, SLOT(exitLoopSlot())); + connect(process, &QIODevice::readyRead, this, &tst_QProcess::exitLoopSlot); process->start("testProcessEcho2/testProcessEcho2"); QVERIFY(process->waitForStarted(5000)); @@ -676,7 +681,7 @@ void tst_QProcess::readTimeoutAndThenCrash() qRegisterMetaType("QProcess::ProcessError"); QSignalSpy spy(process, &QProcess::errorOccurred); - QSignalSpy spy2(process, static_cast(&QProcess::error)); + QSignalSpy spy2(process, static_cast(&QProcess::error)); QVERIFY(spy.isValid()); QVERIFY(spy2.isValid()); @@ -751,14 +756,15 @@ void tst_QProcess::restartProcessDeadlock() // because of the way QProcessManager uses its locks. QProcess proc; process = &proc; - connect(process, SIGNAL(finished(int)), this, SLOT(restartProcess())); + connect(process, static_cast(&QProcess::finished), + this, &tst_QProcess::restartProcess); process->start("testProcessEcho/testProcessEcho"); QCOMPARE(process->write("", 1), qlonglong(1)); QVERIFY(process->waitForFinished(5000)); - process->disconnect(SIGNAL(finished(int))); + QObject::disconnect(process, static_cast(&QProcess::finished), Q_NULLPTR, Q_NULLPTR); QCOMPARE(process->write("", 1), qlonglong(1)); QVERIFY(process->waitForFinished(5000)); @@ -878,7 +884,7 @@ void tst_QProcess::emitReadyReadOnlyWhenNewDataArrives() { QProcess proc; - connect(&proc, SIGNAL(readyRead()), this, SLOT(exitLoopSlot())); + connect(&proc, &QIODevice::readyRead, this, &tst_QProcess::exitLoopSlot); QSignalSpy spy(&proc, &QProcess::readyRead); QVERIFY(spy.isValid()); @@ -898,7 +904,7 @@ void tst_QProcess::emitReadyReadOnlyWhenNewDataArrives() QVERIFY(QTestEventLoop::instance().timeout()); QVERIFY(!proc.waitForReadyRead(250)); - QObject::disconnect(&proc, SIGNAL(readyRead()), 0, 0); + QObject::disconnect(&proc, &QIODevice::readyRead, Q_NULLPTR, Q_NULLPTR); proc.write("B"); QVERIFY(proc.waitForReadyRead(5000)); @@ -960,30 +966,30 @@ public: SoftExitProcess(int n) : waitedForFinished(false), n(n), killing(false) { - connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), - this, SLOT(finishedSlot(int,QProcess::ExitStatus))); + connect(this, static_cast(&QProcess::finished), + this, &SoftExitProcess::finishedSlot); switch (n) { case 0: setReadChannelMode(QProcess::MergedChannels); - connect(this, SIGNAL(readyRead()), this, SLOT(terminateSlot())); + connect(this, &QIODevice::readyRead, this, &SoftExitProcess::terminateSlot); break; case 1: - connect(this, SIGNAL(readyReadStandardOutput()), - this, SLOT(terminateSlot())); + connect(this, &QProcess::readyReadStandardOutput, + this, &SoftExitProcess::terminateSlot); break; case 2: - connect(this, SIGNAL(readyReadStandardError()), - this, SLOT(terminateSlot())); + connect(this, &QProcess::readyReadStandardError, + this, &SoftExitProcess::terminateSlot); break; case 3: - connect(this, SIGNAL(started()), - this, SLOT(terminateSlot())); + connect(this, &QProcess::started, + this, &SoftExitProcess::terminateSlot); break; case 4: default: - connect(this, SIGNAL(stateChanged(QProcess::ProcessState)), - this, SLOT(terminateSlot())); + connect(this, &QProcess::stateChanged, + this, &SoftExitProcess::terminateSlot); break; } } @@ -1179,8 +1185,8 @@ protected: exitCode = 90210; QProcess process; - connect(&process, SIGNAL(finished(int)), this, SLOT(catchExitCode(int)), - Qt::DirectConnection); + connect(&process, static_cast(&QProcess::finished), + this, &TestThread::catchExitCode, Qt::DirectConnection); process.start("testProcessEcho/testProcessEcho"); @@ -1260,8 +1266,9 @@ void tst_QProcess::waitForFinishedWithTimeout() void tst_QProcess::waitForReadyReadInAReadyReadSlot() { process = new QProcess(this); - connect(process, SIGNAL(readyRead()), this, SLOT(waitForReadyReadInAReadyReadSlotSlot())); - connect(process, SIGNAL(finished(int)), this, SLOT(exitLoopSlot())); + connect(process, &QIODevice::readyRead, this, &tst_QProcess::waitForReadyReadInAReadyReadSlotSlot); + connect(process, static_cast(&QProcess::finished), + this, &tst_QProcess::exitLoopSlot); bytesAvailable = 0; process->start("testProcessEcho/testProcessEcho"); @@ -1299,7 +1306,7 @@ void tst_QProcess::waitForReadyReadInAReadyReadSlotSlot() void tst_QProcess::waitForBytesWrittenInABytesWrittenSlot() { process = new QProcess(this); - connect(process, SIGNAL(bytesWritten(qint64)), this, SLOT(waitForBytesWrittenInABytesWrittenSlotSlot())); + connect(process, &QIODevice::bytesWritten, this, &tst_QProcess::waitForBytesWrittenInABytesWrittenSlotSlot); bytesAvailable = 0; process->start("testProcessEcho/testProcessEcho"); @@ -1525,9 +1532,9 @@ void tst_QProcess::failToStart() QProcess process; QSignalSpy stateSpy(&process, &QProcess::stateChanged); QSignalSpy errorSpy(&process, &QProcess::errorOccurred); - QSignalSpy errorSpy2(&process, static_cast(&QProcess::error)); - QSignalSpy finishedSpy(&process, static_cast(&QProcess::finished)); - QSignalSpy finishedSpy2(&process, static_cast(&QProcess::finished)); + QSignalSpy errorSpy2(&process, static_cast(&QProcess::error)); + QSignalSpy finishedSpy(&process, static_cast(&QProcess::finished)); + QSignalSpy finishedSpy2(&process, static_cast(&QProcess::finished)); QVERIFY(stateSpy.isValid()); QVERIFY(errorSpy.isValid()); @@ -1597,9 +1604,9 @@ void tst_QProcess::failToStartWithWait() QProcess process; QEventLoop loop; QSignalSpy errorSpy(&process, &QProcess::errorOccurred); - QSignalSpy errorSpy2(&process, static_cast(&QProcess::error)); - QSignalSpy finishedSpy(&process, static_cast(&QProcess::finished)); - QSignalSpy finishedSpy2(&process, static_cast(&QProcess::finished)); + QSignalSpy errorSpy2(&process, static_cast(&QProcess::error)); + QSignalSpy finishedSpy(&process, static_cast(&QProcess::finished)); + QSignalSpy finishedSpy2(&process, static_cast(&QProcess::finished)); QVERIFY(errorSpy.isValid()); QVERIFY(errorSpy2.isValid()); @@ -1629,9 +1636,9 @@ void tst_QProcess::failToStartWithEventLoop() QProcess process; QEventLoop loop; QSignalSpy errorSpy(&process, &QProcess::errorOccurred); - QSignalSpy errorSpy2(&process, static_cast(&QProcess::error)); - QSignalSpy finishedSpy(&process, static_cast(&QProcess::finished)); - QSignalSpy finishedSpy2(&process, static_cast(&QProcess::finished)); + QSignalSpy errorSpy2(&process, static_cast(&QProcess::error)); + QSignalSpy finishedSpy(&process, static_cast(&QProcess::finished)); + QSignalSpy finishedSpy2(&process, static_cast(&QProcess::finished)); QVERIFY(errorSpy.isValid()); QVERIFY(errorSpy2.isValid()); @@ -1669,7 +1676,7 @@ void tst_QProcess::failToStartEmptyArgs() qRegisterMetaType("QProcess::ProcessError"); QProcess process; - QSignalSpy errorSpy(&process, static_cast(&QProcess::error)); + QSignalSpy errorSpy(&process, static_cast(&QProcess::error)); QVERIFY(errorSpy.isValid()); switch (startOverload) { @@ -1893,9 +1900,9 @@ void tst_QProcess::waitForReadyReadForNonexistantProcess() QProcess process; QSignalSpy errorSpy(&process, &QProcess::errorOccurred); - QSignalSpy errorSpy2(&process, static_cast(&QProcess::error)); - QSignalSpy finishedSpy1(&process, static_cast(&QProcess::finished)); - QSignalSpy finishedSpy2(&process, static_cast(&QProcess::finished)); + QSignalSpy errorSpy2(&process, static_cast(&QProcess::error)); + QSignalSpy finishedSpy1(&process, static_cast(&QProcess::finished)); + QSignalSpy finishedSpy2(&process, static_cast(&QProcess::finished)); QVERIFY(errorSpy.isValid()); QVERIFY(errorSpy2.isValid()); @@ -2291,7 +2298,7 @@ void tst_QProcess::invalidProgramString() qRegisterMetaType("QProcess::ProcessError"); QSignalSpy spy(&process, &QProcess::errorOccurred); - QSignalSpy spy2(&process, static_cast(&QProcess::error)); + QSignalSpy spy2(&process, static_cast(&QProcess::error)); QVERIFY(spy.isValid()); QVERIFY(spy2.isValid()); @@ -2309,7 +2316,7 @@ void tst_QProcess::onlyOneStartedSignal() QProcess process; QSignalSpy spyStarted(&process, &QProcess::started); - QSignalSpy spyFinished(&process, static_cast(&QProcess::finished)); + QSignalSpy spyFinished(&process, static_cast(&QProcess::finished)); QVERIFY(spyStarted.isValid()); QVERIFY(spyFinished.isValid()); @@ -2335,7 +2342,7 @@ class BlockOnReadStdOut : public QObject public: BlockOnReadStdOut(QProcess *process) { - connect(process, SIGNAL(readyReadStandardOutput()), SLOT(block())); + connect(process, &QProcess::readyReadStandardOutput, this, &BlockOnReadStdOut::block); } public slots: @@ -2350,7 +2357,8 @@ void tst_QProcess::finishProcessBeforeReadingDone() QProcess process; BlockOnReadStdOut blocker(&process); QEventLoop loop; - connect(&process, SIGNAL(finished(int)), &loop, SLOT(quit())); + connect(&process, static_cast(&QProcess::finished), + &loop, &QEventLoop::quit); process.start("testProcessOutput/testProcessOutput"); QVERIFY(process.waitForStarted()); loop.exec(); From 3cbb89fa5a79977a37c4aa99ace0adba3cd73b42 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 25 Sep 2015 11:53:46 +0200 Subject: [PATCH 087/240] tst_qprocess: Instantiate QProcess objects on the stack. Instantiate the QProcess object on the stack to ensure resource cleanup and remove the QProcess * member variable. Use qobject_cast(QObject::sender()) instead of the member variable in the helpers slots to ensure that signals from a leaked QProcess do not interfere with other tests. Task-number: QTBUG-47370 Change-Id: Ifc0dccb7e4b18069d236df53bccdcb6a47df6346 Reviewed-by: Joerg Bornemann --- .../auto/corelib/io/qprocess/tst_qprocess.cpp | 306 ++++++++---------- 1 file changed, 141 insertions(+), 165 deletions(-) diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index b66551b524..2b8f2ae3c7 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -73,6 +73,7 @@ class tst_QProcess : public QObject public slots: void initTestCase(); void cleanupTestCase(); + void init(); #ifndef QT_NO_PROCESS private slots: @@ -178,7 +179,6 @@ protected slots: #endif private: - QProcess *process; qint64 bytesAvailable; #endif //QT_NO_PROCESS }; @@ -201,6 +201,11 @@ void tst_QProcess::cleanupTestCase() #endif } +void tst_QProcess::init() +{ + bytesAvailable = 0; +} + #ifndef QT_NO_PROCESS // Testing get/set functions @@ -261,10 +266,10 @@ void tst_QProcess::simpleStart() { qRegisterMetaType("QProcess::ProcessState"); - process = new QProcess; - QSignalSpy spy(process, &QProcess::stateChanged); + QScopedPointer process(new QProcess); + QSignalSpy spy(process.data(), &QProcess::stateChanged); QVERIFY(spy.isValid()); - connect(process, &QIODevice::readyRead, this, &tst_QProcess::readFromProcess); + connect(process.data(), &QIODevice::readyRead, this, &tst_QProcess::readFromProcess); /* valgrind dislike SUID binaries(those that have the `s'-flag set), which * makes it fail to start the process. For this reason utilities like `ping' won't @@ -276,8 +281,7 @@ void tst_QProcess::simpleStart() QCOMPARE(process->state(), QProcess::Running); QTRY_COMPARE(process->state(), QProcess::NotRunning); - delete process; - process = 0; + process.reset(); QCOMPARE(spy.count(), 3); QCOMPARE(qvariant_cast(spy.at(0).at(0)), QProcess::Starting); @@ -340,18 +344,20 @@ void tst_QProcess::startDetached() void tst_QProcess::readFromProcess() { + QProcess *process = qobject_cast(sender()); + QVERIFY(process); int lines = 0; while (process->canReadLine()) { ++lines; - QByteArray line = process->readLine(); + process->readLine(); } } void tst_QProcess::crashTest() { qRegisterMetaType("QProcess::ProcessState"); - process = new QProcess; - QSignalSpy stateSpy(process, &QProcess::stateChanged); + QScopedPointer process(new QProcess); + QSignalSpy stateSpy(process.data(), &QProcess::stateChanged); QVERIFY(stateSpy.isValid()); process->start("testProcessCrash/testProcessCrash"); QVERIFY(process->waitForStarted(5000)); @@ -359,9 +365,9 @@ void tst_QProcess::crashTest() qRegisterMetaType("QProcess::ProcessError"); qRegisterMetaType("QProcess::ExitStatus"); - QSignalSpy spy(process, &QProcess::errorOccurred); - QSignalSpy spy2(process, static_cast(&QProcess::error)); - QSignalSpy spy3(process, static_cast(&QProcess::finished)); + QSignalSpy spy(process.data(), &QProcess::errorOccurred); + QSignalSpy spy2(process.data(), static_cast(&QProcess::error)); + QSignalSpy spy3(process.data(), static_cast(&QProcess::finished)); QVERIFY(spy.isValid()); QVERIFY(spy2.isValid()); @@ -380,8 +386,8 @@ void tst_QProcess::crashTest() QCOMPARE(process->exitStatus(), QProcess::CrashExit); - delete process; - process = 0; + // delete process; + process.reset(); QCOMPARE(stateSpy.count(), 3); QCOMPARE(qvariant_cast(stateSpy.at(0).at(0)), QProcess::Starting); @@ -391,20 +397,20 @@ void tst_QProcess::crashTest() void tst_QProcess::crashTest2() { - process = new QProcess; - process->start("testProcessCrash/testProcessCrash"); - QVERIFY(process->waitForStarted(5000)); + QProcess process; + process.start("testProcessCrash/testProcessCrash"); + QVERIFY(process.waitForStarted(5000)); qRegisterMetaType("QProcess::ProcessError"); qRegisterMetaType("QProcess::ExitStatus"); - QSignalSpy spy(process, static_cast(&QProcess::errorOccurred)); - QSignalSpy spy2(process, static_cast(&QProcess::finished)); + QSignalSpy spy(&process, static_cast(&QProcess::errorOccurred)); + QSignalSpy spy2(&process, static_cast(&QProcess::finished)); QVERIFY(spy.isValid()); QVERIFY(spy2.isValid()); - QObject::connect(process, static_cast(&QProcess::finished), + QObject::connect(&process, static_cast(&QProcess::finished), this, &tst_QProcess::exitLoopSlot); QTestEventLoop::instance().enterLoop(30); @@ -417,10 +423,7 @@ void tst_QProcess::crashTest2() QCOMPARE(spy2.count(), 1); QCOMPARE(*static_cast(spy2.at(0).at(1).constData()), QProcess::CrashExit); - QCOMPARE(process->exitStatus(), QProcess::CrashExit); - - delete process; - process = 0; + QCOMPARE(process.exitStatus(), QProcess::CrashExit); } #ifndef Q_OS_WINCE @@ -443,24 +446,24 @@ void tst_QProcess::echoTest() { QFETCH(QByteArray, input); - process = new QProcess; - connect(process, &QIODevice::readyRead, this, &tst_QProcess::exitLoopSlot); + QProcess process; + connect(&process, &QIODevice::readyRead, this, &tst_QProcess::exitLoopSlot); - process->start("testProcessEcho/testProcessEcho"); - QVERIFY(process->waitForStarted(5000)); + process.start("testProcessEcho/testProcessEcho"); + QVERIFY(process.waitForStarted(5000)); - process->write(input); + process.write(input); QTime stopWatch; stopWatch.start(); do { - QVERIFY(process->isOpen()); + QVERIFY(process.isOpen()); QTestEventLoop::instance().enterLoop(2); - } while (stopWatch.elapsed() < 60000 && process->bytesAvailable() < input.size()); + } while (stopWatch.elapsed() < 60000 && process.bytesAvailable() < input.size()); if (stopWatch.elapsed() >= 60000) QFAIL("Timed out"); - QByteArray message = process->readAll(); + QByteArray message = process.readAll(); QCOMPARE(message.size(), input.size()); char *c1 = message.data(); @@ -473,13 +476,9 @@ void tst_QProcess::echoTest() } QCOMPARE(*c1, *c2); - process->write("", 1); + process.write("", 1); - QVERIFY(process->waitForFinished(5000)); - - - delete process; - process = 0; + QVERIFY(process.waitForFinished(5000)); } #endif @@ -493,17 +492,17 @@ void tst_QProcess::exitLoopSlot() void tst_QProcess::echoTest2() { - process = new QProcess; - connect(process, &QIODevice::readyRead, this, &tst_QProcess::exitLoopSlot); + QProcess process; + connect(&process, &QIODevice::readyRead, this, &tst_QProcess::exitLoopSlot); - process->start("testProcessEcho2/testProcessEcho2"); - QVERIFY(process->waitForStarted(5000)); - QVERIFY(!process->waitForReadyRead(250)); - QCOMPARE(process->error(), QProcess::Timedout); + process.start("testProcessEcho2/testProcessEcho2"); + QVERIFY(process.waitForStarted(5000)); + QVERIFY(!process.waitForReadyRead(250)); + QCOMPARE(process.error(), QProcess::Timedout); - process->write("Hello"); - QSignalSpy spy1(process, &QProcess::readyReadStandardOutput); - QSignalSpy spy2(process, &QProcess::readyReadStandardError); + process.write("Hello"); + QSignalSpy spy1(&process, &QProcess::readyReadStandardOutput); + QSignalSpy spy2(&process, &QProcess::readyReadStandardError); QVERIFY(spy1.isValid()); QVERIFY(spy2.isValid()); @@ -514,11 +513,11 @@ void tst_QProcess::echoTest2() QTestEventLoop::instance().enterLoop(1); if (stopWatch.elapsed() >= 30000) QFAIL("Timed out"); - process->setReadChannel(QProcess::StandardOutput); - qint64 baso = process->bytesAvailable(); + process.setReadChannel(QProcess::StandardOutput); + qint64 baso = process.bytesAvailable(); - process->setReadChannel(QProcess::StandardError); - qint64 base = process->bytesAvailable(); + process.setReadChannel(QProcess::StandardError); + qint64 base = process.bytesAvailable(); if (baso == 5 && base == 5) break; } @@ -526,14 +525,11 @@ void tst_QProcess::echoTest2() QVERIFY(spy1.count() > 0); QVERIFY(spy2.count() > 0); - QCOMPARE(process->readAllStandardOutput(), QByteArray("Hello")); - QCOMPARE(process->readAllStandardError(), QByteArray("Hello")); + QCOMPARE(process.readAllStandardOutput(), QByteArray("Hello")); + QCOMPARE(process.readAllStandardError(), QByteArray("Hello")); - process->write("", 1); - QVERIFY(process->waitForFinished(5000)); - - delete process; - process = 0; + process.write("", 1); + QVERIFY(process.waitForFinished(5000)); } #endif @@ -621,21 +617,18 @@ void tst_QProcess::exitStatus_data() void tst_QProcess::exitStatus() { - process = new QProcess; + QProcess process; QFETCH(QStringList, processList); QFETCH(QList, exitStatus); QCOMPARE(exitStatus.count(), processList.count()); for (int i = 0; i < processList.count(); ++i) { - process->start(processList.at(i)); - QVERIFY(process->waitForStarted(5000)); - QVERIFY(process->waitForFinished(30000)); + process.start(processList.at(i)); + QVERIFY(process.waitForStarted(5000)); + QVERIFY(process.waitForFinished(30000)); - QCOMPARE(process->exitStatus(), exitStatus.at(i)); + QCOMPARE(process.exitStatus(), exitStatus.at(i)); } - - process->deleteLater(); - process = 0; } #ifndef Q_OS_WINCE @@ -643,23 +636,20 @@ void tst_QProcess::exitStatus() void tst_QProcess::loopBackTest() { - process = new QProcess; - process->start("testProcessEcho/testProcessEcho"); - QVERIFY(process->waitForStarted(5000)); + QProcess process; + process.start("testProcessEcho/testProcessEcho"); + QVERIFY(process.waitForStarted(5000)); for (int i = 0; i < 100; ++i) { - process->write("Hello"); + process.write("Hello"); do { - QVERIFY(process->waitForReadyRead(5000)); - } while (process->bytesAvailable() < 5); - QCOMPARE(process->readAll(), QByteArray("Hello")); + QVERIFY(process.waitForReadyRead(5000)); + } while (process.bytesAvailable() < 5); + QCOMPARE(process.readAll(), QByteArray("Hello")); } - process->write("", 1); - QVERIFY(process->waitForFinished(5000)); - - delete process; - process = 0; + process.write("", 1); + QVERIFY(process.waitForFinished(5000)); } #endif @@ -668,35 +658,32 @@ void tst_QProcess::loopBackTest() void tst_QProcess::readTimeoutAndThenCrash() { - process = new QProcess; - process->start("testProcessEcho/testProcessEcho"); - if (process->state() != QProcess::Starting) - QCOMPARE(process->state(), QProcess::Running); + QProcess process; + process.start("testProcessEcho/testProcessEcho"); + if (process.state() != QProcess::Starting) + QCOMPARE(process.state(), QProcess::Running); - QVERIFY(process->waitForStarted(5000)); - QCOMPARE(process->state(), QProcess::Running); + QVERIFY(process.waitForStarted(5000)); + QCOMPARE(process.state(), QProcess::Running); - QVERIFY(!process->waitForReadyRead(5000)); - QCOMPARE(process->error(), QProcess::Timedout); + QVERIFY(!process.waitForReadyRead(5000)); + QCOMPARE(process.error(), QProcess::Timedout); qRegisterMetaType("QProcess::ProcessError"); - QSignalSpy spy(process, &QProcess::errorOccurred); - QSignalSpy spy2(process, static_cast(&QProcess::error)); + QSignalSpy spy(&process, &QProcess::errorOccurred); + QSignalSpy spy2(&process, static_cast(&QProcess::error)); QVERIFY(spy.isValid()); QVERIFY(spy2.isValid()); - process->kill(); + process.kill(); - QVERIFY(process->waitForFinished(5000)); - QCOMPARE(process->state(), QProcess::NotRunning); + QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.state(), QProcess::NotRunning); QCOMPARE(spy.count(), 1); QCOMPARE(*static_cast(spy.at(0).at(0).constData()), QProcess::Crashed); QCOMPARE(spy2.count(), 1); QCOMPARE(*static_cast(spy2.at(0).at(0).constData()), QProcess::Crashed); - - delete process; - process = 0; } #endif @@ -754,24 +741,25 @@ void tst_QProcess::restartProcessDeadlock() // The purpose of this test is to detect whether restarting a // process in the finished() connected slot causes a deadlock // because of the way QProcessManager uses its locks. - QProcess proc; - process = &proc; - connect(process, static_cast(&QProcess::finished), + QProcess process; + connect(&process, static_cast(&QProcess::finished), this, &tst_QProcess::restartProcess); - process->start("testProcessEcho/testProcessEcho"); + process.start("testProcessEcho/testProcessEcho"); - QCOMPARE(process->write("", 1), qlonglong(1)); - QVERIFY(process->waitForFinished(5000)); + QCOMPARE(process.write("", 1), qlonglong(1)); + QVERIFY(process.waitForFinished(5000)); - QObject::disconnect(process, static_cast(&QProcess::finished), Q_NULLPTR, Q_NULLPTR); + QObject::disconnect(&process, static_cast(&QProcess::finished), Q_NULLPTR, Q_NULLPTR); - QCOMPARE(process->write("", 1), qlonglong(1)); - QVERIFY(process->waitForFinished(5000)); + QCOMPARE(process.write("", 1), qlonglong(1)); + QVERIFY(process.waitForFinished(5000)); } void tst_QProcess::restartProcess() { + QProcess *process = qobject_cast(sender()); + QVERIFY(process); process->start("testProcessEcho/testProcessEcho"); } #endif @@ -1245,19 +1233,16 @@ void tst_QProcess::processesInMultipleThreads() // Reading and writing to a process is not supported on Qt/CE void tst_QProcess::waitForFinishedWithTimeout() { - process = new QProcess(this); + QProcess process; - process->start("testProcessEcho/testProcessEcho"); + process.start("testProcessEcho/testProcessEcho"); - QVERIFY(process->waitForStarted(5000)); - QVERIFY(!process->waitForFinished(1)); + QVERIFY(process.waitForStarted(5000)); + QVERIFY(!process.waitForFinished(1)); - process->write("", 1); + process.write("", 1); - QVERIFY(process->waitForFinished()); - - delete process; - process = 0; + QVERIFY(process.waitForFinished()); } #endif @@ -1265,28 +1250,26 @@ void tst_QProcess::waitForFinishedWithTimeout() // Reading and writing to a process is not supported on Qt/CE void tst_QProcess::waitForReadyReadInAReadyReadSlot() { - process = new QProcess(this); - connect(process, &QIODevice::readyRead, this, &tst_QProcess::waitForReadyReadInAReadyReadSlotSlot); - connect(process, static_cast(&QProcess::finished), + QProcess process; + connect(&process, &QIODevice::readyRead, this, &tst_QProcess::waitForReadyReadInAReadyReadSlotSlot); + connect(&process, static_cast(&QProcess::finished), this, &tst_QProcess::exitLoopSlot); bytesAvailable = 0; - process->start("testProcessEcho/testProcessEcho"); - QVERIFY(process->waitForStarted(5000)); + process.start("testProcessEcho/testProcessEcho"); + QVERIFY(process.waitForStarted(5000)); - QSignalSpy spy(process, &QProcess::readyRead); + QSignalSpy spy(&process, &QProcess::readyRead); QVERIFY(spy.isValid()); - process->write("foo"); + process.write("foo"); QTestEventLoop::instance().enterLoop(30); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(spy.count(), 1); - process->disconnect(); - QVERIFY(process->waitForFinished(5000)); - QVERIFY(process->bytesAvailable() > bytesAvailable); - delete process; - process = 0; + process.disconnect(); + QVERIFY(process.waitForFinished(5000)); + QVERIFY(process.bytesAvailable() > bytesAvailable); } #endif @@ -1294,6 +1277,8 @@ void tst_QProcess::waitForReadyReadInAReadyReadSlot() // Reading and writing to a process is not supported on Qt/CE void tst_QProcess::waitForReadyReadInAReadyReadSlotSlot() { + QProcess *process = qobject_cast(sender()); + QVERIFY(process); bytesAvailable = process->bytesAvailable(); process->write("bar", 4); QVERIFY(process->waitForReadyRead(5000)); @@ -1305,25 +1290,23 @@ void tst_QProcess::waitForReadyReadInAReadyReadSlotSlot() // Reading and writing to a process is not supported on Qt/CE void tst_QProcess::waitForBytesWrittenInABytesWrittenSlot() { - process = new QProcess(this); - connect(process, &QIODevice::bytesWritten, this, &tst_QProcess::waitForBytesWrittenInABytesWrittenSlotSlot); + QProcess process; + connect(&process, &QIODevice::bytesWritten, this, &tst_QProcess::waitForBytesWrittenInABytesWrittenSlotSlot); bytesAvailable = 0; - process->start("testProcessEcho/testProcessEcho"); - QVERIFY(process->waitForStarted(5000)); + process.start("testProcessEcho/testProcessEcho"); + QVERIFY(process.waitForStarted(5000)); - QSignalSpy spy(process, &QProcess::bytesWritten); + QSignalSpy spy(&process, &QProcess::bytesWritten); QVERIFY(spy.isValid()); - process->write("f"); + process.write("f"); QTestEventLoop::instance().enterLoop(30); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(spy.count(), 1); - process->write("", 1); - process->disconnect(); - QVERIFY(process->waitForFinished()); - delete process; - process = 0; + process.write("", 1); + process.disconnect(); + QVERIFY(process.waitForFinished()); } #endif @@ -1331,6 +1314,8 @@ void tst_QProcess::waitForBytesWrittenInABytesWrittenSlot() // Reading and writing to a process is not supported on Qt/CE void tst_QProcess::waitForBytesWrittenInABytesWrittenSlotSlot() { + QProcess *process = qobject_cast(sender()); + QVERIFY(process); process->write("b"); QVERIFY(process->waitForBytesWritten(5000)); QTestEventLoop::instance().exitLoop(); @@ -1399,11 +1384,11 @@ void tst_QProcess::spaceArgsTest() << QString::fromLatin1("testProcessSpacesArgs/one space") << QString::fromLatin1("testProcessSpacesArgs/two space s"); - process = new QProcess(this); + QProcess process; for (int i = 0; i < programs.size(); ++i) { QString program = programs.at(i); - process->start(program, args); + process.start(program, args); #if defined(Q_OS_WINCE) const int timeOutMS = 10000; @@ -1411,14 +1396,14 @@ void tst_QProcess::spaceArgsTest() const int timeOutMS = 5000; #endif QByteArray errorMessage; - bool started = process->waitForStarted(timeOutMS); + bool started = process.waitForStarted(timeOutMS); if (!started) - errorMessage = startFailMessage(program, *process); + errorMessage = startFailMessage(program, process); QVERIFY2(started, errorMessage.constData()); - QVERIFY(process->waitForFinished(timeOutMS)); + QVERIFY(process.waitForFinished(timeOutMS)); #if !defined(Q_OS_WINCE) - QStringList actual = QString::fromLatin1(process->readAll()).split("|"); + QStringList actual = QString::fromLatin1(process.readAll()).split("|"); #endif #if !defined(Q_OS_WINCE) QVERIFY(!actual.isEmpty()); @@ -1435,16 +1420,16 @@ void tst_QProcess::spaceArgsTest() program += QString::fromLatin1(" ") + stringArgs; errorMessage.clear(); - process->start(program); - started = process->waitForStarted(5000); + process.start(program); + started = process.waitForStarted(5000); if (!started) - errorMessage = startFailMessage(program, *process); + errorMessage = startFailMessage(program, process); QVERIFY2(started, errorMessage.constData()); - QVERIFY(process->waitForFinished(5000)); + QVERIFY(process.waitForFinished(5000)); #if !defined(Q_OS_WINCE) - actual = QString::fromLatin1(process->readAll()).split("|"); + actual = QString::fromLatin1(process.readAll()).split("|"); #endif #if !defined(Q_OS_WINCE) QVERIFY(!actual.isEmpty()); @@ -1454,9 +1439,6 @@ void tst_QProcess::spaceArgsTest() QCOMPARE(actual, args); #endif } - - delete process; - process = 0; } #if defined(Q_OS_WIN) @@ -2230,38 +2212,32 @@ void tst_QProcess::discardUnwantedOutput() // Windows CE does not support working directory logic void tst_QProcess::setWorkingDirectory() { - process = new QProcess; - process->setWorkingDirectory("test"); + QProcess process; + process.setWorkingDirectory("test"); // use absolute path because on Windows, the executable is relative to the parent's CWD // while on Unix with fork it's relative to the child's (with posix_spawn, it could be either). - process->start(QFileInfo("testSetWorkingDirectory/testSetWorkingDirectory").absoluteFilePath()); + process.start(QFileInfo("testSetWorkingDirectory/testSetWorkingDirectory").absoluteFilePath()); - QVERIFY2(process->waitForFinished(), process->errorString().toLocal8Bit()); + QVERIFY2(process.waitForFinished(), process.errorString().toLocal8Bit()); - QByteArray workingDir = process->readAllStandardOutput(); + QByteArray workingDir = process.readAllStandardOutput(); QCOMPARE(QDir("test").canonicalPath(), QDir(workingDir.constData()).canonicalPath()); - - delete process; - process = 0; } void tst_QProcess::setNonExistentWorkingDirectory() { - process = new QProcess; - process->setWorkingDirectory("this/directory/should/not/exist/for/sure"); + QProcess process; + process.setWorkingDirectory("this/directory/should/not/exist/for/sure"); // use absolute path because on Windows, the executable is relative to the parent's CWD // while on Unix with fork it's relative to the child's (with posix_spawn, it could be either). - process->start(QFileInfo("testSetWorkingDirectory/testSetWorkingDirectory").absoluteFilePath()); - QVERIFY(!process->waitForFinished()); + process.start(QFileInfo("testSetWorkingDirectory/testSetWorkingDirectory").absoluteFilePath()); + QVERIFY(!process.waitForFinished()); #ifdef QPROCESS_USE_SPAWN QEXPECT_FAIL("", "QProcess cannot detect failure to start when using posix_spawn()", Continue); #endif - QCOMPARE(int(process->error()), int(QProcess::FailedToStart)); - - delete process; - process = 0; + QCOMPARE(int(process.error()), int(QProcess::FailedToStart)); } #endif From ddee17e7705fd3f64c564dcd926531d181387fd1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 23 Sep 2015 10:41:21 -0700 Subject: [PATCH 088/240] Remove QT_WARNING_DISABLE_GCC for Clang There's QT_WARNING_DISABLE_CLANG for when a warning applies to a Clang build. Change-Id: I42e7ef1a481840699a8dffff1406ac36b6a6eac3 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/global/qcompilerdetection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 4828d8596a..1a999d24be 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1140,7 +1140,7 @@ # define QT_WARNING_PUSH QT_DO_PRAGMA(clang diagnostic push) # define QT_WARNING_POP QT_DO_PRAGMA(clang diagnostic pop) # define QT_WARNING_DISABLE_CLANG(text) QT_DO_PRAGMA(clang diagnostic ignored text) -# define QT_WARNING_DISABLE_GCC(text) QT_DO_PRAGMA(GCC diagnostic ignored text) // GCC directives work in Clang too +# define QT_WARNING_DISABLE_GCC(text) # define QT_WARNING_DISABLE_INTEL(number) # define QT_WARNING_DISABLE_MSVC(number) #elif defined(Q_CC_GNU) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) From d90536787b8225654e13a9ee0aa7c03c1dc9d57d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 22 Sep 2015 21:41:11 -0700 Subject: [PATCH 089/240] Work around GCC thinking that a variable could be clobbered by longjmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can't be. The block in which the variable "s" exists makes no call to any function that takes the setjmp buffer. This is not a false positive warning: it's an incorrect warning. qjpeghandler.cpp:878:6: error: variable ‘s’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Werror=clobbered] Change-Id: I42e7ef1a481840699a8dffff140681a3d7e34493 Reviewed-by: Gunnar Sletta --- src/gui/image/qjpeghandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp index e29f9783a6..7e9483e6f7 100644 --- a/src/gui/image/qjpeghandler.cpp +++ b/src/gui/image/qjpeghandler.cpp @@ -68,6 +68,7 @@ extern "C" { } QT_BEGIN_NAMESPACE +QT_WARNING_DISABLE_GCC("-Wclobbered") Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32(quint32 *dst, const uchar *src, int len); typedef void (QT_FASTCALL *Rgb888ToRgb32Converter)(quint32 *dst, const uchar *src, int len); From 393c8d0b74ded30c40a5321df5cbbc76dac66eda Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 21 Aug 2015 14:02:38 -0700 Subject: [PATCH 090/240] Fix ICC warning about use of "defined" in a macro qhash.cpp(89): warning #3199: "defined" is always false in a macro expansion in Microsoft mode Change-Id: I7de033f80b0e4431b7f1ffff13fc960bcbb17352 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qsimd_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index be003f6c6d..bb9c26f762 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -150,7 +150,7 @@ # define QT_FUNCTION_TARGET(x) # endif #else -# define QT_COMPILER_SUPPORTS_HERE(x) defined(__ ## x ## __) +# define QT_COMPILER_SUPPORTS_HERE(x) (__ ## x ## __) # define QT_FUNCTION_TARGET(x) #endif From b2e664df614dea23bf77c0fa293682b47a8b5557 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 24 Feb 2015 14:09:39 +0100 Subject: [PATCH 091/240] Enable tst_qaccessibilitylinux This test caused problems because it relies on the at-spi services to run. In addition it could trigger orca (screen reader) to be launched as a side-effect of the dbus call to the screen-reader-enabled setting. Instead just export QT_LINUX_ACCESSIBILITY_ALWAYS_ON to make sure that accessibility will work. This means we won't test the dbus startup any more, but the test will be reliable. There is still a dbus call to org.a11y.Bus to launch the service in case it's not running yet. Task-number: QTBUG-27732 Task-number: QTBUG-44434 Change-Id: Idb86ed98ca4b47cb209027c8b41529e7e5285197 Reviewed-by: Caroline Chao --- .../qaccessibilitylinux.pro | 3 -- .../tst_qaccessibilitylinux.cpp | 34 ++++++++++++++----- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/tests/auto/other/qaccessibilitylinux/qaccessibilitylinux.pro b/tests/auto/other/qaccessibilitylinux/qaccessibilitylinux.pro index 2ea54ab603..10d950541a 100644 --- a/tests/auto/other/qaccessibilitylinux/qaccessibilitylinux.pro +++ b/tests/auto/other/qaccessibilitylinux/qaccessibilitylinux.pro @@ -1,8 +1,5 @@ CONFIG += testcase -# This is temporary to start running the test as part of normal CI. -CONFIG += insignificant_test # QTBUG-27732 - include($$QT_SOURCE_TREE/src/platformsupport/accessibility/accessibility.pri) include($$QT_SOURCE_TREE/src/platformsupport/linuxaccessibility/linuxaccessibility.pri) diff --git a/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp b/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp index 5f0eed5afe..4885a5f037 100644 --- a/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp +++ b/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp @@ -84,7 +84,15 @@ class tst_QAccessibilityLinux : public QObject Q_OBJECT public: - tst_QAccessibilityLinux() : m_window(0), root(0), rootApplication(0), mainWindow(0) {} + tst_QAccessibilityLinux() : m_window(0), root(0), rootApplication(0), mainWindow(0) + { + qputenv("QT_LINUX_ACCESSIBILITY_ALWAYS_ON", QByteArrayLiteral("1")); + dbus = new DBusConnection(); + } + ~tst_QAccessibilityLinux() + { + delete dbus; + } private slots: void initTestCase(); @@ -112,7 +120,7 @@ private: QDBusInterface *rootApplication; QDBusInterface *mainWindow; - DBusConnection dbus; + DBusConnection *dbus; }; // helper to find children of a dbus object @@ -149,7 +157,7 @@ QString tst_QAccessibilityLinux::getParent(QDBusInterface *interface) // helper to get dbus object QDBusInterface *tst_QAccessibilityLinux::getInterface(const QString &path, const QString &interfaceName) { - return new QDBusInterface(address, path, interfaceName, dbus.connection(), this); + return new QDBusInterface(address, path, interfaceName, dbus->connection(), this); } void tst_QAccessibilityLinux::initTestCase() @@ -158,14 +166,22 @@ void tst_QAccessibilityLinux::initTestCase() qApp->setStyle("fusion"); qApp->setApplicationName("tst_QAccessibilityLinux app"); - // Pretend we are a screen reader + + // trigger launching of at-spi if it isn't running already QDBusConnection c = QDBusConnection::sessionBus(); OrgA11yStatusInterface *a11yStatus = new OrgA11yStatusInterface(QStringLiteral("org.a11y.Bus"), QStringLiteral("/org/a11y/bus"), c, this); - a11yStatus->setScreenReaderEnabled(true); + // don't care about the result, calling any function on "org.a11y.Bus" will launch the service + a11yStatus->isEnabled(); + for (int i = 0; i < 5; ++i) { + if (!dbus->isEnabled()) + QTest::qWait(100); + } - QTRY_VERIFY(dbus.isEnabled()); - QTRY_VERIFY(dbus.connection().isConnected()); - address = dbus.connection().baseService().toLatin1().data(); + if (!dbus->isEnabled()) + QSKIP("Could not connect to AT-SPI, make sure lib atspi2 is installed."); + QTRY_VERIFY(dbus->isEnabled()); + QTRY_VERIFY(dbus->connection().isConnected()); + address = dbus->connection().baseService().toLatin1().data(); QVERIFY(!address.isEmpty()); m_window = new AccessibleTestWindow(); @@ -185,7 +201,7 @@ void tst_QAccessibilityLinux::cleanupTestCase() void tst_QAccessibilityLinux::registerDbus() { - QVERIFY(dbus.connection().isConnected()); + QVERIFY(dbus->connection().isConnected()); root = getInterface("/org/a11y/atspi/accessible/root", "org.a11y.atspi.Accessible"); From f98c2ef27a4f6fa3b7e9c35cf7896abc4b22816b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20L=C3=B6sch?= Date: Mon, 10 Aug 2015 12:47:04 +0200 Subject: [PATCH 092/240] Abort underlying socket when aborting QNetworkReply If we abort a connection in QNetworkReply::encrypted the underlying socket gets flushed. This patch fixes that no data will be transmitted after someone called abort(). Change-Id: I59306e69cb9f2e1421b324e11947375130e52135 Task-number: QTBUG-47471 Reviewed-by: Markus Goetz (Woboq GmbH) Reviewed-by: Thiago Macieira --- src/network/access/qhttpnetworkconnection.cpp | 9 +++++++-- .../access/qhttpnetworkconnectionchannel.cpp | 20 +++++++++++++++++++ .../access/qhttpnetworkconnectionchannel_p.h | 1 + src/network/access/qhttpnetworkreply.cpp | 11 ++++++++++ src/network/access/qhttpnetworkreply_p.h | 6 +++++- src/network/access/qhttpthreaddelegate.cpp | 1 + 6 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index b7d17be955..f810df5711 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -835,8 +835,13 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply) // if HTTP mandates we should close // or the reply is not finished yet, e.g. it was aborted // we have to close that connection - if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished()) - channels[i].close(); + if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished()) { + if (reply->isAborted()) { + channels[i].abort(); + } else { + channels[i].close(); + } + } QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); return; diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 477cba267b..0820a8d63e 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -205,6 +205,26 @@ void QHttpNetworkConnectionChannel::close() } +void QHttpNetworkConnectionChannel::abort() +{ + if (!socket) + state = QHttpNetworkConnectionChannel::IdleState; + else if (socket->state() == QAbstractSocket::UnconnectedState) + state = QHttpNetworkConnectionChannel::IdleState; + else + state = QHttpNetworkConnectionChannel::ClosingState; + + // pendingEncrypt must only be true in between connected and encrypted states + pendingEncrypt = false; + + if (socket) { + // socket can be 0 since the host lookup is done from qhttpnetworkconnection.cpp while + // there is no socket yet. + socket->abort(); + } +} + + bool QHttpNetworkConnectionChannel::sendRequest() { Q_ASSERT(!protocolHandler.isNull()); diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 37ad6c9b0a..87329b7397 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -157,6 +157,7 @@ public: void init(); void close(); + void abort(); bool sendRequest(); diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 80f3670660..b744a99f0f 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -247,6 +247,17 @@ char* QHttpNetworkReply::userProvidedDownloadBuffer() return d->userProvidedDownloadBuffer; } +void QHttpNetworkReply::abort() +{ + Q_D(QHttpNetworkReply); + d->state = QHttpNetworkReplyPrivate::Aborted; +} + +bool QHttpNetworkReply::isAborted() const +{ + return d_func()->state == QHttpNetworkReplyPrivate::Aborted; +} + bool QHttpNetworkReply::isFinished() const { return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 0fe298da27..46b6541dfa 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -121,6 +121,9 @@ public: void setUserProvidedDownloadBuffer(char*); char* userProvidedDownloadBuffer(); + void abort(); + + bool isAborted() const; bool isFinished() const; bool isPipeliningUsed() const; @@ -205,7 +208,8 @@ public: SPDYSYNSent, SPDYUploading, SPDYHalfClosed, - SPDYClosed + SPDYClosed, + Aborted } state; QHttpNetworkRequest request; diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index be6fa01098..e4931db304 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -396,6 +396,7 @@ void QHttpThreadDelegate::abortRequest() qDebug() << "QHttpThreadDelegate::abortRequest() thread=" << QThread::currentThreadId() << "sync=" << synchronous; #endif if (httpReply) { + httpReply->abort(); delete httpReply; httpReply = 0; } From bb281eea179d50a413f4ec1ff172d27ee48d3a41 Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Fri, 17 Jul 2015 15:32:23 +1000 Subject: [PATCH 093/240] Make sure networkAccessibilityChanged is emitted Task-number: QTBUG-46323 Change-Id: I8297072b62763136f457ca6ae15282d1c22244f4 Reviewed-by: Timo Jyrinki Reviewed-by: Alex Blasche --- src/network/access/qnetworkaccessmanager.cpp | 70 +++++++++++++------ src/network/access/qnetworkaccessmanager_p.h | 14 +++- .../tst_qnetworkaccessmanager.cpp | 33 +++++---- 3 files changed, 78 insertions(+), 39 deletions(-) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 84931cbb40..f9e9513c55 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -278,7 +278,8 @@ static void ensureInitialized() \snippet code/src_network_access_qnetworkaccessmanager.cpp 4 - Network requests can be reenabled again by calling + Network requests can be re-enabled again, and this property will resume to + reflect the actual device state by calling \snippet code/src_network_access_qnetworkaccessmanager.cpp 5 @@ -467,16 +468,12 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) qRegisterMetaType >(); #ifndef QT_NO_BEARERMANAGEMENT - if (!d->networkSessionRequired) { - // if a session is required, we track online state through - // the QNetworkSession's signals - connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), - SLOT(_q_onlineStateChanged(bool))); - } - // we would need all active configurations to check for - // d->networkConfigurationManager.isOnline(), which is asynchronous - // and potentially expensive. We can just check the configuration here - d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active); + // if a session is required, we track online state through + // the QNetworkSession's signals if a request is already made. + // we need to track current accessibility state by default + // + connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), + SLOT(_q_onlineStateChanged(bool))); #endif } @@ -946,7 +943,8 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible) { Q_D(QNetworkAccessManager); - d->defaultAccessControl = false; + + d->defaultAccessControl = accessible == NotAccessible ? false : true; if (d->networkAccessible != accessible) { NetworkAccessibility previous = networkAccessible(); @@ -965,6 +963,10 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const { Q_D(const QNetworkAccessManager); + + if (d->networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) + return UnknownAccessibility; + if (d->networkSessionRequired) { QSharedPointer networkSession(d->getNetworkSession()); if (networkSession) { @@ -1622,32 +1624,56 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession if (online) { if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) { online = false; - networkAccessible = QNetworkAccessManager::NotAccessible; - emit q->networkAccessibleChanged(networkAccessible); + if (networkAccessible != QNetworkAccessManager::NotAccessible) { + networkAccessible = QNetworkAccessManager::NotAccessible; + emit q->networkAccessibleChanged(networkAccessible); + } } } else { if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) { online = true; if (defaultAccessControl) - networkAccessible = QNetworkAccessManager::Accessible; - emit q->networkAccessibleChanged(networkAccessible); + if (networkAccessible != QNetworkAccessManager::Accessible) { + networkAccessible = QNetworkAccessManager::Accessible; + emit q->networkAccessibleChanged(networkAccessible); + } } } } void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) { - // if the user set a config, we only care whether this one is active. + Q_Q(QNetworkAccessManager); + // if the user set a config, we only care whether this one is active. // Otherwise, this QNAM is online if there is an online config. if (customNetworkConfiguration) { online = (networkConfiguration.state() & QNetworkConfiguration::Active); } else { - if (isOnline && online != isOnline) { - networkSessionStrongRef.clear(); - networkSessionWeakRef.clear(); + if (online != isOnline) { + if (isOnline) { + networkSessionStrongRef.clear(); + networkSessionWeakRef.clear(); + } + online = isOnline; + } + } + if (online) { + if (defaultAccessControl) { + if (networkAccessible != QNetworkAccessManager::Accessible) { + networkAccessible = QNetworkAccessManager::Accessible; + emit q->networkAccessibleChanged(networkAccessible); + } + } + } else if (networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) { + if (networkAccessible != QNetworkAccessManager::UnknownAccessibility) { + networkAccessible = QNetworkAccessManager::UnknownAccessibility; + emit q->networkAccessibleChanged(networkAccessible); + } + } else { + if (networkAccessible != QNetworkAccessManager::NotAccessible) { + networkAccessible = QNetworkAccessManager::NotAccessible; + emit q->networkAccessibleChanged(networkAccessible); } - - online = isOnline; } } diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index c715da00c1..54ae114581 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -78,7 +78,6 @@ public: customNetworkConfiguration(false), networkSessionRequired(networkConfigurationManager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired), - networkAccessible(QNetworkAccessManager::Accessible), activeReplyCount(0), online(false), initializeSession(true), @@ -86,7 +85,18 @@ public: cookieJarCreated(false), defaultAccessControl(true), authenticationManager(QSharedPointer::create()) - { } + { +#ifndef QT_NO_BEARERMANAGEMENT + // we would need all active configurations to check for + // d->networkConfigurationManager.isOnline(), which is asynchronous + // and potentially expensive. We can just check the configuration here + online = (networkConfiguration.state().testFlag(QNetworkConfiguration::Active)); + if (online) + networkAccessible = QNetworkAccessManager::Accessible; + else + networkAccessible = QNetworkAccessManager::NotAccessible; +#endif + } ~QNetworkAccessManagerPrivate(); void _q_replyFinished(); diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp index b4e4b9ce0a..8ecb57dd33 100644 --- a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp +++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp @@ -74,6 +74,10 @@ void tst_QNetworkAccessManager::networkAccessible() // if there is no session, we cannot know in which state we are in QNetworkAccessManager::NetworkAccessibility initialAccessibility = manager.networkAccessible(); + + if (initialAccessibility == QNetworkAccessManager::UnknownAccessibility) + QSKIP("Unknown accessibility", SkipAll); + QCOMPARE(manager.networkAccessible(), initialAccessibility); manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible); @@ -94,29 +98,28 @@ void tst_QNetworkAccessManager::networkAccessible() QCOMPARE(manager.networkAccessible(), initialAccessibility); QNetworkConfigurationManager configManager; - bool sessionRequired = (configManager.capabilities() - & QNetworkConfigurationManager::NetworkSessionRequired); QNetworkConfiguration defaultConfig = configManager.defaultConfiguration(); if (defaultConfig.isValid()) { manager.setConfiguration(defaultConfig); - // the accessibility has not changed if no session is required - if (sessionRequired) { - QCOMPARE(spy.count(), 1); - QCOMPARE(spy.takeFirst().at(0).value(), - QNetworkAccessManager::Accessible); - } else { - QCOMPARE(spy.count(), 0); - } - QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::Accessible); + QCOMPARE(spy.count(), 0); + + if (defaultConfig.state().testFlag(QNetworkConfiguration::Active)) + QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::Accessible); + else + QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible); manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible); - QCOMPARE(spy.count(), 1); - QCOMPARE(QNetworkAccessManager::NetworkAccessibility(spy.takeFirst().at(0).toInt()), - QNetworkAccessManager::NotAccessible); - QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible); + if (defaultConfig.state().testFlag(QNetworkConfiguration::Active)) { + QCOMPARE(spy.count(), 1); + QCOMPARE(QNetworkAccessManager::NetworkAccessibility(spy.takeFirst().at(0).toInt()), + QNetworkAccessManager::NotAccessible); + } else { + QCOMPARE(spy.count(), 0); + } } + QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible); #endif } From e18554d4f7722b7fc5b576efb7ca429112789a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= Date: Thu, 27 Aug 2015 00:50:11 +0300 Subject: [PATCH 094/240] Network: Use QFile::encodeName for POSIX paths instead of toLatin1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit POSIX API doesn't really have defined encoding and kernel works with null-terminated byte strings (char *) without any knowledge about encodings. But usually applications use LANG (and LC_*) as encoding making it possible to use any encoding user wishes, including full Unicode support when UTF-8 is used. This allows to create and listen to sockets with paths containing non-latin characters. eg. listen(QString("/run/υποδοχή")); Change-Id: I022ac6a8a4575103125c48768a66bef88a232a2a Reviewed-by: Thiago Macieira Reviewed-by: Dāvis Mosāns --- src/network/socket/qlocalserver_unix.cpp | 22 +++++++++++----------- src/network/socket/qlocalsocket_unix.cpp | 7 ++++--- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index ef10b1e68d..634074d91f 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -85,7 +85,8 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) } serverName = requestedServerName; - QString tempPath; + QByteArray encodedTempPath; + const QByteArray encodedFullServerName = QFile::encodeName(fullServerName); QScopedPointer tempDir; // Check any of the flags @@ -96,8 +97,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) setError(QLatin1String("QLocalServer::listen")); return false; } - tempPath = tempDir->path(); - tempPath += QLatin1String("/s"); + encodedTempPath = QFile::encodeName(tempDir->path() + QLatin1String("/s")); } // create the unix socket @@ -111,23 +111,23 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) // Construct the unix address struct ::sockaddr_un addr; addr.sun_family = PF_UNIX; - if (sizeof(addr.sun_path) < (uint)fullServerName.toLatin1().size() + 1) { + if (sizeof(addr.sun_path) < (uint)encodedFullServerName.size() + 1) { setError(QLatin1String("QLocalServer::listen")); closeServer(); return false; } if (socketOptions & QLocalServer::WorldAccessOption) { - if (sizeof(addr.sun_path) < (uint)tempPath.toLatin1().size() + 1) { + if (sizeof(addr.sun_path) < (uint)encodedTempPath.size() + 1) { setError(QLatin1String("QLocalServer::listen")); closeServer(); return false; } - ::memcpy(addr.sun_path, tempPath.toLatin1().data(), - tempPath.toLatin1().size() + 1); + ::memcpy(addr.sun_path, encodedTempPath.constData(), + encodedTempPath.size() + 1); } else { - ::memcpy(addr.sun_path, fullServerName.toLatin1().data(), - fullServerName.toLatin1().size() + 1); + ::memcpy(addr.sun_path, encodedFullServerName.constData(), + encodedFullServerName.size() + 1); } // bind @@ -165,13 +165,13 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) if (socketOptions & QLocalServer::OtherAccessOption) mode |= S_IRWXO; - if (::chmod(tempPath.toLatin1(), mode) == -1) { + if (::chmod(encodedTempPath.constData(), mode) == -1) { setError(QLatin1String("QLocalServer::listen")); closeServer(); return false; } - if (::rename(tempPath.toLatin1(), fullServerName.toLatin1()) == -1) { + if (::rename(encodedTempPath.constData(), encodedFullServerName.constData()) == -1) { setError(QLatin1String("QLocalServer::listen")); closeServer(); return false; diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp index 77c5028fb3..bb0f11f038 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -268,15 +268,16 @@ void QLocalSocketPrivate::_q_connectToSocket() connectingPathName += QLatin1Char('/') + connectingName; } + const QByteArray encodedConnectingPathName = QFile::encodeName(connectingPathName); struct sockaddr_un name; name.sun_family = PF_UNIX; - if (sizeof(name.sun_path) < (uint)connectingPathName.toLatin1().size() + 1) { + if (sizeof(name.sun_path) < (uint)encodedConnectingPathName.size() + 1) { QString function = QLatin1String("QLocalSocket::connectToServer"); errorOccurred(QLocalSocket::ServerNotFoundError, function); return; } - ::memcpy(name.sun_path, connectingPathName.toLatin1().data(), - connectingPathName.toLatin1().size() + 1); + ::memcpy(name.sun_path, encodedConnectingPathName.constData(), + encodedConnectingPathName.size() + 1); if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) { QString function = QLatin1String("QLocalSocket::connectToServer"); switch (errno) From 126c2cb8fbb50848a5006fd25e83b8afc7b3e781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 4 Sep 2015 17:56:30 +0200 Subject: [PATCH 095/240] Clean up cancel operation handling on OS X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The logic for handling cancel operations was spread out through the code base and sometimes hard-coded to only include the Escape key shortcut, missing the Command+. shortcut. We now intercept both attempts at cancel operations from the system through cancelOperation, which we forward as normal key events. A new QKeySequence::StandardKey has been added for the Cancel sequence, which maps to Escape on all platforms, and Command+. in addition for OS X. The hard-coded logic in QWidget and subclasses for dealing with closing the dialogs has been replaced with this key sequence, which allows clients to override the behavior. Note that the widget code is not wrapped in checks for QT_NO_SHORTCUT, as we don't care about keeping widgets building and working under that define. The logic in QCocoaWindow to bypass windowShouldClose when delivering IM events has been removed as we now handle that specific case by also forwarding Escape as a cancel operation. Task-number: QTBUG-47557 Task-number: QTBUG-45771 Task-number: QTBUG-44076 Change-Id: Ibe0b3a4819f8659d246a2142dd7d9cd3a826ef78 Reviewed-by: Tim Blechmann Reviewed-by: Morten Johan Sørvig Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qkeysequence.cpp | 2 + src/gui/kernel/qkeysequence.h | 3 +- src/gui/kernel/qplatformtheme.cpp | 4 +- src/plugins/platforms/cocoa/qcocoawindow.h | 1 - src/plugins/platforms/cocoa/qcocoawindow.mm | 8 ++-- src/plugins/platforms/cocoa/qnsview.h | 2 +- src/plugins/platforms/cocoa/qnsview.mm | 37 ++++++++------- src/widgets/dialogs/qcolordialog.cpp | 8 +--- src/widgets/dialogs/qdialog.cpp | 7 +-- src/widgets/dialogs/qfiledialog.cpp | 11 +++-- src/widgets/dialogs/qmessagebox.cpp | 7 +-- src/widgets/dialogs/qprogressdialog.cpp | 3 +- .../itemviews/qabstractitemdelegate.cpp | 12 ++--- src/widgets/kernel/qwhatsthis.cpp | 2 +- src/widgets/kernel/qwidget.cpp | 5 ++- src/widgets/util/qcompleter.cpp | 6 ++- src/widgets/widgets/qabstractbutton.cpp | 8 ++-- src/widgets/widgets/qcalendarwidget.cpp | 5 +-- src/widgets/widgets/qcombobox.cpp | 15 ++++--- src/widgets/widgets/qdatetimeedit.cpp | 2 +- src/widgets/widgets/qeffects.cpp | 2 +- src/widgets/widgets/qmenu.cpp | 45 ++++++++++--------- src/widgets/widgets/qmenubar.cpp | 12 ++--- 23 files changed, 106 insertions(+), 101 deletions(-) diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index ffa9b87147..881d7cc76a 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -291,6 +291,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni \row \li InsertParagraphSeparator \li Enter \li Enter \li Enter \li Enter \row \li InsertLineSeparator \li Shift+Enter \li Meta+Enter, Meta+O \li Shift+Enter \li Shift+Enter \row \li Backspace \li (none) \li Meta+H \li (none) \li (none) + \row \li Cancel \li Escape \li Escape, Ctrl+. \li Escape \li Escape \endtable Note that, since the key sequences used for the standard shortcuts differ @@ -752,6 +753,7 @@ static const struct { \value ZoomIn Zoom in. \value ZoomOut Zoom out. \value FullScreen Toggle the window state to/from full screen. + \value Cancel Cancel the current operation. */ /*! diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h index d6171c86f2..98a611aab5 100644 --- a/src/gui/kernel/qkeysequence.h +++ b/src/gui/kernel/qkeysequence.h @@ -137,7 +137,8 @@ public: FullScreen, Deselect, DeleteCompleteLine, - Backspace + Backspace, + Cancel }; Q_ENUM(StandardKey) diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp index 36a71fe2da..ce8548f628 100644 --- a/src/gui/kernel/qplatformtheme.cpp +++ b/src/gui/kernel/qplatformtheme.cpp @@ -323,7 +323,9 @@ const QKeyBinding QPlatformThemePrivate::keyBindings[] = { {QKeySequence::FullScreen, 1, Qt::Key_F11, KB_Win | KB_KDE}, {QKeySequence::Deselect, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_A, KB_X11}, {QKeySequence::DeleteCompleteLine, 0, Qt::CTRL | Qt::Key_U, KB_X11}, - {QKeySequence::Backspace, 0, Qt::META | Qt::Key_H, KB_Mac} + {QKeySequence::Backspace, 0, Qt::META | Qt::Key_H, KB_Mac}, + {QKeySequence::Cancel, 0, Qt::Key_Escape, KB_All}, + {QKeySequence::Cancel, 0, Qt::CTRL | Qt::Key_Period, KB_Mac} }; const uint QPlatformThemePrivate::numberOfKeyBindings = sizeof(QPlatformThemePrivate::keyBindings)/(sizeof(QKeyBinding)); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 51679116b5..05e6cf3c9e 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -270,7 +270,6 @@ public: // for QNSView QPointer m_enterLeaveTargetWindow; bool m_windowUnderMouse; - bool m_ignoreWindowShouldClose; bool m_inConstructor; bool m_inSetVisible; bool m_inSetGeometry; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 5606f050a3..8a8e03d283 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -345,7 +345,6 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_synchedWindowState(Qt::WindowActive) , m_windowModality(Qt::NonModal) , m_windowUnderMouse(false) - , m_ignoreWindowShouldClose(false) , m_inConstructor(true) , m_inSetVisible(false) , m_inSetGeometry(false) @@ -1219,9 +1218,10 @@ void QCocoaWindow::windowDidEndLiveResize() bool QCocoaWindow::windowShouldClose() { - // might have been set from qnsview.mm - if (m_ignoreWindowShouldClose) - return false; + // This callback should technically only determine if the window + // should (be allowed to) close, but since our QPA API to determine + // that also involves actually closing the window we do both at the + // same time, instead of doing the latter in windowWillClose. bool accepted = false; QWindowSystemInterface::handleCloseEvent(window(), &accepted); QWindowSystemInterface::flushWindowSystemEvents(); diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 14a61554a3..028a34af1c 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -76,6 +76,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); bool m_resendKeyEvent; bool m_scrolling; bool m_exposedOnMoveToWindow; + NSEvent *m_currentlyInterpretedKeyEvent; } - (id)init; @@ -131,7 +132,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)handleKeyEvent:(NSEvent *)theEvent eventType:(int)eventType; - (void)keyDown:(NSEvent *)theEvent; - (void)keyUp:(NSEvent *)theEvent; -- (BOOL)performKeyEquivalent:(NSEvent *)theEvent; - (void)registerDragTypes; - (NSDragOperation)handleDrag:(id )sender; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 4db55c1b73..7da0c4d402 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -152,6 +152,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; m_mouseMoveHelper = [[QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) alloc] initWithView:self]; m_resendKeyEvent = false; m_scrolling = false; + m_currentlyInterpretedKeyEvent = 0; if (!touchDevice) { touchDevice = new QTouchDevice; @@ -1449,21 +1450,17 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) QObject *fo = QGuiApplication::focusObject(); if (m_sendKeyEvent && fo) { - // if escape is pressed we don't want interpretKeyEvents to close a dialog. This will be done via QWindowSystemInterface - if (keyCode == Qt::Key_Escape) - m_platformWindow->m_ignoreWindowShouldClose = true; - QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints); if (QCoreApplication::sendEvent(fo, &queryEvent)) { bool imEnabled = queryEvent.value(Qt::ImEnabled).toBool(); Qt::InputMethodHints hints = static_cast(queryEvent.value(Qt::ImHints).toUInt()); if (imEnabled && !(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhHiddenText)) { // pass the key event to the input method. note that m_sendKeyEvent may be set to false during this call + m_currentlyInterpretedKeyEvent = nsevent; [self interpretKeyEvents:[NSArray arrayWithObject:nsevent]]; + m_currentlyInterpretedKeyEvent = 0; } } - - m_platformWindow->m_ignoreWindowShouldClose = false;; } if (m_resendKeyEvent) m_sendKeyEvent = true; @@ -1491,21 +1488,23 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) [self handleKeyEvent:nsevent eventType:int(QEvent::KeyRelease)]; } -- (BOOL)performKeyEquivalent:(NSEvent *)nsevent +- (void)cancelOperation:(id)sender { - NSString *chars = [nsevent charactersIgnoringModifiers]; + Q_UNUSED(sender); - if ([nsevent type] == NSKeyDown && [chars length] > 0) { - QChar ch = [chars characterAtIndex:0]; - Qt::Key qtKey = qt_mac_cocoaKey2QtKey(ch); - // check for Command + Key_Period - if ([nsevent modifierFlags] & NSCommandKeyMask - && qtKey == Qt::Key_Period) { - [self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)]; - return YES; - } - } - return [super performKeyEquivalent:nsevent]; + NSEvent *currentEvent = [NSApp currentEvent]; + if (!currentEvent || currentEvent.type != NSKeyDown) + return; + + // Handling the key event may recurse back here through interpretKeyEvents + // (when IM is enabled), so we need to guard against that. + if (currentEvent == m_currentlyInterpretedKeyEvent) + return; + + // Send Command+Key_Period and Escape as normal keypresses so that + // the key sequence is delivered through Qt. That way clients can + // intercept the shortcut and override its effect. + [self handleKeyEvent:currentEvent eventType:int(QEvent::KeyPress)]; } - (void)flagsChanged:(NSEvent *)nsevent diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 2ebbaaee10..468bffe49e 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -2286,16 +2286,12 @@ bool QColorDialogPrivate::handleColorPickingMouseButtonRelease(QMouseEvent *e) bool QColorDialogPrivate::handleColorPickingKeyPress(QKeyEvent *e) { Q_Q(QColorDialog); - switch (e->key()) { - case Qt::Key_Escape: + if (e->matches(QKeySequence::Cancel)) { releaseColorPicking(); q->setCurrentColor(beforeScreenColorPicking); - break; - case Qt::Key_Return: - case Qt::Key_Enter: + } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { q->setCurrentColor(grabScreenColor(QCursor::pos())); releaseColorPicking(); - break; } e->accept(); return true; diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp index d04241fee0..5124960ab4 100644 --- a/src/widgets/dialogs/qdialog.cpp +++ b/src/widgets/dialogs/qdialog.cpp @@ -651,11 +651,9 @@ void QDialog::keyPressEvent(QKeyEvent *e) // Calls reject() if Escape is pressed. Simulates a button // click for the default button if Enter is pressed. Move focus // for the arrow keys. Ignore the rest. -#ifdef Q_OS_MAC - if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Period) { + if (e->matches(QKeySequence::Cancel)) { reject(); } else -#endif if (!e->modifiers() || (e->modifiers() & Qt::KeypadModifier && e->key() == Qt::Key_Enter)) { switch (e->key()) { case Qt::Key_Enter: @@ -671,9 +669,6 @@ void QDialog::keyPressEvent(QKeyEvent *e) } } break; - case Qt::Key_Escape: - reject(); - break; default: e->ignore(); return; diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 81beccd5c8..ee2b1e6dae 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -3778,6 +3778,12 @@ void QFileDialogPrivate::_q_nativeEnterDirectory(const QUrl &directory) bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) { Q_Q(QFileDialog); + + if (event->matches(QKeySequence::Cancel)) { + q->hide(); + return true; + } + switch (event->key()) { case Qt::Key_Backspace: _q_navigateToParent(); @@ -3793,9 +3799,6 @@ bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) { return true; } break; - case Qt::Key_Escape: - q->hide(); - return true; default: break; } @@ -3982,7 +3985,7 @@ void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e) int key = e->key(); QLineEdit::keyPressEvent(e); - if (key != Qt::Key_Escape && key != Qt::Key_Back) + if (!e->matches(QKeySequence::Cancel) && key != Qt::Key_Back) e->accept(); } diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index ef9b55acd6..8a48100ea7 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -1450,11 +1450,8 @@ void QMessageBox::changeEvent(QEvent *ev) void QMessageBox::keyPressEvent(QKeyEvent *e) { Q_D(QMessageBox); - if (e->key() == Qt::Key_Escape -#ifdef Q_OS_MAC - || (e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Period) -#endif - ) { + + if (e->matches(QKeySequence::Cancel)) { if (d->detectedEscapeButton) { #ifdef Q_OS_MAC d->detectedEscapeButton->animateClick(); diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp index 97e9267a9d..bbb251c8b2 100644 --- a/src/widgets/dialogs/qprogressdialog.cpp +++ b/src/widgets/dialogs/qprogressdialog.cpp @@ -411,7 +411,8 @@ void QProgressDialog::setCancelButton(QPushButton *cancelButton) if (cancelButton) { connect(d->cancel, SIGNAL(clicked()), this, SIGNAL(canceled())); #ifndef QT_NO_SHORTCUT - d->escapeShortcut = new QShortcut(Qt::Key_Escape, this, SIGNAL(canceled())); + // FIXME: This only registers the primary key sequence of the cancel action + d->escapeShortcut = new QShortcut(QKeySequence::Cancel, this, SIGNAL(canceled())); #endif } else { #ifndef QT_NO_SHORTCUT diff --git a/src/widgets/itemviews/qabstractitemdelegate.cpp b/src/widgets/itemviews/qabstractitemdelegate.cpp index 6efe5ccb71..c2dd1ec8fd 100644 --- a/src/widgets/itemviews/qabstractitemdelegate.cpp +++ b/src/widgets/itemviews/qabstractitemdelegate.cpp @@ -455,6 +455,12 @@ bool QAbstractItemDelegatePrivate::editorEventFilter(QObject *object, QEvent *ev if (editorHandlesKeyEvent(editor, keyEvent)) return false; + if (keyEvent->matches(QKeySequence::Cancel)) { + // don't commit data + emit q->closeEditor(editor, QAbstractItemDelegate::RevertModelCache); + return true; + } + switch (keyEvent->key()) { case Qt::Key_Tab: if (tryFixup(editor)) { @@ -479,10 +485,6 @@ bool QAbstractItemDelegatePrivate::editorEventFilter(QObject *object, QEvent *ev QMetaObject::invokeMethod(q, "_q_commitDataAndCloseEditor", Qt::QueuedConnection, Q_ARG(QWidget*, editor)); return false; - case Qt::Key_Escape: - // don't commit data - emit q->closeEditor(editor, QAbstractItemDelegate::RevertModelCache); - return true; default: return false; } @@ -509,7 +511,7 @@ bool QAbstractItemDelegatePrivate::editorEventFilter(QObject *object, QEvent *ev emit q->closeEditor(editor, QAbstractItemDelegate::NoHint); } } else if (event->type() == QEvent::ShortcutOverride) { - if (static_cast(event)->key() == Qt::Key_Escape) { + if (static_cast(event)->matches(QKeySequence::Cancel)) { event->accept(); return true; } diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp index 1e437c4fb7..81de2f25ca 100644 --- a/src/widgets/kernel/qwhatsthis.cpp +++ b/src/widgets/kernel/qwhatsthis.cpp @@ -459,7 +459,7 @@ bool QWhatsThisPrivate::eventFilter(QObject *o, QEvent *e) { QKeyEvent* kev = (QKeyEvent*)e; - if (kev->key() == Qt::Key_Escape) { + if (kev->matches(QKeySequence::Cancel)) { QWhatsThis::leaveWhatsThisMode(); return true; } else if (customWhatsThis) { diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 2c9cc5c07b..66c86a7bce 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -9349,7 +9349,8 @@ void QWidget::tabletEvent(QTabletEvent *event) call the base class implementation if you do not act upon the key. The default implementation closes popup widgets if the user - presses Esc. Otherwise the event is ignored, so that the widget's + presses the key sequence for QKeySequence::Cancel (typically the + Escape key). Otherwise the event is ignored, so that the widget's parent can interpret it. Note that QKeyEvent starts with isAccepted() == true, so you do not @@ -9362,7 +9363,7 @@ void QWidget::tabletEvent(QTabletEvent *event) void QWidget::keyPressEvent(QKeyEvent *event) { - if ((windowType() == Qt::Popup) && event->key() == Qt::Key_Escape) { + if ((windowType() == Qt::Popup) && event->matches(QKeySequence::Cancel)) { event->accept(); close(); } else { diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index fedc928f61..559f024e5f 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -1337,6 +1337,11 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e) } // default implementation for keys not handled by the widget when popup is open + if (ke->matches(QKeySequence::Cancel)) { + d->popup->hide(); + return true; + } + switch (key) { #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Select: @@ -1357,7 +1362,6 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e) break; case Qt::Key_Backtab: - case Qt::Key_Escape: d->popup->hide(); break; diff --git a/src/widgets/widgets/qabstractbutton.cpp b/src/widgets/widgets/qabstractbutton.cpp index 292bbc3325..a1707b9cab 100644 --- a/src/widgets/widgets/qabstractbutton.cpp +++ b/src/widgets/widgets/qabstractbutton.cpp @@ -1221,16 +1221,14 @@ void QAbstractButton::keyPressEvent(QKeyEvent *e) } break; } - case Qt::Key_Escape: - if (d->down) { + default: + if (e->matches(QKeySequence::Cancel) && d->down) { setDown(false); repaint(); //flush paint event before invoking potentially expensive operation QApplication::flush(); d->emitReleased(); - break; + return; } - // fall through - default: e->ignore(); } } diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp index 2150fc7a50..48b224fe13 100644 --- a/src/widgets/widgets/qcalendarwidget.cpp +++ b/src/widgets/widgets/qcalendarwidget.cpp @@ -776,7 +776,7 @@ bool QCalendarTextNavigator::eventFilter(QObject *o, QEvent *e) applyDate(); emit editingFinished(); removeDateLabel(); - } else if (ke->key() == Qt::Key_Escape) { + } else if (ke->matches(QKeySequence::Cancel)) { removeDateLabel(); } else if (e->type() == QEvent::KeyPress) { createDateLabel(); @@ -3078,8 +3078,7 @@ void QCalendarWidget::resizeEvent(QResizeEvent * event) void QCalendarWidget::keyPressEvent(QKeyEvent * event) { Q_D(QCalendarWidget); - if(d->yearEdit->isVisible()&& event->key() == Qt::Key_Escape) - { + if (d->yearEdit->isVisible()&& event->matches(QKeySequence::Cancel)) { d->yearEdit->setValue(yearShown()); d->_q_yearEditingFinished(); return; diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 89fd3d3d57..aab28bf18a 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -654,8 +654,9 @@ void QComboBoxPrivateContainer::changeEvent(QEvent *e) bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) { switch (e->type()) { - case QEvent::ShortcutOverride: - switch (static_cast(e)->key()) { + case QEvent::ShortcutOverride: { + QKeyEvent *keyEvent = static_cast(e); + switch (keyEvent->key()) { case Qt::Key_Enter: case Qt::Key_Return: #ifdef QT_KEYPAD_NAVIGATION @@ -667,17 +668,21 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) } return true; case Qt::Key_Down: - if (!(static_cast(e)->modifiers() & Qt::AltModifier)) + if (!(keyEvent->modifiers() & Qt::AltModifier)) break; // fall through case Qt::Key_F4: - case Qt::Key_Escape: combo->hidePopup(); return true; default: + if (keyEvent->matches(QKeySequence::Cancel)) { + combo->hidePopup(); + return true; + } break; } - break; + break; + } case QEvent::MouseMove: if (isVisible()) { QMouseEvent *m = static_cast(e); diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index a8da78a025..42987df3ec 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -2655,7 +2655,7 @@ bool QCalendarPopup::event(QEvent *event) { if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); - if (keyEvent->key()== Qt::Key_Escape) + if (keyEvent->matches(QKeySequence::Cancel)) dateChanged = false; } return QWidget::event(event); diff --git a/src/widgets/widgets/qeffects.cpp b/src/widgets/widgets/qeffects.cpp index 708e90cc32..b256861d08 100644 --- a/src/widgets/widgets/qeffects.cpp +++ b/src/widgets/widgets/qeffects.cpp @@ -197,7 +197,7 @@ bool QAlphaWidget::eventFilter(QObject *o, QEvent *e) break; case QEvent::KeyPress: { QKeyEvent *ke = (QKeyEvent*)e; - if (ke->key() == Qt::Key_Escape) { + if (ke->matches(QKeySequence::Cancel)) { showWidget = false; } else { duration = 0; diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 0556c02b64..6e37f91197 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -2679,7 +2679,7 @@ QMenu::event(QEvent *e) if (kev->key() == Qt::Key_Up || kev->key() == Qt::Key_Down || kev->key() == Qt::Key_Left || kev->key() == Qt::Key_Right || kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return - || kev->key() == Qt::Key_Escape) { + || kev->matches(QKeySequence::Cancel)) { e->accept(); return true; } @@ -2965,27 +2965,6 @@ void QMenu::keyPressEvent(QKeyEvent *e) } break; - case Qt::Key_Escape: -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Back: -#endif - key_consumed = true; - if (d->tornoff) { - close(); - return; - } - { - QPointer caused = d->causedPopup.widget; - d->hideMenu(this); // hide after getting causedPopup -#ifndef QT_NO_MENUBAR - if (QMenuBar *mb = qobject_cast(caused)) { - mb->d_func()->setCurrentAction(d->menuAction); - mb->d_func()->setKeyboardMode(true); - } -#endif - } - break; - case Qt::Key_Space: if (!style()->styleHint(QStyle::SH_Menu_SpaceActivatesItem, 0, this)) break; @@ -3022,6 +3001,28 @@ void QMenu::keyPressEvent(QKeyEvent *e) key_consumed = false; } + if (!key_consumed && (e->matches(QKeySequence::Cancel) +#ifdef QT_KEYPAD_NAVIGATION + || e->key() == Qt::Key_Back +#endif + )) { + key_consumed = true; + if (d->tornoff) { + close(); + return; + } + { + QPointer caused = d->causedPopup.widget; + d->hideMenu(this); // hide after getting causedPopup +#ifndef QT_NO_MENUBAR + if (QMenuBar *mb = qobject_cast(caused)) { + mb->d_func()->setCurrentAction(d->menuAction); + mb->d_func()->setKeyboardMode(true); + } +#endif + } + } + if (!key_consumed) { // send to menu bar if ((!e->modifiers() || e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ShiftModifier) && e->text().length()==1) { diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index d382131075..2e48607f82 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -1122,14 +1122,14 @@ void QMenuBar::keyPressEvent(QKeyEvent *e) } break; } - case Qt::Key_Escape: + default: + key_consumed = false; + } + + if (!key_consumed && e->matches(QKeySequence::Cancel)) { d->setCurrentAction(0); d->setKeyboardMode(false); key_consumed = true; - break; - - default: - key_consumed = false; } if(!key_consumed && @@ -1432,7 +1432,7 @@ bool QMenuBar::event(QEvent *e) case QEvent::ShortcutOverride: { QKeyEvent *kev = static_cast(e); //we only filter out escape if there is a current action - if (kev->key() == Qt::Key_Escape && d->currentAction) { + if (kev->matches(QKeySequence::Cancel) && d->currentAction) { e->accept(); return true; } From 1a6ac8319313b6e024305397512513387afcafb8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 27 Sep 2015 11:43:47 -0700 Subject: [PATCH 096/240] Ensure there's no sign-extension here. Both e_shentsize and e_shtrndx are ELF half-words, which means C integers of rank less than int (they're quint16). That means this multiplcation was done actually as int, due to integer promotion from unsigned short. So preempt the integer promotion and force them to full- word integers (unsigned int). While the bit-pattern result of the multiplication is the same, the addition with e_shoff (a qelfoff_t = quintptr) wouldn't: the promotion from 32-bit int to 64-bit would first execute a sign-extension. Now, this shouldn't happen on regular ELF files, but it cause QLibrary to crash if a specially-crafted (or simply corrupt) plugin is found. Found by Coverity, CID 22642 Change-Id: I42e7ef1a481840699a8dffff1407e9f1282eeecf Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/plugin/qelfparser_p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp index d93be439e0..3798231383 100644 --- a/src/corelib/plugin/qelfparser_p.cpp +++ b/src/corelib/plugin/qelfparser_p.cpp @@ -148,7 +148,7 @@ int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library #endif ElfSectionHeader strtab; - qulonglong soff = e_shoff + e_shentsize * (e_shtrndx); + qulonglong soff = e_shoff + qelfword_t(e_shentsize) * qelfword_t(e_shtrndx); if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) { if (lib) From d24366a63281543e6c1a8e6b615ce882ea6259ab Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 25 Sep 2015 10:45:20 +0200 Subject: [PATCH 097/240] Fix comparisons between QByteArray and QString. QByteArray::operator< and friends had their logic reversed. Task-number: QTBUG-48350 Change-Id: I625209cc922b47e78dfb8de9fe100411f285a628 Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.h | 8 ++++---- tests/auto/corelib/tools/qstring/tst_qstring.cpp | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 63107ff688..d44a5baf2a 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1228,13 +1228,13 @@ inline bool QByteArray::operator==(const QString &s) const inline bool QByteArray::operator!=(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) != 0; } inline bool QByteArray::operator<(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) < 0; } -inline bool QByteArray::operator>(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) > 0; } +inline bool QByteArray::operator>(const QString &s) const +{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) < 0; } inline bool QByteArray::operator<=(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) <= 0; } -inline bool QByteArray::operator>=(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) >= 0; } +inline bool QByteArray::operator>=(const QString &s) const +{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) <= 0; } #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) #ifndef QT_NO_CAST_TO_ASCII diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 6d4dbab1fd..0d10a9c5bd 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -4584,6 +4584,22 @@ void tst_QString::operator_smaller() QVERIFY(QString("b") >= "a"); QVERIFY(QString("b") > "a"); + QVERIFY(QString("a") < QByteArray("b")); + QVERIFY(QString("a") <= QByteArray("b")); + QVERIFY(QString("a") <= QByteArray("a")); + QVERIFY(QString("a") == QByteArray("a")); + QVERIFY(QString("a") >= QByteArray("a")); + QVERIFY(QString("b") >= QByteArray("a")); + QVERIFY(QString("b") > QByteArray("a")); + + QVERIFY(QByteArray("a") < QString("b")); + QVERIFY(QByteArray("a") <= QString("b")); + QVERIFY(QByteArray("a") <= QString("a")); + QVERIFY(QByteArray("a") == QString("a")); + QVERIFY(QByteArray("a") >= QString("a")); + QVERIFY(QByteArray("b") >= QString("a")); + QVERIFY(QByteArray("b") > QString("a")); + QVERIFY(QLatin1String("a") < QString("b")); QVERIFY(QLatin1String("a") <= QString("b")); QVERIFY(QLatin1String("a") <= QString("a")); From b47bcba0f5d0f7f682f46adafe16eebec6eb020b Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Fri, 11 Sep 2015 14:09:09 +0200 Subject: [PATCH 098/240] Doc: minor link issue in qtbase Task-number: QTBUG-43810 Change-Id: I018c25146e6be3fa2c9dfffbdc9bd71738aefcc2 Reviewed-by: Martin Smith --- src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc index fc3ac345a8..0547c4f64a 100644 --- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc +++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc @@ -2981,7 +2981,7 @@ \li \b{Url} \target Url \li \tt{url(\e{filename})} \li \tt{\e{filename}} is the name of a file on the local disk - or stored using \l{the Qt Resource System}. Setting an + or stored using \l{The Qt Resource System}. Setting an image implicitly sets the width and height of the element. \endtable From 4accd865c24b7ed918cb705913478bab5aeb5e6e Mon Sep 17 00:00:00 2001 From: David Faure Date: Mon, 14 Sep 2015 11:11:54 +0200 Subject: [PATCH 099/240] QLockFile: sync to disk to avoid leaving an empty lock file on crash The two lines of code are the same as in QFSFileEnginePrivate::nativeSyncToDisk, but we don't want to create a fileengine instance just for this. qlockfile_win.cpp already calls FlushFileBuffers, only the Unix implementation was missing the equivalent call. Task-number: QTBUG-44771 Change-Id: I2253972857e4de9d27ef442c92983a1088d6f03e Reviewed-by: Thiago Macieira --- src/corelib/io/qlockfile_unix.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 27f8a97fd4..b298b08939 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -178,6 +178,13 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() // We hold the lock, continue. fileHandle = fd; + // Sync to disk if possible. Ignore errors (e.g. not supported). +#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 + fdatasync(fileHandle); +#else + fsync(fileHandle); +#endif + return QLockFile::NoError; } From 3964b683f849baade1576ea2f50aab631970df58 Mon Sep 17 00:00:00 2001 From: Martin Afanasjew Date: Sun, 27 Sep 2015 14:39:06 +0200 Subject: [PATCH 100/240] qmake: Fix 'Libs:' line in .pc files on OS X On OS X with a framework-based build of Qt, the 'Libs:' line of the .pc files generated by `qmake` references the framework. This requires two separate arguments to the linker: The fixed string '-framework' and the name of the framework (e.g. 'QtCore'). Only the latter might need quoting. Prior to this fix, they were treated as a single argument (e.g. '-framework QtCore'), thus always quoted because of the contained space, and later lead to errors when trying to link a Qt framework discovered via `pkg-config`. Change-Id: I5c11ee651048832007e2ee4ebcbcf2e3212c8f48 Task-number: QTBUG-47162 Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefile.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 4a03fafd77..7d4026c292 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -3253,7 +3253,8 @@ MakefileGenerator::writePkgConfigFile() int suffix = bundle.lastIndexOf(".framework"); if (suffix != -1) bundle = bundle.left(suffix); - pkgConfiglibName = "-framework " + bundle + " "; + t << "-framework "; + pkgConfiglibName = bundle.toQString(); } else { if (!project->values("QMAKE_DEFAULT_LIBDIRS").contains(libDir)) t << "-L${libdir} "; From 9facf1be9b73da656557bab547aeb4148e6ff448 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 24 Sep 2015 15:56:57 +0200 Subject: [PATCH 101/240] Tests: Always verify whether QTemporaryDir/File creation succeeded. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use QVERIFY2() with QTemporaryDir/File::errorString() consistently. Attempt to catch issues like the below warning and follow-up issues. QSYSTEM: tst_QFiledialog::clearLineEdit() QFileSystemWatcher: FindNextChangeNotification failed for "C:\Users\qt\_____aaaaaaaaaaaaaaaaaaaaaa" (Access is denied.) Task-number: QTBUG-47370 Change-Id: I58a6e87c502627e976efa62ad73c912f3b2d49fa Reviewed-by: Jędrzej Nowacki --- tests/auto/corelib/io/qdir/tst_qdir.cpp | 4 ++-- tests/auto/corelib/io/qfile/tst_qfile.cpp | 2 +- .../corelib/io/qfileinfo/tst_qfileinfo.cpp | 4 ++-- .../tst_qfilesystemwatcher.cpp | 13 ++++++----- .../corelib/io/qlockfile/tst_qlockfile.cpp | 1 + .../corelib/io/qsavefile/tst_qsavefile.cpp | 22 +++++++++---------- .../corelib/io/qsettings/tst_qsettings.cpp | 2 +- .../io/qstandardpaths/tst_qstandardpaths.cpp | 9 ++++++++ .../io/qstorageinfo/tst_qstorageinfo.cpp | 4 ++-- .../io/qtextstream/tst_qtextstream.cpp | 1 + .../qmimedatabase/tst_qmimedatabase.cpp | 1 + .../dbus/qdbusmarshall/tst_qdbusmarshall.cpp | 6 ++++- .../image/qimagereader/tst_qimagereader.cpp | 2 +- .../image/qimagewriter/tst_qimagewriter.cpp | 10 ++++----- .../painting/qpdfwriter/tst_qpdfwriter.cpp | 6 ++--- .../tst_qabstractnetworkcache.cpp | 3 +++ .../tst_qnetworkdiskcache.cpp | 2 +- .../qnetworkreply/tst_qnetworkreply.cpp | 7 +++--- .../languagechange/tst_languagechange.cpp | 2 +- .../auto/testlib/selftests/tst_selftests.cpp | 1 + tests/auto/tools/uic/tst_uic.cpp | 1 + .../dialogs/qfiledialog/tst_qfiledialog.cpp | 8 +++---- .../dialogs/qfiledialog2/tst_qfiledialog2.cpp | 11 +++++----- .../qfilesystemmodel/tst_qfilesystemmodel.cpp | 6 ++--- 24 files changed, 75 insertions(+), 53 deletions(-) diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index 72d036c2ae..1f98c75f3f 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -845,8 +845,8 @@ void tst_QDir::entryListTimedSort() QTemporaryFile aFile(entrylistPath + "A-XXXXXX.qws"); QTemporaryFile bFile(entrylistPath + "B-XXXXXX.qws"); - QVERIFY(aFile.open()); - QVERIFY(bFile.open()); + QVERIFY2(aFile.open(), qPrintable(aFile.errorString())); + QVERIFY2(bFile.open(), qPrintable(bFile.errorString())); { QProcess p; p.start(touchBinary, QStringList() << "-t" << "201306021513" << aFile.fileName()); diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index b423e857d0..b0d0d122e8 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -392,7 +392,7 @@ tst_QFile::tst_QFile() : m_oldDir(QDir::currentPath()) void tst_QFile::initTestCase() { - QVERIFY(m_temporaryDir.isValid()); + QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); m_stdinProcessDir = QFINDTESTDATA("stdinprocess"); QVERIFY(!m_stdinProcessDir.isEmpty()); m_testSourceFile = QFINDTESTDATA("tst_qfile.cpp"); diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index 8d276b3616..8784261c2b 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -317,7 +317,7 @@ static QFileInfoPrivate* getPrivate(QFileInfo &info) void tst_QFileInfo::copy() { QTemporaryFile t; - t.open(); + QVERIFY2(t.open(), qPrintable(t.errorString())); QFileInfo info(t.fileName()); QVERIFY(info.exists()); @@ -612,7 +612,7 @@ void tst_QFileInfo::canonicalPath() { QTemporaryFile tempFile; tempFile.setAutoRemove(true); - tempFile.open(); + QVERIFY2(tempFile.open(), qPrintable(tempFile.errorString())); QFileInfo fi(tempFile.fileName()); QCOMPARE(fi.canonicalPath(), QFileInfo(QDir::tempPath()).canonicalFilePath()); } diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp index a0434aa8ee..026743257c 100644 --- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp +++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp @@ -126,7 +126,7 @@ void tst_QFileSystemWatcher::basicTest() // create test file QTemporaryDir temporaryDirectory(m_tempDirPattern); - QVERIFY(temporaryDirectory.isValid()); + QVERIFY2(temporaryDirectory.isValid(), qPrintable(temporaryDirectory.errorString())); QFile testFile(temporaryDirectory.path() + QLatin1Char('/') + testFileName); QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); testFile.write(QByteArray("hello")); @@ -263,7 +263,7 @@ void tst_QFileSystemWatcher::watchDirectory() QFETCH(QString, backend); QTemporaryDir temporaryDirectory(m_tempDirPattern); - QVERIFY(temporaryDirectory.isValid()); + QVERIFY2(temporaryDirectory.isValid(), qPrintable(temporaryDirectory.errorString())); QDir temporaryDir(temporaryDirectory.path()); const QString testDirName = QStringLiteral("testDir"); @@ -498,7 +498,7 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory() QFETCH(QString, backend); QTemporaryDir temporaryDirectory(m_tempDirPattern); - QVERIFY(temporaryDirectory.isValid()); + QVERIFY2(temporaryDirectory.isValid(), qPrintable(temporaryDirectory.errorString())); QDir temporaryDir(temporaryDirectory.path()); const QString testDirName = QStringLiteral("testDir"); @@ -605,7 +605,7 @@ void tst_QFileSystemWatcher::nonExistingFile() void tst_QFileSystemWatcher::removeFileAndUnWatch() { QTemporaryDir temporaryDirectory(m_tempDirPattern); - QVERIFY(temporaryDirectory.isValid()); + QVERIFY2(temporaryDirectory.isValid(), qPrintable(temporaryDirectory.errorString())); const QString filename = temporaryDirectory.path() + QStringLiteral("/foo.txt"); @@ -664,7 +664,7 @@ void tst_QFileSystemWatcher::QTBUG2331() QFETCH(QString, backend); QTemporaryDir temporaryDirectory(m_tempDirPattern); - QVERIFY(temporaryDirectory.isValid()); + QVERIFY2(temporaryDirectory.isValid(), qPrintable(temporaryDirectory.errorString())); QFileSystemWatcher watcher; watcher.setObjectName(QLatin1String("_qt_autotest_force_engine_") + backend); QVERIFY(watcher.addPath(temporaryDirectory.path())); @@ -724,7 +724,8 @@ void tst_QFileSystemWatcher::signalsEmittedAfterFileMoved() { const int fileCount = 10; QTemporaryDir temporaryDirectory(m_tempDirPattern); - QVERIFY(temporaryDirectory.isValid()); + QVERIFY2(temporaryDirectory.isValid(), qPrintable(temporaryDirectory.errorString())); + QDir testDir(temporaryDirectory.path()); QVERIFY(testDir.mkdir("movehere")); QString movePath = testDir.filePath("movehere"); diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp index 27614e0eb8..21c5696d1d 100644 --- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp +++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp @@ -80,6 +80,7 @@ void tst_QLockFile::initTestCase() #elif defined(QT_NO_PROCESS) QSKIP("This test requires QProcess support"); #else + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); // chdir to our testdata path and execute helper apps relative to that. QString testdata_dir = QFileInfo(QFINDTESTDATA("qlockfiletesthelper")).absolutePath(); QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir)); diff --git a/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp b/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp index 5796636b92..6e6dc2df95 100644 --- a/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp +++ b/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp @@ -99,7 +99,7 @@ static inline QByteArray msgCannotOpen(const QFileDevice &f) void tst_QSaveFile::transactionalWrite() { QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); QFile::remove(targetFile); QSaveFile file(targetFile); @@ -134,7 +134,7 @@ void tst_QSaveFile::saveTwice() // Check that we can reuse a QSaveFile object // (and test the case of an existing target file) QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); QSaveFile file(targetFile); QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData()); @@ -153,7 +153,7 @@ void tst_QSaveFile::saveTwice() void tst_QSaveFile::textStreamManualFlush() { QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); QSaveFile file(targetFile); QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData()); @@ -174,7 +174,7 @@ void tst_QSaveFile::textStreamManualFlush() void tst_QSaveFile::textStreamAutoFlush() { QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); QSaveFile file(targetFile); QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData()); @@ -206,7 +206,7 @@ void tst_QSaveFile::transactionalWriteNoPermissionsOnDir() #endif QFETCH(bool, directWriteFallback); QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); QVERIFY(QFile(dir.path()).setPermissions(QFile::ReadOwner | QFile::ExeOwner)); PermissionRestorer permissionRestorer(dir.path()); @@ -264,7 +264,7 @@ void tst_QSaveFile::transactionalWriteNoPermissionsOnFile() #endif // Setup an existing but readonly file QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); QFile file(targetFile); PermissionRestorer permissionRestorer(targetFile); @@ -285,7 +285,7 @@ void tst_QSaveFile::transactionalWriteNoPermissionsOnFile() void tst_QSaveFile::transactionalWriteCanceled() { QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); QFile::remove(targetFile); QSaveFile file(targetFile); @@ -313,7 +313,7 @@ void tst_QSaveFile::transactionalWriteErrorRenaming() QSKIP("Test is not applicable with root privileges"); #endif QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); QSaveFile file(targetFile); QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData()); @@ -347,7 +347,7 @@ void tst_QSaveFile::symlink() #ifdef Q_OS_UNIX QByteArray someData = "some data"; QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); const QString targetFile = dir.path() + QLatin1String("/outfile"); const QString linkFile = dir.path() + QLatin1String("/linkfile"); @@ -400,7 +400,7 @@ void tst_QSaveFile::symlink() // link to a link in another directory QTemporaryDir dir2; - QVERIFY(dir2.isValid()); + QVERIFY2(dir2.isValid(), qPrintable(dir2.errorString())); const QString linkFile2 = dir2.path() + QLatin1String("/linkfile"); QVERIFY(QFile::link(linkFile, linkFile2)); @@ -458,7 +458,7 @@ void tst_QSaveFile::symlink() void tst_QSaveFile::directory() { QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); const QString subdir = dir.path() + QLatin1String("/subdir"); QVERIFY(QDir(dir.path()).mkdir(QStringLiteral("subdir"))); diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index badff20490..935eb7df89 100644 --- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp +++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp @@ -3331,7 +3331,7 @@ void tst_QSettings::dontReorderIniKeysNeedlessly() QString outFileName2; QTemporaryFile outFile; - outFile.open(); + QVERIFY2(outFile.open(), qPrintable(outFile.errorString())); outFile.write(contentsBefore); outFileName = outFile.fileName(); outFile.close(); diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp index efb343cf85..24ff2f237f 100644 --- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp +++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp @@ -56,6 +56,7 @@ class tst_qstandardpaths : public QObject Q_OBJECT private slots: + void initTestCase(); void dump(); void testDefaultLocations(); void testCustomLocations(); @@ -128,6 +129,14 @@ static const char * const enumNames[MaxStandardLocation + 1 - int(QStandardPaths "AppConfigLocation" }; +void tst_qstandardpaths::initTestCase() +{ + QVERIFY2(m_localConfigTempDir.isValid(), qPrintable(m_localConfigTempDir.errorString())); + QVERIFY2(m_globalConfigTempDir.isValid(), qPrintable(m_globalConfigTempDir.errorString())); + QVERIFY2(m_localAppTempDir.isValid(), qPrintable(m_localAppTempDir.errorString())); + QVERIFY2(m_globalAppTempDir.isValid(), qPrintable(m_globalAppTempDir.errorString())); +} + void tst_qstandardpaths::dump() { #ifdef Q_XDG_PLATFORM diff --git a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp index a7a0cf4ddb..efbcdc78e0 100644 --- a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp +++ b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp @@ -153,7 +153,7 @@ void tst_QStorageInfo::storageList() void tst_QStorageInfo::tempFile() { QTemporaryFile file; - QVERIFY(file.open()); + QVERIFY2(file.open(), qPrintable(file.errorString())); QStorageInfo storage1(file.fileName()); #ifdef Q_OS_LINUX @@ -174,7 +174,7 @@ void tst_QStorageInfo::tempFile() void tst_QStorageInfo::caching() { QTemporaryFile file; - QVERIFY(file.open()); + QVERIFY2(file.open(), qPrintable(file.errorString())); QStorageInfo storage1(file.fileName()); #ifdef Q_OS_LINUX diff --git a/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp index 36da3b8770..ecec97f009 100644 --- a/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp +++ b/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp @@ -258,6 +258,7 @@ tst_QTextStream::tst_QTextStream() void tst_QTextStream::initTestCase() { + QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); QVERIFY(!m_rfc3261FilePath.isEmpty()); QVERIFY(!m_shiftJisFilePath.isEmpty()); diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp index dd04849f87..594aef28f0 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp @@ -120,6 +120,7 @@ tst_QMimeDatabase::tst_QMimeDatabase() void tst_QMimeDatabase::initTestCase() { + QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); QStandardPaths::setTestModeEnabled(true); m_localMimeDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/mime"; if (QDir(m_localMimeDir).exists()) { diff --git a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp index b681f9829a..57fd5084be 100644 --- a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp @@ -150,7 +150,11 @@ int tst_QDBusMarshall::fileDescriptorForTest() { if (!tempFile.isOpen()) { tempFile.setFileTemplate(QDir::tempPath() + "/qdbusmarshalltestXXXXXX.tmp"); - tempFile.open(); + if (!tempFile.open()) { + qWarning("%s: Cannot create temporary file: %s", Q_FUNC_INFO, + qPrintable(tempFile.errorString())); + return 0; + } } return tempFile.handle(); } diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index 07b75adae4..16fe959b11 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -194,7 +194,7 @@ void tst_QImageReader::initTestCase() prefix = QFINDTESTDATA("images/"); if (prefix.isEmpty()) QFAIL("Can't find images directory!"); - QVERIFY(m_temporaryDir.isValid()); + QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); } void tst_QImageReader::cleanupTestCase() diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp index 4f04e50294..06c775dded 100644 --- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp @@ -416,7 +416,7 @@ void tst_QImageWriter::testCanWrite() { // check if canWrite won't leave an empty file QTemporaryDir dir; - QVERIFY(dir.isValid()); + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); QString fileName(dir.path() + QLatin1String("/001.garble")); QVERIFY(!QFileInfo(fileName).exists()); QImageWriter writer(fileName); @@ -524,7 +524,7 @@ void tst_QImageWriter::saveToTemporaryFile() { // 1) Via QImageWriter's API, with a standard temp file name QTemporaryFile file; - QVERIFY(file.open()); + QVERIFY2(file.open(), qPrintable(file.errorString())); QImageWriter writer(&file, "PNG"); if (writer.canWrite()) QVERIFY(writer.write(image)); @@ -538,7 +538,7 @@ void tst_QImageWriter::saveToTemporaryFile() { // 2) Via QImage's API, with a standard temp file name QTemporaryFile file; - QVERIFY(file.open()); + QVERIFY2(file.open(), qPrintable(file.errorString())); QVERIFY(image.save(&file, "PNG")); file.reset(); QImage tmp; @@ -548,7 +548,7 @@ void tst_QImageWriter::saveToTemporaryFile() { // 3) Via QImageWriter's API, with a named temp file QTemporaryFile file("tempXXXXXX"); - QVERIFY(file.open()); + QVERIFY2(file.open(), qPrintable(file.errorString())); QImageWriter writer(&file, "PNG"); QVERIFY(writer.write(image)); #if defined(Q_OS_WINCE) @@ -559,7 +559,7 @@ void tst_QImageWriter::saveToTemporaryFile() { // 4) Via QImage's API, with a named temp file QTemporaryFile file("tempXXXXXX"); - QVERIFY(file.open()); + QVERIFY2(file.open(), qPrintable(file.errorString())); QVERIFY(image.save(&file, "PNG")); file.reset(); QImage tmp; diff --git a/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp b/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp index 4bc31baba8..5eaee1192a 100644 --- a/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp +++ b/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp @@ -50,8 +50,7 @@ private slots: void tst_QPdfWriter::basics() { QTemporaryFile file; - if (!file.open()) - QSKIP("Couldn't open temp file!"); + QVERIFY2(file.open(), qPrintable(file.errorString())); QPdfWriter writer(file.fileName()); QCOMPARE(writer.title(), QString()); @@ -150,8 +149,7 @@ void tst_QPdfWriter::testPageMetrics() QSizeF sizeMMf = QSizeF(widthMMf, heightMMf); QTemporaryFile file; - if (!file.open()) - QSKIP("Couldn't open temp file!"); + QVERIFY2(file.open(), qPrintable(file.errorString())); QPdfWriter writer(file.fileName()); QCOMPARE(writer.pageLayout().orientation(), QPageLayout::Portrait); diff --git a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp index 4cbdef2bbe..fd48ec3253 100644 --- a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp +++ b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp @@ -294,6 +294,7 @@ void tst_QAbstractNetworkCache::runTest() QNetworkAccessManager manager; NetworkDiskCache *diskCache = new NetworkDiskCache(&manager); + QVERIFY2(diskCache->tempDir.isValid(), qPrintable(diskCache->tempDir.errorString())); manager.setCache(diskCache); QCOMPARE(diskCache->gotData, false); @@ -344,6 +345,7 @@ void tst_QAbstractNetworkCache::checkSynchronous() QNetworkAccessManager manager; NetworkDiskCache *diskCache = new NetworkDiskCache(&manager); + QVERIFY2(diskCache->tempDir.isValid(), qPrintable(diskCache->tempDir.errorString())); manager.setCache(diskCache); QCOMPARE(diskCache->gotData, false); @@ -392,6 +394,7 @@ void tst_QAbstractNetworkCache::deleteCache() { QNetworkAccessManager manager; NetworkDiskCache *diskCache = new NetworkDiskCache(&manager); + QVERIFY2(diskCache->tempDir.isValid(), qPrintable(diskCache->tempDir.errorString())); manager.setCache(diskCache); QString url = "httpcachetest_cachecontrol.cgi?max-age=1000"; diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp index 708e7ebca8..1685838e9e 100644 --- a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp +++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp @@ -563,7 +563,7 @@ void tst_QNetworkDiskCache::oldCacheVersionFile() { QTemporaryFile file(cache.cacheDirectory() + "/XXXXXX.d"); file.setAutoRemove(false); - QVERIFY(file.open()); + QVERIFY2(file.open(), qPrintable(file.errorString())); QDataStream out(&file); out << qint32(0xe8); out << qint32(2); diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index debdc6bcb3..fbeeec2ec4 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -1679,7 +1679,7 @@ void tst_QNetworkReply::getFromFile() // create the file: QTemporaryFile file(QDir::currentPath() + "/temp-XXXXXX"); file.setAutoRemove(true); - QVERIFY(file.open()); + QVERIFY2(file.open(), qPrintable(file.errorString())); QNetworkRequest request(QUrl::fromLocalFile(file.fileName())); QNetworkReplyPtr reply; @@ -3065,7 +3065,7 @@ void tst_QNetworkReply::ioGetFromFile() { QTemporaryFile file(QDir::currentPath() + "/temp-XXXXXX"); file.setAutoRemove(true); - QVERIFY(file.open()); + QVERIFY2(file.open(), qPrintable(file.errorString())); QFETCH(QByteArray, data); QCOMPARE(file.write(data), data.size()); @@ -5353,7 +5353,7 @@ void tst_QNetworkReply::chaining() { QTemporaryFile sourceFile(QDir::currentPath() + "/temp-XXXXXX"); sourceFile.setAutoRemove(true); - QVERIFY(sourceFile.open()); + QVERIFY2(sourceFile.open(), qPrintable(sourceFile.errorString())); QFETCH(QByteArray, data); QCOMPARE(sourceFile.write(data), data.size()); @@ -7194,6 +7194,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() { QByteArray postData = "ACT=100"; QTemporaryDir tempDir(QDir::tempPath() + "/tmp_cache_28035"); + QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); tempDir.setAutoRemove(true); QNetworkDiskCache *diskCache = new QNetworkDiskCache(); diff --git a/tests/auto/other/languagechange/tst_languagechange.cpp b/tests/auto/other/languagechange/tst_languagechange.cpp index 788993ef35..68d604547d 100644 --- a/tests/auto/other/languagechange/tst_languagechange.cpp +++ b/tests/auto/other/languagechange/tst_languagechange.cpp @@ -276,7 +276,7 @@ void tst_languageChange::retranslatability() tempDirPattern += QStringLiteral("languagechangetestdirXXXXXX"); QTemporaryDir temporaryDir(tempDirPattern); temporaryDir.setAutoRemove(true); - QVERIFY(temporaryDir.isValid()); + QVERIFY2(temporaryDir.isValid(), qPrintable(temporaryDir.errorString())); const QString finalDir = temporaryDir.path() + QStringLiteral("/finaldir"); const QString fooName = temporaryDir.path() + QStringLiteral("/foo"); QDir dir; diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index 42d929c4a1..11de65c3c0 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -316,6 +316,7 @@ tst_Selftests::tst_Selftests() void tst_Selftests::initTestCase() { + QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); //Detect the location of the sub programs QString subProgram = QLatin1String("float/float"); #if defined(Q_OS_WIN) diff --git a/tests/auto/tools/uic/tst_uic.cpp b/tests/auto/tools/uic/tst_uic.cpp index eac80bed7a..42c8e3e7b9 100644 --- a/tests/auto/tools/uic/tst_uic.cpp +++ b/tests/auto/tools/uic/tst_uic.cpp @@ -86,6 +86,7 @@ static QByteArray msgProcessStartFailed(const QString &command, const QString &w void tst_uic::initTestCase() { + QVERIFY2(m_generated.isValid(), qPrintable(m_generated.errorString())); QVERIFY(m_versionRegexp.isValid()); m_baseline = QFINDTESTDATA("baseline"); QVERIFY2(!m_baseline.isEmpty(), "Could not find 'baseline'."); diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp index cc321bb137..bc3c5e73f0 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp @@ -483,11 +483,11 @@ void tst_QFiledialog::completer() if (startPath.isEmpty()) { tempDir.reset(new QTemporaryDir); - QVERIFY(tempDir->isValid()); + QVERIFY2(tempDir->isValid(), qPrintable(tempDir->errorString())); startPath = tempDir->path(); for (int i = 0; i < 10; ++i) { TemporaryFilePtr file(new QTemporaryFile(startPath + QStringLiteral("/rXXXXXX"))); - QVERIFY(file->open()); + QVERIFY2(file->open(), qPrintable(file->errorString())); files.append(file); } } @@ -889,7 +889,7 @@ void tst_QFiledialog::selectFile() QScopedPointer tempFile; if (file == QLatin1String("temp")) { tempFile.reset(new QTemporaryFile(QDir::tempPath() + QStringLiteral("/aXXXXXX"))); - QVERIFY(tempFile->open()); + QVERIFY2(tempFile->open(), qPrintable(tempFile->errorString())); file = tempFile->fileName(); } @@ -927,7 +927,7 @@ void tst_QFiledialog::selectFileWrongCaseSaveAs() void tst_QFiledialog::selectFiles() { QTemporaryDir tempDir; - QVERIFY(tempDir.isValid()); + QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); const QString tempPath = tempDir.path(); { QNonNativeFileDialog fd; diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp index 7e6e5908ee..ed44a5d503 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp @@ -171,7 +171,7 @@ void tst_QFileDialog2::cleanupSettingsFile() void tst_QFileDialog2::initTestCase() { - QVERIFY(tempDir.isValid()); + QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); QStandardPaths::setTestModeEnabled(true); cleanupSettingsFile(); } @@ -243,13 +243,13 @@ void tst_QFileDialog2::deleteDirAndFiles() QTemporaryFile *t; t = new QTemporaryFile(tempPath + "/foo/aXXXXXX"); t->setAutoRemove(false); - t->open(); + QVERIFY2(t->open(), qPrintable(t->errorString())); t->close(); delete t; t = new QTemporaryFile(tempPath + "/foo/B/yXXXXXX"); t->setAutoRemove(false); - t->open(); + QVERIFY2(t->open(), qPrintable(t->errorString())); t->close(); delete t; FriendlyQFileDialog fd; @@ -849,7 +849,7 @@ void tst_QFileDialog2::task228844_ensurePreviousSorting() current.mkdir("f"); current.mkdir("g"); QTemporaryFile *tempFile = new QTemporaryFile(current.absolutePath() + "/rXXXXXX"); - tempFile->open(); + QVERIFY2(tempFile->open(), qPrintable(tempFile->errorString())); current.cdUp(); QNonNativeFileDialog fd; @@ -1108,6 +1108,7 @@ void tst_QFileDialog2::task254490_selectFileMultipleTimes() QString tempPath = tempDir.path(); QTemporaryFile *t; t = new QTemporaryFile; + QVERIFY2(t->open(), qPrintable(t->errorString())); t->open(); QNonNativeFileDialog fd(0, "TestFileDialog"); @@ -1209,7 +1210,7 @@ void tst_QFileDialog2::QTBUG4419_lineEditSelectAll() { QString tempPath = tempDir.path(); QTemporaryFile temporaryFile(tempPath + "/tst_qfiledialog2_lineEditSelectAll.XXXXXX"); - QVERIFY(temporaryFile.open()); + QVERIFY2(temporaryFile.open(), qPrintable(temporaryFile.errorString())); QNonNativeFileDialog fd(0, "TestFileDialog", temporaryFile.fileName()); fd.setDirectory(tempPath); diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 0e7f760b4e..209048a853 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -173,7 +173,7 @@ void tst_QFileSystemModel::cleanup() void tst_QFileSystemModel::initTestCase() { - QVERIFY(m_tempDir.isValid()); + QVERIFY2(m_tempDir.isValid(), qPrintable(m_tempDir.errorString())); flatDirTestPath = m_tempDir.path(); } @@ -318,7 +318,7 @@ void tst_QFileSystemModel::readOnly() { QCOMPARE(model->isReadOnly(), true); QTemporaryFile file(flatDirTestPath + QStringLiteral("/XXXXXX.dat")); - file.open(); + QVERIFY2(file.open(), qPrintable(file.errorString())); QModelIndex root = model->setRootPath(flatDirTestPath); QTRY_VERIFY(model->rowCount(root) > 0); @@ -819,7 +819,7 @@ void tst_QFileSystemModel::setData() void tst_QFileSystemModel::sortPersistentIndex() { QTemporaryFile file(flatDirTestPath + QStringLiteral("/XXXXXX.dat")); - file.open(); + QVERIFY2(file.open(), qPrintable(file.errorString())); QModelIndex root = model->setRootPath(flatDirTestPath); QTRY_VERIFY(model->rowCount(root) > 0); From 0ea56cc075a9217314be69d1056d9a2abcd921c5 Mon Sep 17 00:00:00 2001 From: Pier Luigi Fiorini Date: Sat, 1 Aug 2015 07:00:22 +0200 Subject: [PATCH 102/240] eglfs_kms: Subpixel antialiasing type [ChangeLog][QPA][eglfs][kms] Provide subpixel antialiasing type. Change-Id: I1eed487cea675d988a128f63a9d5c2c0ddeae21f Reviewed-by: Laszlo Agocs --- .../eglfs_kms/qeglfskmsdevice.cpp | 1 + .../eglfs_kms/qeglfskmsscreen.cpp | 18 ++++++++++++++++++ .../eglfs_kms/qeglfskmsscreen.h | 3 +++ 3 files changed, 22 insertions(+) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp index f3df1f8445..7528d9fe2e 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp @@ -284,6 +284,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr false, drmModeGetCrtc(m_dri_fd, crtc_id), modes, + connector->subpixel, connectorProperty(connector, QByteArrayLiteral("DPMS")) }; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp index 227c8f9a62..d2a86c1e25 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp @@ -321,6 +321,24 @@ qreal QEglFSKmsScreen::refreshRate() const return refresh > 0 ? refresh : 60; } +QPlatformScreen::SubpixelAntialiasingType QEglFSKmsScreen::subpixelAntialiasingTypeHint() const +{ + switch (m_output.subpixel) { + default: + case DRM_MODE_SUBPIXEL_UNKNOWN: + case DRM_MODE_SUBPIXEL_NONE: + return Subpixel_None; + case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB: + return Subpixel_RGB; + case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR: + return Subpixel_BGR; + case DRM_MODE_SUBPIXEL_VERTICAL_RGB: + return Subpixel_VRGB; + case DRM_MODE_SUBPIXEL_VERTICAL_BGR: + return Subpixel_VBGR; + } +} + QPlatformScreen::PowerState QEglFSKmsScreen::powerState() const { return m_powerState; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h index 2ce8700478..7fd6ccaa31 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h @@ -60,6 +60,7 @@ struct QEglFSKmsOutput bool mode_set; drmModeCrtcPtr saved_crtc; QList modes; + int subpixel; drmModePropertyPtr dpms_prop; }; @@ -104,6 +105,8 @@ public: QEglFSKmsOutput &output() { return m_output; } void restoreMode(); + SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE; + QPlatformScreen::PowerState powerState() const Q_DECL_OVERRIDE; void setPowerState(QPlatformScreen::PowerState state) Q_DECL_OVERRIDE; From dceb424fe81ae29dde8e49a6dad300c547c8be26 Mon Sep 17 00:00:00 2001 From: Pier Luigi Fiorini Date: Sat, 11 Jul 2015 22:32:46 +0200 Subject: [PATCH 103/240] eglfs_kms: Skip disconnected outputs For some reason VMware reports 8 outputs, 7 of them are disconnected and so they cause several errors. Skip disconnected outputs to avoid those errors. Change-Id: I5f9fa2ef38b916af9f9ae8b50fce9fc40c18bff3 Reviewed-by: Laszlo Agocs --- .../eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp index 7528d9fe2e..40cd8b8763 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp @@ -191,6 +191,12 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr return Q_NULLPTR; } + // Skip disconnected output + if (configuration == OutputConfigPreferred && connector->connection == DRM_MODE_DISCONNECTED) { + qCDebug(qLcEglfsKmsDebug) << "Skipping disconnected output" << connectorName; + return Q_NULLPTR; + } + // Get the current mode on the current crtc drmModeModeInfo crtc_mode; memset(&crtc_mode, 0, sizeof crtc_mode); From ab6f941b50db3a99304dc4fff450de7dbca570bf Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 27 Sep 2015 12:38:35 -0700 Subject: [PATCH 104/240] QUrl::setPort: use the original port number in the error message Otherwise the error message will always say -1. Change-Id: I42e7ef1a481840699a8dffff1407eceec1906254 Reviewed-by: David Faure --- src/corelib/io/qurl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 89f5aad97f..9bf359222a 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -2411,8 +2411,8 @@ void QUrl::setPort(int port) d->clearError(); if (port < -1 || port > 65535) { - port = -1; d->setError(QUrlPrivate::InvalidPortError, QString::number(port), 0); + port = -1; } d->port = port; From b03d91e3f7d9b3ff96692d4e284b003ca5b90b82 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 27 Sep 2015 12:33:46 -0700 Subject: [PATCH 105/240] Remove unnecessary null-pointer check It was dereferenced 8 lines before and the pointer cannot have changed since. Found by Coverity, CID 11363. Change-Id: I42e7ef1a481840699a8dffff1407ecab4e4f5930 Reviewed-by: Richard J. Moore --- src/network/socket/qabstractsocket.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 75da64468f..02147d2054 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -2485,8 +2485,7 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) // Buffer what was not written yet char *ptr = d->writeBuffer.reserve(size - written); memcpy(ptr, data + written, size - written); - if (d->socketEngine) - d->socketEngine->setWriteNotificationEnabled(true); + d->socketEngine->setWriteNotificationEnabled(true); } return size; // size=actually written + what has been buffered } else if (!d->isBuffered && d->socketType != TcpSocket) { From 84a806589f93240ef39696729c6ce4c10bc4ab02 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 27 Sep 2015 11:52:35 -0700 Subject: [PATCH 106/240] Fix sign-extension If data[0] were > 128 (that is, if the full size, encoded in big endian were > 2 GB), the result of the OR chain would be a negative int (due to C integer promotion rules). We're shifting into the sign bit, which is either implementation-defined behavior or, worse, undefined behavior. This negative number is then sign-extended to ulong (64-bit on 64-bit platforms), which then becomes a big number. This code was probably written with only 32-bit in mind, where there would be no size extension (sign or otherwise). This isn't too bad because there's a size check for the max size of QByteArray a few lines below, but we can fix it, so let's do it. Found by Coverity, CID 22530. Change-Id: I42e7ef1a481840699a8dffff1407ea6c22e1a0ec Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qbytearray.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 5ed72fc341..a9f361c205 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -578,8 +578,8 @@ QByteArray qUncompress(const uchar* data, int nbytes) qWarning("qUncompress: Input data is corrupted"); return QByteArray(); } - ulong expectedSize = (data[0] << 24) | (data[1] << 16) | - (data[2] << 8) | (data[3] ); + ulong expectedSize = uint((data[0] << 24) | (data[1] << 16) | + (data[2] << 8) | (data[3] )); ulong len = qMax(expectedSize, 1ul); QScopedPointer d; From 9830857629e58dccefe6cf6be84925a01fff20ba Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 27 Sep 2015 12:19:58 -0700 Subject: [PATCH 107/240] QFSFileEngine: Remove unused member Change-Id: I42e7ef1a481840699a8dffff1407ebea9c7cb423 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qfsfileengine_p.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 8ba05fa8b9..0a7f551672 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -199,7 +199,6 @@ public: bool closeFileHandle; mutable uint is_sequential : 2; - mutable uint could_stat : 1; mutable uint tried_stat : 1; #if !defined(Q_OS_WINCE) mutable uint need_lstat : 1; From f8b317dd59f9c348970254bfbb29396fa9cdeedf Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Tue, 15 Sep 2015 10:34:19 +0300 Subject: [PATCH 108/240] winrt: Default show to showMaximized on Windows Phone. Status bar visibility can be controlled and window geometry can be adjusted accordingly. Default show to showMaximized instead of showFullScreen. This means that by default application starts status bar visible. [ChangeLog][winphone][Important Behavioral Changes] By default application starts status bar visible. Task-Id: QTBUG-48282 Change-Id: Ia60edd53ec2a7181aa97d21a825600b7c8cf87a7 Reviewed-by: Andrew Knight --- src/plugins/platforms/winrt/qwinrttheme.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrttheme.cpp b/src/plugins/platforms/winrt/qwinrttheme.cpp index a0fa2798a8..c32ec8a151 100644 --- a/src/plugins/platforms/winrt/qwinrttheme.cpp +++ b/src/plugins/platforms/winrt/qwinrttheme.cpp @@ -218,7 +218,7 @@ QVariant QWinRTTheme::styleHint(QPlatformIntegration::StyleHint hint) case QPlatformIntegration::KeyboardAutoRepeatRate: return defaultThemeHint(KeyboardAutoRepeatRate); case QPlatformIntegration::ShowIsFullScreen: - return true; + return false; case QPlatformIntegration::PasswordMaskDelay: return defaultThemeHint(PasswordMaskDelay); case QPlatformIntegration::FontSmoothingGamma: @@ -232,7 +232,7 @@ QVariant QWinRTTheme::styleHint(QPlatformIntegration::StyleHint hint) case QPlatformIntegration::SetFocusOnTouchRelease: return false; case QPlatformIntegration::ShowIsMaximized: - return false; + return true; case QPlatformIntegration::MousePressAndHoldInterval: return defaultThemeHint(MousePressAndHoldInterval); default: From 9ef87603553c59f8666e868a69b75bf240b9cc12 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 28 Sep 2015 16:25:02 +0200 Subject: [PATCH 109/240] QWindowsPipeWriter: clean up OVERLAPPED resource handling Use RAII to ensure that every code path cleans up the event handle, and re-initialize the whole OVERLAPPED object, not just the two offset members. Change-Id: If7e68ec6e61b7bb04df0d06734c04589f6822c4a Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qwindowspipewriter.cpp | 39 +++++++++++++++++++++------ 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index 57053f129a..e75712ba80 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -90,11 +90,38 @@ qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen) return maxlen; } +class QPipeWriterOverlapped +{ +public: + QPipeWriterOverlapped() + { + overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + } + + ~QPipeWriterOverlapped() + { + CloseHandle(overlapped.hEvent); + } + + void prepare() + { + const HANDLE hEvent = overlapped.hEvent; + ZeroMemory(&overlapped, sizeof overlapped); + overlapped.hEvent = hEvent; + } + + OVERLAPPED *operator&() + { + return &overlapped; + } + +private: + OVERLAPPED overlapped; +}; + void QWindowsPipeWriter::run() { - OVERLAPPED overl; - memset(&overl, 0, sizeof overl); - overl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + QPipeWriterOverlapped overl; forever { lock.lock(); while(data.isEmpty() && (!quitNow)) { @@ -115,8 +142,7 @@ void QWindowsPipeWriter::run() const char *ptrData = copy.data(); qint64 maxlen = copy.size(); qint64 totalWritten = 0; - overl.Offset = 0; - overl.OffsetHigh = 0; + overl.prepare(); while ((!quitNow) && totalWritten < maxlen) { DWORD written = 0; if (!WriteFile(writePipe, ptrData + totalWritten, @@ -130,11 +156,9 @@ void QWindowsPipeWriter::run() #ifndef Q_OS_WINCE if (GetLastError() == ERROR_IO_PENDING) { if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) { - CloseHandle(overl.hEvent); return; } } else { - CloseHandle(overl.hEvent); return; } #else @@ -154,7 +178,6 @@ void QWindowsPipeWriter::run() emit bytesWritten(totalWritten); emit canWrite(); } - CloseHandle(overl.hEvent); } #endif //QT_NO_THREAD From 7fe5f82e48c023edff7c1c60a14f3958ffda8ad2 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 28 Sep 2015 16:27:51 +0200 Subject: [PATCH 110/240] clean up QWindowsPipeWriter I/O error handling Exit early, and add warning messages for (unlikely) error cases. Change-Id: I7130b2e298f3a644a9d0e96a3a1860350e11adff Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qwindowspipewriter.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index e75712ba80..fd14523d45 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -147,18 +147,19 @@ void QWindowsPipeWriter::run() DWORD written = 0; if (!WriteFile(writePipe, ptrData + totalWritten, maxlen - totalWritten, &written, &overl)) { - - if (GetLastError() == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) { + const DWORD writeError = GetLastError(); + if (writeError == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) { // give the os a rest msleep(100); continue; } #ifndef Q_OS_WINCE - if (GetLastError() == ERROR_IO_PENDING) { - if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) { - return; - } - } else { + if (writeError != ERROR_IO_PENDING) { + qErrnoWarning(writeError, "QWindowsPipeWriter: async WriteFile failed."); + return; + } + if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) { + qErrnoWarning(GetLastError(), "QWindowsPipeWriter: GetOverlappedResult failed."); return; } #else From b7f4346c4ff2b2bc579818d33854fad9941510de Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 29 Sep 2015 07:20:45 +0000 Subject: [PATCH 111/240] Windows: Change the mocinclude extension to .opt When cleaning in Visual Studio then it will remove all instances of tmp files which meant it would remove the mocinclude.tmp as well incorrectly. Therefore the extension of the mocinclude file needs to be changed to .opt so that it is left untouched by Visual Studio. Change-Id: Iebc055f33f9dc87a4fa42ae87b253f6739903e8f Reviewed-by: Oswald Buddenhagen --- mkspecs/features/moc.prf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf index c0b5682446..8e8deec63c 100644 --- a/mkspecs/features/moc.prf +++ b/mkspecs/features/moc.prf @@ -16,7 +16,7 @@ MOC_INCLUDEPATH = $$QMAKESPEC $$_PRO_FILE_PWD_ $$MOC_INCLUDEPATH $$QMAKE_DEFAULT # has too many includes. We do this to overcome a command-line limit on Win < XP WIN_INCLUDETEMP= win32:count(MOC_INCLUDEPATH, 40, >) { - WIN_INCLUDETEMP = $$MOC_DIR/mocinclude.tmp + WIN_INCLUDETEMP = $$MOC_DIR/mocinclude.opt WIN_INCLUDETEMP_CONT = for (inc, MOC_INCLUDEPATH): \ From 53755617e4bf688b69fa700a0e9bf9ac72876d22 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 29 Sep 2015 10:35:44 +0200 Subject: [PATCH 112/240] QTestLib: Add MSVC 2015 to blacklist. Task-number: QTBUG-48455 Change-Id: I8ea322f393a1f8d44183892f20e5461d571bc4c0 Reviewed-by: Simon Hausmann --- src/testlib/qtestblacklist.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index eb7abdad46..a30936a23b 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -109,7 +109,9 @@ static QSet keywords() #ifdef Q_CC_MSVC << "msvc" #ifdef _MSC_VER - #if _MSC_VER == 1800 + #if _MSC_VER == 1900 + << "msvc-2015" + #elif _MSC_VER == 1800 << "msvc-2013" #elif _MSC_VER == 1700 << "msvc-2012" From 7943d4f77c721da17b6be76cf1045d34654a8cc5 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 28 Sep 2015 22:47:00 +0300 Subject: [PATCH 113/240] ANGLE: Fix Windows Store D3D Trim and Level 9 requirements Due to additional validation not covered in previous patches, the Windows Store certification compatibility had regressed. These changes ensure that the required D3D behaviors are met. Change-Id: I0a74f0d2fecaa87d4a9409da3a7a194254609759 Task-number: QTBUG-38481 Reviewed-by: Samuel Nevala Reviewed-by: Maurice Kalinowski Reviewed-by: Jani Heikkinen --- .../renderer/d3d/d3d11/Renderer11.cpp | 19 +++++- .../src/libGLESv2/entry_points_egl_ext.cpp | 2 + ...s-Store-D3D-Trim-and-Level-9-require.patch | 63 +++++++++++++++++++ src/plugins/platforms/winrt/qwinrtscreen.cpp | 2 +- 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index 5291a3a086..ea5953fee8 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -293,10 +293,25 @@ Renderer11::Renderer11(egl::Display *display) #if defined(ANGLE_ENABLE_WINDOWS_STORE) if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) #else - if (requestedMajorVersion == 9 && requestedMinorVersion == 3) + if (requestedMajorVersion == 9) #endif { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + switch (requestedMinorVersion) { +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + case EGL_DONT_CARE: + case 1: + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); + // fall through + case 2: + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); + // fall through +#endif + case 3: + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + break; + default: + break; + } } EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp index 62f3ca1207..02b663192d 100644 --- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp @@ -49,6 +49,8 @@ EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surfa // validate the attribute parameter switch (attribute) { + case EGL_DEVICE_EXT: + break; case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: if (!display->getExtensions().surfaceD3DTexture2DShareHandle) { diff --git a/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch b/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch new file mode 100644 index 0000000000..e9677fab68 --- /dev/null +++ b/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch @@ -0,0 +1,63 @@ +From f6d73de2a8a36becb8a2e0cce84475e91f1f63b4 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Mon, 28 Sep 2015 22:43:13 +0300 +Subject: [PATCH] ANGLE: Fix Windows Store D3D Trim and Level 9 requirements + +Due to additional validation not covered in previous patches, the Windows +Store certification compatibility had regressed. These changes ensure that +the required D3D behaviors are met. + +Change-Id: I0a74f0d2fecaa87d4a9409da3a7a194254609759 +--- + .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 19 +++++++++++++++++-- + .../angle/src/libGLESv2/entry_points_egl_ext.cpp | 2 ++ + 2 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +index 5291a3a..ea5953f 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +@@ -293,10 +293,25 @@ Renderer11::Renderer11(egl::Display *display) + #if defined(ANGLE_ENABLE_WINDOWS_STORE) + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) + #else +- if (requestedMajorVersion == 9 && requestedMinorVersion == 3) ++ if (requestedMajorVersion == 9) + #endif + { +- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); ++ switch (requestedMinorVersion) { ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) ++ case EGL_DONT_CARE: ++ case 1: ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); ++ // fall through ++ case 2: ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); ++ // fall through ++#endif ++ case 3: ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); ++ break; ++ default: ++ break; ++ } + } + + EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, +diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp +index 62f3ca1..02b6631 100644 +--- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp +@@ -49,6 +49,8 @@ EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surfa + // validate the attribute parameter + switch (attribute) + { ++ case EGL_DEVICE_EXT: ++ break; + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + if (!display->getExtensions().surfaceD3DTexture2DShareHandle) + { +-- +2.5.1.windows.1 + diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 1d36bb31f6..8962332208 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -1115,7 +1115,7 @@ HRESULT QWinRTScreen::onSuspended(IInspectable *, ISuspendingEventArgs *) #ifndef Q_OS_WINPHONE Q_D(QWinRTScreen); ComPtr d3dDevice; - const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, EGL_NO_SURFACE, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf()); + const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, d->eglSurface, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf()); if (ok && d3dDevice) { ComPtr dxgiDevice; if (SUCCEEDED(d3dDevice.As(&dxgiDevice))) From a5f470240f31d35e694a40fe837fc4f49bc32072 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 28 Sep 2015 16:41:34 +0200 Subject: [PATCH 114/240] qprintengine_win.cpp: Check access to members of DOCINFO in warning. DOCINFO::lpszOutput can be 0. Task-number: QTBUG-48203 Change-Id: Ia3940b5b3200143d8d50caa8f4f44c4b22bfff75 Reviewed-by: Andy Shaw --- src/printsupport/kernel/qprintengine_win.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index b377401ed9..a4209d833a 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -93,9 +93,10 @@ static QByteArray msgBeginFailed(const char *function, const DOCINFO &d) { QString result; QTextStream str(&result); - str << "QWin32PrintEngine::begin: " << function << " failed, document \"" - << QString::fromWCharArray(d.lpszDocName) << '"'; - if (d.lpszOutput[0]) + str << "QWin32PrintEngine::begin: " << function << " failed"; + if (d.lpszDocName && d.lpszDocName[0]) + str << ", document \"" << QString::fromWCharArray(d.lpszDocName) << '"'; + if (d.lpszOutput && d.lpszOutput[0]) str << ", file \"" << QString::fromWCharArray(d.lpszOutput) << '"'; return result.toLocal8Bit(); } From 78f9b16d60357b544353cb7d525ffdf56ab72680 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 29 Sep 2015 17:07:47 +0200 Subject: [PATCH 115/240] Skip tst_QNumeric::addOverflow() for MSVC2015. The code still produces Internal Compiler Errors in release mode. Task-number: QTBUG-46344 Change-Id: I86d3608b13a197a0b65b83829d1512203e1578f8 Reviewed-by: Frederik Gladhorn --- tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp index 59a536ed25..6be8ff81cf 100644 --- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp +++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp @@ -225,8 +225,8 @@ void tst_QNumeric::addOverflow_data() // to QTest::toString and QTest::qCompare will remain. template static void addOverflow_template() { -#if defined(Q_CC_MSVC) && Q_CC_MSVC < 1900 - QSKIP("Test disabled, this test generates an Internal Compiler Error compiling"); +#if defined(Q_CC_MSVC) && Q_CC_MSVC < 2000 + QSKIP("Test disabled, this test generates an Internal Compiler Error compiling in release mode"); #else const Int max = std::numeric_limits::max(); Int r; From a2995c180b6b21031dc10d39bc99dbdb3d6212d2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 25 Sep 2015 13:52:31 +0200 Subject: [PATCH 116/240] tst_qprocess: Improve handling of helpers. Verify exit status and code where applicable. Avoid unnecessary data conversions in fileWriterProcess. Improve error handling in helper processes. Task-number: QTBUG-47370 Task-number: QTBUG-48455 Change-Id: Ib5c4f546027131db02caaa05154a5880edac5cf7 Reviewed-by: Thiago Macieira --- .../io/qprocess/fileWriterProcess/main.cpp | 14 ++- .../corelib/io/qprocess/testDetached/main.cpp | 3 +- .../io/qprocess/testExitCodes/main.cpp | 4 +- .../auto/corelib/io/qprocess/tst_qprocess.cpp | 95 +++++++++++++++++-- 4 files changed, 99 insertions(+), 17 deletions(-) diff --git a/tests/auto/corelib/io/qprocess/fileWriterProcess/main.cpp b/tests/auto/corelib/io/qprocess/fileWriterProcess/main.cpp index 411c7e334b..25cb66f9d2 100644 --- a/tests/auto/corelib/io/qprocess/fileWriterProcess/main.cpp +++ b/tests/auto/corelib/io/qprocess/fileWriterProcess/main.cpp @@ -33,20 +33,26 @@ #include #include +#include + int main(int argc, char **argv) { QCoreApplication ca(argc, argv); QFile f; f.open(stdin, QIODevice::ReadOnly); - QString input; + QByteArray input; char buf[1024]; qint64 len; while ((len = f.read(buf, 1024)) > 0) - input += QByteArray(buf, len); + input.append(buf, len); f.close(); QFile f2("fileWriterProcess.txt"); - f2.open(QIODevice::WriteOnly | QIODevice::Truncate); - f2.write(input.toLatin1()); + if (!f2.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + fprintf(stderr, "Cannot open %s for writing: %s\n", + qPrintable(f2.fileName()), qPrintable(f2.errorString())); + return 1; + } + f2.write(input); f2.close(); return 0; } diff --git a/tests/auto/corelib/io/qprocess/testDetached/main.cpp b/tests/auto/corelib/io/qprocess/testDetached/main.cpp index bbcc7033c7..760306ea17 100644 --- a/tests/auto/corelib/io/qprocess/testDetached/main.cpp +++ b/tests/auto/corelib/io/qprocess/testDetached/main.cpp @@ -57,7 +57,8 @@ int main(int argc, char **argv) QFile f(args.at(1)); if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { - fprintf(stderr, "Cannot open %s for writing", qPrintable(f.fileName())); + fprintf(stderr, "Cannot open %s for writing: %s\n", + qPrintable(f.fileName()), qPrintable(f.errorString())); return 1; } diff --git a/tests/auto/corelib/io/qprocess/testExitCodes/main.cpp b/tests/auto/corelib/io/qprocess/testExitCodes/main.cpp index c92d7f515f..c3cf9f56c7 100644 --- a/tests/auto/corelib/io/qprocess/testExitCodes/main.cpp +++ b/tests/auto/corelib/io/qprocess/testExitCodes/main.cpp @@ -33,8 +33,8 @@ #include -int main(int /* argc */, char **argv) +int main(int argc, char **argv) { - return atoi(argv[1]); + return argc >= 2 ? atoi(argv[1]) : -1; } diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 2b8f2ae3c7..45d6cf3dcd 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -333,9 +333,8 @@ void tst_QProcess::execute() void tst_QProcess::startDetached() { - QProcess proc; - QVERIFY(proc.startDetached("testProcessNormal/testProcessNormal", - QStringList() << "arg1" << "arg2")); + QVERIFY(QProcess::startDetached("testProcessNormal/testProcessNormal", + QStringList() << "arg1" << "arg2")); #ifdef QPROCESS_USE_SPAWN QEXPECT_FAIL("", "QProcess cannot detect failure to start when using posix_spawn()", Continue); #endif @@ -479,6 +478,8 @@ void tst_QProcess::echoTest() process.write("", 1); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } #endif @@ -530,6 +531,8 @@ void tst_QProcess::echoTest2() process.write("", 1); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } #endif @@ -546,6 +549,8 @@ void tst_QProcess::echoTestGui() process.write("q"); QVERIFY(process.waitForFinished(50000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); QCOMPARE(process.readAllStandardOutput(), QByteArray("Hello")); QCOMPARE(process.readAllStandardError(), QByteArray("Hello")); @@ -584,6 +589,8 @@ void tst_QProcess::batFiles() proc.start(batFile, QStringList()); QVERIFY(proc.waitForFinished(5000)); + QCOMPARE(proc.exitStatus(), QProcess::NormalExit); + QCOMPARE(proc.exitCode(), 0); QVERIFY(proc.bytesAvailable() > 0); @@ -650,6 +657,8 @@ void tst_QProcess::loopBackTest() process.write("", 1); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } #endif @@ -730,6 +739,8 @@ void tst_QProcess::deadWhileReading() QCOMPARE(output.count("\n"), 10*1024); process.waitForFinished(); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } #endif @@ -754,6 +765,8 @@ void tst_QProcess::restartProcessDeadlock() QCOMPARE(process.write("", 1), qlonglong(1)); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } void tst_QProcess::restartProcess() @@ -788,6 +801,8 @@ void tst_QProcess::closeWriteChannel() if (more.state() == QProcess::Running) more.write("q"); QVERIFY(more.waitForFinished(5000)); + QCOMPARE(more.exitStatus(), QProcess::NormalExit); + QCOMPARE(more.exitCode(), 0); } #endif @@ -818,6 +833,8 @@ void tst_QProcess::closeReadChannel() proc.write("", 1); QVERIFY(proc.waitForFinished(5000)); + QCOMPARE(proc.exitStatus(), QProcess::NormalExit); + QCOMPARE(proc.exitCode(), 0); } } #endif @@ -898,6 +915,8 @@ void tst_QProcess::emitReadyReadOnlyWhenNewDataArrives() proc.write("", 1); QVERIFY(proc.waitForFinished(5000)); + QCOMPARE(proc.exitStatus(), QProcess::NormalExit); + QCOMPARE(proc.exitCode(), 0); } #endif @@ -1078,6 +1097,8 @@ void tst_QProcess::mergedChannels() process.closeWriteChannel(); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } #endif @@ -1116,6 +1137,8 @@ void tst_QProcess::forwardedChannels() QCOMPARE(process.write("input"), 5); process.closeWriteChannel(); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); const char *err; switch (process.exitCode()) { case 0: err = "ok"; break; @@ -1155,6 +1178,8 @@ void tst_QProcess::atEnd() process.write("", 1); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } #endif @@ -1269,6 +1294,8 @@ void tst_QProcess::waitForReadyReadInAReadyReadSlot() process.disconnect(); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); QVERIFY(process.bytesAvailable() > bytesAvailable); } #endif @@ -1307,6 +1334,8 @@ void tst_QProcess::waitForBytesWrittenInABytesWrittenSlot() process.write("", 1); process.disconnect(); QVERIFY(process.waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } #endif @@ -1401,6 +1430,8 @@ void tst_QProcess::spaceArgsTest() errorMessage = startFailMessage(program, process); QVERIFY2(started, errorMessage.constData()); QVERIFY(process.waitForFinished(timeOutMS)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); #if !defined(Q_OS_WINCE) QStringList actual = QString::fromLatin1(process.readAll()).split("|"); @@ -1460,6 +1491,8 @@ void tst_QProcess::nativeArguments() QVERIFY(proc.waitForStarted(10000)); QVERIFY(proc.waitForFinished(10000)); #endif + QCOMPARE(proc.exitStatus(), QProcess::NormalExit); + QCOMPARE(proc.exitCode(), 0); #if defined(Q_OS_WINCE) // WinCE test outputs to a file, so check that @@ -1696,6 +1729,8 @@ void tst_QProcess::removeFileWhileProcessIsRunning() process.write("", 1); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } #endif #ifndef Q_OS_WINCE @@ -1840,6 +1875,8 @@ void tst_QProcess::spaceInName() QVERIFY(process.waitForStarted()); process.write("", 1); QVERIFY(process.waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } #endif @@ -1921,6 +1958,8 @@ void tst_QProcess::setStandardInputFile() process.start("testProcessEcho/testProcessEcho"); QPROCESS_VERIFY(process, waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); QByteArray all = process.readAll(); QCOMPARE(all.size(), int(sizeof data) - 1); // testProcessEcho drops the ending \0 QVERIFY(all == data); @@ -1993,6 +2032,8 @@ void tst_QProcess::setStandardOutputFile() process.start("testProcessEcho2/testProcessEcho2"); process.write(testdata, sizeof testdata); QPROCESS_VERIFY(process,waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); // open the file again and verify the data QVERIFY(file.open(QIODevice::ReadOnly)); @@ -2022,6 +2063,8 @@ void tst_QProcess::setStandardOutputFileNullDevice() process.start("testProcessEcho2/testProcessEcho2"); process.write(testdata, sizeof testdata); QPROCESS_VERIFY(process,waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); QCOMPARE(process.bytesAvailable(), Q_INT64_C(0)); QVERIFY(!QFileInfo(QProcess::nullDevice()).isFile()); @@ -2038,6 +2081,8 @@ void tst_QProcess::setStandardOutputFileAndWaitForBytesWritten() process.write(testdata, sizeof testdata); process.waitForBytesWritten(); QPROCESS_VERIFY(process, waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); // open the file again and verify the data QVERIFY(file.open(QIODevice::ReadOnly)); @@ -2078,7 +2123,11 @@ void tst_QProcess::setStandardOutputProcess() source.waitForBytesWritten(); source.closeWriteChannel(); QPROCESS_VERIFY(source, waitForFinished()); + QCOMPARE(source.exitStatus(), QProcess::NormalExit); + QCOMPARE(source.exitCode(), 0); QPROCESS_VERIFY(sink, waitForFinished()); + QCOMPARE(sink.exitStatus(), QProcess::NormalExit); + QCOMPARE(sink.exitCode(), 0); QByteArray all = sink.readAll(); if (!merged) @@ -2092,25 +2141,34 @@ void tst_QProcess::setStandardOutputProcess() // Reading and writing to a process is not supported on Qt/CE void tst_QProcess::fileWriterProcess() { - QString stdinStr; - for (int i = 0; i < 5000; ++i) - stdinStr += QString::fromLatin1("%1 -- testing testing 1 2 3\n").arg(i); + const QByteArray line = QByteArrayLiteral(" -- testing testing 1 2 3\n"); + QByteArray stdinStr; + stdinStr.reserve(5000 * (4 + line.size()) + 1); + for (int i = 0; i < 5000; ++i) { + stdinStr += QByteArray::number(i); + stdinStr += line; + } QTime stopWatch; stopWatch.start(); + const QString fileName = QLatin1String("fileWriterProcess.txt"); + do { - QFile::remove("fileWriterProcess.txt"); + if (QFile::exists(fileName)) + QVERIFY(QFile::remove(fileName)); QProcess process; process.start("fileWriterProcess/fileWriterProcess", QIODevice::ReadWrite | QIODevice::Text); - process.write(stdinStr.toLatin1()); + process.write(stdinStr); process.closeWriteChannel(); while (process.bytesToWrite()) { QVERIFY(stopWatch.elapsed() < 3500); QVERIFY(process.waitForBytesWritten(2000)); } QVERIFY(process.waitForFinished()); - QCOMPARE(QFile("fileWriterProcess.txt").size(), qint64(stdinStr.size())); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); + QCOMPARE(QFile(fileName).size(), qint64(stdinStr.size())); } while (stopWatch.elapsed() < 3000); } #endif @@ -2170,6 +2228,8 @@ void tst_QProcess::switchReadChannels() process.write(data); process.closeWriteChannel(); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); for (int i = 0; i < 4; ++i) { process.setReadChannel(QProcess::StandardOutput); @@ -2199,6 +2259,8 @@ void tst_QProcess::discardUnwantedOutput() process.write("Hello, World"); process.closeWriteChannel(); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); process.setReadChannel(QProcess::StandardOutput); QCOMPARE(process.bytesAvailable(), Q_INT64_C(0)); @@ -2220,6 +2282,8 @@ void tst_QProcess::setWorkingDirectory() process.start(QFileInfo("testSetWorkingDirectory/testSetWorkingDirectory").absoluteFilePath()); QVERIFY2(process.waitForFinished(), process.errorString().toLocal8Bit()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); QByteArray workingDir = process.readAllStandardOutput(); QCOMPARE(QDir("test").canonicalPath(), QDir(workingDir.constData()).canonicalPath()); @@ -2254,8 +2318,11 @@ void tst_QProcess::startFinishStartFinish() QCOMPARE(QString::fromLatin1(process.readLine().trimmed()), QString("0 -this is a number")); #endif - if (process.state() != QProcess::NotRunning) + if (process.state() != QProcess::NotRunning) { QVERIFY(process.waitForFinished(10000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); + } } } @@ -2308,6 +2375,8 @@ void tst_QProcess::onlyOneStartedSignal() process.start("testProcessNormal/testProcessNormal"); QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); QCOMPARE(spyStarted.count(), 1); QCOMPARE(spyFinished.count(), 1); } @@ -2342,6 +2411,8 @@ void tst_QProcess::finishProcessBeforeReadingDone() QRegExp(QStringLiteral("[\r\n]")), QString::SkipEmptyParts); QVERIFY(!lines.isEmpty()); QCOMPARE(lines.last(), QStringLiteral("10239 -this is a number")); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); } //----------------------------------------------------------------------------- @@ -2358,14 +2429,17 @@ void tst_QProcess::startStopStartStop() QProcess process; process.start("testProcessNormal/testProcessNormal"); QVERIFY(process.waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); process.start("testExitCodes/testExitCodes", QStringList() << "1"); QVERIFY(process.waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 1); process.start("testProcessNormal/testProcessNormal"); QVERIFY(process.waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); } @@ -2437,6 +2511,7 @@ void tst_QProcess::startStopStartStopBuffers() process.write("line3\n"); process.closeWriteChannel(); QVERIFY(process.waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); if (channelMode2 == QProcess::MergedChannels) { From a4df9739a2898f496a1c4ccf6b44d81a7090fa33 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 29 Sep 2015 15:08:01 +0200 Subject: [PATCH 117/240] uic/class_lib_map.h: Fix include path of QValidator-derived classes. Task-number: QTBUG-48492 Change-Id: I1b43bd955cdb36c564483dfa3d9b416885ada983 Reviewed-by: Joerg Bornemann --- src/tools/uic/qclass_lib_map.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/uic/qclass_lib_map.h b/src/tools/uic/qclass_lib_map.h index 940017d063..930a648d57 100644 --- a/src/tools/uic/qclass_lib_map.h +++ b/src/tools/uic/qclass_lib_map.h @@ -969,10 +969,10 @@ QT_CLASS_LIB(QTextEdit, QtWidgets, qtextedit.h) QT_CLASS_LIB(QToolBar, QtWidgets, qtoolbar.h) QT_CLASS_LIB(QToolBox, QtWidgets, qtoolbox.h) QT_CLASS_LIB(QToolButton, QtWidgets, qtoolbutton.h) -QT_CLASS_LIB(QValidator, QtWidgets, qvalidator.h) -QT_CLASS_LIB(QIntValidator, QtWidgets, qvalidator.h) -QT_CLASS_LIB(QDoubleValidator, QtWidgets, qvalidator.h) -QT_CLASS_LIB(QRegExpValidator, QtWidgets, qvalidator.h) +QT_CLASS_LIB(QValidator, QtGui, qvalidator.h) +QT_CLASS_LIB(QIntValidator, QtGui, qvalidator.h) +QT_CLASS_LIB(QDoubleValidator, QtGui, qvalidator.h) +QT_CLASS_LIB(QRegExpValidator, QtGui, qvalidator.h) QT_CLASS_LIB(QScriptEngineDebugger, QtScriptTools, qscriptenginedebugger.h) QT_CLASS_LIB(QDesignerComponents, QtDesigner, qdesigner_components.h) QT_CLASS_LIB(QExtensionFactory, QtDesigner, default_extensionfactory.h) From 0cd7b64a61dc1f3883a210ee595e00354955d1f9 Mon Sep 17 00:00:00 2001 From: Vyacheslav Koscheev Date: Tue, 29 Sep 2015 01:07:06 +0600 Subject: [PATCH 118/240] qwindowsmime compilation fix Change-Id: I6ca030ed1333f62da6270c1295a4f489f088334d Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsmime.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 375a7f11db..52a4ca26dc 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -1579,7 +1579,11 @@ QVector QWindowsMimeConverter::allFormatsForMime(const QMimeData *mim void QWindowsMimeConverter::ensureInitialized() const { if (m_mimes.isEmpty()) { - m_mimes << new QWindowsMimeImage << new QLastResortMimes + m_mimes +#ifndef QT_NO_IMAGEFORMAT_BMP + << new QWindowsMimeImage +#endif //QT_NO_IMAGEFORMAT_BMP + << new QLastResortMimes << new QWindowsMimeText << new QWindowsMimeURI << new QWindowsMimeHtml << new QBuiltInMimes; m_internalMimeCount = m_mimes.size(); From c1e95c62198f3c6bc7b3818572e61e7202ee27e0 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 28 Sep 2015 22:53:55 +0300 Subject: [PATCH 119/240] Remove unused font deployment feature This is a leftover from the unsupported Windows Phone 8.0 mkspec. Change-Id: Ibcf11e131a3cb098960410dbd683eb5950b0c5ad Reviewed-by: Maurice Kalinowski Reviewed-by: Oliver Wolff --- mkspecs/features/winrt/font_deployment.prf | 62 ---------------------- 1 file changed, 62 deletions(-) delete mode 100644 mkspecs/features/winrt/font_deployment.prf diff --git a/mkspecs/features/winrt/font_deployment.prf b/mkspecs/features/winrt/font_deployment.prf deleted file mode 100644 index c767d5bc1a..0000000000 --- a/mkspecs/features/winrt/font_deployment.prf +++ /dev/null @@ -1,62 +0,0 @@ -# Provide default fonts for windows phone -# The DEFAULTFONTS variable indicates, whether the default set of fonts is -# used for deployment. The check below won't work after the fonts are added -# so this helper variable is added and used for the user warning check later. -!defined(FONTS, var):winphone { - FONTS = \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSans.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSans-Bold.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSans-BoldOblique.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSansMono.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSansMono-Bold.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSansMono-BoldOblique.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSansMono-Oblique.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSans-Oblique.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSerif.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSerif-Bold.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSerif-BoldOblique.ttf \ - $$[QT_HOST_PREFIX/src]/lib/fonts/DejaVuSerif-Oblique.ttf - DEFAULTFONTS = -} - -if(build_pass:equals(TEMPLATE, "app"))| \ -if(!build_pass:equals(TEMPLATE, "vcapp")) { - defined(DEFAULTFONTS, var) { - message(Default fonts will automatically be deployed with your application. \ - To avoid automatic deployment unset the \"FONTS\" variable (\"FONTS =\") in your .pro file. \ - You can also customize which fonts are deployed by setting the \"FONTS\" variable.) - } - - contains(TEMPLATE, "vc.*") { - BUILD_DIR = $$OUT_PWD - } else { - load(resolve_target) - BUILD_DIR = $$dirname(QMAKE_RESOLVED_TARGET) - } - - for (FONT, FONTS) { - font_$${FONT}.input = $$FONT - font_$${FONT}.output = $$BUILD_DIR/fonts/$$basename(FONT) - font_$${FONT}.CONFIG = verbatim - QMAKE_SUBSTITUTES += font_$${FONT} - } - - !isEmpty(FONTS):equals(TEMPLATE, "app") { - fonts.files = $$BUILD_DIR/fonts/* - isEmpty(target.path) { - fonts.path = $$OUT_PWD/fonts - } else { - fonts.path = $$target.path/fonts - } - - INSTALLS += fonts - } -} - -!isEmpty(FONTS):winphone:equals(TEMPLATE, "vcapp"):build_pass { - for (FONT, FONTS) { - fonts.files += $$OUT_PWD/fonts/$$basename(FONT) - } - fonts.path = fonts - DEPLOYMENT += fonts -} From 813f468a14fb84af43c1f8fc0a1430277358eba2 Mon Sep 17 00:00:00 2001 From: Dave Flogeras Date: Tue, 29 Sep 2015 08:52:31 -0300 Subject: [PATCH 120/240] Fix for platform socklen_t on other C libraries than glibc. Rather than treating >=glibc-2 specially, we treat Reviewed-by: Thiago Macieira --- mkspecs/linux-g++/qplatformdefs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mkspecs/linux-g++/qplatformdefs.h b/mkspecs/linux-g++/qplatformdefs.h index 5c18632e5d..95a57585d9 100644 --- a/mkspecs/linux-g++/qplatformdefs.h +++ b/mkspecs/linux-g++/qplatformdefs.h @@ -78,10 +78,10 @@ #undef QT_SOCKLEN_T -#if defined(__GLIBC__) && (__GLIBC__ >= 2) -#define QT_SOCKLEN_T socklen_t -#else +#if defined(__GLIBC__) && (__GLIBC__ < 2) #define QT_SOCKLEN_T int +#else +#define QT_SOCKLEN_T socklen_t #endif #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) From ac0184d6085d9e4f7f59352e563055311f4d8792 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 21 Sep 2015 15:39:16 +0300 Subject: [PATCH 121/240] Add qt_safe_ftok wrapper for ftok The ftok function unfortunately can return duplicate keys even for different files if the same project id is used. This is discussed e.g. in Stevens' "Advanced Programming in the UNIX Environment". We want the key to be predictable so we cannot just pass a random number as the project id. To reduce the propability of key collisions we hash the file name with the project number as seed for a predictable value. This is the same approach taken e.g. by Apache, but the real fix is to move away from System V IPC completely once this is feasible on our supported platforms. Task-number: QTBUG-48375 Change-Id: If1a57f215f7ddd147aa38919907cfb83db07aea0 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcore_unix_p.h | 14 ++++++++++++++ src/corelib/kernel/qsharedmemory_systemv.cpp | 2 +- src/corelib/kernel/qsystemsemaphore_systemv.cpp | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index c744873fce..f80dcb5a50 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -47,6 +47,7 @@ #include "qplatformdefs.h" #include "qatomic.h" +#include "qhash.h" #ifndef Q_OS_UNIX # error "qcore_unix_p.h included on a non-Unix system" @@ -322,6 +323,19 @@ union qt_semun { unsigned short *array; /* array for GETALL, SETALL */ }; +#ifndef QT_POSIX_IPC +#ifndef QT_NO_SHAREDMEMORY +#ifndef Q_OS_ANDROID +static inline key_t qt_safe_ftok(const QByteArray &filename, int proj_id) +{ + // Unfortunately ftok can return colliding keys even for different files. + // Try to add some more entropy via qHash. + return ::ftok(filename.constData(), qHash(filename, proj_id)); +} +#endif // !Q_OS_ANDROID +#endif // !QT_NO_SHAREDMEMORY +#endif // !QT_POSIX_IPC + QT_END_NAMESPACE #endif diff --git a/src/corelib/kernel/qsharedmemory_systemv.cpp b/src/corelib/kernel/qsharedmemory_systemv.cpp index 29fee12c0b..0d2eea49e9 100644 --- a/src/corelib/kernel/qsharedmemory_systemv.cpp +++ b/src/corelib/kernel/qsharedmemory_systemv.cpp @@ -82,7 +82,7 @@ key_t QSharedMemoryPrivate::handle() return 0; } - unix_key = ftok(QFile::encodeName(nativeKey).constData(), 'Q'); + unix_key = qt_safe_ftok(QFile::encodeName(nativeKey), 'Q'); if (-1 == unix_key) { errorString = QSharedMemory::tr("%1: ftok failed").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::KeyError; diff --git a/src/corelib/kernel/qsystemsemaphore_systemv.cpp b/src/corelib/kernel/qsystemsemaphore_systemv.cpp index 32a4bdef51..490de5f9ee 100644 --- a/src/corelib/kernel/qsystemsemaphore_systemv.cpp +++ b/src/corelib/kernel/qsystemsemaphore_systemv.cpp @@ -85,7 +85,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) createdFile = (1 == built); // Get the unix key for the created file - unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q'); + unix_key = qt_safe_ftok(QFile::encodeName(fileName), 'Q'); if (-1 == unix_key) { errorString = QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:")); error = QSystemSemaphore::KeyError; From 0f48a0ed0454ad1fd4145c376a3e92991ee1b31e Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Mon, 28 Sep 2015 10:40:22 +0300 Subject: [PATCH 122/240] Clean unused parameter warning from QItemSelectionModel test Change-Id: I6bd40e8de7b44630ef5c7475b8159ab9a0361cb9 Reviewed-by: Friedemann Kleint --- .../itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp index 888ffba282..38e2900c25 100644 --- a/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp +++ b/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp @@ -2808,7 +2808,7 @@ public: QModelIndex tl; QModelIndex br; public slots: - void changed(const QItemSelection &selected, const QItemSelection &deselected) + void changed(const QItemSelection &, const QItemSelection &deselected) { tl = deselected.first().topLeft(); br = deselected.first().bottomRight(); From 0ebebeb983d381010fae710aee60d8550d9be4f3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 29 Sep 2015 10:44:53 +0200 Subject: [PATCH 123/240] MSVC2015: Blacklist tests reading from stdin in buffered/text mode. - tst_QProcess::fileWriterProcess() - tst_QProcess::readLineStdin() - [tst_QProcess::readLineStdin_lineByLine() The test fails apparently due to a bug in its runtime library (fread() dropping data). Task-number: QTBUG-48455 Task-number: QTBUG-48504 Change-Id: I972e560e88312cea0d3dbcea9450c59285a15d5a Reviewed-by: Oliver Wolff --- tests/auto/corelib/io/qfile/BLACKLIST | 5 +++++ tests/auto/corelib/io/qprocess/BLACKLIST | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 tests/auto/corelib/io/qfile/BLACKLIST diff --git a/tests/auto/corelib/io/qfile/BLACKLIST b/tests/auto/corelib/io/qfile/BLACKLIST new file mode 100644 index 0000000000..7aac313b12 --- /dev/null +++ b/tests/auto/corelib/io/qfile/BLACKLIST @@ -0,0 +1,5 @@ +# QTBUG-48455 +[readLineStdin] +msvc-2015 +[readLineStdin_lineByLine] +msvc-2015 diff --git a/tests/auto/corelib/io/qprocess/BLACKLIST b/tests/auto/corelib/io/qprocess/BLACKLIST index dcd913ca49..216faa7fb4 100644 --- a/tests/auto/corelib/io/qprocess/BLACKLIST +++ b/tests/auto/corelib/io/qprocess/BLACKLIST @@ -1,2 +1,5 @@ [lockupsInStartDetached] redhatenterpriselinuxworkstation-6.6 +# QTBUG-48455 +[fileWriterProcess] +msvc-2015 From b86efb1ab9daa76965cda5bdebb225c9e3762e8e Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 24 Sep 2015 11:03:38 +0200 Subject: [PATCH 124/240] Initialize QFutureWatcherBasePrivate::finished and test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's accessed by QFutureWatcherBase::isFinished(), potentially before anything has set it. It gets to be initially true until setFuture() has given it us unfinished future and set it false. Add a regression test for matching state in future and watcher. Task-number: QTBUG-12358 Change-Id: Iae7bdaa434ab80f518afe4d7d55df99c391991a4 Reviewed-by: Frederik Gladhorn Reviewed-by: Thiago Macieira Reviewed-by: Jędrzej Nowacki --- src/corelib/thread/qfuturewatcher.cpp | 7 ++++--- .../thread/qfuturewatcher/tst_qfuturewatcher.cpp | 13 +++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/corelib/thread/qfuturewatcher.cpp b/src/corelib/thread/qfuturewatcher.cpp index 3056216f6e..3863a47673 100644 --- a/src/corelib/thread/qfuturewatcher.cpp +++ b/src/corelib/thread/qfuturewatcher.cpp @@ -248,7 +248,7 @@ bool QFutureWatcherBase::isStarted() const /*! \fn bool QFutureWatcher::isFinished() const Returns \c true if the asynchronous computation represented by the future() - has finished; otherwise returns \c false. + has finished, or if no future has been set; otherwise returns \c false. */ bool QFutureWatcherBase::isFinished() const { @@ -379,7 +379,8 @@ void QFutureWatcherBase::disconnectNotify(const QMetaMethod &signal) */ QFutureWatcherBasePrivate::QFutureWatcherBasePrivate() : maximumPendingResultsReady(QThread::idealThreadCount() * 2), - resultAtConnected(0) + resultAtConnected(0), + finished(true) /* the initial m_future is a canceledResult(), with Finished set */ { } /*! @@ -400,7 +401,7 @@ void QFutureWatcherBase::disconnectOutputInterface(bool pendingAssignment) d->pendingResultsReady.store(0); qDeleteAll(d->pendingCallOutEvents); d->pendingCallOutEvents.clear(); - d->finished = false; + d->finished = false; /* May soon be amended, during connectOutputInterface() */ } futureInterface().d->disconnectOutputInterface(d_func()); diff --git a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp index 60a4d749c9..5ec32b1d02 100644 --- a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp +++ b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp @@ -68,6 +68,7 @@ private slots: void incrementalFilterResults(); void qfutureSynchronizer(); void warnRace(); + void matchFlags(); }; void sleeper() @@ -930,5 +931,17 @@ void tst_QFutureWatcher::warnRace() future.waitForFinished(); } +void tst_QFutureWatcher::matchFlags() +{ + /* Regression test: expect a default watcher to be in the same state as a + * default future. */ + QFutureWatcher watcher; + QFuture future; + QCOMPARE(watcher.isStarted(), future.isStarted()); + QCOMPARE(watcher.isCanceled(), future.isCanceled()); + QCOMPARE(watcher.isFinished(), future.isFinished()); +} + + QTEST_MAIN(tst_QFutureWatcher) #include "tst_qfuturewatcher.moc" From 32f957ccc68084fe11fcf23823c5094a1833a790 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 25 Sep 2015 13:45:38 -0700 Subject: [PATCH 125/240] Don't include in the MinGW qplatformdefs.h There's no need for it and there's harm in doing so, as it #defines "interface". Task-number: QTBUG-48351 Change-Id: I4ca855441b899f3f723a12f673645f3ce7541d9b Reviewed-by: Joerg Bornemann Reviewed-by: Friedemann Kleint --- mkspecs/win32-g++/qplatformdefs.h | 1 - 1 file changed, 1 deletion(-) diff --git a/mkspecs/win32-g++/qplatformdefs.h b/mkspecs/win32-g++/qplatformdefs.h index b4ba092d3b..ef3c518262 100644 --- a/mkspecs/win32-g++/qplatformdefs.h +++ b/mkspecs/win32-g++/qplatformdefs.h @@ -52,7 +52,6 @@ #include #include #include -#include #include #if !defined(_WIN32_WINNT) || (_WIN32_WINNT-0 < 0x0500) From 0bc3983b8a9b7222c0a85e661919ff2f2e8f958a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 30 Sep 2015 13:28:50 +0200 Subject: [PATCH 126/240] Improve messages in tst_qdir/tst_fileinfo/tst_qfiledialog2. Introduce error messages showing the path in file existence, file type and directory entry list tests to make fails related to missing UNC shares clearer. Task-number: QTBUG-48504 Change-Id: I5fb401b94cfa8b58562a906b8d9765039e334027 Reviewed-by: Joerg Bornemann --- tests/auto/corelib/io/qdir/tst_qdir.cpp | 65 ++++++++----- .../corelib/io/qfileinfo/tst_qfileinfo.cpp | 94 +++++++++++++------ .../dialogs/qfiledialog2/tst_qfiledialog2.cpp | 8 +- 3 files changed, 111 insertions(+), 56 deletions(-) diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index 1f98c75f3f..ae6fe7eaef 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -68,6 +68,12 @@ QT_END_NAMESPACE #endif +static QByteArray msgDoesNotExist(const QString &name) +{ + return (QLatin1Char('"') + QDir::toNativeSeparators(name) + + QLatin1String("\" does not exist.")).toLocal8Bit(); +} + class tst_QDir : public QObject { Q_OBJECT @@ -354,7 +360,7 @@ void tst_QDir::mkdir() //make sure it really exists (ie that mkdir returns the right value) QFileInfo fi(path); - QVERIFY(fi.exists() && fi.isDir()); + QVERIFY2(fi.exists() && fi.isDir(), msgDoesNotExist(path).constData()); } void tst_QDir::makedirReturnCode() @@ -378,7 +384,7 @@ void tst_QDir::makedirReturnCode() f.open(QIODevice::WriteOnly); f.write("test"); f.close(); - QVERIFY(f.exists()); + QVERIFY2(f.exists(), msgDoesNotExist(f.fileName()).constData()); QVERIFY(!QDir::current().mkdir(dirName)); // calling mkdir on an existing file will fail. QVERIFY(!QDir::current().mkpath(dirName)); // calling mkpath on an existing file will fail. f.remove(); @@ -474,7 +480,7 @@ void tst_QDir::removeRecursivelyFailure() QVERIFY(!QDir().rmdir(path)); QDir dir(path); QVERIFY(!dir.removeRecursively()); // didn't work - QVERIFY(dir.exists()); // still exists + QVERIFY2(dir.exists(), msgDoesNotExist(dir.absolutePath()).constData()); // still exists QVERIFY(dirAsFile.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner))); QVERIFY(dir.removeRecursively()); @@ -527,14 +533,15 @@ void tst_QDir::exists_data() QTest::newRow("simple dir") << (m_dataPath + "/resources") << true; QTest::newRow("simple dir with slash") << (m_dataPath + "/resources/") << true; #if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) - QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true; - QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << true; - QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << true; - QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << true; - QTest::newRow("unc 5") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp" << true; - QTest::newRow("unc 6") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp/" << true; - QTest::newRow("unc 7") << "//" + QtNetworkSettings::winServerName() + "/testshare/adirthatshouldnotexist" << false; - QTest::newRow("unc 8") << "//" + QtNetworkSettings::winServerName() + "/asharethatshouldnotexist" << false; + const QString uncRoot = QStringLiteral("//") + QtNetworkSettings::winServerName(); + QTest::newRow("unc 1") << uncRoot << true; + QTest::newRow("unc 2") << uncRoot + QLatin1Char('/') << true; + QTest::newRow("unc 3") << uncRoot + "/testshare" << true; + QTest::newRow("unc 4") << uncRoot + "/testshare/" << true; + QTest::newRow("unc 5") << uncRoot + "/testshare/tmp" << true; + QTest::newRow("unc 6") << uncRoot + "/testshare/tmp/" << true; + QTest::newRow("unc 7") << uncRoot + "/testshare/adirthatshouldnotexist" << false; + QTest::newRow("unc 8") << uncRoot + "/asharethatshouldnotexist" << false; QTest::newRow("unc 9") << "//ahostthatshouldnotexist" << false; #endif #if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) @@ -566,7 +573,10 @@ void tst_QDir::exists() QFETCH(bool, expected); QDir dir(path); - QCOMPARE(dir.exists(), expected); + if (expected) + QVERIFY2(dir.exists(), msgDoesNotExist(path).constData()); + else + QVERIFY(!dir.exists()); } void tst_QDir::isRelativePath_data() @@ -802,7 +812,7 @@ void tst_QDir::entryList() #endif //Q_NO_SYMLINKS QDir dir(dirName); - QVERIFY(dir.exists()); + QVERIFY2(dir.exists(), msgDoesNotExist(dirName).constData()); QStringList actual = dir.entryList(nameFilters, (QDir::Filters)filterspec, (QDir::SortFlags)sortspec); @@ -888,18 +898,25 @@ void tst_QDir::entryListSimple_data() #endif #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << 2; - QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << 2; - QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << 2; - QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << 2; - QTest::newRow("unc 5") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp" << 2; - QTest::newRow("unc 6") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp/" << 2; - QTest::newRow("unc 7") << "//" + QtNetworkSettings::winServerName() + "/testshare/adirthatshouldnotexist" << 0; - QTest::newRow("unc 8") << "//" + QtNetworkSettings::winServerName() + "/asharethatshouldnotexist" << 0; + const QString uncRoot = QStringLiteral("//") + QtNetworkSettings::winServerName(); + QTest::newRow("unc 1") << uncRoot << 2; + QTest::newRow("unc 2") << uncRoot + QLatin1Char('/') << 2; + QTest::newRow("unc 3") << uncRoot + "/testshare" << 2; + QTest::newRow("unc 4") << uncRoot + "/testshare/" << 2; + QTest::newRow("unc 5") << uncRoot + "/testshare/tmp" << 2; + QTest::newRow("unc 6") << uncRoot + "/testshare/tmp/" << 2; + QTest::newRow("unc 7") << uncRoot + "/testshare/adirthatshouldnotexist" << 0; + QTest::newRow("unc 8") << uncRoot + "/asharethatshouldnotexist" << 0; QTest::newRow("unc 9") << "//ahostthatshouldnotexist" << 0; #endif } +static QByteArray msgEntryListFailed(int actual, int expectedMin, const QString &name) +{ + return QByteArray::number(actual) + " < " + QByteArray::number(expectedMin) + " in \"" + + QFile::encodeName(QDir::toNativeSeparators(name)) + '"'; +} + void tst_QDir::entryListSimple() { QFETCH(QString, dirName); @@ -907,7 +924,7 @@ void tst_QDir::entryListSimple() QDir dir(dirName); QStringList actual = dir.entryList(); - QVERIFY(actual.count() >= countMin); + QVERIFY2(actual.count() >= countMin, msgEntryListFailed(actual.count(), countMin, dirName).constData()); } void tst_QDir::entryListWithSymLinks() @@ -1121,7 +1138,7 @@ void tst_QDir::setNameFilters() QFETCH(QStringList, expected); QDir dir(dirName); - QVERIFY(dir.exists()); + QVERIFY2(dir.exists(), msgDoesNotExist(dirName).constData()); dir.setNameFilters(nameFilters); QStringList actual = dir.entryList(); @@ -1504,7 +1521,7 @@ void tst_QDir::exists2() QDir dir; if (exists) - QVERIFY(dir.exists(path)); + QVERIFY2(dir.exists(path), msgDoesNotExist(path).constData()); else QVERIFY(!dir.exists(path)); diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index 8784261c2b..210fdb5a12 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -149,6 +149,25 @@ static QString seedAndTemplate() qsrand(QDateTime::currentDateTimeUtc().toTime_t()); return QDir::tempPath() + "/tst_qfileinfo-XXXXXX"; } + +static QByteArray msgDoesNotExist(const QString &name) +{ + return (QLatin1Char('"') + QDir::toNativeSeparators(name) + + QLatin1String("\" does not exist.")).toLocal8Bit(); +} + +static QByteArray msgIsNoDirectory(const QString &name) +{ + return (QLatin1Char('"') + QDir::toNativeSeparators(name) + + QLatin1String("\" is not a directory.")).toLocal8Bit(); +} + +static QByteArray msgIsNotRoot(const QString &name) +{ + return (QLatin1Char('"') + QDir::toNativeSeparators(name) + + QLatin1String("\" is no root directory.")).toLocal8Bit(); +} + class tst_QFileInfo : public QObject { Q_OBJECT @@ -414,13 +433,14 @@ void tst_QFileInfo::isDir_data() //QTest::newRow("drive 2") << "t:s" << false; #endif #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true; - QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << true; - QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << true; - QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << true; - QTest::newRow("unc 5") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp" << true; - QTest::newRow("unc 6") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp/" << true; - QTest::newRow("unc 7") << "//" + QtNetworkSettings::winServerName() + "/testshare/adirthatshouldnotexist" << false; + const QString uncRoot = QStringLiteral("//") + QtNetworkSettings::winServerName(); + QTest::newRow("unc 1") << uncRoot << true; + QTest::newRow("unc 2") << uncRoot + QLatin1Char('/') << true; + QTest::newRow("unc 3") << uncRoot + "/testshare" << true; + QTest::newRow("unc 4") << uncRoot + "/testshare/" << true; + QTest::newRow("unc 5") << uncRoot + "/testshare/tmp" << true; + QTest::newRow("unc 6") << uncRoot + "/testshare/tmp/" << true; + QTest::newRow("unc 7") << uncRoot + "/testshare/adirthatshouldnotexist" << false; #endif } @@ -429,8 +449,11 @@ void tst_QFileInfo::isDir() QFETCH(QString, path); QFETCH(bool, expected); - QFileInfo fi(path); - QCOMPARE(fi.isDir(), expected); + const bool isDir = QFileInfo(path).isDir(); + if (expected) + QVERIFY2(isDir, msgIsNoDirectory(path).constData()); + else + QVERIFY(!isDir); } void tst_QFileInfo::isRoot_data() @@ -453,10 +476,11 @@ void tst_QFileInfo::isRoot_data() #endif #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) - QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true; - QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << true; - QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << false; - QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << false; + const QString uncRoot = QStringLiteral("//") + QtNetworkSettings::winServerName(); + QTest::newRow("unc 1") << uncRoot << true; + QTest::newRow("unc 2") << uncRoot + QLatin1Char('/') << true; + QTest::newRow("unc 3") << uncRoot + "/testshare" << false; + QTest::newRow("unc 4") << uncRoot + "/testshare/" << false; QTest::newRow("unc 7") << "//ahostthatshouldnotexist" << false; #endif } @@ -466,8 +490,11 @@ void tst_QFileInfo::isRoot() QFETCH(QString, path); QFETCH(bool, expected); - QFileInfo fi(path); - QCOMPARE(fi.isRoot(), expected); + const bool isRoot = QFileInfo(path).isRoot(); + if (expected) + QVERIFY2(isRoot, msgIsNotRoot(path).constData()); + else + QVERIFY(!isRoot); } void tst_QFileInfo::exists_data() @@ -493,14 +520,15 @@ void tst_QFileInfo::exists_data() QTest::newRow("simple dir with slash") << (m_resourcesDir + QLatin1Char('/')) << true; #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) - QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true; - QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << true; - QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << true; - QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << true; - QTest::newRow("unc 5") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp" << true; - QTest::newRow("unc 6") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp/" << true; - QTest::newRow("unc 7") << "//" + QtNetworkSettings::winServerName() + "/testshare/adirthatshouldnotexist" << false; - QTest::newRow("unc 8") << "//" + QtNetworkSettings::winServerName() + "/asharethatshouldnotexist" << false; + const QString uncRoot = QStringLiteral("//") + QtNetworkSettings::winServerName(); + QTest::newRow("unc 1") << uncRoot << true; + QTest::newRow("unc 2") << uncRoot + QLatin1Char('/') << true; + QTest::newRow("unc 3") << uncRoot + "/testshare" << true; + QTest::newRow("unc 4") << uncRoot + "/testshare/" << true; + QTest::newRow("unc 5") << uncRoot + "/testshare/tmp" << true; + QTest::newRow("unc 6") << uncRoot + "/testshare/tmp/" << true; + QTest::newRow("unc 7") << uncRoot + "/testshare/adirthatshouldnotexist" << false; + QTest::newRow("unc 8") << uncRoot + "/asharethatshouldnotexist" << false; QTest::newRow("unc 9") << "//ahostthatshouldnotexist" << false; #endif } @@ -511,8 +539,12 @@ void tst_QFileInfo::exists() QFETCH(bool, expected); QFileInfo fi(path); - QCOMPARE(fi.exists(), expected); - QCOMPARE(QFileInfo::exists(path), expected); + const bool exists = fi.exists(); + QCOMPARE(exists, QFileInfo::exists(path)); + if (expected) + QVERIFY2(exists, msgDoesNotExist(path).constData()); + else + QVERIFY(!exists); } void tst_QFileInfo::absolutePath_data() @@ -994,7 +1026,7 @@ void tst_QFileInfo::systemFiles() QSKIP("This is a Windows only test"); #endif QFileInfo fi("c:\\pagefile.sys"); - QVERIFY(fi.exists()); + QVERIFY2(fi.exists(), msgDoesNotExist(fi.absoluteFilePath()).constData()); QVERIFY(fi.size() > 0); QVERIFY(fi.lastModified().isValid()); } @@ -1479,7 +1511,7 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() QTest::newRow("dummy") << target.path() << false << "" << target.canonicalPath(); QSKIP("link not supported by FS or insufficient privilege"); } - QVERIFY(file.exists()); + QVERIFY2(file.exists(), msgDoesNotExist(file.fileName()).constData()); QTest::newRow("absolute dir symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath(); QTest::newRow("relative dir symlink") << relSymlink << true << QDir::fromNativeSeparators(relTarget) << target.canonicalPath(); @@ -1510,7 +1542,7 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() QFile file(fileInJunction.absoluteFilePath()); file.open(QIODevice::ReadWrite); file.close(); - QVERIFY(file.exists()); + QVERIFY2(file.exists(), msgDoesNotExist(file.fileName()).constData()); QTest::newRow("file in junction") << fileInJunction.absoluteFilePath() << false << "" << fileInJunction.canonicalFilePath(); target = QDir::rootPath(); @@ -1602,7 +1634,7 @@ void tst_QFileInfo::isWritable() #else QFileInfo fi("c:\\pagefile.sys"); #endif - QVERIFY(fi.exists()); + QVERIFY2(fi.exists(), msgDoesNotExist(fi.absoluteFilePath()).constData()); QVERIFY(!fi.isWritable()); #endif #if defined (Q_OS_QNX) // On QNX /etc is usually on a read-only filesystem @@ -1860,7 +1892,7 @@ void tst_QFileInfo::owner() QVERIFY(testFile.write(testData) != -1); } QFileInfo fi(fileName); - QVERIFY(fi.exists()); + QVERIFY2(fi.exists(), msgDoesNotExist(fi.absoluteFilePath()).constData()); QCOMPARE(fi.owner(), userName); QFile::remove(fileName); @@ -1895,7 +1927,7 @@ void tst_QFileInfo::group() QVERIFY(testFile.write(testData) != -1); testFile.close(); QFileInfo fi(fileName); - QVERIFY(fi.exists()); + QVERIFY2(fi.exists(), msgDoesNotExist(fi.absoluteFilePath()).constData()); QCOMPARE(fi.group(), expected); } diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp index ed44a5d503..d48c718d4d 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp @@ -81,6 +81,12 @@ public: } }; +static QByteArray msgDoesNotExist(const QString &name) +{ + return (QLatin1Char('"') + QDir::toNativeSeparators(name) + + QLatin1String("\" does not exist.")).toLocal8Bit(); +} + class tst_QFileDialog2 : public QObject { Q_OBJECT @@ -307,7 +313,7 @@ void tst_QFileDialog2::unc() #else QString dir(QDir::currentPath()); #endif - QVERIFY(QFile::exists(dir)); + QVERIFY2(QFile::exists(dir), msgDoesNotExist(dir).constData()); QNonNativeFileDialog fd(0, QString(), dir); QFileSystemModel *model = fd.findChild("qt_filesystem_model"); QVERIFY(model); From 3130f0865a256e5a4bb3eb9918bbde31b8b5fafe Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 30 Sep 2015 10:18:30 +0200 Subject: [PATCH 127/240] Improve tst_qfile. - Introduce consistent error messages for failing QFile::open() and existence checks to make errors about non-available UNC paths on Windows clearer. - Introduce a guard class to ensure the stdin reader processes are terminated properly in case of failures, which currently occur for MSVC2015. - Fix brace coding style and remove unnecessary QString conversions. Task-number: QTBUG-48504 Change-Id: I890b13088558ef05391fb152a6b815276df0fe8c Reviewed-by: Joerg Bornemann --- tests/auto/corelib/io/qfile/tst_qfile.cpp | 284 +++++++++++++--------- 1 file changed, 170 insertions(+), 114 deletions(-) diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index b0d0d122e8..1c695a1113 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -390,6 +390,27 @@ tst_QFile::tst_QFile() : m_oldDir(QDir::currentPath()) { } +static QByteArray msgOpenFailed(QIODevice::OpenMode om, const QFile &file) +{ + QString result; + QDebug(&result).noquote().nospace() << "Could not open \"" + << QDir::toNativeSeparators(file.fileName()) << "\" using " + << om << ": " << file.errorString(); + return result.toLocal8Bit(); +} + +static QByteArray msgOpenFailed(const QFile &file) +{ + return (QLatin1String("Could not open \"") + QDir::toNativeSeparators(file.fileName()) + + QLatin1String("\": ") + file.errorString()).toLocal8Bit(); +} + +static QByteArray msgFileDoesNotExist(const QString &name) +{ + return (QLatin1Char('"') + QDir::toNativeSeparators(name) + + QLatin1String("\" does not exist.")).toLocal8Bit(); +} + void tst_QFile::initTestCase() { QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); @@ -418,19 +439,19 @@ void tst_QFile::initTestCase() // create a file and make it read-only QFile file(QString::fromLatin1(readOnlyFile)); - QVERIFY2(file.open(QFile::WriteOnly), qPrintable(file.errorString())); + QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData()); file.write("a", 1); file.close(); QVERIFY2(file.setPermissions(QFile::ReadOwner), qPrintable(file.errorString())); // create another file and make it not readable file.setFileName(QString::fromLatin1(noReadFile)); - QVERIFY2(file.open(QFile::WriteOnly), qPrintable(file.errorString())); + QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData()); file.write("b", 1); file.close(); #ifndef Q_OS_WIN // Not supported on Windows. QVERIFY2(file.setPermissions(0), qPrintable(file.errorString())); #else - QVERIFY2(file.open(QFile::WriteOnly), qPrintable(file.errorString())); + QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData()); #endif } @@ -455,19 +476,19 @@ void tst_QFile::cleanupTestCase() void tst_QFile::exists() { QFile f( m_testFile ); - QVERIFY(f.exists()); + QVERIFY2(f.exists(), msgFileDoesNotExist(m_testFile)); QFile file("nobodyhassuchafile"); file.remove(); QVERIFY(!file.exists()); QFile file2("nobodyhassuchafile"); - QVERIFY(file2.open(QIODevice::WriteOnly)); + QVERIFY2(file2.open(QIODevice::WriteOnly), msgOpenFailed(file2).constData()); file2.close(); QVERIFY(file.exists()); - QVERIFY(file.open(QIODevice::WriteOnly)); + QVERIFY2(file.open(QIODevice::WriteOnly), msgOpenFailed(file).constData()); file.close(); QVERIFY(file.exists()); @@ -475,8 +496,9 @@ void tst_QFile::exists() QVERIFY(!file.exists()); #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) - QFile unc("//" + QtNetworkSettings::winServerName() + "/testshare/readme.txt"); - QVERIFY(unc.exists()); + const QString uncPath = "//" + QtNetworkSettings::winServerName() + "/testshare/readme.txt"; + QFile unc(uncPath); + QVERIFY2(unc.exists(), msgFileDoesNotExist(uncPath).constData()); #endif } @@ -558,7 +580,12 @@ void tst_QFile::open() if (filename.isEmpty()) QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::open: No file name specified"); - QCOMPARE(f.open( QIODevice::OpenMode(mode) ), ok); + const QIODevice::OpenMode om(mode); + const bool succeeded = f.open(om); + if (ok) + QVERIFY2(succeeded, msgOpenFailed(om, f).constData()); + else + QVERIFY(!succeeded); QTEST( f.error(), "status" ); } @@ -566,7 +593,7 @@ void tst_QFile::open() void tst_QFile::openUnbuffered() { QFile file(m_testFile); - QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)); + QVERIFY2(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered), msgOpenFailed(file).constData()); char c = '\0'; QVERIFY(file.seek(1)); QCOMPARE(file.pos(), qint64(1)); @@ -618,7 +645,7 @@ void tst_QFile::size() QFile f( filename ); QCOMPARE( f.size(), size ); - QVERIFY( f.open(QIODevice::ReadOnly) ); + QVERIFY2(f.open(QIODevice::ReadOnly), msgOpenFailed(f).constData()); QCOMPARE( f.size(), size ); } @@ -662,7 +689,7 @@ void tst_QFile::sizeNoExist() void tst_QFile::seek() { QFile file("newfile.txt"); - file.open(QIODevice::WriteOnly); + QVERIFY2(file.open(QIODevice::WriteOnly), msgOpenFailed(file).constData()); QCOMPARE(file.size(), qint64(0)); QCOMPARE(file.pos(), qint64(0)); QVERIFY(file.seek(10)); @@ -674,7 +701,7 @@ void tst_QFile::seek() void tst_QFile::setSize() { QFile f("createme.txt"); - QVERIFY(f.open(QIODevice::Truncate | QIODevice::ReadWrite)); + QVERIFY2(f.open(QIODevice::Truncate | QIODevice::ReadWrite), msgOpenFailed(f).constData()); f.putChar('a'); f.seek(0); @@ -712,7 +739,7 @@ void tst_QFile::setSize() void tst_QFile::setSizeSeek() { QFile f("setsizeseek.txt"); - QVERIFY(f.open(QFile::WriteOnly)); + QVERIFY2(f.open(QFile::WriteOnly), msgOpenFailed(f).constData()); f.write("ABCD"); QCOMPARE(f.pos(), qint64(4)); @@ -734,7 +761,7 @@ void tst_QFile::setSizeSeek() void tst_QFile::atEnd() { QFile f( m_testFile ); - QVERIFY(f.open( QIODevice::ReadOnly )); + QVERIFY2(f.open(QFile::ReadOnly), msgOpenFailed(f).constData()); int size = f.size(); f.seek( size ); @@ -747,7 +774,7 @@ void tst_QFile::atEnd() void tst_QFile::readLine() { QFile f( m_testFile ); - QVERIFY(f.open( QIODevice::ReadOnly )); + QVERIFY2(f.open(QFile::ReadOnly), msgOpenFailed(f).constData()); int i = 0; char p[128]; @@ -767,7 +794,8 @@ void tst_QFile::readLine() void tst_QFile::readLine2() { QFile f( m_testFile ); - f.open( QIODevice::ReadOnly ); + QVERIFY2(f.open(QFile::ReadOnly), msgOpenFailed(f).constData()); + char p[128]; QCOMPARE(f.readLine(p, 60), qlonglong(59)); @@ -785,7 +813,7 @@ void tst_QFile::readLineNullInLine() { QFile::remove("nullinline.txt"); QFile file("nullinline.txt"); - QVERIFY(file.open(QIODevice::ReadWrite)); + QVERIFY2(file.open(QFile::ReadWrite), msgOpenFailed(file).constData()); QVERIFY(file.write("linewith\0null\nanotherline\0withnull\n\0\nnull\0", 42) > 0); QVERIFY(file.flush()); file.reset(); @@ -816,10 +844,8 @@ void tst_QFile::readAll() QFETCH( QString, fileName ); QFile file(fileName); - if (textMode) - QVERIFY(file.open(QFile::Text | QFile::ReadOnly)); - else - QVERIFY(file.open(QFile::ReadOnly)); + const QIODevice::OpenMode om = textMode ? (QFile::Text | QFile::ReadOnly) : QFile::ReadOnly; + QVERIFY2(file.open(om), msgOpenFailed(om, file).constData()); QByteArray a = file.readAll(); file.reset(); @@ -848,8 +874,8 @@ void tst_QFile::readAllBuffer() QByteArray data1("This is arguably a very simple text."); QByteArray data2("This is surely not as simple a test."); - QVERIFY( writer.open(QIODevice::ReadWrite | QIODevice::Unbuffered) ); - QVERIFY( reader.open(QIODevice::ReadOnly) ); + QVERIFY2(writer.open(QIODevice::ReadWrite | QIODevice::Unbuffered), msgOpenFailed(writer).constData()); + QVERIFY2(reader.open(QIODevice::ReadOnly), msgOpenFailed(reader).constData()); QCOMPARE( writer.write(data1), qint64(data1.size()) ); QVERIFY( writer.seek(0) ); @@ -868,6 +894,32 @@ void tst_QFile::readAllBuffer() QFile::remove(fileName); } +#ifndef QT_NO_PROCESS +class StdinReaderProcessGuard { // Ensure the stdin reader process is stopped on destruction. + Q_DISABLE_COPY(StdinReaderProcessGuard) + +public: + StdinReaderProcessGuard(QProcess *p) : m_process(p) {} + ~StdinReaderProcessGuard() { stop(); } + + bool stop(int msecs = 30000) + { + if (m_process->state() != QProcess::Running) + return true; + m_process->closeWriteChannel(); + if (m_process->waitForFinished(msecs)) + return m_process->exitStatus() == QProcess::NormalExit && !m_process->exitCode(); + m_process->terminate(); + if (!m_process->waitForFinished()) + m_process->kill(); + return false; + } + +private: + QProcess *m_process; +}; +#endif // !QT_NO_PROCESS + #if !defined(Q_OS_WINCE) void tst_QFile::readAllStdin() { @@ -877,18 +929,17 @@ void tst_QFile::readAllStdin() QByteArray lotsOfData(1024, '@'); // 10 megs QProcess process; + StdinReaderProcessGuard processGuard(&process); process.start(m_stdinProcessDir + QStringLiteral("/stdinprocess"), QStringList(QStringLiteral("all"))); QVERIFY2(process.waitForStarted(), qPrintable(process.errorString())); for (int i = 0; i < 5; ++i) { QTest::qWait(1000); process.write(lotsOfData); - while (process.bytesToWrite() > 0) { + while (process.bytesToWrite() > 0) QVERIFY(process.waitForBytesWritten()); - } } - process.closeWriteChannel(); - process.waitForFinished(); + QVERIFY(processGuard.stop()); QCOMPARE(process.readAll().size(), lotsOfData.size() * 5); #endif } @@ -908,6 +959,7 @@ void tst_QFile::readLineStdin() for (int i = 0; i < 2; ++i) { QProcess process; + StdinReaderProcessGuard processGuard(&process); process.start(m_stdinProcessDir + QStringLiteral("/stdinprocess"), QStringList() << QStringLiteral("line") << QString::number(i), QIODevice::Text | QIODevice::ReadWrite); @@ -915,13 +967,11 @@ void tst_QFile::readLineStdin() for (int i = 0; i < 5; ++i) { QTest::qWait(1000); process.write(lotsOfData); - while (process.bytesToWrite() > 0) { + while (process.bytesToWrite() > 0) QVERIFY(process.waitForBytesWritten()); - } } - process.closeWriteChannel(); - QVERIFY(process.waitForFinished(5000)); + QVERIFY(processGuard.stop(5000)); QByteArray array = process.readAll(); QCOMPARE(array.size(), lotsOfData.size() * 5); @@ -942,6 +992,7 @@ void tst_QFile::readLineStdin_lineByLine() #else for (int i = 0; i < 2; ++i) { QProcess process; + StdinReaderProcessGuard processGuard(&process); process.start(m_stdinProcessDir + QStringLiteral("/stdinprocess"), QStringList() << QStringLiteral("line") << QString::number(i), QIODevice::Text | QIODevice::ReadWrite); @@ -956,8 +1007,7 @@ void tst_QFile::readLineStdin_lineByLine() QCOMPARE(process.readAll(), line); } - process.closeWriteChannel(); - QVERIFY(process.waitForFinished(5000)); + QVERIFY(processGuard.stop(5000)); } #endif } @@ -967,7 +1017,7 @@ void tst_QFile::text() { // dosfile.txt is a binary CRLF file QFile file(m_dosFile); - QVERIFY(file.open(QFile::Text | QFile::ReadOnly)); + QVERIFY2(file.open(QFile::Text | QFile::ReadOnly), msgOpenFailed(file).constData()); QCOMPARE(file.readLine(), QByteArray("/dev/system/root / reiserfs acl,user_xattr 1 1\n")); QCOMPARE(file.readLine(), @@ -980,7 +1030,7 @@ void tst_QFile::text() void tst_QFile::missingEndOfLine() { QFile file(m_noEndOfLineFile); - QVERIFY(file.open(QFile::ReadOnly)); + QVERIFY2(file.open(QFile::ReadOnly), msgOpenFailed(file).constData()); int nlines = 0; while (!file.atEnd()) { @@ -1026,7 +1076,7 @@ void tst_QFile::getch() void tst_QFile::ungetChar() { QFile f(m_testFile); - QVERIFY(f.open(QIODevice::ReadOnly)); + QVERIFY2(f.open(QFile::ReadOnly), msgOpenFailed(f).constData()); QByteArray array = f.readLine(); QCOMPARE(array.constData(), "----------------------------------------------------------\n"); @@ -1044,7 +1094,7 @@ void tst_QFile::ungetChar() QFile::remove("genfile.txt"); QFile out("genfile.txt"); - QVERIFY(out.open(QIODevice::ReadWrite)); + QVERIFY2(out.open(QIODevice::ReadWrite), msgOpenFailed(out).constData()); out.write("123"); out.seek(0); QCOMPARE(out.readAll().constData(), "123"); @@ -1127,7 +1177,7 @@ void tst_QFile::createFile() QVERIFY( !QFile::exists( "createme.txt" ) ); QFile f( "createme.txt" ); - QVERIFY( f.open( QIODevice::WriteOnly ) ); + QVERIFY2( f.open(QIODevice::WriteOnly), msgOpenFailed(f).constData()); f.close(); QVERIFY( QFile::exists( "createme.txt" ) ); } @@ -1140,11 +1190,11 @@ void tst_QFile::append() QVERIFY(!QFile::exists(name)); QFile f(name); - QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate)); + QVERIFY2(f.open(QIODevice::WriteOnly | QIODevice::Truncate), msgOpenFailed(f).constData()); f.putChar('a'); f.close(); - QVERIFY(f.open(QIODevice::Append)); + QVERIFY2(f.open(QIODevice::Append), msgOpenFailed(f).constData()); QVERIFY(f.pos() == 1); f.putChar('a'); f.close(); @@ -1181,7 +1231,7 @@ void tst_QFile::permissions() QFETCH(bool, create); if (create) { QFile fc(file); - QVERIFY(fc.open(QFile::WriteOnly)); + QVERIFY2(fc.open(QFile::WriteOnly), msgOpenFailed(fc).constData()); QVERIFY(fc.write("hello\n")); fc.close(); } @@ -1230,7 +1280,7 @@ void tst_QFile::setPermissions() QVERIFY( !QFile::exists( "createme.txt" ) ); QFile f("createme.txt"); - QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate)); + QVERIFY2(f.open(QIODevice::WriteOnly | QIODevice::Truncate), msgOpenFailed(f).constData()); f.putChar('a'); f.close(); @@ -1247,8 +1297,8 @@ void tst_QFile::copy() QFile::remove("test2"); QVERIFY(QFile::copy(m_testSourceFile, "tst_qfile_copy.cpp")); QFile in1(m_testSourceFile), in2("tst_qfile_copy.cpp"); - QVERIFY(in1.open(QFile::ReadOnly)); - QVERIFY(in2.open(QFile::ReadOnly)); + QVERIFY2(in1.open(QFile::ReadOnly), msgOpenFailed(in1).constData()); + QVERIFY2(in2.open(QFile::ReadOnly), msgOpenFailed(in2).constData()); QByteArray data1 = in1.readAll(), data2 = in2.readAll(); QCOMPARE(data1, data2); QFile::remove( "main_copy.cpp" ); @@ -1261,8 +1311,8 @@ void tst_QFile::copyAfterFail() QFile file1("file-to-be-copied.txt"); QFile file2("existing-file.txt"); - QVERIFY(file1.open(QIODevice::ReadWrite) && "(test-precondition)"); - QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)"); + QVERIFY2(file1.open(QIODevice::ReadWrite), msgOpenFailed(file1).constData()); + QVERIFY2(file2.open(QIODevice::ReadWrite), msgOpenFailed(file1).constData()); file2.close(); QVERIFY(!QFile::exists("copied-file-1.txt") && "(test-precondition)"); QVERIFY(!QFile::exists("copied-file-2.txt") && "(test-precondition)"); @@ -1331,7 +1381,7 @@ void tst_QFile::copyFallback() QVERIFY(QFile::remove("file-copy-destination.txt")); // Fallback copy of open file. - QVERIFY(file.open(QIODevice::ReadOnly)); + QVERIFY2(file.open(QIODevice::ReadOnly), msgOpenFailed(file).constData()); QVERIFY(file.copy("file-copy-destination.txt")); QVERIFY(QFile::exists("file-copy-destination.txt")); QVERIFY(!file.isOpen()); @@ -1401,7 +1451,7 @@ void tst_QFile::link() QCOMPARE(info2.symLinkTarget(), referenceTarget); QFile link("myLink.lnk"); - QVERIFY(link.open(QIODevice::ReadOnly)); + QVERIFY2(link.open(QIODevice::ReadOnly), msgOpenFailed(link).constData()); QCOMPARE(link.symLinkTarget(), referenceTarget); link.close(); @@ -1483,15 +1533,15 @@ void tst_QFile::readTextFile() QFETCH(QByteArray, out); QFile winfile("winfile.txt"); - QVERIFY(winfile.open(QFile::WriteOnly | QFile::Truncate)); + QVERIFY2(winfile.open(QFile::WriteOnly | QFile::Truncate), msgOpenFailed(winfile).constData()); winfile.write(in); winfile.close(); - QVERIFY(winfile.open(QFile::ReadOnly)); + QVERIFY2(winfile.open(QFile::ReadOnly), msgOpenFailed(winfile).constData()); QCOMPARE(winfile.readAll(), in); winfile.close(); - QVERIFY(winfile.open(QFile::ReadOnly | QFile::Text)); + QVERIFY2(winfile.open(QFile::ReadOnly | QFile::Text), msgOpenFailed(winfile).constData()); QCOMPARE(winfile.readAll(), out); } @@ -1499,13 +1549,13 @@ void tst_QFile::readTextFile2() { { QFile file(m_testLogFile); - QVERIFY(file.open(QIODevice::ReadOnly)); + QVERIFY2(file.open(QIODevice::ReadOnly), msgOpenFailed(file).constData()); file.read(4097); } { QFile file(m_testLogFile); - QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); + QVERIFY2(file.open(QIODevice::ReadOnly | QIODevice::Text), msgOpenFailed(file).constData()); file.read(4097); } } @@ -1532,7 +1582,8 @@ void tst_QFile::writeTextFile() QFETCH(QByteArray, in); QFile file("textfile.txt"); - QVERIFY(file.open(QFile::WriteOnly | QFile::Truncate | QFile::Text)); + QVERIFY2(file.open(QFile::WriteOnly | QFile::Truncate | QFile::Text), + msgOpenFailed(file).constData()); QByteArray out = in; #ifdef Q_OS_WIN out.replace('\n', "\r\n"); @@ -1555,8 +1606,10 @@ void tst_QFile::largeUncFileSupport() { // 1) Native file handling. QFile file(largeFile); + QVERIFY2(file.exists(), msgFileDoesNotExist(largeFile)); + QCOMPARE(file.size(), size); - QVERIFY(file.open(QIODevice::ReadOnly)); + QVERIFY2(file.open(QIODevice::ReadOnly), msgOpenFailed(file).constData()); QCOMPARE(file.size(), size); QVERIFY(file.seek(dataOffset)); QCOMPARE(file.read(knownData.size()), knownData); @@ -1593,13 +1646,13 @@ void tst_QFile::flush() { QFile file(fileName); - QVERIFY(file.open(QFile::WriteOnly)); + QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData()); QCOMPARE(file.write("abc", 3),qint64(3)); } { QFile file(fileName); - QVERIFY(file.open(QFile::WriteOnly | QFile::Append)); + QVERIFY2(file.open(QFile::WriteOnly | QFile::Append), msgOpenFailed(file).constData()); QCOMPARE(file.pos(), qlonglong(3)); QCOMPARE(file.write("def", 3), qlonglong(3)); QCOMPARE(file.pos(), qlonglong(6)); @@ -1607,7 +1660,7 @@ void tst_QFile::flush() { QFile file("stdfile.txt"); - QVERIFY(file.open(QFile::ReadOnly)); + QVERIFY2(file.open(QFile::ReadOnly), msgOpenFailed(file).constData()); QCOMPARE(file.readAll(), QByteArray("abcdef")); } } @@ -1617,7 +1670,7 @@ void tst_QFile::bufferedRead() QFile::remove("stdfile.txt"); QFile file("stdfile.txt"); - QVERIFY(file.open(QFile::WriteOnly)); + QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData()); file.write("abcdef"); file.close(); @@ -1634,7 +1687,7 @@ void tst_QFile::bufferedRead() { QFile file; - QVERIFY(file.open(stdFile, QFile::ReadOnly)); + QVERIFY2(file.open(stdFile, QFile::ReadOnly), msgOpenFailed(file).constData()); QCOMPARE(file.pos(), qlonglong(1)); QCOMPARE(file.read(&c, 1), qlonglong(1)); QCOMPARE(c, 'b'); @@ -1648,7 +1701,7 @@ void tst_QFile::bufferedRead() void tst_QFile::isSequential() { QFile zero("/dev/null"); - QVERIFY(zero.open(QFile::ReadOnly)); + QVERIFY2(zero.open(QFile::ReadOnly), msgOpenFailed(zero).constData()); QVERIFY(zero.isSequential()); } #endif @@ -1662,15 +1715,15 @@ void tst_QFile::truncate() { for (int i = 0; i < 2; ++i) { QFile file("truncate.txt"); - QVERIFY(file.open(QFile::WriteOnly)); + QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData()); file.write(QByteArray(200, '@')); file.close(); - QVERIFY(file.open((i ? QFile::WriteOnly : QFile::ReadWrite) | QFile::Truncate)); + QVERIFY2(file.open((i ? QFile::WriteOnly : QFile::ReadWrite) | QFile::Truncate), msgOpenFailed(file).constData()); file.write(QByteArray(100, '$')); file.close(); - QVERIFY(file.open(QFile::ReadOnly)); + QVERIFY2(file.open(QFile::ReadOnly), msgOpenFailed(file).constData()); QCOMPARE(file.readAll(), QByteArray(100, '$')); } } @@ -1679,13 +1732,13 @@ void tst_QFile::seekToPos() { { QFile file("seekToPos.txt"); - QVERIFY(file.open(QFile::WriteOnly)); + QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData()); file.write("a\r\nb\r\nc\r\n"); file.flush(); } QFile file("seekToPos.txt"); - QVERIFY(file.open(QFile::ReadOnly | QFile::Text)); + QVERIFY2(file.open(QFile::ReadOnly | QFile::Text), msgOpenFailed(file).constData()); file.seek(1); char c; QVERIFY(file.getChar(&c)); @@ -1707,7 +1760,7 @@ void tst_QFile::seekAfterEndOfFile() QFile::remove(filename); { QFile file(filename); - QVERIFY(file.open(QFile::WriteOnly)); + QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData()); file.write("abcd"); QCOMPARE(file.size(), qint64(4)); file.seek(8); @@ -1723,7 +1776,7 @@ void tst_QFile::seekAfterEndOfFile() } QFile file(filename); - QVERIFY(file.open(QFile::ReadOnly)); + QVERIFY2(file.open(QFile::ReadOnly), msgOpenFailed(file).constData()); QByteArray contents = file.readAll(); QCOMPARE(contents.left(12), QByteArray("abcdefghijkl", 12)); //bytes 12-15 are uninitialised so we don't care what they read as. @@ -1741,7 +1794,7 @@ void tst_QFile::FILEReadWrite() // create test file { QFile f("FILEReadWrite.txt"); - QVERIFY(f.open(QFile::WriteOnly)); + QVERIFY2(f.open(QFile::WriteOnly), msgOpenFailed(f).constData()); QDataStream ds(&f); qint8 c = 0; ds << c; @@ -1777,7 +1830,7 @@ void tst_QFile::FILEReadWrite() #endif QVERIFY(fp); QFile file; - QVERIFY(file.open(fp, QFile::ReadWrite)); + QVERIFY2(file.open(fp, QFile::ReadWrite), msgOpenFailed(file).constData()); QDataStream sfile(&file) ; qint8 var1,var2,var3,var4; @@ -1814,7 +1867,7 @@ void tst_QFile::FILEReadWrite() // check modified file { QFile f("FILEReadWrite.txt"); - QVERIFY(f.open(QFile::ReadOnly)); + QVERIFY2(f.open(QFile::ReadOnly), msgOpenFailed(file).constData()); QDataStream ds(&f); qint8 c = 0; ds >> c; @@ -1928,14 +1981,14 @@ void tst_QFile::i18nFileName() } { QFile file(fileName); - QVERIFY(file.open(QFile::WriteOnly | QFile::Text)); + QVERIFY2(file.open(QFile::WriteOnly | QFile::Text), msgOpenFailed(file).constData()); QTextStream ts(&file); ts.setCodec("UTF-8"); ts << fileName << endl; } { QFile file(fileName); - QVERIFY(file.open(QFile::ReadOnly | QFile::Text)); + QVERIFY2(file.open(QFile::ReadOnly | QFile::Text), msgOpenFailed(file).constData()); QTextStream ts(&file); ts.setCodec("UTF-8"); QString line = ts.readLine(); @@ -1983,13 +2036,13 @@ void tst_QFile::longFileName() QEXPECT_FAIL("244 chars", "Full pathname must be less than 260 chars", Abort); QEXPECT_FAIL("244 chars to absolutepath", "Full pathname must be less than 260 chars", Abort); #endif - QVERIFY(file.open(QFile::WriteOnly | QFile::Text)); + QVERIFY2(file.open(QFile::WriteOnly | QFile::Text), msgOpenFailed(file).constData()); QTextStream ts(&file); ts << fileName << endl; } { QFile file(fileName); - QVERIFY(file.open(QFile::ReadOnly | QFile::Text)); + QVERIFY2(file.open(QFile::ReadOnly | QFile::Text), msgOpenFailed(file).constData()); QTextStream ts(&file); QString line = ts.readLine(); QCOMPARE(line, fileName); @@ -1998,7 +2051,7 @@ void tst_QFile::longFileName() { QVERIFY(QFile::copy(fileName, newName)); QFile file(newName); - QVERIFY(file.open(QFile::ReadOnly | QFile::Text)); + QVERIFY2(file.open(QFile::ReadOnly | QFile::Text), msgOpenFailed(file).constData()); QTextStream ts(&file); QString line = ts.readLine(); QCOMPARE(line, fileName); @@ -2008,12 +2061,12 @@ void tst_QFile::longFileName() { QVERIFY(QFile::rename(fileName, newName)); QFile file(newName); - QVERIFY(file.open(QFile::ReadOnly | QFile::Text)); + QVERIFY2(file.open(QFile::ReadOnly | QFile::Text), msgOpenFailed(file).constData()); QTextStream ts(&file); QString line = ts.readLine(); QCOMPARE(line, fileName); } - QVERIFY(QFile::exists(newName)); + QVERIFY2(QFile::exists(newName), msgFileDoesNotExist(newName).constData()); } #ifdef QT_BUILD_INTERNAL @@ -2146,7 +2199,7 @@ void tst_QFile::remove_and_exists() bool opened = f.open(QIODevice::WriteOnly); QVERIFY(opened); - f.write(QString("testing that remove/exists work...").toLatin1()); + f.write("testing that remove/exists work..."); f.close(); QVERIFY(f.exists()); @@ -2165,7 +2218,7 @@ void tst_QFile::removeOpenFile() QVERIFY(!f.exists()); bool opened = f.open(QIODevice::WriteOnly); QVERIFY(opened); - f.write(QString("testing that remove closes the file first...").toLatin1()); + f.write("testing that remove closes the file first..."); bool removed = f.remove(); // remove should both close and remove the file QVERIFY(removed); @@ -2184,7 +2237,7 @@ void tst_QFile::removeOpenFile() QVERIFY(!f.exists()); bool opened = f.open(QIODevice::WriteOnly); QVERIFY(opened); - f.write(QString("testing that remove closes the file first...").toLatin1()); + f.write("testing that remove closes the file first..."); f.close(); } @@ -2208,7 +2261,7 @@ void tst_QFile::fullDisk() if (!file.exists()) QSKIP("/dev/full doesn't exist on this system"); - QVERIFY(file.open(QIODevice::WriteOnly)); + QVERIFY2(file.open(QIODevice::WriteOnly), msgOpenFailed(file).constData()); file.write("foobar", 6); QVERIFY(!file.flush()); @@ -2235,7 +2288,7 @@ void tst_QFile::fullDisk() QCOMPARE(file.error(), QFile::NoError); // try again without flush: - QVERIFY(file.open(QIODevice::WriteOnly)); + QVERIFY2(file.open(QIODevice::WriteOnly), msgOpenFailed(file).constData()); file.write("foobar", 6); file.close(); QVERIFY(file.error() != QFile::NoError); @@ -2288,8 +2341,7 @@ void tst_QFile::writeLargeDataBlock() { QFile file(fileName); - QVERIFY2( openFile(file, QIODevice::WriteOnly, (FileType)type), - qPrintable(QString("Couldn't open file for writing: [%1]").arg(fileName)) ); + QVERIFY2(openFile(file, QIODevice::WriteOnly, (FileType)type), msgOpenFailed(file)); qint64 fileWriteOriginalData = file.write(originalData); qint64 originalDataSize = (qint64)originalData.size(); #if defined(Q_OS_WIN) @@ -2332,7 +2384,7 @@ void tst_QFile::writeLargeDataBlock() void tst_QFile::readFromWriteOnlyFile() { QFile file("writeonlyfile"); - QVERIFY(file.open(QFile::WriteOnly)); + QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData()); char c; QTest::ignoreMessage(QtWarningMsg, "QIODevice::read (QFile, \"writeonlyfile\"): WriteOnly device"); QCOMPARE(file.read(&c, 1), qint64(-1)); @@ -2341,7 +2393,7 @@ void tst_QFile::readFromWriteOnlyFile() void tst_QFile::writeToReadOnlyFile() { QFile file("readonlyfile"); - QVERIFY(file.open(QFile::ReadOnly)); + QVERIFY2(file.open(QFile::ReadOnly), msgOpenFailed(file).constData()); char c = 0; QTest::ignoreMessage(QtWarningMsg, "QIODevice::write (QFile, \"readonlyfile\"): ReadOnly device"); QCOMPARE(file.write(&c, 1), qint64(-1)); @@ -2363,13 +2415,13 @@ void tst_QFile::virtualFile() // consistency check QFileInfo fi(fname); - QVERIFY(fi.exists()); + QVERIFY2(fi.exists(), msgFileDoesNotExist(fname).constData()); QVERIFY(fi.isFile()); QCOMPARE(fi.size(), Q_INT64_C(0)); // open the file QFile f(fname); - QVERIFY(f.open(QIODevice::ReadOnly)); + QVERIFY2(f.open(QIODevice::ReadOnly), msgOpenFailed(f).constData()); QCOMPARE(f.size(), Q_INT64_C(0)); QVERIFY(f.atEnd()); @@ -2413,7 +2465,7 @@ void tst_QFile::textFile() ::fclose(fs); QFile file("writeabletextfile"); - QVERIFY(file.open(QIODevice::ReadOnly)); + QVERIFY2(file.open(QIODevice::ReadOnly), msgOpenFailed(file).constData()); QByteArray data = file.readAll(); @@ -2543,8 +2595,8 @@ void tst_QFile::renameMultiple() // create the file if it doesn't exist QFile file("file-to-be-renamed.txt"); QFile file2("existing-file.txt"); - QVERIFY(file.open(QIODevice::ReadWrite) && "(test-precondition)"); - QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)"); + QVERIFY2(file.open(QIODevice::ReadWrite), msgOpenFailed(file).constData()); + QVERIFY2(file2.open(QIODevice::ReadWrite), msgOpenFailed(file2).constData()); // any stale files from previous test failures? QFile::remove("file-renamed-once.txt"); @@ -2583,10 +2635,10 @@ void tst_QFile::renameMultiple() void tst_QFile::appendAndRead() { QFile writeFile(QLatin1String("appendfile.txt")); - QVERIFY(writeFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); + QVERIFY2(writeFile.open(QIODevice::WriteOnly | QIODevice::Truncate), msgOpenFailed(writeFile).constData()); QFile readFile(QLatin1String("appendfile.txt")); - QVERIFY(readFile.open(QIODevice::ReadOnly)); + QVERIFY2(readFile.open(QIODevice::ReadOnly), msgOpenFailed(readFile).constData()); // Write to the end of the file, then read that character back, and so on. for (int i = 0; i < 100; ++i) { @@ -2612,11 +2664,13 @@ void tst_QFile::miscWithUncPathAsCurrentDir() { #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QString current = QDir::currentPath(); - QVERIFY(QDir::setCurrent("//" + QtNetworkSettings::winServerName() + "/testshare")); + const QString path = QLatin1String("//") + QtNetworkSettings::winServerName() + + QLatin1String("/testshare"); + QVERIFY2(QDir::setCurrent(path), qPrintable(QDir::toNativeSeparators(path))); QFile file("test.pri"); - QVERIFY(file.exists()); + QVERIFY2(file.exists(), msgFileDoesNotExist(file.fileName()).constData()); QCOMPARE(int(file.size()), 34); - QVERIFY(file.open(QIODevice::ReadOnly)); + QVERIFY2(file.open(QIODevice::ReadOnly), msgOpenFailed(file).constData()); QVERIFY(QDir::setCurrent(current)); #endif } @@ -2634,7 +2688,7 @@ void tst_QFile::handle() int fd; #if !defined(Q_OS_WINCE) QFile file(m_testSourceFile); - QVERIFY(file.open(QIODevice::ReadOnly)); + QVERIFY2(file.open(QIODevice::ReadOnly), msgOpenFailed(file).constData()); fd = int(file.handle()); QVERIFY(fd > 2); QCOMPARE(int(file.handle()), fd); @@ -2648,7 +2702,7 @@ void tst_QFile::handle() // same, but read from QFile first now file.close(); - QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)); + QVERIFY2(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered), msgOpenFailed(file).constData()); fd = int(file.handle()); QVERIFY(fd > 2); QVERIFY(file.getChar(&c)); @@ -2690,7 +2744,7 @@ void tst_QFile::nativeHandleLeaks() { QFile file("qt_file.tmp"); - QVERIFY( file.open(QIODevice::ReadWrite) ); + QVERIFY2(file.open(QIODevice::ReadWrite), msgOpenFailed(file).constData()); fd1 = file.handle(); QVERIFY( -1 != fd1 ); @@ -2709,7 +2763,7 @@ void tst_QFile::nativeHandleLeaks() { QFile file("qt_file.tmp"); - QVERIFY( file.open(QIODevice::ReadOnly) ); + QVERIFY2(file.open(QIODevice::ReadOnly), msgOpenFailed(file).constData()); fd2 = file.handle(); QVERIFY( -1 != fd2 ); @@ -2755,7 +2809,7 @@ void tst_QFile::readEof() { QFile file(filename); - QVERIFY(file.open(QIODevice::ReadOnly | mode)); + QVERIFY2(file.open(QIODevice::ReadOnly | mode), msgOpenFailed(file).constData()); bool isSequential = file.isSequential(); if (!isSequential) { QVERIFY(file.seek(245)); @@ -2777,7 +2831,7 @@ void tst_QFile::readEof() { QFile file(filename); - QVERIFY(file.open(QIODevice::ReadOnly | mode)); + QVERIFY2(file.open(QIODevice::ReadOnly | mode), msgOpenFailed(file).constData()); bool isSequential = file.isSequential(); if (!isSequential) { QVERIFY(file.seek(245)); @@ -2798,7 +2852,7 @@ void tst_QFile::readEof() { QFile file(filename); - QVERIFY(file.open(QIODevice::ReadOnly | mode)); + QVERIFY2(file.open(QIODevice::ReadOnly | mode), msgOpenFailed(file).constData()); bool isSequential = file.isSequential(); if (!isSequential) { QVERIFY(file.seek(245)); @@ -2820,7 +2874,7 @@ void tst_QFile::readEof() { QFile file(filename); - QVERIFY(file.open(QIODevice::ReadOnly | mode)); + QVERIFY2(file.open(QIODevice::ReadOnly | mode), msgOpenFailed(file).constData()); bool isSequential = file.isSequential(); if (!isSequential) { QVERIFY(file.seek(245)); @@ -2841,7 +2895,7 @@ void tst_QFile::readEof() { QFile file(filename); - QVERIFY(file.open(QIODevice::ReadOnly | mode)); + QVERIFY2(file.open(QIODevice::ReadOnly | mode), msgOpenFailed(file).constData()); bool isSequential = file.isSequential(); if (!isSequential) { QVERIFY(file.seek(245)); @@ -2867,7 +2921,7 @@ void tst_QFile::posAfterFailedStat() QFile::remove("tmp.txt"); QFile file("tmp.txt"); QVERIFY(!file.exists()); - QVERIFY(file.open(QIODevice::Append)); + QVERIFY2(file.open(QIODevice::Append), msgOpenFailed(file).constData()); QVERIFY(file.exists()); file.write("qt430", 5); QVERIFY(!file.isSequential()); @@ -2922,11 +2976,11 @@ void tst_QFile::map() QCOMPARE(file.error(), QFile::PermissionsError); // make a file - QVERIFY(file.open(QFile::ReadWrite)); + QVERIFY2(file.open(QFile::ReadWrite), msgOpenFailed(file).constData()); QVERIFY(file.resize(fileSize)); QVERIFY(file.flush()); file.close(); - QVERIFY(file.open(QFile::ReadWrite)); + QVERIFY2(file.open(QFile::ReadWrite), msgOpenFailed(file).constData()); memory = file.map(offset, size); if (error != QFile::NoError) { QVERIFY(file.error() != QFile::NoError); @@ -3061,13 +3115,14 @@ void tst_QFile::mapOpenMode() QFile file(fileName); // make a file - QVERIFY(file.open(QFile::ReadWrite)); + QVERIFY2(file.open(QFile::ReadWrite), msgOpenFailed(file).constData()); QVERIFY(file.write(pattern)); QVERIFY(file.flush()); file.close(); // open according to our mode - QVERIFY(file.open(QIODevice::OpenMode(openMode))); + const QIODevice::OpenMode om(openMode); + QVERIFY2(file.open(om), msgOpenFailed(om, file).constData()); uchar *memory = file.map(0, fileSize, QFileDevice::MemoryMapFlags(flags)); #if defined(Q_OS_WINCE) @@ -3116,7 +3171,8 @@ void tst_QFile::mapWrittenFile() QFile::remove(fileName); } QFile file(fileName); - QVERIFY(file.open(QIODevice::ReadWrite | QFile::OpenMode(mode))); + const QIODevice::OpenMode om = QIODevice::ReadWrite | QIODevice::OpenMode(mode); + QVERIFY2(file.open(om), msgOpenFailed(om, file).constData()); QCOMPARE(file.write(data, sizeof data), qint64(sizeof data)); if ((mode & QIODevice::Unbuffered) == 0) file.flush(); @@ -3328,7 +3384,7 @@ void tst_QFile::caseSensitivity() QString filename("File.txt"); { QFile f(filename); - QVERIFY(f.open(QIODevice::WriteOnly)); + QVERIFY2(f.open(QIODevice::WriteOnly), msgOpenFailed(f)); QVERIFY(f.write(testData)); f.close(); } From 1d6643895dbcf8b720cbf85103032839fae4aa09 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 24 Sep 2015 12:37:57 +0200 Subject: [PATCH 128/240] Moved a comment to where it belongs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There was another function between the comment and the one it documented. Change-Id: I4e96979261738b1ef264984da0d6a8245f2fb643 Reviewed-by: Jędrzej Nowacki Reviewed-by: Oswald Buddenhagen --- src/corelib/thread/qfuturewatcher.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/corelib/thread/qfuturewatcher.cpp b/src/corelib/thread/qfuturewatcher.cpp index 3863a47673..43eff83116 100644 --- a/src/corelib/thread/qfuturewatcher.cpp +++ b/src/corelib/thread/qfuturewatcher.cpp @@ -304,15 +304,6 @@ void QFutureWatcherBase::waitForFinished() futureInterface().waitForFinished(); } -/*! \fn void QFutureWatcher::setPendingResultsLimit(int limit) - - The setPendingResultsLimit() provides throttling control. When the number - of pending resultReadyAt() or resultsReadyAt() signals exceeds the - \a limit, the computation represented by the future will be throttled - automatically. The computation will resume once the number of pending - signals drops below the \a limit. -*/ - bool QFutureWatcherBase::event(QEvent *event) { Q_D(QFutureWatcherBase); @@ -342,6 +333,14 @@ bool QFutureWatcherBase::event(QEvent *event) return QObject::event(event); } +/*! \fn void QFutureWatcher::setPendingResultsLimit(int limit) + + The setPendingResultsLimit() provides throttling control. When the number + of pending resultReadyAt() or resultsReadyAt() signals exceeds the + \a limit, the computation represented by the future will be throttled + automatically. The computation will resume once the number of pending + signals drops below the \a limit. +*/ void QFutureWatcherBase::setPendingResultsLimit(int limit) { Q_D(QFutureWatcherBase); From e4d736b6deedfd1e805421beac29e024989dce95 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 28 Sep 2015 16:22:52 +0200 Subject: [PATCH 129/240] Fix a #! first line. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An executable .sh file should have its #! be the first two bytes. Change-Id: I22c9eee6d349df743b02996bef0e093df3f42eb5 Reviewed-by: Frederik Gladhorn Reviewed-by: Jędrzej Nowacki --- util/unicode/writingSystems.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/unicode/writingSystems.sh b/util/unicode/writingSystems.sh index 8902d97d71..5783fe7797 100755 --- a/util/unicode/writingSystems.sh +++ b/util/unicode/writingSystems.sh @@ -1,5 +1,5 @@ - #!/bin/sh + ############################################################################# ## ## Copyright (C) 2015 The Qt Company Ltd. From 2c5126b9dec0c4997fd5b21f065f4152910633fe Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 28 Sep 2015 15:37:45 +0200 Subject: [PATCH 130/240] Purge extraneous execute permissions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Source files should not be executable. Change-Id: If9b9eaa6c8c7348ca6f48fa9253f3540e95aca37 Reviewed-by: Oswald Buddenhagen Reviewed-by: Frederik Gladhorn Reviewed-by: Jędrzej Nowacki --- src/3rdparty/angle/include/KHR/khrplatform.h | 0 src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 0 src/corelib/tools/qalgorithms.qdoc | 0 tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/3rdparty/angle/include/KHR/khrplatform.h mode change 100755 => 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp mode change 100755 => 100644 src/corelib/tools/qalgorithms.qdoc mode change 100755 => 100644 tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h old mode 100755 new mode 100644 diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp old mode 100755 new mode 100644 diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc old mode 100755 new mode 100644 diff --git a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp old mode 100755 new mode 100644 From 4b785eeaa9c46fadea6df65cadd7a8d4c1d7d272 Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Thu, 1 Oct 2015 08:37:47 +0300 Subject: [PATCH 131/240] Clean up debug code and unused functions from imagegestures example Change-Id: I0dbbb5c6f3227e8cfe3e0f6eb27b2bf16b5d222b Reviewed-by: Friedemann Kleint --- examples/widgets/gestures/imagegestures/imagewidget.cpp | 1 - examples/widgets/gestures/imagegestures/imagewidget.h | 1 - examples/widgets/gestures/imagegestures/mainwidget.h | 2 -- 3 files changed, 4 deletions(-) diff --git a/examples/widgets/gestures/imagegestures/imagewidget.cpp b/examples/widgets/gestures/imagegestures/imagewidget.cpp index 440eb783c1..104095e8fe 100644 --- a/examples/widgets/gestures/imagegestures/imagewidget.cpp +++ b/examples/widgets/gestures/imagegestures/imagewidget.cpp @@ -200,7 +200,6 @@ void ImageWidget::openDirectory(const QString &path) QImage ImageWidget::loadImage(const QString &fileName) { - qDebug() << position << files << fileName; QImageReader reader(fileName); reader.setAutoTransform(true); qCDebug(lcExample) << "loading" << QDir::toNativeSeparators(fileName) << position << '/' << files.size(); diff --git a/examples/widgets/gestures/imagegestures/imagewidget.h b/examples/widgets/gestures/imagegestures/imagewidget.h index 1629516c0a..71ad2792d0 100644 --- a/examples/widgets/gestures/imagegestures/imagewidget.h +++ b/examples/widgets/gestures/imagegestures/imagewidget.h @@ -77,7 +77,6 @@ private: void swipeTriggered(QSwipeGesture*); //! [class definition begin] - void updateImage(); QImage loadImage(const QString &fileName); void loadImage(); void goNextImage(); diff --git a/examples/widgets/gestures/imagegestures/mainwidget.h b/examples/widgets/gestures/imagegestures/mainwidget.h index 20e32d1afb..e37baa398c 100644 --- a/examples/widgets/gestures/imagegestures/mainwidget.h +++ b/examples/widgets/gestures/imagegestures/mainwidget.h @@ -57,8 +57,6 @@ public slots: void openDirectory(const QString &path); private: - bool loadImage(const QString &fileName); - ImageWidget *imageWidget; }; From e8dcd5038d8a6ee73f3efdd6fe5fbe276684feec Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 28 Sep 2015 20:19:36 +0200 Subject: [PATCH 132/240] "frame" execution of config tests precisely the purpose is to make build log parsers able to ignore build failures in verbose configure output. Change-Id: I01af2e019fd1b055fdfcf6749faeebacb7a39c3f Reviewed-by: Frederik Gladhorn Reviewed-by: Thiago Macieira --- configure | 8 +++++++- tools/configure/configureapp.cpp | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 1b7655d280..4ca3187238 100755 --- a/configure +++ b/configure @@ -3339,6 +3339,8 @@ fi # tests that don't need qmake (must be run before displaying help) #------------------------------------------------------------------------------- +echo "Running configuration tests (phase 1)..." + # detect build style if [ "$CFG_DEBUG" = "auto" ]; then if [ "$XPLATFORM_MAC" = "yes" -o "$XPLATFORM_MINGW" = "yes" ]; then @@ -3611,6 +3613,8 @@ unset tty eval "`LC_ALL=C $TEST_COMPILER $SYSROOT_FLAG $TEST_COMPILER_CXXFLAGS -xc++ -E -v - < /dev/null 2>&1 > /dev/null | $AWK "$awkprog" | tee $tty`" unset tty +echo "Done running configuration tests." + #setup the build parts if [ -z "$CFG_BUILD_PARTS" ]; then CFG_BUILD_PARTS="$QT_DEFAULT_BUILD_PARTS" @@ -4112,7 +4116,7 @@ if true; then ###[ '!' -f "$outpath/bin/qmake" ]; fi fi # Build qmake -echo "Running configuration tests..." +echo "Running configuration tests (phase 2)..." #------------------------------------------------------------------------------- # create a qt.conf for the Qt build tree itself @@ -6641,6 +6645,8 @@ s/icpc version \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\) .*$/QT_ICC_MAJOR_VERSION=\1; Q ;; esac +echo "Done running configuration tests." + #------------------------------------------------------------------------------- # part of configuration information goes into qconfig.h #------------------------------------------------------------------------------- diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index f955a8de2e..17f19361f7 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -2577,6 +2577,8 @@ void Configure::autoDetection() dictionary["QT_POINTER_SIZE"] = "8"; else dictionary["QT_POINTER_SIZE"] = "4"; + + cout << "Done running configuration tests." << endl; } bool Configure::verifyConfiguration() From 939dc7765665799f3db6ebeb167ea0ba86ccb0ce Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 23 Sep 2015 18:36:08 +0200 Subject: [PATCH 133/240] more accurate check for presence of target INSTALL make it match qmake's own rules. Change-Id: Ia6b9ac12ac08932ac67f100f4638352a214553bd Reviewed-by: Joerg Bornemann --- mkspecs/features/qt.prf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 2e466ec9be..367e3799ef 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -161,7 +161,8 @@ qt_module_deps = $$resolve_depends(qt_module_deps, "QT.") !no_qt_rpath:!static:contains(QT_CONFIG, rpath):!contains(QT_CONFIG, static):\ contains(qt_module_deps, core) { - relative_qt_rpath:defined(target.path, var) { + relative_qt_rpath:contains(INSTALLS, target):\ + isEmpty(target.files):isEmpty(target.commands):isEmpty(target.extra) { mac { if(equals(TEMPLATE, app):app_bundle)|\ if(equals(TEMPLATE, lib):plugin:plugin_bundle) { From 1ebce824c4d5d30fbc54ce553ba8d109a68e04c2 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 30 Sep 2015 11:05:23 +0200 Subject: [PATCH 134/240] fix place of "qnx" in $$QMAKE_PLATFORM it must come first, as it is most specific. an alternative fix would be re-organizing the includes, but that requires a lot more effort to get right. Change-Id: I1526a3c966f3dc3f3df1efc00ec271d333ed7ebf Reviewed-by: Joerg Bornemann --- mkspecs/common/qcc-base-qnx.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/common/qcc-base-qnx.conf b/mkspecs/common/qcc-base-qnx.conf index dbbf346ea2..156ba0ddd8 100644 --- a/mkspecs/common/qcc-base-qnx.conf +++ b/mkspecs/common/qcc-base-qnx.conf @@ -4,7 +4,7 @@ include(qcc-base.conf) -QMAKE_PLATFORM += qnx +QMAKE_PLATFORM = qnx $$QMAKE_PLATFORM #Choose qnx QPA Plugin as default QT_QPA_DEFAULT_PLATFORM = qnx From be6758a4de9ec9d51adf17d256de2f69edecdb00 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 23 Sep 2015 18:29:02 +0200 Subject: [PATCH 135/240] omit trailing /. from relative RPATHs pointing to own directory Change-Id: Ia4551f5b16f4e66c7ab7fdec82643d9cd8866ccd Reviewed-by: Joerg Bornemann --- mkspecs/features/qt.prf | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 367e3799ef..a8d317a0e3 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -173,11 +173,17 @@ qt_module_deps = $$resolve_depends(qt_module_deps, "QT.") } else { binpath = $$target.path } - QMAKE_RPATHDIR += @loader_path/$$relative_path($$[QT_INSTALL_LIBS], $$binpath) + rpath = @loader_path } else { QMAKE_LFLAGS += -Wl,-z,origin - QMAKE_RPATHDIR += $ORIGIN/$$relative_path($$[QT_INSTALL_LIBS], $$target.path) + binpath = $$target.path + rpath = $ORIGIN } + # NOT the /dev property, as INSTALLS use host paths + relpath = $$relative_path($$[QT_INSTALL_LIBS], $$binpath) + !equals(relpath, .): \ + rpath = $$rpath/$$relpath + QMAKE_RPATHDIR += $$rpath } else { QMAKE_RPATHDIR += $$[QT_INSTALL_LIBS/dev] } From a75995124d2aedf7f8a85407eb5c3c8532fc9ea0 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 22 Sep 2015 16:36:03 +0200 Subject: [PATCH 136/240] fix configure bootstrap on mingw with spaces in the builddir the missing quotes would cause us to misdetect mingw as msys. Change-Id: I408c0e6bfc3cbfecd02c54904cf96ab79e0b6d88 Reviewed-by: Joerg Bornemann --- tools/configure/Makefile.mingw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/configure/Makefile.mingw b/tools/configure/Makefile.mingw index 539664e7d6..f4513c64d6 100644 --- a/tools/configure/Makefile.mingw +++ b/tools/configure/Makefile.mingw @@ -89,7 +89,7 @@ $(OBJECTS): $(PCH) # sh-compatible shell. This is not a problem, because configure.bat # will not do that. ifeq ($(SHELL), sh.exe) - ifeq ($(wildcard $(CURDIR)/sh.exe), ) + ifeq ($(wildcard "$(CURDIR)/sh.exe"), ) SH = 0 else SH = 1 From 8e3e0897634a7c0531c789a5598b7fb3070eb306 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 22 Sep 2015 17:11:37 +0200 Subject: [PATCH 137/240] don't overquote library path Change-Id: I33b91141c79cacd1a46299754937c81a31e665c9 Reviewed-by: Joerg Bornemann --- src/angle/src/common/common.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri index 8e2333d2ba..50dde6398b 100644 --- a/src/angle/src/common/common.pri +++ b/src/angle/src/common/common.pri @@ -44,7 +44,7 @@ winrt|if(msvc:!win32-msvc2005:!win32-msvc2008:!win32-msvc2010) { # Similarly we want the MinGW linker to use the import libraries shipped with the compiler # instead of those from the SDK which cause a crash on startup. - LIBS_PRIVATE += -L\"$$DXLIB_DIR\" + LIBS_PRIVATE += -L$$DXLIB_DIR } } From e88334e013412780daf06fd813896483bbc0991e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 23 Jun 2015 20:12:03 +0200 Subject: [PATCH 138/240] don't support arbitrary flags in LIBS on windows there should be no flags other than /LIBPATH: in LIBS (and the variables that end up in it) - these belong into QMAKE_LFLAGS. while not very important, this change enables the use of drive-relative paths using unix path separators. note that on unix, arbitrary flags must be supported in LIBS due to GNU ld's --push-state and related position-dependent flags (-whole-archive in particular). luckily, on unix, flags start with a dash, not a slash. Started-by: Dyami Caliri Change-Id: Ie5764f14d34ad13020ca010499594eed8c69a4a1 Reviewed-by: Joerg Bornemann --- qmake/generators/win32/winmakefile.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 0d761b08a2..8a41bb7c1e 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -98,13 +98,10 @@ Win32MakefileGenerator::findHighestVersion(const QString &d, const QString &stem ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib) { - if (lib.startsWith('/')) { - if (lib.startsWith("/LIBPATH:")) - return QLatin1String("/LIBPATH:") - + escapeFilePath(Option::fixPathToTargetOS(lib.mid(9).toQString(), false)); - // This appears to be a user-supplied flag. Assume sufficient quoting. - return lib; - } + if (lib.startsWith("/LIBPATH:")) + return QLatin1String("/LIBPATH:") + + escapeFilePath(Option::fixPathToTargetOS(lib.mid(9).toQString(), false)); + // This must be a fully resolved library path. return escapeFilePath(Option::fixPathToTargetOS(lib.toQString(), false)); } @@ -218,7 +215,7 @@ Win32MakefileGenerator::processPrlFiles() QMakeLocalFileName l(opt.mid(libArg.length())); if (!libdirs.contains(l)) libdirs.append(l); - } else if (!opt.startsWith("/")) { + } else { if (!processPrlFile(opt) && (QDir::isRelativePath(opt) || opt.startsWith("-l"))) { QString tmp; if (opt.startsWith("-l")) From 34a967abc9253742220409ab6d9e5713a473eb0a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 24 Jun 2015 17:59:55 +0200 Subject: [PATCH 139/240] de-duplicate calculation of target base Change-Id: I546fe454f925dd9ad39ba444fa78455c8dbdfde6 Reviewed-by: Joerg Bornemann --- qmake/generators/win32/msvc_nmake.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 7646198da1..2d2a5af8ca 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -419,21 +419,22 @@ void NmakeMakefileGenerator::init() project->values("PRECOMPILED_PCH") = ProStringList(precompPch); } - ProString version = project->first("TARGET_VERSION_EXT"); + ProString tgt = project->first("DESTDIR") + + project->first("TARGET") + project->first("TARGET_VERSION_EXT"); if(project->isActiveConfig("shared")) { - project->values("QMAKE_CLEAN").append(project->first("DESTDIR") + project->first("TARGET") + version + ".exp"); - project->values("QMAKE_DISTCLEAN").append(project->first("DESTDIR") + project->first("TARGET") + version + ".lib"); + project->values("QMAKE_CLEAN").append(tgt + ".exp"); + project->values("QMAKE_DISTCLEAN").append(tgt + ".lib"); } if (project->isActiveConfig("debug_info")) { - QString pdbfile = project->first("DESTDIR") + project->first("TARGET") + version + ".pdb"; + QString pdbfile = tgt + ".pdb"; QString escapedPdbFile = escapeFilePath(pdbfile); project->values("QMAKE_CFLAGS").append("/Fd" + escapedPdbFile); project->values("QMAKE_CXXFLAGS").append("/Fd" + escapedPdbFile); project->values("QMAKE_DISTCLEAN").append(pdbfile); } if (project->isActiveConfig("debug")) { - project->values("QMAKE_CLEAN").append(project->first("DESTDIR") + project->first("TARGET") + version + ".ilk"); - project->values("QMAKE_CLEAN").append(project->first("DESTDIR") + project->first("TARGET") + version + ".idb"); + project->values("QMAKE_CLEAN").append(tgt + ".ilk"); + project->values("QMAKE_CLEAN").append(tgt + ".idb"); } else { ProStringList &defines = project->values("DEFINES"); if (!defines.contains("NDEBUG")) From c111e1553ea12c7bb6e9575e1adfb2893a6c1bf9 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 22 May 2015 12:07:49 +0200 Subject: [PATCH 140/240] remove overuse of trimmed() there is no reason to expect the various list elements to be space-encumbered, or to tolerate it if they were. Change-Id: I1a2e5c8d30456b640408503334c55f9262792db5 Reviewed-by: Joerg Bornemann --- qmake/generators/mac/pbuilder_pbx.cpp | 2 +- qmake/generators/unix/unixmake.cpp | 9 ++++----- qmake/generators/win32/msvc_objectmodel.cpp | 2 +- qmake/generators/win32/winmakefile.cpp | 6 +++--- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 7ff1d97b16..bfe9f08e77 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -816,7 +816,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) for(int x = 0; x < tmp.count();) { bool remove = false; QString library, name; - ProString opt = tmp[x].trimmed(); + ProString opt = tmp[x]; if(opt.startsWith("-L")) { QString r = opt.mid(2).toQString(); fixForOutput(r); diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 03196fbc3a..8fc4d6daef 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -448,7 +448,7 @@ UnixMakefileGenerator::findLibraries() for (int i = 0; lflags[i]; i++) { ProStringList &l = project->values(lflags[i]); for (ProStringList::Iterator it = l.begin(); it != l.end(); ) { - QString stub, dir, extn, opt = (*it).trimmed().toQString(); + QString stub, dir, extn, opt = (*it).toQString(); if(opt.startsWith("-")) { if(opt.startsWith("-L")) { QString lib = opt.mid(2); @@ -555,7 +555,7 @@ UnixMakefileGenerator::processPrlFiles() for (int i = 0; lflags[i]; i++) { ProStringList &l = project->values(lflags[i]); for(int lit = 0; lit < l.size(); ++lit) { - QString opt = l.at(lit).trimmed().toQString(); + QString opt = l.at(lit).toQString(); if(opt.startsWith("-")) { if (opt.startsWith(libArg)) { QMakeLocalFileName l(opt.mid(libArg.length())); @@ -589,10 +589,9 @@ UnixMakefileGenerator::processPrlFiles() frameworkdirs.insert(fwidx++, f); } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-framework")) { if(opt.length() > 11) - opt = opt.mid(11); + opt = opt.mid(11).trimmed(); else opt = l.at(++lit).toQString(); - opt = opt.trimmed(); foreach (const QMakeLocalFileName &dir, frameworkdirs) { QString prl = dir.local() + "/" + opt + ".framework/" + opt + Option::prl_ext; if(processPrlFile(prl)) @@ -624,7 +623,7 @@ UnixMakefileGenerator::processPrlFiles() QHash lflags; for(int lit = 0; lit < l.size(); ++lit) { ProKey arch("default"); - ProString opt = l.at(lit).trimmed(); + ProString opt = l.at(lit); if(opt.startsWith("-")) { if (target_mode == TARG_MAC_MODE && opt.startsWith("-Xarch")) { if (opt.length() > 7) { diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 09937c8ac2..11e93e54c2 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -2412,7 +2412,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) // Make sure that all deps are only once QStringList uniqDeps; for (int c = 0; c < deps.count(); ++c) { - QString aDep = deps.at(c).trimmed(); + QString aDep = deps.at(c); if (!aDep.isEmpty()) uniqDeps << aDep; } diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 8a41bb7c1e..55da3d579e 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -115,7 +115,7 @@ Win32MakefileGenerator::findLibraries() ProStringList &l = project->values(lflags[i]); for (ProStringList::Iterator it = l.begin(); it != l.end();) { bool remove = false; - QString opt = (*it).trimmed().toQString(); + QString opt = (*it).toQString(); if(opt.startsWith("/LIBPATH:")) { QString libpath = opt.mid(9); QMakeLocalFileName l(libpath); @@ -210,7 +210,7 @@ Win32MakefileGenerator::processPrlFiles() for (int i = 0; lflags[i]; i++) { ProStringList &l = project->values(lflags[i]); for (int lit = 0; lit < l.size(); ++lit) { - QString opt = l.at(lit).trimmed().toQString(); + QString opt = l.at(lit).toQString(); if (opt.startsWith(libArg)) { QMakeLocalFileName l(opt.mid(libArg.length())); if (!libdirs.contains(l)) @@ -239,7 +239,7 @@ Win32MakefileGenerator::processPrlFiles() if (!project->isActiveConfig("no_smart_library_merge") && !project->isActiveConfig("no_lflags_merge")) { ProStringList lflags; for (int lit = 0; lit < l.size(); ++lit) { - ProString opt = l.at(lit).trimmed(); + ProString opt = l.at(lit); if (opt.startsWith(libArg)) { if (!lflags.contains(opt)) lflags.append(opt); From 7ab9b0d847946ad75d8c1b94edae781974598aff Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 1 Jun 2015 15:07:01 +0200 Subject: [PATCH 141/240] remove unsupported linux-armcc spec it was experimentally added in 2011. there is no evidence that anyone actually uses it. Change-Id: Ie3b131f3783cafe942d180b2623fcc64740d7a73 Reviewed-by: Joerg Bornemann --- mkspecs/common/armcc.conf | 44 --------- mkspecs/unsupported/linux-armcc/qmake.conf | 29 ------ .../unsupported/linux-armcc/qplatformdefs.h | 92 ------------------- 3 files changed, 165 deletions(-) delete mode 100644 mkspecs/common/armcc.conf delete mode 100644 mkspecs/unsupported/linux-armcc/qmake.conf delete mode 100644 mkspecs/unsupported/linux-armcc/qplatformdefs.h diff --git a/mkspecs/common/armcc.conf b/mkspecs/common/armcc.conf deleted file mode 100644 index a52fefc106..0000000000 --- a/mkspecs/common/armcc.conf +++ /dev/null @@ -1,44 +0,0 @@ -# -# qmake configuration for armcc -# - -QMAKE_COMPILER = armcc - -CONFIG += rvct_linker -QMAKE_CC = armcc -QMAKE_CFLAGS += -QMAKE_CFLAGS_DEPS += -M -QMAKE_CFLAGS_WARN_ON += -QMAKE_CFLAGS_WARN_OFF += -W -QMAKE_CFLAGS_RELEASE += -O2 -QMAKE_CFLAGS_DEBUG += -g -O0 -QMAKE_CFLAGS_HIDESYMS += --visibility_inlines_hidden - -QMAKE_CXX = armcc -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS --exceptions --exceptions_unwind -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_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS - -QMAKE_LINK = armlink -QMAKE_LINK_SHLIB = armlink -QMAKE_LINK_C = armlink -QMAKE_LINK_C_SHLIB = armlink -QMAKE_LFLAGS += -QMAKE_LFLAGS_RELEASE += -QMAKE_LFLAGS_DEBUG += -QMAKE_LFLAGS_APP += -QMAKE_LFLAGS_SHLIB += -QMAKE_LFLAGS_PLUGIN += $$QMAKE_LFLAGS_SHLIB -QMAKE_LFLAGS_THREAD += - -QMAKE_AR = armar --create -QMAKE_LIB = armar --create -QMAKE_RANLIB = - diff --git a/mkspecs/unsupported/linux-armcc/qmake.conf b/mkspecs/unsupported/linux-armcc/qmake.conf deleted file mode 100644 index 2c7eb7c2d8..0000000000 --- a/mkspecs/unsupported/linux-armcc/qmake.conf +++ /dev/null @@ -1,29 +0,0 @@ -# -# qmake configuration for linux-armcc -# - -MAKEFILE_GENERATOR = UNIX -CONFIG += incremental armcc_linker -QMAKE_INCREMENTAL_STYLE = sublib - -include(../../common/linux.conf) -include(../../common/armcc.conf) -load(qt_config) - -# use armcc for linking since armlink doesn't understand the arm_linux_config_file option -QMAKE_LINK = armcc -QMAKE_LINK_SHLIB = armcc -QMAKE_LINK_C = armcc -QMAKE_LINK_C_SHLIB = armcc - -QMAKE_LFLAGS_SHLIB += --apcs=/fpic --shared -QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB - -QMAKE_LIBS += libstdc++.so librt.so - -CONFIG -= rvct_linker - -QMAKE_CFLAGS += --gnu --arm_linux --dllimport_runtime --thumb --cpu Cortex-A9 --arm_linux_config_file="$(HOME)/qt_rvct_config" --arm-linux-paths --apcs=/interwork --visibility_inlines_hidden --diag_suppress 1300,2523 -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS --cpp - -QMAKE_LFLAGS += --diag_suppress 6331,6780,6439 --arm_linux_config_file="$(HOME)/qt_rvct_config" --arm-linux-paths diff --git a/mkspecs/unsupported/linux-armcc/qplatformdefs.h b/mkspecs/unsupported/linux-armcc/qplatformdefs.h deleted file mode 100644 index 946b4d2b90..0000000000 --- a/mkspecs/unsupported/linux-armcc/qplatformdefs.h +++ /dev/null @@ -1,92 +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$ -** -****************************************************************************/ - -#ifndef QPLATFORMDEFS_H -#define QPLATFORMDEFS_H - -// Get Qt defines/settings - -#include "qglobal.h" - -// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs - -// 1) need to reset default environment if _BSD_SOURCE is defined -// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0 -// 3) it seems older glibc need this to include the X/Open stuff -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include - - -// We are hot - unistd.h should have turned on the specific APIs we requested - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef QT_NO_IPV6IFNAME -#include -#endif - -#define QT_USE_XOPEN_LFS_EXTENSIONS -#include "../../common/posix/qplatformdefs.h" - -#undef QT_SOCKLEN_T - -#if defined(__GLIBC__) && (__GLIBC__ >= 2) -#define QT_SOCKLEN_T socklen_t -#else -#define QT_SOCKLEN_T int -#endif - -#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) -#define QT_SNPRINTF ::snprintf -#define QT_VSNPRINTF ::vsnprintf -#endif - -#endif // QPLATFORMDEFS_H From 6c4d7667e46f008eebc60a74f04ae47f2baf4a81 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 1 Jun 2015 15:02:25 +0200 Subject: [PATCH 142/240] remove support for {rvct,arm,ti}_linker rvct and armcc support are remnants from symbian, while the ti linker support was never completed in the first place. Change-Id: I5c9d7f0ce67de24c348cbee4af618a499fe06f16 Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake.cpp | 25 +++----------- qmake/generators/win32/mingw_make.cpp | 48 +++++---------------------- 2 files changed, 12 insertions(+), 61 deletions(-) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 8fc4d6daef..56e31922d1 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -111,11 +111,6 @@ UnixMakefileGenerator::init() project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_PREBIND"); if(!project->isEmpty("QMAKE_INCDIR")) project->values("INCLUDEPATH") += project->values("QMAKE_INCDIR"); - project->values("QMAKE_L_FLAG") - << (project->isActiveConfig("rvct_linker") ? "--userlibpath " - : project->isActiveConfig("armcc_linker") ? "-L--userlibpath=" - : project->isActiveConfig("ti_linker") ? "--search_path=" - : "-L"); ProStringList ldadd; if(!project->isEmpty("QMAKE_LIBDIR")) { const ProStringList &libdirs = project->values("QMAKE_LIBDIR"); @@ -437,9 +432,6 @@ UnixMakefileGenerator::fixLibFlag(const ProString &lib) bool UnixMakefileGenerator::findLibraries() { - ProString libArg = project->first("QMAKE_L_FLAG"); - if (libArg == "-L") - libArg.clear(); QList libdirs; int libidx = 0; foreach (const ProString &dlib, project->values("QMAKE_DEFAULT_LIBDIRS")) @@ -459,16 +451,8 @@ UnixMakefileGenerator::findLibraries() continue; } libdirs.insert(libidx++, f); - if (!libArg.isEmpty()) - *it = libArg + f.real(); } else if(opt.startsWith("-l")) { - if (project->isActiveConfig("rvct_linker") || project->isActiveConfig("armcc_linker")) { - (*it) = "lib" + opt.mid(2) + ".so"; - } else if (project->isActiveConfig("ti_linker")) { - (*it) = opt.mid(2); - } else { - stub = opt.mid(2); - } + stub = opt.mid(2); } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-framework")) { if (opt.length() == 10) ++it; @@ -544,7 +528,6 @@ QString linkLib(const QString &file, const QString &libName) { void UnixMakefileGenerator::processPrlFiles() { - const QString libArg = project->first("QMAKE_L_FLAG").toQString(); QList libdirs, frameworkdirs; int libidx = 0, fwidx = 0; foreach (const ProString &dlib, project->values("QMAKE_DEFAULT_LIBDIRS")) @@ -557,8 +540,8 @@ UnixMakefileGenerator::processPrlFiles() for(int lit = 0; lit < l.size(); ++lit) { QString opt = l.at(lit).toQString(); if(opt.startsWith("-")) { - if (opt.startsWith(libArg)) { - QMakeLocalFileName l(opt.mid(libArg.length())); + if (opt.startsWith("-L")) { + QMakeLocalFileName l(opt.mid(2)); if(!libdirs.contains(l)) libdirs.insert(libidx++, l); } else if(opt.startsWith("-l")) { @@ -632,7 +615,7 @@ UnixMakefileGenerator::processPrlFiles() } } - if (opt.startsWith(libArg) || + if (opt.startsWith("-L") || (target_mode == TARG_MAC_MODE && opt.startsWith("-F"))) { if(!lflags[arch].contains(opt)) lflags[arch].append(opt); diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 57955dc456..87213a0e72 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -183,25 +183,6 @@ void createArObjectScriptFile(const QString &fileName, const QString &target, co } } -void createRvctObjectScriptFile(const QString &fileName, const ProStringList &objList) -{ - QString filePath = Option::output_dir + QDir::separator() + fileName; - QFile file(filePath); - if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { - QTextStream t(&file); - for (ProStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) { - QString path = (*it).toQString(); - // ### quoting? - if (QDir::isRelativePath(path)) - t << "./" << path << endl; - else - t << path << endl; - } - t.flush(); - file.close(); - } -} - void MingwMakefileGenerator::writeMingwParts(QTextStream &t) { writeStandardParts(t); @@ -335,32 +316,19 @@ void MingwMakefileGenerator::writeObjectsPart(QTextStream &t) ar_script_file += "." + var("BUILD_NAME"); } // QMAKE_LIB is used for win32, including mingw, whereas QMAKE_AR is used on Unix. - if (project->isActiveConfig("rvct_linker")) { - createRvctObjectScriptFile(ar_script_file, project->values("OBJECTS")); - QString ar_cmd = project->values("QMAKE_LIB").join(' '); - if (ar_cmd.isEmpty()) - ar_cmd = "armar --create"; - objectsLinkLine = ar_cmd + ' ' + fileVar("DEST_TARGET") + " --via " + escapeFilePath(ar_script_file); - } else { - // Strip off any options since the ar commands will be read from file. - QString ar_cmd = var("QMAKE_LIB").section(" ", 0, 0);; - if (ar_cmd.isEmpty()) - ar_cmd = "ar"; - createArObjectScriptFile(ar_script_file, var("DEST_TARGET"), project->values("OBJECTS")); - objectsLinkLine = ar_cmd + " -M < " + escapeFilePath(ar_script_file); - } + // Strip off any options since the ar commands will be read from file. + QString ar_cmd = var("QMAKE_LIB").section(" ", 0, 0); + if (ar_cmd.isEmpty()) + ar_cmd = "ar"; + createArObjectScriptFile(ar_script_file, var("DEST_TARGET"), project->values("OBJECTS")); + objectsLinkLine = ar_cmd + " -M < " + escapeFilePath(ar_script_file); } else { QString ld_script_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET"); if (!var("BUILD_NAME").isEmpty()) { ld_script_file += "." + var("BUILD_NAME"); } - if (project->isActiveConfig("rvct_linker")) { - createRvctObjectScriptFile(ld_script_file, project->values("OBJECTS")); - objectsLinkLine = QString::fromLatin1("--via ") + escapeFilePath(ld_script_file); - } else { - createLdObjectScriptFile(ld_script_file, project->values("OBJECTS")); - objectsLinkLine = escapeFilePath(ld_script_file); - } + createLdObjectScriptFile(ld_script_file, project->values("OBJECTS")); + objectsLinkLine = escapeFilePath(ld_script_file); } Win32MakefileGenerator::writeObjectsPart(t); } From 9db16441657cf3361e2f41a94d9722f99d2efc2b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 22 Sep 2015 20:58:18 +0200 Subject: [PATCH 143/240] inline NmakeMakefileGenerator::getPdbTarget() it was used only once, and virtual for no reason whatsoever. Change-Id: I99411be3dac93d8a129441f656b2443d09108564 Reviewed-by: Joerg Bornemann --- qmake/generators/win32/msvc_nmake.cpp | 7 +------ qmake/generators/win32/msvc_nmake.h | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 2d2a5af8ca..9c34b187bf 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -266,11 +266,6 @@ void NmakeMakefileGenerator::writeSubMakeCall(QTextStream &t, const QString &cal Win32MakefileGenerator::writeSubMakeCall(t, callPrefix, makeArguments); } -QString NmakeMakefileGenerator::getPdbTarget() -{ - return QString(project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".pdb"); -} - QString NmakeMakefileGenerator::defaultInstall(const QString &t) { if((t != "target" && t != "dlltarget") || @@ -288,7 +283,7 @@ QString NmakeMakefileGenerator::defaultInstall(const QString &t) if (project->isActiveConfig("debug_info")) { if (t == "dlltarget" || project->values(ProKey(t + ".CONFIG")).indexOf("no_dll") == -1) { - QString pdb_target = getPdbTarget(); + QString pdb_target = project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".pdb"; QString src_targ = (project->isEmpty("DESTDIR") ? QString("$(DESTDIR)") : project->first("DESTDIR")) + pdb_target; QString dst_targ = filePrefixRoot(root, fileFixify(targetdir + pdb_target, FileFixifyAbsolute)); if(!ret.isEmpty()) diff --git a/qmake/generators/win32/msvc_nmake.h b/qmake/generators/win32/msvc_nmake.h index 83ce96c8b7..df72ef394c 100644 --- a/qmake/generators/win32/msvc_nmake.h +++ b/qmake/generators/win32/msvc_nmake.h @@ -52,7 +52,6 @@ class NmakeMakefileGenerator : public Win32MakefileGenerator protected: virtual void writeSubMakeCall(QTextStream &t, const QString &callPrefix, const QString &makeArguments); - virtual QString getPdbTarget(); virtual QString defaultInstall(const QString &t); virtual QStringList &findDependencies(const QString &file); QString var(const ProKey &value) const; From d98a23eb7c164b8e464907391cde0b95d2c4d8a3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 23 Sep 2015 14:46:06 +0200 Subject: [PATCH 144/240] remove references to $$QMAKE_CYGWIN_EXE it would cause the unix generator to set TARGET_EXT, but that wasn't used anywhere. so remove the dead code. if it ever gets re-introduced, it will be as QMAKE_EXTENSION_EXE. Change-Id: I44ce3e612651fd229177e37ab6c8879cd8c474b7 Reviewed-by: Joerg Bornemann --- mkspecs/cygwin-g++/qmake.conf | 1 - qmake/generators/unix/unixmake2.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/mkspecs/cygwin-g++/qmake.conf b/mkspecs/cygwin-g++/qmake.conf index 53cd35611f..95dcf8ee32 100644 --- a/mkspecs/cygwin-g++/qmake.conf +++ b/mkspecs/cygwin-g++/qmake.conf @@ -57,7 +57,6 @@ QMAKE_LFLAGS_SONAME = -Wl,-soname, QMAKE_LFLAGS_THREAD = QMAKE_LFLAGS_RPATH = -Wl,-rpath, QMAKE_CYGWIN_SHLIB = 1 -QMAKE_CYGWIN_EXE = 1 QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 975c173ea7..4babd728ff 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -1177,8 +1177,6 @@ void UnixMakefileGenerator::init2() } if(!project->isEmpty("TARGET")) project->values("TARGET").first().prepend(project->first("DESTDIR")); - if (!project->values("QMAKE_CYGWIN_EXE").isEmpty()) - project->values("TARGET_EXT").append(".exe"); } else if (project->isActiveConfig("staticlib")) { project->values("TARGET").first().prepend(project->first("QMAKE_PREFIX_STATICLIB")); project->values("TARGET").first() += "." + project->first("QMAKE_EXTENSION_STATICLIB"); From 3e6d1726380326c0faba9029e2a68886595a2ebc Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 29 Sep 2015 12:39:08 +0200 Subject: [PATCH 145/240] move inclusions of unix.conf (and related files) near the top that way we can override the values defined there. Change-Id: Ib9bce596d9fd43875b26a97c5489ee9d0d46b77c Reviewed-by: Joerg Bornemann --- mkspecs/aix-g++-64/qmake.conf | 3 ++- mkspecs/aix-g++/qmake.conf | 3 ++- mkspecs/aix-xlc-64/qmake.conf | 3 ++- mkspecs/aix-xlc/qmake.conf | 3 ++- mkspecs/common/linux.conf | 4 ++-- mkspecs/common/mac.conf | 4 ++-- mkspecs/common/qcc-base-qnx-armle-v7.conf | 3 ++- mkspecs/common/qcc-base-qnx-x86.conf | 3 ++- mkspecs/darwin-g++/qmake.conf | 3 ++- mkspecs/freebsd-g++/qmake.conf | 3 ++- mkspecs/freebsd-g++46/qmake.conf | 3 ++- mkspecs/freebsd-icc/qmake.conf | 3 ++- mkspecs/haiku-g++/qmake.conf | 4 +++- mkspecs/hpux-acc-64/qmake.conf | 3 ++- mkspecs/hpux-acc-o64/qmake.conf | 3 ++- mkspecs/hpux-acc/qmake.conf | 3 ++- mkspecs/hpux-g++-64/qmake.conf | 3 ++- mkspecs/hpux-g++/qmake.conf | 3 ++- mkspecs/hpuxi-acc-32/qmake.conf | 3 ++- mkspecs/hpuxi-acc-64/qmake.conf | 3 ++- mkspecs/hpuxi-g++-64/qmake.conf | 3 ++- mkspecs/hurd-g++/qmake.conf | 3 ++- mkspecs/irix-cc-64/qmake.conf | 3 ++- mkspecs/irix-cc/qmake.conf | 3 ++- mkspecs/irix-g++-64/qmake.conf | 3 ++- mkspecs/irix-g++/qmake.conf | 3 ++- mkspecs/linux-cxx/qmake.conf | 3 ++- mkspecs/linux-g++-32/qmake.conf | 4 +++- mkspecs/linux-g++-64/qmake.conf | 3 ++- mkspecs/linux-kcc/qmake.conf | 3 ++- mkspecs/linux-pgcc/qmake.conf | 3 ++- mkspecs/lynxos-g++/qmake.conf | 3 ++- mkspecs/netbsd-g++/qmake.conf | 3 ++- mkspecs/openbsd-g++/qmake.conf | 3 ++- mkspecs/sco-g++/qmake.conf | 3 ++- mkspecs/solaris-cc-64/qmake.conf | 3 ++- mkspecs/solaris-cc/qmake.conf | 3 ++- mkspecs/solaris-g++-64/qmake.conf | 3 ++- mkspecs/solaris-g++/qmake.conf | 3 ++- mkspecs/tru64-cxx/qmake.conf | 3 ++- mkspecs/tru64-g++/qmake.conf | 3 ++- mkspecs/unixware-cc/qmake.conf | 3 ++- mkspecs/unixware-g++/qmake.conf | 3 ++- mkspecs/unsupported/freebsd-clang/qmake.conf | 4 +++- mkspecs/unsupported/linux-host-g++/qmake.conf | 3 ++- mkspecs/unsupported/qnx-X11-g++/qmake.conf | 2 +- mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf | 3 ++- mkspecs/unsupported/vxworks-ppc-g++/qmake.conf | 3 ++- mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf | 3 ++- mkspecs/unsupported/vxworks-simpentium-g++/qmake.conf | 3 ++- 50 files changed, 102 insertions(+), 52 deletions(-) diff --git a/mkspecs/aix-g++-64/qmake.conf b/mkspecs/aix-g++-64/qmake.conf index 176c437c45..7f620a9577 100644 --- a/mkspecs/aix-g++-64/qmake.conf +++ b/mkspecs/aix-g++-64/qmake.conf @@ -5,6 +5,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = aix +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -67,5 +69,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = ranlib -X64 -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/aix-g++/qmake.conf b/mkspecs/aix-g++/qmake.conf index 553d9af544..d2f26a1b41 100644 --- a/mkspecs/aix-g++/qmake.conf +++ b/mkspecs/aix-g++/qmake.conf @@ -5,6 +5,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = aix +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -67,5 +69,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/aix-xlc-64/qmake.conf b/mkspecs/aix-xlc-64/qmake.conf index 42dbd18b4a..1aea8d81c5 100644 --- a/mkspecs/aix-xlc-64/qmake.conf +++ b/mkspecs/aix-xlc-64/qmake.conf @@ -5,6 +5,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = aix +include(../common/unix.conf) + QMAKE_COMPILER = ibm_xlc QMAKE_CC = xlc @@ -66,5 +68,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = ranlib -X64 -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/aix-xlc/qmake.conf b/mkspecs/aix-xlc/qmake.conf index d2de649355..c765d4ff6b 100644 --- a/mkspecs/aix-xlc/qmake.conf +++ b/mkspecs/aix-xlc/qmake.conf @@ -5,6 +5,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = aix +include(../common/unix.conf) + QMAKE_COMPILER = ibm_xlc QMAKE_CC = xlc @@ -69,5 +71,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = ranlib -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/common/linux.conf b/mkspecs/common/linux.conf index 8d6fb6fe17..b98d9bdf2d 100644 --- a/mkspecs/common/linux.conf +++ b/mkspecs/common/linux.conf @@ -4,6 +4,8 @@ QMAKE_PLATFORM += linux +include(unix.conf) + QMAKE_CFLAGS_THREAD += -D_REENTRANT QMAKE_CXXFLAGS_THREAD += $$QMAKE_CFLAGS_THREAD QMAKE_LFLAGS_GCSECTIONS = -Wl,--gc-sections @@ -51,5 +53,3 @@ QMAKE_RANLIB = QMAKE_STRIP = strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded - -include(unix.conf) diff --git a/mkspecs/common/mac.conf b/mkspecs/common/mac.conf index 91639ddb50..d80b41c74b 100644 --- a/mkspecs/common/mac.conf +++ b/mkspecs/common/mac.conf @@ -6,6 +6,8 @@ QMAKE_PLATFORM += mac darwin +include(unix.conf) + QMAKE_RESOURCE = /Developer/Tools/Rez QMAKE_EXTENSION_SHLIB = dylib QMAKE_LIBDIR = @@ -27,5 +29,3 @@ QMAKE_LIBS_THREAD = QMAKE_AR = ar cq QMAKE_RANLIB = ranlib -s QMAKE_NM = nm -P - -include(unix.conf) diff --git a/mkspecs/common/qcc-base-qnx-armle-v7.conf b/mkspecs/common/qcc-base-qnx-armle-v7.conf index 12d393f070..ad3bb33da4 100644 --- a/mkspecs/common/qcc-base-qnx-armle-v7.conf +++ b/mkspecs/common/qcc-base-qnx-armle-v7.conf @@ -4,9 +4,10 @@ MAKEFILE_GENERATOR = UNIX -include(g++-unix.conf) include(unix.conf) +include(g++-unix.conf) + QMAKE_CC = qcc -Vgcc_ntoarmv7le QMAKE_CXX = qcc -Vgcc_ntoarmv7le QNX_CPUDIR = armle-v7 diff --git a/mkspecs/common/qcc-base-qnx-x86.conf b/mkspecs/common/qcc-base-qnx-x86.conf index b49075086d..37a5d9ce70 100644 --- a/mkspecs/common/qcc-base-qnx-x86.conf +++ b/mkspecs/common/qcc-base-qnx-x86.conf @@ -4,9 +4,10 @@ MAKEFILE_GENERATOR = UNIX -include(g++-unix.conf) include(unix.conf) +include(g++-unix.conf) + QMAKE_CC = qcc -Vgcc_ntox86 QMAKE_CXX = qcc -Vgcc_ntox86 QNX_CPUDIR = x86 diff --git a/mkspecs/darwin-g++/qmake.conf b/mkspecs/darwin-g++/qmake.conf index ab333b1684..79f81a990f 100644 --- a/mkspecs/darwin-g++/qmake.conf +++ b/mkspecs/darwin-g++/qmake.conf @@ -9,6 +9,8 @@ QMAKE_PLATFORM = osx macx mac darwin CONFIG += native_precompiled_headers DEFINES += __USE_WS_X11__ +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = cc @@ -84,5 +86,4 @@ QMAKE_PCH_OUTPUT_EXT = .gch QMAKE_CXXFLAGS_PRECOMPILE += -x objective-c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/freebsd-g++/qmake.conf b/mkspecs/freebsd-g++/qmake.conf index 47505fc06a..282b6bdfa7 100644 --- a/mkspecs/freebsd-g++/qmake.conf +++ b/mkspecs/freebsd-g++/qmake.conf @@ -5,6 +5,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = freebsd bsd +include(../common/unix.conf) + QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD @@ -27,7 +29,6 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) load(qt_config) diff --git a/mkspecs/freebsd-g++46/qmake.conf b/mkspecs/freebsd-g++46/qmake.conf index 277997ab28..b930fca78b 100644 --- a/mkspecs/freebsd-g++46/qmake.conf +++ b/mkspecs/freebsd-g++46/qmake.conf @@ -5,6 +5,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = freebsd bsd +include(../common/unix.conf) + QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD @@ -27,7 +29,6 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) diff --git a/mkspecs/freebsd-icc/qmake.conf b/mkspecs/freebsd-icc/qmake.conf index fb419f7e5b..d72ea73278 100644 --- a/mkspecs/freebsd-icc/qmake.conf +++ b/mkspecs/freebsd-icc/qmake.conf @@ -30,6 +30,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = freebsd bsd +include(../common/unix.conf) + QMAKE_COMPILER = gcc intel_icc # icc pretends to be gcc QMAKE_CC = icc @@ -90,5 +92,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/haiku-g++/qmake.conf b/mkspecs/haiku-g++/qmake.conf index 6144392385..ac28069864 100644 --- a/mkspecs/haiku-g++/qmake.conf +++ b/mkspecs/haiku-g++/qmake.conf @@ -5,6 +5,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = haiku +include(../common/unix.conf) + # Choose haiku QPA Plugin as default QT_QPA_DEFAULT_PLATFORM = haiku @@ -23,5 +25,5 @@ QMAKE_RANLIB = include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) -include(../common/unix.conf) + load(qt_config) diff --git a/mkspecs/hpux-acc-64/qmake.conf b/mkspecs/hpux-acc-64/qmake.conf index 2156b448fe..f0b879de83 100644 --- a/mkspecs/hpux-acc-64/qmake.conf +++ b/mkspecs/hpux-acc-64/qmake.conf @@ -49,6 +49,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = hpux QMAKE_COMPILER_DEFINES += __hpux __HP_aCC +include(../common/unix.conf) + QMAKE_COMPILER = hp_acc QMAKE_CC = cc @@ -111,5 +113,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/hpux-acc-o64/qmake.conf b/mkspecs/hpux-acc-o64/qmake.conf index 69c3df1375..750bb99155 100644 --- a/mkspecs/hpux-acc-o64/qmake.conf +++ b/mkspecs/hpux-acc-o64/qmake.conf @@ -48,6 +48,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = hpux +include(../common/unix.conf) + QMAKE_COMPILER = hp_acc QMAKE_CC = cc @@ -109,5 +111,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/hpux-acc/qmake.conf b/mkspecs/hpux-acc/qmake.conf index eaa8888fbe..2f1ce1054c 100644 --- a/mkspecs/hpux-acc/qmake.conf +++ b/mkspecs/hpux-acc/qmake.conf @@ -28,6 +28,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = hpux QMAKE_COMPILER_DEFINES += __hpux __HP_aCC +include(../common/unix.conf) + QMAKE_COMPILER = hp_acc QMAKE_CC = cc @@ -90,5 +92,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/hpux-g++-64/qmake.conf b/mkspecs/hpux-g++-64/qmake.conf index 3e822edbfb..a27333fa18 100644 --- a/mkspecs/hpux-g++-64/qmake.conf +++ b/mkspecs/hpux-g++-64/qmake.conf @@ -8,6 +8,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = hpux +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -73,5 +75,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/hpux-g++/qmake.conf b/mkspecs/hpux-g++/qmake.conf index 866a3416bc..b488da7178 100644 --- a/mkspecs/hpux-g++/qmake.conf +++ b/mkspecs/hpux-g++/qmake.conf @@ -9,6 +9,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = hpux CONFIG += plugin_no_soname +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -74,5 +76,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/hpuxi-acc-32/qmake.conf b/mkspecs/hpuxi-acc-32/qmake.conf index 79bf20fbb2..e80a7973fe 100644 --- a/mkspecs/hpuxi-acc-32/qmake.conf +++ b/mkspecs/hpuxi-acc-32/qmake.conf @@ -6,6 +6,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = hpux CONFIG += plugin_no_soname +include(../common/unix.conf) + QMAKE_COMPILER = hp_acc QMAKE_CC = cc @@ -66,5 +68,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/hpuxi-acc-64/qmake.conf b/mkspecs/hpuxi-acc-64/qmake.conf index aaec3eab14..360e35c5d6 100644 --- a/mkspecs/hpuxi-acc-64/qmake.conf +++ b/mkspecs/hpuxi-acc-64/qmake.conf @@ -49,6 +49,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = hpux CONFIG += plugin_no_soname +include(../common/unix.conf) + QMAKE_COMPILER = hp_acc QMAKE_CC = cc @@ -109,5 +111,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/hpuxi-g++-64/qmake.conf b/mkspecs/hpuxi-g++-64/qmake.conf index 8a05a5f611..4c376de719 100644 --- a/mkspecs/hpuxi-g++-64/qmake.conf +++ b/mkspecs/hpuxi-g++-64/qmake.conf @@ -13,6 +13,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = hpux +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -76,5 +78,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/hurd-g++/qmake.conf b/mkspecs/hurd-g++/qmake.conf index e7e4e3a82d..f2e3242627 100644 --- a/mkspecs/hurd-g++/qmake.conf +++ b/mkspecs/hurd-g++/qmake.conf @@ -7,6 +7,8 @@ QMAKE_PLATFORM += hurd CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib +include(../common/unix.conf) + QMAKE_CFLAGS_THREAD += -D_REENTRANT QMAKE_CXXFLAGS_THREAD += $$QMAKE_CFLAGS_THREAD QMAKE_LFLAGS_GCSECTIONS = -Wl,--gc-sections @@ -46,7 +48,6 @@ QMAKE_RANLIB = QMAKE_STRIP = strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded -include(../common/unix.conf) include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) load(qt_config) diff --git a/mkspecs/irix-cc-64/qmake.conf b/mkspecs/irix-cc-64/qmake.conf index 05c8b6fc84..ad5c6a3ee1 100644 --- a/mkspecs/irix-cc-64/qmake.conf +++ b/mkspecs/irix-cc-64/qmake.conf @@ -38,6 +38,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = irix QMAKE_COMPILER_DEFINES += __sgi __EDG +include(../common/unix.conf) + QMAKE_COMPILER = sgi_cc QMAKE_CC = cc @@ -103,5 +105,4 @@ QMAKE_RANLIB = QMAKE_CLEAN = -r $(OBJECTS_DIR)so_locations $(OBJECTS_DIR)ii_files -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/irix-cc/qmake.conf b/mkspecs/irix-cc/qmake.conf index 72d4e65474..52abdf8578 100644 --- a/mkspecs/irix-cc/qmake.conf +++ b/mkspecs/irix-cc/qmake.conf @@ -38,6 +38,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = irix QMAKE_COMPILER_DEFINES += __sgi __EDG +include(../common/unix.conf) + QMAKE_COMPILER = sgi_cc QMAKE_CC = cc @@ -103,5 +105,4 @@ QMAKE_RANLIB = QMAKE_CLEAN = -r $(OBJECTS_DIR)so_locations $(OBJECTS_DIR)ii_files -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/irix-g++-64/qmake.conf b/mkspecs/irix-g++-64/qmake.conf index 12c224b5c0..bd258df5e8 100644 --- a/mkspecs/irix-g++-64/qmake.conf +++ b/mkspecs/irix-g++-64/qmake.conf @@ -6,6 +6,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = irix QMAKE_COMPILER_DEFINES += __sgi __GNUC__ +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -73,5 +75,4 @@ QMAKE_RANLIB = QMAKE_CLEAN = so_locations -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/irix-g++/qmake.conf b/mkspecs/irix-g++/qmake.conf index 2c02165e0d..57a27b6a1b 100644 --- a/mkspecs/irix-g++/qmake.conf +++ b/mkspecs/irix-g++/qmake.conf @@ -6,6 +6,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = irix QMAKE_COMPILER_DEFINES += __sgi __GNUC__ +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -73,5 +75,4 @@ QMAKE_RANLIB = QMAKE_CLEAN = so_locations -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/linux-cxx/qmake.conf b/mkspecs/linux-cxx/qmake.conf index 1c7cafc6f2..b156bea084 100644 --- a/mkspecs/linux-cxx/qmake.conf +++ b/mkspecs/linux-cxx/qmake.conf @@ -7,6 +7,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = linux +include(../common/unix.conf) + QMAKE_COMPILER = compaq_cc QMAKE_CC = ccc @@ -61,5 +63,4 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_AR = ar cqs QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/linux-g++-32/qmake.conf b/mkspecs/linux-g++-32/qmake.conf index 340aa85e7c..f09abeeec0 100644 --- a/mkspecs/linux-g++-32/qmake.conf +++ b/mkspecs/linux-g++-32/qmake.conf @@ -6,10 +6,12 @@ MAKEFILE_GENERATOR = UNIX CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib +include(../common/linux.conf) + QMAKE_CFLAGS = -m32 QMAKE_LFLAGS = -m32 -include(../common/linux.conf) include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) + load(qt_config) diff --git a/mkspecs/linux-g++-64/qmake.conf b/mkspecs/linux-g++-64/qmake.conf index 36fb6a83eb..a79b69ff31 100644 --- a/mkspecs/linux-g++-64/qmake.conf +++ b/mkspecs/linux-g++-64/qmake.conf @@ -9,10 +9,11 @@ MAKEFILE_GENERATOR = UNIX CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib +include(../common/linux.conf) + QMAKE_CFLAGS = -m64 QMAKE_LFLAGS = -m64 -include(../common/linux.conf) include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) diff --git a/mkspecs/linux-kcc/qmake.conf b/mkspecs/linux-kcc/qmake.conf index 06efc8c12c..591a59537f 100644 --- a/mkspecs/linux-kcc/qmake.conf +++ b/mkspecs/linux-kcc/qmake.conf @@ -16,6 +16,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = linux +include(../common/unix.conf) + QMAKE_COMPILER = kai_cc QMAKE_CC = KCC @@ -78,5 +80,4 @@ QMAKE_RANLIB = QMAKE_CLEAN = -r $(OBJECTS_DIR)ti_files -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/linux-pgcc/qmake.conf b/mkspecs/linux-pgcc/qmake.conf index 286f937b0e..c41823ba94 100644 --- a/mkspecs/linux-pgcc/qmake.conf +++ b/mkspecs/linux-pgcc/qmake.conf @@ -7,6 +7,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = linux +include(../common/unix.conf) + QMAKE_COMPILER = portland_cc QMAKE_CC = pgcc @@ -67,5 +69,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/lynxos-g++/qmake.conf b/mkspecs/lynxos-g++/qmake.conf index a53d6a8ec7..91bcc6b85d 100644 --- a/mkspecs/lynxos-g++/qmake.conf +++ b/mkspecs/lynxos-g++/qmake.conf @@ -9,6 +9,8 @@ QMAKE_PLATFORM = lynxos CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -74,5 +76,4 @@ QMAKE_RANLIB = QMAKE_STRIP = strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/netbsd-g++/qmake.conf b/mkspecs/netbsd-g++/qmake.conf index 6cb24d9bf9..04c675da24 100644 --- a/mkspecs/netbsd-g++/qmake.conf +++ b/mkspecs/netbsd-g++/qmake.conf @@ -5,6 +5,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = netbsd bsd +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -68,5 +70,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = ranlib -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/openbsd-g++/qmake.conf b/mkspecs/openbsd-g++/qmake.conf index 2fdbd2c469..10330bc081 100644 --- a/mkspecs/openbsd-g++/qmake.conf +++ b/mkspecs/openbsd-g++/qmake.conf @@ -5,6 +5,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = openbsd bsd +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -69,5 +71,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = ranlib -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/sco-g++/qmake.conf b/mkspecs/sco-g++/qmake.conf index ebf60a3954..27fc1cffe3 100644 --- a/mkspecs/sco-g++/qmake.conf +++ b/mkspecs/sco-g++/qmake.conf @@ -7,6 +7,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = sco +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -65,5 +67,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/solaris-cc-64/qmake.conf b/mkspecs/solaris-cc-64/qmake.conf index 6e1d35ef43..1c7b43c29c 100644 --- a/mkspecs/solaris-cc-64/qmake.conf +++ b/mkspecs/solaris-cc-64/qmake.conf @@ -24,6 +24,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = solaris +include(../common/unix.conf) + QMAKE_COMPILER = sun_cc QMAKE_CC = cc @@ -90,5 +92,4 @@ QMAKE_RANLIB = QMAKE_CLEAN = -r $(OBJECTS_DIR)Templates.DB $(OBJECTS_DIR)SunWS_cache -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/solaris-cc/qmake.conf b/mkspecs/solaris-cc/qmake.conf index 23814135b6..045ab033dd 100644 --- a/mkspecs/solaris-cc/qmake.conf +++ b/mkspecs/solaris-cc/qmake.conf @@ -7,6 +7,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = solaris +include(../common/unix.conf) + QMAKE_COMPILER = sun_cc QMAKE_CC = cc @@ -73,5 +75,4 @@ QMAKE_RANLIB = QMAKE_CLEAN = -r $(OBJECTS_DIR)Templates.DB $(OBJECTS_DIR)SunWS_cache -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/solaris-g++-64/qmake.conf b/mkspecs/solaris-g++-64/qmake.conf index 34fd044f3e..91ffb9193e 100644 --- a/mkspecs/solaris-g++-64/qmake.conf +++ b/mkspecs/solaris-g++-64/qmake.conf @@ -28,6 +28,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = solaris +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -92,5 +94,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/solaris-g++/qmake.conf b/mkspecs/solaris-g++/qmake.conf index ccc178395b..594646353d 100644 --- a/mkspecs/solaris-g++/qmake.conf +++ b/mkspecs/solaris-g++/qmake.conf @@ -11,6 +11,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = solaris +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -75,5 +77,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/tru64-cxx/qmake.conf b/mkspecs/tru64-cxx/qmake.conf index a2e0112623..024590bf91 100644 --- a/mkspecs/tru64-cxx/qmake.conf +++ b/mkspecs/tru64-cxx/qmake.conf @@ -6,6 +6,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = tru64 CONFIG += plugin_no_soname +include(../common/unix.conf) + QMAKE_COMPILER = dec_cc QMAKE_CC = cc @@ -65,5 +67,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/tru64-g++/qmake.conf b/mkspecs/tru64-g++/qmake.conf index dd7eb6c9c3..193e2694ea 100644 --- a/mkspecs/tru64-g++/qmake.conf +++ b/mkspecs/tru64-g++/qmake.conf @@ -6,6 +6,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = tru64 CONFIG += plugin_no_soname +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -67,5 +69,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/unixware-cc/qmake.conf b/mkspecs/unixware-cc/qmake.conf index 483b8c0bb3..1a36a3e76b 100644 --- a/mkspecs/unixware-cc/qmake.conf +++ b/mkspecs/unixware-cc/qmake.conf @@ -10,6 +10,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = unixware +include(../common/unix.conf) + QMAKE_COMPILER = sco_cc QMAKE_CC = cc @@ -69,5 +71,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/unixware-g++/qmake.conf b/mkspecs/unixware-g++/qmake.conf index feca5a4c9e..abe2773deb 100644 --- a/mkspecs/unixware-g++/qmake.conf +++ b/mkspecs/unixware-g++/qmake.conf @@ -7,6 +7,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = unixware +include(../common/unix.conf) + QMAKE_COMPILER = gcc QMAKE_CC = gcc @@ -68,5 +70,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/unix.conf) load(qt_config) diff --git a/mkspecs/unsupported/freebsd-clang/qmake.conf b/mkspecs/unsupported/freebsd-clang/qmake.conf index 92b7c47590..9d9815a7b3 100644 --- a/mkspecs/unsupported/freebsd-clang/qmake.conf +++ b/mkspecs/unsupported/freebsd-clang/qmake.conf @@ -5,6 +5,8 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = freebsd bsd +include(../common/unix.conf) + QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD @@ -28,7 +30,7 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../../common/unix.conf) include(../../common/gcc-base-unix.conf) include(../../common/clang.conf) + load(qt_config) diff --git a/mkspecs/unsupported/linux-host-g++/qmake.conf b/mkspecs/unsupported/linux-host-g++/qmake.conf index 546ff21349..3aa7520776 100644 --- a/mkspecs/unsupported/linux-host-g++/qmake.conf +++ b/mkspecs/unsupported/linux-host-g++/qmake.conf @@ -17,6 +17,8 @@ QMAKE_PLATFORM = linux CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib +include(../common/unix.conf) + # # qmake configuration for common gcc # @@ -111,5 +113,4 @@ QMAKE_RANLIB = QMAKE_STRIP = host-strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded -include(../../common/unix.conf) load(qt_config) diff --git a/mkspecs/unsupported/qnx-X11-g++/qmake.conf b/mkspecs/unsupported/qnx-X11-g++/qmake.conf index 8d2c63f330..79a5609dbf 100644 --- a/mkspecs/unsupported/qnx-X11-g++/qmake.conf +++ b/mkspecs/unsupported/qnx-X11-g++/qmake.conf @@ -7,9 +7,9 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = qnx +include(../common/unix.conf) include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) -include(../common/unix.conf) QMAKE_CFLAGS_THREAD = -D_REENTRANT QMAKE_CXXFLAGS_THREAD = $$QMAKE_CLFAGS_THREAD diff --git a/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf b/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf index a4cf23df9c..16e3127803 100644 --- a/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf +++ b/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf @@ -7,6 +7,8 @@ QMAKE_PLATFORM = vxworks CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib +include(../common/unix.conf) + VXWORKS_ARCH = ppc VXWORKS_CPU = PPC32 VXWORKS_DIAB_SPEC = -tPPC7400FV:vxworks66 @@ -88,6 +90,5 @@ QMAKE_RANLIB = QMAKE_STRIP = strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded -include(../../common/unix.conf) load(qt_config) diff --git a/mkspecs/unsupported/vxworks-ppc-g++/qmake.conf b/mkspecs/unsupported/vxworks-ppc-g++/qmake.conf index 1d3e9f4eb4..49cacdba43 100644 --- a/mkspecs/unsupported/vxworks-ppc-g++/qmake.conf +++ b/mkspecs/unsupported/vxworks-ppc-g++/qmake.conf @@ -8,13 +8,14 @@ CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib DEFINES += VXWORKS +include(../../common/linux.conf) + VXWORKS_ARCH = ppc VXWORKS_CPU = PPC32 VXWORKS_ARCH_MUNCH = ppc include(../../common/gcc-base-unix.conf) include(../../common/g++-unix.conf) -include(../../common/linux.conf) QMAKE_CC = cc$$VXWORKS_ARCH_MUNCH QMAKE_CFLAGS = -fno-builtin -I$(WIND_BASE)/target/h -I$(WIND_BASE)/target/h/wrn/coreip -DCPU=$$upper($$VXWORKS_ARCH) -DVX_CPU_FAMILY=$$VXWORKS_ARCH -DTOOL_FAMILY=gnu -DTOOL=gnu -D_WRS_KERNEL -D_VSB_CONFIG_FILE=\'<../lib/h/config/vsbConfig.h>\' diff --git a/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf b/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf index 49f0c21d4a..44e39a8a8c 100644 --- a/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf +++ b/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf @@ -7,6 +7,8 @@ QMAKE_PLATFORM = vxworks CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib +include(../common/unix.conf) + VXWORKS_ARCH = simlinux VXWORKS_CPU = SIMLINUX VXWORKS_DIAB_SPEC = -tX86LH:vxworks66 @@ -87,6 +89,5 @@ QMAKE_RANLIB = QMAKE_STRIP = strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded -include(../../common/unix.conf) load(qt_config) diff --git a/mkspecs/unsupported/vxworks-simpentium-g++/qmake.conf b/mkspecs/unsupported/vxworks-simpentium-g++/qmake.conf index 3c8fd12d4a..4d5cc97fad 100644 --- a/mkspecs/unsupported/vxworks-simpentium-g++/qmake.conf +++ b/mkspecs/unsupported/vxworks-simpentium-g++/qmake.conf @@ -8,13 +8,14 @@ CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib DEFINES += VXWORKS +include(../../common/linux.conf) + VXWORKS_ARCH = simlinux VXWORKS_CPU = SIMLINUX VXWORKS_ARCH_MUNCH = pentium include(../../common/gcc-base-unix.conf) include(../../common/g++-unix.conf) -include(../../common/linux.conf) QMAKE_CC = cc$$VXWORKS_ARCH_MUNCH QMAKE_CFLAGS = -fno-builtin -I$(WIND_BASE)/target/h -I$(WIND_BASE)/target/h/wrn/coreip -DCPU=$$upper($$VXWORKS_ARCH) -DVX_CPU_FAMILY=$$VXWORKS_ARCH -DTOOL_FAMILY=gnu -DTOOL=gnu -D_WRS_KERNEL -D_VSB_CONFIG_FILE=\'<../lib/h/config/vsbConfig.h>\' From f734599629ca30866fcefcc1cfea72a2d77462c3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 29 Sep 2015 12:44:30 +0200 Subject: [PATCH 146/240] unify handling of library prefixes and extensions make sure that all specs define QMAKE_{PREFIX,EXTENSION}_{SH,STATIC}LIB, and adjust the code to make halfways consistent use of these variables, in particular on windows; Win32MakefileGenerator::getLibTarget() is gone as a result, as is QMAKE_CYGWIN_SHLIB. still, tons of hardcoded "lib" references remain in the unix generator, because no-one cares. Change-Id: I6ccf37cc562f6584221c94fa27b2834412e4e4ca Reviewed-by: Joerg Bornemann --- mkspecs/common/msvc-desktop.conf | 3 +++ mkspecs/common/unix.conf | 1 + mkspecs/common/wince/qmake.conf | 3 +++ mkspecs/common/winrt_winphone/qmake.conf | 3 +++ mkspecs/cygwin-g++/qmake.conf | 4 ++-- mkspecs/features/resolve_target.prf | 6 +++--- mkspecs/win32-g++/qmake.conf | 2 ++ mkspecs/win32-icc/qmake.conf | 3 +++ qmake/generators/unix/unixmake.cpp | 10 ---------- qmake/generators/win32/mingw_make.cpp | 8 +------- qmake/generators/win32/mingw_make.h | 1 - qmake/generators/win32/winmakefile.cpp | 15 ++++----------- qmake/generators/win32/winmakefile.h | 1 - 13 files changed, 25 insertions(+), 35 deletions(-) diff --git a/mkspecs/common/msvc-desktop.conf b/mkspecs/common/msvc-desktop.conf index 849048dad0..a1c436388c 100644 --- a/mkspecs/common/msvc-desktop.conf +++ b/mkspecs/common/msvc-desktop.conf @@ -74,6 +74,9 @@ QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS QMAKE_LFLAGS_EXE = \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\" QMAKE_LFLAGS_DLL = /DLL QMAKE_LFLAGS_LTCG = /LTCG +QMAKE_PREFIX_SHLIB = +QMAKE_EXTENSION_SHLIB = dll +QMAKE_PREFIX_STATICLIB = QMAKE_EXTENSION_STATICLIB = lib QMAKE_LIBS_CORE = kernel32.lib user32.lib shell32.lib uuid.lib ole32.lib advapi32.lib ws2_32.lib diff --git a/mkspecs/common/unix.conf b/mkspecs/common/unix.conf index 2146b62f17..8521c85b99 100644 --- a/mkspecs/common/unix.conf +++ b/mkspecs/common/unix.conf @@ -12,5 +12,6 @@ QMAKE_YACCFLAGS_MANGLE += -p $base -b $base QMAKE_YACC_HEADER = $base.tab.h QMAKE_YACC_SOURCE = $base.tab.c QMAKE_PREFIX_SHLIB = lib +QMAKE_EXTENSION_SHLIB = so QMAKE_PREFIX_STATICLIB = lib QMAKE_EXTENSION_STATICLIB = a diff --git a/mkspecs/common/wince/qmake.conf b/mkspecs/common/wince/qmake.conf index 3eac38f6b7..224c350e2f 100644 --- a/mkspecs/common/wince/qmake.conf +++ b/mkspecs/common/wince/qmake.conf @@ -62,6 +62,9 @@ QMAKE_LFLAGS_LTCG = /LTCG QMAKE_LIBS_NETWORK = ws2.lib QMAKE_LIBS_OPENGL = QMAKE_LIBS_COMPAT = +QMAKE_PREFIX_SHLIB = +QMAKE_EXTENSION_SHLIB = dll +QMAKE_PREFIX_STATICLIB = QMAKE_EXTENSION_STATICLIB = lib QMAKE_LIBS_EGL = libEGL.lib diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf index 9ff1966284..288043da88 100644 --- a/mkspecs/common/winrt_winphone/qmake.conf +++ b/mkspecs/common/winrt_winphone/qmake.conf @@ -70,6 +70,9 @@ QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS QMAKE_LFLAGS_EXE = /MANIFEST:NO QMAKE_LFLAGS_DLL = /MANIFEST:NO /DLL QMAKE_LFLAGS_LTCG = /LTCG +QMAKE_PREFIX_SHLIB = +QMAKE_EXTENSION_SHLIB = dll +QMAKE_PREFIX_STATICLIB = QMAKE_EXTENSION_STATICLIB = lib QMAKE_LIBS += runtimeobject.lib diff --git a/mkspecs/cygwin-g++/qmake.conf b/mkspecs/cygwin-g++/qmake.conf index 95dcf8ee32..a4f64d9c66 100644 --- a/mkspecs/cygwin-g++/qmake.conf +++ b/mkspecs/cygwin-g++/qmake.conf @@ -6,7 +6,7 @@ MAKEFILE_GENERATOR = UNIX QMAKE_PLATFORM = cygwin unix posix -CONFIG += incremental +CONFIG += incremental unversioned_libname QMAKE_INCREMENTAL_STYLE = sublib QMAKE_COMPILER = gcc @@ -56,7 +56,6 @@ QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB QMAKE_LFLAGS_SONAME = -Wl,-soname, QMAKE_LFLAGS_THREAD = QMAKE_LFLAGS_RPATH = -Wl,-rpath, -QMAKE_CYGWIN_SHLIB = 1 QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl @@ -64,6 +63,7 @@ QMAKE_LIBS_X11 = -lXext -lX11 QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_THREAD = -lpthread QMAKE_PREFIX_SHLIB = lib +QMAKE_EXTENSION_SHLIB = dll QMAKE_PREFIX_STATICLIB = lib QMAKE_EXTENSION_STATICLIB = a diff --git a/mkspecs/features/resolve_target.prf b/mkspecs/features/resolve_target.prf index aa52e9d67e..d6460c1d9d 100644 --- a/mkspecs/features/resolve_target.prf +++ b/mkspecs/features/resolve_target.prf @@ -54,13 +54,13 @@ win32 { } else { equals(TEMPLATE, lib) { static { - QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${LIBPREFIX}$${TARGET}.a + QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${LIBPREFIX}$${TARGET}.$${QMAKE_EXTENSION_STATICLIB} } else: plugin|unversioned_libname { - QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${LIBPREFIX}$${TARGET}.so + QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${LIBPREFIX}$${TARGET}.$${QMAKE_EXTENSION_SHLIB} } else { TEMP_VERSION = $$VERSION isEmpty(TEMP_VERSION):TEMP_VERSION = 1.0.0 - QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${LIBPREFIX}$${TARGET}.so.$${TEMP_VERSION} + QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${LIBPREFIX}$${TARGET}.$${QMAKE_EXTENSION_SHLIB}.$${TEMP_VERSION} } } else { QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${TARGET} diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index 388d697b58..92bb8f4325 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -87,6 +87,8 @@ QMAKE_LFLAGS_GCSECTIONS = -Wl,--gc-sections QMAKE_LFLAGS_USE_GOLD = -fuse-ld=gold QMAKE_LINK_OBJECT_MAX = 10 QMAKE_LINK_OBJECT_SCRIPT = object_script +QMAKE_PREFIX_SHLIB = +QMAKE_EXTENSION_SHLIB = dll QMAKE_PREFIX_STATICLIB = lib QMAKE_EXTENSION_STATICLIB = a diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf index 65b533b3dd..3b440d143f 100644 --- a/mkspecs/win32-icc/qmake.conf +++ b/mkspecs/win32-icc/qmake.conf @@ -70,6 +70,9 @@ QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:console QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:windows QMAKE_LFLAGS_DLL = /DLL QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG +QMAKE_PREFIX_SHLIB = +QMAKE_EXTENSION_SHLIB = dll +QMAKE_PREFIX_STATICLIB = QMAKE_EXTENSION_STATICLIB = lib QMAKE_LIBS = diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 56e31922d1..1a1ba58dd1 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -45,14 +45,6 @@ QT_BEGIN_NAMESPACE void UnixMakefileGenerator::init() { - if(project->isEmpty("QMAKE_EXTENSION_SHLIB")) { - if(project->isEmpty("QMAKE_CYGWIN_SHLIB")) { - project->values("QMAKE_EXTENSION_SHLIB").append("so"); - } else { - project->values("QMAKE_EXTENSION_SHLIB").append("dll"); - } - } - ProStringList &configs = project->values("CONFIG"); if(project->isEmpty("ICON") && !project->isEmpty("RC_FILE")) project->values("ICON") = project->values("RC_FILE"); @@ -702,7 +694,6 @@ UnixMakefileGenerator::defaultInstall(const QString &t) } else if(project->first("TEMPLATE") == "app") { target = "$(QMAKE_TARGET)"; } else if(project->first("TEMPLATE") == "lib") { - if(project->isEmpty("QMAKE_CYGWIN_SHLIB")) { if (!project->isActiveConfig("staticlib") && !project->isActiveConfig("plugin") && !project->isActiveConfig("unversioned_libname")) { @@ -712,7 +703,6 @@ UnixMakefileGenerator::defaultInstall(const QString &t) links << "$(TARGET0)"; } } - } } for(int i = 0; i < targets.size(); ++i) { QString src = targets.at(i).toQString(), diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 87213a0e72..88a4494ec4 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -56,11 +56,6 @@ QString MingwMakefileGenerator::escapeDependencyPath(const QString &path) const return ret; } -QString MingwMakefileGenerator::getLibTarget() -{ - return QString("lib" + project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".a"); -} - QString MingwMakefileGenerator::getManifestFileForRcFile() const { return project->first("QMAKE_MANIFEST").toQString(); @@ -230,8 +225,7 @@ void MingwMakefileGenerator::init() QString destDir = ""; if(!project->first("DESTDIR").isEmpty()) destDir = Option::fixPathToTargetOS(project->first("DESTDIR") + Option::dir_sep, false, false); - project->values("MINGW_IMPORT_LIB").prepend(destDir + "lib" + project->first("TARGET") - + project->first("TARGET_VERSION_EXT") + ".a"); + project->values("MINGW_IMPORT_LIB").prepend(destDir + project->first("LIB_TARGET")); project->values("QMAKE_LFLAGS").append(QString("-Wl,--out-implib,") + fileVar("MINGW_IMPORT_LIB")); } diff --git a/qmake/generators/win32/mingw_make.h b/qmake/generators/win32/mingw_make.h index e76391080c..73018319bc 100644 --- a/qmake/generators/win32/mingw_make.h +++ b/qmake/generators/win32/mingw_make.h @@ -47,7 +47,6 @@ protected: QString escapeDependencyPath(const QString &path) const; ProString escapeDependencyPath(const ProString &path) const { return MakefileGenerator::escapeDependencyPath(path); } virtual ProString fixLibFlag(const ProString &lib); - QString getLibTarget(); virtual QString getManifestFileForRcFile() const; bool writeMakefile(QTextStream &); void init(); diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 55da3d579e..07e3531420 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -318,14 +318,12 @@ void Win32MakefileGenerator::processVars() void Win32MakefileGenerator::fixTargetExt() { - if (project->isEmpty("QMAKE_EXTENSION_STATICLIB")) - project->values("QMAKE_EXTENSION_STATICLIB").append("lib"); - if (project->isEmpty("QMAKE_EXTENSION_SHLIB")) - project->values("QMAKE_EXTENSION_SHLIB").append("dll"); - if (!project->values("QMAKE_APP_FLAG").isEmpty()) { project->values("TARGET_EXT").append(".exe"); } else if (project->isActiveConfig("shared")) { + project->values("LIB_TARGET").prepend(project->first("QMAKE_PREFIX_STATICLIB") + + project->first("TARGET") + project->first("TARGET_VERSION_EXT") + + '.' + project->first("QMAKE_EXTENSION_STATICLIB")); project->values("TARGET_EXT").append(project->first("TARGET_VERSION_EXT") + "." + project->first("QMAKE_EXTENSION_SHLIB")); project->values("TARGET").first() = project->first("QMAKE_PREFIX_SHLIB") + project->first("TARGET"); @@ -782,11 +780,6 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t) } } -QString Win32MakefileGenerator::getLibTarget() -{ - return QString(project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".lib"); -} - QString Win32MakefileGenerator::defaultInstall(const QString &t) { if((t != "target" && t != "dlltarget") || @@ -833,7 +826,7 @@ QString Win32MakefileGenerator::defaultInstall(const QString &t) } } if(project->isActiveConfig("shared") && !project->isActiveConfig("plugin")) { - QString lib_target = getLibTarget(); + ProString lib_target = project->first("LIB_TARGET"); QString src_targ = escapeFilePath( (project->isEmpty("DESTDIR") ? QString("$(DESTDIR)") : project->first("DESTDIR")) + lib_target); diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h index ea763c3175..d09ec4259d 100644 --- a/qmake/generators/win32/winmakefile.h +++ b/qmake/generators/win32/winmakefile.h @@ -66,7 +66,6 @@ protected: void processVars(); void fixTargetExt(); void processRcFileVar(); - virtual QString getLibTarget(); static QString cQuoted(const QString &str); virtual QString getManifestFileForRcFile() const; }; From cbbeed519b8bd98de71bd93c51c682f9d11158bd Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 1 Jun 2015 15:22:18 +0200 Subject: [PATCH 147/240] remove magic patching up of libraries specified by file name the assumption is that if somebody bothers to actually specify a file name, they'll most probably go all the way to specify the *correct* file name. otherwise, they'll use -L/-l flags to specify the libs in a cross-platform way and rely on qmake's magic. this code was initially added for the purpose of invoking findHighestVersion() under windows. this has been off by default for a while now. at some point, the code did also swap qt for qt-mt and vice versa if the specified one was missing. this is obviously gone for a while as well. the unix code was pretty much broken since day one: there was a regex match on lib.* against itself, which obviously could not have ever succeeded. consequently, the subsequent code ran into a path that tried the file name with a trailing dot (instead of a new extension), which never produced anything meaningful. [ChangeLog][qmake][Important Behavior Changes] The library lookup has been simplified. It may be necessary to be more explicit in some edge cases now. Change-Id: I5804943f1f7a16d38932b31675caabbda33eada7 Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake.cpp | 74 +++++++++----------------- qmake/generators/win32/winmakefile.cpp | 34 ------------ 2 files changed, 25 insertions(+), 83 deletions(-) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 1a1ba58dd1..0cd0ee596f 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -432,7 +432,7 @@ UnixMakefileGenerator::findLibraries() for (int i = 0; lflags[i]; i++) { ProStringList &l = project->values(lflags[i]); for (ProStringList::Iterator it = l.begin(); it != l.end(); ) { - QString stub, dir, extn, opt = (*it).toQString(); + QString opt = (*it).toQString(); if(opt.startsWith("-")) { if(opt.startsWith("-L")) { QString lib = opt.mid(2); @@ -444,63 +444,39 @@ UnixMakefileGenerator::findLibraries() } libdirs.insert(libidx++, f); } else if(opt.startsWith("-l")) { - stub = opt.mid(2); - } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-framework")) { - if (opt.length() == 10) - ++it; - // Skip - } - } else { - extn = dir = ""; - stub = opt; - int slsh = opt.lastIndexOf(Option::dir_sep); - if(slsh != -1) { - dir = opt.left(slsh); - stub = opt.mid(slsh+1); - } - QRegExp stub_reg("^.*lib(" + stub + "[^./=]*)\\.(.*)$"); - if(stub_reg.exactMatch(stub)) { - stub = stub_reg.cap(1); - extn = stub_reg.cap(2); - } - } - if(!stub.isEmpty()) { - stub += project->first(ProKey("QMAKE_" + stub.toUpper() + "_SUFFIX")).toQString(); - bool found = false; - ProStringList extens; - if(!extn.isNull()) - extens << extn; - else + QString lib = opt.mid(2); + lib += project->first(ProKey("QMAKE_" + lib.toUpper() + "_SUFFIX")).toQString(); + bool found = false; + ProStringList extens; extens << project->first("QMAKE_EXTENSION_SHLIB") << "a"; - for (ProStringList::Iterator extit = extens.begin(); extit != extens.end(); ++extit) { - if(dir.isNull()) { - for(QList::Iterator dep_it = libdirs.begin(); dep_it != libdirs.end(); ++dep_it) { + for (ProStringList::Iterator extit = extens.begin(); extit != extens.end(); ++extit) { + for (QList::Iterator dep_it = libdirs.begin(); + dep_it != libdirs.end(); ++dep_it) { QString pathToLib = ((*dep_it).local() + '/' + project->first("QMAKE_PREFIX_SHLIB") - + stub + "." + (*extit)); - if(exists(pathToLib)) { - (*it) = "-l" + stub; + + lib + '.' + (*extit)); + if (exists(pathToLib)) { + (*it) = "-l" + lib; found = true; break; } } - } else { - QString lib = dir + project->first("QMAKE_PREFIX_SHLIB") + stub + "." + (*extit); - if (exists(lib)) { - (*it) = lib; - found = true; - break; - } - } - } - if(!found && project->isActiveConfig("compile_libtool")) { - for(int dep_i = 0; dep_i < libdirs.size(); ++dep_i) { - if (exists(libdirs[dep_i].local() + '/' + project->first("QMAKE_PREFIX_SHLIB") + stub + Option::libtool_ext)) { - (*it) = libdirs[dep_i].real() + Option::dir_sep + project->first("QMAKE_PREFIX_SHLIB") + stub + Option::libtool_ext; - found = true; - break; + } + if (!found && project->isActiveConfig("compile_libtool")) { + for (int dep_i = 0; dep_i < libdirs.size(); ++dep_i) { + if (exists(libdirs[dep_i].local() + '/' + + project->first("QMAKE_PREFIX_SHLIB") + lib + Option::libtool_ext)) { + (*it) = libdirs[dep_i].real() + Option::dir_sep + + project->first("QMAKE_PREFIX_SHLIB") + lib + Option::libtool_ext; + found = true; + break; + } } } + } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-framework")) { + if (opt.length() == 10) + ++it; + // Skip } } ++it; diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 07e3531420..2059cc7585 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -156,40 +156,6 @@ Win32MakefileGenerator::findLibraries() if(out.isEmpty()) out = lib + ".lib"; (*it) = out; - } else if (!exists(Option::normalizePath(opt))) { - QList lib_dirs; - QString file = Option::fixPathToTargetOS(opt); - int slsh = file.lastIndexOf(Option::dir_sep); - if(slsh != -1) { - lib_dirs.append(QMakeLocalFileName(file.left(slsh+1))); - file = file.right(file.length() - slsh - 1); - } else { - lib_dirs = dirs; - } - if(file.endsWith(".lib")) { - file = file.left(file.length() - 4); - if(!file.at(file.length()-1).isNumber()) { - ProString suffix = project->first(ProKey("QMAKE_" + file.toUpper() + "_SUFFIX")); - for(QList::Iterator dep_it = lib_dirs.begin(); dep_it != lib_dirs.end(); ++dep_it) { - QString lib_tmpl(file + "%1" + suffix + ".lib"); - int ver = findHighestVersion((*dep_it).local(), file); - if(ver != -1) { - if(ver) - lib_tmpl = lib_tmpl.arg(ver); - else - lib_tmpl = lib_tmpl.arg(""); - if(slsh != -1) { - QString dir = (*dep_it).real(); - if(!dir.endsWith(Option::dir_sep)) - dir += Option::dir_sep; - lib_tmpl.prepend(dir); - } - (*it) = lib_tmpl; - break; - } - } - } - } } if(remove) { it = l.erase(it); From 5df87614e388640a4717ffcfeb478cc57575dd4e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 1 Jun 2015 20:04:22 +0200 Subject: [PATCH 148/240] remove link_highest_lib_version misfeature in retrospect, we were too conservative in 925fd32a2d8f making the "feature" optional - it simply makes no sense to have qmake automatically find the highest major (!) version of a library based on a loosely defined platform-specific convention (not standard, unlike ELF's .so versioning) with side effects. Change-Id: Iba92df433b199a9fbff88358f6e0f6835f2e813d Reviewed-by: Joerg Bornemann --- qmake/generators/win32/mingw_make.cpp | 2 +- qmake/generators/win32/winmakefile.cpp | 24 ++---------------------- qmake/generators/win32/winmakefile.h | 2 +- 3 files changed, 4 insertions(+), 24 deletions(-) diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 88a4494ec4..70b2e8325b 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -82,7 +82,7 @@ bool MingwMakefileGenerator::findLibraries() QString suffix = project->first(ProKey("QMAKE_" + steam.toUpper() + "_SUFFIX")).toQString(); for (QList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { QString extension; - int ver = findHighestVersion((*dir_it).local(), steam, "dll.a|a"); + int ver = findHighestVersion((*dir_it).local(), steam); if (ver > 0) extension += QString::number(ver); extension += suffix; diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 2059cc7585..2d070e89e2 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -50,7 +50,7 @@ Win32MakefileGenerator::Win32MakefileGenerator() : MakefileGenerator() } int -Win32MakefileGenerator::findHighestVersion(const QString &d, const QString &stem, const QString &ext) +Win32MakefileGenerator::findHighestVersion(const QString &d, const QString &stem) { QString bd = Option::normalizePath(d); if(!exists(bd)) @@ -69,30 +69,10 @@ Win32MakefileGenerator::findHighestVersion(const QString &d, const QString &stem return vover.first().toInt(); int biggest=-1; - if (project->isActiveConfig("link_highest_lib_version")) { - static QHash dirEntryListCache; - QStringList entries = dirEntryListCache.value(bd); - if (entries.isEmpty()) { - QDir dir(bd); - entries = dir.entryList(); - dirEntryListCache.insert(bd, entries); - } - - QRegExp regx(QString("((lib)?%1([0-9]*)).(%2|prl)$").arg(stem).arg(ext), Qt::CaseInsensitive); - for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) { - if(regx.exactMatch((*it))) { - if (!regx.cap(3).isEmpty()) { - bool ok = true; - int num = regx.cap(3).toInt(&ok); - biggest = qMax(biggest, (!ok ? -1 : num)); - } - } - } - } if(libInfoRead && !libinfo.values("QMAKE_PRL_CONFIG").contains("staticlib") && !libinfo.isEmpty("QMAKE_PRL_VERSION")) - biggest = qMax(biggest, libinfo.first("QMAKE_PRL_VERSION").toQString().replace(".", "").toInt()); + biggest = libinfo.first("QMAKE_PRL_VERSION").toQString().replace(".", "").toInt(); return biggest; } diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h index d09ec4259d..25b555ec86 100644 --- a/qmake/generators/win32/winmakefile.h +++ b/qmake/generators/win32/winmakefile.h @@ -57,7 +57,7 @@ protected: virtual void writeRcFilePart(QTextStream &t); - int findHighestVersion(const QString &dir, const QString &stem, const QString &ext = QLatin1String("lib")); + int findHighestVersion(const QString &dir, const QString &stem); virtual bool findLibraries(); virtual ProString fixLibFlag(const ProString &lib); From d1cebb09b68788b660c2691ede61534c5a1673cf Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 2 Jun 2015 18:28:33 +0200 Subject: [PATCH 149/240] make /LIBPATH: deduplication code more like in the unix generator Change-Id: If7e83a46b1a2ad92723a222daffa687d74636858 Reviewed-by: Joerg Bornemann --- qmake/generators/win32/winmakefile.cpp | 31 +++++++++++--------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 2d070e89e2..538ab757bd 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -94,26 +94,25 @@ Win32MakefileGenerator::findLibraries() for (int i = 0; lflags[i]; i++) { ProStringList &l = project->values(lflags[i]); for (ProStringList::Iterator it = l.begin(); it != l.end();) { - bool remove = false; QString opt = (*it).toQString(); if(opt.startsWith("/LIBPATH:")) { QString libpath = opt.mid(9); - QMakeLocalFileName l(libpath); - if (!dirs.contains(l)) { - dirs.append(l); - (*it) = "/LIBPATH:" + l.real(); - } else { - remove = true; + QMakeLocalFileName lp(libpath); + if (dirs.contains(lp)) { + it = l.erase(it); + continue; } + dirs.append(lp); + (*it) = "/LIBPATH:" + lp.real(); } else if(opt.startsWith("-L") || opt.startsWith("/L")) { QString libpath = Option::fixPathToTargetOS(opt.mid(2), false, false); - QMakeLocalFileName l(libpath); - if(!dirs.contains(l)) { - dirs.append(l); - (*it) = "/LIBPATH:" + l.real(); - } else { - remove = true; + QMakeLocalFileName lp(libpath); + if (dirs.contains(lp)) { + it = l.erase(it); + continue; } + dirs.append(lp); + (*it) = "/LIBPATH:" + lp.real(); } else if(opt.startsWith("-l") || opt.startsWith("/l")) { QString lib = opt.right(opt.length() - 2), out; if(!lib.isEmpty()) { @@ -137,11 +136,7 @@ Win32MakefileGenerator::findLibraries() out = lib + ".lib"; (*it) = out; } - if(remove) { - it = l.erase(it); - } else { - ++it; - } + ++it; } } return true; From ffe7f408ead8d70e15a2b981b9a28e5f70100173 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 2 Jun 2015 19:58:41 +0200 Subject: [PATCH 150/240] remove bizarre prl substitution code it appears to have been some weird attempt at back-mapping file names to -l arguments, which has been made ineffective with the partial #if 0. i can't even describe what it did at this point. Change-Id: Ie31cbbe7fab8b21b039bfff5877397af07731f1b Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 0cd0ee596f..8e539ca230 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -550,15 +550,7 @@ UnixMakefileGenerator::processPrlFiles() } } } else if(!opt.isNull()) { - QString lib = opt; - processPrlFile(lib); -#if 0 - if(ret) - opt = linkLib(lib, ""); -#endif - if(!opt.isEmpty()) - for (int k = 0; k < l.size(); ++k) - l[k] = l.at(k).toQString().replace(lib, opt); + processPrlFile(opt); } ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS"); From efe9c7ddbbd2055a7e942f4e358db1d29e6941f8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 22 Sep 2015 12:13:49 +0200 Subject: [PATCH 151/240] remove QMakeMetaInfo::clear() each instance of the class is used only once. Change-Id: I33e01537ee3a731c0f9758ec65c74938e4bec28c Reviewed-by: Joerg Bornemann --- qmake/meta.cpp | 8 -------- qmake/meta.h | 1 - 2 files changed, 9 deletions(-) diff --git a/qmake/meta.cpp b/qmake/meta.cpp index d7aa885541..73414df73e 100644 --- a/qmake/meta.cpp +++ b/qmake/meta.cpp @@ -50,7 +50,6 @@ QMakeMetaInfo::QMakeMetaInfo(QMakeProject *_conf) bool QMakeMetaInfo::readLib(QString lib) { - clear(); QString meta_file = findLib(lib); if(cache_vars.contains(meta_file)) { @@ -84,13 +83,6 @@ QMakeMetaInfo::readLib(QString lib) } -void -QMakeMetaInfo::clear() -{ - vars.clear(); -} - - QString QMakeMetaInfo::findLib(QString lib) { diff --git a/qmake/meta.h b/qmake/meta.h index a08b946916..a1a30fbfa8 100644 --- a/qmake/meta.h +++ b/qmake/meta.h @@ -52,7 +52,6 @@ class QMakeMetaInfo ProValueMap vars; QString meta_type; static QHash cache_vars; - void clear(); public: QMakeMetaInfo(QMakeProject *_conf); From e0470ba2fe9ab80cc857c81cdcd1687ecd909a23 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 2 Jun 2015 20:06:42 +0200 Subject: [PATCH 152/240] remove pointless code from prl processing the code had a dead variable assignment and no side effects. Change-Id: I9add8f1776f23a29c103b46dc725b9f386a4495a Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 8e539ca230..c813e50d79 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -485,14 +485,6 @@ UnixMakefileGenerator::findLibraries() return false; } -QString linkLib(const QString &file, const QString &libName) { - QString ret; - QRegExp reg("^.*lib(" + QRegExp::escape(libName) + "[^./=]*).*$"); - if(reg.exactMatch(file)) - ret = "-l" + reg.cap(1); - return ret; -} - void UnixMakefileGenerator::processPrlFiles() { @@ -527,12 +519,8 @@ UnixMakefileGenerator::processPrlFiles() } QString prl = lfn.local() + '/' + project->first("QMAKE_PREFIX_SHLIB") + lib + prl_ext; - if(processPrlFile(prl)) { - if(prl.startsWith(lfn.local())) - prl.replace(0, lfn.local().length(), lfn.real()); - opt = linkLib(prl, lib); + if (processPrlFile(prl)) break; - } } } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-F")) { QMakeLocalFileName f(opt.right(opt.length()-2)); From 3cd49cb628c61d8735b5893d33e779a5c7a463e8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 2 Jun 2015 20:32:20 +0200 Subject: [PATCH 153/240] remove pointless code path there is no need to consider the "-framework foo" syntax, as we fully control the list and insert elements exclusively as "-framework" "foo" a few lines down. Change-Id: I95fa8b46f53673ea3df1a67a2a44d11f7d679cc6 Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index c813e50d79..d58cb352ae 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -582,17 +582,9 @@ UnixMakefileGenerator::processPrlFiles() } bool found = false; for(int x = 0; x < lflags[arch].size(); ++x) { - ProString xf = lflags[arch].at(x); - if(xf.startsWith("-framework")) { - ProString framework; - if(xf.length() > 11) - framework = xf.mid(11); - else - framework = lflags[arch].at(++x); - if(framework == opt) { - found = true; - break; - } + if (lflags[arch].at(x) == "-framework" && lflags[arch].at(++x) == opt) { + found = true; + break; } } if(!found) { From ba9f4942b0813f135d2c7208ea27a03cd5c1cae5 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 2 Jun 2015 20:42:38 +0200 Subject: [PATCH 154/240] remove questionable libtool "compatibility" code from prl processing this code would get enabled when *not* compiling with libtool, and would try to use the real library in .libs/ when one tried to link the .la file (i.e., it would reproduce libtool's functionality). that directory structure is found only in build directories, so this code was apparently meant to support mixed projects. that doesn't sound useful. on top of that, the other code paths that were supposed to treat .la files like .prl files were disabled before initial release (because Somebody (TM) noticed that their code "doesn't behave well"). this code here did the same thing, but at the wrong abstraction level. as a side effect, this removes an infinite recursion problem in that code. Task-number: QTBUG-46910 Change-Id: If5291f5ff42c1412075c195753162c54598a250e Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index d58cb352ae..3b0080313b 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -508,17 +508,8 @@ UnixMakefileGenerator::processPrlFiles() QString lib = opt.right(opt.length() - 2); QString prl_ext = project->first(ProKey("QMAKE_" + lib.toUpper() + "_SUFFIX")).toQString(); for(int dep_i = 0; dep_i < libdirs.size(); ++dep_i) { - const QMakeLocalFileName &lfn = libdirs[dep_i]; - if(!project->isActiveConfig("compile_libtool")) { //give them the .libs.. - QString la = lfn.local() + '/' + project->first("QMAKE_PREFIX_SHLIB") + lib + Option::libtool_ext; - if (exists(la) && QFile::exists(lfn.local() + "/.libs")) { - QString dot_libs = lfn.real() + Option::dir_sep + ".libs"; - l.append("-L" + dot_libs); - libdirs.insert(libidx++, QMakeLocalFileName(dot_libs)); - } - } - - QString prl = lfn.local() + '/' + project->first("QMAKE_PREFIX_SHLIB") + lib + prl_ext; + QString prl = libdirs[dep_i].local() + '/' + + project->first("QMAKE_PREFIX_SHLIB") + lib + prl_ext; if (processPrlFile(prl)) break; } From 119cb65017680fcf5b480fedd516256196b7d78e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 18 Aug 2015 18:07:57 +0200 Subject: [PATCH 155/240] remove support for CONFIG+=compile_libtool "why not use libtool?" -- sam "srsly dude?!" -- ossi [ChangeLog][qmake] Support for CONFIG+=compile_libtool was removed. Use CONFIG+=create_libtool and/or custom compilers instead. in addition to its utter insanity and superfluousness, this feature was apparently quite broken anyway (QTBUG-35745). Change-Id: I8147a2953f5f065735ae3a2206cd5d33a7c1809a Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake.cpp | 73 ++--------------------------- qmake/generators/unix/unixmake2.cpp | 37 +++------------ 2 files changed, 10 insertions(+), 100 deletions(-) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 3b0080313b..2b69e8fad9 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -50,8 +50,6 @@ UnixMakefileGenerator::init() project->values("ICON") = project->values("RC_FILE"); if(project->isEmpty("QMAKE_EXTENSION_PLUGIN")) project->values("QMAKE_EXTENSION_PLUGIN").append(project->first("QMAKE_EXTENSION_SHLIB")); - if(project->isEmpty("QMAKE_LIBTOOL")) - project->values("QMAKE_LIBTOOL").append("libtool --silent"); project->values("QMAKE_ORIG_TARGET") = project->values("TARGET"); @@ -144,8 +142,6 @@ UnixMakefileGenerator::init() if(project->isActiveConfig("GNUmake") && !project->isEmpty("QMAKE_CFLAGS_DEPS")) include_deps = true; //do not generate deps - if(project->isActiveConfig("compile_libtool")) - Option::obj_ext = ".lo"; //override the .o MakefileGenerator::init(); @@ -225,7 +221,7 @@ UnixMakefileGenerator::init() project->values(runCompImp).append("$(" + compiler + ") " + compile_flag + " " + var("QMAKE_CC_O_FLAG") + "\"$@\" \"$<\""); } - if (project->isActiveConfig("mac") && !project->isEmpty("TARGET") && !project->isActiveConfig("compile_libtool") && + if (project->isActiveConfig("mac") && !project->isEmpty("TARGET") && ((project->isActiveConfig("build_pass") || project->isEmpty("BUILDS")))) { ProString bundle; if(project->isActiveConfig("bundle") && !project->isEmpty("QMAKE_BUNDLE_EXTENSION")) { @@ -302,49 +298,6 @@ UnixMakefileGenerator::init() project->values("QMAKE_INTERNAL_PRL_LIBS") << "QMAKE_AR_SUBLIBS"; } } - - if(project->isActiveConfig("compile_libtool")) { - static const char * const libtoolify[] = { - "QMAKE_RUN_CC", "QMAKE_RUN_CC_IMP", "QMAKE_RUN_CXX", "QMAKE_RUN_CXX_IMP", - "QMAKE_LINK_THREAD", "QMAKE_LINK", "QMAKE_AR_CMD", "QMAKE_LINK_SHLIB_CMD", 0 - }; - for (int i = 0; libtoolify[i]; i++) { - ProStringList &l = project->values(libtoolify[i]); - if(!l.isEmpty()) { - QString libtool_flags, comp_flags; - if (!strncmp(libtoolify[i], "QMAKE_LINK", 10) || !strcmp(libtoolify[i], "QMAKE_AR_CMD")) { - libtool_flags += " --mode=link"; - if(project->isActiveConfig("staticlib")) { - libtool_flags += " -static"; - } else { - if(!project->isEmpty("QMAKE_LIB_FLAG")) { - int maj = project->first("VER_MAJ").toInt(); - int min = project->first("VER_MIN").toInt(); - int pat = project->first("VER_PAT").toInt(); - comp_flags += " -version-info " + QString::number(10*maj + min) + - ":" + QString::number(pat) + ":0"; - if (strcmp(libtoolify[i], "QMAKE_AR_CMD")) { - QString rpath = Option::output_dir; - if(!project->isEmpty("DESTDIR")) { - rpath = project->first("DESTDIR").toQString(); - if(QDir::isRelativePath(rpath)) - rpath.prepend(Option::output_dir + Option::dir_sep); - } - comp_flags += " -rpath " + escapeFilePath(Option::fixPathToTargetOS(rpath, false)); - } - } - } - if(project->isActiveConfig("plugin")) - libtool_flags += " -module"; - } else { - libtool_flags += " --mode=compile"; - } - l.first().prepend("$(LIBTOOL)" + libtool_flags + " "); - if(!comp_flags.isEmpty()) - l.first() += comp_flags; - } - } - } } QStringList @@ -462,17 +415,6 @@ UnixMakefileGenerator::findLibraries() } } } - if (!found && project->isActiveConfig("compile_libtool")) { - for (int dep_i = 0; dep_i < libdirs.size(); ++dep_i) { - if (exists(libdirs[dep_i].local() + '/' - + project->first("QMAKE_PREFIX_SHLIB") + lib + Option::libtool_ext)) { - (*it) = libdirs[dep_i].real() + Option::dir_sep - + project->first("QMAKE_PREFIX_SHLIB") + lib + Option::libtool_ext; - found = true; - break; - } - } - } } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-framework")) { if (opt.length() == 10) ++it; @@ -654,16 +596,7 @@ UnixMakefileGenerator::defaultInstall(const QString &t) uninst.append("-$(DEL_FILE) " + dst); } - if (bundle == NoBundle && project->isActiveConfig("compile_libtool")) { - QString src_targ = escapeFilePath(target); - if(src_targ == "$(TARGET)") - src_targ = "$(TARGETL)"; - QString dst_dir = fileFixify(targetdir, FileFixifyAbsolute); - if(QDir::isRelativePath(dst_dir)) - dst_dir = Option::fixPathToTargetOS(Option::output_dir + Option::dir_sep + dst_dir); - ret = "-$(LIBTOOL) --mode=install cp " + src_targ + ' ' + escapeFilePath(filePrefixRoot(root, dst_dir)); - uninst.append("-$(LIBTOOL) --mode=uninstall " + src_targ); - } else { + { QString src_targ = target; if(!destdir.isEmpty()) src_targ = Option::fixPathToTargetOS(destdir + target, false); @@ -781,7 +714,7 @@ UnixMakefileGenerator::defaultInstall(const QString &t) if(type == "prl" && project->isActiveConfig("create_prl") && !project->isActiveConfig("no_install_prl") && !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) meta = prlFileName(false); - if(type == "libtool" && project->isActiveConfig("create_libtool") && !project->isActiveConfig("compile_libtool")) + if (type == "libtool" && project->isActiveConfig("create_libtool")) meta = libtoolFileName(false); if(type == "pkgconfig" && project->isActiveConfig("create_pc")) meta = pkgConfigFileName(false); diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 4babd728ff..cd4339edec 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -53,13 +53,8 @@ UnixMakefileGenerator::writePrlFile(QTextStream &t) { MakefileGenerator::writePrlFile(t); // libtool support - if(project->isActiveConfig("create_libtool") && project->first("TEMPLATE") == "lib") { //write .la - if(project->isActiveConfig("compile_libtool")) - warn_msg(WarnLogic, "create_libtool specified with compile_libtool can lead to conflicting .la\n" - "formats, create_libtool has been disabled\n"); - else - writeLibtoolFile(); + writeLibtoolFile(); } // pkg-config support if(project->isActiveConfig("create_pc") && project->first("TEMPLATE") == "lib") @@ -214,8 +209,6 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "AR = " << var("QMAKE_AR") << endl; t << "RANLIB = " << var("QMAKE_RANLIB") << endl; - if(project->isActiveConfig("compile_libtool")) - t << "LIBTOOL = " << var("QMAKE_LIBTOOL") << endl; t << "SED = " << var("QMAKE_STREAM_EDITOR") << endl; t << "STRIP = " << var("QMAKE_STRIP") << endl; @@ -274,8 +267,6 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) // comment is also important as otherwise quoted use of "$(DESTDIR)" would include this // spacing. t << "DESTDIR = " << fileVar("DESTDIR") << "#avoid trailing-slash linebreak\n"; - if(project->isActiveConfig("compile_libtool")) - t << "TARGETL = " << fileVar("TARGET_la") << endl; t << "TARGET = " << fileVar("TARGET") << endl; // ### mixed use! if(project->isActiveConfig("plugin")) { t << "TARGETD = " << fileVar("TARGET") << endl; @@ -600,10 +591,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(!project->isEmpty("QMAKE_PRE_LINK")) t << "\n\t" << var("QMAKE_PRE_LINK"); - if(project->isActiveConfig("compile_libtool")) { - t << "\n\t" - << var("QMAKE_LINK_SHLIB_CMD"); - } else if(project->isActiveConfig("plugin")) { + if (project->isActiveConfig("plugin")) { t << "\n\t" << "-$(DEL_FILE) $(TARGET)\n\t" << var("QMAKE_LINK_SHLIB_CMD"); @@ -747,8 +735,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) writeMakeQmake(t); if(project->isEmpty("QMAKE_FAILED_REQUIREMENTS") && !project->isActiveConfig("no_autoqmake")) { QStringList meta_files; - if(project->isActiveConfig("create_libtool") && project->first("TEMPLATE") == "lib" && - !project->isActiveConfig("compile_libtool")) { //libtool + if (project->isActiveConfig("create_libtool") && project->first("TEMPLATE") == "lib") { //libtool meta_files += libtoolFileName(); } if(project->isActiveConfig("create_pc") && project->first("TEMPLATE") == "lib") { //pkg-config @@ -983,10 +970,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "clean:" << clean_targets << "\n\t"; if(!project->isEmpty("OBJECTS")) { - if(project->isActiveConfig("compile_libtool")) - t << "-$(LIBTOOL) --mode=clean $(DEL_FILE) $(OBJECTS)\n\t"; - else - t << "-$(DEL_FILE) $(OBJECTS)\n\t"; + t << "-$(DEL_FILE) $(OBJECTS)\n\t"; } if(doPrecompiledHeaders() && !project->isEmpty("PRECOMPILED_HEADER")) { ProStringList precomp_files; @@ -1043,8 +1027,6 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(!project->isEmpty("QMAKE_BUNDLE")) { QString bundlePath = escapeFilePath(destdir + project->first("QMAKE_BUNDLE")); t << "\t-$(DEL_FILE) -r " << bundlePath << endl; - } else if(project->isActiveConfig("compile_libtool")) { - t << "\t-$(LIBTOOL) --mode=clean $(DEL_FILE) $(TARGET)\n"; } else if (project->isActiveConfig("staticlib") || project->isActiveConfig("plugin")) { t << "\t-$(DEL_FILE) " << escapeFilePath(destdir) << "$(TARGET) \n"; } else if (project->values("QMAKE_APP_FLAG").isEmpty()) { @@ -1185,17 +1167,13 @@ void UnixMakefileGenerator::init2() } else { project->values("TARGETA").append(project->first("DESTDIR") + project->first("QMAKE_PREFIX_STATICLIB") + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_STATICLIB")); - if(project->isActiveConfig("compile_libtool")) - project->values("TARGET_la") = ProStringList(project->first("DESTDIR") + "lib" + project->first("TARGET") + Option::libtool_ext); ProStringList &ar_cmd = project->values("QMAKE_AR_CMD"); if (!ar_cmd.isEmpty()) ar_cmd[0] = ar_cmd.at(0).toQString().replace("(TARGET)","(TARGETA)"); else ar_cmd.append("$(AR) $(TARGETA) $(OBJECTS)"); - if(project->isActiveConfig("compile_libtool")) { - project->values("TARGET") = project->values("TARGET_la"); - } else if(!project->isEmpty("QMAKE_BUNDLE")) { + if (!project->isEmpty("QMAKE_BUNDLE")) { ProString bundle_loc = project->first("QMAKE_BUNDLE_LOCATION"); if(!bundle_loc.isEmpty() && !bundle_loc.startsWith("/")) bundle_loc.prepend("/"); @@ -1349,7 +1327,7 @@ void UnixMakefileGenerator::init2() project->values("QMAKE_CFLAGS") += project->values("QMAKE_CFLAGS_PLUGIN"); project->values("QMAKE_CXXFLAGS") += project->values("QMAKE_CXXFLAGS_PLUGIN"); project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_PLUGIN"); - if(project->isActiveConfig("plugin_with_soname") && !project->isActiveConfig("compile_libtool")) + if (project->isActiveConfig("plugin_with_soname")) project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_SONAME"); } else { project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_SHLIB"); @@ -1368,8 +1346,7 @@ void UnixMakefileGenerator::init2() project->first("VER_MIN") + "." + project->first("VER_PAT")); } - if(!project->isActiveConfig("compile_libtool")) - project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_SONAME"); + project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_SONAME"); } } From b39cda2ec2f8ffcd2e26c7a2f1a9f19d47f46b30 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 14 Aug 2015 18:55:04 +0200 Subject: [PATCH 156/240] remove QMAKE__SUFFIX support this feature was added with a dubious commit message a decade ago, was undocumented, and there are no public traces of it being used. if i had to guess what it was meant for: to be able to consistently use -lfoo throughout a project and centrally (e.g., in .qmake.cache) choose to use foo (bar possibly being "d") instead. however, more explicit methods are being used instead, including in qt itself. Change-Id: Ic3a98dc3aec59876f26909fbf9f7aba32baa05bf Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake.cpp | 5 +---- qmake/generators/win32/mingw_make.cpp | 2 -- qmake/generators/win32/winmakefile.cpp | 2 -- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 2b69e8fad9..25f686646b 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -398,7 +398,6 @@ UnixMakefileGenerator::findLibraries() libdirs.insert(libidx++, f); } else if(opt.startsWith("-l")) { QString lib = opt.mid(2); - lib += project->first(ProKey("QMAKE_" + lib.toUpper() + "_SUFFIX")).toQString(); bool found = false; ProStringList extens; extens << project->first("QMAKE_EXTENSION_SHLIB") << "a"; @@ -409,7 +408,6 @@ UnixMakefileGenerator::findLibraries() + project->first("QMAKE_PREFIX_SHLIB") + lib + '.' + (*extit)); if (exists(pathToLib)) { - (*it) = "-l" + lib; found = true; break; } @@ -448,10 +446,9 @@ UnixMakefileGenerator::processPrlFiles() libdirs.insert(libidx++, l); } else if(opt.startsWith("-l")) { QString lib = opt.right(opt.length() - 2); - QString prl_ext = project->first(ProKey("QMAKE_" + lib.toUpper() + "_SUFFIX")).toQString(); for(int dep_i = 0; dep_i < libdirs.size(); ++dep_i) { QString prl = libdirs[dep_i].local() + '/' - + project->first("QMAKE_PREFIX_SHLIB") + lib + prl_ext; + + project->first("QMAKE_PREFIX_SHLIB") + lib; if (processPrlFile(prl)) break; } diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 70b2e8325b..506aff5c6f 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -79,13 +79,11 @@ bool MingwMakefileGenerator::findLibraries() if ((*it).startsWith("-l")) { QString steam = (*it).mid(2).toQString(); ProString out; - QString suffix = project->first(ProKey("QMAKE_" + steam.toUpper() + "_SUFFIX")).toQString(); for (QList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { QString extension; int ver = findHighestVersion((*dir_it).local(), steam); if (ver > 0) extension += QString::number(ver); - extension += suffix; if (QMakeMetaInfo::libExists((*dir_it).local() + '/' + steam) || exists((*dir_it).local() + '/' + steam + extension + ".a") || exists((*dir_it).local() + '/' + steam + extension + ".dll.a")) { diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 538ab757bd..3d511ea7e8 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -116,14 +116,12 @@ Win32MakefileGenerator::findLibraries() } else if(opt.startsWith("-l") || opt.startsWith("/l")) { QString lib = opt.right(opt.length() - 2), out; if(!lib.isEmpty()) { - ProString suffix = project->first(ProKey("QMAKE_" + lib.toUpper() + "_SUFFIX")); for(QList::Iterator it = dirs.begin(); it != dirs.end(); ++it) { QString extension; int ver = findHighestVersion((*it).local(), lib); if(ver > 0) extension += QString::number(ver); - extension += suffix; extension += ".lib"; if (QMakeMetaInfo::libExists((*it).local() + '/' + lib) || exists((*it).local() + '/' + lib + extension)) { From 8233e401b1892b27e669546c8df02c2320e8e775 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 27 Sep 2015 12:56:59 -0700 Subject: [PATCH 157/240] QLocale: remove (harmless) dead code On line 92 and on line 146, len == 2 or len == 3, so uc1 and uc2 cannot be 0, ever. Found by Coverity, CID 11013 and CID 11012. Change-Id: I42e7ef1a481840699a8dffff1407edefd3e7aa4f Reviewed-by: Oswald Buddenhagen --- src/corelib/tools/qlocale.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 181daa04e4..57ef53eea4 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -89,9 +89,9 @@ QLocale::Language QLocalePrivate::codeToLanguage(const QString &code) int len = code.length(); if (len != 2 && len != 3) return QLocale::C; - ushort uc1 = len-- > 0 ? code[0].toLower().unicode() : 0; - ushort uc2 = len-- > 0 ? code[1].toLower().unicode() : 0; - ushort uc3 = len-- > 0 ? code[2].toLower().unicode() : 0; + ushort uc1 = code[0].toLower().unicode(); + ushort uc2 = code[1].toLower().unicode(); + ushort uc3 = len > 2 ? code[2].toLower().unicode() : 0; const unsigned char *c = language_code_list; for (; *c != 0; c += 3) { @@ -145,9 +145,9 @@ QLocale::Country QLocalePrivate::codeToCountry(const QString &code) int len = code.length(); if (len != 2 && len != 3) return QLocale::AnyCountry; - ushort uc1 = len-- > 0 ? code[0].toUpper().unicode() : 0; - ushort uc2 = len-- > 0 ? code[1].toUpper().unicode() : 0; - ushort uc3 = len-- > 0 ? code[2].toUpper().unicode() : 0; + ushort uc1 = code[0].toUpper().unicode(); + ushort uc2 = code[1].toUpper().unicode(); + ushort uc3 = len > 2 ? code[2].toUpper().unicode() : 0; const unsigned char *c = country_code_list; for (; *c != 0; c += 3) { From a2f501f9394660ad68a9b559d7e87ddfd1f4bd48 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 11 Dec 2014 14:32:59 -0800 Subject: [PATCH 158/240] Make -dbus-linked the default on all platforms [ChangeLog][QtDBus] The QtDBus library now links directly to the libdbus-1 system library if it was detected at configure time. To force linking to the library, pass option -dbus-linked to configure; to force dynamically loading at runtime, use -dbus-runtime. Task-number: QTBUG-14131 Change-Id: Ie33d1f22f85b465ab0ce166b8f17b8491eae1c21 Reviewed-by: Oswald Buddenhagen --- configure | 29 +++++++++++++++++++++-------- tools/configure/configureapp.cpp | 14 ++++++++------ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/configure b/configure index 4ca3187238..3bcf2dde4f 100755 --- a/configure +++ b/configure @@ -1986,7 +1986,8 @@ while [ "$#" -gt 0 ]; do if [ "$VAL" = "no" ] || [ "$VAL" = "linked" ] || [ "$VAL" = "runtime" ]; then CFG_DBUS="$VAL" elif [ "$VAL" = "yes" ]; then - CFG_DBUS="runtime" + # keep as auto, we'll auto-detect whether to go linked or runtime later + CFG_DBUS=auto else UNKNOWN_OPT=yes fi @@ -1998,6 +1999,13 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; + dbus-runtime) + if [ "$VAL" = "yes" ]; then + CFG_DBUS="runtime" + else + UNKNOWN_OPT=yes + fi + ;; nis) if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then CFG_NIS="$VAL" @@ -2631,8 +2639,8 @@ Additional options: -pch ............... Use precompiled header support. -no-dbus ........... Do not compile the Qt D-Bus module. - + -dbus .............. Compile the Qt D-Bus module and dynamically load libdbus-1. - -dbus-linked ....... Compile the Qt D-Bus module and link to libdbus-1. + + -dbus-linked ....... Compile the Qt D-Bus module and link to libdbus-1. + -dbus-runtime ...... Compile the Qt D-Bus module and dynamically load libdbus-1. -reduce-relocations ..... Reduce relocations in the libraries through extra linker optimizations (Qt/X11 and Qt for Embedded Linux only; @@ -5027,10 +5035,10 @@ if [ "$CFG_ICONV" != "no" ]; then fi # auto-detect libdbus-1 support -if [ "$CFG_DBUS" = "auto" ]; then - CFG_DBUS="runtime" -fi -if [ "$CFG_DBUS" = "linked" ]; then +# auto: detect if libdbus-1 is present; if so, link to it +# linked: fail if libdbus-1 is not present; otherwise link to it +# runtime: no detection (cannot fail), load libdbus-1 at runtime +if [ "$CFG_DBUS" = "auto" ] || [ "$CFG_DBUS" = "linked" ]; then if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --atleast-version="$MIN_DBUS_1_VERSION" dbus-1 2>/dev/null; then QT_CFLAGS_DBUS=`$PKG_CONFIG --cflags dbus-1 2>/dev/null` QT_LIBS_DBUS=`$PKG_CONFIG --libs dbus-1 2>/dev/null` @@ -5046,14 +5054,19 @@ if [ "$CFG_DBUS" = "linked" ]; then QT_CFLAGS_DBUS=`env -i PATH="$PATH" pkg-config --cflags dbus-1 2>/dev/null` fi QMakeVar set QT_HOST_CFLAGS_DBUS "$QT_CFLAGS_DBUS" + CFG_DBUS=linked else - if [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then + # Failed to compile the test, so it's an error if CFG_DBUS is "linked" + if [ "$CFG_DBUS" = "linked" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then echo "The Qt D-Bus module cannot be enabled because libdbus-1 version $MIN_DBUS_1_VERSION was not found." [ -z "$PKG_CONFIG" ] && echo " Use of pkg-config is not enabled, maybe you want to pass -pkg-config?" 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_DBUS is "auto" here + CFG_DBUS=runtime fi fi fi diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 17f19361f7..c54bc9426e 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -904,13 +904,15 @@ void Configure::parseCmdLine() } else if (configCmdLine.at(i) == "-no-qdbus") { dictionary[ "DBUS" ] = "no"; } else if (configCmdLine.at(i) == "-qdbus") { - dictionary[ "DBUS" ] = "yes"; + dictionary[ "DBUS" ] = "auto"; } else if (configCmdLine.at(i) == "-no-dbus") { dictionary[ "DBUS" ] = "no"; } else if (configCmdLine.at(i) == "-dbus") { - dictionary[ "DBUS" ] = "yes"; + dictionary[ "DBUS" ] = "auto"; } else if (configCmdLine.at(i) == "-dbus-linked") { dictionary[ "DBUS" ] = "linked"; + } else if (configCmdLine.at(i) == "-dbus-runtime") { + dictionary[ "DBUS" ] = "runtime"; } else if (configCmdLine.at(i) == "-audio-backend") { dictionary[ "AUDIO_BACKEND" ] = "yes"; } else if (configCmdLine.at(i) == "-no-audio-backend") { @@ -2023,8 +2025,8 @@ bool Configure::displayHelp() desc("LIBPROXY", "no", "-no-libproxy", "Do not compile in libproxy support."); desc("LIBPROXY", "yes", "-libproxy", "Compile in libproxy support (for cross compilation targets).\n"); desc("DBUS", "no", "-no-dbus", "Do not compile in D-Bus support."); - desc("DBUS", "yes", "-dbus", "Compile in D-Bus support and load libdbus-1\ndynamically."); desc("DBUS", "linked", "-dbus-linked", "Compile in D-Bus support and link to libdbus-1.\n"); + desc("DBUS", "runtime", "-dbus-runtime", "Compile in D-Bus support and load libdbus-1\ndynamically."); desc("AUDIO_BACKEND", "no","-no-audio-backend", "Do not compile in the platform audio backend into\nQt Multimedia."); desc("AUDIO_BACKEND", "yes","-audio-backend", "Compile in the platform audio backend into Qt Multimedia.\n"); desc("WMF_BACKEND", "no","-no-wmf-backend", "Do not compile in the windows media foundation backend\ninto Qt Multimedia."); @@ -2496,7 +2498,7 @@ void Configure::autoDetection() if (dictionary["LIBPROXY"] == "auto") dictionary["LIBPROXY"] = checkAvailability("LIBPROXY") ? "yes" : "no"; if (dictionary["DBUS"] == "auto") - dictionary["DBUS"] = checkAvailability("DBUS") ? "yes" : "no"; + dictionary["DBUS"] = checkAvailability("DBUS") ? "linked" : "runtime"; if (dictionary["QML_DEBUG"] == "auto") dictionary["QML_DEBUG"] = dictionary["QML"] == "yes" ? "yes" : "no"; if (dictionary["AUDIO_BACKEND"] == "auto") @@ -2966,7 +2968,7 @@ void Configure::generateOutputVars() if (dictionary[ "LIBPROXY" ] == "yes") qtConfig += "libproxy"; - if (dictionary[ "DBUS" ] == "yes") + if (dictionary[ "DBUS" ] == "runtime") qtConfig += "dbus"; else if (dictionary[ "DBUS" ] == "linked") qtConfig += "dbus dbus-linked"; @@ -3076,7 +3078,7 @@ void Configure::generateOutputVars() qmakeVars += QString("OPENSSL_LIBS += -L%1/lib").arg(opensslPath); } } - if (dictionary[ "DBUS" ] != "no") { + if (dictionary[ "DBUS" ] == "linked") { if (!dbusPath.isEmpty()) { qmakeVars += QString("QT_CFLAGS_DBUS = -I%1/include").arg(dbusPath); qmakeVars += QString("QT_LIBS_DBUS = -L%1/lib").arg(dbusPath); From e9365c2c2fecbc779c44456fb1c946905a670684 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 28 Sep 2015 15:26:57 -0700 Subject: [PATCH 159/240] Revert "Add support for same-file intrinsics with Clang 3.7" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 39c2b8c5c12dfb8560fa04ce346a129adb223e29. The feature is not working: $ clang -c -o /dev/null -msse2 -include tmmintrin.h -xc /dev/null In file included from :316: In file included from :1: /home/thiago/clang3.7/bin/../lib/clang/3.7.0/include/tmmintrin.h:28:2: error: "SSSE3 instruction set not enabled" For reference: $ icpc -c -o /dev/null -msse2 -include tmmintrin.h -xc /dev/null; echo $? 0 $ gcc -c -o /dev/null -msse2 -include tmmintrin.h -xc /dev/null; echo $? 0 Change-Id: I42e7ef1a481840699a8dffff140844cb8872ed6e Reviewed-by: Sérgio Martins --- src/corelib/tools/qsimd_p.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index bb9c26f762..1e8b3420cf 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -54,9 +54,9 @@ * for the x86 and ARM intrinsics: * - GCC: the -mXXX or march=YYY flag is necessary before #include * up to 4.8; GCC >= 4.9 can include unconditionally - * - Clang: same as GCC, with unconditional inclusion with version 3.7 * - Intel CC: #include can happen unconditionally * - MSVC: #include can happen unconditionally + * - RVCT: ??? * * We will try to include all headers possible under this configuration. * @@ -138,8 +138,7 @@ #define QT_COMPILER_SUPPORTS(x) (QT_COMPILER_SUPPORTS_ ## x - 0) #if (defined(Q_CC_INTEL) || defined(Q_CC_MSVC) \ - || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409) \ - || (defined(Q_CC_CLANG) && Q_CC_CLANG >= 307)) \ + || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409)) \ && !defined(QT_BOOTSTRAPPED) # define QT_COMPILER_SUPPORTS_SIMD_ALWAYS # define QT_COMPILER_SUPPORTS_HERE(x) QT_COMPILER_SUPPORTS(x) From 906d92bde4d6c56bc73d3abee7652b3b6ade6446 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 30 Sep 2015 14:49:31 -0700 Subject: [PATCH 160/240] Fix missing "We mean it" in qtbase private headers Change-Id: I42e7ef1a481840699a8dffff1408dfd4fd9c8e32 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/dbus/dbus_minimal_p.h | 11 +++++++++++ src/gui/kernel/qpaintdevicewindow_p.h | 11 +++++++++++ src/gui/painting/qrgba64_p.h | 11 +++++++++++ src/network/ssl/qsslpresharedkeyauthenticator_p.h | 11 +++++++++++ .../accessibility/qaccessiblebridgeutils_p.h | 11 +++++++++++ src/platformsupport/dbusmenu/qdbusmenutypes_p.h | 11 +++++++++++ src/platformsupport/dbustray/qdbustraytypes_p.h | 11 +++++++++++ .../dbustray/qxdgnotificationproxy_p.h | 11 +++++++++++ src/platformsupport/input/tslib/qtslib_p.h | 11 +++++++++++ src/widgets/accessible/qaccessiblewidgetfactory_p.h | 11 +++++++++++ 10 files changed, 110 insertions(+) diff --git a/src/dbus/dbus_minimal_p.h b/src/dbus/dbus_minimal_p.h index 7ebd82dbf8..f0a29540c8 100644 --- a/src/dbus/dbus_minimal_p.h +++ b/src/dbus/dbus_minimal_p.h @@ -34,6 +34,17 @@ #ifndef DBUS_MINIMAL_P_H #define DBUS_MINIMAL_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + extern "C" { // Equivalent to dbus-arch-deps.h diff --git a/src/gui/kernel/qpaintdevicewindow_p.h b/src/gui/kernel/qpaintdevicewindow_p.h index e234906fe0..071f2ee54c 100644 --- a/src/gui/kernel/qpaintdevicewindow_p.h +++ b/src/gui/kernel/qpaintdevicewindow_p.h @@ -34,6 +34,17 @@ #ifndef QPAINTDEVICEWINDOW_P_H #define QPAINTDEVICEWINDOW_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #include #include diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h index c6cbe666ac..724658ad94 100644 --- a/src/gui/painting/qrgba64_p.h +++ b/src/gui/painting/qrgba64_p.h @@ -34,6 +34,17 @@ #ifndef QRGBA64_P_H #define QRGBA64_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #include #include diff --git a/src/network/ssl/qsslpresharedkeyauthenticator_p.h b/src/network/ssl/qsslpresharedkeyauthenticator_p.h index ba7a740907..c57b6b10ca 100644 --- a/src/network/ssl/qsslpresharedkeyauthenticator_p.h +++ b/src/network/ssl/qsslpresharedkeyauthenticator_p.h @@ -34,6 +34,17 @@ #ifndef QSSLPRESHAREDKEYAUTHENTICATOR_P_H #define QSSLPRESHAREDKEYAUTHENTICATOR_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/accessibility/qaccessiblebridgeutils_p.h b/src/platformsupport/accessibility/qaccessiblebridgeutils_p.h index fca3e16a68..4e52e4b6fc 100644 --- a/src/platformsupport/accessibility/qaccessiblebridgeutils_p.h +++ b/src/platformsupport/accessibility/qaccessiblebridgeutils_p.h @@ -34,6 +34,17 @@ #ifndef QACCESSIBLEBRIDGEUTILS_H #define QACCESSIBLEBRIDGEUTILS_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #include diff --git a/src/platformsupport/dbusmenu/qdbusmenutypes_p.h b/src/platformsupport/dbusmenu/qdbusmenutypes_p.h index 8dae75281c..bc9f064f88 100644 --- a/src/platformsupport/dbusmenu/qdbusmenutypes_p.h +++ b/src/platformsupport/dbusmenu/qdbusmenutypes_p.h @@ -34,6 +34,17 @@ #ifndef QDBUSMENUTYPES_H #define QDBUSMENUTYPES_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #include #include diff --git a/src/platformsupport/dbustray/qdbustraytypes_p.h b/src/platformsupport/dbustray/qdbustraytypes_p.h index e6f200362f..d8e52b932d 100644 --- a/src/platformsupport/dbustray/qdbustraytypes_p.h +++ b/src/platformsupport/dbustray/qdbustraytypes_p.h @@ -35,6 +35,17 @@ #ifndef QDBUSTRAYTYPES_P_H #define QDBUSTRAYTYPES_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #ifndef QT_NO_SYSTEMTRAYICON #include diff --git a/src/platformsupport/dbustray/qxdgnotificationproxy_p.h b/src/platformsupport/dbustray/qxdgnotificationproxy_p.h index 3e573cb118..5c74405ae8 100644 --- a/src/platformsupport/dbustray/qxdgnotificationproxy_p.h +++ b/src/platformsupport/dbustray/qxdgnotificationproxy_p.h @@ -45,6 +45,17 @@ #ifndef QXDGNOTIFICATIONPROXY_P_H #define QXDGNOTIFICATIONPROXY_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #include #include diff --git a/src/platformsupport/input/tslib/qtslib_p.h b/src/platformsupport/input/tslib/qtslib_p.h index c3ee6697fa..b6448c67d7 100644 --- a/src/platformsupport/input/tslib/qtslib_p.h +++ b/src/platformsupport/input/tslib/qtslib_p.h @@ -34,6 +34,17 @@ #ifndef QTSLIB_H #define QTSLIB_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include struct tsdev; diff --git a/src/widgets/accessible/qaccessiblewidgetfactory_p.h b/src/widgets/accessible/qaccessiblewidgetfactory_p.h index b3f9d8a251..d94f2d1cb2 100644 --- a/src/widgets/accessible/qaccessiblewidgetfactory_p.h +++ b/src/widgets/accessible/qaccessiblewidgetfactory_p.h @@ -36,6 +36,17 @@ #ifndef QACCESSIBLEWIDGETFACTORY_H #define QACCESSIBLEWIDGETFACTORY_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + QT_BEGIN_NAMESPACE QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object); From 918f1cd3d822eba5fcad013b1764d8b5d7f15423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 1 Oct 2015 12:34:38 +0200 Subject: [PATCH 161/240] Xcode: Set DYLD_IMAGE_SUFFIX=_debug when launching Debug configuration This ensures that we pick up the debug version of the Qt libraries in a debug and release build. Change-Id: I7fc1ed72a6f01b138608413954d4b9e45b7782a0 Reviewed-by: Oswald Buddenhagen Reviewed-by: Richard Moe Gustavsen --- mkspecs/macx-xcode/default.xcscheme | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mkspecs/macx-xcode/default.xcscheme b/mkspecs/macx-xcode/default.xcscheme index 4a16fefca0..ab2f6a8ab7 100644 --- a/mkspecs/macx-xcode/default.xcscheme +++ b/mkspecs/macx-xcode/default.xcscheme @@ -73,6 +73,13 @@ ReferencedContainer = "container:@QMAKE_ORIG_TARGET@.xcodeproj"> + + + + From f191ba9d71bd910f205a2f41c5ac6c0d959439ed Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 28 Sep 2015 17:37:55 +0200 Subject: [PATCH 162/240] Revamp signal handling in eglfs/linuxfb Go back to the pipe-based signal handling. signalfd() introduces more harm than good and is a regression for applications that install their own signal handlers. Simplify the somewhat overcomplicated suspend (Ctrl+Z) logic too. There is no need for requiring a callback. Just enable/disable the keyboard and cursor on suspend and resume and emit the signals. Backends (like kms) may then perform additional steps, if they choose to do so. Task-number: QTBUG-48384 Change-Id: Ifd52de89c59915a2e0be6bf5ebc6f2ff1728eb50 Reviewed-by: Louai Al-Khanji --- .../fbconvenience/qfbvthandler.cpp | 113 +++++++++--------- .../fbconvenience/qfbvthandler_p.h | 9 +- .../eglfs_kms/qeglfskmsscreen.cpp | 6 +- 3 files changed, 60 insertions(+), 68 deletions(-) diff --git a/src/platformsupport/fbconvenience/qfbvthandler.cpp b/src/platformsupport/fbconvenience/qfbvthandler.cpp index c46e470c34..5e062b3f0a 100644 --- a/src/platformsupport/fbconvenience/qfbvthandler.cpp +++ b/src/platformsupport/fbconvenience/qfbvthandler.cpp @@ -79,87 +79,79 @@ static void setTTYCursor(bool enable) } #endif +#ifdef VTH_ENABLED +static QFbVtHandler *vth; + +void QFbVtHandler::signalHandler(int sigNo) +{ + char a = sigNo; + QT_WRITE(vth->m_sigFd[0], &a, sizeof(a)); +} +#endif + QFbVtHandler::QFbVtHandler(QObject *parent) : QObject(parent), m_tty(-1), - m_signalFd(-1), m_signalNotifier(0) { #ifdef VTH_ENABLED - setTTYCursor(false); - - if (isatty(0)) { + if (isatty(0)) m_tty = 0; - ioctl(m_tty, KDGKBMODE, &m_oldKbdMode); - if (!qEnvironmentVariableIntValue("QT_QPA_ENABLE_TERMINAL_KEYBOARD")) { - // Disable the tty keyboard. - ioctl(m_tty, KDSKBMUTE, 1); - ioctl(m_tty, KDSKBMODE, KBD_OFF_MODE); - } + if (::socketpair(AF_UNIX, SOCK_STREAM, 0, m_sigFd)) { + qErrnoWarning(errno, "QFbVtHandler: socketpair() failed"); + return; } - // SIGSEGV and such cannot safely be blocked. We cannot handle them in an - // async-safe manner either. Restoring the keyboard, video mode, etc. may - // all contain calls that cannot safely be made from a signal handler. + vth = this; + setTTYCursor(false); + setKeyboardEnabled(false); - // Other signals: block them and use signalfd. - sigset_t mask; - sigemptyset(&mask); + m_signalNotifier = new QSocketNotifier(m_sigFd[1], QSocketNotifier::Read, this); + connect(m_signalNotifier, &QSocketNotifier::activated, this, &QFbVtHandler::handleSignal); - // Catch Ctrl+C. - sigaddset(&mask, SIGINT); - - // Ctrl+Z. Up to the platform plugins to handle it in a meaningful way. - sigaddset(&mask, SIGTSTP); - sigaddset(&mask, SIGCONT); - - // Default signal used by kill. To overcome the common issue of no cleaning - // up when killing a locally started app via a remote session. - sigaddset(&mask, SIGTERM); - - m_signalFd = signalfd(-1, &mask, SFD_CLOEXEC); - if (m_signalFd < 0) { - qErrnoWarning(errno, "signalfd() failed"); - } else { - m_signalNotifier = new QSocketNotifier(m_signalFd, QSocketNotifier::Read, this); - connect(m_signalNotifier, &QSocketNotifier::activated, this, &QFbVtHandler::handleSignal); - - // Block the signals that are handled via signalfd. Applies only to the current - // thread, but new threads will inherit the creator's signal mask. - pthread_sigmask(SIG_BLOCK, &mask, 0); - } + struct sigaction sa; + sa.sa_flags = 0; + sa.sa_handler = signalHandler; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, 0); // Ctrl+C + sigaction(SIGTSTP, &sa, 0); // Ctrl+Z + sigaction(SIGCONT, &sa, 0); + sigaction(SIGTERM, &sa, 0); // default signal used by kill #endif } QFbVtHandler::~QFbVtHandler() { #ifdef VTH_ENABLED - restoreKeyboard(); + setKeyboardEnabled(true); setTTYCursor(true); - if (m_signalFd != -1) - close(m_signalFd); + if (m_signalNotifier) { + close(m_sigFd[0]); + close(m_sigFd[1]); + } #endif } -void QFbVtHandler::restoreKeyboard() +void QFbVtHandler::setKeyboardEnabled(bool enable) { #ifdef VTH_ENABLED if (m_tty == -1) return; - ioctl(m_tty, KDSKBMUTE, 0); - ioctl(m_tty, KDSKBMODE, m_oldKbdMode); -#endif -} - -// To be called from the slot connected to suspendRequested() in case the -// platform plugin does in fact allow suspending on Ctrl+Z. -void QFbVtHandler::suspend() -{ -#ifdef VTH_ENABLED - kill(getpid(), SIGSTOP); + if (enable) { + ::ioctl(m_tty, KDSKBMUTE, 0); + ::ioctl(m_tty, KDSKBMODE, m_oldKbdMode); + } else { + ::ioctl(m_tty, KDGKBMODE, &m_oldKbdMode); + if (!qEnvironmentVariableIntValue("QT_QPA_ENABLE_TERMINAL_KEYBOARD")) { + ::ioctl(m_tty, KDSKBMUTE, 1); + ::ioctl(m_tty, KDSKBMODE, KBD_OFF_MODE); + } + } +#else + Q_UNUSED(enable); #endif } @@ -168,17 +160,22 @@ void QFbVtHandler::handleSignal() #ifdef VTH_ENABLED m_signalNotifier->setEnabled(false); - signalfd_siginfo sig; - if (read(m_signalFd, &sig, sizeof(sig)) == sizeof(sig)) { - switch (sig.ssi_signo) { + char sigNo; + if (QT_READ(m_sigFd[1], &sigNo, sizeof(sigNo)) == sizeof(sigNo)) { + switch (sigNo) { case SIGINT: // fallthrough case SIGTERM: handleInt(); break; case SIGTSTP: - emit suspendRequested(); + emit aboutToSuspend(); + setKeyboardEnabled(true); + setTTYCursor(true); + ::kill(getpid(), SIGSTOP); break; case SIGCONT: + setTTYCursor(false); + setKeyboardEnabled(false); emit resumed(); break; default: @@ -194,7 +191,7 @@ void QFbVtHandler::handleInt() { #ifdef VTH_ENABLED emit interrupted(); - restoreKeyboard(); + setKeyboardEnabled(true); setTTYCursor(true); _exit(1); #endif diff --git a/src/platformsupport/fbconvenience/qfbvthandler_p.h b/src/platformsupport/fbconvenience/qfbvthandler_p.h index 3681def9f0..91eba248fe 100644 --- a/src/platformsupport/fbconvenience/qfbvthandler_p.h +++ b/src/platformsupport/fbconvenience/qfbvthandler_p.h @@ -59,23 +59,22 @@ public: QFbVtHandler(QObject *parent = 0); ~QFbVtHandler(); - void suspend(); - signals: void interrupted(); - void suspendRequested(); + void aboutToSuspend(); void resumed(); private slots: void handleSignal(); private: - void restoreKeyboard(); + void setKeyboardEnabled(bool enable); void handleInt(); + static void signalHandler(int sigNo); int m_tty; int m_oldKbdMode; - int m_signalFd; + int m_sigFd[2]; QSocketNotifier *m_signalNotifier; }; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp index d2a86c1e25..60586f98a7 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp @@ -52,15 +52,11 @@ public: QEglFSKmsInterruptHandler(QEglFSKmsScreen *screen) : m_screen(screen) { m_vtHandler = static_cast(QGuiApplicationPrivate::platformIntegration())->vtHandler(); connect(m_vtHandler, &QFbVtHandler::interrupted, this, &QEglFSKmsInterruptHandler::restoreVideoMode); - connect(m_vtHandler, &QFbVtHandler::suspendRequested, this, &QEglFSKmsInterruptHandler::handleSuspendRequest); + connect(m_vtHandler, &QFbVtHandler::aboutToSuspend, this, &QEglFSKmsInterruptHandler::restoreVideoMode); } public slots: void restoreVideoMode() { m_screen->restoreMode(); } - void handleSuspendRequest() { - m_screen->restoreMode(); - m_vtHandler->suspend(); - } private: QFbVtHandler *m_vtHandler; From 7c0b9e1e8d069afab997efd3df9632d342b23150 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 2 Oct 2015 11:00:53 +0200 Subject: [PATCH 163/240] Fix build without PCH after commit 3ae2387f375798a983b6d052723f10fc88b63da0 Include errno.h for errno and EEXIST. Change-Id: Id28d5a08097319eb84b1fe9ef20c9be6ebe575fa Reviewed-by: Frederik Gladhorn --- src/corelib/io/qtemporarydir.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/io/qtemporarydir.cpp b/src/corelib/io/qtemporarydir.cpp index c7150d7b33..71436c6497 100644 --- a/src/corelib/io/qtemporarydir.cpp +++ b/src/corelib/io/qtemporarydir.cpp @@ -49,6 +49,10 @@ #include #endif +#if !defined(Q_OS_WIN) +#include +#endif + QT_BEGIN_NAMESPACE //************* QTemporaryDirPrivate From 0addf25bd7417acca1d3d9df145ff36c5683b0a0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 2 Oct 2015 09:28:28 +0200 Subject: [PATCH 164/240] tst_QSharedPointer: Add jom.exe to the list of make tools to be searched. Task-number: QTBUG-48565 Change-Id: I9b1371fb1d3ea451c185bfe5fa3a6acabe28be15 Reviewed-by: Liang Qi Reviewed-by: Oliver Wolff --- tests/auto/corelib/tools/qsharedpointer/externaltests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp index c3a615fdff..2128eeb164 100644 --- a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp @@ -641,6 +641,7 @@ namespace QTest { make.setProcessChannelMode(channelMode); static const char makes[] = + "jom.exe\0" //preferred for visual c++ or mingw "nmake.exe\0" //for visual c++ "mingw32-make.exe\0" //for mingw "gmake\0" From bbb2c95d7ad329a05a8f74d80ac69b3ca5851db1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 2 Oct 2015 09:43:17 +0200 Subject: [PATCH 165/240] tst_qdesktopservices: Use regular expression to suppress error message. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The error return has been observed to vary. Task-number: QTBUG-48566 Change-Id: Iecfe7819898a6a8a482c1b2251543193ecfa4841 Reviewed-by: Liang Qi Reviewed-by: Jędrzej Nowacki Reviewed-by: Oliver Wolff --- .../auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp b/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp index c8964eb02c..db4b15530c 100644 --- a/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp +++ b/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp @@ -35,6 +35,7 @@ #include #include #include +#include class tst_qdesktopservices : public QObject { @@ -74,7 +75,9 @@ void tst_qdesktopservices::openUrl() QCOMPARE(QDesktopServices::openUrl(QUrl()), false); #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) // this test is only valid on windows on other systems it might mean open a new document in the application handling .file - QTest::ignoreMessage(QtWarningMsg, "ShellExecute 'file://invalid.file' failed (error 3)."); + const QRegularExpression messagePattern("ShellExecute 'file://invalid\\.file' failed \\(error \\d+\\)\\."); + QVERIFY(messagePattern.isValid()); + QTest::ignoreMessage(QtWarningMsg, messagePattern); QCOMPARE(QDesktopServices::openUrl(QUrl("file://invalid.file")), false); #endif } From 8058ab57581dcae569188c2c3dbc8667c34dd106 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 30 Sep 2015 15:40:02 +0200 Subject: [PATCH 166/240] qdoc: Resolve namespaces declared in index trees QDoc never called resolveNamespaces() unless running in single-exec mode. This commit fixes that, and causes public namespaces documented in other modules to be treated as 'seen', i.e, as if they were declared locally. Change-Id: Id1dda7aaea6c9bd38bbeb5992121575a1876cbf7 Task-number: QTBUG-48523 Reviewed-by: Martin Smith --- src/tools/qdoc/qdocdatabase.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 6312deacbf..acd11ff20b 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -1296,6 +1296,8 @@ void QDocDatabase::resolveIssues() { QDocIndexFiles::qdocIndexFiles()->resolveRelates(); QDocIndexFiles::destroyQDocIndexFiles(); } + if (Generator::generating()) + resolveNamespaces(); } void QDocDatabase::resolveStuff() @@ -1326,8 +1328,10 @@ void QDocDatabase::resolveNamespaces() int count = nmm_.remove(s); if (count > 1) { foreach (Node* n, nodes) { - if (n->isNamespace() && n->wasSeen()) { + // Treat public namespaces from index trees as 'seen' + if (n->isNamespace() && (n->wasSeen() || (n->isIndexNode() && n->access() == Node::Public))) { ns = static_cast(n); + ns->markSeen(); break; } } From 17f649ab296816965be6c38c00bcd37aa9f6d42b Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Thu, 1 Oct 2015 10:26:14 +0200 Subject: [PATCH 167/240] Doc: Fix URL in QSystemTrayIcon documentation Change-Id: Id7da32c8b48486e8bd80893e0a73297d2f325d50 Task-number: QTWEBSITE-690 Reviewed-by: Venugopal Shivashankar --- src/widgets/util/qsystemtrayicon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp index 358e4c38d6..d22791048f 100644 --- a/src/widgets/util/qsystemtrayicon.cpp +++ b/src/widgets/util/qsystemtrayicon.cpp @@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE \l{http://standards.freedesktop.org/systemtray-spec/systemtray-spec-0.2.html freedesktop.org} XEmbed system tray specification. \li All X11 desktop environments that implement the D-Bus - \l{http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/ StatusNotifierItem} + \l{http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierItem} specification, including recent versions of KDE and Unity. \li All supported versions of OS X. Note that the Growl notification system must be installed for From e03bcdea62d5e27f5b80d19bf19d170d74568b9a Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 28 Sep 2015 12:29:19 +0200 Subject: [PATCH 168/240] qdoc: Fix a regression with QML node attributes written to index files QDoc needs to write the following attributes to index files: For qmlclass: qml-module-name, qml-base-type For qmlmodule: qml-module-name, qml-module-version Because of a regression introduced in Qt 5.5, no QML module name or base type information were written for QML types, resulting in linking issues. Change-Id: I69e616dadfc9ede389bc05e16acb831f1e15bac5 Task-number: QTBUG-48479 Reviewed-by: Martin Smith --- src/tools/qdoc/qdocindexfiles.cpp | 38 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index fc262d9834..fdc42316cb 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -946,27 +946,27 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, } writer.writeAttribute("name", objName); - if (node->isQmlModule()) { - logicalModuleName = node->logicalModuleName(); - logicalModuleVersion = node->logicalModuleVersion(); - if (!logicalModuleName.isEmpty()) { - writer.writeAttribute("qml-module-name", logicalModuleName); - if (node->isQmlModule()) - writer.writeAttribute("qml-module-version", logicalModuleVersion); - if (!qmlFullBaseName.isEmpty()) - writer.writeAttribute("qml-base-type", qmlFullBaseName); + + // Write module and base type info for QML/JS types + if (node->type() == Node::QmlType || node->type() == Node::QmlModule) { + QString baseNameAttr("qml-base-type"); + QString moduleNameAttr("qml-module-name"); + QString moduleVerAttr("qml-module-version"); + if (node->isJsNode()) { + baseNameAttr = "js-base-type"; + moduleNameAttr = "js-module-name"; + moduleVerAttr = "js-module-version"; } - } - else if (node->isJsModule()) { - logicalModuleName = node->logicalModuleName(); - logicalModuleVersion = node->logicalModuleVersion(); - if (!logicalModuleName.isEmpty()) { - writer.writeAttribute("js-module-name", logicalModuleName); - if (node->isQmlModule()) - writer.writeAttribute("js-module-version", logicalModuleVersion); - if (!qmlFullBaseName.isEmpty()) - writer.writeAttribute("js-base-type", qmlFullBaseName); + if (node->type() == Node::QmlModule) { + logicalModuleName = node->logicalModuleName(); + logicalModuleVersion = node->logicalModuleVersion(); } + if (!logicalModuleName.isEmpty()) + writer.writeAttribute(moduleNameAttr, logicalModuleName); + if (!logicalModuleVersion.isEmpty()) + writer.writeAttribute(moduleVerAttr, logicalModuleVersion); + if (!qmlFullBaseName.isEmpty()) + writer.writeAttribute(baseNameAttr, qmlFullBaseName); } QString href; From 549eada0ab1b277b380251beb16379b77cd9d8a1 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 25 Sep 2015 14:26:23 +0200 Subject: [PATCH 169/240] Doc: Use correct image in Qt::BusyCursor documentation Change-Id: I54e832808a37d46f5520c57ceb2a270685ed3f94 Task-number: QTBUG-48445 Reviewed-by: Martin Smith --- src/corelib/global/qnamespace.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 7947f7d1a0..adfa28d384 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2405,7 +2405,7 @@ \value WhatsThisCursor \inlineimage cursor-whatsthis.png An arrow with a question mark, typically used to indicate the presence of What's This? help for a widget. - \value BusyCursor \inlineimage cursor-wait.png + \value BusyCursor \inlineimage cursor-busy.png An hourglass or watch cursor, usually shown during operations that allow the user to interact with the application while they are performed in the From fbf3daef384706cd5ddc15c48bcf0b3980eaf6a4 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Thu, 24 Sep 2015 10:10:19 +0200 Subject: [PATCH 170/240] Doc: Update obsolete URLs to external documentation Change-Id: I199de83971701c14e903e712fcdcd29aaff95c6d Task-number: QTBUG-48420 Reviewed-by: Venugopal Shivashankar Reviewed-by: Liang Qi --- doc/global/externalsites/qt-webpages.qdoc | 8 ++++---- examples/widgets/doc/src/codeeditor.qdoc | 2 +- examples/widgets/doc/src/syntaxhighlighter.qdoc | 2 +- examples/widgets/widgets/stylesheet/mainwindow.cpp | 2 +- src/corelib/doc/src/eventsandfilters.qdoc | 2 +- src/corelib/global/qnamespace.qdoc | 2 +- src/gui/image/qpixmapcache.cpp | 2 +- src/tools/qdoc/doc/qdoc-manual-contextcmds.qdoc | 2 +- src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc | 6 +++--- src/tools/qdoc/doc/qdoc-manual-topiccmds.qdoc | 6 +++--- src/widgets/dialogs/qwizard.cpp | 2 +- src/widgets/doc/src/widgets-and-layouts/layout.qdoc | 2 +- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/doc/global/externalsites/qt-webpages.qdoc b/doc/global/externalsites/qt-webpages.qdoc index 386573e526..e70a441495 100644 --- a/doc/global/externalsites/qt-webpages.qdoc +++ b/doc/global/externalsites/qt-webpages.qdoc @@ -41,11 +41,11 @@ \title Qt Licensing Overview */ /*! - \externalpage http://doc.qt.digia.com/qq/ + \externalpage http://doc.qt.io/archives/qq/ \title Qt Quarterly */ /*! - \externalpage http://doc.qt.digia.com/qq/qq19-plurals.html + \externalpage http://doc.qt.io/archives/qq/qq19-plurals.html \title Qt Quarterly: Plural Form in Translation */ /*! @@ -62,11 +62,11 @@ \title Qt Coding Style */ /*! - \externalpage http://doc.qt.digia.com/qt-eclipse-1.6/index.html + \externalpage http://doc.qt.io/archives/qt-eclipse-1.6/index.html \title Eclipse Plugin */ /*! - \externalpage http://doc.qt.digia.com/qq/qq11-events.html + \externalpage http://doc.qt.io/archives/qq/qq11-events.html \title Qt Quarterly: Another Look at Events */ /*! diff --git a/examples/widgets/doc/src/codeeditor.qdoc b/examples/widgets/doc/src/codeeditor.qdoc index 645854a58c..6c9e5921b8 100644 --- a/examples/widgets/doc/src/codeeditor.qdoc +++ b/examples/widgets/doc/src/codeeditor.qdoc @@ -192,6 +192,6 @@ fetched with QTextBlock::userData(). Matching parentheses can be highlighted with an extra selection. The "Matching Parentheses with QSyntaxHighlighter" article in Qt Quarterly 31 implements - this. You find it here: \l{http://doc.qt.digia.com/qq/}. + this. You find it here: \l{http://doc.qt.io/archives/qq/}. */ diff --git a/examples/widgets/doc/src/syntaxhighlighter.qdoc b/examples/widgets/doc/src/syntaxhighlighter.qdoc index 2b283afe5e..7d33299c81 100644 --- a/examples/widgets/doc/src/syntaxhighlighter.qdoc +++ b/examples/widgets/doc/src/syntaxhighlighter.qdoc @@ -248,7 +248,7 @@ It is possible to implement parenthesis matching with QSyntaxHighlighter. The "Matching Parentheses with QSyntaxHighlighter" article in Qt Quarterly 31 - (\l{http://doc.qt.digia.com/qq/}) implements this. We also have + (\l{http://doc.qt.io/archives/qq/}) implements this. We also have the \l{Code Editor Example}, which shows how to implement line numbers and how to highlight the current line. diff --git a/examples/widgets/widgets/stylesheet/mainwindow.cpp b/examples/widgets/widgets/stylesheet/mainwindow.cpp index a49c06dfd2..6d84897c77 100644 --- a/examples/widgets/widgets/stylesheet/mainwindow.cpp +++ b/examples/widgets/widgets/stylesheet/mainwindow.cpp @@ -67,7 +67,7 @@ void MainWindow::on_aboutAction_triggered() { QMessageBox::about(this, tr("About Style sheet"), tr("The Style Sheet example shows how widgets can be styled " - "using Qt " + "using Qt " "Style Sheets. Click File|Edit Style Sheet to pop up the " "style editor, and either choose an existing style sheet or design " "your own.")); diff --git a/src/corelib/doc/src/eventsandfilters.qdoc b/src/corelib/doc/src/eventsandfilters.qdoc index a4710eb288..99a40bb1b8 100644 --- a/src/corelib/doc/src/eventsandfilters.qdoc +++ b/src/corelib/doc/src/eventsandfilters.qdoc @@ -100,7 +100,7 @@ event delivery mechanisms are flexible. The documentation for QCoreApplication::notify() concisely tells the whole story; the \e{Qt Quarterly} article - \l{http://doc.qt.digia.com/qq/qq11-events.html}{Another Look at Events} + \l{http://doc.qt.io/archives/qq/qq11-events.html}{Another Look at Events} rehashes it less concisely. Here we will explain enough for 95% of applications. diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index adfa28d384..b8ce8792cb 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2715,7 +2715,7 @@ "\l{http://bugreports.qt.io/browse/QTWEBSITE-13}{http://bugreports.qt.../QTWEBSITE-13/}"), whereas Qt::ElideRight is appropriate for other strings (e.g., - "\l{http://doc.qt.digia.com/qq/qq09-mac-deployment.html}{Deploying Applications on Ma...}"). + "\l{http://doc.qt.io/archives/qq/qq09-mac-deployment.html}{Deploying Applications on Ma...}"). \sa QAbstractItemView::textElideMode, QFontMetrics::elidedText(), AlignmentFlag, QTabBar::elideMode */ diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index 71a79745e8..de37e0ab44 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE memory. The \e{Qt Quarterly} article - \l{http://doc.qt.digia.com/qq/qq12-qpixmapcache.html}{Optimizing + \l{http://doc.qt.io/archives/qq/qq12-qpixmapcache.html}{Optimizing with QPixmapCache} explains how to use QPixmapCache to speed up applications by caching the results of painting. diff --git a/src/tools/qdoc/doc/qdoc-manual-contextcmds.qdoc b/src/tools/qdoc/doc/qdoc-manual-contextcmds.qdoc index a2e851293c..d707c77cfb 100644 --- a/src/tools/qdoc/doc/qdoc-manual-contextcmds.qdoc +++ b/src/tools/qdoc/doc/qdoc-manual-contextcmds.qdoc @@ -269,7 +269,7 @@ library.} It is provided to keep old source code working. We strongly advise against using it in new code. See the \l - {http://doc.qt.digia.com/4.0/porting4.html} {Porting + {http://doc.qt.io/qt-4.8/porting4.html} {Porting Guide} for more information. \endquotation diff --git a/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc b/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc index d490f8549a..69980c1e18 100644 --- a/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc +++ b/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc @@ -1392,8 +1392,8 @@ \endcode The complete variable entry in \l qtgui.qdocconf provides the - standard header of the \l {http://doc.qt.digia.com/} - {Qt Reference Documentation}. + standard header of the \l {http://doc.qt.io/qt-5/qtgui-index.html} + {Qt GUI Documentation}. \target HTML.style-variable \section1 HTML.style @@ -1521,7 +1521,7 @@ This makes sure that whenever \c qt.index is used to generate references to for example Qt classes, the base URL is \c - http://doc.qt.digia.com/4.7. + http://doc.qt.io/qt-4.8/. See also \l indexes. diff --git a/src/tools/qdoc/doc/qdoc-manual-topiccmds.qdoc b/src/tools/qdoc/doc/qdoc-manual-topiccmds.qdoc index 306fc40cb8..1dfd031633 100644 --- a/src/tools/qdoc/doc/qdoc-manual-topiccmds.qdoc +++ b/src/tools/qdoc/doc/qdoc-manual-topiccmds.qdoc @@ -812,7 +812,7 @@ - QFtp + QFtp Implementation of the FTP protocol @@ -885,7 +885,7 @@

#include <Qt>
@@ -893,7 +893,7 @@

Types


\endraw diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index 8b9ea95cf3..b9906f13da 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -3662,7 +3662,7 @@ bool QWizardPage::validatePage() from the rest of your implementation, whenever the value of isComplete() changes. This ensures that QWizard updates the enabled or disabled state of its buttons. An example of the reimplementation is - available \l{http://doc.qt.digia.com/qq/qq22-qwizard.html#validatebeforeitstoolate} + available \l{http://doc.qt.io/archives/qq/qq22-qwizard.html#validatebeforeitstoolate} {here}. \sa completeChanged(), isFinalPage() diff --git a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc index 60281ce109..47c2a17e7e 100644 --- a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc +++ b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc @@ -249,7 +249,7 @@ For further guidance when implementing these functions, see the \e{Qt Quarterly} article - \l{http://doc.qt.digia.com/qq/qq04-height-for-width.html} + \l{http://doc.qt.io/archives/qq/qq04-height-for-width.html} {Trading Height for Width}. From d49169ae890bcf4f341b7c2f36b875668f063de6 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Tue, 29 Sep 2015 13:36:16 +0200 Subject: [PATCH 171/240] Doc: replace \target with \keyword if at start of page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A \target whose purpose is to link to the top of a page (and not to a section within a page) works better as a \keyword, because \target generates a new html anchor which, in this case, is not tied to any title element on the page. A \keyword links to the page itself, as expected. Task-number: QTBUG-48482 Change-Id: I957551edd0eb7e665358d04b37dab41e2686b851 Reviewed-by: Topi Reiniö --- qmake/doc/src/qmake-manual.qdoc | 2 +- src/corelib/doc/src/objectmodel/metaobjects.qdoc | 2 +- src/corelib/doc/src/objectmodel/properties.qdoc | 2 +- src/corelib/global/qnamespace.qdoc | 2 +- src/corelib/plugin/qplugin.qdoc | 2 +- src/dbus/doc/src/qtdbus-module.qdoc | 2 +- src/tools/qdoc/doc/qdoc-minimum-qdocconf.qdoc | 2 +- src/widgets/doc/src/qtwidgets-examples.qdoc | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index da6ce337d2..cfa288da82 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -4466,7 +4466,7 @@ */ /*! - \target qmake-getting-started + \keyword qmake-getting-started \page qmake-tutorial.html \title Getting Started \contentspage {qmake Manual}{Contents} diff --git a/src/corelib/doc/src/objectmodel/metaobjects.qdoc b/src/corelib/doc/src/objectmodel/metaobjects.qdoc index a482c5cc8b..52c134c517 100644 --- a/src/corelib/doc/src/objectmodel/metaobjects.qdoc +++ b/src/corelib/doc/src/objectmodel/metaobjects.qdoc @@ -32,7 +32,7 @@ \ingroup qt-basic-concepts \keyword meta-object - \target Meta-Object System + \keyword Meta-Object System Qt's meta-object system provides the signals and slots mechanism for inter-object communication, run-time type information, and the dynamic diff --git a/src/corelib/doc/src/objectmodel/properties.qdoc b/src/corelib/doc/src/objectmodel/properties.qdoc index 55622dd56b..28be328e3a 100644 --- a/src/corelib/doc/src/objectmodel/properties.qdoc +++ b/src/corelib/doc/src/objectmodel/properties.qdoc @@ -31,7 +31,7 @@ \brief An overview of Qt's property system. \ingroup qt-basic-concepts - \target Qt's Property System + \keyword Qt's Property System Qt provides a sophisticated property system similar to the ones supplied by some compiler vendors. However, as a compiler- and diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index b8ce8792cb..3dc791397c 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -28,7 +28,7 @@ /*! \namespace Qt \inmodule QtCore - \target Qt Namespace + \keyword Qt Namespace \brief The Qt namespace contains miscellaneous identifiers used throughout the Qt library. diff --git a/src/corelib/plugin/qplugin.qdoc b/src/corelib/plugin/qplugin.qdoc index 94f5bc8a30..00ecb30430 100644 --- a/src/corelib/plugin/qplugin.qdoc +++ b/src/corelib/plugin/qplugin.qdoc @@ -28,7 +28,7 @@ /*! \headerfile \title Defining Plugins - \target qtplugin-defining-plugins + \keyword qtplugin-defining-plugins \ingroup plugins \brief The header file defines macros for defining plugins. diff --git a/src/dbus/doc/src/qtdbus-module.qdoc b/src/dbus/doc/src/qtdbus-module.qdoc index 498da43d7a..87d35386c8 100644 --- a/src/dbus/doc/src/qtdbus-module.qdoc +++ b/src/dbus/doc/src/qtdbus-module.qdoc @@ -34,7 +34,7 @@ \ingroup modules \qtvariable dbus - \target The QDBus compiler + \keyword The QDBus compiler Applications using the Qt D-Bus module can provide services to diff --git a/src/tools/qdoc/doc/qdoc-minimum-qdocconf.qdoc b/src/tools/qdoc/doc/qdoc-minimum-qdocconf.qdoc index 66ceed4a3d..1fcd23a0f8 100644 --- a/src/tools/qdoc/doc/qdoc-minimum-qdocconf.qdoc +++ b/src/tools/qdoc/doc/qdoc-minimum-qdocconf.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! \page qdoc-minimum-qdocconf.html -\target minimal-qdocconf +\keyword minimal-qdocconf \title A Minimal qdocconf File \brief Describes a minimal .qdocconf file diff --git a/src/widgets/doc/src/qtwidgets-examples.qdoc b/src/widgets/doc/src/qtwidgets-examples.qdoc index 7b727183b8..9c0b29d687 100644 --- a/src/widgets/doc/src/qtwidgets-examples.qdoc +++ b/src/widgets/doc/src/qtwidgets-examples.qdoc @@ -127,7 +127,7 @@ /*! \ingroup all-examples - \target Graphicsview Examples + \keyword Graphicsview Examples \title Graphics View Examples \brief Using the Graphics View framework. \page examples-graphicsview.html From b8e0f7cfc638a71770f44ada828ff2cf6d2ee201 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Thu, 1 Oct 2015 17:41:07 +0300 Subject: [PATCH 172/240] Fix the spurious socket notifications on OS X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Core Foundation Framework forwards notifications about socket activity through a callback function which called from the run loop. Previous implementation sets kCFSocketReadCallBack, kCFSocketWriteCallBack to be automatically re-enabled after they are triggered. With these semantics, an application need not read all available data in response to a read notification: a single recv in response to each read notification is appropriate. If an application issues multiple recv calls in response to a single notification, it can receive spurious notifications. To solve this issue, this patch disables automatically reenabling callback feature. Now, callback gets called exactly once, and is not called again until manually re-enabled by calling CFSocketEnableCallBacks() just before entering to wait for the new events. Task-number: QTBUG-48556 Change-Id: Ia3393c2026230c7b3397cc614758dec1d432535f Reviewed-by: Morten Johan Sørvig --- .../cfsocketnotifier/qcfsocketnotifier.cpp | 37 +++++++++++++++---- .../cfsocketnotifier/qcfsocketnotifier_p.h | 6 ++- .../platforms/cocoa/qcocoaeventdispatcher.mm | 11 ++++-- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp index 2b5723d827..91f7aeb7d0 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp @@ -55,11 +55,15 @@ void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CF // notifier is now gone. The upshot is we have to check the notifier // every time. if (callbackType == kCFSocketReadCallBack) { - if (socketInfo->readNotifier) + if (socketInfo->readNotifier && socketInfo->readEnabled) { + socketInfo->readEnabled = false; QGuiApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent); + } } else if (callbackType == kCFSocketWriteCallBack) { - if (socketInfo->writeNotifier) + if (socketInfo->writeNotifier && socketInfo->writeEnabled) { + socketInfo->writeEnabled = false; QGuiApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent); + } } if (cfSocketNotifier->maybeCancelWaitForMoreEvents) @@ -150,8 +154,8 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) } CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket); - flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write - flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation + // QSocketNotifier doesn't close the socket upon destruction/invalidation + flags &= ~(kCFSocketCloseOnInvalidate | kCFSocketAutomaticallyReenableReadCallBack); CFSocketSetSocketFlags(socketInfo->socket, flags); // Add CFSocket to runloop. @@ -171,15 +175,14 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) macSockets.insert(nativeSocket, socketInfo); } - // Increment read/write counters and select enable callbacks if necessary. if (type == QSocketNotifier::Read) { Q_ASSERT(socketInfo->readNotifier == 0); socketInfo->readNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + socketInfo->readEnabled = false; } else if (type == QSocketNotifier::Write) { Q_ASSERT(socketInfo->writeNotifier == 0); socketInfo->writeNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + socketInfo->writeEnabled = false; } } @@ -212,10 +215,12 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) if (type == QSocketNotifier::Read) { Q_ASSERT(notifier == socketInfo->readNotifier); socketInfo->readNotifier = 0; + socketInfo->readEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); } else if (type == QSocketNotifier::Write) { Q_ASSERT(notifier == socketInfo->writeNotifier); socketInfo->writeNotifier = 0; + socketInfo->writeEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); } @@ -232,6 +237,24 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) } } +void QCFSocketNotifier::enableSocketNotifiers() +{ + // Enable CFSockets in runloop. + for (MacSocketHash::ConstIterator it = macSockets.constBegin(); it != macSockets.constEnd(); ++it) { + MacSocketInfo *socketInfo = (*it); + if (CFSocketIsValid(socketInfo->socket)) { + if (socketInfo->readNotifier && !socketInfo->readEnabled) { + socketInfo->readEnabled = true; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + } + if (socketInfo->writeNotifier && !socketInfo->writeEnabled) { + socketInfo->writeEnabled = true; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + } + } + } +} + void QCFSocketNotifier::removeSocketNotifiers() { // Remove CFSockets from the runloop. diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h index af8122f753..1d6dcf2885 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h @@ -53,11 +53,14 @@ QT_BEGIN_NAMESPACE struct MacSocketInfo { - MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {} + MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0), + readEnabled(false), writeEnabled(false) {} CFSocketRef socket; CFRunLoopSourceRef runloop; QObject *readNotifier; QObject *writeNotifier; + bool readEnabled; + bool writeEnabled; }; typedef QHash MacSocketHash; @@ -81,6 +84,7 @@ public: void setMaybeCancelWaitForMoreEventsCallback(MaybeCancelWaitForMoreEventsFn callBack); void registerSocketNotifier(QSocketNotifier *notifier); void unregisterSocketNotifier(QSocketNotifier *notifier); + void enableSocketNotifiers(); void removeSocketNotifiers(); MacSocketHash macSockets; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 52b2e23345..b443233d15 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -845,10 +845,13 @@ QCocoaEventDispatcher::QCocoaEventDispatcher(QObject *parent) void QCocoaEventDispatcherPrivate::waitingObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity activity, void *info) { - if (activity == kCFRunLoopBeforeWaiting) - emit static_cast(info)->aboutToBlock(); - else - emit static_cast(info)->awake(); + QCocoaEventDispatcher *dispatcher = static_cast(info); + if (activity == kCFRunLoopBeforeWaiting) { + dispatcher->d_func()->cfSocketNotifier.enableSocketNotifiers(); + emit dispatcher->aboutToBlock(); + } else { + emit dispatcher->awake(); + } } void QCocoaEventDispatcherPrivate::processPostedEvents() From 44f323e5007a389c4103bfc6ca577d26078ce92b Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Sat, 3 Oct 2015 02:46:15 +0300 Subject: [PATCH 173/240] ANGLE: Fix D3D feature level detection. Commit 7943d4f tried to fix this with a switch/case, but the feature levels need to be in descending order so this failed. So, follow the same style used for feature levels 10/11. Change-Id: Ia1c22981bf8b99eb53df13833aba452482398295 Task-number: QTBUG-38481 Task-number: QTBUG-48571 Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- .../renderer/d3d/d3d11/Renderer11.cpp | 28 +++++------ ...s-Store-D3D-Trim-and-Level-9-require.patch | 50 ++++++++----------- 2 files changed, 35 insertions(+), 43 deletions(-) diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index ea5953fee8..223e2b019b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -293,25 +293,23 @@ Renderer11::Renderer11(egl::Display *display) #if defined(ANGLE_ENABLE_WINDOWS_STORE) if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) #else - if (requestedMajorVersion == 9) + if (requestedMajorVersion == 9 && requestedMinorVersion == 3) #endif { - switch (requestedMinorVersion) { -#if defined(ANGLE_ENABLE_WINDOWS_STORE) - case EGL_DONT_CARE: - case 1: - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); - // fall through - case 2: - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); - // fall through -#endif - case 3: + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) + { mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); - break; - default: - break; } +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); + } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); + } +#endif } EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, diff --git a/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch b/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch index e9677fab68..705219ed24 100644 --- a/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch +++ b/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch @@ -1,6 +1,6 @@ -From f6d73de2a8a36becb8a2e0cce84475e91f1f63b4 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Mon, 28 Sep 2015 22:43:13 +0300 +From 3d696560f987a08d608b29bf3e0f557e96bebc56 Mon Sep 17 00:00:00 2001 +From: Samuel Nevala +Date: Sat, 3 Oct 2015 02:30:26 +0300 Subject: [PATCH] ANGLE: Fix Windows Store D3D Trim and Level 9 requirements Due to additional validation not covered in previous patches, the Windows @@ -9,39 +9,33 @@ the required D3D behaviors are met. Change-Id: I0a74f0d2fecaa87d4a9409da3a7a194254609759 --- - .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 19 +++++++++++++++++-- - .../angle/src/libGLESv2/entry_points_egl_ext.cpp | 2 ++ - 2 files changed, 19 insertions(+), 2 deletions(-) + .../angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 16 +++++++++++++++- + .../angle/src/libGLESv2/entry_points_egl_ext.cpp | 2 ++ + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp -index 5291a3a..ea5953f 100644 +index 5291a3a..61d9212 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp -@@ -293,10 +293,25 @@ Renderer11::Renderer11(egl::Display *display) - #if defined(ANGLE_ENABLE_WINDOWS_STORE) - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) - #else -- if (requestedMajorVersion == 9 && requestedMinorVersion == 3) -+ if (requestedMajorVersion == 9) +@@ -296,7 +296,21 @@ Renderer11::Renderer11(egl::Display *display) + if (requestedMajorVersion == 9 && requestedMinorVersion == 3) #endif { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); -+ switch (requestedMinorVersion) { -+#if defined(ANGLE_ENABLE_WINDOWS_STORE) -+ case EGL_DONT_CARE: -+ case 1: -+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); -+ // fall through -+ case 2: -+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); -+ // fall through -+#endif -+ case 3: ++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) ++ { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); -+ break; -+ default: -+ break; + } ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) ++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) ++ { ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); ++ } ++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) ++ { ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); ++ } ++#endif } EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, @@ -59,5 +53,5 @@ index 62f3ca1..02b6631 100644 if (!display->getExtensions().surfaceD3DTexture2DShareHandle) { -- -2.5.1.windows.1 +1.9.5.msysgit.1 From 2677cc47fc9e5bfa1d3daf69e464521041a8144c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 17 Aug 2015 19:33:52 +0200 Subject: [PATCH 174/240] merge processPrlFiles() into findLibraries() seems pointless to tear apart the functions, on the way duplicating some boilerplate. Change-Id: Ide3697ca1c931e8de607ac48c21cecce4781fe13 Reviewed-by: Joerg Bornemann --- qmake/generators/makefile.cpp | 16 ++- qmake/generators/makefile.h | 5 +- qmake/generators/unix/unixmake.cpp | 132 +++++++++---------------- qmake/generators/unix/unixmake.h | 3 +- qmake/generators/win32/mingw_make.cpp | 40 ++++++-- qmake/generators/win32/mingw_make.h | 2 +- qmake/generators/win32/winmakefile.cpp | 87 ++++++---------- qmake/generators/win32/winmakefile.h | 3 +- 8 files changed, 124 insertions(+), 164 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 4a03fafd77..0d7571341a 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -252,10 +252,12 @@ MakefileGenerator::setProjectFile(QMakeProject *p) else target_mode = TARG_UNIX_MODE; init(); - findLibraries(); - if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE && - project->isActiveConfig("link_prl")) //load up prl's' - processPrlFiles(); + bool linkPrl = (Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE) + && project->isActiveConfig("link_prl"); + bool mergeLflags = linkPrl + && !project->isActiveConfig("no_smart_library_merge") + && !project->isActiveConfig("no_lflags_merge"); + findLibraries(linkPrl, mergeLflags); } ProStringList @@ -944,12 +946,6 @@ MakefileGenerator::filterIncludedFiles(const char *var) } } -void -MakefileGenerator::processPrlFiles() -{ - qFatal("MakefileGenerator::processPrlFiles() called!"); -} - static QString qv(const ProString &val) { diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index 07483dbcb0..8aec360147 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -197,11 +197,10 @@ protected: QString prlFileName(bool fixify=true); void writePrlFile(); bool processPrlFile(QString &); - virtual void processPrlFiles(); virtual void writePrlFile(QTextStream &); //make sure libraries are found - virtual bool findLibraries(); + virtual bool findLibraries(bool linkPrl, bool mergeLflags); //for retrieving values and lists of values virtual QString var(const ProKey &var) const; @@ -276,7 +275,7 @@ inline bool MakefileGenerator::noIO() const inline QString MakefileGenerator::defaultInstall(const QString &) { return QString(""); } -inline bool MakefileGenerator::findLibraries() +inline bool MakefileGenerator::findLibraries(bool, bool) { return true; } inline MakefileGenerator::~MakefileGenerator() diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 25f686646b..288bd6e498 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -375,12 +375,14 @@ UnixMakefileGenerator::fixLibFlag(const ProString &lib) } bool -UnixMakefileGenerator::findLibraries() +UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) { - QList libdirs; - int libidx = 0; + QList libdirs, frameworkdirs; + int libidx = 0, fwidx = 0; foreach (const ProString &dlib, project->values("QMAKE_DEFAULT_LIBDIRS")) libdirs.append(QMakeLocalFileName(dlib.toQString())); + frameworkdirs.append(QMakeLocalFileName("/System/Library/Frameworks")); + frameworkdirs.append(QMakeLocalFileName("/Library/Frameworks")); static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 }; for (int i = 0; lflags[i]; i++) { ProStringList &l = project->values(lflags[i]); @@ -398,94 +400,58 @@ UnixMakefileGenerator::findLibraries() libdirs.insert(libidx++, f); } else if(opt.startsWith("-l")) { QString lib = opt.mid(2); - bool found = false; ProStringList extens; extens << project->first("QMAKE_EXTENSION_SHLIB") << "a"; - for (ProStringList::Iterator extit = extens.begin(); extit != extens.end(); ++extit) { - for (QList::Iterator dep_it = libdirs.begin(); - dep_it != libdirs.end(); ++dep_it) { - QString pathToLib = ((*dep_it).local() + '/' - + project->first("QMAKE_PREFIX_SHLIB") - + lib + '.' + (*extit)); - if (exists(pathToLib)) { - found = true; - break; - } + for (QList::Iterator dep_it = libdirs.begin(); + dep_it != libdirs.end(); ++dep_it) { + QString libBase = (*dep_it).local() + '/' + + project->first("QMAKE_PREFIX_SHLIB") + lib; + if (linkPrl && processPrlFile(libBase)) + goto found; + for (ProStringList::Iterator extit = extens.begin(); extit != extens.end(); ++extit) { + if (exists(libBase + '.' + (*extit))) + goto found; } } - } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-framework")) { - if (opt.length() == 10) - ++it; - // Skip - } - } - ++it; - } - } - return false; -} - -void -UnixMakefileGenerator::processPrlFiles() -{ - QList libdirs, frameworkdirs; - int libidx = 0, fwidx = 0; - foreach (const ProString &dlib, project->values("QMAKE_DEFAULT_LIBDIRS")) - libdirs.append(QMakeLocalFileName(dlib.toQString())); - frameworkdirs.append(QMakeLocalFileName("/System/Library/Frameworks")); - frameworkdirs.append(QMakeLocalFileName("/Library/Frameworks")); - static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 }; - for (int i = 0; lflags[i]; i++) { - ProStringList &l = project->values(lflags[i]); - for(int lit = 0; lit < l.size(); ++lit) { - QString opt = l.at(lit).toQString(); - if(opt.startsWith("-")) { - if (opt.startsWith("-L")) { - QMakeLocalFileName l(opt.mid(2)); - if(!libdirs.contains(l)) - libdirs.insert(libidx++, l); - } else if(opt.startsWith("-l")) { - QString lib = opt.right(opt.length() - 2); - for(int dep_i = 0; dep_i < libdirs.size(); ++dep_i) { - QString prl = libdirs[dep_i].local() + '/' - + project->first("QMAKE_PREFIX_SHLIB") + lib; - if (processPrlFile(prl)) - break; - } + found: ; } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-F")) { - QMakeLocalFileName f(opt.right(opt.length()-2)); - if(!frameworkdirs.contains(f)) + QMakeLocalFileName f(opt.mid(2)); + if (!frameworkdirs.contains(f)) frameworkdirs.insert(fwidx++, f); } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-framework")) { - if(opt.length() > 11) - opt = opt.mid(11).trimmed(); - else - opt = l.at(++lit).toQString(); - foreach (const QMakeLocalFileName &dir, frameworkdirs) { - QString prl = dir.local() + "/" + opt + ".framework/" + opt + Option::prl_ext; - if(processPrlFile(prl)) - break; + if (linkPrl) { + if (opt.length() == 10) + opt = (*++it).toQString(); + else + opt = opt.mid(10).trimmed(); + foreach (const QMakeLocalFileName &dir, frameworkdirs) { + QString prl = dir.local() + "/" + opt + ".framework/" + opt + Option::prl_ext; + if (processPrlFile(prl)) + break; + } + } else { + if (opt.length() == 10) + ++it; + // Skip } } - } else if(!opt.isNull()) { + } else if (linkPrl) { processPrlFile(opt); } ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS"); - if(!prl_libs.isEmpty()) { - for(int prl = 0; prl < prl_libs.size(); ++prl) - l.insert(++lit, prl_libs.at(prl)); - prl_libs.clear(); - } + for (int prl = 0; prl < prl_libs.size(); ++prl) + it = l.insert(++it, prl_libs.at(prl)); + prl_libs.clear(); + ++it; } - //merge them into a logical order - if(!project->isActiveConfig("no_smart_library_merge") && !project->isActiveConfig("no_lflags_merge")) { + if (mergeLflags) { QHash lflags; for(int lit = 0; lit < l.size(); ++lit) { ProKey arch("default"); ProString opt = l.at(lit); - if(opt.startsWith("-")) { + if (opt.startsWith('-')) { if (target_mode == TARG_MAC_MODE && opt.startsWith("-Xarch")) { if (opt.length() > 7) { arch = opt.mid(7).toKey(); @@ -493,21 +459,20 @@ UnixMakefileGenerator::processPrlFiles() } } - if (opt.startsWith("-L") || - (target_mode == TARG_MAC_MODE && opt.startsWith("-F"))) { - if(!lflags[arch].contains(opt)) + if (opt.startsWith("-L") + || (target_mode == TARG_MAC_MODE && opt.startsWith("-F"))) { + if (!lflags[arch].contains(opt)) lflags[arch].append(opt); - } else if(opt.startsWith("-l") || opt == "-pthread") { - // Make sure we keep the dependency-order of libraries - if (lflags[arch].contains(opt)) - lflags[arch].removeAll(opt); + } else if (opt.startsWith("-l") || opt == "-pthread") { + // Make sure we keep the dependency order of libraries + lflags[arch].removeAll(opt); lflags[arch].append(opt); } else if (target_mode == TARG_MAC_MODE && opt.startsWith("-framework")) { - if(opt.length() > 11) - opt = opt.mid(11); - else { + if (opt.length() > 10) { + opt = opt.mid(10).trimmed(); + } else { opt = l.at(++lit); - if (target_mode == TARG_MAC_MODE && opt.startsWith("-Xarch")) + if (opt.startsWith("-Xarch")) opt = l.at(++lit); // The user has done the right thing and prefixed each part } bool found = false; @@ -544,6 +509,7 @@ UnixMakefileGenerator::processPrlFiles() } } } + return false; } QString diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h index b136ea04d0..db3f59f517 100644 --- a/qmake/generators/unix/unixmake.h +++ b/qmake/generators/unix/unixmake.h @@ -54,9 +54,8 @@ protected: virtual bool doDepends() const { return !Option::mkfile::do_stub_makefile && MakefileGenerator::doDepends(); } virtual QString defaultInstall(const QString &); virtual ProString fixLibFlag(const ProString &lib); - virtual void processPrlFiles(); - virtual bool findLibraries(); + virtual bool findLibraries(bool linkPrl, bool mergeLflags); virtual QString escapeFilePath(const QString &path) const; ProString escapeFilePath(const ProString &path) const { return MakefileGenerator::escapeFilePath(path); } virtual QStringList &findDependencies(const QString &); diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 506aff5c6f..f8b19b3785 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -33,7 +33,6 @@ #include "mingw_make.h" #include "option.h" -#include "meta.h" #include @@ -68,7 +67,7 @@ ProString MingwMakefileGenerator::fixLibFlag(const ProString &lib) return escapeFilePath(lib); } -bool MingwMakefileGenerator::findLibraries() +bool MingwMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) { QList dirs; static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 }; @@ -78,15 +77,16 @@ bool MingwMakefileGenerator::findLibraries() while (it != l.end()) { if ((*it).startsWith("-l")) { QString steam = (*it).mid(2).toQString(); - ProString out; + QString out; for (QList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { QString extension; int ver = findHighestVersion((*dir_it).local(), steam); if (ver > 0) extension += QString::number(ver); - if (QMakeMetaInfo::libExists((*dir_it).local() + '/' + steam) - || exists((*dir_it).local() + '/' + steam + extension + ".a") - || exists((*dir_it).local() + '/' + steam + extension + ".dll.a")) { + QString libBase = (*dir_it).local() + '/' + steam; + if ((linkPrl && processPrlFile(libBase)) + || exists(libBase + extension + ".a") + || exists(libBase + extension + ".dll.a")) { out = *it + extension; break; } @@ -97,10 +97,38 @@ bool MingwMakefileGenerator::findLibraries() QMakeLocalFileName f((*it).mid(2).toQString()); dirs.append(f); *it = "-L" + f.real(); + } else if (linkPrl && !(*it).startsWith('-')) { + QString prl = (*it).toQString(); + if (!processPrlFile(prl) && QDir::isRelativePath(prl)) { + for (QList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { + prl = (*dir_it).local() + '/' + *it; + if (processPrlFile(prl)) + break; + } + } } + ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS"); + for (int prl = 0; prl < prl_libs.size(); ++prl) + it = l.insert(++it, prl_libs.at(prl)); + prl_libs.clear(); ++it; } + if (mergeLflags) { + ProStringList lopts; + for (int lit = 0; lit < l.size(); ++lit) { + ProString opt = l.at(lit); + if (opt.startsWith("-L")) { + if (!lopts.contains(opt)) + lopts.append(opt); + } else { + // Make sure we keep the dependency order of libraries + lopts.removeAll(opt); + lopts.append(opt); + } + } + l = lopts; + } } return true; } diff --git a/qmake/generators/win32/mingw_make.h b/qmake/generators/win32/mingw_make.h index 73018319bc..9a30bc8ea6 100644 --- a/qmake/generators/win32/mingw_make.h +++ b/qmake/generators/win32/mingw_make.h @@ -62,7 +62,7 @@ private: QString preCompHeaderOut; - virtual bool findLibraries(); + virtual bool findLibraries(bool linkPrl, bool mergeLflags); QString objectsLinkLine; }; diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 3d511ea7e8..e5eee2ed90 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -87,7 +87,7 @@ ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib) } bool -Win32MakefileGenerator::findLibraries() +Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) { QList dirs; static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 }; @@ -123,8 +123,9 @@ Win32MakefileGenerator::findLibraries() if(ver > 0) extension += QString::number(ver); extension += ".lib"; - if (QMakeMetaInfo::libExists((*it).local() + '/' + lib) - || exists((*it).local() + '/' + lib + extension)) { + QString libBase = (*it).local() + '/' + lib; + if ((linkPrl && processPrlFile(libBase)) + || exists(libBase + extension)) { out = (*it).real() + Option::dir_sep + lib + extension; break; } @@ -133,67 +134,39 @@ Win32MakefileGenerator::findLibraries() if(out.isEmpty()) out = lib + ".lib"; (*it) = out; + } else if (linkPrl && !processPrlFile(opt) && QDir::isRelativePath(opt)) { + for (QList::Iterator it = dirs.begin(); it != dirs.end(); ++it) { + QString prl = (*it).local() + '/' + opt; + if (processPrlFile(prl)) + break; + } } + + ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS"); + for (int prl = 0; prl < prl_libs.size(); ++prl) + it = l.insert(++it, prl_libs.at(prl)); + prl_libs.clear(); ++it; } + if (mergeLflags) { + ProStringList lopts; + for (int lit = 0; lit < l.size(); ++lit) { + ProString opt = l.at(lit); + if (opt.startsWith("/LIBPATH:")) { + if (!lopts.contains(opt)) + lopts.append(opt); + } else { + // Make sure we keep the dependency order of libraries + lopts.removeAll(opt); + lopts.append(opt); + } + } + l = lopts; + } } return true; } -void -Win32MakefileGenerator::processPrlFiles() -{ - const QString libArg = project->first("QMAKE_L_FLAG").toQString(); - QList libdirs; - static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 }; - for (int i = 0; lflags[i]; i++) { - ProStringList &l = project->values(lflags[i]); - for (int lit = 0; lit < l.size(); ++lit) { - QString opt = l.at(lit).toQString(); - if (opt.startsWith(libArg)) { - QMakeLocalFileName l(opt.mid(libArg.length())); - if (!libdirs.contains(l)) - libdirs.append(l); - } else { - if (!processPrlFile(opt) && (QDir::isRelativePath(opt) || opt.startsWith("-l"))) { - QString tmp; - if (opt.startsWith("-l")) - tmp = opt.mid(2); - else - tmp = opt; - for(QList::Iterator it = libdirs.begin(); it != libdirs.end(); ++it) { - QString prl = (*it).local() + '/' + tmp; - if (processPrlFile(prl)) - break; - } - } - } - ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS"); - for (int prl = 0; prl < prl_libs.size(); ++prl) - l.insert(++lit, prl_libs.at(prl)); - prl_libs.clear(); - } - - // Merge them into a logical order - if (!project->isActiveConfig("no_smart_library_merge") && !project->isActiveConfig("no_lflags_merge")) { - ProStringList lflags; - for (int lit = 0; lit < l.size(); ++lit) { - ProString opt = l.at(lit); - if (opt.startsWith(libArg)) { - if (!lflags.contains(opt)) - lflags.append(opt); - } else { - // Make sure we keep the dependency-order of libraries - lflags.removeAll(opt); - lflags.append(opt); - } - } - l = lflags; - } - } -} - - void Win32MakefileGenerator::processVars() { project->values("QMAKE_ORIG_TARGET") = project->values("TARGET"); diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h index 25b555ec86..7698f13285 100644 --- a/qmake/generators/win32/winmakefile.h +++ b/qmake/generators/win32/winmakefile.h @@ -58,11 +58,10 @@ protected: virtual void writeRcFilePart(QTextStream &t); int findHighestVersion(const QString &dir, const QString &stem); - virtual bool findLibraries(); + virtual bool findLibraries(bool linkPrl, bool mergeLflags); virtual ProString fixLibFlag(const ProString &lib); - virtual void processPrlFiles(); void processVars(); void fixTargetExt(); void processRcFileVar(); From 3e73e3552c8644ace6ac86a8f72e9f1217611979 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 2 Jun 2015 21:21:53 +0200 Subject: [PATCH 175/240] make lflags deduplication independent from link_prl the dependency doesn't seem to make any sense. while the deduplication is a bit naive and thus dangerous, it was already enabled by default anyway by virtue of link_prl being enabled by default, so this amounts to a non-change for by far most projects. use no_lflags_merge to disable it. Change-Id: Ia441931ddbc41ed617aee21e6fe8821e3448d2bc Reviewed-by: Joerg Bornemann --- qmake/generators/makefile.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 0d7571341a..e329fe2898 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -254,8 +254,7 @@ MakefileGenerator::setProjectFile(QMakeProject *p) init(); bool linkPrl = (Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE) && project->isActiveConfig("link_prl"); - bool mergeLflags = linkPrl - && !project->isActiveConfig("no_smart_library_merge") + bool mergeLflags = !project->isActiveConfig("no_smart_library_merge") && !project->isActiveConfig("no_lflags_merge"); findLibraries(linkPrl, mergeLflags); } From 3e01f1ad3b19880628cf26e5395d34a1a9f2af05 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 18 Sep 2015 21:02:37 +0200 Subject: [PATCH 176/240] make processPrlFile() munge the path less when replacing the target don't prepend the normalized path to the target name, but replace only the filename in the original string. this ensures that any variables in the path are preserved. Change-Id: I58c2b54b7114bfdbf659e6a6ce3e02c2611900d4 Reviewed-by: Joerg Bornemann --- qmake/generators/makefile.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index e329fe2898..b4190311ed 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -877,7 +877,6 @@ MakefileGenerator::processPrlFile(QString &file) if(QMakeMetaInfo::libExists(file)) { try_replace_file = true; meta_file = file; - file = ""; } else { QString tmp = file; int ext = tmp.lastIndexOf('.'); @@ -904,14 +903,14 @@ MakefileGenerator::processPrlFile(QString &file) foreach (const ProString &def, libinfo.values("QMAKE_PRL_DEFINES")) if (!defs.contains(def) && prl_defs.contains(def)) defs.append(def); - if(try_replace_file && !libinfo.isEmpty("QMAKE_PRL_TARGET")) { - QString dir; - int slsh = real_meta_file.lastIndexOf('/'); - if(slsh != -1) - dir = real_meta_file.left(slsh+1); - file = libinfo.first("QMAKE_PRL_TARGET").toQString(); - if(QDir::isRelativePath(file)) - file.prepend(dir); + if (try_replace_file) { + ProString tgt = libinfo.first("QMAKE_PRL_TARGET"); + if (!tgt.isEmpty()) { + int off = qMax(file.lastIndexOf('/'), file.lastIndexOf('\\')) + 1; + debug_msg(1, " Replacing library reference %s with %s", + file.mid(off).toLatin1().constData(), tgt.toQString().toLatin1().constData()); + file.replace(off, 1000, tgt.toQString()); + } } } } From c00e11d573447c0247f5db4a1141f6c307e0b36d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 22 Sep 2015 12:47:19 +0200 Subject: [PATCH 177/240] make .prl processing less convoluted don't look up the files and normalize the paths multiple times, as this is inefficient and hard to understand. on the way, processPrlFile() got unnested, and libExists() got nuked. note that a missing QMAKE_PRL_TARGET will be now complained about, which really should never happen. Change-Id: Ibcd77a7f963204c013548496ecd2d635e1a4baba Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen --- qmake/generators/mac/pbuilder_pbx.cpp | 4 +- qmake/generators/makefile.cpp | 92 ++++++++++++--------------- qmake/meta.cpp | 8 +-- qmake/meta.h | 11 ++-- 4 files changed, 50 insertions(+), 65 deletions(-) diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index bfe9f08e77..219415ffdc 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -833,8 +833,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) encode the version number in the Project file which might be a bad things in days to come? --Sam */ - QString lib_file = (*lit) + Option::dir_sep + lib; - if(QMakeMetaInfo::libExists(lib_file)) { + QString lib_file = QMakeMetaInfo::findLib(Option::normalizePath((*lit) + Option::dir_sep + lib)); + if (!lib_file.isEmpty()) { QMakeMetaInfo libinfo(project); if(libinfo.readLib(lib_file)) { if(!libinfo.isEmpty("QMAKE_PRL_TARGET")) { diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index b4190311ed..1aeac4390d 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -872,64 +872,56 @@ MakefileGenerator::init() bool MakefileGenerator::processPrlFile(QString &file) { - bool ret = false, try_replace_file=false; - QString meta_file, orig_file = file; - if(QMakeMetaInfo::libExists(file)) { + bool try_replace_file = false; + QString f = fileFixify(file, FileFixifyBackwards); + QString meta_file = QMakeMetaInfo::findLib(f); + if (!meta_file.isEmpty()) { try_replace_file = true; - meta_file = file; } else { - QString tmp = file; + QString tmp = f; int ext = tmp.lastIndexOf('.'); if(ext != -1) tmp = tmp.left(ext); - meta_file = tmp; + meta_file = QMakeMetaInfo::findLib(tmp); } -// meta_file = fileFixify(meta_file); - QString real_meta_file = Option::normalizePath(meta_file); - if(!meta_file.isEmpty()) { - QString f = fileFixify(real_meta_file, FileFixifyBackwards); - if(QMakeMetaInfo::libExists(f)) { - QMakeMetaInfo libinfo(project); - debug_msg(1, "Processing PRL file: %s", real_meta_file.toLatin1().constData()); - if(!libinfo.readLib(f)) { - fprintf(stderr, "Error processing meta file: %s\n", real_meta_file.toLatin1().constData()); - } else if(project->isActiveConfig("no_read_prl_" + libinfo.type().toLower())) { - debug_msg(2, "Ignored meta file %s [%s]", real_meta_file.toLatin1().constData(), libinfo.type().toLatin1().constData()); - } else { - ret = true; - project->values("QMAKE_CURRENT_PRL_LIBS") = libinfo.values("QMAKE_PRL_LIBS"); - ProStringList &defs = project->values("DEFINES"); - const ProStringList &prl_defs = project->values("PRL_EXPORT_DEFINES"); - foreach (const ProString &def, libinfo.values("QMAKE_PRL_DEFINES")) - if (!defs.contains(def) && prl_defs.contains(def)) - defs.append(def); - if (try_replace_file) { - ProString tgt = libinfo.first("QMAKE_PRL_TARGET"); - if (!tgt.isEmpty()) { - int off = qMax(file.lastIndexOf('/'), file.lastIndexOf('\\')) + 1; - debug_msg(1, " Replacing library reference %s with %s", - file.mid(off).toLatin1().constData(), tgt.toQString().toLatin1().constData()); - file.replace(off, 1000, tgt.toQString()); - } - } - } - } - if(ret) { - QString mf = QMakeMetaInfo::findLib(meta_file); - if(project->values("QMAKE_PRL_INTERNAL_FILES").indexOf(mf) == -1) - project->values("QMAKE_PRL_INTERNAL_FILES").append(mf); - if(project->values("QMAKE_INTERNAL_INCLUDED_FILES").indexOf(mf) == -1) - project->values("QMAKE_INTERNAL_INCLUDED_FILES").append(mf); + if (meta_file.isEmpty()) + return false; + QMakeMetaInfo libinfo(project); + debug_msg(1, "Processing PRL file: %s", meta_file.toLatin1().constData()); + if (!libinfo.readLib(meta_file)) { + fprintf(stderr, "Error processing meta file %s\n", meta_file.toLatin1().constData()); + return false; + } + if (project->isActiveConfig("no_read_prl_" + libinfo.type().toLower())) { + debug_msg(2, "Ignored meta file %s [%s]", + meta_file.toLatin1().constData(), libinfo.type().toLatin1().constData()); + return false; + } + project->values("QMAKE_CURRENT_PRL_LIBS") = libinfo.values("QMAKE_PRL_LIBS"); + ProStringList &defs = project->values("DEFINES"); + const ProStringList &prl_defs = project->values("PRL_EXPORT_DEFINES"); + foreach (const ProString &def, libinfo.values("QMAKE_PRL_DEFINES")) + if (!defs.contains(def) && prl_defs.contains(def)) + defs.append(def); + if (try_replace_file) { + ProString tgt = libinfo.first("QMAKE_PRL_TARGET"); + if (tgt.isEmpty()) { + fprintf(stderr, "Error: %s does not define QMAKE_PRL_TARGET\n", + meta_file.toLatin1().constData()); + } else { + int off = qMax(file.lastIndexOf('/'), file.lastIndexOf('\\')) + 1; + debug_msg(1, " Replacing library reference %s with %s", + file.mid(off).toLatin1().constData(), + tgt.toQString().toLatin1().constData()); + file.replace(off, 1000, tgt.toQString()); } } - if(try_replace_file && file.isEmpty()) { -#if 0 - warn_msg(WarnLogic, "Found prl [%s] file with no target [%s]!", meta_file.toLatin1().constData(), - orig_file.toLatin1().constData()); -#endif - file = orig_file; - } - return ret; + QString mf = fileFixify(meta_file); + if (!project->values("QMAKE_PRL_INTERNAL_FILES").contains(mf)) + project->values("QMAKE_PRL_INTERNAL_FILES").append(mf); + if (!project->values("QMAKE_INTERNAL_INCLUDED_FILES").contains(mf)) + project->values("QMAKE_INTERNAL_INCLUDED_FILES").append(mf); + return true; } void diff --git a/qmake/meta.cpp b/qmake/meta.cpp index 73414df73e..719b2c060f 100644 --- a/qmake/meta.cpp +++ b/qmake/meta.cpp @@ -48,10 +48,8 @@ QMakeMetaInfo::QMakeMetaInfo(QMakeProject *_conf) bool -QMakeMetaInfo::readLib(QString lib) +QMakeMetaInfo::readLib(const QString &meta_file) { - QString meta_file = findLib(lib); - if(cache_vars.contains(meta_file)) { vars = cache_vars[meta_file]; return true; @@ -84,10 +82,8 @@ QMakeMetaInfo::readLib(QString lib) QString -QMakeMetaInfo::findLib(QString lib) +QMakeMetaInfo::findLib(const QString &lib) { - lib = Option::normalizePath(lib); - QString ret; QString extns[] = { Option::prl_ext, /*Option::pkgcfg_ext, Option::libtool_ext,*/ QString() }; for(int extn = 0; !extns[extn].isNull(); extn++) { diff --git a/qmake/meta.h b/qmake/meta.h index a1a30fbfa8..7c91ffda44 100644 --- a/qmake/meta.h +++ b/qmake/meta.h @@ -55,11 +55,11 @@ class QMakeMetaInfo public: QMakeMetaInfo(QMakeProject *_conf); - bool readLib(QString lib); - static QString findLib(QString lib); - static bool libExists(QString lib); - QString type() const; + // These functions expect the path to be normalized + static QString findLib(const QString &lib); + bool readLib(const QString &meta_file); + QString type() const; bool isEmpty(const ProKey &v); ProStringList &values(const ProKey &v); ProString first(const ProKey &v); @@ -91,9 +91,6 @@ inline ProString QMakeMetaInfo::first(const ProKey &v) inline ProValueMap &QMakeMetaInfo::variables() { return vars; } -inline bool QMakeMetaInfo::libExists(QString lib) -{ return !findLib(lib).isNull(); } - QT_END_NAMESPACE #endif // META_H From dd9ec15640fb48fc27011b8f9420411a1637a203 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 25 Sep 2015 14:21:44 +0200 Subject: [PATCH 178/240] rewrite windows library handling first, store the library's full name in the .prl file, like we do on unix. this is not expected to have any side effects, as QMAKE_PRL_TARGET was entirely unused under windows so far. then, rewrite the mingw library handling: instead of letting the linker resolve the actual libraries, do it ourselves like we do for msvc. we could not do that before due to the partial file names in the .prl files: if the library didn't exist at qmake execution time, we'd have to guess the file extension (the msvc generators never had that problem, as they know about only one possible extension for libraries anyway). make use of processPrlFile()'s ability to replace the reference to the .prl file with the actual library. that way we don't need to re-assemble the file name from pieces, which was fragile and inefficient. QMAKE_*_VERSION_OVERRIDE does not affect libraries coming with .prl files any more. additionally, it is now used literally (not numerically), and values less or equal to zero lost their special meaning as "none" - this isn't a problem, because that's the default anyway, and there is no need to override bogus versions from .prl files any more. no changelog for that, as i found no public traces of that feature outside qtbase. [ChangeLog][qmake][Windows] Libraries coming with .prl files can now have non-standard file extensions and a major version of zero. [ChangeLog][qmake][Windows][Important Behavior Changes] The .prl files written by earlier versions of Qt cannot be used any more. This will affect you if you depend on 3rd party libraries which come with .prl files. Patch up QMAKE_PRL_TARGET to contain the complete file name of the library, and replace any /LIBPATH: in QMAKE_PRL_LIBS with -L. (the part about /LIBPATH: actually refers to the next commit.) Change-Id: I07399341bff0609cb6db9660cbc62b141fb2ad96 Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefile.cpp | 9 ++- qmake/generators/unix/unixmake.cpp | 5 ++ qmake/generators/win32/mingw_make.cpp | 41 ++++++++------ qmake/generators/win32/winmakefile.cpp | 78 ++++++++++---------------- qmake/generators/win32/winmakefile.h | 1 - 5 files changed, 63 insertions(+), 71 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 1aeac4390d..f5c3939eaf 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -908,6 +908,9 @@ MakefileGenerator::processPrlFile(QString &file) if (tgt.isEmpty()) { fprintf(stderr, "Error: %s does not define QMAKE_PRL_TARGET\n", meta_file.toLatin1().constData()); + } else if (!tgt.contains('.')) { + fprintf(stderr, "Error: %s defines QMAKE_PRL_TARGET without extension\n", + meta_file.toLatin1().constData()); } else { int off = qMax(file.lastIndexOf('/'), file.lastIndexOf('\\')) + 1; debug_msg(1, " Replacing library reference %s with %s", @@ -954,10 +957,6 @@ qv(const ProStringList &val) void MakefileGenerator::writePrlFile(QTextStream &t) { - ProString target = project->first("TARGET"); - int slsh = target.lastIndexOf(Option::dir_sep); - if(slsh != -1) - target.chopFront(slsh + 1); QString bdir = Option::output_dir; if(bdir.isEmpty()) bdir = qmake_getpwd(); @@ -967,7 +966,7 @@ MakefileGenerator::writePrlFile(QTextStream &t) if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) t << "QMAKE_PRL_SOURCE_DIR =" << qv(project->first("QMAKE_ABSOLUTE_SOURCE_PATH")) << endl; - t << "QMAKE_PRL_TARGET =" << qv(target) << endl; + t << "QMAKE_PRL_TARGET =" << qv(project->first("LIB_TARGET")) << endl; if(!project->isEmpty("PRL_EXPORT_DEFINES")) t << "QMAKE_PRL_DEFINES =" << qv(project->values("PRL_EXPORT_DEFINES")) << endl; if(!project->isEmpty("PRL_EXPORT_CFLAGS")) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 288bd6e498..b44d7f032a 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -275,6 +275,11 @@ UnixMakefileGenerator::init() init2(); project->values("QMAKE_INTERNAL_PRL_LIBS") << "QMAKE_LIBS"; + ProString target = project->first("TARGET"); + int slsh = target.lastIndexOf(Option::dir_sep); + if (slsh != -1) + target.chopFront(slsh + 1); + project->values("LIB_TARGET").prepend(target); if(!project->isEmpty("QMAKE_MAX_FILES_PER_AR")) { bool ok; int max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt(&ok); diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index f8b19b3785..fc21dd4dd2 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -71,39 +71,48 @@ bool MingwMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) { QList dirs; static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 }; + static const QLatin1String extens[] = + { QLatin1String(".dll.a"), QLatin1String(".a"), QLatin1String(0) }; for (int i = 0; lflags[i]; i++) { ProStringList &l = project->values(lflags[i]); ProStringList::Iterator it = l.begin(); while (it != l.end()) { if ((*it).startsWith("-l")) { QString steam = (*it).mid(2).toQString(); - QString out; + ProString verovr = + project->first(ProKey("QMAKE_" + steam.toUpper() + "_VERSION_OVERRIDE")); for (QList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { - QString extension; - int ver = findHighestVersion((*dir_it).local(), steam); - if (ver > 0) - extension += QString::number(ver); - QString libBase = (*dir_it).local() + '/' + steam; - if ((linkPrl && processPrlFile(libBase)) - || exists(libBase + extension + ".a") - || exists(libBase + extension + ".dll.a")) { - out = *it + extension; - break; + QString cand = (*dir_it).real() + Option::dir_sep + steam; + if (linkPrl && processPrlFile(cand)) { + (*it) = cand; + goto found; + } + QString libBase = (*dir_it).local() + '/' + steam + verovr; + for (int e = 0; extens[e].data(); e++) { + if (exists(libBase + extens[e])) { + (*it) = cand + verovr + extens[e]; + goto found; + } } } - if (!out.isEmpty()) // We assume if it never finds it that its correct - (*it) = out; + // We assume if it never finds it that its correct + found: ; } else if ((*it).startsWith("-L")) { QMakeLocalFileName f((*it).mid(2).toQString()); dirs.append(f); *it = "-L" + f.real(); } else if (linkPrl && !(*it).startsWith('-')) { QString prl = (*it).toQString(); - if (!processPrlFile(prl) && QDir::isRelativePath(prl)) { + if (fileInfo(prl).isAbsolute()) { + if (processPrlFile(prl)) + (*it) = prl; + } else { for (QList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { - prl = (*dir_it).local() + '/' + *it; - if (processPrlFile(prl)) + QString cand = (*dir_it).real() + Option::dir_sep + prl; + if (processPrlFile(cand)) { + (*it) = cand; break; + } } } } diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index e5eee2ed90..45e967510c 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -49,33 +49,6 @@ Win32MakefileGenerator::Win32MakefileGenerator() : MakefileGenerator() { } -int -Win32MakefileGenerator::findHighestVersion(const QString &d, const QString &stem) -{ - QString bd = Option::normalizePath(d); - if(!exists(bd)) - return -1; - - QMakeMetaInfo libinfo(project); - bool libInfoRead = libinfo.readLib(bd + '/' + stem); - - // If the library, for which we're trying to find the highest version - // number, is a static library - if (libInfoRead && libinfo.values("QMAKE_PRL_CONFIG").contains("staticlib")) - return -1; - - const ProStringList &vover = project->values(ProKey("QMAKE_" + stem.toUpper() + "_VERSION_OVERRIDE")); - if (!vover.isEmpty()) - return vover.first().toInt(); - - int biggest=-1; - if(libInfoRead - && !libinfo.values("QMAKE_PRL_CONFIG").contains("staticlib") - && !libinfo.isEmpty("QMAKE_PRL_VERSION")) - biggest = libinfo.first("QMAKE_PRL_VERSION").toQString().replace(".", "").toInt(); - return biggest; -} - ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib) { if (lib.startsWith("/LIBPATH:")) @@ -114,32 +87,38 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) dirs.append(lp); (*it) = "/LIBPATH:" + lp.real(); } else if(opt.startsWith("-l") || opt.startsWith("/l")) { - QString lib = opt.right(opt.length() - 2), out; - if(!lib.isEmpty()) { - for(QList::Iterator it = dirs.begin(); - it != dirs.end(); ++it) { - QString extension; - int ver = findHighestVersion((*it).local(), lib); - if(ver > 0) - extension += QString::number(ver); - extension += ".lib"; - QString libBase = (*it).local() + '/' + lib; - if ((linkPrl && processPrlFile(libBase)) - || exists(libBase + extension)) { - out = (*it).real() + Option::dir_sep + lib + extension; + QString lib = opt.mid(2); + ProString verovr = + project->first(ProKey("QMAKE_" + lib.toUpper() + "_VERSION_OVERRIDE")); + for (QList::Iterator dir_it = dirs.begin(); + dir_it != dirs.end(); ++dir_it) { + QString cand = (*dir_it).real() + Option::dir_sep + lib; + if (linkPrl && processPrlFile(cand)) { + (*it) = cand; + goto found; + } + QString extension = verovr + ".lib"; + if (exists((*dir_it).local() + '/' + lib + extension)) { + (*it) = cand + extension; + goto found; + } + } + (*it) = lib + ".lib"; + found: ; + } else if (linkPrl) { + if (fileInfo(opt).isAbsolute()) { + if (processPrlFile(opt)) + (*it) = opt; + } else { + for (QList::Iterator dir_it = dirs.begin(); + dir_it != dirs.end(); ++dir_it) { + QString cand = (*dir_it).real() + Option::dir_sep + opt; + if (processPrlFile(cand)) { + (*it) = cand; break; } } } - if(out.isEmpty()) - out = lib + ".lib"; - (*it) = out; - } else if (linkPrl && !processPrlFile(opt) && QDir::isRelativePath(opt)) { - for (QList::Iterator it = dirs.begin(); it != dirs.end(); ++it) { - QString prl = (*it).local() + '/' + opt; - if (processPrlFile(prl)) - break; - } } ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS"); @@ -242,6 +221,7 @@ void Win32MakefileGenerator::fixTargetExt() } else { project->values("TARGET_EXT").append("." + project->first("QMAKE_EXTENSION_STATICLIB")); project->values("TARGET").first() = project->first("QMAKE_PREFIX_STATICLIB") + project->first("TARGET"); + project->values("LIB_TARGET").prepend(project->first("TARGET") + project->first("TARGET_EXT")); // for the .prl only } } diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h index 7698f13285..ba1821e819 100644 --- a/qmake/generators/win32/winmakefile.h +++ b/qmake/generators/win32/winmakefile.h @@ -57,7 +57,6 @@ protected: virtual void writeRcFilePart(QTextStream &t); - int findHighestVersion(const QString &dir, const QString &stem); virtual bool findLibraries(bool linkPrl, bool mergeLflags); virtual ProString fixLibFlag(const ProString &lib); From 4bb004de94380304d8950e860d1823975927ec59 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 23 Sep 2015 14:57:05 +0200 Subject: [PATCH 179/240] merge MingwMakefileGenerator::findLibraries() into Win32MakefileGenerator as a side effect, this makes the extensions used for searching libraries configurable under windows (QMAKE_LIB_EXTENSIONS). Change-Id: I3e64304fcadbfe74d601b50a70a73180c894503e Reviewed-by: Joerg Bornemann --- mkspecs/win32-g++/qmake.conf | 1 + qmake/generators/makefile.cpp | 16 +++++ qmake/generators/makefile.h | 2 + qmake/generators/win32/mingw_make.cpp | 89 ++++---------------------- qmake/generators/win32/mingw_make.h | 2 +- qmake/generators/win32/msvc_nmake.cpp | 2 - qmake/generators/win32/msvc_vcproj.cpp | 2 - qmake/generators/win32/winmakefile.cpp | 87 +++++++++++++++---------- qmake/generators/win32/winmakefile.h | 1 + 9 files changed, 87 insertions(+), 115 deletions(-) diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index 92bb8f4325..c00b4cd5ff 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -91,6 +91,7 @@ QMAKE_PREFIX_SHLIB = QMAKE_EXTENSION_SHLIB = dll QMAKE_PREFIX_STATICLIB = lib QMAKE_EXTENSION_STATICLIB = a +QMAKE_LIB_EXTENSIONS = a dll.a QMAKE_LIBS = QMAKE_LIBS_CORE = -lole32 -luuid -lws2_32 -ladvapi32 -lshell32 -luser32 -lkernel32 diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index f5c3939eaf..7506678b0d 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -2729,6 +2729,22 @@ MakefileGenerator::fileInfo(QString file) const return fi; } +MakefileGenerator::LibFlagType +MakefileGenerator::parseLibFlag(const ProString &flag, ProString *arg) +{ + if (flag.startsWith("-L")) { + *arg = flag.mid(2); + return LibFlagPath; + } + if (flag.startsWith("-l")) { + *arg = flag.mid(2); + return LibFlagLib; + } + if (flag.startsWith('-')) + return LibFlagOther; + return LibFlagFile; +} + ProStringList MakefileGenerator::fixLibFlags(const ProKey &var) { diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index 8aec360147..61b8f9ac60 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -220,6 +220,8 @@ protected: QString filePrefixRoot(const QString &, const QString &); + enum LibFlagType { LibFlagLib, LibFlagPath, LibFlagFile, LibFlagOther }; + virtual LibFlagType parseLibFlag(const ProString &flag, ProString *arg); ProStringList fixLibFlags(const ProKey &var); virtual ProString fixLibFlag(const ProString &lib); diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index fc21dd4dd2..97bfef88a4 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -62,84 +62,21 @@ QString MingwMakefileGenerator::getManifestFileForRcFile() const ProString MingwMakefileGenerator::fixLibFlag(const ProString &lib) { - if (lib.startsWith("lib")) - return QStringLiteral("-l") + escapeFilePath(lib.mid(3)); - return escapeFilePath(lib); + if (lib.startsWith("-l")) // Fallback for unresolved -l libs. + return QLatin1String("-l") + escapeFilePath(lib.mid(2)); + if (lib.startsWith("-L")) // Lib search path. Needed only by -l above. + return QLatin1String("-L") + + escapeFilePath(Option::fixPathToTargetOS(lib.mid(2).toQString(), false)); + if (lib.startsWith("lib")) // Fallback for unresolved MSVC-style libs. + return QLatin1String("-l") + escapeFilePath(lib.mid(3).toQString()); + return escapeFilePath(Option::fixPathToTargetOS(lib.toQString(), false)); } -bool MingwMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) +MakefileGenerator::LibFlagType +MingwMakefileGenerator::parseLibFlag(const ProString &flag, ProString *arg) { - QList dirs; - static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 }; - static const QLatin1String extens[] = - { QLatin1String(".dll.a"), QLatin1String(".a"), QLatin1String(0) }; - for (int i = 0; lflags[i]; i++) { - ProStringList &l = project->values(lflags[i]); - ProStringList::Iterator it = l.begin(); - while (it != l.end()) { - if ((*it).startsWith("-l")) { - QString steam = (*it).mid(2).toQString(); - ProString verovr = - project->first(ProKey("QMAKE_" + steam.toUpper() + "_VERSION_OVERRIDE")); - for (QList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { - QString cand = (*dir_it).real() + Option::dir_sep + steam; - if (linkPrl && processPrlFile(cand)) { - (*it) = cand; - goto found; - } - QString libBase = (*dir_it).local() + '/' + steam + verovr; - for (int e = 0; extens[e].data(); e++) { - if (exists(libBase + extens[e])) { - (*it) = cand + verovr + extens[e]; - goto found; - } - } - } - // We assume if it never finds it that its correct - found: ; - } else if ((*it).startsWith("-L")) { - QMakeLocalFileName f((*it).mid(2).toQString()); - dirs.append(f); - *it = "-L" + f.real(); - } else if (linkPrl && !(*it).startsWith('-')) { - QString prl = (*it).toQString(); - if (fileInfo(prl).isAbsolute()) { - if (processPrlFile(prl)) - (*it) = prl; - } else { - for (QList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { - QString cand = (*dir_it).real() + Option::dir_sep + prl; - if (processPrlFile(cand)) { - (*it) = cand; - break; - } - } - } - } - - ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS"); - for (int prl = 0; prl < prl_libs.size(); ++prl) - it = l.insert(++it, prl_libs.at(prl)); - prl_libs.clear(); - ++it; - } - if (mergeLflags) { - ProStringList lopts; - for (int lit = 0; lit < l.size(); ++lit) { - ProString opt = l.at(lit); - if (opt.startsWith("-L")) { - if (!lopts.contains(opt)) - lopts.append(opt); - } else { - // Make sure we keep the dependency order of libraries - lopts.removeAll(opt); - lopts.append(opt); - } - } - l = lopts; - } - } - return true; + // Skip MSVC handling from Win32MakefileGenerator + return MakefileGenerator::parseLibFlag(flag, arg); } bool MingwMakefileGenerator::writeMakefile(QTextStream &t) @@ -250,8 +187,6 @@ void MingwMakefileGenerator::init() project->values("TARGET_PRL").append(project->first("TARGET")); - project->values("QMAKE_L_FLAG") << "-L"; - processVars(); project->values("QMAKE_LIBS") += project->values("RES_FILE"); diff --git a/qmake/generators/win32/mingw_make.h b/qmake/generators/win32/mingw_make.h index 9a30bc8ea6..4e94a23ae2 100644 --- a/qmake/generators/win32/mingw_make.h +++ b/qmake/generators/win32/mingw_make.h @@ -62,7 +62,7 @@ private: QString preCompHeaderOut; - virtual bool findLibraries(bool linkPrl, bool mergeLflags); + virtual LibFlagType parseLibFlag(const ProString &flag, ProString *arg); QString objectsLinkLine; }; diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 9c34b187bf..31a9c53c90 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -368,8 +368,6 @@ void NmakeMakefileGenerator::init() return; } - project->values("QMAKE_L_FLAG") << "/LIBPATH:"; - processVars(); project->values("QMAKE_LIBS") += project->values("RES_FILE"); diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index ae4fcfd482..f3155b467d 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -809,8 +809,6 @@ void VcprojGenerator::init() else if (project->first("TEMPLATE") == "vclib") project->values("QMAKE_LIB_FLAG").append("1"); - project->values("QMAKE_L_FLAG") << "/LIBPATH:"; - processVars(); // set /VERSION for EXE/DLL header diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 45e967510c..e6bf3388fa 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -51,43 +51,61 @@ Win32MakefileGenerator::Win32MakefileGenerator() : MakefileGenerator() ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib) { - if (lib.startsWith("/LIBPATH:")) + if (lib.startsWith("-l")) // Fallback for unresolved -l libs. + return escapeFilePath(lib.mid(2) + QLatin1String(".lib")); + if (lib.startsWith("-L")) // Lib search path. Needed only by -l above. return QLatin1String("/LIBPATH:") - + escapeFilePath(Option::fixPathToTargetOS(lib.mid(9).toQString(), false)); - - // This must be a fully resolved library path. + + escapeFilePath(Option::fixPathToTargetOS(lib.mid(2).toQString(), false)); return escapeFilePath(Option::fixPathToTargetOS(lib.toQString(), false)); } +MakefileGenerator::LibFlagType +Win32MakefileGenerator::parseLibFlag(const ProString &flag, ProString *arg) +{ + LibFlagType ret = MakefileGenerator::parseLibFlag(flag, arg); + if (ret != LibFlagFile) + return ret; + // MSVC compatibility. This should be deprecated. + if (flag.startsWith("/LIBPATH:")) { + *arg = flag.mid(9); + return LibFlagPath; + } + // These are pure qmake inventions. They *really* should be deprecated. + if (flag.startsWith("/L")) { + *arg = flag.mid(2); + return LibFlagPath; + } + if (flag.startsWith("/l")) { + *arg = flag.mid(2); + return LibFlagLib; + } + return LibFlagFile; +} + bool Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) { + ProStringList impexts = project->values("QMAKE_LIB_EXTENSIONS"); + if (impexts.isEmpty()) + impexts = project->values("QMAKE_EXTENSION_STATICLIB"); QList dirs; static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 }; for (int i = 0; lflags[i]; i++) { ProStringList &l = project->values(lflags[i]); for (ProStringList::Iterator it = l.begin(); it != l.end();) { - QString opt = (*it).toQString(); - if(opt.startsWith("/LIBPATH:")) { - QString libpath = opt.mid(9); - QMakeLocalFileName lp(libpath); + const ProString &opt = *it; + ProString arg; + LibFlagType type = parseLibFlag(opt, &arg); + if (type == LibFlagPath) { + QMakeLocalFileName lp(arg.toQString()); if (dirs.contains(lp)) { it = l.erase(it); continue; } dirs.append(lp); - (*it) = "/LIBPATH:" + lp.real(); - } else if(opt.startsWith("-L") || opt.startsWith("/L")) { - QString libpath = Option::fixPathToTargetOS(opt.mid(2), false, false); - QMakeLocalFileName lp(libpath); - if (dirs.contains(lp)) { - it = l.erase(it); - continue; - } - dirs.append(lp); - (*it) = "/LIBPATH:" + lp.real(); - } else if(opt.startsWith("-l") || opt.startsWith("/l")) { - QString lib = opt.mid(2); + (*it) = "-L" + lp.real(); + } else if (type == LibFlagLib) { + QString lib = arg.toQString(); ProString verovr = project->first(ProKey("QMAKE_" + lib.toUpper() + "_VERSION_OVERRIDE")); for (QList::Iterator dir_it = dirs.begin(); @@ -97,22 +115,26 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) (*it) = cand; goto found; } - QString extension = verovr + ".lib"; - if (exists((*dir_it).local() + '/' + lib + extension)) { - (*it) = cand + extension; - goto found; + QString libBase = (*dir_it).local() + '/' + lib + verovr; + for (ProStringList::ConstIterator extit = impexts.begin(); + extit != impexts.end(); ++extit) { + if (exists(libBase + '.' + *extit)) { + (*it) = cand + verovr + '.' + *extit; + goto found; + } } } - (*it) = lib + ".lib"; + // We assume if it never finds it that it's correct found: ; - } else if (linkPrl) { - if (fileInfo(opt).isAbsolute()) { - if (processPrlFile(opt)) - (*it) = opt; + } else if (linkPrl && type == LibFlagFile) { + QString lib = opt.toQString(); + if (fileInfo(lib).isAbsolute()) { + if (processPrlFile(lib)) + (*it) = lib; } else { for (QList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { - QString cand = (*dir_it).real() + Option::dir_sep + opt; + QString cand = (*dir_it).real() + Option::dir_sep + lib; if (processPrlFile(cand)) { (*it) = cand; break; @@ -131,7 +153,7 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) ProStringList lopts; for (int lit = 0; lit < l.size(); ++lit) { ProString opt = l.at(lit); - if (opt.startsWith("/LIBPATH:")) { + if (opt.startsWith(QLatin1String("-L"))) { if (!lopts.contains(opt)) lopts.append(opt); } else { @@ -174,7 +196,6 @@ void Win32MakefileGenerator::processVars() fixTargetExt(); processRcFileVar(); - ProString libArg = project->first("QMAKE_L_FLAG"); ProStringList libs; ProStringList &libDir = project->values("QMAKE_LIBDIR"); for (ProStringList::Iterator libDir_it = libDir.begin(); libDir_it != libDir.end(); ++libDir_it) { @@ -182,7 +203,7 @@ void Win32MakefileGenerator::processVars() if (!lib.isEmpty()) { if (lib.endsWith('\\')) lib.chop(1); - libs << libArg + Option::fixPathToTargetOS(lib, false, false); + libs << QLatin1String("-L") + lib; } } project->values("QMAKE_LIBS") += libs + project->values("LIBS"); diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h index ba1821e819..54c4d3be53 100644 --- a/qmake/generators/win32/winmakefile.h +++ b/qmake/generators/win32/winmakefile.h @@ -59,6 +59,7 @@ protected: virtual bool findLibraries(bool linkPrl, bool mergeLflags); + virtual LibFlagType parseLibFlag(const ProString &flag, ProString *arg); virtual ProString fixLibFlag(const ProString &lib); void processVars(); From 8be1c3fae88c265fb3955e14c453ebf4b4e19275 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 25 Sep 2015 14:21:51 +0200 Subject: [PATCH 180/240] remove now superfluous QMAKE_*_VERSION_OVERRIDEs these were necessary to suppress the appending of the qt major version to the library name when reading .prl files. this has outlived its usefulness, as the .prl files now contain the full library name. additionally, the overrides would break the use of qt if the .prl files were not shipped, as zero lost its special meaning as "none". Change-Id: I9f028c17fc0428cb546a4a26ee209febff32da5e Reviewed-by: Joerg Bornemann --- mkspecs/features/qt.prf | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index a8d317a0e3..d416a8955a 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -119,12 +119,6 @@ for(ever) { !mac|!contains(MODULE_CONFIG, lib_bundle): \ MODULE_NAME ~= s,^Qt,Qt$$QT_MAJOR_VERSION, - win32 { - # Make sure the version number isn't appended again to the lib name - QMAKE_$${upper($$MODULE_NAME$$QT_LIBINFIX)}_VERSION_OVERRIDE = 0 - QMAKE_$${upper($$MODULE_NAME$$QT_LIBINFIX)}D_VERSION_OVERRIDE = 0 - } - isEmpty(LINKAGE) { !isEmpty(MODULE_LIBS_ADD): \ LINKAGE = -L$$MODULE_LIBS_ADD From a3292031295a09e5e959141db78c2310e08562ae Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 1 Oct 2015 16:39:57 +0200 Subject: [PATCH 181/240] configure.exe: Add -verbose option. Make it possible to inspect the output of the configure tests. Task-number: QTBUG-48525 Change-Id: If93d597679ae1b189dfdaa485852d34cad52593b Reviewed-by: Oswald Buddenhagen --- tools/configure/configureapp.cpp | 20 +++++++++++++++++--- tools/configure/configureapp.h | 2 ++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index c54bc9426e..d4ea0f6d04 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -83,7 +83,7 @@ static inline void promptKeyPress() exit(0); // Exit cleanly for Ctrl+C } -Configure::Configure(int& argc, char** argv) +Configure::Configure(int& argc, char** argv) : verbose(0) { // Default values for indentation optionIndent = 4; @@ -383,6 +383,7 @@ void Configure::parseCmdLine() configCmdLine.clear(); reloadCmdLine(); } + else if (configCmdLine.at(i) == "-loadconfig") { ++i; if (i != argCount) { @@ -420,6 +421,10 @@ void Configure::parseCmdLine() || configCmdLine.at(i) == "-?") dictionary[ "HELP" ] = "yes"; + else if (configCmdLine.at(i) == "-v" || configCmdLine.at(i) == "-verbose") { + ++verbose; + } + else if (configCmdLine.at(i) == "-qconfig") { ++i; if (i == argCount) @@ -2058,6 +2063,7 @@ bool Configure::displayHelp() desc( "-loadconfig ", "Run configure with the parameters from file configure_.cache."); desc( "-saveconfig ", "Run configure and save the parameters in file configure_.cache."); desc( "-redo", "Run configure with the same parameters as last time.\n"); + desc( "-v, -verbose", "Run configure tests with verbose output.\n"); // Qt\Windows CE only options go below here ----------------------------------------------------------------------------- desc("Qt for Windows CE only:\n\n"); @@ -3377,7 +3383,7 @@ bool Configure::tryCompileProject(const QString &projectPath, const QString &ext } // run qmake - QString command = QString("%1 %2 %3 2>&1") + QString command = QString("%1 %2 %3") .arg(QDir::toNativeSeparators(QDir(newpwd).relativeFilePath(buildPath + "/bin/qmake.exe")), QDir::toNativeSeparators(sourcePath + "/config.tests/" + projectPath), extraOptions); @@ -3389,6 +3395,11 @@ bool Configure::tryCompileProject(const QString &projectPath, const QString &ext addSysroot(&command); } + if (verbose) + cout << qPrintable(command) << endl; + else + command += " 2>&1"; + int code = 0; QString output = Environment::execute(command, &code); //cout << output << endl; @@ -3398,7 +3409,10 @@ bool Configure::tryCompileProject(const QString &projectPath, const QString &ext command = dictionary[ "MAKE" ]; if (command.contains("nmake") || command.contains("jom")) command += " /NOLOGO"; - command += " -s 2>&1"; + if (verbose) + cout << qPrintable(command) << endl; + else + command += " -s 2>&1"; output = Environment::execute(command, &code); //cout << output << endl; diff --git a/tools/configure/configureapp.h b/tools/configure/configureapp.h index de8d1a2469..78cc118a9d 100644 --- a/tools/configure/configureapp.h +++ b/tools/configure/configureapp.h @@ -93,6 +93,8 @@ public: private: bool checkAngleAvailability(QString *errorMessage = 0) const; + int verbose; + // Our variable dictionaries QMap dictionary; QStringList allBuildParts; From 76cd806e6de3f9ed8e89b73dc5babfb227ea8760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 2 Oct 2015 13:53:31 +0200 Subject: [PATCH 182/240] Remove extra semicolon in declaration of QMacAutoReleasePool Change-Id: Ie7f92fae5f80fc2a8b4dae58f6688ea47dbcb95b Reviewed-by: Simon Hausmann --- src/corelib/global/qglobal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 6ee3e37ce6..4813c2b100 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -602,7 +602,7 @@ public: QMacAutoReleasePool(); ~QMacAutoReleasePool(); private: - Q_DISABLE_COPY(QMacAutoReleasePool); + Q_DISABLE_COPY(QMacAutoReleasePool) NSAutoreleasePool *pool; }; From fe383e045b713bed5c2171b2b09e620d9acd3ffb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 9 Jul 2015 12:53:26 -0700 Subject: [PATCH 183/240] syncqt: scan private headers for the "We mean it" comment Change-Id: Ib056b47dde3341ef9a52ffff13ef5f50c72d753d Reviewed-by: Oswald Buddenhagen --- bin/syncqt.pl | 64 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index 3b3e127e86..13cf78a4ab 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -1149,9 +1149,12 @@ if($check_includes) { $header = 0 if($header eq $_); } if($header) { + # We need both $public_header and $private_header because QPA headers count as neither my $public_header = $header; + my $private_header = 0; if($public_header =~ /_p.h$/ || $public_header =~ /_pch.h$/) { $public_header = 0; + $private_header = $header =~ /_p.h$/ && $subdir !~ /3rdparty/ } elsif (isQpaHeader($public_header)) { $public_header = 0; } else { @@ -1169,43 +1172,50 @@ if($check_includes) { } my $iheader = $subdir . "/" . $header; - if($public_header) { - if(open(F, "<$iheader")) { - my $qt_begin_namespace_found = 0; - my $qt_end_namespace_found = 0; - my $qt_namespace_suffix = ""; - my $line; - my $stop_processing = 0; - while($line = ) { - chomp $line; - my $output_line = 1; - if($line =~ /^ *\# *pragma (qt_no_included_check|qt_sync_stop_processing)/) { - $stop_processing = 1; - last; - } elsif($line =~ /^ *\# *include/) { - my $include = $line; - if($line =~ /<.*>/) { - $include =~ s,.*<(.*)>.*,$1,; - } elsif($line =~ /".*"/) { - $include =~ s,.*"(.*)".*,$1,; - } else { - $include = 0; - } - if($include) { + if (open(F, "<$iheader")) { + my $qt_begin_namespace_found = 0; + my $qt_end_namespace_found = 0; + my $qt_namespace_suffix = ""; + my $line; + my $stop_processing = 0; + my $we_mean_it = 0; + while ($line = ) { + chomp $line; + my $output_line = 1; + if ($line =~ /^ *\# *pragma (qt_no_included_check|qt_sync_stop_processing)/) { + $stop_processing = 1; + last; + } elsif ($line =~ /^ *\# *include/) { + my $include = $line; + if ($line =~ /<.*>/) { + $include =~ s,.*<(.*)>.*,$1,; + } elsif ($line =~ /".*"/) { + $include =~ s,.*"(.*)".*,$1,; + } else { + $include = 0; + } + if ($include) { + if ($public_header) { for my $trylib (keys(%modules)) { if(-e "$out_basedir/include/$trylib/$include") { print "$lib: WARNING: $iheader includes $include when it should include $trylib/$include\n"; } } } - } elsif ($header_skip_qt_begin_namespace_test == 0 and $line =~ /^QT_BEGIN_NAMESPACE(_[A-Z_]+)?\s*$/) { + } + } elsif (!$private_header) { + if ($header_skip_qt_begin_namespace_test == 0 and $line =~ /^QT_BEGIN_NAMESPACE(_[A-Z_]+)?\s*$/) { $qt_namespace_suffix = defined($1) ? $1 : ""; $qt_begin_namespace_found = 1; } elsif ($header_skip_qt_begin_namespace_test == 0 and $line =~ /^QT_END_NAMESPACE$qt_namespace_suffix\s*$/) { $qt_end_namespace_found = 1; } + } elsif ($line =~ "^// We mean it.") { + ++$we_mean_it; } + } + if ($public_header) { if ($header_skip_qt_begin_namespace_test == 0 and $stop_processing == 0) { if ($qt_begin_namespace_found == 0) { print "$lib: WARNING: $iheader does not include QT_BEGIN_NAMESPACE\n"; @@ -1215,9 +1225,11 @@ if($check_includes) { print "$lib: WARNING: $iheader has QT_BEGIN_NAMESPACE$qt_namespace_suffix but no QT_END_NAMESPACE$qt_namespace_suffix\n"; } } - - close(F); + } elsif ($private_header) { + print "$lib: WARNING: $iheader does not have the \"We mean it.\" warning\n" if (!$we_mean_it); } + + close(F); } } } From da5b8bfe4647f4a0494e7dd2e08d6652f72803f0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 5 Oct 2015 10:53:00 +0200 Subject: [PATCH 184/240] Add missing "We mean it" comments to private headers. Change-Id: If81a5e1db0fe93377e7cc54a78b01c50b44abe57 Reviewed-by: Liang Qi --- src/corelib/global/qhooks_p.h | 11 +++++++++++ src/platformsupport/dbusmenu/qdbusmenuadaptor_p.h | 11 +++++++++++ src/platformsupport/dbusmenu/qdbusplatformmenu_p.h | 11 +++++++++++ .../dbustray/qstatusnotifieritemadaptor_p.h | 11 +++++++++++ 4 files changed, 44 insertions(+) diff --git a/src/corelib/global/qhooks_p.h b/src/corelib/global/qhooks_p.h index 12a59a1399..3ff4980abe 100644 --- a/src/corelib/global/qhooks_p.h +++ b/src/corelib/global/qhooks_p.h @@ -35,6 +35,17 @@ #ifndef QHOOKS_H #define QHOOKS_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/dbusmenu/qdbusmenuadaptor_p.h b/src/platformsupport/dbusmenu/qdbusmenuadaptor_p.h index 85b5bd8d49..41ab761f12 100644 --- a/src/platformsupport/dbusmenu/qdbusmenuadaptor_p.h +++ b/src/platformsupport/dbusmenu/qdbusmenuadaptor_p.h @@ -45,6 +45,17 @@ #ifndef DBUSMENUADAPTOR_H #define DBUSMENUADAPTOR_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include #include #include "qdbusmenutypes_p.h" diff --git a/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h b/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h index fdad7990e9..6d2d27463f 100644 --- a/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h +++ b/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h @@ -33,6 +33,17 @@ #ifndef QDBUSPLATFORMMENU_H #define QDBUSPLATFORMMENU_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// // // W A R N I N G // ------------- diff --git a/src/platformsupport/dbustray/qstatusnotifieritemadaptor_p.h b/src/platformsupport/dbustray/qstatusnotifieritemadaptor_p.h index 56fbb75d7a..c3849f0e03 100644 --- a/src/platformsupport/dbustray/qstatusnotifieritemadaptor_p.h +++ b/src/platformsupport/dbustray/qstatusnotifieritemadaptor_p.h @@ -45,6 +45,17 @@ #ifndef QSTATUSNOTIFIERITEMADAPTER_P_H #define QSTATUSNOTIFIERITEMADAPTER_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #ifndef QT_NO_SYSTEMTRAYICON #include From da104e7db04a5aeafb99a7b0ef3ab3cdd08da272 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Sat, 3 Oct 2015 17:02:36 +0300 Subject: [PATCH 185/240] Revert "Fix the spurious socket notifications on OS X" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b8e0f7cfc638a71770f44ada828ff2cf6d2ee201. Needs a more testing. Change-Id: Iff0b2741922cfa8f16fbc3f4ce0f83869d6cd8b6 Reviewed-by: Alex Trotsenko Reviewed-by: Tor Arne Vestbø --- .../cfsocketnotifier/qcfsocketnotifier.cpp | 37 ++++--------------- .../cfsocketnotifier/qcfsocketnotifier_p.h | 6 +-- .../platforms/cocoa/qcocoaeventdispatcher.mm | 11 ++---- 3 files changed, 12 insertions(+), 42 deletions(-) diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp index 91f7aeb7d0..2b5723d827 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp @@ -55,15 +55,11 @@ void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CF // notifier is now gone. The upshot is we have to check the notifier // every time. if (callbackType == kCFSocketReadCallBack) { - if (socketInfo->readNotifier && socketInfo->readEnabled) { - socketInfo->readEnabled = false; + if (socketInfo->readNotifier) QGuiApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent); - } } else if (callbackType == kCFSocketWriteCallBack) { - if (socketInfo->writeNotifier && socketInfo->writeEnabled) { - socketInfo->writeEnabled = false; + if (socketInfo->writeNotifier) QGuiApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent); - } } if (cfSocketNotifier->maybeCancelWaitForMoreEvents) @@ -154,8 +150,8 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) } CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket); - // QSocketNotifier doesn't close the socket upon destruction/invalidation - flags &= ~(kCFSocketCloseOnInvalidate | kCFSocketAutomaticallyReenableReadCallBack); + flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write + flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation CFSocketSetSocketFlags(socketInfo->socket, flags); // Add CFSocket to runloop. @@ -175,14 +171,15 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) macSockets.insert(nativeSocket, socketInfo); } + // Increment read/write counters and select enable callbacks if necessary. if (type == QSocketNotifier::Read) { Q_ASSERT(socketInfo->readNotifier == 0); socketInfo->readNotifier = notifier; - socketInfo->readEnabled = false; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); } else if (type == QSocketNotifier::Write) { Q_ASSERT(socketInfo->writeNotifier == 0); socketInfo->writeNotifier = notifier; - socketInfo->writeEnabled = false; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); } } @@ -215,12 +212,10 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) if (type == QSocketNotifier::Read) { Q_ASSERT(notifier == socketInfo->readNotifier); socketInfo->readNotifier = 0; - socketInfo->readEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); } else if (type == QSocketNotifier::Write) { Q_ASSERT(notifier == socketInfo->writeNotifier); socketInfo->writeNotifier = 0; - socketInfo->writeEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); } @@ -237,24 +232,6 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) } } -void QCFSocketNotifier::enableSocketNotifiers() -{ - // Enable CFSockets in runloop. - for (MacSocketHash::ConstIterator it = macSockets.constBegin(); it != macSockets.constEnd(); ++it) { - MacSocketInfo *socketInfo = (*it); - if (CFSocketIsValid(socketInfo->socket)) { - if (socketInfo->readNotifier && !socketInfo->readEnabled) { - socketInfo->readEnabled = true; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); - } - if (socketInfo->writeNotifier && !socketInfo->writeEnabled) { - socketInfo->writeEnabled = true; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); - } - } - } -} - void QCFSocketNotifier::removeSocketNotifiers() { // Remove CFSockets from the runloop. diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h index 1d6dcf2885..af8122f753 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h @@ -53,14 +53,11 @@ QT_BEGIN_NAMESPACE struct MacSocketInfo { - MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0), - readEnabled(false), writeEnabled(false) {} + MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {} CFSocketRef socket; CFRunLoopSourceRef runloop; QObject *readNotifier; QObject *writeNotifier; - bool readEnabled; - bool writeEnabled; }; typedef QHash MacSocketHash; @@ -84,7 +81,6 @@ public: void setMaybeCancelWaitForMoreEventsCallback(MaybeCancelWaitForMoreEventsFn callBack); void registerSocketNotifier(QSocketNotifier *notifier); void unregisterSocketNotifier(QSocketNotifier *notifier); - void enableSocketNotifiers(); void removeSocketNotifiers(); MacSocketHash macSockets; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index b443233d15..52b2e23345 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -845,13 +845,10 @@ QCocoaEventDispatcher::QCocoaEventDispatcher(QObject *parent) void QCocoaEventDispatcherPrivate::waitingObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity activity, void *info) { - QCocoaEventDispatcher *dispatcher = static_cast(info); - if (activity == kCFRunLoopBeforeWaiting) { - dispatcher->d_func()->cfSocketNotifier.enableSocketNotifiers(); - emit dispatcher->aboutToBlock(); - } else { - emit dispatcher->awake(); - } + if (activity == kCFRunLoopBeforeWaiting) + emit static_cast(info)->aboutToBlock(); + else + emit static_cast(info)->awake(); } void QCocoaEventDispatcherPrivate::processPostedEvents() From 9684e16f002f4f813c49141de2933a7fb0c71461 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 27 Sep 2015 13:26:56 -0700 Subject: [PATCH 186/240] QUtf8Codec: Remove dead code The maximum value for charsNeeded is 4, so if bytesAvailable is less than charsNeeded - 1, the it's at most 2. It can't be larger than 2. Found by Coverity, CID 11000. Change-Id: I42e7ef1a481840699a8dffff1407ef9221a4fd80 Reviewed-by: Lars Knoll --- src/corelib/codecs/qutfcodec_p.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/corelib/codecs/qutfcodec_p.h b/src/corelib/codecs/qutfcodec_p.h index 99887352c9..d97145c6fc 100644 --- a/src/corelib/codecs/qutfcodec_p.h +++ b/src/corelib/codecs/qutfcodec_p.h @@ -217,8 +217,6 @@ namespace QUtf8Functions return Traits::Error; if (bytesAvailable > 1 && !isContinuationByte(Traits::peekByte(src, 1))) return Traits::Error; - if (bytesAvailable > 2 && !isContinuationByte(Traits::peekByte(src, 2))) - return Traits::Error; return Traits::EndOfString; } From 694d30035593addc377fea374d1dbe8e3f5ca503 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 2 Oct 2015 13:52:17 +0200 Subject: [PATCH 187/240] qdoc: Avoid extra spaces in function synopses Instead of blindly leading each parameter name with a space, check if the data type name is empty first. This prevents extra spaces from appearing in QML method signatures, which can be documented with parameter names only, without data types. Change-Id: I726f8c29839430186fcae4ac19d00404233395e0 Task-number: QTWEBSITE-691 Reviewed-by: Martin Smith --- src/tools/qdoc/cppcodemarker.cpp | 6 +++--- src/tools/qdoc/htmlgenerator.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index 774ff115b9..3b38745b70 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -156,12 +156,13 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, if (func->metaness() != FunctionNode::MacroWithoutParams) { synopsis += "("; if (!func->parameters().isEmpty()) { - //synopsis += QLatin1Char(' '); QVector::ConstIterator p = func->parameters().constBegin(); while (p != func->parameters().constEnd()) { if (p != func->parameters().constBegin()) synopsis += ", "; synopsis += typified((*p).dataType()); + if (!(*p).dataType().isEmpty()) + synopsis += QLatin1Char(' '); if (style != Subpage && !(*p).name().isEmpty()) synopsis += "<@param>" + protect((*p).name()) + ""; @@ -170,7 +171,6 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, synopsis += " = " + protect((*p).defaultValue()); ++p; } - //synopsis += QLatin1Char(' '); } synopsis += QLatin1Char(')'); } @@ -334,7 +334,7 @@ QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary) synopsis += ", "; synopsis += typified((*p).dataType()); if (!(*p).name().isEmpty()) { - if (!synopsis.endsWith(QLatin1Char('('))) + if (!(*p).dataType().isEmpty()) synopsis += QLatin1Char(' '); synopsis += "<@param>" + protect((*p).name()) + ""; } diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index eaa6de42ef..5b2039764a 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -3150,7 +3150,7 @@ void HtmlGenerator::generateQmlItem(const Node *node, } marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])"), "\\1\\2"); - marked.replace("<@param>", " "); + marked.replace("<@param>", ""); marked.replace("", ""); if (summary) @@ -3390,7 +3390,7 @@ void HtmlGenerator::generateSynopsis(const Node *node, } marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])"), "\\1\\2"); - marked.replace("<@param>", " "); + marked.replace("<@param>", ""); marked.replace("", ""); if (style == CodeMarker::Summary) { From decc54636821b7239815209165943211deaee5e9 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 5 Oct 2015 19:32:19 +0200 Subject: [PATCH 188/240] Doc: remove unused code from OpenGL Window example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ifb2c7206dee55102eba91b4c30543f3ac4838259 Reviewed-by: Topi Reiniö --- examples/gui/openglwindow/main.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/examples/gui/openglwindow/main.cpp b/examples/gui/openglwindow/main.cpp index 6ab05176a6..d79ecd6510 100644 --- a/examples/gui/openglwindow/main.cpp +++ b/examples/gui/openglwindow/main.cpp @@ -57,8 +57,6 @@ public: void render() Q_DECL_OVERRIDE; private: - GLuint loadShader(GLenum type, const char *source); - GLuint m_posAttr; GLuint m_colAttr; GLuint m_matrixUniform; @@ -113,14 +111,6 @@ static const char *fragmentShaderSource = //! [3] //! [4] -GLuint TriangleWindow::loadShader(GLenum type, const char *source) -{ - GLuint shader = glCreateShader(type); - glShaderSource(shader, 1, &source, 0); - glCompileShader(shader); - return shader; -} - void TriangleWindow::initialize() { m_program = new QOpenGLShaderProgram(this); From 590c73bee2083c8dc8635123726e138a26dd3a97 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 2 Oct 2015 09:08:45 +0200 Subject: [PATCH 189/240] Add static assert checking QT_POINTER_SIZE. QT_POINTER_SIZE is determined by the configure test ptrsize, which has been observed to fail due to unrelated build issues. Add a check to verify the correct size. Task-number: QTBUG-48525 Change-Id: I4fcb9761b54370b39c0d3e1e0a6d0aa3c0223f40 Reviewed-by: Joerg Bornemann --- src/corelib/global/qglobal.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 7da9713e80..02220d0db2 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -120,7 +120,9 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); // (if this list becomes too long, consider factoring into a separate file) Q_STATIC_ASSERT_X(sizeof(int) == 4, "Qt assumes that int is 32 bits"); Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits"); - +#ifndef QT_BOOTSTRAPPED +Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "configure test ptrsize failed to correctly determine QT_POINTER_SIZE"); +#endif /*! \class QFlag From c7e5e1d9e01849347a9e59b8285477a20d82002b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 4 Sep 2015 17:56:20 +0200 Subject: [PATCH 190/240] Move shortcut handling back into QPA and simplify delivery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 7f5b94b47 moved shortcut handling into QGuiApplication (for all platforms except OS X), due to crashes on Android where the events are delivered from another thread. Now that we have synchronous event delivery (also across threads) from QPA, this is no longer needed, and we can move the code back to QPA, where the platform has more control over when and how shortcut events are delivered in relation to normal key events. Handling shortcuts is as before a two step process. We first send a QKeyEvent::ShortcutOverride event to the active window, which allows clients (widgets e.g.) to signal that they want to handle the shortcut themselves. If the override event is accepted, we treat it as the shortcut not being handled as a regular shortcut, and send the event as a key press instead, allowing the widget to handle the shortcut. If nothing accepted the shortcut override event we pass it along to the global shortcut map, which will treat the event as handled if an exact or partial match is found. The QShortcutMap::tryShortcutEvent() and nextState() implementation has been simplified to not use the events accepted state for its internal operation, which removes the need for saving the state of the incoming event. The QKeyEvent::ShortcutOverride event was also always sent with the accepted state set to false, by calling ignore() on it before sending it. This is now explicit by having shortcut override events being ignored by default in their constructor, and the documentation has been updated accordingly. Change-Id: I9afa29dbc00bef09fd22ee6bf09661b06340d715 Reviewed-by: Tor Arne Vestbø Reviewed-by: Christian Stromme --- src/gui/kernel/qevent.cpp | 10 +- src/gui/kernel/qguiapplication.cpp | 13 -- src/gui/kernel/qshortcutmap.cpp | 59 +++---- src/gui/kernel/qshortcutmap_p.h | 5 +- src/gui/kernel/qwindowsysteminterface.cpp | 178 +++++++++------------- src/gui/kernel/qwindowsysteminterface.h | 18 +-- src/plugins/platforms/cocoa/qnsview.mm | 6 +- src/testlib/qtestkeyboard.h | 6 +- 8 files changed, 109 insertions(+), 186 deletions(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 780a102644..0bb21752bc 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -1029,8 +1029,10 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, when keys are pressed or released. A key event contains a special accept flag that indicates whether - the receiver will handle the key event. This flag is set by default, - so there is no need to call accept() when acting on a key event. + the receiver will handle the key event. This flag is set by default + for QEvent::KeyPress and QEvent::KeyRelease, so there is no need to + call accept() when acting on a key event. For QEvent::ShortcutOverride + the receiver needs to explicitly accept the event to trigger the override. Calling ignore() on a key event will propagate it to the parent widget. The event is propagated up the parent widget chain until a widget accepts it or an event filter consumes it. @@ -1065,6 +1067,8 @@ QKeyEvent::QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const nScanCode(0), nVirtualKey(0), nModifiers(0), c(count), autor(autorep) { + if (type == QEvent::ShortcutOverride) + ignore(); } /*! @@ -1092,6 +1096,8 @@ QKeyEvent::QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, nScanCode(nativeScanCode), nVirtualKey(nativeVirtualKey), nModifiers(nativeModifiers), c(count), autor(autorep) { + if (type == QEvent::ShortcutOverride) + ignore(); } diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index b309f67866..3f50ab8688 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1915,19 +1915,6 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE window = QGuiApplication::focusWindow(); } -#if !defined(Q_OS_OSX) - // On OS X the shortcut override is checked earlier, see: QWindowSystemInterface::handleKeyEvent() - const bool checkShortcut = e->keyType == QEvent::KeyPress && window != 0; - if (checkShortcut) { - QKeyEvent override(QEvent::ShortcutOverride, e->key, e->modifiers, - e->nativeScanCode, e->nativeVirtualKey, e->nativeModifiers, - e->unicode, e->repeat, e->repeatCount); - override.setTimestamp(e->timestamp); - if (QWindowSystemInterface::tryHandleShortcutOverrideEvent(window, &override)) - return; - } -#endif // Q_OS_OSX - QKeyEvent ev(e->keyType, e->key, e->modifiers, e->nativeScanCode, e->nativeVirtualKey, e->nativeModifiers, e->unicode, e->repeat, e->repeatCount); diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index 3e267f2e0b..3b2e6ffd29 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -309,59 +309,42 @@ QKeySequence::SequenceMatch QShortcutMap::state() } /*! \internal - Uses ShortcutOverride event to see if any widgets want to override - the event. If not, uses nextState(QKeyEvent) to check for a grabbed - Shortcut, and dispatchEvent() is found and identical. + Uses nextState(QKeyEvent) to check for a grabbed shortcut. - \note that this function should only be called from QWindowSystemInterface, - otherwise it will result in duplicate events. + If so, it is dispatched using dispatchEvent(). + + Returns true if a shortcut handled the event. \sa nextState, dispatchEvent */ -bool QShortcutMap::tryShortcutEvent(QObject *o, QKeyEvent *e) +bool QShortcutMap::tryShortcut(QKeyEvent *e) { Q_D(QShortcutMap); if (e->key() == Qt::Key_unknown) return false; - bool wasAccepted = e->isAccepted(); - bool wasSpontaneous = e->spont; - if (d->currentState == QKeySequence::NoMatch) { - ushort orgType = e->t; - e->t = QEvent::ShortcutOverride; - e->ignore(); - QCoreApplication::sendEvent(o, e); - e->t = orgType; - e->spont = wasSpontaneous; - if (e->isAccepted()) { - if (!wasAccepted) - e->ignore(); - return false; - } - } + QKeySequence::SequenceMatch previousState = state(); - QKeySequence::SequenceMatch result = nextState(e); - bool stateWasAccepted = e->isAccepted(); - if (wasAccepted) - e->accept(); - else - e->ignore(); - - int identicalMatches = d->identicals.count(); - - switch(result) { + switch (nextState(e)) { case QKeySequence::NoMatch: - return stateWasAccepted; + // In the case of going from a partial match to no match we handled the + // event, since we already stated that we did for the partial match. But + // in the normal case of directly going to no match we say we didn't. + return previousState == QKeySequence::PartialMatch; + case QKeySequence::PartialMatch: + // For a partial match we don't know yet if we will handle the shortcut + // but we need to say we did, so that we get the follow-up key-presses. + return true; case QKeySequence::ExactMatch: resetState(); dispatchEvent(e); + // If there are no identicals we've only found disabled shortcuts, and + // shouldn't say that we handled the event. + return d->identicals.count() > 0; default: - break; + Q_UNREACHABLE(); } - // If nextState is QKeySequence::ExactMatch && identicals.count == 0 - // we've only found disabled shortcuts - return identicalMatches > 0 || result == QKeySequence::PartialMatch; } /*! \internal @@ -396,10 +379,6 @@ QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e) } } - // Should we eat this key press? - if (d->currentState == QKeySequence::PartialMatch - || (d->currentState == QKeySequence::ExactMatch && d->identicals.count())) - e->accept(); // Does the new state require us to clean up? if (result == QKeySequence::NoMatch) clearSequence(d->currentSequences); diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h index 2376d27c78..16542b078a 100644 --- a/src/gui/kernel/qshortcutmap_p.h +++ b/src/gui/kernel/qshortcutmap_p.h @@ -75,7 +75,9 @@ public: int setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &key = QKeySequence()); int setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &key = QKeySequence()); - bool tryShortcutEvent(QObject *o, QKeyEvent *e); + QKeySequence::SequenceMatch state(); + + bool tryShortcut(QKeyEvent *e); bool hasShortcutForKeySequence(const QKeySequence &seq) const; #ifdef Dump_QShortcutMap @@ -85,7 +87,6 @@ public: private: void resetState(); QKeySequence::SequenceMatch nextState(QKeyEvent *e); - QKeySequence::SequenceMatch state(); void dispatchEvent(QKeyEvent *e); QKeySequence::SequenceMatch find(QKeyEvent *e, int ignoredModifiers = 0); diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 09e6e2deb8..e7abff9ccc 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -41,6 +41,7 @@ #include #include #include "qhighdpiscaling_p.h" +#include QT_BEGIN_NAMESPACE @@ -191,114 +192,50 @@ void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, ulong timest QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -bool QWindowSystemInterface::tryHandleShortcutEvent(QWindow *w, int k, Qt::KeyboardModifiers mods, - const QString & text, bool autorep, ushort count) -{ - unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); - return tryHandleShortcutEvent(w, timestamp, k, mods, text, autorep, count); -} - -bool QWindowSystemInterface::tryHandleShortcutEvent(QWindow *w, ulong timestamp, int k, Qt::KeyboardModifiers mods, - const QString & text, bool autorep, ushort count) +bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestamp, int keyCode, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, + quint32 nativeVirtualKey, quint32 nativeModifiers, const QString &text, bool autorepeat, ushort count) { #ifndef QT_NO_SHORTCUT - QGuiApplicationPrivate::modifier_buttons = mods; + if (!window) + window = QGuiApplication::focusWindow(); - if (!w) - w = QGuiApplication::focusWindow(); - if (!w) - return false; + QShortcutMap &shortcutMap = QGuiApplicationPrivate::instance()->shortcutMap; + if (shortcutMap.state() == QKeySequence::NoMatch) { + // Check if the shortcut is overridden by some object in the event delivery path (typically the focus object). + // If so, we should not look up the shortcut in the shortcut map, but instead deliver the event as a regular + // key event, so that the target that accepted the shortcut override event can handle it. Note that we only + // do this if the shortcut map hasn't found a partial shortcut match yet. If it has, the shortcut can not be + // overridden. + QWindowSystemInterfacePrivate::KeyEvent *shortcutOverrideEvent = new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp, + QEvent::ShortcutOverride, keyCode, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorepeat, count); - QObject *focus = w->focusObject(); - if (!focus) - focus = w; + { + // FIXME: Template handleWindowSystemEvent to support both sync and async delivery + QScopedValueRollback syncRollback(QWindowSystemInterfacePrivate::synchronousWindowSystemEvents); + QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = true; - QKeyEvent qevent(QEvent::ShortcutOverride, k, mods, text, autorep, count); - qevent.setTimestamp(timestamp); - return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(focus, &qevent); + if (QWindowSystemInterfacePrivate::handleWindowSystemEvent(shortcutOverrideEvent)) + return false; + } + } + + // The shortcut event is dispatched as a QShortcutEvent, not a QKeyEvent, but we use + // the QKeyEvent as a container for the various properties that the shortcut map needs + // to inspect to determine if a shortcut matched the keys that were pressed. + QKeyEvent keyEvent(QEvent::ShortcutOverride, keyCode, modifiers, nativeScanCode, + nativeVirtualKey, nativeModifiers, text, autorepeat, count); + + return shortcutMap.tryShortcut(&keyEvent); #else - Q_UNUSED(w) + Q_UNUSED(window) Q_UNUSED(timestamp) - Q_UNUSED(k) - Q_UNUSED(mods) - Q_UNUSED(text) - Q_UNUSED(autorep) - Q_UNUSED(count) - return false; -#endif -} - -bool QWindowSystemInterface::tryHandleShortcutOverrideEvent(QWindow *w, QKeyEvent *ev) -{ -#ifndef QT_NO_SHORTCUT - Q_ASSERT(ev->type() == QKeyEvent::ShortcutOverride); - QGuiApplicationPrivate::modifier_buttons = ev->modifiers(); - - QObject *focus = w->focusObject(); - if (!focus) - focus = w; - return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(focus, ev); -#else - Q_UNUSED(w) - Q_UNUSED(ev) - return false; -#endif -} - -// used by QTestLib to directly send shortcuts to objects -bool QWindowSystemInterface::tryHandleShortcutEventToObject(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, - const QString &text, bool autorep, ushort count) -{ -#ifndef QT_NO_SHORTCUT - QGuiApplicationPrivate::modifier_buttons = mods; - - QKeyEvent qevent(QEvent::ShortcutOverride, k, mods, text, autorep, count); - qevent.setTimestamp(timestamp); - return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(o, &qevent); -#else - Q_UNUSED(w) - Q_UNUSED(timestamp) - Q_UNUSED(k) - Q_UNUSED(mods) - Q_UNUSED(text) - Q_UNUSED(autorep) - Q_UNUSED(count) - return false; -#endif -} - -bool QWindowSystemInterface::tryHandleExtendedShortcutEvent(QWindow *w, int k, Qt::KeyboardModifiers mods, - quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, - const QString &text, bool autorep, ushort count) -{ - unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); - return tryHandleExtendedShortcutEvent(w, timestamp, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); -} - -bool QWindowSystemInterface::tryHandleExtendedShortcutEvent(QWindow *w, ulong timestamp, int k, Qt::KeyboardModifiers mods, - quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, - const QString &text, bool autorep, ushort count) -{ -#ifndef QT_NO_SHORTCUT - QGuiApplicationPrivate::modifier_buttons = mods; - - QObject *focus = w->focusObject(); - if (!focus) - focus = w; - - QKeyEvent qevent(QEvent::ShortcutOverride, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); - qevent.setTimestamp(timestamp); - return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(focus, &qevent); -#else - Q_UNUSED(w) - Q_UNUSED(timestamp) - Q_UNUSED(k) - Q_UNUSED(mods) + Q_UNUSED(key) + Q_UNUSED(modifiers) Q_UNUSED(nativeScanCode) Q_UNUSED(nativeVirtualKey) Q_UNUSED(nativeModifiers) Q_UNUSED(text) - Q_UNUSED(autorep) + Q_UNUSED(autorepeat) Q_UNUSED(count) return false; #endif @@ -312,13 +249,8 @@ bool QWindowSystemInterface::handleKeyEvent(QWindow *w, QEvent::Type t, int k, Q bool QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { - // This is special handling needed for OS X which eventually will call sendEvent(), on other platforms - // this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for - // shortcut overriding on other platforms. -#if defined(Q_OS_OSX) - if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(tlw, timestamp, k, mods, text)) + if (t == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(tlw, timestamp, k, mods, 0, 0, 0, text, autorep, count)) return true; -#endif // Q_OS_OSX QWindowSystemInterfacePrivate::KeyEvent * e = new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count); @@ -343,7 +275,9 @@ bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestam const QString& text, bool autorep, ushort count, bool tryShortcutOverride) { - Q_UNUSED(tryShortcutOverride) + if (tryShortcutOverride && type == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(tlw, timestamp, key, modifiers, 0, 0, 0, text, autorep, count)) + return true; + QWindowSystemInterfacePrivate::KeyEvent * e = new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); @@ -926,9 +860,41 @@ Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::Keybo QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous); } -Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) +Q_GUI_EXPORT bool qt_handleShortcutEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) { - return QWindowSystemInterface::tryHandleShortcutEventToObject(o, timestamp, k, mods, text, autorep, count); +#ifndef QT_NO_SHORTCUT + + // FIXME: This method should not allow targeting a specific object, but should + // instead forward the event to a window, which then takes care of normal event + // propagation. We need to fix a lot of tests before we can refactor this (the + // window needs to be exposed and active and have a focus object), so we leave + // it as is for now. See QTBUG-48577. + + QGuiApplicationPrivate::modifier_buttons = mods; + + QKeyEvent qevent(QEvent::ShortcutOverride, k, mods, text, autorep, count); + qevent.setTimestamp(timestamp); + + QShortcutMap &shortcutMap = QGuiApplicationPrivate::instance()->shortcutMap; + if (shortcutMap.state() == QKeySequence::NoMatch) { + // Try sending as QKeyEvent::ShortcutOverride first + QCoreApplication::sendEvent(o, &qevent); + if (qevent.isAccepted()) + return false; + } + + // Then as QShortcutEvent + return shortcutMap.tryShortcut(&qevent); +#else + Q_UNUSED(o) + Q_UNUSED(timestamp) + Q_UNUSED(k) + Q_UNUSED(mods) + Q_UNUSED(text) + Q_UNUSED(autorep) + Q_UNUSED(count) + return false; +#endif } static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt) diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 97bd087b53..387c1e00b9 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -78,22 +78,8 @@ public: Qt::KeyboardModifiers mods = Qt::NoModifier, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); - static bool tryHandleShortcutOverrideEvent(QWindow *w, QKeyEvent *ev); - - static bool tryHandleShortcutEvent(QWindow *w, int k, Qt::KeyboardModifiers mods, - const QString & text = QString(), bool autorep = false, ushort count = 1); - static bool tryHandleShortcutEvent(QWindow *w, ulong timestamp, int k, Qt::KeyboardModifiers mods, - const QString & text = QString(), bool autorep = false, ushort count = 1); - - static bool tryHandleShortcutEventToObject(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, - const QString & text = QString(), bool autorep = false, ushort count = 1); - - static bool tryHandleExtendedShortcutEvent(QWindow *w, int k, Qt::KeyboardModifiers mods, - quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, - const QString & text = QString(), bool autorep = false, ushort count = 1); - static bool tryHandleExtendedShortcutEvent(QWindow *w, ulong timestamp, int k, Qt::KeyboardModifiers mods, - quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, - const QString & text = QString(), bool autorep = false, ushort count = 1); + static bool handleShortcutEvent(QWindow *w, ulong timestamp, int k, Qt::KeyboardModifiers mods, quint32 nativeScanCode, + quint32 nativeVirtualKey, quint32 nativeModifiers, const QString & text = QString(), bool autorep = false, ushort count = 1); static bool handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); static bool handleKeyEvent(QWindow *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index a4f4c0855b..24ee26ce46 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1446,10 +1446,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) if (eventType == QEvent::KeyPress) { if (m_composingText.isEmpty()) { - QKeyEvent override(QEvent::ShortcutOverride, keyCode, modifiers, - nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1); - override.setTimestamp(timestamp); - m_sendKeyEvent = !QWindowSystemInterface::tryHandleShortcutOverrideEvent(focusWindow, &override); + m_sendKeyEvent = !QWindowSystemInterface::handleShortcutEvent(focusWindow, timestamp, keyCode, + modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1); } QObject *fo = QGuiApplication::focusObject(); diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h index d73658d8fc..d2b3ef240b 100644 --- a/src/testlib/qtestkeyboard.h +++ b/src/testlib/qtestkeyboard.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); -Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1); +Q_GUI_EXPORT bool qt_handleShortcutEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1); namespace QTest { @@ -97,7 +97,7 @@ namespace QTest if (action == Shortcut) { int timestamp = 0; - qt_sendShortcutOverrideEvent(window, timestamp, code, modifier, text, repeat); + qt_handleShortcutEvent(window, timestamp, code, modifier, text, repeat); return; } @@ -178,7 +178,7 @@ namespace QTest QKeyEvent a(press ? QEvent::KeyPress : QEvent::KeyRelease, code, modifier, text, repeat); QSpontaneKeyEvent::setSpontaneous(&a); - if (press && qt_sendShortcutOverrideEvent(widget, a.timestamp(), code, modifier, text, repeat)) + if (press && qt_handleShortcutEvent(widget, a.timestamp(), code, modifier, text, repeat)) return; if (!qApp->notify(widget, &a)) QTest::qWarn("Keyboard event not accepted by receiving widget"); From 3c449f7da5b606a83cabc35ccff9c71826561b02 Mon Sep 17 00:00:00 2001 From: Libor Tomsik Date: Fri, 25 Sep 2015 10:04:21 +0200 Subject: [PATCH 191/240] Fix selected items after sorting in QTableWidget OldPersistentIndexes store selected items during sort operation. They were wrongly taken from static list of indexes. This change takes them from parent (QTableWidget) who maintains the list of selected segments. Task-number: QTBUG-48408 Change-Id: Ie1bc4071a275dd76d113d883ab30ccd4cb1fa625 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/itemviews/qtablewidget.cpp | 12 +++++++----- .../qtablewidget/tst_qtablewidget.cpp | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp index f0c7ac0d32..a10b95f701 100644 --- a/src/widgets/itemviews/qtablewidget.cpp +++ b/src/widgets/itemviews/qtablewidget.cpp @@ -555,9 +555,7 @@ void QTableModel::ensureSorted(int column, Qt::SortOrder order, LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); std::stable_sort(sorting.begin(), sorting.end(), compare); - - QModelIndexList oldPersistentIndexes = persistentIndexList(); - QModelIndexList newPersistentIndexes = oldPersistentIndexes; + QModelIndexList oldPersistentIndexes, newPersistentIndexes; QVector newTable = tableItems; QVector newVertical = verticalHeaderItems; QVector colItems = columnItems(column); @@ -573,7 +571,12 @@ void QTableModel::ensureSorted(int column, Qt::SortOrder order, newRow = oldRow; vit = colItems.insert(vit, item); if (newRow != oldRow) { - changed = true; + if (!changed) { + emit layoutAboutToBeChanged(); + oldPersistentIndexes = persistentIndexList(); + newPersistentIndexes = oldPersistentIndexes; + changed = true; + } // move the items @ oldRow to newRow int cc = columnCount(); QVector rowItems(cc); @@ -600,7 +603,6 @@ void QTableModel::ensureSorted(int column, Qt::SortOrder order, } if (changed) { - emit layoutAboutToBeChanged(); tableItems = newTable; verticalHeaderItems = newVertical; changePersistentIndexList(oldPersistentIndexes, diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp index 6d2b2ea964..ea31fd19dd 100644 --- a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp +++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp @@ -94,6 +94,7 @@ private slots: void task262056_sortDuplicate(); void itemWithHeaderItems(); void mimeData(); + void selectedRowAfterSorting(); private: QTableWidget *testWidget; @@ -1565,5 +1566,23 @@ void tst_QTableWidget::mimeData() delete data2; } +void tst_QTableWidget::selectedRowAfterSorting() +{ + TestTableWidget table(3,3); + table.setSelectionBehavior(QAbstractItemView::SelectRows); + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) + table.setItem(r,c,new QTableWidgetItem(QStringLiteral("0"))); + QHeaderView *localHorizontalHeader = table.horizontalHeader(); + localHorizontalHeader->setSortIndicator(1,Qt::DescendingOrder); + table.setProperty("sortingEnabled",true); + table.selectRow(1); + table.item(1,1)->setText("9"); + QCOMPARE(table.selectedItems().count(),3); + foreach (QTableWidgetItem *item, table.selectedItems()) { + QCOMPARE(item->row(),0); + } +} + QTEST_MAIN(tst_QTableWidget) #include "tst_qtablewidget.moc" From c87bb03e5eb53b7a33a8501b8f5b4227ec7ddd57 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 24 Jun 2015 15:25:11 +0200 Subject: [PATCH 192/240] QDebug: add missing docs for op<<(Container) Change-Id: I9f89d8e792bf0d432a0b2522f26026c6ad81e2f4 Reviewed-by: Thiago Macieira --- src/corelib/io/qdebug.cpp | 56 +++++++++++++++++++++++++++++++++++++++ src/corelib/io/qdebug.h | 16 +++++------ 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 30086b2dac..6b8f832eed 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -668,6 +668,62 @@ QDebug &QDebug::resetFormat() \internal */ +/*! + \fn QDebug operator<<(QDebug stream, const QList &list) + \relates QDebug + + Writes the contents of \a list to \a stream. \c T needs to + support streaming into QDebug. +*/ + +/*! + \fn QDebug operator<<(QDebug stream, const QVector &vector) + \relates QDebug + + Writes the contents of \a vector to \a stream. \c T needs to + support streaming into QDebug. +*/ + +/*! + \fn QDebug operator<<(QDebug stream, const QSet &set) + \relates QDebug + + Writes the contents of \a set to \a stream. \c T needs to + support streaming into QDebug. +*/ + +/*! + \fn QDebug operator<<(QDebug stream, const QMap &map) + \relates QDebug + + Writes the contents of \a map to \a stream. Both \c Key and + \c T need to support streaming into QDebug. +*/ + +/*! + \fn QDebug operator<<(QDebug stream, const QHash &hash) + \relates QDebug + + Writes the contents of \a hash to \a stream. Both \c Key and + \c T need to support streaming into QDebug. +*/ + +/*! + \fn QDebug operator<<(QDebug stream, const QPair &pair) + \relates QDebug + + Writes the contents of \a pair to \a stream. Both \c T1 and + \c T2 need to support streaming into QDebug. +*/ + +/*! + \fn QDebug operator<<(QDebug stream, const QFlags &flag) + \relates QDebug + \since 4.7 + + Writes \a flag to \a stream. +*/ + /*! \class QDebugStateSaver diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 3c3ceba249..7c75608e2a 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -201,12 +201,12 @@ inline QDebug operator<<(QDebug debug, const QVector &vec) return operator<<(debug, vec.toList()); } -template -inline QDebug operator<<(QDebug debug, const QMap &map) +template +inline QDebug operator<<(QDebug debug, const QMap &map) { const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QMap("; - for (typename QMap::const_iterator it = map.constBegin(); + for (typename QMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) { debug << '(' << it.key() << ", " << it.value() << ')'; } @@ -215,12 +215,12 @@ inline QDebug operator<<(QDebug debug, const QMap &map) return debug.maybeSpace(); } -template -inline QDebug operator<<(QDebug debug, const QHash &hash) +template +inline QDebug operator<<(QDebug debug, const QHash &hash) { const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QHash("; - for (typename QHash::const_iterator it = hash.constBegin(); + for (typename QHash::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it) debug << '(' << it.key() << ", " << it.value() << ')'; debug << ')'; @@ -261,7 +261,7 @@ inline QDebug operator<<(QDebug debug, const QContiguousCache &cache) return debug.maybeSpace(); } -#ifndef QT_NO_QOBJECT +#if !defined(QT_NO_QOBJECT) && !defined(Q_QDOC) Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, int value, const QMetaObject *meta, const char *name); Q_CORE_EXPORT QDebug qt_QMetaEnum_flagDebugOperator(QDebug &dbg, quint64 value, const QMetaObject *meta, const char *name); @@ -290,7 +290,7 @@ inline typename QtPrivate::QEnableIf< !QtPrivate::IsQEnumHelper::Value && !QtPrivate::IsQEnumHelper >::Value, QDebug>::Type qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags &flags) -#else // !QT_NO_QOBJECT +#else // !QT_NO_QOBJECT && !Q_QDOC template inline QDebug qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags &flags) #endif From 48e9f69dfbec7650fb8aa4c99c8978082a87186e Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sun, 19 Jul 2015 21:43:23 +0200 Subject: [PATCH 193/240] doc: fix a typo in QVersionNumber docs Change-Id: I6ba901efe0822ed1d5ae8359f8b7aefe730f2d06 Reviewed-by: Keith Gardner Reviewed-by: Thiago Macieira --- src/corelib/tools/qversionnumber.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp index 4197fc47b1..f432820252 100644 --- a/src/corelib/tools/qversionnumber.cpp +++ b/src/corelib/tools/qversionnumber.cpp @@ -202,7 +202,7 @@ QVector QVersionNumber::segments() const Returns an equivalent version number but with all trailing zeros removed. To check if two numbers are equivalent, use normalized() on both version - numbers before perforing the compare. + numbers before performing the compare. \snippet qversionnumber/main.cpp 4 */ From eb88d77a2752b11dfb1f12f1267676ebfb36cf0c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 29 Jul 2015 14:58:02 +0200 Subject: [PATCH 194/240] tst_qversionnumber: enable c++11 and don't use core-private QVersionNumber is now public API. Change-Id: I5b21b6ce5f1651158b6f29bc6f06e5d4e133bed8 Reviewed-by: Keith Gardner Reviewed-by: Thiago Macieira --- tests/auto/corelib/tools/qversionnumber/qversionnumber.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro b/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro index 1e74d42bbd..ba4b2b40cb 100644 --- a/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro +++ b/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro @@ -1,4 +1,5 @@ CONFIG += testcase parallel_test +contains(QT_CONFIG, c++11):CONFIG += c++11 c++14 TARGET = tst_qversionnumber -QT = core-private testlib +QT = core testlib SOURCES = tst_qversionnumber.cpp From 52812e9a2b578d3c25f85612a6fdcffbdefd84e1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 6 Jul 2015 16:57:31 +0200 Subject: [PATCH 195/240] QMulti(Map|Hash): add move ctor from Q(Map|Hash) There was a copy ctor, a move ctor was missing. Change-Id: If09a4d4c74682169759eff43b298f6c77702c169 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qhash.h | 3 +++ src/corelib/tools/qmap.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 8d65a018ae..8e71925fd9 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -948,6 +948,9 @@ public: // compiler-generated destructor is fine! QMultiHash(const QHash &other) : QHash(other) {} +#ifdef Q_COMPILER_RVALUE_REFS + QMultiHash(QHash &&other) Q_DECL_NOTHROW : QHash(std::move(other)) {} +#endif void swap(QMultiHash &other) { QHash::swap(other); } // prevent QMultiHash<->QHash swaps inline typename QHash::iterator replace(const Key &key, const T &value) diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index b7bd268bda..df2e5f1caf 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -1177,6 +1177,9 @@ public: } #endif QMultiMap(const QMap &other) : QMap(other) {} +#ifdef Q_COMPILER_RVALUE_REFS + QMultiMap(QMap &&other) Q_DECL_NOTHROW : QMap(std::move(other)) {} +#endif inline void swap(QMultiMap &other) { QMap::swap(other); } inline typename QMap::iterator replace(const Key &key, const T &value) From f89803e459ca02ad4be0c2e1620b80b0cb248642 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 3 Jul 2015 13:24:31 +0200 Subject: [PATCH 196/240] Make container move semantics consistent Make all containers (excepting QVarLengthArray) - nothrow default-constructible - nothrow move-constructible - nothrow move-assignable - nothrow swappable [ChangeLog][QtCore] All containers (with the exception of QVarLengthArray, but including QSharedPointer) are now nothrow_default_constructible, nothrow_move_constructible, nothrow_move_assignable, and nothrow-swappable. Change-Id: I12138d262f9f7f600f0e1218137da208c12e7c0a Reviewed-by: Thiago Macieira --- src/corelib/tools/qbitarray.h | 2 +- src/corelib/tools/qhash.h | 4 ++-- src/corelib/tools/qlinkedlist.h | 9 +++++---- src/corelib/tools/qlist.h | 7 ++++--- src/corelib/tools/qmap.h | 12 ++++++------ src/corelib/tools/qqueue.h | 2 +- src/corelib/tools/qset.h | 4 ++-- src/corelib/tools/qstack.h | 2 +- 8 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h index 4e5c26b86a..e686d53db4 100644 --- a/src/corelib/tools/qbitarray.h +++ b/src/corelib/tools/qbitarray.h @@ -48,7 +48,7 @@ class Q_CORE_EXPORT QBitArray QByteArray d; public: - inline QBitArray() {} + inline QBitArray() Q_DECL_NOTHROW {} explicit QBitArray(int size, bool val = false); QBitArray(const QBitArray &other) : d(other.d) {} inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; } diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 8e71925fd9..a18dd74706 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -935,7 +935,7 @@ template class QMultiHash : public QHash { public: - QMultiHash() {} + QMultiHash() Q_DECL_NOTHROW {} #ifdef Q_COMPILER_INITIALIZER_LISTS inline QMultiHash(std::initializer_list > list) { @@ -951,7 +951,7 @@ public: #ifdef Q_COMPILER_RVALUE_REFS QMultiHash(QHash &&other) Q_DECL_NOTHROW : QHash(std::move(other)) {} #endif - void swap(QMultiHash &other) { QHash::swap(other); } // prevent QMultiHash<->QHash swaps + void swap(QMultiHash &other) Q_DECL_NOTHROW { QHash::swap(other); } // prevent QMultiHash<->QHash swaps inline typename QHash::iterator replace(const Key &key, const T &value) { return QHash::insert(key, value); } diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index f216aa121c..2854885d60 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -74,7 +74,7 @@ class QLinkedList union { QLinkedListData *d; QLinkedListNode *e; }; public: - inline QLinkedList() : d(const_cast(&QLinkedListData::shared_null)) { } + inline QLinkedList() Q_DECL_NOTHROW : d(const_cast(&QLinkedListData::shared_null)) { } inline QLinkedList(const QLinkedList &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); } #if defined(Q_COMPILER_INITIALIZER_LISTS) inline QLinkedList(std::initializer_list list) @@ -86,11 +86,12 @@ public: ~QLinkedList(); QLinkedList &operator=(const QLinkedList &); #ifdef Q_COMPILER_RVALUE_REFS - inline QLinkedList(QLinkedList &&other) : d(other.d) { other.d = const_cast(&QLinkedListData::shared_null); } - inline QLinkedList &operator=(QLinkedList &&other) + QLinkedList(QLinkedList &&other) Q_DECL_NOTHROW + : d(other.d) { other.d = const_cast(&QLinkedListData::shared_null); } + QLinkedList &operator=(QLinkedList &&other) Q_DECL_NOTHROW { QLinkedList moved(std::move(other)); swap(moved); return *this; } #endif - inline void swap(QLinkedList &other) { qSwap(d, other.d); } + inline void swap(QLinkedList &other) Q_DECL_NOTHROW { qSwap(d, other.d); } bool operator==(const QLinkedList &l) const; inline bool operator!=(const QLinkedList &l) const { return !(*this == l); } diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 32e0141d55..9a57a2c6a5 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -143,11 +143,12 @@ public: ~QList(); QList &operator=(const QList &l); #ifdef Q_COMPILER_RVALUE_REFS - inline QList(QList &&other) : d(other.d) { other.d = const_cast(&QListData::shared_null); } - inline QList &operator=(QList &&other) + inline QList(QList &&other) Q_DECL_NOTHROW + : d(other.d) { other.d = const_cast(&QListData::shared_null); } + inline QList &operator=(QList &&other) Q_DECL_NOTHROW { QList moved(std::move(other)); swap(moved); return *this; } #endif - inline void swap(QList &other) { qSwap(d, other.d); } + inline void swap(QList &other) Q_DECL_NOTHROW { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QList(std::initializer_list args) : d(const_cast(&QListData::shared_null)) diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index df2e5f1caf..fe9ddaaa32 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -321,7 +321,7 @@ class QMap QMapData *d; public: - inline QMap() : d(static_cast *>(const_cast(&QMapDataBase::shared_null))) { } + inline QMap() Q_DECL_NOTHROW : d(static_cast *>(const_cast(&QMapDataBase::shared_null))) { } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QMap(std::initializer_list > list) : d(static_cast *>(const_cast(&QMapDataBase::shared_null))) @@ -336,17 +336,17 @@ public: QMap &operator=(const QMap &other); #ifdef Q_COMPILER_RVALUE_REFS - inline QMap(QMap &&other) + inline QMap(QMap &&other) Q_DECL_NOTHROW : d(other.d) { other.d = static_cast *>( const_cast(&QMapDataBase::shared_null)); } - inline QMap &operator=(QMap &&other) + inline QMap &operator=(QMap &&other) Q_DECL_NOTHROW { QMap moved(std::move(other)); swap(moved); return *this; } #endif - inline void swap(QMap &other) { qSwap(d, other.d); } + inline void swap(QMap &other) Q_DECL_NOTHROW { qSwap(d, other.d); } explicit QMap(const typename std::map &other); std::map toStdMap() const; @@ -1168,7 +1168,7 @@ template class QMultiMap : public QMap { public: - QMultiMap() {} + QMultiMap() Q_DECL_NOTHROW {} #ifdef Q_COMPILER_INITIALIZER_LISTS inline QMultiMap(std::initializer_list > list) { @@ -1180,7 +1180,7 @@ public: #ifdef Q_COMPILER_RVALUE_REFS QMultiMap(QMap &&other) Q_DECL_NOTHROW : QMap(std::move(other)) {} #endif - inline void swap(QMultiMap &other) { QMap::swap(other); } + void swap(QMultiMap &other) Q_DECL_NOTHROW { QMap::swap(other); } inline typename QMap::iterator replace(const Key &key, const T &value) { return QMap::insert(key, value); } diff --git a/src/corelib/tools/qqueue.h b/src/corelib/tools/qqueue.h index 7a7abab070..0cb8353d0f 100644 --- a/src/corelib/tools/qqueue.h +++ b/src/corelib/tools/qqueue.h @@ -44,7 +44,7 @@ class QQueue : public QList { public: // compiler-generated special member functions are fine! - inline void swap(QQueue &other) { QList::swap(other); } // prevent QList<->QQueue swaps + inline void swap(QQueue &other) Q_DECL_NOTHROW { QList::swap(other); } // prevent QList<->QQueue swaps #ifndef Q_QDOC // bring in QList::swap(int, int). We cannot say using QList::swap, // because we don't want to make swap(QList&) available. diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index aeba6cf68d..ed89617cd6 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -48,7 +48,7 @@ class QSet typedef QHash Hash; public: - inline QSet() {} + inline QSet() Q_DECL_NOTHROW {} #ifdef Q_COMPILER_INITIALIZER_LISTS inline QSet(std::initializer_list list) { @@ -60,7 +60,7 @@ public: // compiler-generated copy/move ctor/assignment operators are fine! // compiler-generated destructor is fine! - inline void swap(QSet &other) { q_hash.swap(other.q_hash); } + inline void swap(QSet &other) Q_DECL_NOTHROW { q_hash.swap(other.q_hash); } inline bool operator==(const QSet &other) const { return q_hash == other.q_hash; } diff --git a/src/corelib/tools/qstack.h b/src/corelib/tools/qstack.h index 278e89ca2f..cb72316c32 100644 --- a/src/corelib/tools/qstack.h +++ b/src/corelib/tools/qstack.h @@ -44,7 +44,7 @@ class QStack : public QVector { public: // compiler-generated special member functions are fine! - inline void swap(QStack &other) { QVector::swap(other); } // prevent QVector<->QStack swaps + inline void swap(QStack &other) Q_DECL_NOTHROW { QVector::swap(other); } // prevent QVector<->QStack swaps inline void push(const T &t) { QVector::append(t); } T pop(); T &top(); From 60b17b0231984fc9f8328b58a95a59294effed5e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 18 Sep 2015 09:07:57 +0200 Subject: [PATCH 197/240] Fix documentation of new method Change-Id: I7accaac765f5514b67279b640de7f98c8042c35a Reviewed-by: Thiago Macieira --- src/dbus/qdbusmessage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp index 302d94696d..32b7787514 100644 --- a/src/dbus/qdbusmessage.cpp +++ b/src/dbus/qdbusmessage.cpp @@ -378,10 +378,10 @@ QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &inte \since 5.6 Constructs a new DBus message with the given \a path, \a interface - and \a name, representing a signal emission to \a destination. + and \a name, representing a signal emission to a specific destination. A DBus signal is emitted from one application and is received only by - the application owning the destination service name. + the application owning the destination \a service name. The QDBusMessage object that is returned can be sent using the QDBusConnection::send() function. From b1a8f75db8740a630e97994df0465251208a3470 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 21 Sep 2015 14:11:16 +0200 Subject: [PATCH 198/240] Add \since 5.6 to method docs and document the changed signal Change-Id: I9a727a2a01927693e8182eb5518ee4d8f6e5be23 Reviewed-by: Thiago Macieira Reviewed-by: Erik Verbruggen --- src/corelib/statemachine/qhistorystate.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp index a0ebb9d239..8887ce27e5 100644 --- a/src/corelib/statemachine/qhistorystate.cpp +++ b/src/corelib/statemachine/qhistorystate.cpp @@ -166,6 +166,8 @@ QHistoryState::~QHistoryState() Returns this history state's default transition. The default transition is taken when the history state has never been entered before. The target states of the default transition therefore make up the default state. + + \since 5.6 */ QAbstractTransition *QHistoryState::defaultTransition() const { @@ -178,6 +180,8 @@ QAbstractTransition *QHistoryState::defaultTransition() const This will set the source state of the \a transition to the history state. Note that the eventTest method of the \a transition will never be called. + + \since 5.6 */ void QHistoryState::setDefaultTransition(QAbstractTransition *transition) { @@ -290,6 +294,15 @@ bool QHistoryState::event(QEvent *e) \sa QHistoryState::historyType */ +/*! + \fn QHistoryState::defaultTransitionChanged() + \since 5.6 + + This signal is emitted when the defaultTransition property is changed. + + \sa QHistoryState::defaultTransition +*/ + QT_END_NAMESPACE #endif //QT_NO_STATEMACHINE From 275f5347efffd3919aae884eb5943fbe36010fc5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 21 Sep 2015 14:20:25 +0200 Subject: [PATCH 199/240] Fix \since This API only appeared in 5.6. Change-Id: I3ddda44f7c55c94c7f22f76f83a45094209d8c39 Reviewed-by: Thiago Macieira --- src/corelib/tools/qcommandlineparser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index 20e0688f45..15c7a0646f 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -325,13 +325,13 @@ void QCommandLineParser::setSingleDashWordOptionMode(QCommandLineParser::SingleD \sa setOptionsAfterPositionalArgumentsMode() - \since 5.5 + \since 5.6 */ /*! Sets the parsing mode to \a parsingMode. This must be called before process() or parse(). - \since 5.5 + \since 5.6 */ void QCommandLineParser::setOptionsAfterPositionalArgumentsMode(QCommandLineParser::OptionsAfterPositionalArgumentsMode parsingMode) { From 04e8d72a642bac5708343f3519dbf3d69507118c Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Fri, 15 May 2015 16:12:18 +0300 Subject: [PATCH 200/240] xcb: Add support for Qt::WA_ShowWithoutActivating Also re-enable and update the tst_showWithoutActivating test. Change-Id: Ic7fa9b1bf7637e4661c593aaeabb3220cd4204ff Task-number: QTBUG-46098 Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbwindow.cpp | 17 +++++++- .../qwidget_window/tst_qwidget_window.cpp | 42 +++++++++---------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 6575149d86..e7f5bbf0e9 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -775,6 +775,13 @@ void QXcbWindow::setVisible(bool visible) hide(); } +static inline bool testShowWithoutActivating(const QWindow *window) +{ + // QWidget-attribute Qt::WA_ShowWithoutActivating. + const QVariant showWithoutActivating = window->property("_q_showWithoutActivating"); + return showWithoutActivating.isValid() && showWithoutActivating.toBool(); +} + void QXcbWindow::show() { if (window()->isTopLevel()) { @@ -822,7 +829,9 @@ void QXcbWindow::show() updateNetWmStateBeforeMap(); } - if (connection()->time() != XCB_TIME_CURRENT_TIME) + if (testShowWithoutActivating(window())) + updateNetWmUserTime(0); + else if (connection()->time() != XCB_TIME_CURRENT_TIME) updateNetWmUserTime(connection()->time()); if (window()->objectName() == QLatin1String("QSystemTrayIconSysWindow")) @@ -1329,7 +1338,11 @@ void QXcbWindow::updateNetWmStateBeforeMap() void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp) { xcb_window_t wid = m_window; - connection()->setNetWmUserTime(timestamp); + // If timestamp == 0, then it means that the window should not be + // initially activated. Don't update global user time for this + // special case. + if (timestamp != 0) + connection()->setNetWmUserTime(timestamp); const bool isSupportedByWM = connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW)); if (m_netWmUserTimeWindow || isSupportedByWM) { 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 4bdb299213..5188dfbcfa 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -338,30 +338,30 @@ void tst_QWidget_window::tst_windowFilePath() void tst_QWidget_window::tst_showWithoutActivating() { -#ifndef Q_DEAD_CODE_FROM_QT4_X11 - QSKIP("This test is X11-only."); -#else - QWidget w; - w.show(); - QVERIFY(QTest::qWaitForWindowExposed(&w)); - QApplication::processEvents(); + QString platformName = QGuiApplication::platformName().toLower(); + if (platformName == "cocoa") + QSKIP("Cocoa: This fails. Figure out why."); + else if (platformName != QStringLiteral("xcb") + && platformName != QStringLiteral("windows") + && platformName != QStringLiteral("ios")) + QSKIP("Qt::WA_ShowWithoutActivating is currently supported only on xcb, windows, and ios platforms."); - QApplication::clipboard(); - QLineEdit *lineEdit = new QLineEdit; - lineEdit->setAttribute(Qt::WA_ShowWithoutActivating, true); - lineEdit->show(); - lineEdit->setAttribute(Qt::WA_ShowWithoutActivating, false); - lineEdit->raise(); - lineEdit->activateWindow(); + QWidget w1; + w1.setAttribute(Qt::WA_ShowWithoutActivating); + w1.show(); + QVERIFY(!QTest::qWaitForWindowActive(&w1)); - Window window; - int revertto; - QTRY_COMPARE(lineEdit->winId(), - (XGetInputFocus(QX11Info::display(), &window, &revertto), window) ); - // Note the use of the , before window because we want the XGetInputFocus to be re-executed - // in each iteration of the inside loop of the QTRY_COMPARE macro + QWidget w2; + w2.show(); + QVERIFY(QTest::qWaitForWindowActive(&w2)); -#endif // Q_DEAD_CODE_FROM_QT4_X11 + QWidget w3; + w3.setAttribute(Qt::WA_ShowWithoutActivating); + w3.show(); + QVERIFY(!QTest::qWaitForWindowActive(&w3)); + + w3.activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(&w3)); } void tst_QWidget_window::tst_paintEventOnSecondShow() From 363498ee5a64dcd14f7c43174921492af497d569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 6 Oct 2015 14:17:05 +0200 Subject: [PATCH 201/240] QMacStyle: Set NSButton title to empty string, not nil Fixes the following warning [-Wnonnull]: warning: null passed to a callee that requires a non-null argument Change-Id: I52f7dc338afdcfe0cd605281d1bf59025abb5ac6 Reviewed-by: Jake Petroules --- src/widgets/styles/qmacstyle_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index fe8ea837be..e8da137654 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -1867,7 +1867,7 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const if ([bv isKindOfClass:[NSButton class]]) { NSButton *bc = (NSButton *)bv; - bc.title = nil; + bc.title = @""; } if ([bv isKindOfClass:[NSControl class]]) { From a41cd126a3861c1ee5e8318b3594e9463f899234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Wed, 7 Oct 2015 16:28:57 +0100 Subject: [PATCH 202/240] xml: Use the correct QString::arg() overload arg(const QString &a, int fieldWidth, QChar fillChar) was being called and that's not what we want. Found with clazy static analyzer Change-Id: Ia5051bb2f979af496038c66580d199262b6cfa8b Reviewed-by: Marc Mutz Reviewed-by: Mitch Curtis --- src/xml/sax/qxml.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index 8e382f76f6..97a3b070d8 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -6457,7 +6457,7 @@ bool QXmlSimpleReaderPrivate::isExpandedEntityValueTooLarge(QString *errorMessag if (*expandedIt > entityCharacterLimit) { if (errorMessage) { *errorMessage = QString::fromLatin1("The XML entity \"%1\" expands to a string that is too large to process (%2 characters > %3).") - .arg(entity, *expandedIt, entityCharacterLimit); + .arg(entity, QString::number(*expandedIt), QString::number(entityCharacterLimit)); } return true; } From 3ae1eb623685375468afb8cc71075467d54f12f3 Mon Sep 17 00:00:00 2001 From: Libor Tomsik Date: Wed, 7 Oct 2015 21:03:15 +0200 Subject: [PATCH 203/240] QTreeWidget: Fixed reverse order of first level items in Drag and Drop The list with taken indexes (selected items) was created in reverse order but then retrieved from beginning. This was causing unexpected rotation of the moved items. Task-number: QTBUG-45320 Change-Id: I858d9af7b838bbd2618442c176dac0648b3512c4 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/itemviews/qtreewidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp index 5970e94292..db4451c99a 100644 --- a/src/widgets/itemviews/qtreewidget.cpp +++ b/src/widgets/itemviews/qtreewidget.cpp @@ -3386,7 +3386,7 @@ void QTreeWidget::dropEvent(QDropEvent *event) { // Remove the items QList taken; - for (int i = indexes.count() - 1; i >= 0; --i) { + for (int i = 0; i < indexes.count(); ++i) { QTreeWidgetItem *parent = itemFromIndex(indexes.at(i)); if (!parent || !parent->parent()) { taken.append(takeTopLevelItem(indexes.at(i).row())); From a3a7d485fa2d572225c7050badf28784316aec37 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 30 Sep 2015 23:27:20 +0200 Subject: [PATCH 204/240] Fix crash in QMetaProperty::write for custom types and conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit if t >= QMetaType::User, we would not return false nor call convert. We would then pass a pointer to whatever is in the QVariant to the qt_metacall that is expecting a pointer to an object of a different type. Since we have custom converters, we can call QVarent::convert even for custom types anyway. [ChangeLog][QtCore] Fixed crash when setting a QVariant of a different type to a property of a custom type. Attempt to do a conversion instead. Task-number: QTBUG-40644 Change-Id: Ib6fbd7e7ddcf25c5ee247ea04177e079f6d7de35 Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qmetaobject.cpp | 4 +- src/dbus/qdbusinternalfilters.cpp | 3 ++ .../qmetaproperty/tst_qmetaproperty.cpp | 45 ++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index f1ad74efb4..6abec27684 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2014 Olivier Goffart +** Copyright (C) 2015 Olivier Goffart ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -3068,7 +3068,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const if (t == QMetaType::UnknownType) return false; } - if (t != QMetaType::QVariant && t != (uint)value.userType() && (t < QMetaType::User && !v.convert((QVariant::Type)t))) + if (t != QMetaType::QVariant && int(t) != value.userType() && !v.convert(t)) return false; } diff --git a/src/dbus/qdbusinternalfilters.cpp b/src/dbus/qdbusinternalfilters.cpp index d9e5f7408b..fd6f91e65a 100644 --- a/src/dbus/qdbusinternalfilters.cpp +++ b/src/dbus/qdbusinternalfilters.cpp @@ -366,6 +366,9 @@ static int writeProperty(QObject *obj, const QByteArray &property_name, QVariant value = other; } + if (mp.userType() == qMetaTypeId()) + value = QVariant::fromValue(QDBusVariant(value)); + // the property type here should match return mp.write(obj, value) ? PropertyWriteSuccess : PropertyWriteFailed; } diff --git a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp index 4d54aa4dc8..10656a0dcd 100644 --- a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp +++ b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2014 Olivier Goffart +** Copyright (C) 2015 Olivier Goffart ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -38,15 +38,29 @@ #include #include +struct CustomType +{ + int padding; + QString str; + CustomType(const QString &str = QString()) : str(str) {} + operator QString() const { return str; } + friend bool operator!=(const CustomType &a, const CustomType &b) + { return a.str != b.str; } +}; + +Q_DECLARE_METATYPE(CustomType) + class tst_QMetaProperty : public QObject { Q_OBJECT Q_PROPERTY(EnumType value WRITE setValue READ getValue) Q_PROPERTY(EnumType value2 WRITE set_value READ get_value) + Q_PROPERTY(QString value7 MEMBER value7) Q_PROPERTY(int value8 READ value8) Q_PROPERTY(int value9 READ value9 CONSTANT) Q_PROPERTY(int value10 READ value10 FINAL) Q_PROPERTY(QMap map MEMBER map) + Q_PROPERTY(CustomType custom MEMBER custom) private slots: void hasStdCppSet(); @@ -55,6 +69,7 @@ private slots: void gadget(); void readAndWriteWithLazyRegistration(); void mapProperty(); + void conversion(); public: enum EnumType { EnumType1 }; @@ -68,7 +83,9 @@ public: int value9() const { return 1; } int value10() const { return 1; } + QString value7; QMap map; + CustomType custom; }; void tst_QMetaProperty::hasStdCppSet() @@ -195,5 +212,31 @@ void tst_QMetaProperty::mapProperty() QCOMPARE(map, (v.value >())); } +void tst_QMetaProperty::conversion() +{ + QMetaType::registerConverter(); + QMetaType::registerConverter(); + + QString hello = QStringLiteral("Hello"); + + // Write to a QString property using a CustomType in a QVariant + QMetaProperty value7P = metaObject()->property(metaObject()->indexOfProperty("value7")); + QVERIFY(value7P.isValid()); + QVERIFY(value7P.write(this, QVariant::fromValue(CustomType(hello)))); + QCOMPARE(value7, hello); + + // Write to a CustomType property using a QString in a QVariant + QMetaProperty customP = metaObject()->property(metaObject()->indexOfProperty("custom")); + QVERIFY(customP.isValid()); + QVERIFY(customP.write(this, hello)); + QCOMPARE(custom.str, hello); + + // Something that cannot be converted should fail + QVERIFY(!customP.write(this, 45)); + QVERIFY(!customP.write(this, QVariant::fromValue(this))); + QVERIFY(!value7P.write(this, QVariant::fromValue(this))); + QVERIFY(!value7P.write(this, QVariant::fromValue(this))); +} + QTEST_MAIN(tst_QMetaProperty) #include "tst_qmetaproperty.moc" From 6542161d5c698d461a11f0e5ca6cc2a00d33a824 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Wed, 7 Oct 2015 16:49:47 +0300 Subject: [PATCH 205/240] Fix spurious socket notifications on OS X and iOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Core Foundation Framework forwards notifications about socket activity through a callback function which called from the run loop. The default behavior of Core Foundation is to automatically re-enable the read callback after each notification, and we explicitly enabled the same behavior for the write callback. With this behavior, if the client did multiple recv() calls in response to the first notification in a series of read notifications, the client would still get the QSocketNotifier notifications for the data that was already read. To get rid of these extra notifications, we disable automatically re-enabling the callbacks, and then manually enable them on each run loop pass. Task-number: QTBUG-48556 Change-Id: I0b060222b787f45600be0cb7da85d04aef415e57 Reviewed-by: Tor Arne Vestbø --- .../cfsocketnotifier/qcfsocketnotifier.cpp | 129 +++++++++++++----- .../cfsocketnotifier/qcfsocketnotifier_p.h | 14 +- 2 files changed, 105 insertions(+), 38 deletions(-) diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp index 2b5723d827..c58e0ea78d 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp @@ -55,11 +55,15 @@ void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CF // notifier is now gone. The upshot is we have to check the notifier // every time. if (callbackType == kCFSocketReadCallBack) { - if (socketInfo->readNotifier) + if (socketInfo->readNotifier && socketInfo->readEnabled) { + socketInfo->readEnabled = false; QGuiApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent); + } } else if (callbackType == kCFSocketWriteCallBack) { - if (socketInfo->writeNotifier) + if (socketInfo->writeNotifier && socketInfo->writeEnabled) { + socketInfo->writeEnabled = false; QGuiApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent); + } } if (cfSocketNotifier->maybeCancelWaitForMoreEvents) @@ -88,12 +92,12 @@ void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSource CFRunLoopRemoveSource(CFRunLoopGetMain(), runloop, kCFRunLoopCommonModes); CFSocketDisableCallBacks(socket, kCFSocketReadCallBack); CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack); - CFRunLoopSourceInvalidate(runloop); } QCFSocketNotifier::QCFSocketNotifier() -:eventDispatcher(0) -, maybeCancelWaitForMoreEvents(0) + : eventDispatcher(0) + , maybeCancelWaitForMoreEvents(0) + , enableNotifiersObserver(0) { } @@ -150,36 +154,34 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) } CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket); - flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write - flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation + // QSocketNotifier doesn't close the socket upon destruction/invalidation + flags &= ~kCFSocketCloseOnInvalidate; + // Expicitly disable automatic re-enable, as we do that manually on each runloop pass + flags &= ~(kCFSocketAutomaticallyReenableWriteCallBack | kCFSocketAutomaticallyReenableReadCallBack); CFSocketSetSocketFlags(socketInfo->socket, flags); - // Add CFSocket to runloop. - if (!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) { - qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop"); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); - return; - } - - // Disable both callback types by default. This must be done after - // we add the CFSocket to the runloop, or else these calls will have - // no effect. - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); - macSockets.insert(nativeSocket, socketInfo); } - // Increment read/write counters and select enable callbacks if necessary. if (type == QSocketNotifier::Read) { Q_ASSERT(socketInfo->readNotifier == 0); socketInfo->readNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + socketInfo->readEnabled = false; } else if (type == QSocketNotifier::Write) { Q_ASSERT(socketInfo->writeNotifier == 0); socketInfo->writeNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + socketInfo->writeEnabled = false; + } + + if (!enableNotifiersObserver) { + // Create a run loop observer which enables the socket notifiers on each + // pass of the run loop, before any sources are processed. + CFRunLoopObserverContext context = {}; + context.info = this; + enableNotifiersObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeSources, + true, 0, enableSocketNotifiers, &context); + Q_ASSERT(enableNotifiersObserver); + CFRunLoopAddObserver(CFRunLoopGetMain(), enableNotifiersObserver, kCFRunLoopCommonModes); } } @@ -212,21 +214,18 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) if (type == QSocketNotifier::Read) { Q_ASSERT(notifier == socketInfo->readNotifier); socketInfo->readNotifier = 0; + socketInfo->readEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); } else if (type == QSocketNotifier::Write) { Q_ASSERT(notifier == socketInfo->writeNotifier); socketInfo->writeNotifier = 0; + socketInfo->writeEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); } // Remove CFSocket from runloop if this was the last QSocketNotifier. if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) { - if (CFSocketIsValid(socketInfo->socket)) - qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop); - CFRunLoopSourceInvalidate(socketInfo->runloop); - CFRelease(socketInfo->runloop); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); + unregisterSocketInfo(socketInfo); delete socketInfo; macSockets.remove(nativeSocket); } @@ -235,14 +234,70 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) void QCFSocketNotifier::removeSocketNotifiers() { // Remove CFSockets from the runloop. - for (MacSocketHash::ConstIterator it = macSockets.constBegin(); it != macSockets.constEnd(); ++it) { - MacSocketInfo *socketInfo = (*it); - if (CFSocketIsValid(socketInfo->socket)) { + foreach (MacSocketInfo *socketInfo, macSockets) { + unregisterSocketInfo(socketInfo); + delete socketInfo; + } + + macSockets.clear(); + + destroyRunLoopObserver(); +} + +void QCFSocketNotifier::destroyRunLoopObserver() +{ + if (!enableNotifiersObserver) + return; + + CFRunLoopObserverInvalidate(enableNotifiersObserver); + CFRelease(enableNotifiersObserver); + enableNotifiersObserver = 0; +} + +void QCFSocketNotifier::unregisterSocketInfo(MacSocketInfo *socketInfo) +{ + if (socketInfo->runloop) { + if (CFSocketIsValid(socketInfo->socket)) qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop); - CFRunLoopSourceInvalidate(socketInfo->runloop); - CFRelease(socketInfo->runloop); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); + CFRunLoopSourceInvalidate(socketInfo->runloop); + CFRelease(socketInfo->runloop); + } + CFSocketInvalidate(socketInfo->socket); + CFRelease(socketInfo->socket); +} + +void QCFSocketNotifier::enableSocketNotifiers(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info) +{ + Q_UNUSED(ref); + Q_UNUSED(activity); + + QCFSocketNotifier *that = static_cast(info); + + foreach (MacSocketInfo *socketInfo, that->macSockets) { + if (!CFSocketIsValid(socketInfo->socket)) + continue; + + if (!socketInfo->runloop) { + // Add CFSocket to runloop. + if (!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) { + qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop"); + CFSocketInvalidate(socketInfo->socket); + continue; + } + + if (!socketInfo->readNotifier) + CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + if (!socketInfo->writeNotifier) + CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + } + + if (socketInfo->readNotifier && !socketInfo->readEnabled) { + socketInfo->readEnabled = true; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + } + if (socketInfo->writeNotifier && !socketInfo->writeEnabled) { + socketInfo->writeEnabled = true; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); } } } diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h index af8122f753..9bccc1bf98 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h @@ -53,11 +53,14 @@ QT_BEGIN_NAMESPACE struct MacSocketInfo { - MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {} + MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0), + readEnabled(false), writeEnabled(false) {} CFSocketRef socket; CFRunLoopSourceRef runloop; QObject *readNotifier; QObject *writeNotifier; + bool readEnabled; + bool writeEnabled; }; typedef QHash MacSocketHash; @@ -83,9 +86,18 @@ public: void unregisterSocketNotifier(QSocketNotifier *notifier); void removeSocketNotifiers(); +private: + void destroyRunLoopObserver(); + + static void unregisterSocketInfo(MacSocketInfo *socketInfo); + static void enableSocketNotifiers(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info); + MacSocketHash macSockets; QAbstractEventDispatcher *eventDispatcher; MaybeCancelWaitForMoreEventsFn maybeCancelWaitForMoreEvents; + CFRunLoopObserverRef enableNotifiersObserver; + + friend void qt_mac_socket_callback(CFSocketRef, CFSocketCallBackType, CFDataRef, const void *, void *); }; QT_END_NAMESPACE From 9ff1310af51814e521572fa3de4e086907633a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 2 Oct 2015 13:54:33 +0200 Subject: [PATCH 206/240] Distinguish between Objective-C and Objective-C++ sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of lumping both Objective-C (.m) and Objective-C++ (.mm) sources into the same pile, passing them on to the same compiler as for C++ (CXX), with the C++ flags (CXXFLAGS), we follow Apple's lead and treat them as variants of the C and C++ languages separately, so that Objective-C sources are built with CC and with CFLAGS, and Objective-C++ sources with CXX, and CXXFLAGS. This lets us remove a lot of duplicated flags and definitions from the QMAKE_OBJECTIVE_CFLAGS variable, which in 99% of the cases just matched the C++ equivalent. The remaining Objective-C/C++ flags are added to CFLAGS/CXXFLAGS, as the compiler will just ignore them when running in C/C++ mode. This matches Xcode, which also doesn't have a separate build setting for Objective-C/C++ flags. The Makefile qmake generator has been rewritten to support Objective-C/C++ fully, by not assuming that we're just iterating over the C and C++ extensions when dealing with compilation rules, precompiled headers, etc. There's some duplicated logic in this code, as inherent by qmake's already duplicated code paths, but this can be cleaned up when C++11 support is mandatory and we can use lambda functions. Task-number: QTBUG-36575 Change-Id: I4f06576d5f49e939333a2e03d965da54119e5e31 Reviewed-by: Tor Arne Vestbø --- configure | 3 +- mkspecs/common/clang-mac.conf | 1 - mkspecs/common/gcc-base-mac.conf | 8 -- mkspecs/common/ios/clang.conf | 2 +- mkspecs/features/default_post.prf | 4 - mkspecs/features/gcov.prf | 1 - mkspecs/features/mac/objective_c.prf | 27 +--- mkspecs/features/mac/sdk.prf | 2 - mkspecs/features/spec_pre.prf | 2 + mkspecs/features/unix/hide_symbols.prf | 1 - mkspecs/features/warn_off.prf | 1 - mkspecs/features/warn_on.prf | 1 - mkspecs/macx-clang-32/qmake.conf | 1 - mkspecs/macx-g++-32/qmake.conf | 1 - mkspecs/macx-icc/qmake.conf | 8 -- .../macx-ios-clang/features/default_post.prf | 1 - qmake/generators/mac/pbuilder_pbx.cpp | 32 +++-- qmake/generators/makefile.cpp | 31 ++++- qmake/generators/unix/unixmake.cpp | 122 ++++++++---------- qmake/generators/unix/unixmake2.cpp | 54 ++++---- qmake/option.cpp | 4 + qmake/option.h | 2 + src/testlib/testlib.pro | 2 +- 23 files changed, 138 insertions(+), 173 deletions(-) diff --git a/configure b/configure index 3bcf2dde4f..80ed12cdbe 100755 --- a/configure +++ b/configure @@ -318,7 +318,7 @@ macSDKify() val=$(echo $sdk_val $(echo $val | cut -s -d ' ' -f 2-)) echo "$var=$val" ;; - QMAKE_CFLAGS=*|QMAKE_CXXFLAGS=*|QMAKE_OBJECTIVE_CFLAGS=*) + QMAKE_CFLAGS=*|QMAKE_CXXFLAGS=*) echo "$line -isysroot $sysroot $version_min_flag" ;; QMAKE_LFLAGS=*) @@ -6413,7 +6413,6 @@ if [ '!' -z "$W_FLAGS" ]; then # add the user defined warning flags QMakeVar add QMAKE_CFLAGS_WARN_ON "$W_FLAGS" QMakeVar add QMAKE_CXXFLAGS_WARN_ON "$W_FLAGS" - QMakeVar add QMAKE_OBJECTIVE_CFLAGS_WARN_ON "$W_FLAGS" fi if [ "$XPLATFORM_MINGW" = "yes" ]; then diff --git a/mkspecs/common/clang-mac.conf b/mkspecs/common/clang-mac.conf index d95e982b14..c616e20b6e 100644 --- a/mkspecs/common/clang-mac.conf +++ b/mkspecs/common/clang-mac.conf @@ -7,5 +7,4 @@ QMAKE_OBJCXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE QMAKE_XCODE_GCC_VERSION = com.apple.compilers.llvm.clang.1_0 QMAKE_CXXFLAGS += -stdlib=libc++ -QMAKE_OBJECTIVE_CFLAGS += -stdlib=libc++ QMAKE_LFLAGS += -stdlib=libc++ diff --git a/mkspecs/common/gcc-base-mac.conf b/mkspecs/common/gcc-base-mac.conf index 747f09ae81..e9bf780ec1 100644 --- a/mkspecs/common/gcc-base-mac.conf +++ b/mkspecs/common/gcc-base-mac.conf @@ -12,14 +12,6 @@ include(gcc-base.conf) QMAKE_COMPILER_DEFINES += __APPLE__ __GNUC__=4 __APPLE_CC__ -QMAKE_OBJECTIVE_CFLAGS = $$QMAKE_CFLAGS -QMAKE_OBJECTIVE_CFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -QMAKE_OBJECTIVE_CFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF -QMAKE_OBJECTIVE_CFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG -QMAKE_OBJECTIVE_CFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE -QMAKE_OBJECTIVE_CFLAGS_RELEASE_WITH_DEBUGINFO = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO -QMAKE_OBJECTIVE_CFLAGS_HIDESYMS = $$QMAKE_CXXFLAGS_HIDESYMS - QMAKE_LFLAGS += -headerpad_max_install_names QMAKE_LFLAGS_SHLIB += -single_module -dynamiclib diff --git a/mkspecs/common/ios/clang.conf b/mkspecs/common/ios/clang.conf index 36cb655229..f45b89665f 100644 --- a/mkspecs/common/ios/clang.conf +++ b/mkspecs/common/ios/clang.conf @@ -22,7 +22,7 @@ QMAKE_IOS_OBJ_CFLAGS += -Wno-deprecated-implementations -Wprotocol -Wno-select # Set build flags QMAKE_CFLAGS += $$QMAKE_IOS_CFLAGS QMAKE_CXXFLAGS += $$QMAKE_IOS_CFLAGS $$QMAKE_IOS_CXXFLAGS -QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_IOS_CFLAGS $$QMAKE_IOS_CXXFLAGS $$QMAKE_IOS_OBJ_CFLAGS +QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_IOS_OBJ_CFLAGS QMAKE_IOS_CFLAGS = QMAKE_IOS_CXXFLAGS = diff --git a/mkspecs/features/default_post.prf b/mkspecs/features/default_post.prf index ebe83af25e..cd8d8859aa 100644 --- a/mkspecs/features/default_post.prf +++ b/mkspecs/features/default_post.prf @@ -35,7 +35,6 @@ force_debug_info|debug: \ force_debug_info { QMAKE_CFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO - QMAKE_OBJECTIVE_CFLAGS_RELEASE = $$QMAKE_OBJECTIVE_CFLAGS_RELEASE_WITH_DEBUGINFO QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO } @@ -51,13 +50,11 @@ optimize_full { debug { QMAKE_CFLAGS += $$QMAKE_CFLAGS_DEBUG QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_DEBUG - QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_OBJECTIVE_CFLAGS_DEBUG QMAKE_LFLAGS += $$QMAKE_LFLAGS_DEBUG QMAKE_LIBFLAGS += $$QMAKE_LIBFLAGS_DEBUG } else { QMAKE_CFLAGS += $$QMAKE_CFLAGS_RELEASE QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_RELEASE - QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_OBJECTIVE_CFLAGS_RELEASE QMAKE_LFLAGS += $$QMAKE_LFLAGS_RELEASE QMAKE_LIBFLAGS += $$QMAKE_LIBFLAGS_RELEASE } @@ -107,7 +104,6 @@ c++11|c++14|c++1z { !strict_c++:!isEmpty(QMAKE_CXXFLAGS_GNU$$cxxstd): cxxstd = GNU$$cxxstd QMAKE_CXXFLAGS += $$eval(QMAKE_CXXFLAGS_$$cxxstd) - QMAKE_OBJECTIVE_CFLAGS += $$eval(QMAKE_CXXFLAGS_$$cxxstd) QMAKE_LFLAGS += $$eval(QMAKE_LFLAGS_$$cxxstd) unset(cxxstd) diff --git a/mkspecs/features/gcov.prf b/mkspecs/features/gcov.prf index 330831fc0e..f45ba4c520 100644 --- a/mkspecs/features/gcov.prf +++ b/mkspecs/features/gcov.prf @@ -25,7 +25,6 @@ QMAKE_CFLAGS += -fprofile-arcs -ftest-coverage QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -QMAKE_OBJECTIVE_CFLAGS += -fprofile-arcs -ftest-coverage QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage QMAKE_CLEAN += $(OBJECTS_DIR)*.gcno and $(OBJECTS_DIR)*.gcda diff --git a/mkspecs/features/mac/objective_c.prf b/mkspecs/features/mac/objective_c.prf index 0f25f41eec..b3b1d4be99 100644 --- a/mkspecs/features/mac/objective_c.prf +++ b/mkspecs/features/mac/objective_c.prf @@ -1,23 +1,10 @@ -for(source, SOURCES) { - contains(source,.*\\.mm?$) { - warning(Objective-C source \'$$source\' found in SOURCES but should be in OBJECTIVE_SOURCES) - SOURCES -= $$source - OBJECTIVE_SOURCES += $$source - } -} +# Objective-C/C++ sources go in SOURCES, like all other sources +SOURCES += $$OBJECTIVE_SOURCES -isEmpty(QMAKE_OBJECTIVE_CC):QMAKE_OBJECTIVE_CC = $$QMAKE_CC +# Strip C/C++ flags from QMAKE_OBJECTIVE_CFLAGS just in case +QMAKE_OBJECTIVE_CFLAGS -= $$QMAKE_CFLAGS $$QMAKE_CXXFLAGS -OBJECTIVE_C_OBJECTS_DIR = $$OBJECTS_DIR -isEmpty(OBJECTIVE_C_OBJECTS_DIR):OBJECTIVE_C_OBJECTS_DIR = . -isEmpty(QMAKE_EXT_OBJECTIVE_C):QMAKE_EXT_OBJECTIVE_C = .mm .m - -objective_c.dependency_type = TYPE_C -objective_c.variables = QMAKE_OBJECTIVE_CFLAGS -objective_c.commands = $$QMAKE_OBJECTIVE_CC -c $(QMAKE_COMP_QMAKE_OBJECTIVE_CFLAGS) $(DEFINES) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} -objective_c.output = $$OBJECTIVE_C_OBJECTS_DIR/${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} -objective_c.input = OBJECTIVE_SOURCES -objective_c.name = Compile ${QMAKE_FILE_IN} -silent:objective_c.commands = @echo objective-c ${QMAKE_FILE_IN} && $$objective_c.commands -QMAKE_EXTRA_COMPILERS += objective_c +# Add Objective-C/C++ flags to C/C++ flags, the compiler can handle it +QMAKE_CFLAGS += $$QMAKE_OBJECTIVE_CFLAGS +QMAKE_CXXFLAGS += $$QMAKE_OBJECTIVE_CFLAGS diff --git a/mkspecs/features/mac/sdk.prf b/mkspecs/features/mac/sdk.prf index a5643e311d..210843bd94 100644 --- a/mkspecs/features/mac/sdk.prf +++ b/mkspecs/features/mac/sdk.prf @@ -32,7 +32,6 @@ isEmpty(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.version) { !equals(MAKEFILE_GENERATOR, XCODE) { QMAKE_CFLAGS += -isysroot $$QMAKE_MAC_SDK_PATH QMAKE_CXXFLAGS += -isysroot $$QMAKE_MAC_SDK_PATH - QMAKE_OBJECTIVE_CFLAGS += -isysroot $$QMAKE_MAC_SDK_PATH QMAKE_LFLAGS += -Wl,-syslibroot,$$QMAKE_MAC_SDK_PATH } @@ -80,6 +79,5 @@ isEmpty(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.platform_name) { version_min_flag = -m$${version_identifier}-version-min=$$deployment_target QMAKE_CFLAGS += $$version_min_flag QMAKE_CXXFLAGS += $$version_min_flag - QMAKE_OBJECTIVE_CFLAGS += $$version_min_flag QMAKE_LFLAGS += $$version_min_flag } diff --git a/mkspecs/features/spec_pre.prf b/mkspecs/features/spec_pre.prf index cdc1d7ee1e..ff310d9793 100644 --- a/mkspecs/features/spec_pre.prf +++ b/mkspecs/features/spec_pre.prf @@ -7,6 +7,8 @@ QMAKE_DIRLIST_SEP = $$DIRLIST_SEPARATOR QMAKE_EXT_C = .c QMAKE_EXT_CPP = .cpp .cc .cxx +QMAKE_EXT_OBJC = .m +QMAKE_EXT_OBJCXX = .mm QMAKE_EXT_CPP_MOC = .moc QMAKE_EXT_H = .h .hpp .hh .hxx QMAKE_EXT_H_MOC = .cpp diff --git a/mkspecs/features/unix/hide_symbols.prf b/mkspecs/features/unix/hide_symbols.prf index 4af99c2eac..f4d3921cb1 100644 --- a/mkspecs/features/unix/hide_symbols.prf +++ b/mkspecs/features/unix/hide_symbols.prf @@ -1,4 +1,3 @@ QMAKE_CFLAGS += $$QMAKE_CFLAGS_HIDESYMS QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_HIDESYMS -QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_OBJECTIVE_CFLAGS_HIDESYMS QMAKE_LFLAGS += $$QMAKE_LFLAGS_HIDESYMS diff --git a/mkspecs/features/warn_off.prf b/mkspecs/features/warn_off.prf index e37979c035..072a7aca15 100644 --- a/mkspecs/features/warn_off.prf +++ b/mkspecs/features/warn_off.prf @@ -1,4 +1,3 @@ CONFIG -= warn_on QMAKE_CFLAGS += $$QMAKE_CFLAGS_WARN_OFF QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_WARN_OFF -QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_OBJECTIVE_CFLAGS_WARN_OFF \ No newline at end of file diff --git a/mkspecs/features/warn_on.prf b/mkspecs/features/warn_on.prf index 7e78a8e0d3..03a4a24a61 100644 --- a/mkspecs/features/warn_on.prf +++ b/mkspecs/features/warn_on.prf @@ -1,5 +1,4 @@ CONFIG -= warn_off QMAKE_CFLAGS += $$QMAKE_CFLAGS_WARN_ON QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_WARN_ON -QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_OBJECTIVE_CFLAGS_WARN_ON diff --git a/mkspecs/macx-clang-32/qmake.conf b/mkspecs/macx-clang-32/qmake.conf index 87c601ee74..ec33c02e93 100644 --- a/mkspecs/macx-clang-32/qmake.conf +++ b/mkspecs/macx-clang-32/qmake.conf @@ -14,7 +14,6 @@ include(../common/clang-mac.conf) QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 QMAKE_CFLAGS += -arch i386 -QMAKE_OBJECTIVE_CFLAGS += -arch i386 QMAKE_CXXFLAGS += -arch i386 QMAKE_LFLAGS += -arch i386 diff --git a/mkspecs/macx-g++-32/qmake.conf b/mkspecs/macx-g++-32/qmake.conf index 2a8197ebbd..af6fe5689e 100644 --- a/mkspecs/macx-g++-32/qmake.conf +++ b/mkspecs/macx-g++-32/qmake.conf @@ -17,7 +17,6 @@ include(../common/g++-macx.conf) QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 QMAKE_CFLAGS += -arch i386 -QMAKE_OBJECTIVE_CFLAGS += -arch i386 QMAKE_CXXFLAGS += -arch i386 QMAKE_LFLAGS += -arch i386 diff --git a/mkspecs/macx-icc/qmake.conf b/mkspecs/macx-icc/qmake.conf index efce568ea9..70ea5ee80f 100644 --- a/mkspecs/macx-icc/qmake.conf +++ b/mkspecs/macx-icc/qmake.conf @@ -34,14 +34,6 @@ QMAKE_CFLAGS_SSE4_2 += -msse4.2 QMAKE_CFLAGS_AVX += -mavx QMAKE_CFLAGS_AVX2 += -march=core-avx2 -QMAKE_OBJECTIVE_CC = clang -QMAKE_OBJECTIVE_CFLAGS = -pipe -QMAKE_OBJECTIVE_CFLAGS_WARN_ON = -Wall -W -QMAKE_OBJECTIVE_CFLAGS_WARN_OFF = -w -QMAKE_OBJECTIVE_CFLAGS_RELEASE = -Os -QMAKE_OBJECTIVE_CFLAGS_DEBUG = -g -QMAKE_OBJECTIVE_CFLAGS_HIDESYMS = -fvisibility=hidden - QMAKE_CXX = icpc QMAKE_CXXFLAGS = $$QMAKE_CFLAGS QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS diff --git a/mkspecs/macx-ios-clang/features/default_post.prf b/mkspecs/macx-ios-clang/features/default_post.prf index 5266c88f16..40e7a893de 100644 --- a/mkspecs/macx-ios-clang/features/default_post.prf +++ b/mkspecs/macx-ios-clang/features/default_post.prf @@ -93,6 +93,5 @@ macx-xcode { QMAKE_CFLAGS += $$arch_flags QMAKE_CXXFLAGS += $$arch_flags - QMAKE_OBJECTIVE_CFLAGS += $$arch_flags QMAKE_LFLAGS += $$arch_flags } diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 219415ffdc..ccb3cfe810 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -417,20 +417,24 @@ public: inline QString groupName() const { return group; } inline QString compilerName() const { return compiler; } inline bool isObjectOutput(const QString &file) const { - bool ret = object_output; - for(int i = 0; !ret && i < Option::c_ext.size(); ++i) { - if(file.endsWith(Option::c_ext.at(i))) { - ret = true; - break; - } + if (object_output) + return true; + + if (file.endsWith(Option::objc_ext)) + return true; + if (file.endsWith(Option::objcpp_ext)) + return true; + + for (int i = 0; i < Option::c_ext.size(); ++i) { + if (file.endsWith(Option::c_ext.at(i))) + return true; } - for(int i = 0; !ret && i < Option::cpp_ext.size(); ++i) { - if(file.endsWith(Option::cpp_ext.at(i))) { - ret = true; - break; - } + for (int i = 0; i < Option::cpp_ext.size(); ++i) { + if (file.endsWith(Option::cpp_ext.at(i))) + return true; } - return ret; + + return false; } }; @@ -490,9 +494,9 @@ static QString xcodeFiletypeForFilename(const QString &filename) return "sourcecode.c.h"; } - if (filename.endsWith(QStringLiteral(".mm"))) + if (filename.endsWith(Option::objcpp_ext)) return QStringLiteral("sourcecode.cpp.objcpp"); - if (filename.endsWith(QStringLiteral(".m"))) + if (filename.endsWith(Option::objc_ext)) return QStringLiteral("sourcecode.c.objc"); if (filename.endsWith(QStringLiteral(".framework"))) return QStringLiteral("wrapper.framework"); diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index c991a57c9d..6f844a5c4d 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -378,6 +378,13 @@ MakefileGenerator::init() ProValueMap &v = project->variables(); + v["QMAKE_BUILTIN_COMPILERS"] = ProStringList() << "C" << "CXX"; + + v["QMAKE_LANGUAGE_C"] = ProString("c"); + v["QMAKE_LANGUAGE_CXX"] = ProString("c++"); + v["QMAKE_LANGUAGE_OBJC"] = ProString("objective-c"); + v["QMAKE_LANGUAGE_OBJCXX"] = ProString("objective-c++"); + if (v["TARGET"].isEmpty()) warn_msg(WarnLogic, "TARGET is empty"); @@ -1136,12 +1143,28 @@ MakefileGenerator::writeObj(QTextStream &t, const char *src) << " " << escapeDependencyPaths(findDependencies(srcf)).join(" \\\n\t\t"); ProKey comp; - for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) { - if((*sit).endsWith((*cppit))) { - comp = "QMAKE_RUN_CXX"; - break; + foreach (const ProString &compiler, project->values("QMAKE_BUILTIN_COMPILERS")) { + // Unfortunately we were not consistent about the C++ naming + ProString extensionSuffix = compiler; + if (extensionSuffix == "CXX") + extensionSuffix = ProString("CPP"); + + // Nor the C naming + ProString compilerSuffix = compiler; + if (compilerSuffix == "C") + compilerSuffix = ProString("CC"); + + foreach (const ProString &extension, project->values(ProKey("QMAKE_EXT_" + extensionSuffix))) { + if ((*sit).endsWith(extension)) { + comp = ProKey("QMAKE_RUN_" + compilerSuffix); + break; + } } + + if (!comp.isNull()) + break; } + if (comp.isEmpty()) comp = "QMAKE_RUN_CC"; if (!project->isEmpty(comp)) { diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index b44d7f032a..1d9ebb35e3 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -145,14 +145,16 @@ UnixMakefileGenerator::init() MakefileGenerator::init(); - QString comps[] = { "C", "CXX", "OBJC", "OBJCXX", QString() }; - for(int i = 0; !comps[i].isNull(); i++) { + if (project->isActiveConfig("objective_c")) + project->values("QMAKE_BUILTIN_COMPILERS") << "OBJC" << "OBJCXX"; + + foreach (const ProString &compiler, project->values("QMAKE_BUILTIN_COMPILERS")) { QString compile_flag = var("QMAKE_COMPILE_FLAG"); if(compile_flag.isEmpty()) compile_flag = "-c"; if(doPrecompiledHeaders() && !project->isEmpty("PRECOMPILED_HEADER")) { - QString pchFlags = var(ProKey("QMAKE_" + comps[i] + "FLAGS_USE_PRECOMPILE")); + QString pchFlags = var(ProKey("QMAKE_" + compiler + "FLAGS_USE_PRECOMPILE")); QString pchBaseName; if(!project->isEmpty("PRECOMPILED_DIR")) { @@ -179,22 +181,11 @@ UnixMakefileGenerator::init() pchBaseName += project->first("QMAKE_PCH_OUTPUT_EXT").toQString(); pchBaseName += Option::dir_sep; - QString pchOutputFile; - if(comps[i] == "C") { - pchOutputFile = "c"; - } else if(comps[i] == "CXX") { - pchOutputFile = "c++"; - } else if(project->isActiveConfig("objective_c")) { - if(comps[i] == "OBJC") - pchOutputFile = "objective-c"; - else if(comps[i] == "OBJCXX") - pchOutputFile = "objective-c++"; - } - - if(!pchOutputFile.isEmpty()) { + ProString language = project->first(ProKey("QMAKE_LANGUAGE_" + compiler)); + if (!language.isEmpty()) { pchFlags.replace("${QMAKE_PCH_OUTPUT}", - escapeFilePath(pchBaseName + pchOutputFile + headerSuffix)); + escapeFilePath(pchBaseName + language + headerSuffix)); } } @@ -202,23 +193,27 @@ UnixMakefileGenerator::init() compile_flag += " " + pchFlags; } - QString cflags; - if(comps[i] == "OBJC" || comps[i] == "OBJCXX") - cflags += " $(CFLAGS)"; - else - cflags += " $(" + comps[i] + "FLAGS)"; - compile_flag += cflags + " $(INCPATH)"; + QString compilerExecutable; + if (compiler == "C" || compiler == "OBJC") { + compilerExecutable = "$(CC)"; + compile_flag += " $(CFLAGS)"; + } else { + compilerExecutable = "$(CXX)"; + compile_flag += " $(CXXFLAGS)"; + } - QString compiler = comps[i]; - if (compiler == "C") - compiler = "CC"; + compile_flag += " $(INCPATH)"; - const ProKey runComp("QMAKE_RUN_" + compiler); + ProString compilerVariable = compiler; + if (compilerVariable == "C") + compilerVariable = ProString("CC"); + + const ProKey runComp("QMAKE_RUN_" + compilerVariable); if(project->isEmpty(runComp)) - project->values(runComp).append("$(" + compiler + ") " + compile_flag + " " + var("QMAKE_CC_O_FLAG") + "$obj $src"); - const ProKey runCompImp("QMAKE_RUN_" + compiler + "_IMP"); + project->values(runComp).append(compilerExecutable + " " + compile_flag + " " + var("QMAKE_CC_O_FLAG") + "$obj $src"); + const ProKey runCompImp("QMAKE_RUN_" + compilerVariable + "_IMP"); if(project->isEmpty(runCompImp)) - project->values(runCompImp).append("$(" + compiler + ") " + compile_flag + " " + var("QMAKE_CC_O_FLAG") + "\"$@\" \"$<\""); + project->values(runCompImp).append(compilerExecutable + " " + compile_flag + " " + var("QMAKE_CC_O_FLAG") + "\"$@\" \"$<\""); } if (project->isActiveConfig("mac") && !project->isEmpty("TARGET") && @@ -306,10 +301,11 @@ UnixMakefileGenerator::init() } QStringList -&UnixMakefileGenerator::findDependencies(const QString &file) +&UnixMakefileGenerator::findDependencies(const QString &f) { - QStringList &ret = MakefileGenerator::findDependencies(file); + QStringList &ret = MakefileGenerator::findDependencies(f); if (doPrecompiledHeaders() && !project->isEmpty("PRECOMPILED_HEADER")) { + ProString file = f; QString header_prefix; if(!project->isEmpty("PRECOMPILED_DIR")) header_prefix = project->first("PRECOMPILED_DIR").toQString(); @@ -329,45 +325,33 @@ QStringList QString header_suffix = project->isActiveConfig("clang_pch_style") ? project->first("QMAKE_PCH_OUTPUT_EXT").toQString() : ""; header_prefix += Option::dir_sep + project->first("QMAKE_PRECOMP_PREFIX"); - for(QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) { - if(file.endsWith(*it)) { - if(!project->isEmpty("QMAKE_CFLAGS_PRECOMPILE")) { - QString precomp_c_h = header_prefix + "c" + header_suffix; - if(!ret.contains(precomp_c_h)) - ret += precomp_c_h; - } - if(project->isActiveConfig("objective_c")) { - if(!project->isEmpty("QMAKE_OBJCFLAGS_PRECOMPILE")) { - QString precomp_objc_h = header_prefix + "objective-c" + header_suffix; - if(!ret.contains(precomp_objc_h)) - ret += precomp_objc_h; - } - if(!project->isEmpty("QMAKE_OBJCXXFLAGS_PRECOMPILE")) { - QString precomp_objcpp_h = header_prefix + "objective-c++" + header_suffix; - if(!ret.contains(precomp_objcpp_h)) - ret += precomp_objcpp_h; - } - } - break; - } - } - for(QStringList::Iterator it = Option::cpp_ext.begin(); it != Option::cpp_ext.end(); ++it) { - if(file.endsWith(*it)) { - if(!project->isEmpty("QMAKE_CXXFLAGS_PRECOMPILE")) { - QString precomp_cpp_h = header_prefix + "c++" + header_suffix; - if(!ret.contains(precomp_cpp_h)) - ret += precomp_cpp_h; - } - if(project->isActiveConfig("objective_c")) { - if(!project->isEmpty("QMAKE_OBJCXXFLAGS_PRECOMPILE")) { - QString precomp_objcpp_h = header_prefix + "objective-c++" + header_suffix; - if(!ret.contains(precomp_objcpp_h)) - ret += precomp_objcpp_h; - } - } - break; + + foreach (const ProString &compiler, project->values("QMAKE_BUILTIN_COMPILERS")) { + if (project->isEmpty(ProKey("QMAKE_" + compiler + "FLAGS_PRECOMPILE"))) + continue; + + ProString language = project->first(ProKey("QMAKE_LANGUAGE_" + compiler)); + if (language.isEmpty()) + continue; + + // Unfortunately we were not consistent about the C++ naming + ProString extensionSuffix = compiler; + if (extensionSuffix == "CXX") + extensionSuffix = ProString("CPP"); + + foreach (const ProString &extension, project->values(ProKey("QMAKE_EXT_" + extensionSuffix))) { + if (!file.endsWith(extension.toQString())) + continue; + + QString precompiledHeader = header_prefix + language + header_suffix; + if (!ret.contains(precompiledHeader)) + ret += precompiledHeader; + + goto foundPrecompiledDependency; } } + foundPrecompiledDependency: + ; // Hurray!! } } return ret; diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index cd4339edec..10b31def39 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -1001,15 +1001,14 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) ProString header_suffix = project->isActiveConfig("clang_pch_style") ? project->first("QMAKE_PCH_OUTPUT_EXT") : ""; - if(!project->isEmpty("QMAKE_CFLAGS_PRECOMPILE")) - precomp_files += precomph_out_dir + header_prefix + "c" + header_suffix; - if(!project->isEmpty("QMAKE_CXXFLAGS_PRECOMPILE")) - precomp_files += precomph_out_dir + header_prefix + "c++" + header_suffix; - if(project->isActiveConfig("objective_c")) { - if(!project->isEmpty("QMAKE_OBJCFLAGS_PRECOMPILE")) - precomp_files += precomph_out_dir + header_prefix + "objective-c" + header_suffix; - if(!project->isEmpty("QMAKE_OBJCXXFLAGS_PRECOMPILE")) - precomp_files += precomph_out_dir + header_prefix + "objective-c++" + header_suffix; + foreach (const ProString &compiler, project->values("QMAKE_BUILTIN_COMPILERS")) { + if (project->isEmpty(ProKey("QMAKE_" + compiler + "FLAGS_PRECOMPILE"))) + continue; + ProString language = project->first(ProKey("QMAKE_LANGUAGE_" + compiler)); + if (language.isEmpty()) + continue; + + precomp_files += precomph_out_dir + header_prefix + language + header_suffix; } } t << "-$(DEL_FILE) " << escapeFilePaths(precomp_files).join(' ') << "\n\t"; @@ -1064,17 +1063,16 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(doPrecompiledHeaders() && !project->isEmpty("PRECOMPILED_HEADER")) { QString pchInput = project->first("PRECOMPILED_HEADER").toQString(); t << "###### Precompiled headers\n"; - QString comps[] = { "C", "CXX", "OBJC", "OBJCXX", QString() }; - for(int i = 0; !comps[i].isNull(); i++) { - QString pchFlags = var(ProKey("QMAKE_" + comps[i] + "FLAGS_PRECOMPILE")); + foreach (const ProString &compiler, project->values("QMAKE_BUILTIN_COMPILERS")) { + QString pchFlags = var(ProKey("QMAKE_" + compiler + "FLAGS_PRECOMPILE")); if(pchFlags.isEmpty()) continue; QString cflags; - if(comps[i] == "OBJC" || comps[i] == "OBJCXX") + if (compiler == "C" || compiler == "OBJC") cflags += " $(CFLAGS)"; else - cflags += " $(" + comps[i] + "FLAGS)"; + cflags += " $(CXXFLAGS)"; ProString pchBaseName = project->first("QMAKE_ORIG_TARGET"); ProString pchOutput; @@ -1102,21 +1100,13 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) ProString header_suffix = project->isActiveConfig("clang_pch_style") ? project->first("QMAKE_PCH_OUTPUT_EXT") : ""; pchOutput += Option::dir_sep; - QString pchOutputDir = pchOutput.toQString(), pchOutputFile; + QString pchOutputDir = pchOutput.toQString(); - if(comps[i] == "C") { - pchOutputFile = "c"; - } else if(comps[i] == "CXX") { - pchOutputFile = "c++"; - } else if(project->isActiveConfig("objective_c")) { - if(comps[i] == "OBJC") - pchOutputFile = "objective-c"; - else if(comps[i] == "OBJCXX") - pchOutputFile = "objective-c++"; - } - if(pchOutputFile.isEmpty()) + QString language = project->first(ProKey("QMAKE_LANGUAGE_" + compiler)).toQString(); + if (language.isEmpty()) continue; - pchOutput += header_prefix + pchOutputFile + header_suffix; + + pchOutput += header_prefix + language + header_suffix; t << escapeDependencyPath(pchOutput) << ": " << escapeDependencyPath(pchInput) << ' ' << escapeDependencyPaths(findDependencies(pchInput)).join(" \\\n\t\t") @@ -1126,14 +1116,14 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) .replace("${QMAKE_PCH_OUTPUT_BASE}", escapeFilePath(pchBaseName.toQString())) .replace("${QMAKE_PCH_OUTPUT}", escapeFilePath(pchOutput.toQString())); - QString compiler; - if(comps[i] == "C" || comps[i] == "OBJC" || comps[i] == "OBJCXX") - compiler = "$(CC)"; + QString compilerExecutable; + if (compiler == "C" || compiler == "OBJC") + compilerExecutable = "$(CC)"; else - compiler = "$(CXX)"; + compilerExecutable = "$(CXX)"; // compile command - t << "\n\t" << compiler << cflags << " $(INCPATH) " << pchFlags << endl << endl; + t << "\n\t" << compilerExecutable << cflags << " $(INCPATH) " << pchFlags << endl << endl; } } diff --git a/qmake/option.cpp b/qmake/option.cpp index 4d20f64d58..da59616e5c 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -59,6 +59,8 @@ QStringList Option::h_ext; QString Option::cpp_moc_ext; QStringList Option::cpp_ext; QStringList Option::c_ext; +QString Option::objc_ext; +QString Option::objcpp_ext; QString Option::obj_ext; QString Option::lex_ext; QString Option::yacc_ext; @@ -465,6 +467,8 @@ bool Option::postProcessProject(QMakeProject *project) Option::cpp_ext = project->values("QMAKE_EXT_CPP").toQStringList(); Option::h_ext = project->values("QMAKE_EXT_H").toQStringList(); Option::c_ext = project->values("QMAKE_EXT_C").toQStringList(); + Option::objc_ext = project->first("QMAKE_EXT_OBJC").toQString(); + Option::objcpp_ext = project->first("QMAKE_EXT_OBJCXX").toQString(); Option::res_ext = project->first("QMAKE_EXT_RES").toQString(); Option::pkgcfg_ext = project->first("QMAKE_EXT_PKGCONFIG").toQString(); Option::libtool_ext = project->first("QMAKE_EXT_LIBTOOL").toQString(); diff --git a/qmake/option.h b/qmake/option.h index 0ab0365bb3..663f096072 100644 --- a/qmake/option.h +++ b/qmake/option.h @@ -91,6 +91,8 @@ struct Option static QStringList h_ext; static QStringList cpp_ext; static QStringList c_ext; + static QString objc_ext; + static QString objcpp_ext; static QString cpp_moc_ext; static QString obj_ext; static QString lex_ext; diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro index 0070cdb271..ff4379f85d 100644 --- a/src/testlib/testlib.pro +++ b/src/testlib/testlib.pro @@ -92,7 +92,7 @@ mac { # don't know yet if the target that links to testlib will build under Xcode or not. # The corresponding flags for the target lives in xctest.prf, where we do know. QMAKE_LFLAGS += -F$${platform_dev_frameworks_path} -weak_framework XCTest - QMAKE_OBJECTIVE_CFLAGS += -F$${platform_dev_frameworks_path} + QMAKE_CXXFLAGS += -F$${platform_dev_frameworks_path} MODULE_CONFIG += xctest } } From db2c89beae6235520dd6a375001abf107b229e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 2 Oct 2015 16:44:10 +0200 Subject: [PATCH 207/240] Stop generating implicit suffix rules in Makefiles Suffix rules are the old-fashioned way of defining implicit rules for make. We don't need them as we generate explicit rules for all sources we build. [ChangeLog][qmake] Makefile output no longer contains implicit suffix rules, as all sources are built using explicit rules. Change-Id: I4ecfa5b80c8ae33aea8730836f3baf99dd4951dd Task-number: QTBUG-30813 Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake2.cpp | 11 ----------- qmake/generators/win32/msvc_nmake.cpp | 2 ++ qmake/generators/win32/winmakefile.cpp | 11 ----------- 3 files changed, 2 insertions(+), 22 deletions(-) diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 10b31def39..d0cd5d2354 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -298,17 +298,6 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) /* rules */ t << "first:" << (!project->isActiveConfig("no_default_goal_deps") ? " all" : "") << "\n"; - t << "####### Implicit rules\n\n"; - t << ".SUFFIXES: " << Option::obj_ext; - for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit) - t << " " << (*cit); - for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) - t << " " << (*cppit); - t << endl << endl; - for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) - t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; - for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit) - t << (*cit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; if(include_deps) { if (project->isActiveConfig("gcc_MD_depends")) { diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 31a9c53c90..a546e03b59 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -448,6 +448,8 @@ QStringList NmakeMakefileGenerator::sourceFilesForImplicitRulesFilter() void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t) { + t << "####### Implicit rules\n\n"; + t << ".SUFFIXES:"; for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit) t << " " << (*cit); diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index e6bf3388fa..1fba7057ab 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -570,7 +570,6 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) t << "DESTDIR_TARGET = " << fileVar("DEST_TARGET") << endl; t << endl; - t << "####### Implicit rules\n\n"; writeImplicitRulesPart(t); t << "####### Build rules\n\n"; @@ -642,16 +641,6 @@ void Win32MakefileGenerator::writeObjectsPart(QTextStream &t) void Win32MakefileGenerator::writeImplicitRulesPart(QTextStream &t) { - t << ".SUFFIXES:"; - for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) - t << " " << (*cppit); - for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit) - t << " " << (*cit); - t << endl << endl; - for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) - t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; - for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit) - t << (*cit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; } void Win32MakefileGenerator::writeBuildRulesPart(QTextStream &) From 54b5287adf4f5b004fcf47840c7f2e1e561a90c1 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 25 Sep 2015 18:54:46 +0200 Subject: [PATCH 208/240] Insert leading after each line, not before Task-number: QTBUG-45791 Change-Id: I763d9d1ba00989d0c6b1e0b955173dadbef26b10 Reviewed-by: Stephen Chu Reviewed-by: Lars Knoll --- src/gui/text/qtextengine_p.h | 3 +-- .../auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 160daa0cfd..dbe8e1ee2b 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -367,8 +367,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine uint leadingIncluded : 1; QFixed height() const { return ascent + descent + (leadingIncluded? qMax(QFixed(),leading) : QFixed()); } - QFixed base() const { return ascent - + (leadingIncluded ? qMax(QFixed(),leading) : QFixed()); } + QFixed base() const { return ascent; } void setDefaultHeight(QTextEngine *eng); void operator+=(const QScriptLine &other); }; diff --git a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp index d8e9836112..ec62bafd6c 100644 --- a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp +++ b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp @@ -65,6 +65,7 @@ private slots: void inFontUcs4(); void lineWidth(); void mnemonicTextWidth(); + void leadingBelowLine(); }; tst_QFontMetrics::tst_QFontMetrics() @@ -343,5 +344,16 @@ void tst_QFontMetrics::mnemonicTextWidth() QCOMPARE(fm.size(Qt::TextShowMnemonic, f1), fm.size(Qt::TextShowMnemonic, f2)); QCOMPARE(fm.size(Qt::TextHideMnemonic, f1), fm.size(Qt::TextHideMnemonic, f2)); } + +void tst_QFontMetrics::leadingBelowLine() +{ + QScriptLine line; + line.leading = 10; + line.leadingIncluded = true; + line.ascent = 5; + QCOMPARE(line.height(), line.ascent + line.descent + line.leading); + QCOMPARE(line.base(), line.ascent); +} + QTEST_MAIN(tst_QFontMetrics) #include "tst_qfontmetrics.moc" From de70798859e0363c8ca3133a4ed1a1092cfe47f5 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 6 Oct 2015 10:14:26 +0200 Subject: [PATCH 209/240] QMetaProperty::write should reset the property if an empty QVariant is given MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ChangeLog][QtCore][QMetaProperty] write() now resets the property if an empty QVariant is given, or set a default constructed object if the property is not resettable Change-Id: I9f9b57114e740f03ec4db6f223c1e8280a3d5209 Reviewed-by: Jędrzej Nowacki Reviewed-by: Oswald Buddenhagen --- src/corelib/kernel/qmetaobject.cpp | 16 ++++++++++++++-- src/corelib/kernel/qobject.cpp | 2 +- .../kernel/qmetaproperty/tst_qmetaproperty.cpp | 14 +++++++++++++- .../auto/corelib/kernel/qobject/tst_qobject.cpp | 4 ++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 6abec27684..820af298c0 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -3028,6 +3028,11 @@ QVariant QMetaProperty::read(const QObject *object) const Writes \a value as the property's value to the given \a object. Returns true if the write succeeded; otherwise returns \c false. + If \a value is not of the same type type as the property, a conversion + is attempted. An empty QVariant() is equivalent to a call to reset() + if this property is resetable, or setting a default-constructed object + otherwise. + \sa read(), reset(), isWritable() */ bool QMetaProperty::write(QObject *object, const QVariant &value) const @@ -3068,8 +3073,15 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const if (t == QMetaType::UnknownType) return false; } - if (t != QMetaType::QVariant && int(t) != value.userType() && !v.convert(t)) - return false; + if (t != QMetaType::QVariant && int(t) != value.userType()) { + if (!value.isValid()) { + if (isResettable()) + return reset(object); + v = QVariant(t, 0); + } else if (!v.convert(t)) { + return false; + } + } } // the status variable is changed by qt_metacall to indicate what it did diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 4bd8b4b662..c9884cd76c 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3831,7 +3831,7 @@ int QObjectPrivate::signalIndex(const char *signalName, \b{Note:} Dynamic properties starting with "_q_" are reserved for internal purposes. - \sa property(), metaObject(), dynamicPropertyNames() + \sa property(), metaObject(), dynamicPropertyNames(), QMetaProperty::write() */ bool QObject::setProperty(const char *name, const QVariant &value) { diff --git a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp index 10656a0dcd..22c78f8e48 100644 --- a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp +++ b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp @@ -55,7 +55,7 @@ class tst_QMetaProperty : public QObject Q_OBJECT Q_PROPERTY(EnumType value WRITE setValue READ getValue) Q_PROPERTY(EnumType value2 WRITE set_value READ get_value) - Q_PROPERTY(QString value7 MEMBER value7) + Q_PROPERTY(QString value7 MEMBER value7 RESET resetValue7) Q_PROPERTY(int value8 READ value8) Q_PROPERTY(int value9 READ value9 CONSTANT) Q_PROPERTY(int value10 READ value10 FINAL) @@ -79,6 +79,7 @@ public: void set_value(EnumType) {} EnumType get_value() const { return EnumType1; } + void resetValue7() { value7 = QStringLiteral("reset"); } int value8() const { return 1; } int value9() const { return 1; } int value10() const { return 1; } @@ -236,6 +237,17 @@ void tst_QMetaProperty::conversion() QVERIFY(!customP.write(this, QVariant::fromValue(this))); QVERIFY(!value7P.write(this, QVariant::fromValue(this))); QVERIFY(!value7P.write(this, QVariant::fromValue(this))); + + // none of this should have changed the values + QCOMPARE(value7, hello); + QCOMPARE(custom.str, hello); + + // Empty variant should be converted to default object + QVERIFY(customP.write(this, QVariant())); + QCOMPARE(custom.str, QString()); + // or reset resetable + QVERIFY(value7P.write(this, QVariant())); + QCOMPARE(value7, QLatin1Literal("reset")); } QTEST_MAIN(tst_QMetaProperty) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 4617ce5e74..a3c6d8e9df 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -1925,7 +1925,7 @@ void tst_QObject::property() QCOMPARE(object.property("string"), QVariant("String1")); QVERIFY(object.setProperty("string", "String2")); QCOMPARE(object.property("string"), QVariant("String2")); - QVERIFY(!object.setProperty("string", QVariant())); + QVERIFY(object.setProperty("string", QVariant())); const int idx = mo->indexOfProperty("variant"); QVERIFY(idx != -1); @@ -2027,7 +2027,7 @@ void tst_QObject::property() QCOMPARE(object.property("customString"), QVariant("String1")); QVERIFY(object.setProperty("customString", "String2")); QCOMPARE(object.property("customString"), QVariant("String2")); - QVERIFY(!object.setProperty("customString", QVariant())); + QVERIFY(object.setProperty("customString", QVariant())); } void tst_QObject::metamethod() From c55a36cb9015cf1eebd49eaa5b1b4f4ec9b28451 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Wed, 7 Oct 2015 16:58:09 +0300 Subject: [PATCH 210/240] xcb: Fix DnD for separate X screens Recreate QShapedPixmapWindow when the cursor goes to another X screen. Change-Id: Ifd4c4281971b23abc45a9f6c0509832a45c31521 Reviewed-by: Lars Knoll --- src/gui/kernel/qshapedpixmapdndwindow.cpp | 4 +- src/gui/kernel/qshapedpixmapdndwindow_p.h | 2 +- src/gui/kernel/qsimpledrag.cpp | 29 +++++++------- src/gui/kernel/qsimpledrag_p.h | 2 + src/plugins/platforms/xcb/qxcbconnection.h | 2 + src/plugins/platforms/xcb/qxcbcursor.cpp | 45 ++++++++++++---------- src/plugins/platforms/xcb/qxcbcursor.h | 2 +- src/plugins/platforms/xcb/qxcbdrag.cpp | 45 +++++++--------------- src/plugins/platforms/xcb/qxcbdrag.h | 2 +- src/plugins/platforms/xcb/qxcbscreen.cpp | 9 +++++ src/plugins/platforms/xcb/qxcbscreen.h | 3 ++ 11 files changed, 75 insertions(+), 70 deletions(-) diff --git a/src/gui/kernel/qshapedpixmapdndwindow.cpp b/src/gui/kernel/qshapedpixmapdndwindow.cpp index 8f80789fb0..5736c41e25 100644 --- a/src/gui/kernel/qshapedpixmapdndwindow.cpp +++ b/src/gui/kernel/qshapedpixmapdndwindow.cpp @@ -38,8 +38,8 @@ QT_BEGIN_NAMESPACE -QShapedPixmapWindow::QShapedPixmapWindow() - : QWindow(), +QShapedPixmapWindow::QShapedPixmapWindow(QScreen *screen) + : QWindow(screen), m_backingStore(0) { QSurfaceFormat format; diff --git a/src/gui/kernel/qshapedpixmapdndwindow_p.h b/src/gui/kernel/qshapedpixmapdndwindow_p.h index fc311cff92..7536c09165 100644 --- a/src/gui/kernel/qshapedpixmapdndwindow_p.h +++ b/src/gui/kernel/qshapedpixmapdndwindow_p.h @@ -55,7 +55,7 @@ class QShapedPixmapWindow : public QWindow { Q_OBJECT public: - QShapedPixmapWindow(); + explicit QShapedPixmapWindow(QScreen *screen = 0); ~QShapedPixmapWindow(); void render(); diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index b02f1dd8bd..6acac4cade 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -203,25 +203,15 @@ void QBasicDrag::restoreCursor() void QBasicDrag::startDrag() { - // ### TODO Check if its really necessary to have m_drag_icon_window - // when QDrag is used without a pixmap - QDrag::setPixmap() - if (!m_drag_icon_window) - m_drag_icon_window = new QShapedPixmapWindow(); - - m_drag_icon_window->setPixmap(m_drag->pixmap()); - m_drag_icon_window->setHotspot(m_drag->hotSpot()); - + QPoint pos; #ifndef QT_NO_CURSOR - QPoint pos = QCursor::pos(); + pos = QCursor::pos(); if (pos.x() == int(qInf())) { // ### fixme: no mouse pos registered. Get pos from touch... pos = QPoint(); } - m_drag_icon_window->updateGeometry(pos); #endif - - m_drag_icon_window->setVisible(true); - + recreateShapedPixmapWindow(Q_NULLPTR, pos); enableEventFilter(); } @@ -229,6 +219,19 @@ void QBasicDrag::endDrag() { } +void QBasicDrag::recreateShapedPixmapWindow(QScreen *screen, const QPoint &pos) +{ + delete m_drag_icon_window; + // ### TODO Check if its really necessary to have m_drag_icon_window + // when QDrag is used without a pixmap - QDrag::setPixmap() + m_drag_icon_window = new QShapedPixmapWindow(screen); + + m_drag_icon_window->setPixmap(m_drag->pixmap()); + m_drag_icon_window->setHotspot(m_drag->hotSpot()); + m_drag_icon_window->updateGeometry(pos); + m_drag_icon_window->setVisible(true); +} + void QBasicDrag::cancel() { disableEventFilter(); diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h index a011475381..4c9edbae05 100644 --- a/src/gui/kernel/qsimpledrag_p.h +++ b/src/gui/kernel/qsimpledrag_p.h @@ -58,6 +58,7 @@ class QWindow; class QEventLoop; class QDropData; class QShapedPixmapWindow; +class QScreen; class Q_GUI_EXPORT QBasicDrag : public QPlatformDrag, public QObject { @@ -80,6 +81,7 @@ protected: void moveShapedPixmapWindow(const QPoint &deviceIndependentPosition); QShapedPixmapWindow *shapedPixmapWindow() const { return m_drag_icon_window; } + void recreateShapedPixmapWindow(QScreen *screen, const QPoint &pos); void updateCursor(Qt::DropAction action); bool canDrop() const { return m_can_drop; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 6ee32bf600..fb5b941fff 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -376,8 +376,10 @@ public: QXcbConnection *connection() const { return const_cast(this); } + const QList &virtualDesktops() const { return m_virtualDesktops; } const QList &screens() const { return m_screens; } int primaryScreenNumber() const { return m_primaryScreenNumber; } + QXcbVirtualDesktop *primaryVirtualDesktop() const { return m_virtualDesktops.value(m_primaryScreenNumber); } QXcbScreen *primaryScreen() const; inline xcb_atom_t atom(QXcbAtom::Atom atom) const { return m_allAtoms[atom]; } diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 0cd9159052..b321ed95dc 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -607,30 +607,33 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor) } #endif -void QXcbCursor::queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint *pos, int *keybMask) +void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask) { if (pos) *pos = QPoint(); - xcb_screen_iterator_t it = xcb_setup_roots_iterator(c->setup()); - while (it.rem) { - xcb_window_t root = it.data->root; - xcb_query_pointer_cookie_t cookie = xcb_query_pointer(c->xcb_connection(), root); - xcb_generic_error_t *err = 0; - xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(c->xcb_connection(), cookie, &err); - if (!err && reply) { - if (pos) - *pos = QPoint(reply->root_x, reply->root_y); - if (rootWin) - *rootWin = root; - if (keybMask) - *keybMask = reply->mask; - free(reply); - return; + + xcb_window_t root = c->primaryVirtualDesktop()->root(); + xcb_query_pointer_cookie_t cookie = xcb_query_pointer(c->xcb_connection(), root); + xcb_generic_error_t *err = 0; + xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(c->xcb_connection(), cookie, &err); + if (!err && reply) { + if (virtualDesktop) { + foreach (QXcbVirtualDesktop *vd, c->virtualDesktops()) { + if (vd->root() == reply->root) { + *virtualDesktop = vd; + break; + } + } } - free(err); + if (pos) + *pos = QPoint(reply->root_x, reply->root_y); + if (keybMask) + *keybMask = reply->mask; free(reply); - xcb_screen_next(&it); + return; } + free(err); + free(reply); } QPoint QXcbCursor::pos() const @@ -642,9 +645,9 @@ QPoint QXcbCursor::pos() const void QXcbCursor::setPos(const QPoint &pos) { - xcb_window_t root = 0; - queryPointer(connection(), &root, 0); - xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, pos.x(), pos.y()); + QXcbVirtualDesktop *virtualDesktop = Q_NULLPTR; + queryPointer(connection(), &virtualDesktop, 0); + xcb_warp_pointer(xcb_connection(), XCB_NONE, virtualDesktop->root(), 0, 0, 0, 0, pos.x(), pos.y()); xcb_flush(xcb_connection()); } diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h index f4f6e61706..3c6dece1f2 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.h +++ b/src/plugins/platforms/xcb/qxcbcursor.h @@ -75,7 +75,7 @@ public: QPoint pos() const Q_DECL_OVERRIDE; void setPos(const QPoint &pos) Q_DECL_OVERRIDE; - static void queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint *pos, int *keybMask = 0); + static void queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask = 0); private: #ifndef QT_NO_CURSOR diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index de23c59a63..f9c3aa7fed 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -39,6 +39,7 @@ #include "qxcbwindow.h" #include "qxcbscreen.h" #include "qwindow.h" +#include "qxcbcursor.h" #include #include #include @@ -160,7 +161,7 @@ void QXcbDrag::init() source_time = XCB_CURRENT_TIME; target_time = XCB_CURRENT_TIME; - current_screen = 0; + QXcbCursor::queryPointer(connection(), ¤t_virtual_desktop, 0); drag_types.clear(); } @@ -308,38 +309,20 @@ void QXcbDrag::move(const QPoint &globalPos) if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid()) return; - const QList &screens = connection()->screens(); - QXcbScreen *screen = connection()->primaryScreen(); - for (int i = 0; i < screens.size(); ++i) { - if (screens.at(i)->geometry().contains(globalPos)) { - screen = screens.at(i); - break; - } + QXcbVirtualDesktop *virtualDesktop = Q_NULLPTR; + QPoint cursorPos; + QXcbCursor::queryPointer(connection(), &virtualDesktop, &cursorPos); + QXcbScreen *screen = virtualDesktop->screenAt(cursorPos); + QPoint deviceIndependentPos = QHighDpiScaling::mapPositionFromNative(globalPos, screen); + + if (virtualDesktop != current_virtual_desktop) { + recreateShapedPixmapWindow(static_cast(screen)->screen(), deviceIndependentPos); + current_virtual_desktop = virtualDesktop; + } else { + QBasicDrag::moveShapedPixmapWindow(deviceIndependentPos); } - QBasicDrag::moveShapedPixmapWindow(QHighDpiScaling::mapPositionFromNative(globalPos, screen)); - - if (screen != current_screen) { - // ### need to recreate the shaped pixmap window? -// int screen = QCursor::x11Screen(); -// if ((qt_xdnd_current_screen == -1 && screen != X11->defaultScreen) || (screen != qt_xdnd_current_screen)) { -// // recreate the pixmap on the new screen... -// delete xdnd_data.deco; -// QWidget* parent = object->source()->window()->x11Info().screen() == screen -// ? object->source()->window() : QApplication::desktop()->screen(screen); -// xdnd_data.deco = new QShapedPixmapWidget(parent); -// if (!QWidget::mouseGrabber()) { -// updatePixmap(); -// xdnd_data.deco->grabMouse(); -// } -// } -// xdnd_data.deco->move(QCursor::pos() - xdnd_data.deco->pm_hot); - current_screen = screen; - } - - -// qt_xdnd_current_screen = screen; - xcb_window_t rootwin = current_screen->root(); + xcb_window_t rootwin = current_virtual_desktop->root(); xcb_translate_coordinates_reply_t *translate = ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y()); if (!translate) diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 9584c04238..c9d257906f 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -133,7 +133,7 @@ private: // window to send events to (always valid if current_target) xcb_window_t current_proxy_target; - QXcbScreen *current_screen; + QXcbVirtualDesktop *current_virtual_desktop; // 10 minute timer used to discard old XdndDrop transactions enum { XdndDropTransactionTimeout = 600000 }; diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index c6e48dc8c4..2e0c55eea8 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -61,6 +61,15 @@ QXcbVirtualDesktop::~QXcbVirtualDesktop() delete m_xSettings; } +QXcbScreen *QXcbVirtualDesktop::screenAt(const QPoint &pos) const +{ + foreach (QXcbScreen *screen, connection()->screens()) { + if (screen->virtualDesktop() == this && screen->nativeGeometry().contains(pos)) + return screen; + } + return Q_NULLPTR; +} + QXcbXSettings *QXcbVirtualDesktop::xSettings() const { if (!m_xSettings) { diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index cbb6307d6e..d8d63608e7 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -64,6 +64,8 @@ public: int number() const { return m_number; } QSize size() const { return QSize(m_screen->width_in_pixels, m_screen->height_in_pixels); } QSize physicalSize() const { return QSize(m_screen->width_in_millimeters, m_screen->height_in_millimeters); } + xcb_window_t root() const { return m_screen->root; } + QXcbScreen *screenAt(const QPoint &pos) const; QXcbXSettings *xSettings() const; @@ -104,6 +106,7 @@ public: void setVirtualSiblings(QList sl) { m_siblings = sl; } void removeVirtualSibling(QPlatformScreen *s) { m_siblings.removeOne(s); } void addVirtualSibling(QPlatformScreen *s) { ((QXcbScreen *) s)->isPrimary() ? m_siblings.prepend(s) : m_siblings.append(s); } + QXcbVirtualDesktop *virtualDesktop() const { return m_virtualDesktop; } void setPrimary(bool primary) { m_primary = primary; } bool isPrimary() const { return m_primary; } From c8cd9f1b9a3d338a12bdccce957d74d515eb9c32 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 7 Oct 2015 12:03:05 +0200 Subject: [PATCH 211/240] Polish DnD Examples. - Remove class DragLabel in draggabletext and add a static creation function instead since it only has a constructor setting some properties. - Use QRegularExpression instead of QRegExp - Use new connection syntax. - Ensure compilation with DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII demonstrating use of QLatin1String vs QStringLiteral. - Streamline code. Change-Id: I2e2ddeb40837dba379990836c77fb72ad7263e2d Reviewed-by: Oliver Wolff --- .../draganddrop/draggableicons/main.cpp | 3 +- .../draggabletext/draggabletext.pro | 6 +- .../draganddrop/draggabletext/draglabel.cpp | 49 ---------------- .../draganddrop/draggabletext/draglabel.h | 58 ------------------- .../draganddrop/draggabletext/dragwidget.cpp | 45 +++++++------- .../widgets/draganddrop/dropsite/droparea.cpp | 6 +- .../draganddrop/dropsite/dropsitewindow.cpp | 27 ++++----- .../draganddrop/fridgemagnets/dragwidget.cpp | 19 +++--- .../draganddrop/fridgemagnets/main.cpp | 2 +- examples/widgets/draganddrop/puzzle/main.cpp | 2 +- .../widgets/draganddrop/puzzle/mainwindow.cpp | 47 +++++++-------- .../widgets/draganddrop/puzzle/mainwindow.h | 3 +- .../widgets/draganddrop/puzzle/pieceslist.cpp | 10 ++-- .../widgets/draganddrop/puzzle/pieceslist.h | 2 + .../draganddrop/puzzle/puzzlewidget.cpp | 26 +++------ .../widgets/draganddrop/puzzle/puzzlewidget.h | 1 - 16 files changed, 91 insertions(+), 215 deletions(-) delete mode 100644 examples/widgets/draganddrop/draggabletext/draglabel.cpp delete mode 100644 examples/widgets/draganddrop/draggabletext/draglabel.h diff --git a/examples/widgets/draganddrop/draggableicons/main.cpp b/examples/widgets/draganddrop/draggableicons/main.cpp index 165f71dbf7..44b4f848bf 100644 --- a/examples/widgets/draganddrop/draggableicons/main.cpp +++ b/examples/widgets/draganddrop/draggableicons/main.cpp @@ -50,11 +50,10 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); QWidget mainWidget; - QHBoxLayout *horizontalLayout = new QHBoxLayout; + QHBoxLayout *horizontalLayout = new QHBoxLayout(&mainWidget); horizontalLayout->addWidget(new DragWidget); horizontalLayout->addWidget(new DragWidget); - mainWidget.setLayout(horizontalLayout); mainWidget.setWindowTitle(QObject::tr("Draggable Icons")); mainWidget.show(); diff --git a/examples/widgets/draganddrop/draggabletext/draggabletext.pro b/examples/widgets/draganddrop/draggabletext/draggabletext.pro index 2815be1613..1add2a270e 100644 --- a/examples/widgets/draganddrop/draggabletext/draggabletext.pro +++ b/examples/widgets/draganddrop/draggabletext/draggabletext.pro @@ -1,10 +1,8 @@ QT += widgets -HEADERS = draglabel.h \ - dragwidget.h +HEADERS = dragwidget.h RESOURCES = draggabletext.qrc -SOURCES = draglabel.cpp \ - dragwidget.cpp \ +SOURCES = dragwidget.cpp \ main.cpp # install diff --git a/examples/widgets/draganddrop/draggabletext/draglabel.cpp b/examples/widgets/draganddrop/draggabletext/draglabel.cpp deleted file mode 100644 index 4e741fb6c8..0000000000 --- a/examples/widgets/draganddrop/draggabletext/draglabel.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "draglabel.h" - -DragLabel::DragLabel(const QString &text, QWidget *parent) - : QLabel(text, parent) -{ - setAutoFillBackground(true); - setFrameShape(QFrame::Panel); - setFrameShadow(QFrame::Raised); -} diff --git a/examples/widgets/draganddrop/draggabletext/draglabel.h b/examples/widgets/draganddrop/draggabletext/draglabel.h deleted file mode 100644 index 8d2c31aa1d..0000000000 --- a/examples/widgets/draganddrop/draggabletext/draglabel.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DRAGLABEL_H -#define DRAGLABEL_H - -#include - -QT_BEGIN_NAMESPACE -class QDragEnterEvent; -class QDragMoveEvent; -class QFrame; -QT_END_NAMESPACE - -class DragLabel : public QLabel -{ -public: - DragLabel(const QString &text, QWidget *parent); -}; - -#endif // DRAGLABEL_H diff --git a/examples/widgets/draganddrop/draggabletext/dragwidget.cpp b/examples/widgets/draganddrop/draggabletext/dragwidget.cpp index 3b8bca3277..36c4df2e43 100644 --- a/examples/widgets/draganddrop/draggabletext/dragwidget.cpp +++ b/examples/widgets/draganddrop/draggabletext/dragwidget.cpp @@ -40,13 +40,23 @@ #include -#include "draglabel.h" #include "dragwidget.h" +static QLabel *createDragLabel(const QString &text, QWidget *parent) +{ + QLabel *label = new QLabel(text, parent); + label->setAutoFillBackground(true); + label->setFrameShape(QFrame::Panel); + label->setFrameShadow(QFrame::Raised); + return label; +} + +static QString hotSpotMimeDataKey() { return QStringLiteral("application/x-hotspot"); } + DragWidget::DragWidget(QWidget *parent) : QWidget(parent) { - QFile dictionaryFile(":/dictionary/words.txt"); + QFile dictionaryFile(QStringLiteral(":/dictionary/words.txt")); dictionaryFile.open(QIODevice::ReadOnly); QTextStream inputStream(&dictionaryFile); @@ -57,7 +67,7 @@ DragWidget::DragWidget(QWidget *parent) QString word; inputStream >> word; if (!word.isEmpty()) { - DragLabel *wordLabel = new DragLabel(word, this); + QLabel *wordLabel = createDragLabel(word, this); wordLabel->move(x, y); wordLabel->show(); wordLabel->setAttribute(Qt::WA_DeleteOnClose); @@ -69,12 +79,6 @@ DragWidget::DragWidget(QWidget *parent) } } - /* - QPalette newPalette = palette(); - newPalette.setColor(QPalette::Window, Qt::white); - setPalette(newPalette); - */ - setAcceptDrops(true); setMinimumSize(400, qMax(200, y)); setWindowTitle(tr("Draggable Text")); @@ -98,19 +102,19 @@ void DragWidget::dropEvent(QDropEvent *event) { if (event->mimeData()->hasText()) { const QMimeData *mime = event->mimeData(); - QStringList pieces = mime->text().split(QRegExp("\\s+"), + QStringList pieces = mime->text().split(QRegularExpression(QStringLiteral("\\s+")), QString::SkipEmptyParts); QPoint position = event->pos(); QPoint hotSpot; - QList hotSpotPos = mime->data("application/x-hotspot").split(' '); + QByteArrayList hotSpotPos = mime->data(hotSpotMimeDataKey()).split(' '); if (hotSpotPos.size() == 2) { hotSpot.setX(hotSpotPos.first().toInt()); hotSpot.setY(hotSpotPos.last().toInt()); } - foreach (QString piece, pieces) { - DragLabel *newLabel = new DragLabel(piece, this); + foreach (const QString &piece, pieces) { + QLabel *newLabel = createDragLabel(piece, this); newLabel->move(position - hotSpot); newLabel->show(); newLabel->setAttribute(Qt::WA_DeleteOnClose); @@ -127,18 +131,15 @@ void DragWidget::dropEvent(QDropEvent *event) } else { event->ignore(); } - foreach (QObject *child, children()) { - if (child->inherits("QWidget")) { - QWidget *widget = static_cast(child); - if (!widget->isVisible()) - widget->deleteLater(); - } + foreach (QWidget *widget, findChildren()) { + if (!widget->isVisible()) + widget->deleteLater(); } } void DragWidget::mousePressEvent(QMouseEvent *event) { - QLabel *child = static_cast(childAt(event->pos())); + QLabel *child = qobject_cast(childAt(event->pos())); if (!child) return; @@ -146,8 +147,8 @@ void DragWidget::mousePressEvent(QMouseEvent *event) QMimeData *mimeData = new QMimeData; mimeData->setText(child->text()); - mimeData->setData("application/x-hotspot", - QByteArray::number(hotSpot.x()) + " " + QByteArray::number(hotSpot.y())); + mimeData->setData(hotSpotMimeDataKey(), + QByteArray::number(hotSpot.x()) + ' ' + QByteArray::number(hotSpot.y())); QPixmap pixmap(child->size()); child->render(&pixmap); diff --git a/examples/widgets/draganddrop/dropsite/droparea.cpp b/examples/widgets/draganddrop/dropsite/droparea.cpp index d3d2bb10ca..0016434cc3 100644 --- a/examples/widgets/draganddrop/dropsite/droparea.cpp +++ b/examples/widgets/draganddrop/dropsite/droparea.cpp @@ -92,10 +92,8 @@ void DropArea::dropEvent(QDropEvent *event) } else if (mimeData->hasUrls()) { QList urlList = mimeData->urls(); QString text; - for (int i = 0; i < urlList.size() && i < 32; ++i) { - QString url = urlList.at(i).path(); - text += url + QString("\n"); - } + for (int i = 0; i < urlList.size() && i < 32; ++i) + text += urlList.at(i).path() + QLatin1Char('\n'); setText(text); } else { setText(tr("Cannot display data")); diff --git a/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp b/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp index 5f0e689fc9..5d48be1c34 100644 --- a/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp +++ b/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp @@ -55,8 +55,8 @@ DropSiteWindow::DropSiteWindow() //! [constructor part2] dropArea = new DropArea; - connect(dropArea, SIGNAL(changed(const QMimeData*)), - this, SLOT(updateFormatsTable(const QMimeData*))); + connect(dropArea, &DropArea::changed, + this, &DropSiteWindow::updateFormatsTable); //! [constructor part2] //! [constructor part3] @@ -78,17 +78,16 @@ DropSiteWindow::DropSiteWindow() buttonBox->addButton(clearButton, QDialogButtonBox::ActionRole); buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole); - connect(quitButton, SIGNAL(pressed()), this, SLOT(close())); - connect(clearButton, SIGNAL(pressed()), dropArea, SLOT(clear())); + connect(quitButton, &QAbstractButton::pressed, this, &QWidget::close); + connect(clearButton, &QAbstractButton::pressed, dropArea, &DropArea::clear); //! [constructor part4] //! [constructor part5] - QVBoxLayout *mainLayout = new QVBoxLayout; + QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(abstractLabel); mainLayout->addWidget(dropArea); mainLayout->addWidget(formatsTable); mainLayout->addWidget(buttonBox); - setLayout(mainLayout); setWindowTitle(tr("Drop Site")); setMinimumSize(350, 500); @@ -112,22 +111,18 @@ void DropSiteWindow::updateFormatsTable(const QMimeData *mimeData) //! [updateFormatsTable() part3] QString text; - if (format == "text/plain") { + if (format == QLatin1String("text/plain")) { text = mimeData->text().simplified(); - } else if (format == "text/html") { + } else if (format == QLatin1String("text/html")) { text = mimeData->html().simplified(); - } else if (format == "text/uri-list") { + } else if (format == QLatin1String("text/uri-list")) { QList urlList = mimeData->urls(); for (int i = 0; i < urlList.size() && i < 32; ++i) - text.append(urlList[i].toString() + " "); + text.append(urlList.at(i).toString() + QLatin1Char(' ')); } else { QByteArray data = mimeData->data(format); - for (int i = 0; i < data.size() && i < 32; ++i) { - QString hex = QString("%1").arg(uchar(data[i]), 2, 16, - QChar('0')) - .toUpper(); - text.append(hex + " "); - } + for (int i = 0; i < data.size() && i < 32; ++i) + text.append(QStringLiteral("%1 ").arg(uchar(data[i]), 2, 16, QLatin1Char('0')).toUpper()); } //! [updateFormatsTable() part3] diff --git a/examples/widgets/draganddrop/fridgemagnets/dragwidget.cpp b/examples/widgets/draganddrop/fridgemagnets/dragwidget.cpp index a591a29994..3a9ab5fa76 100644 --- a/examples/widgets/draganddrop/fridgemagnets/dragwidget.cpp +++ b/examples/widgets/draganddrop/fridgemagnets/dragwidget.cpp @@ -43,11 +43,13 @@ #include +static inline QString fridgetMagnetsMimeType() { return QStringLiteral("application/x-fridgemagnet"); } + //! [0] DragWidget::DragWidget(QWidget *parent) : QWidget(parent) { - QFile dictionaryFile(":/dictionary/words.txt"); + QFile dictionaryFile(QStringLiteral(":/dictionary/words.txt")); dictionaryFile.open(QFile::ReadOnly); QTextStream inputStream(&dictionaryFile); //! [0] @@ -74,7 +76,6 @@ DragWidget::DragWidget(QWidget *parent) //! [1] //! [2] - //Fridge magnets is used for demoing Qt on S60 and themed backgrounds look better than white QPalette newPalette = palette(); newPalette.setColor(QPalette::Window, Qt::white); setPalette(newPalette); @@ -90,7 +91,7 @@ DragWidget::DragWidget(QWidget *parent) void DragWidget::dragEnterEvent(QDragEnterEvent *event) { //! [4] //! [5] - if (event->mimeData()->hasFormat("application/x-fridgemagnet")) { + if (event->mimeData()->hasFormat(fridgetMagnetsMimeType())) { if (children().contains(event->source())) { event->setDropAction(Qt::MoveAction); event->accept(); @@ -110,7 +111,7 @@ void DragWidget::dragEnterEvent(QDragEnterEvent *event) //! [8] void DragWidget::dragMoveEvent(QDragMoveEvent *event) { - if (event->mimeData()->hasFormat("application/x-fridgemagnet")) { + if (event->mimeData()->hasFormat(fridgetMagnetsMimeType())) { if (children().contains(event->source())) { event->setDropAction(Qt::MoveAction); event->accept(); @@ -128,10 +129,10 @@ void DragWidget::dragMoveEvent(QDragMoveEvent *event) //! [9] void DragWidget::dropEvent(QDropEvent *event) { - if (event->mimeData()->hasFormat("application/x-fridgemagnet")) { + if (event->mimeData()->hasFormat(fridgetMagnetsMimeType())) { const QMimeData *mime = event->mimeData(); //! [9] //! [10] - QByteArray itemData = mime->data("application/x-fridgemagnet"); + QByteArray itemData = mime->data(fridgetMagnetsMimeType()); QDataStream dataStream(&itemData, QIODevice::ReadOnly); QString text; @@ -152,11 +153,11 @@ void DragWidget::dropEvent(QDropEvent *event) } //! [11] //! [12] } else if (event->mimeData()->hasText()) { - QStringList pieces = event->mimeData()->text().split(QRegExp("\\s+"), + QStringList pieces = event->mimeData()->text().split(QRegularExpression(QStringLiteral("\\s+")), QString::SkipEmptyParts); QPoint position = event->pos(); - foreach (QString piece, pieces) { + foreach (const QString &piece, pieces) { DragLabel *newLabel = new DragLabel(piece, this); newLabel->move(position); newLabel->show(); @@ -190,7 +191,7 @@ void DragWidget::mousePressEvent(QMouseEvent *event) //! [15] QMimeData *mimeData = new QMimeData; - mimeData->setData("application/x-fridgemagnet", itemData); + mimeData->setData(fridgetMagnetsMimeType(), itemData); mimeData->setText(child->labelText()); //! [15] diff --git a/examples/widgets/draganddrop/fridgemagnets/main.cpp b/examples/widgets/draganddrop/fridgemagnets/main.cpp index edff4486d6..a52ff8cabd 100644 --- a/examples/widgets/draganddrop/fridgemagnets/main.cpp +++ b/examples/widgets/draganddrop/fridgemagnets/main.cpp @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) #endif DragWidget window; - bool smallScreen = QApplication::arguments().contains("-small-screen"); + bool smallScreen = QApplication::arguments().contains(QStringLiteral("-small-screen")); if (smallScreen) window.showFullScreen(); else diff --git a/examples/widgets/draganddrop/puzzle/main.cpp b/examples/widgets/draganddrop/puzzle/main.cpp index 706ebe4d70..e8ecbe37db 100644 --- a/examples/widgets/draganddrop/puzzle/main.cpp +++ b/examples/widgets/draganddrop/puzzle/main.cpp @@ -48,7 +48,7 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); MainWindow window; - window.openImage(":/images/example.jpg"); + window.loadImage(QStringLiteral(":/images/example.jpg")); window.show(); return app.exec(); } diff --git a/examples/widgets/draganddrop/puzzle/mainwindow.cpp b/examples/widgets/draganddrop/puzzle/mainwindow.cpp index 0fbdfc3f8d..48e79946e7 100644 --- a/examples/widgets/draganddrop/puzzle/mainwindow.cpp +++ b/examples/widgets/draganddrop/puzzle/mainwindow.cpp @@ -55,26 +55,27 @@ MainWindow::MainWindow(QWidget *parent) setWindowTitle(tr("Puzzle")); } -void MainWindow::openImage(const QString &path) +void MainWindow::openImage() { - QString fileName = path; + const QString fileName = + QFileDialog::getOpenFileName(this, tr("Open Image"), QString(), + tr("Image Files (*.png *.jpg *.bmp)")); - if (fileName.isNull()) { - fileName = QFileDialog::getOpenFileName(this, - tr("Open Image"), "", "Image Files (*.png *.jpg *.bmp)"); - } + if (!fileName.isEmpty()) + loadImage(fileName); +} - if (!fileName.isEmpty()) { - QPixmap newImage; - if (!newImage.load(fileName)) { - QMessageBox::warning(this, tr("Open Image"), - tr("The image file could not be loaded."), - QMessageBox::Cancel); - return; - } - puzzleImage = newImage; - setupPuzzle(); +void MainWindow::loadImage(const QString &fileName) +{ + QPixmap newImage; + if (!newImage.load(fileName)) { + QMessageBox::warning(this, tr("Open Image"), + tr("The image file could not be loaded."), + QMessageBox::Close); + return; } + puzzleImage = newImage; + setupPuzzle(); } void MainWindow::setCompleted() @@ -120,19 +121,15 @@ void MainWindow::setupMenus() { QMenu *fileMenu = menuBar()->addMenu(tr("&File")); - QAction *openAction = fileMenu->addAction(tr("&Open...")); + QAction *openAction = fileMenu->addAction(tr("&Open..."), this, &MainWindow::openImage); openAction->setShortcuts(QKeySequence::Open); - QAction *exitAction = fileMenu->addAction(tr("E&xit")); + QAction *exitAction = fileMenu->addAction(tr("E&xit"), qApp, &QCoreApplication::quit); exitAction->setShortcuts(QKeySequence::Quit); QMenu *gameMenu = menuBar()->addMenu(tr("&Game")); - QAction *restartAction = gameMenu->addAction(tr("&Restart")); - - connect(openAction, SIGNAL(triggered()), this, SLOT(openImage())); - connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit())); - connect(restartAction, SIGNAL(triggered()), this, SLOT(setupPuzzle())); + gameMenu->addAction(tr("&Restart"), this, &MainWindow::setupPuzzle); } void MainWindow::setupWidgets() @@ -144,8 +141,8 @@ void MainWindow::setupWidgets() piecesList = new PiecesList(puzzleWidget->pieceSize(), this); - connect(puzzleWidget, SIGNAL(puzzleCompleted()), - this, SLOT(setCompleted()), Qt::QueuedConnection); + connect(puzzleWidget, &PuzzleWidget::puzzleCompleted, + this, &MainWindow::setCompleted, Qt::QueuedConnection); frameLayout->addWidget(piecesList); frameLayout->addWidget(puzzleWidget); diff --git a/examples/widgets/draganddrop/puzzle/mainwindow.h b/examples/widgets/draganddrop/puzzle/mainwindow.h index 093a14472e..b5b7d0d903 100644 --- a/examples/widgets/draganddrop/puzzle/mainwindow.h +++ b/examples/widgets/draganddrop/puzzle/mainwindow.h @@ -56,9 +56,10 @@ class MainWindow : public QMainWindow public: MainWindow(QWidget *parent = 0); + void loadImage(const QString &path); public slots: - void openImage(const QString &path = QString()); + void openImage(); void setupPuzzle(); private slots: diff --git a/examples/widgets/draganddrop/puzzle/pieceslist.cpp b/examples/widgets/draganddrop/puzzle/pieceslist.cpp index e60fd0a9ff..fb27aa2304 100644 --- a/examples/widgets/draganddrop/puzzle/pieceslist.cpp +++ b/examples/widgets/draganddrop/puzzle/pieceslist.cpp @@ -57,7 +57,7 @@ PiecesList::PiecesList(int pieceSize, QWidget *parent) void PiecesList::dragEnterEvent(QDragEnterEvent *event) { - if (event->mimeData()->hasFormat("image/x-puzzle-piece")) + if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())) event->accept(); else event->ignore(); @@ -65,7 +65,7 @@ void PiecesList::dragEnterEvent(QDragEnterEvent *event) void PiecesList::dragMoveEvent(QDragMoveEvent *event) { - if (event->mimeData()->hasFormat("image/x-puzzle-piece")) { + if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())) { event->setDropAction(Qt::MoveAction); event->accept(); } else { @@ -75,8 +75,8 @@ void PiecesList::dragMoveEvent(QDragMoveEvent *event) void PiecesList::dropEvent(QDropEvent *event) { - if (event->mimeData()->hasFormat("image/x-puzzle-piece")) { - QByteArray pieceData = event->mimeData()->data("image/x-puzzle-piece"); + if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())) { + QByteArray pieceData = event->mimeData()->data(PiecesList::puzzleMimeType()); QDataStream dataStream(&pieceData, QIODevice::ReadOnly); QPixmap pixmap; QPoint location; @@ -112,7 +112,7 @@ void PiecesList::startDrag(Qt::DropActions /*supportedActions*/) dataStream << pixmap << location; QMimeData *mimeData = new QMimeData; - mimeData->setData("image/x-puzzle-piece", itemData); + mimeData->setData(PiecesList::puzzleMimeType(), itemData); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); diff --git a/examples/widgets/draganddrop/puzzle/pieceslist.h b/examples/widgets/draganddrop/puzzle/pieceslist.h index 83c1ad8285..07fa504f41 100644 --- a/examples/widgets/draganddrop/puzzle/pieceslist.h +++ b/examples/widgets/draganddrop/puzzle/pieceslist.h @@ -51,6 +51,8 @@ public: explicit PiecesList(int pieceSize, QWidget *parent = 0); void addPiece(QPixmap pixmap, QPoint location); + static QString puzzleMimeType() { return QStringLiteral("image/x-puzzle-piece"); } + protected: void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE; void dragMoveEvent(QDragMoveEvent *event) Q_DECL_OVERRIDE; diff --git a/examples/widgets/draganddrop/puzzle/puzzlewidget.cpp b/examples/widgets/draganddrop/puzzle/puzzlewidget.cpp index 69c0cbf0cc..29052da4fb 100644 --- a/examples/widgets/draganddrop/puzzle/puzzlewidget.cpp +++ b/examples/widgets/draganddrop/puzzle/puzzlewidget.cpp @@ -39,6 +39,7 @@ ****************************************************************************/ #include "puzzlewidget.h" +#include "pieceslist.h" #include #include @@ -65,7 +66,7 @@ void PuzzleWidget::clear() void PuzzleWidget::dragEnterEvent(QDragEnterEvent *event) { - if (event->mimeData()->hasFormat("image/x-puzzle-piece")) + if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())) event->accept(); else event->ignore(); @@ -83,8 +84,8 @@ void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event) { QRect updateRect = highlightedRect.united(targetSquare(event->pos())); - if (event->mimeData()->hasFormat("image/x-puzzle-piece") - && findPiece(targetSquare(event->pos())) == -1) { + if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType()) + && pieceRects.indexOf(targetSquare(event->pos())) == -1) { highlightedRect = targetSquare(event->pos()); event->setDropAction(Qt::MoveAction); @@ -99,10 +100,10 @@ void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event) void PuzzleWidget::dropEvent(QDropEvent *event) { - if (event->mimeData()->hasFormat("image/x-puzzle-piece") - && findPiece(targetSquare(event->pos())) == -1) { + if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType()) + && pieceRects.indexOf(targetSquare(event->pos())) == -1) { - QByteArray pieceData = event->mimeData()->data("image/x-puzzle-piece"); + QByteArray pieceData = event->mimeData()->data(PiecesList::puzzleMimeType()); QDataStream dataStream(&pieceData, QIODevice::ReadOnly); QRect square = targetSquare(event->pos()); QPixmap pixmap; @@ -130,19 +131,10 @@ void PuzzleWidget::dropEvent(QDropEvent *event) } } -int PuzzleWidget::findPiece(const QRect &pieceRect) const -{ - for (int i = 0; i < pieceRects.size(); ++i) { - if (pieceRect == pieceRects[i]) - return i; - } - return -1; -} - void PuzzleWidget::mousePressEvent(QMouseEvent *event) { QRect square = targetSquare(event->pos()); - int found = findPiece(square); + int found = pieceRects.indexOf(square); if (found == -1) return; @@ -164,7 +156,7 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event) dataStream << pixmap << location; QMimeData *mimeData = new QMimeData; - mimeData->setData("image/x-puzzle-piece", itemData); + mimeData->setData(PiecesList::puzzleMimeType(), itemData); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); diff --git a/examples/widgets/draganddrop/puzzle/puzzlewidget.h b/examples/widgets/draganddrop/puzzle/puzzlewidget.h index 6bf264b5e0..eb8a3a29f9 100644 --- a/examples/widgets/draganddrop/puzzle/puzzlewidget.h +++ b/examples/widgets/draganddrop/puzzle/puzzlewidget.h @@ -75,7 +75,6 @@ protected: void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; private: - int findPiece(const QRect &pieceRect) const; const QRect targetSquare(const QPoint &position) const; QList piecePixmaps; From 48663eafd3521eadcd6094178afa75909dc3c09e Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 10 Oct 2015 10:00:32 +0200 Subject: [PATCH 212/240] QtCore/qmake: drop some unneeded QChar -> QString conversions Change-Id: Id2fb5089b0ec51073efb846b59ecc63942cfb60d Reviewed-by: Olivier Goffart (Woboq GmbH) --- qmake/generators/projectgenerator.cpp | 2 +- src/corelib/kernel/qvariant.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp index 9b1796c45d..7d042ce66c 100644 --- a/qmake/generators/projectgenerator.cpp +++ b/qmake/generators/projectgenerator.cpp @@ -166,7 +166,7 @@ ProjectGenerator::init() QString nd = newdir; if(nd == ".") nd = ""; - else if(!nd.isEmpty() && !nd.endsWith(QString(QChar(QDir::separator())))) + else if (!nd.isEmpty() && !nd.endsWith(QDir::separator())) nd += QDir::separator(); nd += profiles[i]; fileFixify(nd); diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 35f178e6a9..fdcbdb1c45 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -413,7 +413,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) QString *str = static_cast(result); switch (d->type) { case QVariant::Char: - *str = QString(*v_cast(d)); + *str = *v_cast(d); break; case QMetaType::Char: case QMetaType::SChar: From a6ddae873bbe4c3cc68949f5a2758b5458422e7c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 10 Oct 2015 10:34:46 +0200 Subject: [PATCH 213/240] QtCore: Don't compare QChars to literal 0s This is prone to ambiguities, even though we currently don't run into them. Use QChar::isNull() instead. Change-Id: I71843878b3f4f8a5deae2ef57a6f6628461be216 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qdir.cpp | 2 +- src/corelib/tools/qstring.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index e1d9858a66..4d2b36632f 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -138,7 +138,7 @@ inline QChar QDirPrivate::getFilterSepChar(const QString &nameFilter) // static inline QStringList QDirPrivate::splitFilters(const QString &nameFilter, QChar sep) { - if (sep == 0) + if (sep.isNull()) sep = getFilterSepChar(nameFilter); QStringList ret = nameFilter.split(sep); for (int i = 0; i < ret.count(); ++i) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index e3a3cc79c6..ea220ed557 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1509,7 +1509,7 @@ QString::QString(const QChar *unicode, int size) } else { if (size < 0) { size = 0; - while (unicode[size] != 0) + while (!unicode[size].isNull()) ++size; } if (!size) { From 2463b4452da6267d23bf1008a6472b30690690bc Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 10 Oct 2015 10:38:29 +0200 Subject: [PATCH 214/240] QtCore: don't convert single characters to QString for QTextCodec::fromUnicode() Use the fromUnicode(QChar *, int size) overload instead. Saves 0.5KiB text size on Linux GCC 4.9 AMD64 release builds. Change-Id: I1a1081e09bff4c2116288b8c2616e1bb7ee2bb42 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qsettings.cpp | 5 +++-- src/corelib/xml/qxmlstream.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index b9993c454e..458109888f 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -632,8 +632,9 @@ void QSettingsPrivate::iniEscapedString(const QString &str, QByteArray &result, int startPos = result.size(); result.reserve(startPos + str.size() * 3 / 2); + const QChar *unicode = str.unicode(); for (i = 0; i < str.size(); ++i) { - uint ch = str.at(i).unicode(); + uint ch = unicode[i].unicode(); if (ch == ';' || ch == ',' || ch == '=') needsQuotes = true; @@ -687,7 +688,7 @@ void QSettingsPrivate::iniEscapedString(const QString &str, QByteArray &result, #ifndef QT_NO_TEXTCODEC } else if (useCodec) { // slow - result += codec->fromUnicode(str.at(i)); + result += codec->fromUnicode(&unicode[i], 1); #endif } else { result += (char)ch; diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 13c84db9ae..69e2e5d5c1 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -3013,7 +3013,8 @@ void QXmlStreamWriterPrivate::checkIfASCIICompatibleCodec() #ifndef QT_NO_TEXTCODEC Q_ASSERT(encoder); // assumes ASCII-compatibility for all 8-bit encodings - const QByteArray bytes = encoder->fromUnicode(QStringLiteral(" ")); + QChar space = QLatin1Char(' '); + const QByteArray bytes = encoder->fromUnicode(&space, 1); isCodecASCIICompatible = (bytes.count() == 1); #else isCodecASCIICompatible = true; From eb149ec95c2c70b44ec993f5f051f4daaecae7fd Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 9 Oct 2015 22:06:58 +0000 Subject: [PATCH 215/240] Offscreen: Protect against the QT_NO_CURSOR define for changeCursor If QT_NO_CURSOR is defined then changeCursor() is not implemented in QPlatformCursor which means that it isn't really being overridden in the offscreen plugin. Therefore the same define is checked for to prevent a compiler from having a problem with it. Change-Id: Id7c104292354cb7462b3161602fc8d382a6dd390 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/plugins/platforms/offscreen/qoffscreencommon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.cpp b/src/plugins/platforms/offscreen/qoffscreencommon.cpp index 11977fc6ed..31d7397f6f 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.cpp +++ b/src/plugins/platforms/offscreen/qoffscreencommon.cpp @@ -75,13 +75,13 @@ public: QOffscreenScreen::windowContainingCursor = containing ? containing->handle() : 0; } - +#ifndef QT_NO_CURSOR void changeCursor(QCursor *windowCursor, QWindow *window) Q_DECL_OVERRIDE { Q_UNUSED(windowCursor); Q_UNUSED(window); } - +#endif private: QPoint m_pos; }; From 0cfdfcc82ec58b2016f4ab2973343eb85874f27d Mon Sep 17 00:00:00 2001 From: Christoph Schleifenbaum Date: Sun, 11 Oct 2015 15:27:37 +0200 Subject: [PATCH 216/240] QListView: Use correct available size when calculating scrollbars. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calculation was working as long as one didn't use per pixel scrolling. Task-number: QTBUG-48579 Change-Id: Ie02e28b008c5c81ed45d7dd17fed96148c23b598 Reviewed-by: Thorbjørn Lindeijer Reviewed-by: Friedemann Kleint Reviewed-by: David Faure --- src/widgets/itemviews/qlistview.cpp | 6 ++--- .../itemviews/qlistview/tst_qlistview.cpp | 24 ++++++++++++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index f3fd3e75a1..8257944821 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1846,8 +1846,7 @@ void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded && qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded; - const QSize viewportSize(viewport()->width() + (qq->verticalScrollBar()->maximum() > 0 ? qq->verticalScrollBar()->width() : 0), - viewport()->height() + (qq->horizontalScrollBar()->maximum() > 0 ? qq->horizontalScrollBar()->height() : 0)); + const QSize viewportSize = qq->contentsRect().size(); bool verticalWantsToShow = contentsSize.height() > viewportSize.height(); bool horizontalWantsToShow; @@ -1877,8 +1876,7 @@ void QCommonListViewBase::updateVerticalScrollBar(const QSize &step) const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded && qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded; - const QSize viewportSize(viewport()->width() + (qq->verticalScrollBar()->maximum() > 0 ? qq->verticalScrollBar()->width() : 0), - viewport()->height() + (qq->horizontalScrollBar()->maximum() > 0 ? qq->horizontalScrollBar()->height() : 0)); + const QSize viewportSize = qq->contentsRect().size(); bool horizontalWantsToShow = contentsSize.width() > viewportSize.width(); bool verticalWantsToShow; diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index 244af1316a..1b21096b44 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -148,6 +148,7 @@ private slots: void spacing(); void testScrollToWithHidden(); void testViewOptions(); + void taskQTBUG_39902_mutualScrollBars_data(); void taskQTBUG_39902_mutualScrollBars(); }; @@ -2359,8 +2360,21 @@ private: QStyle* m_oldStyle; }; +void tst_QListView::taskQTBUG_39902_mutualScrollBars_data() +{ + QTest::addColumn("horizontalScrollMode"); + QTest::addColumn("verticalScrollMode"); + QTest::newRow("per item / per item") << QAbstractItemView::ScrollPerItem << QAbstractItemView::ScrollPerItem; + QTest::newRow("per pixel / per item") << QAbstractItemView::ScrollPerPixel << QAbstractItemView::ScrollPerItem; + QTest::newRow("per item / per pixel") << QAbstractItemView::ScrollPerItem << QAbstractItemView::ScrollPerPixel; + QTest::newRow("per pixel / per pixel") << QAbstractItemView::ScrollPerPixel << QAbstractItemView::ScrollPerPixel; +} + void tst_QListView::taskQTBUG_39902_mutualScrollBars() { + QFETCH(QAbstractItemView::ScrollMode, horizontalScrollMode); + QFETCH(QAbstractItemView::ScrollMode, verticalScrollMode); + QWidget window; window.resize(400, 300); QListView *view = new QListView(&window); @@ -2372,6 +2386,9 @@ void tst_QListView::taskQTBUG_39902_mutualScrollBars() model.setData(model.index(i, 0), itemSize, Qt::SizeHintRole); view->setModel(&model); + view->setVerticalScrollMode(verticalScrollMode); + view->setHorizontalScrollMode(horizontalScrollMode); + window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); // make sure QListView is done with layouting the items (1/10 sec, like QListView) @@ -2412,7 +2429,7 @@ void tst_QListView::taskQTBUG_39902_mutualScrollBars() QTRY_VERIFY(view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(view->verticalScrollBar()->isVisible()); - // now remove just one single pixel in with -> both scroll bars will show up since they depend on each other + // now remove just one single pixel in width -> both scroll bars will show up since they depend on each other view->resize(itemSize.width() + view->frameWidth() * 2 - 1, model.rowCount() * itemSize.height() + view->frameWidth() * 2); QTRY_VERIFY(view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(view->verticalScrollBar()->isVisible()); @@ -2421,6 +2438,11 @@ void tst_QListView::taskQTBUG_39902_mutualScrollBars() view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2); QTRY_VERIFY(!view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(!view->verticalScrollBar()->isVisible()); + + // now remove just one single pixel in height -> both scroll bars will show up since they depend on each other + view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2 - 1); + QTRY_VERIFY(view->horizontalScrollBar()->isVisible()); + QTRY_VERIFY(view->verticalScrollBar()->isVisible()); } QTEST_MAIN(tst_QListView) From 2a1ea8f13be95f664b112663986102300a17bdfe Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Tue, 8 Sep 2015 16:14:08 +0200 Subject: [PATCH 217/240] DirectFB: Use correct pixel format for Texture Glyph Cache QImage::Format_Indexed8 -> QImage::Format_Alpha8 Change-Id: I7faa7c9d2cb20306f63a2522e7fa78736b9ee583 Task-number: QTBUG-47490 Reviewed-by: Laszlo Agocs --- src/gui/painting/qtextureglyphcache.cpp | 4 ++-- src/plugins/platforms/directfb/qdirectfbblitter.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 44e14f656d..97f82d16d3 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -286,9 +286,9 @@ void QImageTextureGlyphCache::createTextureData(int width, int height) case QFontEngine::Format_Mono: m_image = QImage(width, height, QImage::Format_Mono); break; - case QFontEngine::Format_A8: { + case QFontEngine::Format_A8: m_image = QImage(width, height, QImage::Format_Alpha8); - break; } + break; case QFontEngine::Format_A32: m_image = QImage(width, height, QImage::Format_RGB32); break; diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.cpp b/src/plugins/platforms/directfb/qdirectfbblitter.cpp index 4deac969e4..b87310ed76 100644 --- a/src/plugins/platforms/directfb/qdirectfbblitter.cpp +++ b/src/plugins/platforms/directfb/qdirectfbblitter.cpp @@ -473,7 +473,7 @@ IDirectFBSurface *QDirectFbTextureGlyphCache::sourceSurface() case QImage::Format_Mono: desc.pixelformat = DSPF_A1; break; - case QImage::Format_Indexed8: + case QImage::Format_Alpha8: desc.pixelformat = DSPF_A8; break; default: From 690f9a7e74701e64db1035ccb11673942988d927 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 10 Oct 2015 23:40:58 +0200 Subject: [PATCH 218/240] QtCore: use QStringRef in more places Apart from removing some unwanted allocations, also reduces text size by ~800B on Linux AMD64 GCC 4.9 release builds. Change-Id: Ibcd1d8264f54f2b165b69bee8aa50ff7f4ad3a10 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qfilesystemengine.cpp | 2 +- src/corelib/io/qfilesystementry.cpp | 3 +-- src/corelib/io/qfilesystemwatcher.cpp | 6 ++++-- src/corelib/io/qresource.cpp | 6 +++--- src/corelib/io/qsettings.cpp | 4 ++-- src/corelib/io/qsettings_mac.cpp | 4 ++-- src/corelib/plugin/qpluginloader.cpp | 6 +++--- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index e4dec2b7fb..a49d69d447 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -152,7 +152,7 @@ static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &ent const QStringList &paths = QDir::searchPaths(filePath.left(prefixSeparator)); for (int i = 0; i < paths.count(); i++) { - entry = QFileSystemEntry(QDir::cleanPath(paths.at(i) % QLatin1Char('/') % filePath.mid(prefixSeparator + 1))); + entry = QFileSystemEntry(QDir::cleanPath(paths.at(i) % QLatin1Char('/') % filePath.midRef(prefixSeparator + 1))); // Recurse! if (_q_resolveEntryAndCreateLegacyEngine_recursive(entry, data, engine, true)) return true; diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp index 79f16a0839..709970e3ac 100644 --- a/src/corelib/io/qfilesystementry.cpp +++ b/src/corelib/io/qfilesystementry.cpp @@ -53,8 +53,7 @@ static bool isUncRoot(const QString &server) if (idx == -1 || idx + 1 == localPath.length()) return true; - localPath = localPath.right(localPath.length() - idx - 1).trimmed(); - return localPath.isEmpty(); + return localPath.rightRef(localPath.length() - idx - 1).trimmed().isEmpty(); } static inline QString fixIfRelativeUncPath(const QString &path) diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 7fc3049f46..23a2fbecdb 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -296,7 +296,9 @@ QStringList QFileSystemWatcher::addPaths(const QStringList &paths) QFileSystemWatcherEngine *engine = 0; - if(!objectName().startsWith(QLatin1String("_qt_autotest_force_engine_"))) { + const QString on = objectName(); + + if (!on.startsWith(QLatin1String("_qt_autotest_force_engine_"))) { // Normal runtime case - search intelligently for best engine if(d->native) { engine = d->native; @@ -307,7 +309,7 @@ QStringList QFileSystemWatcher::addPaths(const QStringList &paths) } else { // Autotest override case - use the explicitly selected engine only - QString forceName = objectName().mid(26); + const QStringRef forceName = on.midRef(26); if(forceName == QLatin1String("poller")) { qDebug() << "QFileSystemWatcher: skipping native engine, using only polling engine"; d_func()->initPollerEngine(); diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 4e6079306b..0674ef34e0 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -800,8 +800,8 @@ bool QResourceRoot::mappingRootSubdir(const QString &path, QString *match) const { const QString root = mappingRoot(); if(!root.isEmpty()) { - const QStringList root_segments = root.split(QLatin1Char('/'), QString::SkipEmptyParts), - path_segments = path.split(QLatin1Char('/'), QString::SkipEmptyParts); + const QVector root_segments = root.splitRef(QLatin1Char('/'), QString::SkipEmptyParts), + path_segments = path.splitRef(QLatin1Char('/'), QString::SkipEmptyParts); if(path_segments.size() <= root_segments.size()) { int matched = 0; for(int i = 0; i < path_segments.size(); ++i) { @@ -811,7 +811,7 @@ bool QResourceRoot::mappingRootSubdir(const QString &path, QString *match) const } if(matched == path_segments.size()) { if(match && root_segments.size() > matched) - *match = root_segments.at(matched); + *match = root_segments.at(matched).toString(); return true; } } diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 458109888f..0c44582af8 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -488,7 +488,7 @@ QVariant QSettingsPrivate::stringToVariant(const QString &s) if (s.startsWith(QLatin1Char('@'))) { if (s.endsWith(QLatin1Char(')'))) { if (s.startsWith(QLatin1String("@ByteArray("))) { - return QVariant(s.toLatin1().mid(11, s.size() - 12)); + return QVariant(s.midRef(11, s.size() - 12).toLatin1()); } else if (s.startsWith(QLatin1String("@Variant(")) || s.startsWith(QLatin1String("@DateTime("))) { #ifndef QT_NO_DATASTREAM @@ -501,7 +501,7 @@ QVariant QSettingsPrivate::stringToVariant(const QString &s) version = QDataStream::Qt_4_0; offset = 9; } - QByteArray a(s.toLatin1().mid(offset)); + QByteArray a = s.midRef(offset).toLatin1(); QDataStream stream(&a, QIODevice::ReadOnly); stream.setVersion(version); QVariant result; diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp index 1ad198b990..f1d2e81bdc 100644 --- a/src/corelib/io/qsettings_mac.cpp +++ b/src/corelib/io/qsettings_mac.cpp @@ -403,11 +403,11 @@ QMacSettingsPrivate::QMacSettingsPrivate(QSettings::Scope scope, const QString & } while ((nextDot = domainName.indexOf(QLatin1Char('.'), curPos)) != -1) { - javaPackageName.prepend(domainName.mid(curPos, nextDot - curPos)); + javaPackageName.prepend(domainName.midRef(curPos, nextDot - curPos)); javaPackageName.prepend(QLatin1Char('.')); curPos = nextDot + 1; } - javaPackageName.prepend(domainName.mid(curPos)); + javaPackageName.prepend(domainName.midRef(curPos)); javaPackageName = javaPackageName.toLower(); if (curPos == 0) javaPackageName.prepend(QLatin1String("com.")); diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index 292ad30525..24101be87b 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -286,9 +286,9 @@ static QString locatePlugin(const QString& fileName) suffixes.prepend(QString()); // Split up "subdir/filename" - const int slash = fileName.lastIndexOf('/'); - const QString baseName = fileName.mid(slash + 1); - const QString basePath = isAbsolute ? QString() : fileName.left(slash + 1); // keep the '/' + const int slash = fileName.lastIndexOf(QLatin1Char('/')); + const QStringRef baseName = fileName.midRef(slash + 1); + const QStringRef basePath = isAbsolute ? QStringRef() : fileName.leftRef(slash + 1); // keep the '/' const bool debug = qt_debug_component(); From 5962c6e37e747044ab005ca53c7a90b4db210767 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 10 Oct 2015 23:41:14 +0200 Subject: [PATCH 219/240] QtCore: use QStringBuilder in more places Change-Id: I1a2016039c6cfa35505b987b6d4627bf806500ba Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qprocess.cpp | 12 ++---------- src/corelib/io/qtldurl.cpp | 15 +++++---------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 8ee8d0b703..8fbe96adb9 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -156,16 +156,8 @@ QStringList QProcessEnvironmentPrivate::toList() const { QStringList result; result.reserve(hash.size()); - Hash::ConstIterator it = hash.constBegin(), - end = hash.constEnd(); - for ( ; it != end; ++it) { - QString data = nameToString(it.key()); - QString value = valueToString(it.value()); - data.reserve(data.length() + value.length() + 1); - data.append(QLatin1Char('=')); - data.append(value); - result << data; - } + for (Hash::const_iterator it = hash.cbegin(), end = hash.cend(); it != end; ++it) + result << nameToString(it.key()) + QLatin1Char('=') + valueToString(it.value()); return result; } diff --git a/src/corelib/io/qtldurl.cpp b/src/corelib/io/qtldurl.cpp index d68d0ddf46..265055083e 100644 --- a/src/corelib/io/qtldurl.cpp +++ b/src/corelib/io/qtldurl.cpp @@ -99,19 +99,14 @@ Q_CORE_EXPORT bool qIsEffectiveTLD(const QString &domain) if (containsTLDEntry(domain)) return true; - if (domain.contains(QLatin1Char('.'))) { - int count = domain.size() - domain.indexOf(QLatin1Char('.')); - QString wildCardDomain; - wildCardDomain.reserve(count + 1); - wildCardDomain.append(QLatin1Char('*')); - wildCardDomain.append(domain.right(count)); + const int dot = domain.indexOf(QLatin1Char('.')); + if (dot >= 0) { + int count = domain.size() - dot; + QString wildCardDomain = QLatin1Char('*') + domain.rightRef(count); // 2. if table contains '*.bar.com', // test if table contains '!foo.bar.com' if (containsTLDEntry(wildCardDomain)) { - QString exceptionDomain; - exceptionDomain.reserve(domain.size() + 1); - exceptionDomain.append(QLatin1Char('!')); - exceptionDomain.append(domain); + QString exceptionDomain = QLatin1Char('!') + domain; return (! containsTLDEntry(exceptionDomain)); } } From a2f6ece27f95eb7cb9940af6ba734d4ba52bf4cb Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Fri, 9 Oct 2015 11:13:27 +0200 Subject: [PATCH 220/240] QLockFile: fix errno handling In case of a lock failure, we potentially pollute the errno value before printing it. Also, switch to qt_error_string, as strerror is not reentrant. Change-Id: I952aac14204637155726bcefc0ed8a21d7fcd501 Reviewed-by: David Faure --- src/corelib/io/qlockfile_unix.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 5ff4b1cbe1..bd9f8a5988 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -171,8 +171,10 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() } } // Ensure nobody else can delete the file while we have it - if (!setNativeLocks(fd)) - qWarning() << "setNativeLocks failed:" << strerror(errno); + if (!setNativeLocks(fd)) { + const int errnoSaved = errno; + qWarning() << "setNativeLocks failed:" << qt_error_string(errnoSaved); + } if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) { close(fd); From a623fe8d2a60ff333d5779f877e3b20f0e141ff1 Mon Sep 17 00:00:00 2001 From: Juha Turunen Date: Sun, 11 Oct 2015 20:29:51 -0700 Subject: [PATCH 221/240] Fixed a QTimer::singleShot() crash when a functor callback is used If QTimer::singleShot() is used with a functor callback and a context object with different thread affinity than the caller, a crash can occur. If the context object's thread is scheduled before connecting to QCoreApplication::aboutToQuit(), the timer has a change to fire and QSingleShotTimer::timerEvent() will delete the QSingleShotTimer object making the this pointer used in the connection invalid. This can occur relatively often if an interval of 0 is used. Making the moveToThread() call the last thing in the constructor ensures that the constructor gets to run to completion before the timer has a chance to fire. Task-number: QTBUG-48700 Change-Id: Iab73d02933635821b8d1ca1ff3d53e92eca85834 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qtimer.cpp | 9 ++----- .../auto/corelib/kernel/qtimer/tst_qtimer.cpp | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index b9109a96aa..af9a1be6ab 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -278,15 +278,10 @@ QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObj { timerId = startTimer(msec, timerType); if (r && thread() != r->thread()) { - // We need the invocation to happen in the receiver object's thread. - // So, move QSingleShotTimer to the correct thread. Before that occurs, we - // shall remove the parent from the object. + // Avoid leaking the QSingleShotTimer instance in case the application exits before the timer fires + connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); setParent(0); moveToThread(r->thread()); - - // Given we're also parentless now, we should take defence against leaks - // in case the application quits before we expire. - connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); } } diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index 1dc358bd97..b34a3a6beb 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -72,6 +72,7 @@ private slots: void singleShotStaticFunctionZeroTimeout(); void recurseOnTimeoutAndStopTimer(); void singleShotToFunctors(); + void crossThreadSingleShotToFunctor(); void dontBlockEvents(); void postedEventsShouldNotStarveTimers(); @@ -877,5 +878,28 @@ void tst_QTimer::postedEventsShouldNotStarveTimers() QVERIFY(timerHelper.count > 5); } +struct DummyFunctor { + void operator()() {} +}; + +void tst_QTimer::crossThreadSingleShotToFunctor() +{ + // We're testing for crashes here, so the test simply running to + // completion is considered a success + QThread t; + t.start(); + + QObject* o = new QObject(); + o->moveToThread(&t); + + for (int i = 0; i < 10000; i++) { + QTimer::singleShot(0, o, DummyFunctor()); + } + + t.quit(); + t.wait(); + delete o; +} + QTEST_MAIN(tst_QTimer) #include "tst_qtimer.moc" From 676edc006e9f439d839fd77c0cce1a2e7f064359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 4 Sep 2015 22:50:11 +0200 Subject: [PATCH 222/240] OS X: Forward key events to popup window if present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On OS X we don't treat popup windows as worthy of being activated and focus windows (key windows). Instead we keep track of the active popup windows and forward events to them manually. The forwarding logic is split between QPA, which handles mouse, and QWidgetWindow and QQuickWindowPrivate, which handles key events. This commit adds the logic for key events to QPA, which is the right platform layer for this kind of workarounds. The widget code is left as is for now, and the QQuickWindowPrivate code can be removed in a follow up. Task-number: QTBUG-39415 Change-Id: Iee411fcba9fc81ddcc3a7bc82591184675a6d7a2 Reviewed-by: Gabriel de Dietrich Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 24ee26ce46..8c22e51fe2 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1441,12 +1441,17 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) if (!(modifiers & (Qt::ControlModifier | Qt::MetaModifier)) && (ch.unicode() < 0xf700 || ch.unicode() > 0xf8ff)) text = QCFString::toQString(characters); - QWindow *focusWindow = [self topLevelWindow]; + QWindow *window = [self topLevelWindow]; + + // Popups implicitly grab key events; forward to the active popup if there is one. + // This allows popups to e.g. intercept shortcuts and close the popup in response. + if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) + window = popup->window(); if (eventType == QEvent::KeyPress) { if (m_composingText.isEmpty()) { - m_sendKeyEvent = !QWindowSystemInterface::handleShortcutEvent(focusWindow, timestamp, keyCode, + m_sendKeyEvent = !QWindowSystemInterface::handleShortcutEvent(window, timestamp, keyCode, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1); } @@ -1469,7 +1474,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) } if (m_sendKeyEvent && m_composingText.isEmpty()) - QWindowSystemInterface::handleExtendedKeyEvent(focusWindow, timestamp, QEvent::Type(eventType), keyCode, modifiers, + QWindowSystemInterface::handleExtendedKeyEvent(window, timestamp, QEvent::Type(eventType), keyCode, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1, false); m_sendKeyEvent = false; From 0872156559dd290e8e940d22a89cb95a46ef0cf6 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Sat, 10 Oct 2015 19:49:41 +0300 Subject: [PATCH 223/240] QAbstractSocket: fix writing to socket in HostLookup state After calling connectToHost(), the socket enters HostLookup state. At this stage, the socket engine was not created yet, and writing to the socket should result in either data buffering or an error. So, add a check for d->socketEngine to prevent a crash on unbuffered sockets. Task-number: QTBUG-48356 Change-Id: I15ea9ce7de97ce6d7e13e358eca5350745b556bb Reviewed-by: Oswald Buddenhagen Reviewed-by: Richard J. Moore --- src/network/socket/qabstractsocket.cpp | 9 +++++---- .../network/socket/qudpsocket/tst_qudpsocket.cpp | 13 +++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index d93150799c..5b1c5fa601 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -2456,13 +2456,15 @@ qint64 QAbstractSocket::readLineData(char *data, qint64 maxlen) qint64 QAbstractSocket::writeData(const char *data, qint64 size) { Q_D(QAbstractSocket); - if (d->state == QAbstractSocket::UnconnectedState) { + if (d->state == QAbstractSocket::UnconnectedState + || (!d->socketEngine && d->socketType != TcpSocket && !d->isBuffered)) { d->socketError = QAbstractSocket::UnknownSocketError; setErrorString(tr("Socket is not connected")); return -1; } - if (!d->isBuffered && d->socketType == TcpSocket && d->writeBuffer.isEmpty()) { + if (!d->isBuffered && d->socketType == TcpSocket + && d->socketEngine && d->writeBuffer.isEmpty()) { // This code is for the new Unbuffered QTcpSocket use case qint64 written = d->socketEngine->write(data, size); if (written < 0) { @@ -2473,8 +2475,7 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) // Buffer what was not written yet char *ptr = d->writeBuffer.reserve(size - written); memcpy(ptr, data + written, size - written); - if (d->socketEngine) - d->socketEngine->setWriteNotificationEnabled(true); + d->socketEngine->setWriteNotificationEnabled(true); } return size; // size=actually written + what has been buffered } else if (!d->isBuffered && d->socketType != TcpSocket) { diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index a4695955af..6f96e6d6f5 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -117,6 +117,7 @@ private slots: void readyRead(); void readyReadForEmptyDatagram(); void asyncReadDatagram(); + void writeInHostLookupState(); protected slots: void empty_readyReadSlot(); @@ -1725,5 +1726,17 @@ void tst_QUdpSocket::asyncReadDatagram() delete m_asyncReceiver; } +void tst_QUdpSocket::writeInHostLookupState() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + QUdpSocket socket; + socket.connectToHost("nosuchserver.qt-project.org", 80); + QCOMPARE(socket.state(), QUdpSocket::HostLookupState); + QVERIFY(!socket.putChar('0')); +} + QTEST_MAIN(tst_QUdpSocket) #include "tst_qudpsocket.moc" From a7297ed85bc58a1f242b49a643e3abbdc7cf7e24 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Mon, 12 Oct 2015 12:30:35 +0200 Subject: [PATCH 224/240] Fix gstreamer configuration test. Don't use gst_is_initialized(). It was added in 0.10.31, but we don't actually require that version. Change-Id: If5d662e18511cf636861bf93eeccc1f5b69e26f1 Reviewed-by: Christian Stromme --- config.tests/unix/gstreamer/gstreamer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/config.tests/unix/gstreamer/gstreamer.cpp b/config.tests/unix/gstreamer/gstreamer.cpp index cc61498787..ae8200f093 100644 --- a/config.tests/unix/gstreamer/gstreamer.cpp +++ b/config.tests/unix/gstreamer/gstreamer.cpp @@ -37,6 +37,5 @@ int main(int, char**) { - gst_is_initialized(); return 0; } From 72d0c62d1420ddc69accdb6f7e70fe0e72bd507e Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 21 Sep 2015 20:40:13 +0200 Subject: [PATCH 225/240] WinRT: Fix native MessageBox not closing The message box buttons need to be added inside the XAML thread. Otherwise QWinRTMessageDialogHelper::onCompleted will not be triggered. To successfully emit the clicked signal across different threads do not exit the eventloop. Change-Id: Ie884bdfe0dc64132559755083dae50c2aa43d80b Task-number: QTBUG-48209 Reviewed-by: Oliver Wolff --- .../winrt/qwinrtmessagedialoghelper.cpp | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp index 68bf1fdcac..bb04144563 100644 --- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp +++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp @@ -133,45 +133,46 @@ bool QWinRTMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModa RETURN_FALSE_IF_FAILED("Failed to create dialog"); } - // Add Buttons - ComPtr> dialogCommands; - hr = dialog->get_Commands(&dialogCommands); - RETURN_FALSE_IF_FAILED("Failed to get dialog commands"); - - // If no button is specified we need to create one to get close notification - int buttons = options->standardButtons(); - if (buttons == 0) - buttons = Ok; - - for (int i = FirstButton; i < LastButton; i<<=1) { - if (!(buttons & i)) - continue; - // Add native command - const QString label = d->theme->standardButtonText(i); - HStringReference nativeLabel(reinterpret_cast(label.utf16()), label.size()); - ComPtr command; - hr = commandFactory->Create(nativeLabel.Get(), &command); - RETURN_FALSE_IF_FAILED("Failed to create message box command"); - ComPtr id = Make(static_cast(i)); - hr = command->put_Id(id.Get()); - RETURN_FALSE_IF_FAILED("Failed to set command ID"); - hr = dialogCommands->Append(command.Get()); - if (hr == E_BOUNDS) { - qErrnoWarning(hr, "The WinRT message dialog supports a maximum of three buttons"); - continue; - } - RETURN_FALSE_IF_FAILED("Failed to append message box command"); - if (i == Abort || i == Cancel || i == Close) { - quint32 size; - hr = dialogCommands->get_Size(&size); - RETURN_FALSE_IF_FAILED("Failed to get command list size"); - hr = dialog->put_CancelCommandIndex(size - 1); - RETURN_FALSE_IF_FAILED("Failed to set cancel index"); - } - } - - hr = QEventDispatcherWinRT::runOnXamlThread([this, d, dialog]() { + hr = QEventDispatcherWinRT::runOnXamlThread([this, d, options, commandFactory, dialog]() { HRESULT hr; + + // Add Buttons + ComPtr> dialogCommands; + hr = dialog->get_Commands(&dialogCommands); + RETURN_HR_IF_FAILED("Failed to get dialog commands"); + + // If no button is specified we need to create one to get close notification + int buttons = options->standardButtons(); + if (buttons == 0) + buttons = Ok; + + for (int i = FirstButton; i < LastButton; i<<=1) { + if (!(buttons & i)) + continue; + // Add native command + const QString label = d->theme->standardButtonText(i); + HStringReference nativeLabel(reinterpret_cast(label.utf16()), label.size()); + ComPtr command; + hr = commandFactory->Create(nativeLabel.Get(), &command); + RETURN_HR_IF_FAILED("Failed to create message box command"); + ComPtr id = Make(static_cast(i)); + hr = command->put_Id(id.Get()); + RETURN_HR_IF_FAILED("Failed to set command ID"); + hr = dialogCommands->Append(command.Get()); + if (hr == E_BOUNDS) { + qErrnoWarning(hr, "The WinRT message dialog supports a maximum of three buttons"); + continue; + } + RETURN_HR_IF_FAILED("Failed to append message box command"); + if (i == Abort || i == Cancel || i == Close) { + quint32 size; + hr = dialogCommands->get_Size(&size); + RETURN_HR_IF_FAILED("Failed to get command list size"); + hr = dialog->put_CancelCommandIndex(size - 1); + RETURN_HR_IF_FAILED("Failed to set cancel index"); + } + } + ComPtr> op; hr = dialog->ShowAsync(&op); RETURN_HR_IF_FAILED("Failed to show dialog"); @@ -206,8 +207,7 @@ HRESULT QWinRTMessageDialogHelper::onCompleted(IAsyncOperation *as Q_UNUSED(status); Q_D(QWinRTMessageDialogHelper); - if (d->loop.isRunning()) - d->loop.exit(); + QEventLoopLocker locker(&d->loop); d->shown = false; From 798128856c83f2542af166de0083ed46bcd70704 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 Oct 2015 09:00:55 +0200 Subject: [PATCH 226/240] qdoc: Fix single-character string literals. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use character literals where applicable. Change-Id: I7011ae6ee55107b4788cc434e0dc3618c4213799 Reviewed-by: Topi Reiniö --- src/tools/qdoc/config.cpp | 6 +++--- src/tools/qdoc/cppcodemarker.cpp | 2 +- src/tools/qdoc/cppcodeparser.cpp | 2 +- src/tools/qdoc/generator.cpp | 6 +++--- src/tools/qdoc/htmlgenerator.cpp | 18 +++++++++--------- src/tools/qdoc/node.h | 2 +- src/tools/qdoc/puredocparser.cpp | 2 +- src/tools/qdoc/qdocdatabase.cpp | 8 ++++---- src/tools/qdoc/qdocindexfiles.cpp | 24 ++++++++++++------------ src/tools/qdoc/qmlvisitor.cpp | 2 +- 10 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/tools/qdoc/config.cpp b/src/tools/qdoc/config.cpp index ae6bbaf5da..6c47b86d22 100644 --- a/src/tools/qdoc/config.cpp +++ b/src/tools/qdoc/config.cpp @@ -493,7 +493,7 @@ QStringList Config::getCanonicalPathList(const QString& var, bool validate) cons QDir dir(sl[i].simplified()); QString path = dir.path(); if (dir.isRelative()) - dir.setPath(d + "/" + path); + dir.setPath(d + QLatin1Char('/') + path); if (validate && !QFileInfo::exists(dir.path())) lastLocation_.warning(tr("Cannot find file or directory: %1").arg(path)); else @@ -889,7 +889,7 @@ QStringList Config::loadMaster(const QString& fileName) if (!fin.open(QFile::ReadOnly | QFile::Text)) { if (!Config::installDir.isEmpty()) { int prefix = location.filePath().length() - location.fileName().length(); - fin.setFileName(Config::installDir + "/" + fileName.right(fileName.length() - prefix)); + fin.setFileName(Config::installDir + QLatin1Char('/') + fileName.right(fileName.length() - prefix)); } if (!fin.open(QFile::ReadOnly | QFile::Text)) location.fatal(tr("Cannot open master qdocconf file '%1': %2").arg(fileName).arg(fin.errorString())); @@ -945,7 +945,7 @@ void Config::load(Location location, const QString& fileName) if (!fin.open(QFile::ReadOnly | QFile::Text)) { if (!Config::installDir.isEmpty()) { int prefix = location.filePath().length() - location.fileName().length(); - fin.setFileName(Config::installDir + "/" + fileName.right(fileName.length() - prefix)); + fin.setFileName(Config::installDir + QLatin1Char('/') + fileName.right(fileName.length() - prefix)); } if (!fin.open(QFile::ReadOnly | QFile::Text)) location.fatal(tr("Cannot open file '%1': %2").arg(fileName).arg(fin.errorString())); diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index 3b38745b70..e299eae434 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -154,7 +154,7 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, synopsis = typified(func->returnType()) + QLatin1Char(' '); synopsis += name; if (func->metaness() != FunctionNode::MacroWithoutParams) { - synopsis += "("; + synopsis += QLatin1Char('('); if (!func->parameters().isEmpty()) { QVector::ConstIterator p = func->parameters().constBegin(); while (p != func->parameters().constEnd()) { diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index 5d2a2c90d0..f20b998cc4 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -2321,7 +2321,7 @@ bool CppCodeParser::matchDocsAndStuff() QString topics; QSet::ConstIterator t = topicCommandsUsed.constBegin(); while (t != topicCommandsUsed.constEnd()) { - topics += " \\" + *t + ","; + topics += " \\" + *t + QLatin1Char(','); ++t; } topics[topics.lastIndexOf(',')] = '.'; diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index 5037d95640..3ce5bf99d0 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -1500,7 +1500,7 @@ void Generator::generateOverloadedSignal(const Node* node, CodeMarker* marker) // We have an overloaded signal, show an example QString code = "connect(" + objectName + ", static_cast<" + func->returnType() - + "(" + func->parent()->name() + "::*)("; + + QLatin1Char('(') + func->parent()->name() + "::*)("; for (int i = 0; i < func->parameters().size(); ++i) { if (i != 0) code += ", "; @@ -1508,7 +1508,7 @@ void Generator::generateOverloadedSignal(const Node* node, CodeMarker* marker) code += p.dataType() + p.rightType(); } - code += ")"; + code += QLatin1Char(')'); if (func->isConst()) code += " const"; code += ">(&" + func->parent()->name() + "::" + func->name() + "),\n [=]("; @@ -1519,7 +1519,7 @@ void Generator::generateOverloadedSignal(const Node* node, CodeMarker* marker) const Parameter &p = func->parameters().at(i); code += p.dataType(); if (code[code.size()-1].isLetterOrNumber()) - code += " "; + code += QLatin1Char(' '); code += p.name() + p.rightType(); } diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 5b2039764a..90f8ab2046 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -1191,7 +1191,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark if (unit < 3) { out() << "id=\"" << Doc::canonicalTitle(Text::sectionHeading(atom).toString()) << "\""; } - out() << ">"; + out() << '>'; inSectionHeading_ = true; break; } @@ -1228,18 +1228,18 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark if (!p1.isEmpty()) { if (p1 == QLatin1String("borderless")) attr = p1; - else if (p1.contains("%")) + else if (p1.contains(QLatin1Char('%'))) width = p1; } if (!p2.isEmpty()) { if (p2 == QLatin1String("borderless")) attr = p2; - else if (p2.contains("%")) + else if (p2.contains(QLatin1Char('%'))) width = p2; } - out() << "
\n "; numTableRows_ = 0; } @@ -1288,7 +1288,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark out() << p; } else { - QStringList spans = p.split(","); + QStringList spans = p.split(QLatin1Char(',')); if (spans.size() == 2) { if (spans.at(0) != "1") out() << " colspan=\"" << spans.at(0) << '"'; @@ -2216,7 +2216,7 @@ void HtmlGenerator::generateRequisites(Aggregate *inner, CodeMarker *marker) out() << "" << "
" << *i << ":" - << " "; + " "; if (*i == headerText) out() << requisites.value(*i).toString(); @@ -2262,7 +2262,7 @@ void HtmlGenerator::generateQmlRequisites(QmlTypeNode *qcn, CodeMarker *marker) else logicalModuleVersion = qcn->logicalModuleVersion(); text.clear(); - text << "import " + qcn->logicalModuleName() + " " + logicalModuleVersion; + text << "import " + qcn->logicalModuleName() + QLatin1Char(' ') + logicalModuleVersion; requisites.insert(importText, text); //add the since and project into the map @@ -3820,7 +3820,7 @@ QString HtmlGenerator::getAutoLink(const Atom *atom, const Node *relative, const int hashtag = link.lastIndexOf(QChar('#')); if (hashtag != -1) link.truncate(hashtag); - link += "#" + ref; + link += QLatin1Char('#') + ref; } return link; } diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index 6262cee0ab..6b1032805f 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -1134,7 +1134,7 @@ class CollectionNode : public Aggregate virtual QString logicalModuleName() const Q_DECL_OVERRIDE { return logicalModuleName_; } virtual QString logicalModuleVersion() const Q_DECL_OVERRIDE { - return logicalModuleVersionMajor_ + "." + logicalModuleVersionMinor_; + return logicalModuleVersionMajor_ + QLatin1Char('.') + logicalModuleVersionMinor_; } virtual QString logicalModuleIdentifier() const Q_DECL_OVERRIDE { return logicalModuleName_ + logicalModuleVersionMajor_; diff --git a/src/tools/qdoc/puredocparser.cpp b/src/tools/qdoc/puredocparser.cpp index 80a7ec4bf5..b47f1fc453 100644 --- a/src/tools/qdoc/puredocparser.cpp +++ b/src/tools/qdoc/puredocparser.cpp @@ -173,7 +173,7 @@ bool PureDocParser::processQdocComments() QString topics; QSet::ConstIterator t = topicCommandsUsed.constBegin(); while (t != topicCommandsUsed.constEnd()) { - topics += " \\" + *t + ","; + topics += " \\" + *t + QLatin1Char(','); ++t; } topics[topics.lastIndexOf(',')] = '.'; diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index acd11ff20b..28373bd3b5 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -340,10 +340,10 @@ void QDocForest::printLinkCounts(const QString& project) while (i != m.end()) { QString line = " " + i.value(); if (i.value() != module) - depends += " " + i.value(); + depends += QLatin1Char(' ') + i.value(); int pad = 30 - line.length(); for (int k=0; k& counts) if (i.value() != module) { counts.append(-(i.key())); strings.append(i.value()); - depends += " " + i.value(); + depends += QLatin1Char(' ') + i.value(); } ++i; } @@ -1674,7 +1674,7 @@ const Node* QDocDatabase::findNodeForAtom(const Atom* a, const Node* relative, Q const Node* node = 0; Atom* atom = const_cast(a); - QStringList targetPath = atom->string().split("#"); + QStringList targetPath = atom->string().split(QLatin1Char('#')); QString first = targetPath.first().trimmed(); if (Generator::debugging()) qDebug() << " first:" << first; diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index fdc42316cb..292a4de021 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -660,7 +660,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, QString groupsAttr = attributes.value(QLatin1String("groups")).toString(); if (!groupsAttr.isEmpty()) { - QStringList groupNames = groupsAttr.split(","); + QStringList groupNames = groupsAttr.split(QLatin1Char(',')); foreach (const QString &name, groupNames) { qdb_->addToGroup(name, node); } @@ -1029,11 +1029,11 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, baseStrings.insert(n->fullName()); } if (!baseStrings.isEmpty()) - writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(",")); + writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(QLatin1Char(','))); if (!node->physicalModuleName().isEmpty()) writer.writeAttribute("module", node->physicalModuleName()); if (!classNode->groupNames().isEmpty()) - writer.writeAttribute("groups", classNode->groupNames().join(",")); + writer.writeAttribute("groups", classNode->groupNames().join(QLatin1Char(','))); if (!brief.isEmpty()) writer.writeAttribute("brief", brief); } @@ -1044,7 +1044,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, if (!namespaceNode->physicalModuleName().isEmpty()) writer.writeAttribute("module", namespaceNode->physicalModuleName()); if (!namespaceNode->groupNames().isEmpty()) - writer.writeAttribute("groups", namespaceNode->groupNames().join(",")); + writer.writeAttribute("groups", namespaceNode->groupNames().join(QLatin1Char(','))); if (!brief.isEmpty()) writer.writeAttribute("brief", brief); } @@ -1056,7 +1056,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, writer.writeAttribute("fulltitle", qcn->fullTitle()); writer.writeAttribute("subtitle", qcn->subTitle()); if (!qcn->groupNames().isEmpty()) - writer.writeAttribute("groups", qcn->groupNames().join(",")); + writer.writeAttribute("groups", qcn->groupNames().join(QLatin1Char(','))); if (!brief.isEmpty()) writer.writeAttribute("brief", brief); } @@ -1098,7 +1098,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, writer.writeAttribute("module", node->physicalModuleName()); } if (!docNode->groupNames().isEmpty()) - writer.writeAttribute("groups", docNode->groupNames().join(",")); + writer.writeAttribute("groups", docNode->groupNames().join(QLatin1Char(','))); if (!brief.isEmpty()) writer.writeAttribute("brief", brief); } @@ -1113,7 +1113,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, if (!cn->physicalModuleName().isEmpty()) writer.writeAttribute("module", cn->physicalModuleName()); if (!cn->groupNames().isEmpty()) - writer.writeAttribute("groups", cn->groupNames().join(",")); + writer.writeAttribute("groups", cn->groupNames().join(QLatin1Char(','))); /* This is not read back in, so it probably shouldn't be written out in the first place. @@ -1122,7 +1122,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, QStringList names; foreach (const Node* member, cn->members()) names.append(member->name()); - writer.writeAttribute("members", names.join(",")); + writer.writeAttribute("members", names.join(QLatin1Char(','))); } if (!brief.isEmpty()) writer.writeAttribute("brief", brief); @@ -1138,7 +1138,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, if (!cn->physicalModuleName().isEmpty()) writer.writeAttribute("module", cn->physicalModuleName()); if (!cn->groupNames().isEmpty()) - writer.writeAttribute("groups", cn->groupNames().join(",")); + writer.writeAttribute("groups", cn->groupNames().join(QLatin1Char(','))); /* This is not read back in, so it probably shouldn't be written out in the first place. @@ -1147,7 +1147,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, QStringList names; foreach (const Node* member, cn->members()) names.append(member->name()); - writer.writeAttribute("members", names.join(",")); + writer.writeAttribute("members", names.join(QLatin1Char(','))); } if (!brief.isEmpty()) writer.writeAttribute("brief", brief); @@ -1163,7 +1163,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, if (!cn->physicalModuleName().isEmpty()) writer.writeAttribute("module", cn->physicalModuleName()); if (!cn->groupNames().isEmpty()) - writer.writeAttribute("groups", cn->groupNames().join(",")); + writer.writeAttribute("groups", cn->groupNames().join(QLatin1Char(','))); /* This is not read back in, so it probably shouldn't be written out in the first place. @@ -1172,7 +1172,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, QStringList names; foreach (const Node* member, cn->members()) names.append(member->name()); - writer.writeAttribute("members", names.join(",")); + writer.writeAttribute("members", names.join(QLatin1Char(','))); } if (!brief.isEmpty()) writer.writeAttribute("brief", brief); diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp index 155e1de054..0cb4d84513 100644 --- a/src/tools/qdoc/qmlvisitor.cpp +++ b/src/tools/qdoc/qmlvisitor.cpp @@ -624,7 +624,7 @@ bool QmlDocVisitor::visit(QQmlJS::AST::UiImport *import) QString version = document.mid(import->versionToken.offset, import->versionToken.length); QString importId = document.mid(import->importIdToken.offset, import->importIdToken.length); QString importUri = getFullyQualifiedId(import->importUri); - QString reconstructed = importUri + QString(" ") + version; + QString reconstructed = importUri + QLatin1Char(' ') + version; importList.append(ImportRec(name, version, importId, importUri)); return true; From ee634611d4d78d7ee66b79dc765abab231391eab Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 9 Oct 2015 16:06:36 +0200 Subject: [PATCH 227/240] qdoc: Insert targets for function and enum nodes read from the index QDoc wrote \target and \keyword information into the index file properly, but did not read them back in. This was because the code for handling enum and function elements read their own child elements (without handling targets), and marked the remaining children to be skipped. This commit fixes the issue by refactoring the code for inserting targets into a new function and calling it from relevant places. Change-Id: I85d7b26ce54620daec35b19e447d1a065515b863 Task-number: QTBUG-48687 Reviewed-by: Martin Smith --- src/tools/qdoc/qdocindexfiles.cpp | 46 +++++++++++++++++++++++++------ src/tools/qdoc/qdocindexfiles.h | 3 ++ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index 292a4de021..ef86d782c7 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -463,10 +463,15 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, location = Location(parent->name().toLower() + ".html"); while (reader.readNextStartElement()) { + QXmlStreamAttributes childAttributes = reader.attributes(); if (reader.name() == QLatin1String("value")) { - QXmlStreamAttributes childAttributes = reader.attributes(); + EnumItem item(childAttributes.value(QLatin1String("name")).toString(), childAttributes.value(QLatin1String("value")).toString()); enumNode->addItem(item); + } else if (reader.name() == QLatin1String("keyword")) { + insertTarget(TargetRec::Keyword, childAttributes, enumNode); + } else if (reader.name() == QLatin1String("target")) { + insertTarget(TargetRec::Target, childAttributes, enumNode); } reader.skipCurrentElement(); } @@ -552,8 +557,8 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, */ while (reader.readNextStartElement()) { + QXmlStreamAttributes childAttributes = reader.attributes(); if (reader.name() == QLatin1String("parameter")) { - QXmlStreamAttributes childAttributes = reader.attributes(); // Do not use the default value for the parameter; it is not // required, and has been known to cause problems. Parameter parameter(childAttributes.value(QLatin1String("left")).toString(), @@ -561,6 +566,10 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, childAttributes.value(QLatin1String("name")).toString(), QString()); // childAttributes.value(QLatin1String("default")) functionNode->addParameter(parameter); + } else if (reader.name() == QLatin1String("keyword")) { + insertTarget(TargetRec::Keyword, childAttributes, functionNode); + } else if (reader.name() == QLatin1String("target")) { + insertTarget(TargetRec::Target, childAttributes, functionNode); } reader.skipCurrentElement(); } @@ -581,18 +590,15 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, location = Location(parent->name().toLower() + ".html"); } else if (elementName == QLatin1String("keyword")) { - QString title = attributes.value(QLatin1String("title")).toString(); - qdb_->insertTarget(name, title, TargetRec::Keyword, current, 1); + insertTarget(TargetRec::Keyword, attributes, current); goto done; } else if (elementName == QLatin1String("target")) { - QString title = attributes.value(QLatin1String("title")).toString(); - qdb_->insertTarget(name, title, TargetRec::Target, current, 2); + insertTarget(TargetRec::Target, attributes, current); goto done; } else if (elementName == QLatin1String("contents")) { - QString title = attributes.value(QLatin1String("title")).toString(); - qdb_->insertTarget(name, title, TargetRec::Contents, current, 3); + insertTarget(TargetRec::Contents, attributes, current); goto done; } else @@ -702,6 +708,30 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader& reader, } } +void QDocIndexFiles::insertTarget(TargetRec::TargetType type, + const QXmlStreamAttributes &attributes, + Node *node) +{ + int priority; + switch (type) { + case TargetRec::Keyword: + priority = 1; + break; + case TargetRec::Target: + priority = 2; + break; + case TargetRec::Contents: + priority = 3; + break; + default: + return; + } + + QString name = attributes.value(QLatin1String("name")).toString(); + QString title = attributes.value(QLatin1String("title")).toString(); + qdb_->insertTarget(name, title, type, node, priority); +} + /*! This function tries to resolve class inheritance immediately after the index file is read. It is not always possible to diff --git a/src/tools/qdoc/qdocindexfiles.h b/src/tools/qdoc/qdocindexfiles.h index 67a7e7226e..9873322b3b 100644 --- a/src/tools/qdoc/qdocindexfiles.h +++ b/src/tools/qdoc/qdocindexfiles.h @@ -35,6 +35,7 @@ #define QDOCINDEXFILES_H #include "node.h" +#include "tree.h" QT_BEGIN_NAMESPACE @@ -43,6 +44,7 @@ class Generator; class QStringList; class QDocDatabase; class QXmlStreamWriter; +class QXmlStreamAttributes; class QDocIndexFiles { @@ -64,6 +66,7 @@ class QDocIndexFiles void readIndexFile(const QString& path); void readIndexSection(QXmlStreamReader &reader, Node* current, const QString& indexUrl); + void insertTarget(TargetRec::TargetType type, const QXmlStreamAttributes &attributes, Node *node); void resolveIndex(); void resolveRelates(); bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false); From dab4877a0a6ad755483a8e47205112a247058fef Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 7 Oct 2015 12:07:22 +0200 Subject: [PATCH 228/240] qdoc: Improve formatting of function signatures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a continuation of the work started in commit 694d30035593addc377fea374d1dbe8e3f5ca503. Attach reference ('&') and pointer ('*') qualifiers to the parameter name, as per Qt coding style. Previously, function signatures were documented like this: QString & QString::append(const QString & str) After this change, they will appear like this: QString &QString::append(const QString &str) Change-Id: Ie103fc2929635bc32145e50469c600f9f378f97c Reviewed-by: Tor Arne Vestbø Reviewed-by: Martin Smith --- src/tools/qdoc/codemarker.cpp | 7 ++++++- src/tools/qdoc/codemarker.h | 2 +- src/tools/qdoc/cppcodemarker.cpp | 18 +++++++----------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/tools/qdoc/codemarker.cpp b/src/tools/qdoc/codemarker.cpp index 458799fc27..a668205a66 100644 --- a/src/tools/qdoc/codemarker.cpp +++ b/src/tools/qdoc/codemarker.cpp @@ -210,7 +210,7 @@ void CodeMarker::appendProtectedString(QString *output, const QStringRef &str) } } -QString CodeMarker::typified(const QString &string) +QString CodeMarker::typified(const QString &string, bool trailingSpace) { QString result; QString pendingWord; @@ -254,6 +254,11 @@ QString CodeMarker::typified(const QString &string) } } } + if (trailingSpace && string.size()) { + if (!string.endsWith(QLatin1Char('*')) + && !string.endsWith(QLatin1Char('&'))) + result += QLatin1Char(' '); + } return result; } diff --git a/src/tools/qdoc/codemarker.h b/src/tools/qdoc/codemarker.h index 31a9f3a254..011c8623dd 100644 --- a/src/tools/qdoc/codemarker.h +++ b/src/tools/qdoc/codemarker.h @@ -159,7 +159,7 @@ public: static const Node *nodeForString(const QString& string); static QString stringForNode(const Node *node); - QString typified(const QString &string); + QString typified(const QString &string, bool trailingSpace = false); protected: virtual QString sortName(const Node *node, const QString* name = 0); diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index e299eae434..01ff827d58 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -150,8 +150,9 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, case Node::QmlSignalHandler: case Node::QmlMethod: func = (const FunctionNode *) node; + if (style != Subpage && !func->returnType().isEmpty()) - synopsis = typified(func->returnType()) + QLatin1Char(' '); + synopsis = typified(func->returnType(), true); synopsis += name; if (func->metaness() != FunctionNode::MacroWithoutParams) { synopsis += QLatin1Char('('); @@ -160,9 +161,7 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, while (p != func->parameters().constEnd()) { if (p != func->parameters().constBegin()) synopsis += ", "; - synopsis += typified((*p).dataType()); - if (!(*p).dataType().isEmpty()) - synopsis += QLatin1Char(' '); + synopsis += typified((*p).dataType(), true); if (style != Subpage && !(*p).name().isEmpty()) synopsis += "<@param>" + protect((*p).name()) + ""; @@ -273,7 +272,7 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, synopsis = name + " : " + typified(variable->dataType()); } else { - synopsis = typified(variable->leftType()) + QLatin1Char(' ') + + synopsis = typified(variable->leftType(), true) + name + protect(variable->rightType()); } break; @@ -323,7 +322,7 @@ QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary) (node->type() == Node::QmlSignalHandler)) { const FunctionNode* func = static_cast(node); if (!func->returnType().isEmpty()) - synopsis = typified(func->returnType()) + QLatin1Char(' ') + name; + synopsis = typified(func->returnType(), true) + name; else synopsis = name; synopsis += QLatin1Char('('); @@ -332,12 +331,9 @@ QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary) while (p != func->parameters().constEnd()) { if (p != func->parameters().constBegin()) synopsis += ", "; - synopsis += typified((*p).dataType()); - if (!(*p).name().isEmpty()) { - if (!(*p).dataType().isEmpty()) - synopsis += QLatin1Char(' '); + synopsis += typified((*p).dataType(), true); + if (!(*p).name().isEmpty()) synopsis += "<@param>" + protect((*p).name()) + ""; - } synopsis += protect((*p).rightType()); ++p; } From f9bf737d74c2493f7a535048cb4992d3e4cd3c99 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 Oct 2015 09:06:58 +0200 Subject: [PATCH 229/240] Examples/Doc snippets: Fix single-character string literals. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use character literals where applicable. Change-Id: I79fa5018f05735201ae35ee94ba0d356fcad1056 Reviewed-by: Topi Reiniö --- examples/embedded/digiflip/digiflip.cpp | 2 +- examples/network/torrent/filemanager.cpp | 12 +++--- examples/network/torrent/metainfo.cpp | 2 +- examples/opengl/contextinfo/widget.cpp | 2 +- examples/qtconcurrent/wordcount/main.cpp | 8 ++-- examples/sql/masterdetail/dialog.cpp | 2 +- examples/sql/querymodel/customsqlmodel.cpp | 2 +- .../dialogs/classwizard/classwizard.cpp | 38 +++++++++---------- .../gestures/imagegestures/imagewidget.cpp | 10 ++--- examples/widgets/graphicsview/boxes/scene.cpp | 4 +- .../widgets/itemviews/chart/mainwindow.cpp | 2 +- .../itemviews/editabletreemodel/treemodel.cpp | 2 +- .../widgets/itemviews/frozencolumn/main.cpp | 6 +-- .../widgets/itemviews/interview/model.cpp | 2 +- .../itemviews/simpledommodel/dommodel.cpp | 2 +- .../itemviews/simpletreemodel/treemodel.cpp | 2 +- .../widgets/tools/regexp/regexpdialog.cpp | 4 +- .../regularexpressiondialog.cpp | 4 +- .../tools/settingseditor/variantdelegate.cpp | 4 +- .../addressbook/part7/addressbook.cpp | 16 ++++---- .../tutorials/modelview/5_edit/mymodel.cpp | 2 +- .../widgets/widgets/calculator/calculator.cpp | 2 +- examples/xml/htmlinfo/main.cpp | 2 +- examples/xml/saxbookmarks/xbelgenerator.cpp | 4 +- .../doc/snippets/code/doc_src_containers.cpp | 6 +-- .../snippets/code/src_corelib_tools_qhash.cpp | 6 +-- .../code/src_corelib_tools_qlinkedlist.cpp | 6 +-- .../snippets/code/src_corelib_tools_qmap.cpp | 6 +-- src/corelib/doc/snippets/qstring/main.cpp | 4 +- src/corelib/doc/snippets/qstringlist/main.cpp | 2 +- src/gui/doc/snippets/qfontdatabase/main.cpp | 2 +- .../snippets/code/src_qtestlib_qtestcase.cpp | 2 +- src/xml/doc/snippets/rsslisting/handler.cpp | 2 +- src/xml/doc/snippets/simpleparse/main.cpp | 2 +- 34 files changed, 87 insertions(+), 87 deletions(-) diff --git a/examples/embedded/digiflip/digiflip.cpp b/examples/embedded/digiflip/digiflip.cpp index 3bb3023caf..af4289efb3 100644 --- a/examples/embedded/digiflip/digiflip.cpp +++ b/examples/embedded/digiflip/digiflip.cpp @@ -112,7 +112,7 @@ protected: QString str = QString::number(n); if (str.length() == 1) - str.prepend("0"); + str.prepend('0'); QFont font; font.setFamily("Helvetica"); diff --git a/examples/network/torrent/filemanager.cpp b/examples/network/torrent/filemanager.cpp index b4e921b0a5..58330014cf 100644 --- a/examples/network/torrent/filemanager.cpp +++ b/examples/network/torrent/filemanager.cpp @@ -219,8 +219,8 @@ bool FileManager::generateFiles() QString prefix; if (!destinationPath.isEmpty()) { prefix = destinationPath; - if (!prefix.endsWith("/")) - prefix += "/"; + if (!prefix.endsWith('/')) + prefix += '/'; QDir dir; if (!dir.mkpath(prefix)) { errString = tr("Failed to create directory %1").arg(prefix); @@ -261,13 +261,13 @@ bool FileManager::generateFiles() if (!destinationPath.isEmpty()) { prefix = destinationPath; - if (!prefix.endsWith("/")) - prefix += "/"; + if (!prefix.endsWith('/')) + prefix += '/'; } if (!metaInfo.name().isEmpty()) { prefix += metaInfo.name(); - if (!prefix.endsWith("/")) - prefix += "/"; + if (!prefix.endsWith('/')) + prefix += '/'; } if (!dir.mkpath(prefix)) { errString = tr("Failed to create directory %1").arg(prefix); diff --git a/examples/network/torrent/metainfo.cpp b/examples/network/torrent/metainfo.cpp index cca52c7e7e..52e7afe43a 100644 --- a/examples/network/torrent/metainfo.cpp +++ b/examples/network/torrent/metainfo.cpp @@ -96,7 +96,7 @@ bool MetaInfo::parse(const QByteArray &data) QByteArray path; foreach (QVariant p, pathElements) { if (!path.isEmpty()) - path += "/"; + path += '/'; path += p.toByteArray(); } diff --git a/examples/opengl/contextinfo/widget.cpp b/examples/opengl/contextinfo/widget.cpp index c318accf87..2d36fe4265 100644 --- a/examples/opengl/contextinfo/widget.cpp +++ b/examples/opengl/contextinfo/widget.cpp @@ -299,7 +299,7 @@ void Widget::printFormat(const QSurfaceFormat &format) QString opts; for (size_t i = 0; i < sizeof(options) / sizeof(Option); ++i) if (format.testOption(options[i].option)) - opts += QString::fromLatin1(options[i].str) + QStringLiteral(" "); + opts += QString::fromLatin1(options[i].str) + QLatin1Char(' '); m_output->append(tr("Options: %1").arg(opts)); for (size_t i = 0; i < sizeof(renderables) / sizeof(Renderable); ++i) diff --git a/examples/qtconcurrent/wordcount/main.cpp b/examples/qtconcurrent/wordcount/main.cpp index f45f2820c7..7f6d0f43ba 100644 --- a/examples/qtconcurrent/wordcount/main.cpp +++ b/examples/qtconcurrent/wordcount/main.cpp @@ -61,10 +61,10 @@ QStringList findFiles(const QString &startDir, QStringList filters) QDir dir(startDir); foreach (QString file, dir.entryList(filters, QDir::Files)) - names += startDir + "/" + file; + names += startDir + '/' + file; foreach (QString subdir, dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) - names += findFiles(startDir + "/" + subdir, filters); + names += findFiles(startDir + '/' + subdir, filters); return names; } @@ -81,7 +81,7 @@ WordCount singleThreadedWordCount(QStringList files) f.open(QIODevice::ReadOnly); QTextStream textStream(&f); while (textStream.atEnd() == false) - foreach(QString word, textStream.readLine().split(" ")) + foreach (const QString &word, textStream.readLine().split(' ')) wordCount[word] += 1; } @@ -100,7 +100,7 @@ WordCount countWords(const QString &file) WordCount wordCount; while (textStream.atEnd() == false) - foreach (QString word, textStream.readLine().split(" ")) + foreach (const QString &word, textStream.readLine().split(' ')) wordCount[word] += 1; return wordCount; diff --git a/examples/sql/masterdetail/dialog.cpp b/examples/sql/masterdetail/dialog.cpp index 5518707f58..3171acc448 100644 --- a/examples/sql/masterdetail/dialog.cpp +++ b/examples/sql/masterdetail/dialog.cpp @@ -153,7 +153,7 @@ void Dialog::addTracks(int albumId, QStringList tracks) for (int i = 0; i < tracks.count(); i++) { QString trackNumber = QString::number(i); if (i < 10) - trackNumber.prepend("0"); + trackNumber.prepend('0'); QDomText textNode = albumDetails.createTextNode(tracks.at(i)); diff --git a/examples/sql/querymodel/customsqlmodel.cpp b/examples/sql/querymodel/customsqlmodel.cpp index 5966802abe..4cdfdd6ae3 100644 --- a/examples/sql/querymodel/customsqlmodel.cpp +++ b/examples/sql/querymodel/customsqlmodel.cpp @@ -53,7 +53,7 @@ QVariant CustomSqlModel::data(const QModelIndex &index, int role) const QVariant value = QSqlQueryModel::data(index, role); if (value.isValid() && role == Qt::DisplayRole) { if (index.column() == 0) - return value.toString().prepend("#"); + return value.toString().prepend('#'); else if (index.column() == 2) return value.toString().toUpper(); } diff --git a/examples/widgets/dialogs/classwizard/classwizard.cpp b/examples/widgets/dialogs/classwizard/classwizard.cpp index c913d7b592..d3e366efe6 100644 --- a/examples/widgets/dialogs/classwizard/classwizard.cpp +++ b/examples/widgets/dialogs/classwizard/classwizard.cpp @@ -79,31 +79,31 @@ void ClassWizard::accept() if (field("comment").toBool()) { block += "/*\n"; - block += " " + header.toLatin1() + "\n"; + block += " " + header.toLatin1() + '\n'; block += "*/\n"; - block += "\n"; + block += '\n'; } if (field("protect").toBool()) { - block += "#ifndef " + macroName + "\n"; - block += "#define " + macroName + "\n"; - block += "\n"; + block += "#ifndef " + macroName + '\n'; + block += "#define " + macroName + '\n'; + block += '\n'; } if (field("includeBase").toBool()) { - block += "#include " + baseInclude + "\n"; - block += "\n"; + block += "#include " + baseInclude + '\n'; + block += '\n'; } block += "class " + className; if (!baseClass.isEmpty()) block += " : public " + baseClass; - block += "\n"; + block += '\n'; block += "{\n"; /* qmake ignore Q_OBJECT */ if (field("qobjectMacro").toBool()) { block += " Q_OBJECT\n"; - block += "\n"; + block += '\n'; } block += "public:\n"; @@ -115,7 +115,7 @@ void ClassWizard::accept() block += " " + className + "();\n"; if (field("copyCtor").toBool()) { block += " " + className + "(const " + className + " &other);\n"; - block += "\n"; + block += '\n'; block += " " + className + " &operator=" + "(const " + className + " &other);\n"; } @@ -123,11 +123,11 @@ void ClassWizard::accept() block += "};\n"; if (field("protect").toBool()) { - block += "\n"; + block += '\n'; block += "#endif\n"; } - QFile headerFile(outputDir + "/" + header); + QFile headerFile(outputDir + '/' + header); if (!headerFile.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(0, QObject::tr("Simple Wizard"), QObject::tr("Cannot write file %1:\n%2") @@ -141,12 +141,12 @@ void ClassWizard::accept() if (field("comment").toBool()) { block += "/*\n"; - block += " " + implementation.toLatin1() + "\n"; + block += " " + implementation.toLatin1() + '\n'; block += "*/\n"; - block += "\n"; + block += '\n'; } block += "#include \"" + header.toLatin1() + "\"\n"; - block += "\n"; + block += '\n'; if (field("qobjectCtor").toBool()) { block += className + "::" + className + "(QObject *parent)\n"; @@ -171,7 +171,7 @@ void ClassWizard::accept() block += "{\n"; block += " *this = other;\n"; block += "}\n"; - block += "\n"; + block += '\n'; block += className + " &" + className + "::operator=(const " + className + " &other)\n"; block += "{\n"; @@ -183,7 +183,7 @@ void ClassWizard::accept() } } - QFile implementationFile(outputDir + "/" + implementation); + QFile implementationFile(outputDir + '/' + implementation); if (!implementationFile.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(0, QObject::tr("Simple Wizard"), QObject::tr("Cannot write file %1:\n%2") @@ -356,9 +356,9 @@ void CodeStylePage::initializePage() if (baseClass.isEmpty()) { baseIncludeLineEdit->clear(); } else if (QRegExp("Q[A-Z].*").exactMatch(baseClass)) { - baseIncludeLineEdit->setText("<" + baseClass + ">"); + baseIncludeLineEdit->setText('<' + baseClass + '>'); } else { - baseIncludeLineEdit->setText("\"" + baseClass.toLower() + ".h\""); + baseIncludeLineEdit->setText('"' + baseClass.toLower() + ".h\""); } } //! [16] diff --git a/examples/widgets/gestures/imagegestures/imagewidget.cpp b/examples/widgets/gestures/imagegestures/imagewidget.cpp index 104095e8fe..28c715c688 100644 --- a/examples/widgets/gestures/imagegestures/imagewidget.cpp +++ b/examples/widgets/gestures/imagegestures/imagewidget.cpp @@ -229,7 +229,7 @@ void ImageWidget::goNextImage() prevImage = currentImage; currentImage = nextImage; if (position+1 < files.size()) - nextImage = loadImage(path+QLatin1String("/")+files.at(position+1)); + nextImage = loadImage(path + QLatin1Char('/') + files.at(position+1)); else nextImage = QImage(); } @@ -246,7 +246,7 @@ void ImageWidget::goPrevImage() nextImage = currentImage; currentImage = prevImage; if (position > 0) - prevImage = loadImage(path+QLatin1String("/")+files.at(position-1)); + prevImage = loadImage(path + QLatin1Char('/') + files.at(position-1)); else prevImage = QImage(); } @@ -276,12 +276,12 @@ void ImageWidget::goToImage(int index) position = index; if (index > 0) - prevImage = loadImage(path+QLatin1String("/")+files.at(position-1)); + prevImage = loadImage(path + QLatin1Char('/') + files.at(position-1)); else prevImage = QImage(); - currentImage = loadImage(path+QLatin1String("/")+files.at(position)); + currentImage = loadImage(path + QLatin1Char('/') + files.at(position)); if (position+1 < files.size()) - nextImage = loadImage(path+QLatin1String("/")+files.at(position+1)); + nextImage = loadImage(path + QLatin1Char('/') + files.at(position+1)); else nextImage = QImage(); update(); diff --git a/examples/widgets/graphicsview/boxes/scene.cpp b/examples/widgets/graphicsview/boxes/scene.cpp index 48bdcb9d93..c9691704cb 100644 --- a/examples/widgets/graphicsview/boxes/scene.cpp +++ b/examples/widgets/graphicsview/boxes/scene.cpp @@ -319,9 +319,9 @@ RenderOptionsDialog::RenderOptionsDialog() while (++it != tokens.end()) { m_parameterNames << name; if (!singleElement) { - m_parameterNames.back() += "["; + m_parameterNames.back() += '['; m_parameterNames.back() += counter + counterPos; - m_parameterNames.back() += "]"; + m_parameterNames.back() += ']'; int j = 8; // position of last digit ++counter[j]; while (j > 0 && counter[j] > '9') { diff --git a/examples/widgets/itemviews/chart/mainwindow.cpp b/examples/widgets/itemviews/chart/mainwindow.cpp index 9a3b372233..a148c3036d 100644 --- a/examples/widgets/itemviews/chart/mainwindow.cpp +++ b/examples/widgets/itemviews/chart/mainwindow.cpp @@ -124,7 +124,7 @@ void MainWindow::loadFile(const QString &fileName) if (!line.isEmpty()) { model->insertRows(row, 1, QModelIndex()); - QStringList pieces = line.split(",", QString::SkipEmptyParts); + QStringList pieces = line.split(',', QString::SkipEmptyParts); model->setData(model->index(row, 0, QModelIndex()), pieces.value(0)); model->setData(model->index(row, 1, QModelIndex()), diff --git a/examples/widgets/itemviews/editabletreemodel/treemodel.cpp b/examples/widgets/itemviews/editabletreemodel/treemodel.cpp index 2903dd7d38..2b12c142cd 100644 --- a/examples/widgets/itemviews/editabletreemodel/treemodel.cpp +++ b/examples/widgets/itemviews/editabletreemodel/treemodel.cpp @@ -246,7 +246,7 @@ void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent) while (number < lines.count()) { int position = 0; while (position < lines[number].length()) { - if (lines[number].mid(position, 1) != " ") + if (lines[number].at(position) != ' ') break; ++position; } diff --git a/examples/widgets/itemviews/frozencolumn/main.cpp b/examples/widgets/itemviews/frozencolumn/main.cpp index cfdf57135c..1292a7f403 100644 --- a/examples/widgets/itemviews/frozencolumn/main.cpp +++ b/examples/widgets/itemviews/frozencolumn/main.cpp @@ -54,15 +54,15 @@ int main(int argc, char* argv[]) QFile file(":/grades.txt"); if (file.open(QFile::ReadOnly)) { QString line = file.readLine(200); - QStringList list = line.simplified().split(","); + QStringList list = line.simplified().split(','); model->setHorizontalHeaderLabels(list); int row = 0; QStandardItem *newItem = 0; while (file.canReadLine()) { line = file.readLine(200); - if (!line.startsWith("#") && line.contains(",")) { - list= line.simplified().split(","); + if (!line.startsWith('#') && line.contains(',')) { + list = line.simplified().split(','); for (int col = 0; col < list.length(); ++col){ newItem = new QStandardItem(list.at(col)); model->setItem(row, col, newItem); diff --git a/examples/widgets/itemviews/interview/model.cpp b/examples/widgets/itemviews/interview/model.cpp index ba65144cfa..efbb67486b 100644 --- a/examples/widgets/itemviews/interview/model.cpp +++ b/examples/widgets/itemviews/interview/model.cpp @@ -88,7 +88,7 @@ QVariant Model::data(const QModelIndex &index, int role) const if (!index.isValid()) return QVariant(); if (role == Qt::DisplayRole) - return QVariant("Item " + QString::number(index.row()) + ":" + QString::number(index.column())); + return QVariant("Item " + QString::number(index.row()) + ':' + QString::number(index.column())); if (role == Qt::DecorationRole) { if (index.column() == 0) return iconProvider.icon(QFileIconProvider::Folder); diff --git a/examples/widgets/itemviews/simpledommodel/dommodel.cpp b/examples/widgets/itemviews/simpledommodel/dommodel.cpp index f6450abc8b..531957f60b 100644 --- a/examples/widgets/itemviews/simpledommodel/dommodel.cpp +++ b/examples/widgets/itemviews/simpledommodel/dommodel.cpp @@ -88,7 +88,7 @@ QVariant DomModel::data(const QModelIndex &index, int role) const for (int i = 0; i < attributeMap.count(); ++i) { QDomNode attribute = attributeMap.item(i); attributes << attribute.nodeName() + "=\"" - +attribute.nodeValue() + "\""; + +attribute.nodeValue() + '"'; } return attributes.join(' '); case 2: diff --git a/examples/widgets/itemviews/simpletreemodel/treemodel.cpp b/examples/widgets/itemviews/simpletreemodel/treemodel.cpp index aaa4685b27..f5cd1a160e 100644 --- a/examples/widgets/itemviews/simpletreemodel/treemodel.cpp +++ b/examples/widgets/itemviews/simpletreemodel/treemodel.cpp @@ -180,7 +180,7 @@ void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent) while (number < lines.count()) { int position = 0; while (position < lines[number].length()) { - if (lines[number].mid(position, 1) != " ") + if (lines[number].at(position) != ' ') break; position++; } diff --git a/examples/widgets/tools/regexp/regexpdialog.cpp b/examples/widgets/tools/regexp/regexpdialog.cpp index 32df8a4b91..8ed1e790fb 100644 --- a/examples/widgets/tools/regexp/regexpdialog.cpp +++ b/examples/widgets/tools/regexp/regexpdialog.cpp @@ -153,8 +153,8 @@ void RegExpDialog::refresh() QString escaped = pattern; escaped.replace("\\", "\\\\"); escaped.replace("\"", "\\\""); - escaped.prepend("\""); - escaped.append("\""); + escaped.prepend('"'); + escaped.append('"'); escapedPatternLineEdit->setText(escaped); QRegExp rx(pattern); diff --git a/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp b/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp index d40b4b325d..6cddc1f6c1 100644 --- a/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp +++ b/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp @@ -111,8 +111,8 @@ void RegularExpressionDialog::refresh() QString escaped = pattern; escaped.replace(QLatin1String("\\"), QLatin1String("\\\\")); escaped.replace(QLatin1String("\""), QLatin1String("\\\"")); - escaped.prepend(QLatin1String("\"")); - escaped.append(QLatin1String("\"")); + escaped.prepend(QLatin1Char('"')); + escaped.append(QLatin1Char('"')); escapedPatternLineEdit->setText(escaped); QRegularExpression rx(pattern); diff --git a/examples/widgets/tools/settingseditor/variantdelegate.cpp b/examples/widgets/tools/settingseditor/variantdelegate.cpp index f68082c660..fe2391762b 100644 --- a/examples/widgets/tools/settingseditor/variantdelegate.cpp +++ b/examples/widgets/tools/settingseditor/variantdelegate.cpp @@ -60,7 +60,7 @@ VariantDelegate::VariantDelegate(QObject *parent) dateExp.setPattern("([0-9]{,4})-([0-9]{,2})-([0-9]{,2})"); timeExp.setPattern("([0-9]{,2}):([0-9]{,2}):([0-9]{,2})"); - dateTimeExp.setPattern(dateExp.pattern() + "T" + timeExp.pattern()); + dateTimeExp.setPattern(dateExp.pattern() + 'T' + timeExp.pattern()); } void VariantDelegate::paint(QPainter *painter, @@ -217,7 +217,7 @@ void VariantDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, value = QSize(sizeExp.cap(1).toInt(), sizeExp.cap(2).toInt()); break; case QVariant::StringList: - value = text.split(","); + value = text.split(','); break; case QVariant::Time: { diff --git a/examples/widgets/tutorials/addressbook/part7/addressbook.cpp b/examples/widgets/tutorials/addressbook/part7/addressbook.cpp index 6764423d71..2953ecd7de 100644 --- a/examples/widgets/tutorials/addressbook/part7/addressbook.cpp +++ b/examples/widgets/tutorials/addressbook/part7/addressbook.cpp @@ -421,23 +421,23 @@ void AddressBook::exportAsVCard() //! [export function part2] //! [export function part3] - out << "BEGIN:VCARD" << "\n"; - out << "VERSION:2.1" << "\n"; - out << "N:" << lastName << ";" << firstName << "\n"; + out << "BEGIN:VCARD" << '\n'; + out << "VERSION:2.1" << '\n'; + out << "N:" << lastName << ';' << firstName << '\n'; if (!nameList.isEmpty()) - out << "FN:" << nameList.join(' ') << "\n"; + out << "FN:" << nameList.join(' ') << '\n'; else - out << "FN:" << firstName << "\n"; + out << "FN:" << firstName << '\n'; //! [export function part3] //! [export function part4] address.replace(";", "\\;", Qt::CaseInsensitive); - address.replace("\n", ";", Qt::CaseInsensitive); + address.replace('\n', ";", Qt::CaseInsensitive); address.replace(",", " ", Qt::CaseInsensitive); - out << "ADR;HOME:;" << address << "\n"; - out << "END:VCARD" << "\n"; + out << "ADR;HOME:;" << address << '\n'; + out << "END:VCARD" << '\n'; QMessageBox::information(this, tr("Export Successful"), tr("\"%1\" has been exported as a vCard.").arg(name)); diff --git a/examples/widgets/tutorials/modelview/5_edit/mymodel.cpp b/examples/widgets/tutorials/modelview/5_edit/mymodel.cpp index 5eb677bb9d..c04c77772f 100644 --- a/examples/widgets/tutorials/modelview/5_edit/mymodel.cpp +++ b/examples/widgets/tutorials/modelview/5_edit/mymodel.cpp @@ -83,7 +83,7 @@ bool MyModel::setData(const QModelIndex & index, const QVariant & value, int rol { for(int col= 0; col < COLS; col++) { - result += m_gridData[row][col] + " "; + result += m_gridData[row][col] + ' '; } } emit editCompleted( result ); diff --git a/examples/widgets/widgets/calculator/calculator.cpp b/examples/widgets/widgets/calculator/calculator.cpp index e76011ee0d..87061a9868 100644 --- a/examples/widgets/widgets/calculator/calculator.cpp +++ b/examples/widgets/widgets/calculator/calculator.cpp @@ -276,7 +276,7 @@ void Calculator::pointClicked() { if (waitingForOperand) display->setText("0"); - if (!display->text().contains(".")) + if (!display->text().contains('.')) display->setText(display->text() + tr(".")); waitingForOperand = false; } diff --git a/examples/xml/htmlinfo/main.cpp b/examples/xml/htmlinfo/main.cpp index 3869ca5472..1424cfca67 100644 --- a/examples/xml/htmlinfo/main.cpp +++ b/examples/xml/htmlinfo/main.cpp @@ -79,7 +79,7 @@ void parseHtmlFile(QTextStream &out, const QString &fileName) { } //! [2] - out << " Title: \"" << title << "\"" << endl + out << " Title: \"" << title << '"' << endl << " Number of paragraphs: " << paragraphCount << endl << " Number of links: " << links.size() << endl << " Showing first few links:" << endl; diff --git a/examples/xml/saxbookmarks/xbelgenerator.cpp b/examples/xml/saxbookmarks/xbelgenerator.cpp index 24612c132c..5f1ec62e7e 100644 --- a/examples/xml/saxbookmarks/xbelgenerator.cpp +++ b/examples/xml/saxbookmarks/xbelgenerator.cpp @@ -81,8 +81,8 @@ QString XbelGenerator::escapedAttribute(const QString &str) { QString result = escapedText(str); result.replace("\"", """); - result.prepend("\""); - result.append("\""); + result.prepend(QLatin1Char('"')); + result.append(QLatin1Char('"')); return result; } diff --git a/src/corelib/doc/snippets/code/doc_src_containers.cpp b/src/corelib/doc/snippets/code/doc_src_containers.cpp index 00971d69b9..395e48bc89 100644 --- a/src/corelib/doc/snippets/code/doc_src_containers.cpp +++ b/src/corelib/doc/snippets/code/doc_src_containers.cpp @@ -176,7 +176,7 @@ QMap map; ... QMap::const_iterator i; for (i = map.constBegin(); i != map.constEnd(); ++i) - qDebug() << i.key() << ":" << i.value(); + qDebug() << i.key() << ':' << i.value(); //! [13] @@ -236,7 +236,7 @@ foreach (const QString &str, list) { QMap map; ... foreach (const QString &str, map.keys()) - qDebug() << str << ":" << map.value(str); + qDebug() << str << ':' << map.value(str); //! [19] @@ -245,7 +245,7 @@ QMultiMap map; ... foreach (const QString &str, map.uniqueKeys()) { foreach (int i, map.values(str)) - qDebug() << str << ":" << i; + qDebug() << str << ':' << i; } //! [20] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp index 0ac7cb5769..0976488a48 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp @@ -220,7 +220,7 @@ for (i = hash.begin(); i != hash.end(); ++i) //! [19] QHash::iterator i = hash.begin(); while (i != hash.end()) { - if (i.key().startsWith("_")) + if (i.key().startsWith('_')) i = hash.erase(i); else ++i; @@ -233,7 +233,7 @@ QHash::iterator i = hash.begin(); while (i != hash.end()) { QHash::iterator prev = i; ++i; - if (prev.key().startsWith("_")) + if (prev.key().startsWith('_')) hash.erase(prev); } //! [20] @@ -242,7 +242,7 @@ while (i != hash.end()) { //! [21] // WRONG while (i != hash.end()) { - if (i.key().startsWith("_")) + if (i.key().startsWith('_')) hash.erase(i); ++i; } diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp index 014af8b0ee..f1cf644df6 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp @@ -128,7 +128,7 @@ QLinkedList list; ... QLinkedList::iterator i = list.begin(); while (i != list.end()) { - if ((*i).startsWith("_")) + if ((*i).startsWith('_')) i = list.erase(i); else ++i; @@ -141,7 +141,7 @@ QLinkedList::iterator i = list.begin(); while (i != list.end()) { QLinkedList::iterator previous = i; ++i; - if ((*previous).startsWith("_")) + if ((*previous).startsWith('_')) list.erase(previous); } //! [11] @@ -150,7 +150,7 @@ while (i != list.end()) { //! [12] // WRONG while (i != list.end()) { - if ((*i).startsWith("_")) + if ((*i).startsWith('_')) list.erase(i); ++i; } diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp index 29e53fc700..3241991129 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp @@ -234,7 +234,7 @@ for (i = map.begin(); i != map.end(); ++i) //! [20] QMap::iterator i = map.begin(); while (i != map.end()) { - if (i.key().startsWith("_")) + if (i.key().startsWith('_')) i = map.erase(i); else ++i; @@ -247,7 +247,7 @@ QMap::iterator i = map.begin(); while (i != map.end()) { QMap::iterator prev = i; ++i; - if (prev.key().startsWith("_")) + if (prev.key().startsWith('_')) map.erase(prev); } //! [21] @@ -256,7 +256,7 @@ while (i != map.end()) { //! [22] // WRONG while (i != map.end()) { - if (i.key().startsWith("_")) + if (i.key().startsWith('_')) map.erase(i); ++i; } diff --git a/src/corelib/doc/snippets/qstring/main.cpp b/src/corelib/doc/snippets/qstring/main.cpp index e03e705a0b..d0b5fb00f3 100644 --- a/src/corelib/doc/snippets/qstring/main.cpp +++ b/src/corelib/doc/snippets/qstring/main.cpp @@ -777,10 +777,10 @@ void Widget::splitCaseSensitiveFunction() //! [62] QString str = "a,,b,c"; - QStringList list1 = str.split(","); + QStringList list1 = str.split(','); // list1: [ "a", "", "b", "c" ] - QStringList list2 = str.split(",", QString::SkipEmptyParts); + QStringList list2 = str.split(',', QString::SkipEmptyParts); // list2: [ "a", "b", "c" ] //! [62] } diff --git a/src/corelib/doc/snippets/qstringlist/main.cpp b/src/corelib/doc/snippets/qstringlist/main.cpp index 64f2061786..04d4dc8a89 100644 --- a/src/corelib/doc/snippets/qstringlist/main.cpp +++ b/src/corelib/doc/snippets/qstringlist/main.cpp @@ -82,7 +82,7 @@ Widget::Widget(QWidget *parent) //! [5] //! [6] QStringList list; //! [5] - list = str.split(","); + list = str.split(','); // list: ["Arial", "Helvetica", "Times", "Courier"] //! [6] diff --git a/src/gui/doc/snippets/qfontdatabase/main.cpp b/src/gui/doc/snippets/qfontdatabase/main.cpp index e33ad5f539..aacd6f47fa 100644 --- a/src/gui/doc/snippets/qfontdatabase/main.cpp +++ b/src/gui/doc/snippets/qfontdatabase/main.cpp @@ -60,7 +60,7 @@ int main(int argc, char **argv) QString sizes; foreach (int points, database.smoothSizes(family, style)) - sizes += QString::number(points) + " "; + sizes += QString::number(points) + ' '; styleItem->setText(1, sizes.trimmed()); } diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp index 29cbefdc04..8c32787b42 100644 --- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp +++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp @@ -147,7 +147,7 @@ namespace QTest { { QByteArray ba = "MyPoint("; ba += QByteArray::number(point.x()) + ", " + QByteArray::number(point.y()); - ba += ")"; + ba += ')'; return qstrdup(ba.data()); } } diff --git a/src/xml/doc/snippets/rsslisting/handler.cpp b/src/xml/doc/snippets/rsslisting/handler.cpp index 4825cf2f62..27e4a23fb4 100644 --- a/src/xml/doc/snippets/rsslisting/handler.cpp +++ b/src/xml/doc/snippets/rsslisting/handler.cpp @@ -174,7 +174,7 @@ bool Handler::characters (const QString &chars) bool Handler::fatalError (const QXmlParseException & exception) { qWarning() << "Fatal error on line" << exception.lineNumber() - << ", column" << exception.columnNumber() << ":" + << ", column" << exception.columnNumber() << ':' << exception.message(); return false; diff --git a/src/xml/doc/snippets/simpleparse/main.cpp b/src/xml/doc/snippets/simpleparse/main.cpp index 480dc1c528..cbb8ac96aa 100644 --- a/src/xml/doc/snippets/simpleparse/main.cpp +++ b/src/xml/doc/snippets/simpleparse/main.cpp @@ -78,7 +78,7 @@ int main(int argc, char **argv) for (int i = 0; i < items; ++i) { for (int j = 0; j < indentations[i]; ++j) - std::cout << " "; + std::cout << ' '; std::cout << names[i].toLocal8Bit().constData() << std::endl; } } From bba86a01c9828d03b1564984a08561d62686d329 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 Oct 2015 09:26:59 +0200 Subject: [PATCH 230/240] Libraries: Fix single-character string literals. Use character literals where applicable. Change-Id: I8e198774c2247c1cc1d852a41b59b301199b7878 Reviewed-by: Marc Mutz --- src/corelib/io/qfilesystemwatcher_win.cpp | 2 +- src/corelib/io/qsettings_mac.cpp | 2 +- src/corelib/json/qjsondocument.cpp | 2 +- src/corelib/json/qjsonvalue.cpp | 10 +++++----- src/corelib/json/qjsonwriter.cpp | 4 ++-- src/corelib/statemachine/qstatemachine.cpp | 6 +++--- src/corelib/tools/qregularexpression.cpp | 10 +++++----- src/gui/painting/qpdf.cpp | 2 +- src/network/access/qhttpnetworkconnection.cpp | 2 +- src/network/access/qnetworkaccessmanager.cpp | 2 +- src/network/kernel/qauthenticator.cpp | 4 ++-- src/network/kernel/qnetworkproxy.cpp | 4 ++-- src/network/kernel/qnetworkproxy_generic.cpp | 2 +- src/network/socket/qhttpsocketengine.cpp | 2 +- src/network/socket/qlocalserver_unix.cpp | 2 +- src/network/ssl/qsslellipticcurve.cpp | 2 +- src/network/ssl/qsslsocket.cpp | 2 +- src/network/ssl/qsslsocket_openssl.cpp | 4 ++-- .../dbusmenu/qdbusmenutypes.cpp | 2 +- .../qdevicediscovery_static.cpp | 4 ++-- .../devicediscovery/qdevicediscovery_udev.cpp | 2 +- .../basic/qbasicfontdatabase.cpp | 2 +- .../input/evdevmouse/qevdevmousehandler.cpp | 2 +- .../linuxaccessibility/atspiadaptor.cpp | 4 ++-- .../networkmanager/qnetworkmanagerengine.cpp | 4 ++-- .../generic/tuiotouch/qtuiohandler.cpp | 2 +- .../platforms/android/androidjniinput.cpp | 4 ++-- .../platforms/android/androidjnimain.cpp | 2 +- .../qandroidassetsfileenginehandler.cpp | 8 ++++---- .../android/qandroidinputcontext.cpp | 6 +++--- .../android/qandroidplatformfontdatabase.cpp | 6 +++--- src/plugins/platforms/cocoa/qcocoahelpers.mm | 2 +- .../eglfs_kms/qeglfskmsdevice.cpp | 4 ++-- .../platforms/qnx/qqnxvirtualkeyboardpps.cpp | 2 +- src/plugins/platforms/xcb/qxcbconnection.cpp | 2 +- src/plugins/platforms/xcb/qxcbscreen.cpp | 2 +- src/printsupport/kernel/qprintengine_win.cpp | 20 +++++++++---------- src/sql/drivers/oci/qsql_oci.cpp | 2 +- src/sql/drivers/sqlite/qsql_sqlite.cpp | 2 +- src/testlib/qtestblacklist.cpp | 2 +- src/widgets/dialogs/qfilesystemmodel.cpp | 2 +- src/widgets/itemviews/qtableview.cpp | 2 +- src/widgets/kernel/qwidgetsvariant.cpp | 2 +- src/widgets/util/qscroller.cpp | 6 +++--- 44 files changed, 81 insertions(+), 81 deletions(-) diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 4907a20a5f..410753868e 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -186,7 +186,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, } if (!found) { QWindowsFileSystemWatcherEngineThread *thread = new QWindowsFileSystemWatcherEngineThread(); - DEBUG() << " ###Creating new thread" << thread << "(" << (threads.count()+1) << "threads)"; + DEBUG() << " ###Creating new thread" << thread << '(' << (threads.count()+1) << "threads)"; thread->handles.append(handle.handle); thread->handleForDir.insert(QFileSystemWatcherPathKey(absolutePath), handle); diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp index f1d2e81bdc..e0b317b4c2 100644 --- a/src/corelib/io/qsettings_mac.cpp +++ b/src/corelib/io/qsettings_mac.cpp @@ -386,7 +386,7 @@ QMacSettingsPrivate::QMacSettingsPrivate(QSettings::Scope scope, const QString & if (main_bundle_identifier != NULL) { QString bundle_identifier(qtKey(main_bundle_identifier)); // CFBundleGetIdentifier returns identifier separated by slashes rather than periods. - QStringList bundle_identifier_components = bundle_identifier.split(QLatin1String("/")); + QStringList bundle_identifier_components = bundle_identifier.split(QLatin1Char('/')); // pre-reverse them so that when they get reversed again below, they are in the com.company.product format. QStringList bundle_identifier_components_reversed; for (int i=0; i(o.d->header->root()), json, 0, true); dbg.nospace() << "QJsonDocument(" << json.constData() // print as utf-8 string without extra quotation marks - << ")"; + << ')'; return dbg; } #endif diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp index ae6a3678bd..4c7a44b4a0 100644 --- a/src/corelib/json/qjsonvalue.cpp +++ b/src/corelib/json/qjsonvalue.cpp @@ -738,23 +738,23 @@ QDebug operator<<(QDebug dbg, const QJsonValue &o) dbg << "QJsonValue(null)"; break; case QJsonValue::Bool: - dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ")"; + dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ')'; break; case QJsonValue::Double: - dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ")"; + dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ')'; break; case QJsonValue::String: - dbg.nospace() << "QJsonValue(string, " << o.toString() << ")"; + dbg.nospace() << "QJsonValue(string, " << o.toString() << ')'; break; case QJsonValue::Array: dbg.nospace() << "QJsonValue(array, "; dbg << o.toArray(); - dbg << ")"; + dbg << ')'; break; case QJsonValue::Object: dbg.nospace() << "QJsonValue(object, "; dbg << o.toObject(); - dbg << ")"; + dbg << ')'; break; } return dbg; diff --git a/src/corelib/json/qjsonwriter.cpp b/src/corelib/json/qjsonwriter.cpp index 99f83554c2..45a05e93a3 100644 --- a/src/corelib/json/qjsonwriter.cpp +++ b/src/corelib/json/qjsonwriter.cpp @@ -137,13 +137,13 @@ static void valueToJson(const QJsonPrivate::Base *b, const QJsonPrivate::Value & json += compact ? "[" : "[\n"; arrayContentToJson(static_cast(v.base(b)), json, indent + (compact ? 0 : 1), compact); json += QByteArray(4*indent, ' '); - json += "]"; + json += ']'; break; case QJsonValue::Object: json += compact ? "{" : "{\n"; objectContentToJson(static_cast(v.base(b)), json, indent + (compact ? 0 : 1), compact); json += QByteArray(4*indent, ' '); - json += "}"; + json += '}'; break; case QJsonValue::Null: default: diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index c5e251b37b..3ffe191093 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1288,7 +1288,7 @@ QVariant QStateMachinePrivate::savedValueForRestorable(const QList= 0; --i) { QAbstractState *s = exitedStates_sorted.at(i); @@ -1311,7 +1311,7 @@ void QStateMachinePrivate::registerRestorable(QAbstractState *state, QObject *ob const QVariant &value) { #ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - qDebug() << q_func() << ": registerRestorable(" << state << object << propertyName << value << ")"; + qDebug() << q_func() << ": registerRestorable(" << state << object << propertyName << value << ')'; #endif RestorableId id(object, propertyName); QHash &restorables = registeredRestorablesForState[state]; @@ -1327,7 +1327,7 @@ void QStateMachinePrivate::unregisterRestorables(const QList & const QByteArray &propertyName) { #ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - qDebug() << q_func() << ": unregisterRestorables(" << states << object << propertyName << ")"; + qDebug() << q_func() << ": unregisterRestorables(" << states << object << propertyName << ')'; #endif RestorableId id(object, propertyName); for (int i = 0; i < states.size(); ++i) { diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index d8b0bf6e9f..81b108059b 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -2479,7 +2479,7 @@ QDataStream &operator>>(QDataStream &in, QRegularExpression &re) QDebug operator<<(QDebug debug, const QRegularExpression &re) { QDebugStateSaver saver(debug); - debug.nospace() << "QRegularExpression(" << re.pattern() << ", " << re.patternOptions() << ")"; + debug.nospace() << "QRegularExpression(" << re.pattern() << ", " << re.patternOptions() << ')'; return debug; } @@ -2521,7 +2521,7 @@ QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOption flags.chop(1); } - debug.nospace() << "QRegularExpression::PatternOptions(" << flags << ")"; + debug.nospace() << "QRegularExpression::PatternOptions(" << flags << ')'; return debug; } @@ -2550,7 +2550,7 @@ QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match) for (int i = 0; i <= match.lastCapturedIndex(); ++i) { debug << i << ":(" << match.capturedStart(i) << ", " << match.capturedEnd(i) - << ", " << match.captured(i) << ")"; + << ", " << match.captured(i) << ')'; if (i < match.lastCapturedIndex()) debug << ", "; } @@ -2558,12 +2558,12 @@ QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match) debug << ", has partial match: (" << match.capturedStart(0) << ", " << match.capturedEnd(0) << ", " - << match.captured(0) << ")"; + << match.captured(0) << ')'; } else { debug << ", no match"; } - debug << ")"; + debug << ')'; return debug; } diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 0814e0494d..0f81f09f60 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1793,7 +1793,7 @@ void QPdfEnginePrivate::printString(const QString &string) { array.append(part[j]); } } - array.append(")"); + array.append(')'); write(array); } diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index e6f1918da8..c4cb8e65c0 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -326,7 +326,7 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair) QByteArray host; if (add.setAddress(hostName)) { if (add.protocol() == QAbstractSocket::IPv6Protocol) - host = "[" + hostName.toLatin1() + "]";//format the ipv6 in the standard way + host = '[' + hostName.toLatin1() + ']'; //format the ipv6 in the standard way else host = hostName.toLatin1(); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 7147823309..086140f967 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1704,7 +1704,7 @@ QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkReq break; } // putting the boundary into quotes, recommended in RFC 2046 section 5.1.1 - contentType += "; boundary=\"" + multiPart->d_func()->boundary + "\""; + contentType += "; boundary=\"" + multiPart->d_func()->boundary + '"'; newRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType)); } diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index d626d0bcfc..95994653e6 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -693,13 +693,13 @@ QByteArray QAuthenticatorPrivate::digestMd5Response(const QByteArray &challenge, credentials += "uri=\"" + path + "\", "; if (!opaque.isEmpty()) credentials += "opaque=\"" + opaque + "\", "; - credentials += "response=\"" + response + '\"'; + credentials += "response=\"" + response + '"'; if (!options.value("algorithm").isEmpty()) credentials += ", algorithm=" + options.value("algorithm"); if (!options.value("qop").isEmpty()) { credentials += ", qop=" + qop + ", "; credentials += "nc=" + nonceCountString + ", "; - credentials += "cnonce=\"" + cnonce + '\"'; + credentials += "cnonce=\"" + cnonce + '"'; } return credentials; diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp index d219d72136..4c7c0c5442 100644 --- a/src/network/kernel/qnetworkproxy.cpp +++ b/src/network/kernel/qnetworkproxy.cpp @@ -1605,7 +1605,7 @@ QDebug operator<<(QDebug debug, const QNetworkProxy &proxy) debug << "Unknown proxy " << int(type); break; } - debug << "\"" << proxy.hostName() << ":" << proxy.port() << "\" "; + debug << '"' << proxy.hostName() << ':' << proxy.port() << "\" "; QNetworkProxy::Capabilities caps = proxy.capabilities(); QStringList scaps; if (caps & QNetworkProxy::TunnelingCapability) @@ -1618,7 +1618,7 @@ QDebug operator<<(QDebug debug, const QNetworkProxy &proxy) scaps << QStringLiteral("Caching"); if (caps & QNetworkProxy::HostNameLookupCapability) scaps << QStringLiteral("NameLookup"); - debug << "[" << scaps.join(QLatin1Char(' ')) << "]"; + debug << '[' << scaps.join(QLatin1Char(' ')) << ']'; return debug; } #endif diff --git a/src/network/kernel/qnetworkproxy_generic.cpp b/src/network/kernel/qnetworkproxy_generic.cpp index d3295376da..145ba18e3f 100644 --- a/src/network/kernel/qnetworkproxy_generic.cpp +++ b/src/network/kernel/qnetworkproxy_generic.cpp @@ -58,7 +58,7 @@ static bool ignoreProxyFor(const QNetworkProxyQuery &query) QString peerHostName = query.peerHostName(); // Since we use suffix matching, "*" is our 'default' behaviour - if (token.startsWith("*")) + if (token.startsWith('*')) token = token.mid(1); // Harmonize trailing dot notation diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 1a90abd22c..92ca76b560 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -481,7 +481,7 @@ void QHttpSocketEngine::slotSocketConnected() QUrl::toAce(d->peerName); QByteArray path = peerAddress + ':' + QByteArray::number(d->peerPort); QByteArray data = method; - data += " "; + data += ' '; data += path; data += " HTTP/1.1\r\n"; data += "Proxy-Connection: keep-alive\r\n"; diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index 634074d91f..a356e21214 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -209,7 +209,7 @@ bool QLocalServerPrivate::listen(qintptr socketDescriptor) QString name = QString::fromLatin1(addr.sun_path); if (!name.isEmpty()) { fullServerName = name; - serverName = fullServerName.mid(fullServerName.lastIndexOf(QLatin1String("/"))+1); + serverName = fullServerName.mid(fullServerName.lastIndexOf(QLatin1Char('/')) + 1); if (serverName.isEmpty()) { serverName = fullServerName; } diff --git a/src/network/ssl/qsslellipticcurve.cpp b/src/network/ssl/qsslellipticcurve.cpp index b4396d567b..0824a61e8d 100644 --- a/src/network/ssl/qsslellipticcurve.cpp +++ b/src/network/ssl/qsslellipticcurve.cpp @@ -170,7 +170,7 @@ QDebug operator<<(QDebug debug, QSslEllipticCurve curve) { QDebugStateSaver saver(debug); debug.resetFormat().nospace(); - debug << "QSslEllipticCurve(" << curve.shortName() << ")"; + debug << "QSslEllipticCurve(" << curve.shortName() << ')'; return debug; } #endif diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index b62cfd2fde..0472a9a198 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1242,7 +1242,7 @@ void QSslSocket::setCiphers(const QString &ciphers) { Q_D(QSslSocket); d->configuration.ciphers.clear(); - foreach (const QString &cipherName, ciphers.split(QLatin1String(":"),QString::SkipEmptyParts)) { + foreach (const QString &cipherName, ciphers.split(QLatin1Char(':'), QString::SkipEmptyParts)) { QSslCipher cipher(cipherName); if (!cipher.isNull()) d->configuration.ciphers << cipher; diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 0a4c68d7c0..a8e4c61e9a 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -225,7 +225,7 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *ciph char buf [256]; QString descriptionOneLine = QString::fromLatin1(q_SSL_CIPHER_description(cipher, buf, sizeof(buf))); - QStringList descriptionList = descriptionOneLine.split(QLatin1String(" "), QString::SkipEmptyParts); + QStringList descriptionList = descriptionOneLine.split(QLatin1Char(' '), QString::SkipEmptyParts); if (descriptionList.size() > 5) { // ### crude code. ciph.d->isNull = false; @@ -290,7 +290,7 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx) << "OU=" << cert.subjectInfo(QSslCertificate::OrganizationalUnitName) << "C=" << cert.subjectInfo(QSslCertificate::CountryName) << "ST=" << cert.subjectInfo(QSslCertificate::StateOrProvinceName); - qCDebug(lcSsl) << "Valid:" << cert.effectiveDate() << "-" << cert.expiryDate(); + qCDebug(lcSsl) << "Valid:" << cert.effectiveDate() << '-' << cert.expiryDate(); } #endif } diff --git a/src/platformsupport/dbusmenu/qdbusmenutypes.cpp b/src/platformsupport/dbusmenu/qdbusmenutypes.cpp index 94df0f53dd..8d5d96353c 100644 --- a/src/platformsupport/dbusmenu/qdbusmenutypes.cpp +++ b/src/platformsupport/dbusmenu/qdbusmenutypes.cpp @@ -247,7 +247,7 @@ QDebug operator<<(QDebug d, const QDBusMenuItem &item) { QDebugStateSaver saver(d); d.nospace(); - d << "QDBusMenuItem(id=" << item.m_id << ", properties=" << item.m_properties << ")"; + d << "QDBusMenuItem(id=" << item.m_id << ", properties=" << item.m_properties << ')'; return d; } diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp index 1bc834b5ef..3aab785b34 100644 --- a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp +++ b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp @@ -90,7 +90,7 @@ QStringList QDeviceDiscoveryStatic::scanConnectedDevices() if (m_types & Device_InputMask) { dir.setPath(QString::fromLatin1(QT_EVDEV_DEVICE_PATH)); foreach (const QString &deviceFile, dir.entryList()) { - QString absoluteFilePath = dir.absolutePath() + QString::fromLatin1("/") + deviceFile; + QString absoluteFilePath = dir.absolutePath() + QLatin1Char('/') + deviceFile; if (checkDeviceType(absoluteFilePath)) devices << absoluteFilePath; } @@ -100,7 +100,7 @@ QStringList QDeviceDiscoveryStatic::scanConnectedDevices() if (m_types & Device_VideoMask) { dir.setPath(QString::fromLatin1(QT_DRM_DEVICE_PATH)); foreach (const QString &deviceFile, dir.entryList()) { - QString absoluteFilePath = dir.absolutePath() + QString::fromLatin1("/") + deviceFile; + QString absoluteFilePath = dir.absolutePath() + QLatin1Char('/') + deviceFile; if (checkDeviceType(absoluteFilePath)) devices << absoluteFilePath; } diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp index 8fa82e2ad7..f285e61a9f 100644 --- a/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp +++ b/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp @@ -210,7 +210,7 @@ bool QDeviceDiscoveryUDev::checkDeviceType(udev_device *dev) if ((m_types & Device_Keyboard) && (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD"), "1") == 0 )) { const char *capabilities_key = udev_device_get_sysattr_value(dev, "capabilities/key"); - QStringList val = QString::fromUtf8(capabilities_key).split(QString::fromUtf8(" "), QString::SkipEmptyParts); + QStringList val = QString::fromUtf8(capabilities_key).split(QLatin1Char(' '), QString::SkipEmptyParts); if (!val.isEmpty()) { bool ok; unsigned long long keys = val.last().toULongLong(&ok, 16); diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp index b04ae8ee52..728b166b71 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp @@ -188,7 +188,7 @@ QStringList QBasicFontDatabase::addTTFile(const QByteArray &fontData, const QByt error = FT_New_Face(library, file.constData(), index, &face); } if (error != FT_Err_Ok) { - qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error; + qDebug() << "FT_New_Face failed with index" << index << ':' << hex << error; break; } numFaces = face->num_faces; diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp index 2e9723329e..c4ebc5c51d 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp @@ -148,7 +148,7 @@ bool QEvdevMouseHandler::getHardwareMaximum() qCDebug(qLcEvdevMouse) << "Absolute pointing device" << "hardware max x" << m_hardwareWidth << "hardware max y" << m_hardwareHeight - << "hardware scalers x" << m_hardwareScalerX << "y" << m_hardwareScalerY; + << "hardware scalers x" << m_hardwareScalerX << 'y' << m_hardwareScalerY; return true; } diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp index d155cecd89..0293c74fb9 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp @@ -2312,7 +2312,7 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString (column < 0) || (row >= interface->tableInterface()->rowCount()) || (column >= interface->tableInterface()->columnCount())) { - qAtspiDebug() << "WARNING: invalid index for tableInterface GetAccessibleAt (" << row << ", " << column << ")"; + qAtspiDebug() << "WARNING: invalid index for tableInterface GetAccessibleAt (" << row << ", " << column << ')'; return false; } @@ -2331,7 +2331,7 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString int column = message.arguments().at(1).toInt(); QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, column); if (!cell) { - qAtspiDebug() << "WARNING: AtSpiAdaptor::GetIndexAt(" << row << "," << column << ") did not find a cell. " << interface; + qAtspiDebug() << "WARNING: AtSpiAdaptor::GetIndexAt(" << row << ',' << column << ") did not find a cell. " << interface; return false; } int index = interface->indexOfChild(cell); diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp index 7258877eb7..3b8a85a26b 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp @@ -845,7 +845,7 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri QHashIterator i(ofonoContextManagers); while (i.hasNext()) { i.next(); - const QString path = i.key() +"/"+contextPart; + const QString path = i.key() + QLatin1Char('/') +contextPart; if (isActiveContext(path)) { cpPriv->state |= QNetworkConfiguration::Active; break; @@ -1024,7 +1024,7 @@ QNetworkConfiguration::BearerType QNetworkManagerEngine::currentBearerType(const QHashIterator i(ofonoContextManagers); while (i.hasNext()) { i.next(); - QString contextPath = i.key() +"/"+contextPart; + QString contextPath = i.key() + QLatin1Char('/') +contextPart; if (i.value()->contexts().contains(contextPath)) { diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp index dd161570e8..2b42889cb1 100644 --- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp +++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp @@ -202,7 +202,7 @@ void QTuioHandler::process2DCurAlive(const QOscMessage &message) for (int i = 1; i < arguments.count(); ++i) { if (QMetaType::Type(arguments.at(i).type()) != QMetaType::Int) { - qWarning() << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ")"; + qWarning() << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ')'; return; } diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index b410e5f68e..8982787ec9 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -278,7 +278,7 @@ namespace QtAndroidInput } #ifdef QT_DEBUG_ANDROID_STYLUS - qDebug() << action << pointerType << buttonState << "@" << x << y << "pressure" << pressure << ": buttons" << buttons; + qDebug() << action << pointerType << buttonState << '@' << x << y << "pressure" << pressure << ": buttons" << buttons; #endif QWindowSystemInterface::handleTabletEvent(tlw, ulong(time), @@ -681,7 +681,7 @@ namespace QtAndroidInput return Qt::Key_AudioCycleTrack; default: - qWarning() << "Unhandled key code " << key << "!"; + qWarning() << "Unhandled key code " << key << '!'; return 0; } } diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index cd40b7eec2..c7c82e255c 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -292,7 +292,7 @@ namespace QtAndroid QString manufacturer = QJNIObjectPrivate::getStaticObjectField("android/os/Build", "MANUFACTURER", "Ljava/lang/String;").toString(); QString model = QJNIObjectPrivate::getStaticObjectField("android/os/Build", "MODEL", "Ljava/lang/String;").toString(); - return manufacturer + QStringLiteral(" ") + model; + return manufacturer + QLatin1Char(' ') + model; } int createSurface(AndroidSurfaceClient *client, const QRect &geometry, bool onTop, int imageDepth) diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index 64be75b63f..6ad3d2dc9a 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -122,8 +122,8 @@ public: m_assetFile = 0; m_assetDir = asset; m_fileName = fileName; - if (!m_fileName.endsWith(QChar(QLatin1Char('/')))) - m_fileName += "/"; + if (!m_fileName.endsWith(QLatin1Char('/'))) + m_fileName += QLatin1Char('/'); } ~AndroidAbstractFileEngine() @@ -231,8 +231,8 @@ public: return; m_fileName = file; - if (!m_fileName.endsWith(QChar(QLatin1Char('/')))) - m_fileName += "/"; + if (!m_fileName.endsWith(QLatin1Char('/'))) + m_fileName += QLatin1Char('/'); close(); } diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index b44340106d..e3ea048e84 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -342,7 +342,7 @@ QAndroidInputContext::QAndroidInputContext() if (clazz == NULL) { qCritical() << "Native registration unable to find class '" << QtNativeInputConnectionClassName - << "'"; + << '\''; return; } @@ -350,7 +350,7 @@ QAndroidInputContext::QAndroidInputContext() if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) { qCritical() << "RegisterNatives failed for '" << QtNativeInputConnectionClassName - << "'"; + << '\''; return; } @@ -358,7 +358,7 @@ QAndroidInputContext::QAndroidInputContext() if (clazz == NULL) { qCritical() << "Native registration unable to find class '" << QtExtractedTextClassName - << "'"; + << '\''; return; } diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp index be1a3d7bdf..a8bbec9400 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp @@ -69,11 +69,11 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami { QStringList result; if (styleHint == QFont::Monospace || styleHint == QFont::Courier) - result.append(QString(qgetenv("QT_ANDROID_FONTS_MONOSPACE")).split(";")); + result.append(QString(qgetenv("QT_ANDROID_FONTS_MONOSPACE")).split(QLatin1Char(';'))); else if (styleHint == QFont::Serif) - result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(";")); + result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(QLatin1Char(';'))); else - result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(";")); + result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(QLatin1Char(';'))); result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script)); return result; diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index bb493ef2be..8ad80333f8 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -622,7 +622,7 @@ QString qt_mac_applicationName() if (appName.isEmpty()) { QString arg0 = QGuiApplicationPrivate::instance()->appName(); if (arg0.contains("/")) { - QStringList parts = arg0.split("/"); + QStringList parts = arg0.split(QLatin1Char('/')); appName = parts.at(parts.count() - 1); } else { appName = arg0; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp index 40cd8b8763..c29d64c06d 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp @@ -219,7 +219,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr for (int i = 0; i < connector->count_modes; i++) { const drmModeModeInfo &mode = connector->modes[i]; qCDebug(qLcEglfsKmsDebug) << "mode" << i << mode.hdisplay << "x" << mode.vdisplay - << "@" << mode.vrefresh << "hz"; + << '@' << mode.vrefresh << "hz"; modes << connector->modes[i]; } @@ -278,7 +278,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr int height = modes[selected_mode].vdisplay; int refresh = modes[selected_mode].vrefresh; qCDebug(qLcEglfsKmsDebug) << "Selected mode" << selected_mode << ":" << width << "x" << height - << "@" << refresh << "hz for output" << connectorName; + << '@' << refresh << "hz for output" << connectorName; } QEglFSKmsOutput output = { diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp index 392d45c5b4..2c7a28e835 100644 --- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp +++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp @@ -121,7 +121,7 @@ bool QQnxVirtualKeyboardPps::connect() if (m_fd == -1) { qVirtualKeyboardDebug() << Q_FUNC_INFO << ": Unable to open" << ms_PPSPath - << ":" << strerror(errno); + << ':' << strerror(errno); close(); return false; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index c35b019f7e..13d73c7194 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -476,7 +476,7 @@ void QXcbConnection::initializeScreens() // Push the screens to QApplication QXcbIntegration *integration = QXcbIntegration::instance(); foreach (QXcbScreen* screen, m_screens) { - qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")"; + qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ')'; integration->screenAdded(screen, screen->isPrimary()); } diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 2e0c55eea8..64645b92f6 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -735,7 +735,7 @@ QDebug operator<<(QDebug debug, const QXcbScreen *screen) formatSizeF(debug, screen->physicalSize()); // TODO 5.6 if (debug.verbosity() > 2) { debug << ", screenNumber=" << screen->screenNumber(); - debug << ", virtualSize=" << screen->virtualSize().width() << "x" << screen->virtualSize().height() << " ("; + debug << ", virtualSize=" << screen->virtualSize().width() << 'x' << screen->virtualSize().height() << " ("; formatSizeF(debug, screen->virtualSize()); debug << "), nativeGeometry="; formatRect(debug, screen->nativeGeometry()); diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index a4209d833a..c8ce2e482d 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -1150,7 +1150,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->updateMetrics(); d->doReinit(); #ifdef QT_DEBUG_METRICS - qDebug() << "QWin32PrintEngine::setProperty(PPK_Orientation," << orientation << ")"; + qDebug() << "QWin32PrintEngine::setProperty(PPK_Orientation," << orientation << ')'; d->debugMetrics(); #endif // QT_DEBUG_METRICS break; @@ -1173,7 +1173,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->setPageSize(pageSize); d->doReinit(); #ifdef QT_DEBUG_METRICS - qDebug() << "QWin32PrintEngine::setProperty(PPK_PageSize," << value.toInt() << ")"; + qDebug() << "QWin32PrintEngine::setProperty(PPK_PageSize," << value.toInt() << ')'; d->debugMetrics(); #endif // QT_DEBUG_METRICS } @@ -1189,7 +1189,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->setPageSize(pageSize); d->doReinit(); #ifdef QT_DEBUG_METRICS - qDebug() << "QWin32PrintEngine::setProperty(PPK_PaperName," << value.toString() << ")"; + qDebug() << "QWin32PrintEngine::setProperty(PPK_PaperName," << value.toString() << ')'; d->debugMetrics(); #endif // QT_DEBUG_METRICS } @@ -1228,7 +1228,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->stretch_y = d->dpi_y / double(d->resolution); d->updateMetrics(); #ifdef QT_DEBUG_METRICS - qDebug() << "QWin32PrintEngine::setProperty(PPK_Resolution," << value.toInt() << ")"; + qDebug() << "QWin32PrintEngine::setProperty(PPK_Resolution," << value.toInt() << ')'; d->debugMetrics(); #endif // QT_DEBUG_METRICS break; @@ -1242,7 +1242,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->setPageSize(pageSize); d->doReinit(); #ifdef QT_DEBUG_METRICS - qDebug() << "QWin32PrintEngine::setProperty(PPK_WindowsPageSize," << value.toInt() << ")"; + qDebug() << "QWin32PrintEngine::setProperty(PPK_WindowsPageSize," << value.toInt() << ')'; d->debugMetrics(); #endif // QT_DEBUG_METRICS break; @@ -1258,7 +1258,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->setPageSize(pageSize); d->doReinit(); #ifdef QT_DEBUG_METRICS - qDebug() << "QWin32PrintEngine::setProperty(PPK_CustomPaperSize," << value.toSizeF() << ")"; + qDebug() << "QWin32PrintEngine::setProperty(PPK_CustomPaperSize," << value.toSizeF() << ')'; d->debugMetrics(); #endif // QT_DEBUG_METRICS } @@ -1273,7 +1273,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & margins.at(2).toReal(), margins.at(3).toReal())); d->updateMetrics(); #ifdef QT_DEBUG_METRICS - qDebug() << "QWin32PrintEngine::setProperty(PPK_PageMargins," << margins << ")"; + qDebug() << "QWin32PrintEngine::setProperty(PPK_PageMargins," << margins << ')'; d->debugMetrics(); #endif // QT_DEBUG_METRICS break; @@ -1288,7 +1288,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->setPageSize(pageSize); d->doReinit(); #ifdef QT_DEBUG_METRICS - qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageSize," << pageSize << ")"; + qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageSize," << pageSize << ')'; d->debugMetrics(); #endif // QT_DEBUG_METRICS } @@ -1301,7 +1301,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->m_pageLayout.setMargins(pair.first); d->updateMetrics(); #ifdef QT_DEBUG_METRICS - qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageMargins," << pair.first << pair.second << ")"; + qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageMargins," << pair.first << pair.second << ')'; d->debugMetrics(); #endif // QT_DEBUG_METRICS break; @@ -1317,7 +1317,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->m_pageLayout.setMargins(pageLayout.margins()); d->updateMetrics(); #ifdef QT_DEBUG_METRICS - qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageLayout," << pageLayout << ")"; + qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageLayout," << pageLayout << ')'; d->debugMetrics(); #endif // QT_DEBUG_METRICS } diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp index 33e3b96276..f0c0b224bd 100644 --- a/src/sql/drivers/oci/qsql_oci.cpp +++ b/src/sql/drivers/oci/qsql_oci.cpp @@ -2452,7 +2452,7 @@ QStringList QOCIDriver::tables(QSql::TableType type) const t.exec(query + whereList.join(QLatin1String(" or "))); while (t.next()) { if (t.value(0).toString() != d->user) - tl.append(t.value(0).toString() + QLatin1String(".") + t.value(1).toString()); + tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString()); else tl.append(t.value(1).toString()); } diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index 06e849ccd5..4286f5b338 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -744,7 +744,7 @@ static QSqlIndex qGetTableInfo(QSqlQuery &q, const QString &tableName, bool only schema = tableName.left(indexOfSeparator).append(QLatin1Char('.')); table = tableName.mid(indexOfSeparator + 1); } - q.exec(QLatin1String("PRAGMA ") + schema + QLatin1String("table_info (") + _q_escapeIdentifier(table) + QLatin1String(")")); + q.exec(QLatin1String("PRAGMA ") + schema + QLatin1String("table_info (") + _q_escapeIdentifier(table) + QLatin1Char(')')); QSqlIndex ind; while (q.next()) { diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index a30936a23b..c2643a2304 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -174,7 +174,7 @@ static bool isGPUTestBlacklisted(const char *slot, const char *data = 0) if (gpuFeatures->find(disableKey) != gpuFeatures->end()) { QByteArray msg = QByteArrayLiteral("Skipped due to GPU blacklist: ") + disableKey; if (data) - msg += QByteArrayLiteral(":") + QByteArray(data); + msg += ':' + QByteArray(data); QTest::qSkip(msg.constData(), __FILE__, __LINE__); return true; } diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index fd49246e9f..556e927cbf 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -372,7 +372,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) { - if (!pathElements.at(0).contains(QLatin1String(":"))) { + if (!pathElements.at(0).contains(QLatin1Char(':'))) { QString rootPath = QDir(longPath).rootPath(); pathElements.prepend(rootPath); } diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 3e3e3099c8..0af4a26494 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -190,7 +190,7 @@ QList QSpanCollection::spansInRect(int x, int y, int w, #ifdef DEBUG_SPAN_UPDATE QDebug operator<<(QDebug str, const QSpanCollection::Span &span) { - str << "(" << span.top() << "," << span.left() << "," << span.bottom() << "," << span.right() << ")"; + str << '(' << span.top() << ',' << span.left() << ',' << span.bottom() << ',' << span.right() << ')'; return str; } #endif diff --git a/src/widgets/kernel/qwidgetsvariant.cpp b/src/widgets/kernel/qwidgetsvariant.cpp index b0dcc4aa1b..fc02c9c77d 100644 --- a/src/widgets/kernel/qwidgetsvariant.cpp +++ b/src/widgets/kernel/qwidgetsvariant.cpp @@ -109,7 +109,7 @@ static void streamDebug(QDebug dbg, const QVariant &v) dbg.nospace() << *v_cast(d); break; default: - dbg.nospace() << "QMetaType::Type(" << d->type << ")"; + dbg.nospace() << "QMetaType::Type(" << d->type << ')'; } } #endif diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp index de12983f21..563c501356 100644 --- a/src/widgets/util/qscroller.cpp +++ b/src/widgets/util/qscroller.cpp @@ -976,7 +976,7 @@ bool QScroller::handleInput(Input input, const QPointF &position, qint64 timesta { Q_D(QScroller); - qScrollerDebug() << "QScroller::handleInput(" << input << ", " << d->stateName(d->state) << ", " << position << ", " << timestamp << ")"; + qScrollerDebug() << "QScroller::handleInput(" << input << ", " << d->stateName(d->state) << ", " << position << ", " << timestamp << ')'; struct statechange { State state; Input input; @@ -1296,7 +1296,7 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal lowerSnapPos = nextSnapPos(startPos, -1, orientation); qreal higherSnapPos = nextSnapPos(startPos, 1, orientation); - qScrollerDebug() << " Real Delta:" << lowerSnapPos <<"-"< higherSnapPos || qIsNaN(higherSnapPos)) @@ -1703,7 +1703,7 @@ void QScrollerPrivate::setState(QScroller::State newstate) if (state == newstate) return; - qScrollerDebug() << q << "QScroller::setState(" << stateName(newstate) << ")"; + qScrollerDebug() << q << "QScroller::setState(" << stateName(newstate) << ')'; switch (newstate) { case QScroller::Inactive: From 9b6cd2764a1516f3f6a13f9c3379603fe0d563a7 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 25 Sep 2015 15:55:31 +0200 Subject: [PATCH 231/240] Testlib: Output function / total time along with crash dump. Previously, only QXmlTestLogger had timers to take elapsed times and log them. Move those into class QTestLog for access by the loggers and output the times in the crash dump to make it easier to spot hangs/recursion crashes. Produces: QFATAL : foo() Received signal 11 Function time: 22ms Total time: 23ms A crash occurred in ... Function time: 24ms Total time: 26ms Task-number: QTBUG-47370 Change-Id: Ia530a63104087daffc9a15f68c15d93378b9407e Reviewed-by: Simon Hausmann --- src/testlib/qtestcase.cpp | 15 ++++++++--- src/testlib/qtestlog.cpp | 17 +++++++++++++ src/testlib/qtestlog_p.h | 5 ++++ src/testlib/qxmltestlogger.cpp | 9 +++---- src/testlib/qxmltestlogger_p.h | 3 --- .../testlib/selftests/expected_crashes_3.txt | 1 + .../auto/testlib/selftests/tst_selftests.cpp | 25 +++++++++++++++---- 7 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 000470e9e5..0847d639fd 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2597,9 +2597,13 @@ private: void FatalSignalHandler::signal(int signum) { + const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime()); + const int msecsTotalTime = qRound(QTestLog::msecsTotalTime()); if (signum != SIGINT) stackTrace(); - qFatal("Received signal %d", signum); + qFatal("Received signal %d\n" + " Function time: %dms Total time: %dms", + signum, msecsFunctionTime, msecsTotalTime); #if defined(Q_OS_INTEGRITY) { struct sigaction act; @@ -2794,12 +2798,15 @@ static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo) char appName[MAX_PATH]; if (!GetModuleFileNameA(NULL, appName, MAX_PATH)) appName[0] = 0; - + const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime()); + const int msecsTotalTime = qRound(QTestLog::msecsTotalTime()); const void *exceptionAddress = exInfo->ExceptionRecord->ExceptionAddress; - printf("A crash occurred in %s.\n\n" + printf("A crash occurred in %s.\n" + "Function time: %dms Total time: %dms\n\n" "Exception address: 0x%p\n" "Exception code : 0x%lx\n", - appName, exceptionAddress, exInfo->ExceptionRecord->ExceptionCode); + appName, msecsFunctionTime, msecsTotalTime, + exceptionAddress, exInfo->ExceptionRecord->ExceptionCode); DebugSymbolResolver resolver(GetCurrentProcess()); if (resolver.isValid()) { diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 59aeb27ffe..3513e10eec 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -46,6 +46,7 @@ #include #include +#include #include #include @@ -75,6 +76,9 @@ static void saveCoverageTool(const char * appname, bool testfailed, bool install #endif } +static QElapsedTimer elapsedFunctionTime; +static QElapsedTimer elapsedTotalTime; + namespace QTest { int fails = 0; @@ -325,6 +329,7 @@ namespace QTest { void QTestLog::enterTestFunction(const char* function) { + elapsedFunctionTime.restart(); if (printAvailableTags) return; @@ -450,6 +455,8 @@ void QTestLog::addBenchmarkResult(const QBenchmarkResult &result) void QTestLog::startLogging() { + elapsedTotalTime.start(); + elapsedFunctionTime.start(); QTest::TestLoggers::startLogging(); QTest::oldMessageHandler = qInstallMessageHandler(QTest::messageHandler); } @@ -597,4 +604,14 @@ bool QTestLog::installedTestCoverage() return QTest::installedTestCoverage; } +qint64 QTestLog::nsecsTotalTime() +{ + return elapsedTotalTime.nsecsElapsed(); +} + +qint64 QTestLog::nsecsFunctionTime() +{ + return elapsedFunctionTime.nsecsElapsed(); +} + QT_END_NAMESPACE diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index b4786b4904..b7e9d16ec3 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -110,6 +110,11 @@ public: static void setInstalledTestCoverage(bool installed); static bool installedTestCoverage(); + static qint64 nsecsTotalTime(); + static qreal msecsTotalTime() { return QTestLog::nsecsTotalTime() / 1000000.; } + static qint64 nsecsFunctionTime(); + static qreal msecsFunctionTime() { return QTestLog::nsecsFunctionTime() / 1000000.; } + private: QTestLog(); ~QTestLog(); diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp index bf607b4702..f96b5647e4 100644 --- a/src/testlib/qxmltestlogger.cpp +++ b/src/testlib/qxmltestlogger.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -124,15 +125,13 @@ void QXmlTestLogger::startLogging() " " QTEST_VERSION_STR "\n" "\n", qVersion(), quotedBuild.constData()); outputString(buf.constData()); - m_totalTime.start(); } void QXmlTestLogger::stopLogging() { QTestCharBuffer buf; QTest::qt_asprintf(&buf, - "\n", - m_totalTime.nsecsElapsed() / 1000000.); + "\n", QTestLog::msecsTotalTime()); outputString(buf.constData()); if (xmlmode == QXmlTestLogger::Complete) { outputString("\n"); @@ -148,8 +147,6 @@ void QXmlTestLogger::enterTestFunction(const char *function) xmlQuote("edFunction, function); QTest::qt_asprintf(&buf, "\n", quotedFunction.constData()); outputString(buf.constData()); - - m_functionTime.start(); } void QXmlTestLogger::leaveTestFunction() @@ -158,7 +155,7 @@ void QXmlTestLogger::leaveTestFunction() QTest::qt_asprintf(&buf, " \n" "\n", - m_functionTime.nsecsElapsed() / 1000000.); + QTestLog::msecsFunctionTime()); outputString(buf.constData()); } diff --git a/src/testlib/qxmltestlogger_p.h b/src/testlib/qxmltestlogger_p.h index 5cf8b4596c..49a21d9ca1 100644 --- a/src/testlib/qxmltestlogger_p.h +++ b/src/testlib/qxmltestlogger_p.h @@ -47,7 +47,6 @@ #include -#include QT_BEGIN_NAMESPACE @@ -79,8 +78,6 @@ public: private: XmlMode xmlmode; - QElapsedTimer m_functionTime; - QElapsedTimer m_totalTime; }; QT_END_NAMESPACE diff --git a/tests/auto/testlib/selftests/expected_crashes_3.txt b/tests/auto/testlib/selftests/expected_crashes_3.txt index 57c3ddc2ba..0e3f60dd1b 100644 --- a/tests/auto/testlib/selftests/expected_crashes_3.txt +++ b/tests/auto/testlib/selftests/expected_crashes_3.txt @@ -2,6 +2,7 @@ Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@ PASS : tst_Crashes::initTestCase() QFATAL : tst_Crashes::crash() Received signal 11 + Function time: ms Total time: ms FAIL! : tst_Crashes::crash() Received a fatal error. Loc: [Unknown file(0)] Totals: 1 passed, 1 failed, 0 skipped, 0 blacklisted diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index 11de65c3c0..63c48fc809 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -626,13 +626,28 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge for (int n = 0; n < loggers.count(); ++n) { QString logger = loggers[n]; -#if defined(Q_OS_WIN) - if (n == 0 && subdir == QLatin1String("crashes")) { // Remove stack trace which is output to stdout. - const int exceptionLogStart = actualOutputs.first().indexOf("A crash occurred in "); + if (n == 0 && subdir == QLatin1String("crashes")) { + QByteArray &actual = actualOutputs[0]; +#ifndef Q_OS_WIN + // Remove digits of times to match the expected file. + const QLatin1String timePattern("Function time:"); + int timePos = actual.indexOf(timePattern); + if (timePos >= 0) { + timePos += timePattern.size(); + const int nextLinePos = actual.indexOf('\n', timePos); + for (int c = (nextLinePos != -1 ? nextLinePos : actual.size()) - 1; c >= timePos; --c) { + if (actual.at(c) >= '0' && actual.at(c) <= '9') + actual.remove(c, 1); + } + } +#else // !Q_OS_WIN + // Remove stack trace which is output to stdout. + const int exceptionLogStart = actual.indexOf("A crash occurred in "); if (exceptionLogStart >= 0) - actualOutputs[0].truncate(exceptionLogStart); - } + actual.truncate(exceptionLogStart); #endif // Q_OS_WIN + } + QList res = splitLines(actualOutputs[n]); const QString expectedFileName = expectedFileNameFromTest(subdir, logger); QList exp = expectedResult(expectedFileName); From 0df5d079290b4c3b13e58e9397fabdc1dfdba96b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 25 Sep 2015 13:23:46 +0200 Subject: [PATCH 232/240] Don't let closed http sockets pass as valid connections A QAbstractSocket can be close()'d at any time, independently of its current connection state. being closed means that we cannot use it to read or write data, but internally it might still have some data to send or receive, for example to an http server. We can even get a connected() signal after close()'ing the socket. We need to catch this condition and mark any pending data not yet written to the socket for resending. Task-number: QTBUG-48326 Change-Id: I6f61c35f2c567f2a138f8cfe9ade7fd1ec039be6 Reviewed-by: Simon Hausmann --- .../access/qhttpnetworkconnectionchannel.cpp | 7 ++- .../tst_qhttpnetworkconnection.cpp | 54 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 293909c914..b4eda3477e 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -272,7 +272,12 @@ bool QHttpNetworkConnectionChannel::ensureConnection() QAbstractSocket::SocketState socketState = socket->state(); // resend this request after we receive the disconnected signal - if (socketState == QAbstractSocket::ClosingState) { + // If !socket->isOpen() then we have already called close() on the socket, but there was still a + // pending connectToHost() for which we hadn't seen a connected() signal, yet. The connected() + // has now arrived (as indicated by socketState != ClosingState), but we cannot send anything on + // such a socket anymore. + if (socketState == QAbstractSocket::ClosingState || + (socketState != QAbstractSocket::UnconnectedState && !socket->isOpen())) { if (reply) resendCurrent = true; return false; diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp index 5d072af6d5..0d188a8fec 100644 --- a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp +++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp @@ -36,6 +36,7 @@ #include "private/qhttpnetworkconnection_p.h" #include "private/qnoncontiguousbytedevice_p.h" #include +#include #include "../../../network-settings.h" @@ -106,6 +107,8 @@ private Q_SLOTS: void getAndThenDeleteObject(); void getAndThenDeleteObject_data(); + + void overlappingCloseAndWrite(); }; tst_QHttpNetworkConnection::tst_QHttpNetworkConnection() @@ -1112,6 +1115,57 @@ void tst_QHttpNetworkConnection::getAndThenDeleteObject() } } +class TestTcpServer : public QTcpServer +{ + Q_OBJECT +public: + TestTcpServer() : errorCodeReports(0) + { + connect(this, &QTcpServer::newConnection, this, &TestTcpServer::onNewConnection); + QVERIFY(listen(QHostAddress::LocalHost)); + } + + int errorCodeReports; + +public slots: + void onNewConnection() + { + QTcpSocket *socket = nextPendingConnection(); + if (!socket) + return; + // close socket instantly! + connect(socket, &QTcpSocket::readyRead, socket, &QTcpSocket::close); + } + + void onReply(QNetworkReply::NetworkError code) + { + QCOMPARE(code, QNetworkReply::RemoteHostClosedError); + ++errorCodeReports; + } +}; + +void tst_QHttpNetworkConnection::overlappingCloseAndWrite() +{ + // server accepts connections, but closes the socket instantly + TestTcpServer server; + QNetworkAccessManager accessManager; + + // ten requests are scheduled. All should result in an RemoteHostClosed... + QUrl url; + url.setScheme(QStringLiteral("http")); + url.setHost(server.serverAddress().toString()); + url.setPort(server.serverPort()); + for (int i = 0; i < 10; ++i) { + QNetworkRequest request(url); + QNetworkReply *reply = accessManager.get(request); + // Not using Qt5 connection syntax here because of overly baroque syntax to discern between + // different error() methods. + QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), + &server, SLOT(onReply(QNetworkReply::NetworkError))); + } + + QTRY_COMPARE(server.errorCodeReports, 10); +} QTEST_MAIN(tst_QHttpNetworkConnection) From 967e4f258cd39991fd2d0ac3753544900d51fbc2 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 31 Mar 2015 00:14:24 +0200 Subject: [PATCH 233/240] QLinkedList/QSet: add {const_,}reverse_iterator, {c,}r{begin,end}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now all Qt sequential containers consistently provide reverse iterators. The associative ones, by way of not returning std::pair from op*, can't just use std::reverse_iterator. They would miss .key() and .value() methods. So that has to wait for 5.7. The reverse versions of the new key_iterators can also just use std::reverse_iterator, but I'm afraid that after bikeshedding over keyRBegin() vs. rKeyBegin() vs. reverseKeyBegin() vs. rkbegin() vs. krbegin() (<-- of course, what else?), it would anyway be too late for 5.6, so defer, too. [ChangeLog][QtCore][QLinkedList/QSet] Added rbegin(), crbegin(), rend(), crend(), and reverse_iterator and const_reverse_iterator typedefs. Task-number: QTBUG-25919 Change-Id: I58316fffade469e9a42c61d7aa1455ae3443fd94 Reviewed-by: Sérgio Martins Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qlinkedlist.cpp | 78 +++++++++++++++++++ src/corelib/tools/qlinkedlist.h | 23 ++++-- src/corelib/tools/qset.h | 25 ++++-- src/corelib/tools/qset.qdoc | 78 +++++++++++++++++++ .../tools/qlinkedlist/tst_qlinkedlist.cpp | 16 ++++ tests/auto/corelib/tools/qset/tst_qset.cpp | 16 ++++ 6 files changed, 224 insertions(+), 12 deletions(-) diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp index fbd263e88b..5d91bfe924 100644 --- a/src/corelib/tools/qlinkedlist.cpp +++ b/src/corelib/tools/qlinkedlist.cpp @@ -388,6 +388,52 @@ const QLinkedListData QLinkedListData::shared_null = { \sa constBegin(), end() */ +/*! \fn QLinkedList::reverse_iterator QLinkedList::rbegin() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the list, in reverse order. + + \sa begin(), crbegin(), rend() +*/ + +/*! \fn QLinkedList::const_reverse_iterator QLinkedList::rbegin() const + \since 5.6 + \overload +*/ + +/*! \fn QLinkedList::const_reverse_iterator QLinkedList::crbegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the list, in reverse order. + + \sa begin(), rbegin(), rend() +*/ + +/*! \fn QLinkedList::reverse_iterator QLinkedList::rend() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past + the last item in the list, in reverse order. + + \sa end(), crend(), rbegin() +*/ + +/*! \fn QLinkedList::const_reverse_iterator QLinkedList::rend() const + \since 5.6 + \overload +*/ + +/*! \fn QLinkedList::const_reverse_iterator QLinkedList::crend() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one + past the last item in the list, in reverse order. + + \sa end(), rend(), rbegin() +*/ + /*! \fn QLinkedList::iterator QLinkedList::insert(iterator before, const T &value) Inserts \a value in front of the item pointed to by the iterator @@ -423,6 +469,38 @@ const QLinkedListData QLinkedListData::shared_null = { Qt-style synonym for QLinkedList::const_iterator. */ +/*! \typedef QLinkedList::reverse_iterator + \since 5.6 + + The QLinkedList::reverse_iterator typedef provides an STL-style non-const + reverse iterator for QLinkedList. + + It is simply a typedef for \c{std::reverse_iterator}. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QLinkedList::rbegin(), QLinkedList::rend(), QLinkedList::const_reverse_iterator, QLinkedList::iterator +*/ + +/*! \typedef QLinkedList::const_reverse_iterator + \since 5.6 + + The QLinkedList::const_reverse_iterator typedef provides an STL-style const + reverse iterator for QLinkedList. + + It is simply a typedef for \c{std::reverse_iterator}. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QLinkedList::rbegin(), QLinkedList::rend(), QLinkedList::reverse_iterator, QLinkedList::const_iterator +*/ + /*! \typedef QLinkedList::size_type diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 2854885d60..110529d843 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -183,14 +183,25 @@ public: friend class const_iterator; // stl style + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + inline iterator begin() { detach(); return e->n; } - inline const_iterator begin() const { return e->n; } - inline const_iterator cbegin() const { return e->n; } - inline const_iterator constBegin() const { return e->n; } + inline const_iterator begin() const Q_DECL_NOTHROW { return e->n; } + inline const_iterator cbegin() const Q_DECL_NOTHROW { return e->n; } + inline const_iterator constBegin() const Q_DECL_NOTHROW { return e->n; } inline iterator end() { detach(); return e; } - inline const_iterator end() const { return e; } - inline const_iterator cend() const { return e; } - inline const_iterator constEnd() const { return e; } + inline const_iterator end() const Q_DECL_NOTHROW { return e; } + inline const_iterator cend() const Q_DECL_NOTHROW { return e; } + inline const_iterator constEnd() const Q_DECL_NOTHROW { return e; } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); } + const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); } + const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); } + iterator insert(iterator before, const T &t); iterator erase(iterator pos); iterator erase(iterator first, iterator last); diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index ed89617cd6..3f4208e8b3 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -39,6 +39,8 @@ #include #endif +#include + QT_BEGIN_NAMESPACE @@ -161,14 +163,25 @@ public: }; // STL style + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + inline iterator begin() { return q_hash.begin(); } - inline const_iterator begin() const { return q_hash.begin(); } - inline const_iterator cbegin() const { return q_hash.begin(); } - inline const_iterator constBegin() const { return q_hash.constBegin(); } + inline const_iterator begin() const Q_DECL_NOTHROW { return q_hash.begin(); } + inline const_iterator cbegin() const Q_DECL_NOTHROW { return q_hash.begin(); } + inline const_iterator constBegin() const Q_DECL_NOTHROW { return q_hash.constBegin(); } inline iterator end() { return q_hash.end(); } - inline const_iterator end() const { return q_hash.end(); } - inline const_iterator cend() const { return q_hash.end(); } - inline const_iterator constEnd() const { return q_hash.constEnd(); } + inline const_iterator end() const Q_DECL_NOTHROW { return q_hash.end(); } + inline const_iterator cend() const Q_DECL_NOTHROW { return q_hash.end(); } + inline const_iterator constEnd() const Q_DECL_NOTHROW { return q_hash.constEnd(); } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); } + const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); } + const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); } + iterator erase(iterator i) { Q_ASSERT_X(isValidIterator(i), "QSet::erase", "The specified const_iterator argument 'i' is invalid"); diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc index d91a589aa1..542def4651 100644 --- a/src/corelib/tools/qset.qdoc +++ b/src/corelib/tools/qset.qdoc @@ -384,6 +384,52 @@ \sa constBegin(), end() */ +/*! \fn QSet::reverse_iterator QSet::rbegin() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the set, in reverse order. + + \sa begin(), crbegin(), rend() +*/ + +/*! \fn QSet::const_reverse_iterator QSet::rbegin() const + \since 5.6 + \overload +*/ + +/*! \fn QSet::const_reverse_iterator QSet::crbegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the set, in reverse order. + + \sa begin(), rbegin(), rend() +*/ + +/*! \fn QSet::reverse_iterator QSet::rend() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past + the last item in the set, in reverse order. + + \sa end(), crend(), rbegin() +*/ + +/*! \fn QSet::const_reverse_iterator QSet::rend() const + \since 5.6 + \overload +*/ + +/*! \fn QSet::const_reverse_iterator QSet::crend() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one + past the last item in the set, in reverse order. + + \sa end(), rend(), rbegin() +*/ + /*! \typedef QSet::Iterator \since 4.2 @@ -445,6 +491,38 @@ Typedef for T. Provided for STL compatibility. */ +/*! \typedef QSet::reverse_iterator + \since 5.6 + + The QSet::reverse_iterator typedef provides an STL-style non-const + reverse iterator for QSet. + + It is simply a typedef for \c{std::reverse_iterator}. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QSet::rbegin(), QSet::rend(), QSet::const_reverse_iterator, QSet::iterator +*/ + +/*! \typedef QSet::const_reverse_iterator + \since 5.6 + + The QSet::const_reverse_iterator typedef provides an STL-style const + reverse iterator for QSet. + + It is simply a typedef for \c{std::reverse_iterator}. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QSet::rbegin(), QSet::rend(), QSet::reverse_iterator, QSet::const_iterator +*/ + /*! \fn QSet::const_iterator QSet::insert(const T &value) diff --git a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp index 2e829bb05e..d3ace40164 100644 --- a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp +++ b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp @@ -204,6 +204,7 @@ private slots: void removeOneInt() const; void removeOneMovable() const; void removeOneComplex() const; + void reverseIterators() const; void startsWithInt() const; void startsWithMovable() const; void startsWithComplex() const; @@ -754,6 +755,21 @@ void tst_QLinkedList::removeOneComplex() const QCOMPARE(liveCount, Complex::getLiveCount()); } +void tst_QLinkedList::reverseIterators() const +{ + QLinkedList l; + l << 1 << 2 << 3 << 4; + QLinkedList lr = l; + std::reverse(lr.begin(), lr.end()); + const QLinkedList &clr = lr; + QVERIFY(std::equal(l.begin(), l.end(), lr.rbegin())); + QVERIFY(std::equal(l.begin(), l.end(), lr.crbegin())); + QVERIFY(std::equal(l.begin(), l.end(), clr.rbegin())); + QVERIFY(std::equal(lr.rbegin(), lr.rend(), l.begin())); + QVERIFY(std::equal(lr.crbegin(), lr.crend(), l.begin())); + QVERIFY(std::equal(clr.rbegin(), clr.rend(), l.begin())); +} + template void tst_QLinkedList::startsWith() const { diff --git a/tests/auto/corelib/tools/qset/tst_qset.cpp b/tests/auto/corelib/tools/qset/tst_qset.cpp index 134d257d64..fe4d81085c 100644 --- a/tests/auto/corelib/tools/qset/tst_qset.cpp +++ b/tests/auto/corelib/tools/qset/tst_qset.cpp @@ -65,6 +65,7 @@ private slots: void begin(); void end(); void insert(); + void reverseIterators(); void setOperations(); void stlIterator(); void stlMutableIterator(); @@ -555,6 +556,21 @@ void tst_QSet::insert() } } +void tst_QSet::reverseIterators() +{ + QSet s; + s << 1 << 17 << 61 << 127 << 911; + std::vector v(s.begin(), s.end()); + std::reverse(v.begin(), v.end()); + const QSet &cs = s; + QVERIFY(std::equal(v.begin(), v.end(), s.rbegin())); + QVERIFY(std::equal(v.begin(), v.end(), s.crbegin())); + QVERIFY(std::equal(v.begin(), v.end(), cs.rbegin())); + QVERIFY(std::equal(s.rbegin(), s.rend(), v.begin())); + QVERIFY(std::equal(s.crbegin(), s.crend(), v.begin())); + QVERIFY(std::equal(cs.rbegin(), cs.rend(), v.begin())); +} + void tst_QSet::setOperations() { QSet set1, set2; From b63c3d4d9a8917a84cf24439a0f75a17df0aafee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 30 Jun 2015 13:18:57 +0200 Subject: [PATCH 234/240] Make the CoreFoundation event dispatcher depend on QtCore only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In anticipation of moving it to QtCore. The call to QWindowSystemInterface::sendWindowSystemEvents() has been moved to QIOSEventDispatcher by making processPostedEvents() virtual. Change-Id: I9e03be4153a9f5f34e9a0ac942cdff572a44c318 Reviewed-by: Tor Arne Vestbø --- .../eventdispatchers/qeventdispatcher_cf.mm | 12 +++----- .../eventdispatchers/qeventdispatcher_cf_p.h | 30 ++++++++++--------- .../platforms/ios/qioseventdispatcher.h | 1 + .../platforms/ios/qioseventdispatcher.mm | 21 +++++++++++++ 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm b/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm index 13b7dc4358..0273fe5ed4 100644 --- a/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm +++ b/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm @@ -41,8 +41,6 @@ #include #include -#include - #include #include @@ -169,6 +167,7 @@ static const CFTimeInterval kCFTimeIntervalDistantFuture = std::numeric_limits class RunLoopSource { public: - typedef void (T::*CallbackFunction) (); + typedef bool (T::*CallbackFunction)(); enum { kHighestPriority = 0 } RunLoopSourcePriority; @@ -221,18 +221,8 @@ public: void interrupt(); void flush(); -private: - RunLoopSource<> m_postedEventsRunLoopSource; - RunLoopObserver<> m_runLoopActivityObserver; - - RunLoopModeTracker *m_runLoopModeTracker; - - QTimerInfoList m_timerInfoList; - CFRunLoopTimerRef m_runLoopTimer; - CFRunLoopTimerRef m_blockedRunLoopTimer; - bool m_overdueTimerScheduled; - - QCFSocketNotifier m_cfSocketNotifier; +protected: + virtual bool processPostedEvents(); struct ProcessEventsState { @@ -251,7 +241,19 @@ private: ProcessEventsState m_processEvents; - void processPostedEvents(); +private: + RunLoopSource<> m_postedEventsRunLoopSource; + RunLoopObserver<> m_runLoopActivityObserver; + + RunLoopModeTracker *m_runLoopModeTracker; + + QTimerInfoList m_timerInfoList; + CFRunLoopTimerRef m_runLoopTimer; + CFRunLoopTimerRef m_blockedRunLoopTimer; + bool m_overdueTimerScheduled; + + QCFSocketNotifier m_cfSocketNotifier; + void processTimers(CFRunLoopTimerRef); void handleRunLoopActivity(CFRunLoopActivity activity); diff --git a/src/plugins/platforms/ios/qioseventdispatcher.h b/src/plugins/platforms/ios/qioseventdispatcher.h index fdaa7e68fe..e8ea1cc28b 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.h +++ b/src/plugins/platforms/ios/qioseventdispatcher.h @@ -46,6 +46,7 @@ public: explicit QIOSEventDispatcher(QObject *parent = 0); bool processEvents(QEventLoop::ProcessEventsFlags flags) Q_DECL_OVERRIDE; + bool processPostedEvents() Q_DECL_OVERRIDE; void handleRunLoopExit(CFRunLoopActivity activity); diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index bd4b8778ed..0e9f176487 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -39,6 +39,8 @@ #include #include +#include + #import #import #import @@ -461,6 +463,25 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo return processedEvents; } +/*! + Override of the CoreFoundation posted events runloop source callback + so that we can send window system (QPA) events in addition to sending + normal Qt events. +*/ +bool QIOSEventDispatcher::processPostedEvents() +{ + // Don't send window system events if the base CF dispatcher has determined + // that events should not be sent for this pass of the runloop source. + if (!QEventDispatcherCoreFoundation::processPostedEvents()) + return false; + + qEventDispatcherDebug() << "Sending window system events for " << m_processEvents.flags; qIndent(); + QWindowSystemInterface::sendWindowSystemEvents(m_processEvents.flags); + qUnIndent(); + + return true; +} + void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity) { Q_UNUSED(activity); From 6046458dee115841c6f01b2a2e01b41be1bfbdc9 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 13 Oct 2015 15:54:18 +0200 Subject: [PATCH 235/240] eglfs: Handle custom platform window implementations better Backends may want to subclass QEglFSWindow and reimplement resetSurface() and similar. Make it possible to do this by moving window creation to the device integration interface, similarly to screens. In addition to customizing the windows, some backends may want to disable the dependency on surfaceless contexts when using offscreen windows (i.e. pbuffer surfaces). Make this possible too. Change-Id: Ic5a426e07f821c7a800217b8799f91770ba6a6d8 Reviewed-by: Oswald Buddenhagen Reviewed-by: Louai Al-Khanji --- .../eglconvenience/qeglconvenience_p.h | 1 - .../eglconvenience/qeglpbuffer.cpp | 6 ++-- .../eglconvenience/qeglpbuffer_p.h | 4 ++- .../eglconvenience/qeglplatformcontext.cpp | 5 +-- .../eglconvenience/qeglplatformcontext_p.h | 11 +++++- src/plugins/platforms/eglfs/qeglfscontext.cpp | 3 +- .../eglfs/qeglfsdeviceintegration.cpp | 21 ++++++++++++ .../platforms/eglfs/qeglfsdeviceintegration.h | 5 +++ .../platforms/eglfs/qeglfsintegration.cpp | 15 +++++--- src/plugins/platforms/eglfs/qeglfswindow.cpp | 34 ++++++++----------- src/plugins/platforms/eglfs/qeglfswindow.h | 2 +- 11 files changed, 73 insertions(+), 34 deletions(-) diff --git a/src/platformsupport/eglconvenience/qeglconvenience_p.h b/src/platformsupport/eglconvenience/qeglconvenience_p.h index 59441d8c9a..ec6f668cba 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience_p.h +++ b/src/platformsupport/eglconvenience/qeglconvenience_p.h @@ -88,7 +88,6 @@ public: protected: virtual bool filterConfig(EGLConfig config) const; -private: QSurfaceFormat m_format; EGLDisplay m_display; EGLint m_surfaceType; diff --git a/src/platformsupport/eglconvenience/qeglpbuffer.cpp b/src/platformsupport/eglconvenience/qeglpbuffer.cpp index 756609a641..d1a31642b2 100644 --- a/src/platformsupport/eglconvenience/qeglpbuffer.cpp +++ b/src/platformsupport/eglconvenience/qeglpbuffer.cpp @@ -49,13 +49,15 @@ QT_BEGIN_NAMESPACE and return a new instance of this class. */ -QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface) +QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface, + QEGLPlatformContext::Flags flags) : QPlatformOffscreenSurface(offscreenSurface) , m_format(format) , m_display(display) , m_pbuffer(EGL_NO_SURFACE) { - bool hasSurfaceless = q_hasEglExtension(display, "EGL_KHR_surfaceless_context"); + bool hasSurfaceless = !flags.testFlag(QEGLPlatformContext::NoSurfaceless) + && q_hasEglExtension(display, "EGL_KHR_surfaceless_context"); // Disable surfaceless contexts on Mesa for now. As of 10.6.0 and Intel at least, some // operations (glReadPixels) are unable to work without a surface since they at some diff --git a/src/platformsupport/eglconvenience/qeglpbuffer_p.h b/src/platformsupport/eglconvenience/qeglpbuffer_p.h index 3372c0735d..81fdab8901 100644 --- a/src/platformsupport/eglconvenience/qeglpbuffer_p.h +++ b/src/platformsupport/eglconvenience/qeglpbuffer_p.h @@ -47,13 +47,15 @@ #include #include +#include QT_BEGIN_NAMESPACE class QEGLPbuffer : public QPlatformOffscreenSurface { public: - QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface); + QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface, + QEGLPlatformContext::Flags flags = 0); ~QEGLPbuffer(); QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; } diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 2de7fb3b40..acd6197ed5 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -106,11 +106,12 @@ QT_BEGIN_NAMESPACE #endif QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig *config, const QVariant &nativeHandle) + EGLConfig *config, const QVariant &nativeHandle, Flags flags) : m_eglDisplay(display) , m_swapInterval(-1) , m_swapIntervalEnvChecked(false) , m_swapIntervalFromEnv(-1) + , m_flags(flags) { if (nativeHandle.isNull()) { m_eglConfig = config ? *config : q_configFromGLFormat(display, format); @@ -291,7 +292,7 @@ void QEGLPlatformContext::updateFormatFromGL() // drivers (Mesa) when certain attributes are present (multisampling). EGLSurface tempSurface = EGL_NO_SURFACE; EGLContext tempContext = EGL_NO_CONTEXT; - if (!q_hasEglExtension(m_eglDisplay, "EGL_KHR_surfaceless_context")) + if (m_flags.testFlag(NoSurfaceless) || !q_hasEglExtension(m_eglDisplay, "EGL_KHR_surfaceless_context")) tempSurface = createTemporaryOffscreenSurface(); EGLBoolean ok = eglMakeCurrent(m_eglDisplay, tempSurface, tempSurface, m_eglContext); diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index 2ab7ad28d0..2fa465556b 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -56,8 +56,14 @@ QT_BEGIN_NAMESPACE class QEGLPlatformContext : public QPlatformOpenGLContext { public: + enum Flag { + NoSurfaceless = 0x01 + }; + Q_DECLARE_FLAGS(Flags, Flag) + QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig *config = 0, const QVariant &nativeHandle = QVariant()); + EGLConfig *config = 0, const QVariant &nativeHandle = QVariant(), + Flags flags = 0); ~QEGLPlatformContext(); void initialize() Q_DECL_OVERRIDE; @@ -93,10 +99,13 @@ private: int m_swapInterval; bool m_swapIntervalEnvChecked; int m_swapIntervalFromEnv; + Flags m_flags; bool m_ownsContext; QVector m_contextAttrs; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QEGLPlatformContext::Flags) + QT_END_NAMESPACE #endif //QEGLPLATFORMCONTEXT_H diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp index e2223aba43..6fcdae7ad2 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -44,7 +44,8 @@ QT_BEGIN_NAMESPACE QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLConfig *config, const QVariant &nativeHandle) - : QEGLPlatformContext(format, share, display, config, nativeHandle), + : QEGLPlatformContext(format, share, display, config, nativeHandle, + qt_egl_device_integration()->supportsSurfacelessContexts() ? Flags(0) : QEGLPlatformContext::NoSurfaceless), m_tempWindow(0) { } diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp index d27c949c8d..0c2aa7ad61 100644 --- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp @@ -34,6 +34,7 @@ #include "qeglfsdeviceintegration.h" #include "qeglfsintegration.h" #include "qeglfscursor.h" +#include "qeglfswindow.h" #include #include #include @@ -175,6 +176,11 @@ EGLNativeDisplayType QEGLDeviceIntegration::platformDisplay() const return EGL_DEFAULT_DISPLAY; } +EGLDisplay QEGLDeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay) +{ + return eglGetDisplay(nativeDisplay); +} + bool QEGLDeviceIntegration::usesDefaultScreen() { return true; @@ -238,6 +244,11 @@ qreal QEGLDeviceIntegration::refreshRate() const return q_refreshRateFromFb(framebuffer); } +EGLint QEGLDeviceIntegration::surfaceType() const +{ + return EGL_WINDOW_BIT; +} + QSurfaceFormat QEGLDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const { QSurfaceFormat format = inputFormat; @@ -257,6 +268,11 @@ bool QEGLDeviceIntegration::filterConfig(EGLDisplay, EGLConfig) const return true; } +QEglFSWindow *QEGLDeviceIntegration::createWindow(QWindow *window) const +{ + return new QEglFSWindow(window); +} + EGLNativeWindowType QEGLDeviceIntegration::createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format) @@ -313,4 +329,9 @@ bool QEGLDeviceIntegration::supportsPBuffers() const return true; } +bool QEGLDeviceIntegration::supportsSurfacelessContexts() const +{ + return true; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h index 260fc313f7..d91d67de16 100644 --- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h @@ -56,6 +56,7 @@ QT_BEGIN_NAMESPACE class QPlatformSurface; +class QEglFSWindow; #define QEGLDeviceIntegrationFactoryInterface_iid "org.qt-project.qt.qpa.egl.QEGLDeviceIntegrationFactoryInterface.5.5" @@ -67,6 +68,7 @@ public: virtual void platformInit(); virtual void platformDestroy(); virtual EGLNativeDisplayType platformDisplay() const; + virtual EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay); virtual bool usesDefaultScreen(); virtual void screenInit(); virtual void screenDestroy(); @@ -79,6 +81,8 @@ public: virtual QImage::Format screenFormat() const; virtual qreal refreshRate() const; virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const; + virtual EGLint surfaceType() const; + virtual QEglFSWindow *createWindow(QWindow *window) const; virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format); @@ -92,6 +96,7 @@ public: virtual QByteArray fbDeviceName() const; virtual int framebufferIndex() const; virtual bool supportsPBuffers() const; + virtual bool supportsSurfacelessContexts() const; }; class Q_EGLFS_EXPORT QEGLDeviceIntegrationPlugin : public QObject diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index f0946b9b64..2df06caa6b 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -117,7 +117,7 @@ void QEglFSIntegration::initialize() { qt_egl_device_integration()->platformInit(); - m_display = eglGetDisplay(nativeDisplay()); + m_display = qt_egl_device_integration()->createDisplay(nativeDisplay()); if (m_display == EGL_NO_DISPLAY) qFatal("Could not open egl display"); @@ -179,7 +179,7 @@ QPlatformBackingStore *QEglFSIntegration::createPlatformBackingStore(QWindow *wi QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const { QWindowSystemInterface::flushWindowSystemEvents(); - QEglFSWindow *w = new QEglFSWindow(window); + QEglFSWindow *w = qt_egl_device_integration()->createWindow(window); w->create(); if (window->type() != Qt::ToolTip) w->requestActivateWindow(); @@ -213,10 +213,14 @@ QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOf { EGLDisplay dpy = surface->screen() ? static_cast(surface->screen()->handle())->display() : display(); QSurfaceFormat fmt = qt_egl_device_integration()->surfaceFormatFor(surface->requestedFormat()); - if (qt_egl_device_integration()->supportsPBuffers()) - return new QEGLPbuffer(dpy, fmt, surface); - else + if (qt_egl_device_integration()->supportsPBuffers()) { + QEGLPlatformContext::Flags flags = 0; + if (!qt_egl_device_integration()->supportsSurfacelessContexts()) + flags |= QEGLPlatformContext::NoSurfaceless; + return new QEGLPbuffer(dpy, fmt, surface, flags); + } else { return new QEglFSOffscreenWindow(dpy, fmt, surface); + } // Never return null. Multiple QWindows are not supported by this plugin. } @@ -433,6 +437,7 @@ EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceForm }; Chooser chooser(display); + chooser.setSurfaceType(qt_egl_device_integration()->surfaceType()); chooser.setSurfaceFormat(format); return chooser.chooseConfig(); } diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index c3b9dd6ef0..8301be8c17 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -51,7 +51,7 @@ QEglFSWindow::QEglFSWindow(QWindow *w) m_backingStore(0), m_raster(false), m_winId(0), - m_surface(0), + m_surface(EGL_NO_SURFACE), m_window(0), m_flags(0) { @@ -120,13 +120,14 @@ void QEglFSWindow::create() setGeometry(QRect()); // will become fullscreen QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size())); - EGLDisplay display = static_cast(screen)->display(); - QSurfaceFormat platformFormat = qt_egl_device_integration()->surfaceFormatFor(window()->requestedFormat()); - m_config = QEglFSIntegration::chooseConfig(display, platformFormat); - m_format = q_glFormatFromConfig(display, m_config, platformFormat); - resetSurface(); + if (m_surface == EGL_NO_SURFACE) { + EGLint error = eglGetError(); + eglTerminate(screen->display()); + qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error); + } + screen->setPrimarySurface(m_surface); if (isRaster()) { @@ -158,15 +159,10 @@ void QEglFSWindow::destroy() QOpenGLCompositor::instance()->removeWindow(this); } -// The virtual functions resetSurface and invalidateSurface may get overridden -// in derived classes, for example in the Android port, to perform the native -// window and surface creation differently. - void QEglFSWindow::invalidateSurface() { if (m_surface != EGL_NO_SURFACE) { - EGLDisplay display = static_cast(screen())->display(); - eglDestroySurface(display, m_surface); + eglDestroySurface(screen()->display(), m_surface); m_surface = EGL_NO_SURFACE; } qt_egl_device_integration()->destroyNativeWindow(m_window); @@ -175,15 +171,13 @@ void QEglFSWindow::invalidateSurface() void QEglFSWindow::resetSurface() { - QEglFSScreen *nativeScreen = static_cast(screen()); - EGLDisplay display = nativeScreen->display(); - m_window = qt_egl_device_integration()->createNativeWindow(this, nativeScreen->geometry().size(), m_format); + EGLDisplay display = screen()->display(); + QSurfaceFormat platformFormat = qt_egl_device_integration()->surfaceFormatFor(window()->requestedFormat()); + + m_config = QEglFSIntegration::chooseConfig(display, platformFormat); + m_format = q_glFormatFromConfig(display, m_config, platformFormat); + m_window = qt_egl_device_integration()->createNativeWindow(this, screen()->geometry().size(), m_format); m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL); - if (m_surface == EGL_NO_SURFACE) { - EGLint error = eglGetError(); - eglTerminate(display); - qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error); - } } void QEglFSWindow::setVisible(bool visible) diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index 53b9e18dc1..806b21de0a 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -89,7 +89,7 @@ public: const QPlatformTextureList *textures() const Q_DECL_OVERRIDE; void endCompositing() Q_DECL_OVERRIDE; -private: +protected: QOpenGLCompositorBackingStore *m_backingStore; bool m_raster; WId m_winId; From e82e075e51db598c5a6fe4da399c2b1966a36110 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 28 Sep 2015 16:33:29 +0200 Subject: [PATCH 236/240] QOpenGLWidget: Do not recurse when calling grabFramebuffer() from paintGL() Task-number: QTBUG-48450 Change-Id: I14b1ff40727f705d8b89371b4d3bb5d6adc139fe Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qopenglwidget.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 92f6066936..ee0543ceda 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -559,7 +559,8 @@ public: flushPending(false), paintDevice(0), updateBehavior(QOpenGLWidget::NoPartialUpdate), - requestedSamples(0) + requestedSamples(0), + inPaintGL(false) { requestedFormat = QSurfaceFormat::defaultFormat(); } @@ -602,6 +603,7 @@ public: QSurfaceFormat requestedFormat; QOpenGLWidget::UpdateBehavior updateBehavior; int requestedSamples; + bool inPaintGL; }; void QOpenGLWidgetPaintDevicePrivate::beginPaint() @@ -823,7 +825,9 @@ void QOpenGLWidgetPrivate::invokeUserPaint() QOpenGLContextPrivate::get(ctx)->defaultFboRedirect = fbo->handle(); f->glViewport(0, 0, q->width() * q->devicePixelRatioF(), q->height() * q->devicePixelRatioF()); + inPaintGL = true; q->paintGL(); + inPaintGL = false; flushPending = true; QOpenGLContextPrivate::get(ctx)->defaultFboRedirect = 0; @@ -870,7 +874,9 @@ QImage QOpenGLWidgetPrivate::grabFramebuffer() if (!initialized) return QImage(); - render(); + if (!inPaintGL) + render(); + resolveSamples(); q->makeCurrent(); QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatioF(), false, false); From bc6d32686cbec7e225999f19ba5fb149507c8dec Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 28 Sep 2015 16:42:27 +0200 Subject: [PATCH 237/240] QOpenGLWidget: Fix grabbing multisample framebuffers Task-number: QTBUG-48450 Change-Id: I0a680e0d682c7c08c3aea40d922bbf2ad66c1de0 Reviewed-by: Joni Poikelin Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qopenglwidget.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index ee0543ceda..65a70ceb02 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -877,11 +877,22 @@ QImage QOpenGLWidgetPrivate::grabFramebuffer() if (!inPaintGL) render(); - resolveSamples(); - q->makeCurrent(); + if (resolvedFbo) { + resolveSamples(); + resolvedFbo->bind(); + } else { + q->makeCurrent(); + } + QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatioF(), false, false); res.setDevicePixelRatio(q->devicePixelRatioF()); + // While we give no guarantees of what is going to be left bound, prefer the + // multisample fbo instead of the resolved one. Clients may continue to + // render straight after calling this function. + if (resolvedFbo) + q->makeCurrent(); + return res; } From f0d21f6921275032edfc35bf36f71807b90fdfa2 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 13 Oct 2015 16:07:19 +0200 Subject: [PATCH 238/240] Add support for the Jetson TK1 Pro using EGLDevice For now we pick one crtc and find the corresponding layer. If this is not desired, set QT_QPA_EGLFS_LAYER_INDEX to override the layer to be used. Enable qt.qpa.eglfs.kms to get logs about the available layers. Change-Id: I762783f960739e32966c8cde17d8f55fbe40091f Done-with: Louai Al-Khanji Reviewed-by: Oswald Buddenhagen Reviewed-by: Louai Al-Khanji --- .../qpa/eglfs-egldevice/eglfs-egldevice.cpp | 53 ++ .../qpa/eglfs-egldevice/eglfs-egldevice.pro | 12 + configure | 12 +- .../linux-jetson-tk1-pro-g++/qmake.conf | 38 ++ .../linux-jetson-tk1-pro-g++/qplatformdefs.h | 34 ++ .../deviceintegration/deviceintegration.pro | 1 + .../eglfs_kms_egldevice.json | 3 + .../eglfs_kms_egldevice.pro | 21 + .../qeglfskmsegldeviceintegration.cpp | 464 ++++++++++++++++++ .../qeglfskmsegldeviceintegration.h | 137 ++++++ .../qeglfskmsegldevicemain.cpp | 49 ++ 11 files changed, 823 insertions(+), 1 deletion(-) create mode 100644 config.tests/qpa/eglfs-egldevice/eglfs-egldevice.cpp create mode 100644 config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro create mode 100644 mkspecs/devices/linux-jetson-tk1-pro-g++/qmake.conf create mode 100644 mkspecs/devices/linux-jetson-tk1-pro-g++/qplatformdefs.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.json create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp diff --git a/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.cpp b/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.cpp new file mode 100644 index 0000000000..06809b2624 --- /dev/null +++ b/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +// Test both EGLDevice/Output/Stream and DRM as we only use them in combination. +// +// Other KMS/DRM tests relying on pkgconfig for libdrm are not suitable since +// some systems do not use pkgconfig for the graphics stuff. + +#include +#include +#include +#include +#include +#include + +int main(int, char **) +{ + EGLDeviceEXT device = 0; + EGLStreamKHR stream = 0; + EGLOutputLayerEXT layer = 0; + drmModeCrtcPtr currentMode = drmModeGetCrtc(0, 0); + return EGL_DRM_CRTC_EXT; +} diff --git a/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro b/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro new file mode 100644 index 0000000000..87214abc7a --- /dev/null +++ b/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro @@ -0,0 +1,12 @@ +SOURCES = eglfs-egldevice.cpp + +for(p, QMAKE_LIBDIR_EGL) { + exists($$p):LIBS += -L$$p +} + +INCLUDEPATH += $$QMAKE_INCDIR_EGL +LIBS += $$QMAKE_LIBS_EGL + +LIBS += -ldrm + +CONFIG -= qt diff --git a/configure b/configure index 80ed12cdbe..3a32487dcf 100755 --- a/configure +++ b/configure @@ -685,6 +685,7 @@ CFG_XCB_XLIB=auto CFG_XCB_GLX=no CFG_EGLFS=auto CFG_EGLFS_BRCM=no +CFG_EGLFS_EGLDEVICE=no CFG_EGLFS_MALI=no CFG_EGLFS_VIV=no CFG_DIRECTFB=auto @@ -5746,6 +5747,11 @@ if [ "$CFG_EGLFS" != "no" ]; then else CFG_EGLFS_BRCM=no fi + if compileTest qpa/eglfs-egldevice "eglfs-egldevice"; then + CFG_EGLFS_EGLDEVICE=yes + else + CFG_EGLFS_EGLDEVICE=no + fi if compileTest qpa/eglfs-mali "eglfs-mali" \ || compileTest qpa/eglfs-mali-2 "eglfs-mali-2"; then CFG_EGLFS_MALI=yes @@ -6194,6 +6200,9 @@ fi if [ "$CFG_EGLFS_BRCM" = "yes" ]; then QT_CONFIG="$QT_CONFIG eglfs_brcm" fi +if [ "$CFG_EGLFS_EGLDEVICE" = "yes" ]; then + QT_CONFIG="$QT_CONFIG eglfs_egldevice" +fi if [ "$CFG_EGLFS_MALI" = "yes" ]; then QT_CONFIG="$QT_CONFIG eglfs_mali" fi @@ -7259,7 +7268,8 @@ report_support " PulseAudio ............." "$CFG_PULSEAUDIO" report_support " QPA backends:" report_support " DirectFB ............." "$CFG_DIRECTFB" report_support " EGLFS ................" "$CFG_EGLFS" -report_support " EGLFS i.MX6....... ." "$CFG_EGLFS_VIV" +report_support " EGLFS i.MX6 ........" "$CFG_EGLFS_VIV" +report_support " EGLFS EGLDevice ...." "$CFG_EGLFS_EGLDEVICE" report_support " EGLFS KMS .........." "$CFG_KMS" report_support " EGLFS Mali ........." "$CFG_EGLFS_MALI" report_support " EGLFS Raspberry Pi ." "$CFG_EGLFS_BRCM" diff --git a/mkspecs/devices/linux-jetson-tk1-pro-g++/qmake.conf b/mkspecs/devices/linux-jetson-tk1-pro-g++/qmake.conf new file mode 100644 index 0000000000..ca9ebda087 --- /dev/null +++ b/mkspecs/devices/linux-jetson-tk1-pro-g++/qmake.conf @@ -0,0 +1,38 @@ +# +# qmake configuration for the Jetson TK1 Pro boards +# +# A typical configure line might look like: +# configure \ +# -device jetson-tk1-pro \ +# -device-option VIBRANTE_SDK_TOPDIR=/opt/nvidia/vibrante-vcm30t124-linux +# -device-option CROSS_COMPILE=/opt/nvidia/toolchains/tegra-4.8.1-nv/usr/bin/arm-cortex_a15-linux-gnueabi/arm-cortex_a15-linux-gnueabi- \ +# -sysroot /opt/nvidia/vibrante-vcm30t124-linux/targetfs \ +# -no-gcc-sysroot + +include(../common/linux_device_pre.conf) + +isEmpty(VIBRANTE_SDK_TOPDIR):error("You must pass -device-option VIBRANTE_SDK_TOPDIR=/path/to/sdk") + +QMAKE_INCDIR += \ + $${VIBRANTE_SDK_TOPDIR}/include \ + $$[QT_SYSROOT]/usr/include + +QMAKE_LIBDIR += \ + $${VIBRANTE_SDK_TOPDIR}/lib-target \ + $$[QT_SYSROOT]/usr/lib \ + $$[QT_SYSROOT]/lib/arm-linux-gnueabihf \ + $$[QT_SYSROOT]/usr/lib/arm-linux-gnueabihf + +QMAKE_LFLAGS += \ + -Wl,-rpath-link,$${VIBRANTE_SDK_TOPDIR}/lib-target \ + -Wl,-rpath-link,$$[QT_SYSROOT]/usr/lib \ + -Wl,-rpath-link,$$[QT_SYSROOT]/usr/lib/arm-linux-gnueabihf \ + -Wl,-rpath-link,$$[QT_SYSROOT]/lib/arm-linux-gnueabihf + +DISTRO_OPTS += hard-float +COMPILER_FLAGS += -mtune=cortex-a15 -march=armv7-a -mfpu=neon-vfpv4 -DWIN_INTERFACE_CUSTOM + +EGLFS_DEVICE_INTEGRATION = eglfs_kms_egldevice + +include(../common/linux_arm_device_post.conf) +load(qt_config) diff --git a/mkspecs/devices/linux-jetson-tk1-pro-g++/qplatformdefs.h b/mkspecs/devices/linux-jetson-tk1-pro-g++/qplatformdefs.h new file mode 100644 index 0000000000..beacd150b8 --- /dev/null +++ b/mkspecs/devices/linux-jetson-tk1-pro-g++/qplatformdefs.h @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins 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 "../../linux-g++/qplatformdefs.h" diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro index 0adbb0d49f..f8bb854f1c 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro @@ -2,6 +2,7 @@ TEMPLATE = subdirs contains(QT_CONFIG, egl_x11): SUBDIRS += eglfs_x11 contains(QT_CONFIG, kms): SUBDIRS += eglfs_kms +contains(QT_CONFIG, eglfs_egldevice): SUBDIRS += eglfs_kms_egldevice contains(QT_CONFIG, eglfs_brcm): SUBDIRS += eglfs_brcm contains(QT_CONFIG, eglfs_mali): SUBDIRS += eglfs_mali contains(QT_CONFIG, eglfs_viv): SUBDIRS += eglfs_viv diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.json new file mode 100644 index 0000000000..169ba1eb02 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs_kms_egldevice" ] +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro new file mode 100644 index 0000000000..2274c5b228 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro @@ -0,0 +1,21 @@ +TARGET = qeglfs-kms-egldevice-integration + +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSKmsEglDeviceIntegrationPlugin +load(qt_plugin) + +QT += core-private gui-private platformsupport-private eglfs_device_lib-private + +INCLUDEPATH += $$PWD/../.. + +CONFIG += egl +QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF + +SOURCES += $$PWD/qeglfskmsegldevicemain.cpp \ + $$PWD/qeglfskmsegldeviceintegration.cpp + +HEADERS += $$PWD/qeglfskmsegldeviceintegration.h + +OTHER_FILES += $$PWD/eglfs_kms_egldevice.json + +LIBS += -ldrm diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp new file mode 100644 index 0000000000..2f32bd73a3 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -0,0 +1,464 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins 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 "qeglfskmsegldeviceintegration.h" +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms") + +QEglFSKmsEglDeviceIntegration::QEglFSKmsEglDeviceIntegration() + : m_dri_fd(-1) + , m_egl_device(EGL_NO_DEVICE_EXT) + , m_egl_display(EGL_NO_DISPLAY) + , m_drm_connector(Q_NULLPTR) + , m_drm_encoder(Q_NULLPTR) + , m_drm_crtc(0) +{ + qCDebug(qLcEglfsKmsDebug, "New DRM/KMS on EGLDevice integration created"); +} + +void QEglFSKmsEglDeviceIntegration::platformInit() +{ + if (!query_egl_device()) + qFatal("Could not set up EGL device!"); + + const char *deviceName = m_query_device_string(m_egl_device, EGL_DRM_DEVICE_FILE_EXT); + if (!deviceName) + qFatal("Failed to query device name from EGLDevice"); + + qCDebug(qLcEglfsKmsDebug, "Opening %s", deviceName); + + m_dri_fd = drmOpen(deviceName, Q_NULLPTR); + if (m_dri_fd < 0) + qFatal("Could not open DRM device"); + + if (!setup_kms()) + qFatal("Could not set up KMS on device %s!", m_device.constData()); + + qCDebug(qLcEglfsKmsDebug, "DRM/KMS initialized"); +} + +void QEglFSKmsEglDeviceIntegration::platformDestroy() +{ + if (qt_safe_close(m_dri_fd) == -1) + qErrnoWarning("Could not close DRM device"); + + m_dri_fd = -1; +} + +EGLNativeDisplayType QEglFSKmsEglDeviceIntegration::platformDisplay() const +{ + return static_cast(m_egl_device); +} + +EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay) +{ + qCDebug(qLcEglfsKmsDebug, "Creating display"); + + const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + + m_get_platform_display = reinterpret_cast(eglGetProcAddress("eglGetPlatformDisplayEXT")); + m_has_egl_platform_device = extensions && strstr(extensions, "EGL_EXT_platform_device"); + + EGLDisplay display; + + if (!m_has_egl_platform_device) { + qWarning("EGL_EXT_platform_device not available, falling back to legacy path!"); + display = eglGetDisplay(nativeDisplay); + } else { + display = m_get_platform_display(EGL_PLATFORM_DEVICE_EXT, nativeDisplay, Q_NULLPTR); + } + + if (display == EGL_NO_DISPLAY) + qFatal("Could not get EGL display"); + + EGLint major, minor; + if (!eglInitialize(display, &major, &minor)) + qFatal("Could not initialize egl display"); + + if (!eglBindAPI(EGL_OPENGL_ES_API)) + qFatal("Failed to bind EGL_OPENGL_ES_API\n"); + + return display; +} + +QSizeF QEglFSKmsEglDeviceIntegration::physicalScreenSize() const +{ + return QSizeF(m_drm_connector->mmWidth, m_drm_connector->mmHeight); +} + +QSize QEglFSKmsEglDeviceIntegration::screenSize() const +{ + return QSize(m_drm_mode.hdisplay, m_drm_mode.vdisplay); +} + +int QEglFSKmsEglDeviceIntegration::screenDepth() const +{ + return 32; +} + +QSurfaceFormat QEglFSKmsEglDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +{ + QSurfaceFormat format(inputFormat); + format.setRenderableType(QSurfaceFormat::OpenGLES); + format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + format.setRedBufferSize(8); + format.setGreenBufferSize(8); + format.setBlueBufferSize(8); + return format; +} + +EGLint QEglFSKmsEglDeviceIntegration::surfaceType() const +{ + return EGL_STREAM_BIT_KHR; +} + +class QEglJetsonTK1Window : public QEglFSWindow +{ +public: + QEglJetsonTK1Window(QWindow *w, const QEglFSKmsEglDeviceIntegration *integration) + : QEglFSWindow(w) + , m_integration(integration) + , m_egl_stream(EGL_NO_STREAM_KHR) + { } + + void invalidateSurface() Q_DECL_OVERRIDE; + void resetSurface() Q_DECL_OVERRIDE; + + const QEglFSKmsEglDeviceIntegration *m_integration; + EGLStreamKHR m_egl_stream; + EGLint m_latency; +}; + +void QEglJetsonTK1Window::invalidateSurface() +{ + QEglFSWindow::invalidateSurface(); + m_integration->m_destroy_stream(screen()->display(), m_egl_stream); +} + +void QEglJetsonTK1Window::resetSurface() +{ + qCDebug(qLcEglfsKmsDebug, "Creating stream"); + + EGLDisplay display = screen()->display(); + EGLOutputLayerEXT layer = EGL_NO_OUTPUT_LAYER_EXT; + EGLint count; + + m_egl_stream = m_integration->m_create_stream(display, Q_NULLPTR); + if (m_egl_stream == EGL_NO_STREAM_KHR) { + qWarning("resetSurface: Couldn't create EGLStream for native window"); + return; + } + + qCDebug(qLcEglfsKmsDebug, "Created stream %p on display %p", m_egl_stream, display); + + if (!m_integration->m_get_output_layers(display, Q_NULLPTR, Q_NULLPTR, 0, &count) || count == 0) { + qWarning("No output layers found"); + return; + } + + qCDebug(qLcEglfsKmsDebug, "Output has %d layers", count); + + QVector layers; + layers.resize(count); + EGLint actualCount; + if (!m_integration->m_get_output_layers(display, Q_NULLPTR, layers.data(), count, &actualCount)) { + qWarning("Failed to get layers"); + return; + } + + for (int i = 0; i < actualCount; ++i) { + EGLAttrib id; + if (m_integration->m_query_output_layer_attrib(display, layers[i], EGL_DRM_CRTC_EXT, &id)) { + qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - crtc %d", i, layers[i], id); + if (id == EGLAttrib(m_integration->m_drm_crtc)) + layer = layers[i]; + } else if (m_integration->m_query_output_layer_attrib(display, layers[i], EGL_DRM_PLANE_EXT, &id)) { + // Not used yet, just for debugging. + qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - plane %d", i, layers[i], id); + } else { + qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - unknown", i, layers[i]); + } + } + + QByteArray reqLayerIndex = qgetenv("QT_QPA_EGLFS_LAYER_INDEX"); + if (!reqLayerIndex.isEmpty()) { + int idx = reqLayerIndex.toInt(); + if (idx >= 0 && idx < layers.count()) + layer = layers[idx]; + } + + if (layer == EGL_NO_OUTPUT_LAYER_EXT) { + qWarning("resetSurface: Couldn't get EGLOutputLayer for native window"); + return; + } + + qCDebug(qLcEglfsKmsDebug, "Using layer %p", layer); + + if (!m_integration->m_stream_consumer_output(display, m_egl_stream, layer)) + qWarning("resetSurface: Unable to connect stream"); + + m_config = QEglFSIntegration::chooseConfig(display, m_integration->surfaceFormatFor(window()->requestedFormat())); + m_format = q_glFormatFromConfig(display, m_config); + qCDebug(qLcEglfsKmsDebug) << "Stream producer format is" << m_format; + + const int w = m_integration->screenSize().width(); + const int h = m_integration->screenSize().height(); + qCDebug(qLcEglfsKmsDebug, "Creating stream producer surface of size %dx%d", w, h); + + const EGLint stream_producer_attribs[] = { + EGL_WIDTH, w, + EGL_HEIGHT, h, + EGL_NONE + }; + + m_surface = m_integration->m_create_stream_producer_surface(display, m_config, m_egl_stream, stream_producer_attribs); + if (m_surface == EGL_NO_SURFACE) + return; + + qCDebug(qLcEglfsKmsDebug, "Created stream producer surface %p", m_surface); +} + +QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const +{ + QEglJetsonTK1Window *eglWindow = new QEglJetsonTK1Window(window, this); + + if (!const_cast(this)->query_egl_extensions(eglWindow->screen()->display())) + qFatal("Required extensions missing!"); + + return eglWindow; +} + +bool QEglFSKmsEglDeviceIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case QPlatformIntegration::ThreadedPixmaps: + case QPlatformIntegration::OpenGL: + case QPlatformIntegration::ThreadedOpenGL: + case QPlatformIntegration::BufferQueueingOpenGL: + return true; + default: + return false; + } +} + +void QEglFSKmsEglDeviceIntegration::waitForVSync(QPlatformSurface *) const +{ + static bool mode_set = false; + + if (!mode_set) { + mode_set = true; + + drmModeCrtcPtr currentMode = drmModeGetCrtc(m_dri_fd, m_drm_crtc); + const bool alreadySet = currentMode + && currentMode->width == m_drm_mode.hdisplay + && currentMode->height == m_drm_mode.vdisplay; + if (currentMode) + drmModeFreeCrtc(currentMode); + if (alreadySet) { + qCDebug(qLcEglfsKmsDebug, "Mode already set"); + return; + } + + qCDebug(qLcEglfsKmsDebug, "Setting mode"); + int ret = drmModeSetCrtc(m_dri_fd, m_drm_crtc, + -1, 0, 0, + &m_drm_connector->connector_id, 1, + const_cast(&m_drm_mode)); + if (ret) + qFatal("drmModeSetCrtc failed"); + } +} + +qreal QEglFSKmsEglDeviceIntegration::refreshRate() const +{ + quint32 refresh = m_drm_mode.vrefresh; + return refresh > 0 ? refresh : 60; +} + +bool QEglFSKmsEglDeviceIntegration::supportsSurfacelessContexts() const +{ + // Returning false disables the usage of EGL_KHR_surfaceless_context even when the + // extension is available. This is just what we need since, at least with NVIDIA + // 352.00 making a null surface current with a context breaks. + return false; +} + +bool QEglFSKmsEglDeviceIntegration::setup_kms() +{ + drmModeRes *resources; + drmModeConnector *connector; + drmModeEncoder *encoder; + quint32 crtc = 0; + int i; + + resources = drmModeGetResources(m_dri_fd); + if (!resources) { + qWarning("drmModeGetResources failed"); + return false; + } + + for (i = 0; i < resources->count_connectors; i++) { + connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]); + if (!connector) + continue; + + if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0) + break; + + drmModeFreeConnector(connector); + } + + if (i == resources->count_connectors) { + qWarning("No currently active connector found."); + return false; + } + + qCDebug(qLcEglfsKmsDebug, "Using connector with type %d", connector->connector_type); + + for (i = 0; i < resources->count_encoders; i++) { + encoder = drmModeGetEncoder(m_dri_fd, resources->encoders[i]); + if (!encoder) + continue; + + if (encoder->encoder_id == connector->encoder_id) + break; + + drmModeFreeEncoder(encoder); + } + + for (int j = 0; j < resources->count_crtcs; j++) { + if ((encoder->possible_crtcs & (1 << j))) { + crtc = resources->crtcs[j]; + break; + } + } + + if (crtc == 0) + qFatal("No suitable CRTC available"); + + m_drm_connector = connector; + m_drm_encoder = encoder; + m_drm_mode = connector->modes[0]; + m_drm_crtc = crtc; + + qCDebug(qLcEglfsKmsDebug).noquote() << "Using crtc" << m_drm_crtc + << "with mode" << m_drm_mode.hdisplay << "x" << m_drm_mode.vdisplay + << "@" << m_drm_mode.vrefresh; + + drmModeFreeResources(resources); + + return true; +} + +bool QEglFSKmsEglDeviceIntegration::query_egl_device() +{ + const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + if (!extensions) { + qWarning("eglQueryString failed"); + return false; + } + + m_has_egl_device_base = strstr(extensions, "EGL_EXT_device_base"); + m_query_devices = reinterpret_cast(eglGetProcAddress("eglQueryDevicesEXT")); + m_query_device_string = reinterpret_cast(eglGetProcAddress("eglQueryDeviceStringEXT")); + + if (!m_has_egl_device_base || !m_query_devices || !m_query_device_string) + qFatal("EGL_EXT_device_base missing"); + + EGLint num_devices = 0; + if (m_query_devices(1, &m_egl_device, &num_devices) != EGL_TRUE) { + qWarning("eglQueryDevicesEXT failed: eglError: %x", eglGetError()); + return false; + } + + qCDebug(qLcEglfsKmsDebug, "Found %d EGL devices", num_devices); + + if (num_devices < 1 || m_egl_device == EGL_NO_DEVICE_EXT) { + qWarning("eglQueryDevicesEXT could not find any EGL devices"); + return false; + } + + return true; +} + +bool QEglFSKmsEglDeviceIntegration::query_egl_extensions(EGLDisplay display) +{ + if (!eglBindAPI(EGL_OPENGL_ES_API)) { + qWarning() << Q_FUNC_INFO << "failed to bind EGL_OPENGL_ES_API"; + return false; + } + + m_create_stream = reinterpret_cast(eglGetProcAddress("eglCreateStreamKHR")); + m_destroy_stream = reinterpret_cast(eglGetProcAddress("eglDestroyStreamKHR")); + m_stream_attrib = reinterpret_cast(eglGetProcAddress("eglStreamAttribKHR")); + m_query_stream = reinterpret_cast(eglGetProcAddress("eglQueryStreamKHR")); + m_query_stream_u64 = reinterpret_cast(eglGetProcAddress("eglQueryStreamu64KHR")); + m_create_stream_producer_surface = reinterpret_cast(eglGetProcAddress("eglCreateStreamProducerSurfaceKHR")); + m_stream_consumer_output = reinterpret_cast(eglGetProcAddress("eglStreamConsumerOutputEXT")); + m_get_output_layers = reinterpret_cast(eglGetProcAddress("eglGetOutputLayersEXT")); + m_get_output_ports = reinterpret_cast(eglGetProcAddress("eglGetOutputPortsEXT")); + m_output_layer_attrib = reinterpret_cast(eglGetProcAddress("eglOutputLayerAttribEXT")); + m_query_output_layer_attrib = reinterpret_cast(eglGetProcAddress("eglQueryOutputLayerAttribEXT")); + m_query_output_layer_string = reinterpret_cast(eglGetProcAddress("eglQueryOutputLayerStringEXT")); + m_query_output_port_attrib = reinterpret_cast(eglGetProcAddress("eglQueryOutputPortAttribEXT")); + m_query_output_port_string = reinterpret_cast(eglGetProcAddress("eglQueryOutputPortStringEXT")); + m_get_stream_file_descriptor = reinterpret_cast(eglGetProcAddress("eglGetStreamFileDescriptorKHR")); + m_create_stream_from_file_descriptor = reinterpret_cast(eglGetProcAddress("eglCreateStreamFromFileDescriptorKHR")); + m_stream_consumer_gltexture = reinterpret_cast(eglGetProcAddress("eglStreamConsumerGLTextureExternalKHR")); + m_stream_consumer_acquire = reinterpret_cast(eglGetProcAddress("eglStreamConsumerAcquireKHR")); + + const char *extensions = eglQueryString(display, EGL_EXTENSIONS); + if (!extensions) { + qWarning() << Q_FUNC_INFO << "eglQueryString failed"; + return false; + } + + m_has_egl_stream = strstr(extensions, "EGL_KHR_stream"); + m_has_egl_stream_producer_eglsurface = strstr(extensions, "EGL_KHR_stream_producer_eglsurface"); + m_has_egl_stream_consumer_egloutput = strstr(extensions, "EGL_EXT_stream_consumer_egloutput"); + m_has_egl_output_drm = strstr(extensions, "EGL_EXT_output_drm"); + m_has_egl_output_base = strstr(extensions, "EGL_EXT_output_base"); + m_has_egl_stream_cross_process_fd = strstr(extensions, "EGL_KHR_stream_cross_process_fd"); + m_has_egl_stream_consumer_gltexture = strstr(extensions, "EGL_KHR_stream_consumer_gltexture"); + + return m_has_egl_output_base && + m_has_egl_output_drm && + m_has_egl_stream && + m_has_egl_stream_producer_eglsurface && + m_has_egl_stream_consumer_egloutput; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h new file mode 100644 index 0000000000..c6132354a8 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins 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 QEGLFSKMSEGLDEVICEINTEGRATION_H +#define QEGLFSKMSEGLDEVICEINTEGRATION_H + +#include "qeglfsdeviceintegration.h" +#include "qeglfswindow.h" +#include "qeglfsintegration.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QEglFSKmsEglDeviceIntegration : public QEGLDeviceIntegration +{ +public: + QEglFSKmsEglDeviceIntegration(); + + void platformInit() Q_DECL_OVERRIDE; + void platformDestroy() Q_DECL_OVERRIDE; + EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; + EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) Q_DECL_OVERRIDE; + QSizeF physicalScreenSize() const Q_DECL_OVERRIDE; + QSize screenSize() const Q_DECL_OVERRIDE; + int screenDepth() const Q_DECL_OVERRIDE; + qreal refreshRate() const Q_DECL_OVERRIDE; + QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE; + EGLint surfaceType() const Q_DECL_OVERRIDE; + QEglFSWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; + void waitForVSync(QPlatformSurface *surface) const Q_DECL_OVERRIDE; + bool supportsSurfacelessContexts() const Q_DECL_OVERRIDE; + + bool setup_kms(); + + bool query_egl_device(); + bool query_egl_extensions(EGLDisplay display); + + // device bits + QByteArray m_device; + int m_dri_fd; + EGLDeviceEXT m_egl_device; + EGLDisplay m_egl_display; + + // KMS bits + drmModeConnector *m_drm_connector; + drmModeEncoder *m_drm_encoder; + drmModeModeInfo m_drm_mode; + quint32 m_drm_crtc; + + // EGLStream infrastructure + PFNEGLGETPLATFORMDISPLAYEXTPROC m_get_platform_display; + bool m_has_egl_platform_device; + + PFNEGLQUERYDEVICESEXTPROC m_query_devices; + PFNEGLQUERYDEVICESTRINGEXTPROC m_query_device_string; + bool m_has_egl_device_base; + + PFNEGLCREATESTREAMKHRPROC m_create_stream; + PFNEGLDESTROYSTREAMKHRPROC m_destroy_stream; + PFNEGLSTREAMATTRIBKHRPROC m_stream_attrib; + PFNEGLQUERYSTREAMKHRPROC m_query_stream; + PFNEGLQUERYSTREAMU64KHRPROC m_query_stream_u64; + bool m_has_egl_stream; + + PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC m_create_stream_producer_surface; + bool m_has_egl_stream_producer_eglsurface; + + PFNEGLSTREAMCONSUMEROUTPUTEXTPROC m_stream_consumer_output; + bool m_has_egl_stream_consumer_egloutput; + + bool m_has_egl_output_drm; + + PFNEGLGETOUTPUTLAYERSEXTPROC m_get_output_layers; + PFNEGLGETOUTPUTPORTSEXTPROC m_get_output_ports; + PFNEGLOUTPUTLAYERATTRIBEXTPROC m_output_layer_attrib; + PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC m_query_output_layer_attrib; + PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC m_query_output_layer_string; + PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC m_query_output_port_attrib; + PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC m_query_output_port_string; + bool m_has_egl_output_base; + + PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC m_get_stream_file_descriptor; + PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC m_create_stream_from_file_descriptor; + bool m_has_egl_stream_cross_process_fd; + + PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC m_stream_consumer_gltexture; + PFNEGLSTREAMCONSUMERACQUIREKHRPROC m_stream_consumer_acquire; + bool m_has_egl_stream_consumer_gltexture; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp new file mode 100644 index 0000000000..f987ae38a6 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** 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 "qeglfskmsegldeviceintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSKmsEglDeviceIntegrationPlugin : public QEGLDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_kms_egldevice.json") + +public: + QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsEglDeviceIntegration; } +}; + +QT_END_NAMESPACE + +#include "qeglfskmsegldevicemain.moc" From 0a203bf753f2dc40257f1fcde20607e8f9853780 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 13 Oct 2015 16:09:51 +0200 Subject: [PATCH 239/240] Separate KMS and GBM tests KMS is no longer a platform plugin so the relevant leftover bits are now removed. As the introduction of the EGLDevice-based backend for eglfs shows, using DRM/KMS is not tied to GBM, separate buffer management approaches, like EGLStreams, work fine as well. Therefore separate KMS from GBM and remove the EGL and GLES dependency in the tests - this way there is nothing preventing us from using GBM without GL for example. Change-Id: Id7ebe172b44b315f9a637892237d2bb62d99aed2 Reviewed-by: Oswald Buddenhagen Reviewed-by: Louai Al-Khanji --- config.tests/qpa/gbm/gbm.cpp | 44 ++++++++++++++ config.tests/qpa/gbm/gbm.pro | 4 ++ config.tests/qpa/kms/kms.cpp | 7 +-- config.tests/qpa/kms/kms.pro | 2 +- configure | 60 ++++++++++++------- .../deviceintegration/deviceintegration.pro | 2 +- 6 files changed, 91 insertions(+), 28 deletions(-) create mode 100644 config.tests/qpa/gbm/gbm.cpp create mode 100644 config.tests/qpa/gbm/gbm.pro diff --git a/config.tests/qpa/gbm/gbm.cpp b/config.tests/qpa/gbm/gbm.cpp new file mode 100644 index 0000000000..d4f211163d --- /dev/null +++ b/config.tests/qpa/gbm/gbm.cpp @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** 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 +extern "C" { +#include +} + +int main(int, char **) +{ + gbm_surface *surface = 0; + return 0; +} diff --git a/config.tests/qpa/gbm/gbm.pro b/config.tests/qpa/gbm/gbm.pro new file mode 100644 index 0000000000..19177062a8 --- /dev/null +++ b/config.tests/qpa/gbm/gbm.pro @@ -0,0 +1,4 @@ +SOURCES = gbm.cpp +CONFIG += link_pkgconfig +PKGCONFIG += gbm +CONFIG -= qt diff --git a/config.tests/qpa/kms/kms.cpp b/config.tests/qpa/kms/kms.cpp index 64c11158c5..ac0c281386 100644 --- a/config.tests/qpa/kms/kms.cpp +++ b/config.tests/qpa/kms/kms.cpp @@ -32,17 +32,14 @@ ****************************************************************************/ #include +#include extern "C" { -#include #include #include } -#include -#include int main(int, char **) { - // Check for gbm_surface which is quite a recent addition. - gbm_surface *surface = 0; + drmModeCrtcPtr currentMode = drmModeGetCrtc(0, 0); return 0; } diff --git a/config.tests/qpa/kms/kms.pro b/config.tests/qpa/kms/kms.pro index 618063dbb9..1fb73677e7 100644 --- a/config.tests/qpa/kms/kms.pro +++ b/config.tests/qpa/kms/kms.pro @@ -1,4 +1,4 @@ SOURCES = kms.cpp CONFIG += link_pkgconfig -PKGCONFIG += libdrm libudev egl gbm glesv2 +PKGCONFIG += libdrm libudev CONFIG -= qt diff --git a/configure b/configure index 3a32487dcf..996990706b 100755 --- a/configure +++ b/configure @@ -689,6 +689,7 @@ CFG_EGLFS_EGLDEVICE=no CFG_EGLFS_MALI=no CFG_EGLFS_VIV=no CFG_DIRECTFB=auto +CFG_GBM=auto CFG_LINUXFB=auto CFG_KMS=auto CFG_MIRCLIENT=auto @@ -1828,6 +1829,13 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; + gbm) + if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then + CFG_GBM="$VAL" + else + UNKNOWN_OPT=yes + fi + ;; linuxfb) if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then CFG_LINUXFB="$VAL" @@ -2667,8 +2675,11 @@ Additional options: -no-eglfs .......... Do not compile EGLFS (EGL Full Screen/Single Surface) support. * -eglfs ............. Compile EGLFS support. - -no-kms ............ Do not compile EGLFS KMS backend. - * -kms ............... Compile EGLFS KMS backend. + -no-kms ............ Do not compile backends for KMS. + * -kms ............... Compile backends for KMS. + + -no-gbm ............ Do not compile backends for GBM. + * -gbm ............... Compile backends for GBM. -no-directfb ....... Do not compile DirectFB support. * -directfb .......... Compile DirectFB support. @@ -4717,13 +4728,6 @@ if [ "$CFG_EGLFS" = "yes" ]; then CFG_EGL=yes fi -if [ "$CFG_KMS" = "yes" ]; then - if [ "$CFG_EGL" = "no" ]; then - echo "The KMS plugin requires EGL support and cannot be built" - exit 101 - fi -fi - # auto-detect SQL-modules support for _SQLDR in $CFG_SQL_AVAILABLE; do case $_SQLDR in @@ -5353,7 +5357,6 @@ ORIG_CFG_XCB="$CFG_XCB" ORIG_CFG_EGLFS="$CFG_EGLFS" ORIG_CFG_DIRECTFB="$CFG_DIRECTFB" ORIG_CFG_LINUXFB="$CFG_LINUXFB" -ORIG_CFG_KMS="$CFG_KMS" ORIG_CFG_MIRCLIENT="$CFG_MIRCLIENT" if [ "$CFG_LIBUDEV" != "no" ]; then @@ -5609,6 +5612,20 @@ if [ "$CFG_DIRECTFB" != "no" ]; then fi fi +if [ "$CFG_GBM" != "no" ]; then + if compileTest qpa/gbm "GBM"; then + CFG_GBM=yes + elif [ "$CFG_GBM" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then + echo " GBM 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_GBM=no + fi +fi + if [ "$CFG_LINUXFB" != "no" ]; then if compileTest qpa/linuxfb "LinuxFB"; then CFG_LINUXFB=yes @@ -5768,14 +5785,6 @@ if [ "$CFG_EGLFS" != "no" ]; then fi fi -if [ "$CFG_KMS" = "yes" ]; then - if [ "$CFG_EGL" = "yes" ]; then - CFG_KMS="yes" - else - CFG_KMS="no" - fi -fi - # Detect accessibility support if [ "$CFG_ACCESSIBILITY" = "no" ]; then echo >&2 "Warning: Disabling Accessibility. This version of Qt is unsupported." @@ -5821,6 +5830,9 @@ if [ "$CFG_DIRECTFB" = "yes" ]; then QMakeVar set QMAKE_CFLAGS_DIRECTFB "$QMAKE_CFLAGS_DIRECTFB" QMakeVar set QMAKE_LIBS_DIRECTFB "$QMAKE_LIBS_DIRECTFB" fi +if [ "$CFG_GBM" = "yes" ]; then + QT_CONFIG="$QT_CONFIG gbm" +fi if [ "$CFG_LINUXFB" = "yes" ]; then QT_CONFIG="$QT_CONFIG linuxfb" fi @@ -5832,9 +5844,9 @@ if [ "$CFG_MIRCLIENT" = "yes" ]; then fi if [ "$XPLATFORM_MAC" = "no" ] && [ "$XPLATFORM_MINGW" = "no" ] && [ "$XPLATFORM_QNX" = "no" ] && [ "$XPLATFORM_ANDROID" = "no" ] && [ "$XPLATFORM_HAIKU" = "no" ]; then - if [ "$CFG_XCB" = "no" ] && [ "$CFG_EGLFS" = "no" ] && [ "$CFG_DIRECTFB" = "no" ] && [ "$CFG_LINUXFB" = "no" ] && [ "$CFG_KMS" = "no" ] && [ "$CFG_MIRCLIENT" = "no" ]; then + if [ "$CFG_XCB" = "no" ] && [ "$CFG_EGLFS" = "no" ] && [ "$CFG_DIRECTFB" = "no" ] && [ "$CFG_LINUXFB" = "no" ] && [ "$CFG_MIRCLIENT" = "no" ]; then if [ "$QPA_PLATFORM_GUARD" = "yes" ] && - ( [ "$ORIG_CFG_XCB" = "auto" ] || [ "$ORIG_CFG_EGLFS" = "auto" ] || [ "$ORIG_CFG_DIRECTFB" = "auto" ] || [ "$ORIG_CFG_LINUXFB" = "auto" ] || [ "$ORIG_CFG_KMS" = "auto" ] || [ "$ORIG_CFG_MIRCLIENT" = "auto" ] ); then + ( [ "$ORIG_CFG_XCB" = "auto" ] || [ "$ORIG_CFG_EGLFS" = "auto" ] || [ "$ORIG_CFG_DIRECTFB" = "auto" ] || [ "$ORIG_CFG_LINUXFB" = "auto" ] || [ "$ORIG_CFG_MIRCLIENT" = "auto" ] ); then echo "No QPA platform plugin enabled!" echo " If you really want to build without a QPA platform plugin you must pass" echo " -no-qpa-platform-guard to configure. Doing this will" @@ -6203,6 +6215,12 @@ fi if [ "$CFG_EGLFS_EGLDEVICE" = "yes" ]; then QT_CONFIG="$QT_CONFIG eglfs_egldevice" fi +if [ "$CFG_EGLFS" = "yes" ] && [ "$CFG_KMS" = "yes" ] && [ "$CFG_GBM" = "yes" ]; then + QT_CONFIG="$QT_CONFIG eglfs_gbm" + CFG_EGLFS_GBM="yes" +else + CFG_EGLFS_GBM="no" +fi if [ "$CFG_EGLFS_MALI" = "yes" ]; then QT_CONFIG="$QT_CONFIG eglfs_mali" fi @@ -7270,7 +7288,7 @@ report_support " DirectFB ............." "$CFG_DIRECTFB" report_support " EGLFS ................" "$CFG_EGLFS" report_support " EGLFS i.MX6 ........" "$CFG_EGLFS_VIV" report_support " EGLFS EGLDevice ...." "$CFG_EGLFS_EGLDEVICE" -report_support " EGLFS KMS .........." "$CFG_KMS" +report_support " EGLFS GBM .........." "$CFG_EGLFS_GBM" report_support " EGLFS Mali ........." "$CFG_EGLFS_MALI" report_support " EGLFS Raspberry Pi ." "$CFG_EGLFS_BRCM" report_support " EGLFS X11 .........." "$CFG_EGL_X" diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro index f8bb854f1c..cf367d930f 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro @@ -1,7 +1,7 @@ TEMPLATE = subdirs contains(QT_CONFIG, egl_x11): SUBDIRS += eglfs_x11 -contains(QT_CONFIG, kms): SUBDIRS += eglfs_kms +contains(QT_CONFIG, eglfs_gbm): SUBDIRS += eglfs_kms contains(QT_CONFIG, eglfs_egldevice): SUBDIRS += eglfs_kms_egldevice contains(QT_CONFIG, eglfs_brcm): SUBDIRS += eglfs_brcm contains(QT_CONFIG, eglfs_mali): SUBDIRS += eglfs_mali From 281121697340084f7d385eab530f41916789b94d Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Tue, 29 Sep 2015 13:49:16 +0200 Subject: [PATCH 240/240] Windows: Open GL blacklist - Add add intel hd graphics 3000 devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the windows driver for Intel HD Graphics 3000 is buggy (crashes on initialization) and according to intel, this driver won't receive any bugfixes. device IDs taken from http://www.pcidatabase.com/search.php?device_search_str=graphics Task-number: QTBUG-42240 Change-Id: Ib846d37f67d901060d1318f3f211a5e5dc4f6814 Reviewed-by: Friedemann Kleint Reviewed-by: Jan Arve Sæther Reviewed-by: Tim Blechmann Reviewed-by: Laszlo Agocs --- .../windows/openglblacklists/default.json | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json index b00c9df408..f1500409fe 100644 --- a/src/plugins/platforms/windows/openglblacklists/default.json +++ b/src/plugins/platforms/windows/openglblacklists/default.json @@ -4,7 +4,7 @@ "entries": [ { "id": 1, - "description": "Desktop OpenGL is unreliable on some Intel HD laptops (QTBUG-43263, QTBUG-42240)", + "description": "Desktop OpenGL is unreliable on some Intel HD laptops (QTBUG-43263)", "vendor_id": "0x8086", "device_id": [ "0x0A16" ], "os": { @@ -42,6 +42,18 @@ "features": [ "disable_desktopgl" ] + }, + { + "id": 4, + "description": "Intel HD Graphics 3000 crashes when initializing the OpenGL driver (QTBUG-42240)", + "vendor_id": "0x8086", + "device_id": [ "0x0102", "0x0116" ], + "os": { + "type": "win" + }, + "features": [ + "disable_desktopgl" + ] } ] }