From 54cc48176086a5f529c679141e9dde7911abda5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 2 May 2014 20:52:25 +0200 Subject: Cocoa: Clear window hash entry in ~QCocoaWindow. The Cocoa platform plugin maintains a NSWindow-> QCocoaWindow hash. Hash entries was not properly cleared on QCocoaWindow destruction. Add call to clear the entry for the destroyed window. Make QCocoaIntegration remove the key from the hash in this case instead of setting it to 0. Task-number: QTBUG-37597 Change-Id: I3adaeee45069aea1d2ecacd948298302eafe1929 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 5 ++++- src/plugins/platforms/cocoa/qcocoawindow.mm | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index c4398622e8..7fa3adc521 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -520,7 +520,10 @@ NSToolbar *QCocoaIntegration::toolbar(QWindow *window) const void QCocoaIntegration::setWindow(NSWindow* nsWindow, QCocoaWindow *window) { - mWindows.insert(nsWindow, window); + if (window == 0) + mWindows.remove(nsWindow); + else + mWindows.insert(nsWindow, window); } QCocoaWindow *QCocoaIntegration::window(NSWindow *window) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 60152b56b2..d355dd0ed1 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -420,6 +420,9 @@ QCocoaWindow::~QCocoaWindow() qDebug() << "QCocoaWindow::~QCocoaWindow" << this; #endif + if (QCocoaIntegration *ci = QCocoaIntegration::instance()) + ci->setWindow(m_nsWindow, 0); + QCocoaAutoReleasePool pool; [m_nsWindow setContentView:nil]; [m_nsWindow.helper detachFromPlatformWindow]; -- cgit v1.2.3 From 4e9853139ca04858f1639e0fba6b8caf57474f29 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 13 May 2014 16:49:33 +0200 Subject: Update Copyright year in commercial nag screens Change-Id: I70420c44c018dbe733a50badb7f9f7f419459f7a Reviewed-by: Lars Knoll --- src/corelib/kernel/qtcore_eval.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp index 40c1157fb4..a5c4c36638 100644 --- a/src/corelib/kernel/qtcore_eval.cpp +++ b/src/corelib/kernel/qtcore_eval.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE static const char boilerplate_supported_but_time_limited[] = "\nQt %1 Evaluation License\n" - "Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).\n" + "Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).\n" "This trial version may only be used for evaluation purposes\n" "and will shut down after 120 minutes.\n" "Registered to:\n" @@ -65,7 +65,7 @@ static const char boilerplate_supported_but_time_limited[] = static const char boilerplate_supported[] = "\nQt %1 Evaluation License\n" - "Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).\n" + "Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).\n" "This trial version may only be used for evaluation purposes\n" "Registered to:\n" " Licensee: %2\n\n" -- cgit v1.2.3 From bbdf6a8039c19d63537d4ac056d1f3830550b362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 28 Apr 2014 01:55:45 +0200 Subject: Android: Use exceptionCheck() function. This was the only place where we didn't use the exceptionCheck() function. Besides being more consistent, it's also more verbose if an exception occurs. Change-Id: Ib1e3dba82b0730cf189ec725f4da425d7ac85cdc Reviewed-by: Yoann Lopes --- src/corelib/kernel/qjnihelpers.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index 311ebaa092..cbd3d776a7 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -113,10 +113,8 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) { jclass jQtNative = env->FindClass("org/qtproject/qt5/android/QtNative"); - if (env->ExceptionCheck()) { - env->ExceptionClear(); + if (exceptionCheck(env)) return JNI_ERR; - } jmethodID activityMethodID = env->GetStaticMethodID(jQtNative, "activity", -- cgit v1.2.3 From fce9c2dd26e7b489cfe7a3de0f21a77f4dca62a2 Mon Sep 17 00:00:00 2001 From: Bernd Weimer Date: Wed, 4 Jun 2014 10:14:43 +0200 Subject: QNX: Fix build for QNX 6.5 QNX 6.5 does not have readdir64_r, which is selected by current qplatformdefs.h. There is only a reentrant version (readdir_r) which does not support large files and a large file version (readdir64) which is not reentrant. The reentrant version (readdir_r) will be chosen now. In summary, the following versions will be used: QNX 6.5: readdir_r (postfix '_r': reentrant version) QNX 6.6: _readdir_r (prefix '_' : extra stat info included) BB 10: _readdir64_r (infix '64': large file support) Change-Id: I00739f0e2054a32f52555309d03463a6c52e3d99 Reviewed-by: Wolfgang Bremer Reviewed-by: Samuli Piippo Reviewed-by: Sergio Ahumada --- mkspecs/qnx-armle-v7-qcc/qplatformdefs.h | 2 +- mkspecs/qnx-x86-qcc/qplatformdefs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/qnx-armle-v7-qcc/qplatformdefs.h b/mkspecs/qnx-armle-v7-qcc/qplatformdefs.h index 27e4a3aa41..2f95f0d392 100644 --- a/mkspecs/qnx-armle-v7-qcc/qplatformdefs.h +++ b/mkspecs/qnx-armle-v7-qcc/qplatformdefs.h @@ -83,7 +83,7 @@ #include #define QT_USE_XOPEN_LFS_EXTENSIONS -#if defined(__EXT_QNX__READDIR_R) && !defined(__EXT_QNX__READDIR64_R) +#if !defined(__EXT_QNX__READDIR64_R) #define QT_NO_READDIR64 #endif #include "../common/posix/qplatformdefs.h" diff --git a/mkspecs/qnx-x86-qcc/qplatformdefs.h b/mkspecs/qnx-x86-qcc/qplatformdefs.h index 246f82e27f..b47aecde0d 100644 --- a/mkspecs/qnx-x86-qcc/qplatformdefs.h +++ b/mkspecs/qnx-x86-qcc/qplatformdefs.h @@ -83,7 +83,7 @@ #include #define QT_USE_XOPEN_LFS_EXTENSIONS -#if defined(__EXT_QNX__READDIR_R) && !defined(__EXT_QNX__READDIR64_R) +#if !defined(__EXT_QNX__READDIR64_R) #define QT_NO_READDIR64 #endif #include "../common/posix/qplatformdefs.h" -- cgit v1.2.3 From d1c00155464fe9a8ce08216141ca978fe6415dcc Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 4 Jun 2014 15:54:25 +0200 Subject: Make multisampling more robust in QOpenGLFramebufferObject MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some drivers are reported to get confused when passing different sample counts (requested vs. actual) to the color and depth/stencil attachments. To overcome this, pass the requested sample count to all the attachments. Task-number: QTBUG-33406 Change-Id: I17b0e3dbbd78de2ab0f45e95164b4f326d47aeff Reviewed-by: Paul Olav Tvete Reviewed-by: Kimmo Leppälä --- src/gui/opengl/qopenglframebufferobject.cpp | 10 ++++++++-- src/gui/opengl/qopenglframebufferobject_p.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index 7d91d2c497..cd6468cccd 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -436,9 +436,9 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi samples = qBound(0, int(samples), int(maxSamples)); #endif + requestedSamples = samples; size = sz; target = texture_target; - // texture dimensions QT_RESET_GLERROR(); // reset error state GLuint fbo = 0; @@ -472,6 +472,9 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi valid = checkFramebufferStatus(ctx); if (valid) { + // Query the actual number of samples. This can be greater than the requested + // value since the typically supported values are 0, 4, 8, ..., and the + // requests are mapped to the next supported value. funcs.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples); color_buffer_guard = new QOpenGLSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc); } @@ -542,7 +545,10 @@ void QOpenGLFramebufferObjectPrivate::initTexture(GLenum target, GLenum internal void QOpenGLFramebufferObjectPrivate::initAttachments(QOpenGLContext *ctx, QOpenGLFramebufferObject::Attachment attachment) { - int samples = format.samples(); + // Use the same sample count for all attachments. format.samples() already contains + // the actual number of samples for the color attachment and is not suitable. Use + // requestedSamples instead. + const int samples = requestedSamples; // free existing attachments if (depth_buffer_guard) { diff --git a/src/gui/opengl/qopenglframebufferobject_p.h b/src/gui/opengl/qopenglframebufferobject_p.h index 7a653bc16d..75348d1481 100644 --- a/src/gui/opengl/qopenglframebufferobject_p.h +++ b/src/gui/opengl/qopenglframebufferobject_p.h @@ -131,6 +131,7 @@ public: GLenum target; QSize size; QOpenGLFramebufferObjectFormat format; + int requestedSamples; uint valid : 1; QOpenGLFramebufferObject::Attachment fbo_attachment; QOpenGLExtensions funcs; -- cgit v1.2.3 From 1b21974f3eeebc0528d4101d97154641d405b255 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 4 Jun 2014 16:44:44 +0200 Subject: Avoid polluting the output with warnings on eglfs Many windowing functions are not supported (since they do not make sense) on the embedded platforms. Provide empty implementations for a few more to avoid showing useless warnings, in particular for widget apps. The user cannot do anything about it and these are not errors. Task-number: QTBUG-39081 Change-Id: I29afd981e037d1e6772bcdfc33497e6d0ae02008 Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/eglfs/qeglfswindow.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index f3fd06037e..4403e3c28e 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -66,6 +66,8 @@ public: void lower() Q_DECL_OVERRIDE; void propagateSizeHints() Q_DECL_OVERRIDE { } + void setOpacity(qreal) Q_DECL_OVERRIDE { } + void setMask(const QRegion &) Q_DECL_OVERRIDE { } bool setKeyboardGrabEnabled(bool) Q_DECL_OVERRIDE { return false; } bool setMouseGrabEnabled(bool) Q_DECL_OVERRIDE { return false; } -- cgit v1.2.3 From 0712b4ff7139b5c2cc96fd40ea7bb77a9bb8fd1c Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 4 Jun 2014 17:53:39 +0200 Subject: Fix visual selection with EGL on xcb Using a 24-bit visual for 8888 configs is wrong since we loose the alpha channel. This breaks translucent windows and, among others, leads to not showing drag pixmaps (that typically have transparent areas) properly. Change-Id: I516c84327680b76996b622831e431c29d840471e Task-number: QTBUG-35126 Reviewed-by: Paul Olav Tvete --- .../eglconvenience/qxlibeglintegration.cpp | 39 ++++++++-------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp index 80453816fc..9c2d50823a 100644 --- a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp +++ b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp @@ -84,32 +84,22 @@ VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay int visualRedSize = qPopulationCount(chosenVisualInfo->red_mask); int visualGreenSize = qPopulationCount(chosenVisualInfo->green_mask); int visualBlueSize = qPopulationCount(chosenVisualInfo->blue_mask); - int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size - - bool visualMatchesConfig = false; - if ( visualRedSize == configRedSize && - visualGreenSize == configGreenSize && - visualBlueSize == configBlueSize ) - { - // We need XRender to check the alpha channel size of the visual. If we don't have - // the alpha size, we don't check it against the EGL config's alpha size. - if (visualAlphaSize >= 0) - visualMatchesConfig = visualAlphaSize == configAlphaSize; - else - visualMatchesConfig = true; - } + int visualAlphaSize = chosenVisualInfo->depth == 32 ? 8 : 0; + + const bool visualMatchesConfig = visualRedSize == configRedSize + && visualGreenSize == configGreenSize + && visualBlueSize == configBlueSize + && visualAlphaSize == configAlphaSize; + // In some cases EGL tends to suggest a 24-bit visual for 8888 + // configs. In such a case we have to fall back to XGetVisualInfo. if (!visualMatchesConfig) { - if (visualAlphaSize >= 0) { - qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable", - (int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize, - configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize); - } else { - qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable", - (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, - configId, configRedSize, configGreenSize, configBlueSize); - } visualId = 0; +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + qWarning("Warning: EGL suggested using X Visual ID %d (%d %d %d depth %d) for EGL config %d (%d %d %d %d), but this is incompatible", + (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, chosenVisualInfo->depth, + configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize); +#endif } } else { qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID", @@ -133,8 +123,7 @@ VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay return visualId; } - // Finally, try to - // use XGetVisualInfo and only use the bit depths to match on: + // Finally, try to use XGetVisualInfo and only use the bit depths to match on: if (!visualId) { XVisualInfo visualInfoTemplate; memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); -- cgit v1.2.3 From ab3603d2b5ed2cb6bc403643d82e97015449546b Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 5 Jun 2014 14:20:34 +0200 Subject: Fix alpha in no-opengl configuration on xcb Like the EGL + xcb configuration, the -no-opengl is broken too when it comes to translucent windows: Requesting an alpha channel is futile since the xcb_create_window call always uses the root's depth and visual. This is now corrected by picking a 32-bit visual. This will make translucent windows and drag pixmaps appear correctly again. Task-number: QTBUG-35126 Change-Id: I00e7d6e08b5fcc055ef3ea6d822561740a1f5457 Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbwindow.cpp | 34 ++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index a46fe437d8..74d8b7c2c8 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -337,12 +337,38 @@ void QXcbWindow::create() #endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL) { m_window = xcb_generate_id(xcb_connection()); + m_visualId = m_screen->screen()->root_visual; m_depth = m_screen->screen()->root_depth; + + uint32_t mask = 0; + uint32_t values[3]; + + if (m_format.alphaBufferSize() == 8) { + xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(m_screen->screen()); + while (depthIter.rem) { + if (depthIter.data->depth == 32) { + xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data); + if (visualIter.rem) { + m_visualId = visualIter.data->visual_id; + m_depth = 32; + uint32_t colormap = xcb_generate_id(xcb_connection()); + xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap, + xcb_parent_id, m_visualId); + mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP; + values[0] = m_screen->screen()->white_pixel; + values[1] = m_screen->screen()->black_pixel; + values[2] = colormap; + break; + } + } + xcb_depth_next(&depthIter); + } + } + m_imageFormat = imageFormatForDepth(m_depth); - m_visualId = m_screen->screen()->root_visual; Q_XCB_CALL(xcb_create_window(xcb_connection(), - XCB_COPY_FROM_PARENT, // depth -- same as root + m_depth, m_window, // window id xcb_parent_id, // parent window id rect.x(), @@ -352,8 +378,8 @@ void QXcbWindow::create() 0, // border width XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class m_visualId, // visual - 0, // value mask - 0)); // value list + mask, + values)); } connection()->addWindowEventListener(m_window, this); -- cgit v1.2.3 From a6855cbf4046b8f5c7c4571631a722009828d578 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 5 Jun 2014 15:54:19 +0200 Subject: QPlatformClipboard::emitChanged(): Do not emit signals when closing down. Prevents a shutdown crash in the Qt Mfc migration solution. Task-number: QTBUG-39317 Change-Id: I7f0aa40715baed57ff59682a477084347dfd45bc Reviewed-by: Andy Shaw --- src/gui/kernel/qplatformclipboard.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qplatformclipboard.cpp b/src/gui/kernel/qplatformclipboard.cpp index 5c25054260..d93268c9f2 100644 --- a/src/gui/kernel/qplatformclipboard.cpp +++ b/src/gui/kernel/qplatformclipboard.cpp @@ -123,7 +123,8 @@ bool QPlatformClipboard::ownsMode(QClipboard::Mode mode) const void QPlatformClipboard::emitChanged(QClipboard::Mode mode) { - QGuiApplication::clipboard()->emitChanged(mode); + if (!QGuiApplicationPrivate::is_app_closing) // QTBUG-39317, prevent emission when closing down. + QGuiApplication::clipboard()->emitChanged(mode); } QT_END_NAMESPACE -- cgit v1.2.3 From c3baa7c1dc8c29bfe60e8e5c676c606d4f699005 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 5 Jun 2014 08:22:25 +0200 Subject: Fix selection by dragging after double click in QWidgetTextControl. Remove return in mouseMove depending on variable mousePressed which is not present in Qt 4. The variable was true in Qt versions before 5.3 due to an additional mouse press event received before a double click. Task-number: QTBUG-39023 Task-number: QTBUG-25831 Change-Id: I57ed9284961195c71df9e9b9d697b1cfbad7c228 Reviewed-by: Laszlo Agocs --- src/widgets/widgets/qwidgettextcontrol.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 54b20e36f5..b34c297f2e 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -1692,9 +1692,6 @@ void QWidgetTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button return; } - if (!mousePressed) - return; - const qreal mouseX = qreal(mousePos.x()); int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit); -- cgit v1.2.3 From c3e416296a1026d7ba99cf209f5e0720ff5050b1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 26 May 2014 14:24:20 +0200 Subject: Revert "Fixed duplicate QMoveEvent generated for each QWidget::move call" A better fix is to check whether the widget already has the requested geometry when receiving the spontaneous event from the platform in QWidgetWindow and to suppress that. This reverts commit 72259baa76a0f1faa1983c720621676e9c15e15f. Task-number: QTBUG-32590 Change-Id: I4d7a9b4c340c2d6a427727ecb8de50c3d199f7a9 Reviewed-by: Andy Shaw --- src/widgets/kernel/qwidget_qpa.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index 17ed4ca477..e5f552679c 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -779,10 +779,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) } } - // generate a move event for QWidgets without window handles. QWidgets with native - // window handles already receive a move event from - // QGuiApplicationPrivate::processGeometryChangeEvent. - if (isMove && (!q->windowHandle() || q->testAttribute(Qt::WA_DontShowOnScreen))) { + if (isMove) { QMoveEvent e(q->pos(), oldPos); QApplication::sendEvent(q, &e); } -- cgit v1.2.3 From a1c5198387fdb7db44a02bb94c56187874e67304 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 26 May 2014 14:28:19 +0200 Subject: Suppress move/resize events if they are the result of call to move()/resize(). QWidget::resize() or QWidget::move() set the new size/position values and send events. The spontaneous events generated by the platform should be ignored in that case. Task-number: QTBUG-30744 Task-number: QTBUG-38768 Task-number: QTBUG-32590 Change-Id: I9c0ae38842ed76a8a88ca64fdc9bbe106b2766b7 Reviewed-by: Andy Shaw --- src/widgets/kernel/qwidgetwindow.cpp | 12 ++++- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 57 ++++++++++++++++++----- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index fc328e7af0..35a526e77d 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -591,16 +591,24 @@ void QWidgetWindow::updateNormalGeometry() void QWidgetWindow::handleMoveEvent(QMoveEvent *event) { + // If the widget's position already matches that of the event, this is a + // result of call to QWidget::move(), which already sends an event. + const bool spontaneous = m_widget->geometry().topLeft() != event->pos(); updateGeometry(); - QGuiApplication::sendSpontaneousEvent(m_widget, event); + if (spontaneous) + QGuiApplication::sendSpontaneousEvent(m_widget, event); } void QWidgetWindow::handleResizeEvent(QResizeEvent *event) { QSize oldSize = m_widget->data->crect.size(); + // If the widget's size already matches that of the event, this is a + // result of call to QWidget::resize(), which already sends an event. + const bool spontaneous = oldSize != event->size(); updateGeometry(); - QGuiApplication::sendSpontaneousEvent(m_widget, event); + if (spontaneous) + QGuiApplication::sendSpontaneousEvent(m_widget, event); if (m_widget->d_func()->paintOnScreen()) { QRegion updateRegion(geometry()); diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 34936fa5b8..73bec9a6b9 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -262,6 +262,7 @@ private slots: void optimizedResizeMove(); void optimizedResize_topLevel(); void resizeEvent(); + void moveEvent(); void task110173(); void testDeletionInEventHandlers(); @@ -2108,41 +2109,53 @@ void tst_QWidget::showFullScreen() class ResizeWidget : public QWidget { public: - ResizeWidget(QWidget *p = 0) : QWidget(p) + ResizeWidget(QWidget *p = 0) + : QWidget(p) + , m_spontaneousResizeEventCount(0) + , m_synthesizedResizeEventCount(0) + , m_spontaneousMoveEventCount(0) + , m_synthesizedMoveEventCount(0) { setObjectName(QLatin1String("ResizeWidget")); setWindowTitle(objectName()); - m_resizeEventCount = 0; } protected: void resizeEvent(QResizeEvent *e){ QCOMPARE(size(), e->size()); - ++m_resizeEventCount; + (e->spontaneous() ? m_spontaneousResizeEventCount : m_synthesizedResizeEventCount)++; + } + void moveEvent(QMoveEvent *e) + { + (e->spontaneous() ? m_spontaneousMoveEventCount : m_synthesizedMoveEventCount)++; } public: - int m_resizeEventCount; + int m_spontaneousResizeEventCount; + int m_synthesizedResizeEventCount; + int m_spontaneousMoveEventCount; + int m_synthesizedMoveEventCount; }; void tst_QWidget::resizeEvent() { - QSKIP("QTBUG-30744"); - { QWidget wParent; wParent.resize(200, 200); ResizeWidget wChild(&wParent); wParent.show(); QTest::qWaitForWindowExposed(&wParent); - QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint + QCOMPARE (wChild.m_synthesizedResizeEventCount, 1); // initial resize event before paint + QCOMPARE (wChild.m_spontaneousResizeEventCount, 0); wParent.hide(); QSize safeSize(640,480); if (wChild.size() == safeSize) safeSize.setWidth(639); wChild.resize(safeSize); - QCOMPARE (wChild.m_resizeEventCount, 1); + QCOMPARE (wChild.m_synthesizedResizeEventCount, 1); + QCOMPARE (wChild.m_spontaneousResizeEventCount, 0); wParent.show(); - QCOMPARE (wChild.m_resizeEventCount, 2); + QCOMPARE (wChild.m_synthesizedResizeEventCount, 2); + QCOMPARE (wChild.m_spontaneousResizeEventCount, 0); } { @@ -2150,19 +2163,39 @@ void tst_QWidget::resizeEvent() wTopLevel.resize(200, 200); wTopLevel.show(); QTest::qWaitForWindowExposed(&wTopLevel); - QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels + const int synthesizedResizeEventCountAfterShow = wTopLevel.m_synthesizedResizeEventCount; + QCOMPARE (synthesizedResizeEventCountAfterShow, 1); // initial resize event before paint for toplevels + QCOMPARE (wTopLevel.m_spontaneousResizeEventCount, 0); wTopLevel.hide(); QSize safeSize(640,480); if (wTopLevel.size() == safeSize) safeSize.setWidth(639); wTopLevel.resize(safeSize); - QCOMPARE (wTopLevel.m_resizeEventCount, 1); + QCOMPARE (wTopLevel.m_synthesizedResizeEventCount, synthesizedResizeEventCountAfterShow); + QCOMPARE (wTopLevel.m_spontaneousResizeEventCount, 0); wTopLevel.show(); QTest::qWaitForWindowExposed(&wTopLevel); - QCOMPARE (wTopLevel.m_resizeEventCount, 2); +#ifdef Q_OS_OSX + QEXPECT_FAIL("", "QTBUG-30744", Abort); +#endif + QCOMPARE (wTopLevel.m_synthesizedResizeEventCount, synthesizedResizeEventCountAfterShow + 1); + QCOMPARE (wTopLevel.m_spontaneousResizeEventCount, 0); } } +void tst_QWidget::moveEvent() +{ + ResizeWidget wTopLevel; + wTopLevel.resize(200, 200); + centerOnScreen(&wTopLevel); + wTopLevel.show(); + QTest::qWaitForWindowExposed(&wTopLevel); + const int synthesizedMoveEventCountAfterShow = wTopLevel.m_synthesizedMoveEventCount; + wTopLevel.move(wTopLevel.pos() + QPoint(20, 20)); + QTRY_COMPARE (wTopLevel.m_synthesizedMoveEventCount, synthesizedMoveEventCountAfterShow + 1); + QCOMPARE (wTopLevel.m_spontaneousMoveEventCount, 0); +} + void tst_QWidget::showMinimized() { QWidget plain; -- cgit v1.2.3 From 3441738d5f63f2d147bfcd37351be48c66ec5181 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 5 Jun 2014 11:18:47 +0200 Subject: Remove unfinished NEON version of vectorized rotate sampling A vectorized codepath for rotating transforms were added in 5.3.0, but was only properly tested for SSE2. The NEON version remains unfinished. Since it was never working, this patch reverts the NEON version. Task-number: QTBUG-39445 Change-Id: Ifbce0e03781d217ad976c6b18ac88381055cba66 Reviewed-by: Gunnar Sletta --- src/gui/painting/qdrawhelper.cpp | 65 ---------------------------------------- 1 file changed, 65 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index b5ccafdf9a..24da65921e 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -1798,71 +1798,6 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c } fx = v_fx.i[0]; fy = v_fy.i[0]; -#elif defined(__ARM_NEON__) - BILINEAR_ROTATE_BOUNDS_PROLOG - - const int16x8_t colorMask = vdupq_n_s16(0x00ff); - const int16x8_t invColorMask = vmvnq_s16(colorMask); - const int16x8_t v_256 = vdupq_n_s16(256); - int32x4_t v_fdx = vdupq_n_s32(fdx*4); - int32x4_t v_fdy = vdupq_n_s32(fdy*4); - - const uchar *textureData = data->texture.imageData; - const int bytesPerLine = data->texture.bytesPerLine; - - union Vect_buffer { int32x4_t vect; quint32 i[4]; }; - Vect_buffer v_fx, v_fy; - - for (int i = 0; i < 4; i++) { - v_fx.i[i] = fx; - v_fy.i[i] = fy; - fx += fdx; - fy += fdy; - } - - const int32x4_t v_ffff_mask = vdupq_n_s32(0x0000ffff); - - while (b < boundedEnd) { - if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2) - break; - if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1) - break; - if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2) - break; - if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1) - break; - - Vect_buffer tl, tr, bl, br; - - Vect_buffer v_fx_shifted, v_fy_shifted; - v_fx_shifted.vect = vshrq_n_s32(v_fx.vect, 16); - v_fy_shifted.vect = vshrq_n_s32(v_fy.vect, 16); - - for (int i = 0; i < 4; i++) { - const int x1 = v_fx_shifted.i[i]; - const int y1 = v_fy_shifted.i[i]; - const uchar *sl = textureData + bytesPerLine * y1; - const uint *s1 = (const uint *)sl; - const uint *s2 = (const uint *)(sl + bytesPerLine); - tl.i[i] = s1[x1]; - tr.i[i] = s1[x1+1]; - bl.i[i] = s2[x1]; - br.i[i] = s2[x1+1]; - } - - int32x4_t v_distx = vshrq_n_s32(vandq_s32(v_fx.vect, v_ffff_mask), 12); - int32x4_t v_disty = vshrq_n_s32(vandq_s32(v_fy.vect, v_ffff_mask), 12); - v_distx = vorrq_s32(v_distx, vshlq_n_s32(v_distx, 16)); - v_disty = vorrq_s32(v_disty, vshlq_n_s32(v_disty, 16)); - int16x8_t v_disty_ = vshlq_n_s16(v_disty, 4); - - interpolate_4_pixels_16_neon(vreinterpretq_s16_s32(tl.vect), vreinterpretq_s16_s32(tr.vect), vreinterpretq_s16_s32(bl.vect), vreinterpretq_s16_s32(br.vect), vreinterpretq_s16_s32(v_distx), v_disty, v_disty_, colorMask, invColorMask, v_256, b); - b+=4; - v_fx.vect = vaddq_s32(v_fx.vect, v_fdx); - v_fy.vect = vaddq_s32(v_fy.vect, v_fdy); - } - fx = v_fx.i[0]; - fy = v_fy.i[0]; #endif } -- cgit v1.2.3 From dbc7ed82149d8915a32489a0d3a930d2793c6e65 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 5 Jun 2014 12:30:07 +0200 Subject: Ensure that there is no duplication of the output directory in output When a relative path was specified as the output then it would be in both Option::output_dir and Option::output. Therefore in that case Option::output should be just the filename as Option::output_dir has the correct path to output to. Task-number: QTBUG-39460 Change-Id: Idc988e6bad94f34b89660fb5e8d6fa3a39dc623b Reviewed-by: Oswald Buddenhagen --- qmake/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qmake/main.cpp b/qmake/main.cpp index f5116ba752..82573a61fc 100644 --- a/qmake/main.cpp +++ b/qmake/main.cpp @@ -252,8 +252,10 @@ int runQMake(int argc, char **argv) #endif if(!dir.isNull() && dir != ".") Option::output_dir = dir; - if(QDir::isRelativePath(Option::output_dir)) + if (QDir::isRelativePath(Option::output_dir)) { + Option::output.setFileName(fi.fileName()); Option::output_dir.prepend(oldpwd + QLatin1Char('/')); + } Option::output_dir = QDir::cleanPath(Option::output_dir); } -- cgit v1.2.3 From bc9423316f373a5baa63aa47b9ab340d34c9d6ac Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 28 May 2014 14:14:23 +0200 Subject: iOS: delay callbacks to UITextInput to avoid recursion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the application calls "reset" or "commit" on the input method (or forces active focus on some other item) from a text changed or key pressed handler, iOS will sometimes throw an exception. It does so because we try to change the state of UITextInput (by calling textDidChange) while processing a callback from the same place (insertText). Optimally this should not happen since we would normally post such events to Qt, not send them directly. But with text input we cannot do this since UITextInput expects us to update immediately upon receiving text input callbacks. If not, word completion and spell checking will stop working. This change will guard against recursive callbacks by delaying callbacks to UITextInput when text/selection/first responder changes. Change-Id: I099f30adf1c5aba241fc833a45b423016f4ed8d0 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosinputcontext.mm | 10 +-- src/plugins/platforms/ios/quiview.h | 1 + src/plugins/platforms/ios/quiview_textinput.mm | 89 +++++++++++++++++--------- 3 files changed, 61 insertions(+), 39 deletions(-) diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 8be3846e06..d109d53168 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -54,7 +54,6 @@ QIOSInputContext *m_context; BOOL m_keyboardVisible; BOOL m_keyboardVisibleAndDocked; - BOOL m_ignoreKeyboardChanges; BOOL m_touchPressWhileKeyboardVisible; BOOL m_keyboardHiddenByGesture; QRectF m_keyboardRect; @@ -74,7 +73,6 @@ m_context = context; m_keyboardVisible = NO; m_keyboardVisibleAndDocked = NO; - m_ignoreKeyboardChanges = NO; m_touchPressWhileKeyboardVisible = NO; m_keyboardHiddenByGesture = NO; m_duration = 0; @@ -160,7 +158,7 @@ - (void) keyboardWillShow:(NSNotification *)notification { - if (m_ignoreKeyboardChanges) + if ([QUIView inUpdateKeyboardLayout]) return; // Note that UIKeyboardWillShowNotification is only sendt when the keyboard is docked. m_keyboardVisibleAndDocked = YES; @@ -175,7 +173,7 @@ - (void) keyboardWillHide:(NSNotification *)notification { - if (m_ignoreKeyboardChanges) + if ([QUIView inUpdateKeyboardLayout]) return; // Note that UIKeyboardWillHideNotification is also sendt when the keyboard is undocked. m_keyboardVisibleAndDocked = NO; @@ -407,11 +405,7 @@ void QIOSInputContext::update(Qt::InputMethodQueries query) void QIOSInputContext::reset() { - // Since the call to reset will cause a 'keyboardWillHide' - // notification to be sendt, we block keyboard nofifications to avoid artifacts: - m_keyboardListener->m_ignoreKeyboardChanges = true; [m_focusView reset]; - m_keyboardListener->m_ignoreKeyboardChanges = false; } void QIOSInputContext::commit() diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h index 575dedab89..122e7c604b 100644 --- a/src/plugins/platforms/ios/quiview.h +++ b/src/plugins/platforms/ios/quiview.h @@ -75,4 +75,5 @@ - (void)updateInputMethodWithQuery:(Qt::InputMethodQueries)query; - (void)reset; - (void)commit; ++ (bool)inUpdateKeyboardLayout; @end diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm index 03006b3f99..e65ac1cc46 100644 --- a/src/plugins/platforms/ios/quiview_textinput.mm +++ b/src/plugins/platforms/ios/quiview_textinput.mm @@ -45,9 +45,12 @@ class StaticVariables { public: QInputMethodQueryEvent inputMethodQueryEvent; + bool inUpdateKeyboardLayout; QTextCharFormat markedTextFormat; - StaticVariables() : inputMethodQueryEvent(Qt::ImQueryInput) + StaticVariables() + : inputMethodQueryEvent(Qt::ImQueryInput) + , inUpdateKeyboardLayout(false) { // There seems to be no way to query how the preedit text // should be drawn. So we need to hard-code the color. @@ -152,6 +155,47 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables); return [super resignFirstResponder]; } ++ (bool)inUpdateKeyboardLayout +{ + return staticVariables()->inUpdateKeyboardLayout; +} + +- (void)updateKeyboardLayout +{ + if (![self isFirstResponder]) + return; + + // There seems to be no API to inform that the keyboard layout needs to update. + // As a work-around, we quickly resign first responder just to reassign it again. + QScopedValueRollback rollback(staticVariables()->inUpdateKeyboardLayout); + staticVariables()->inUpdateKeyboardLayout = true; + [super resignFirstResponder]; + [self updateTextInputTraits]; + [super becomeFirstResponder]; +} + +- (void)updateUITextInputDelegate:(NSNumber *)intQuery +{ + // As documented, we should not report textWillChange/textDidChange unless the text + // was changed externally. That will cause spell checking etc to fail. But we don't + // really know if the text/selection was changed by UITextInput or Qt/app when getting + // update calls from Qt. We therefore use a less ideal approach where we always assume + // that UITextView caused the change if we're currently processing an event sendt from it. + if (m_inSendEventToFocusObject) + return; + + Qt::InputMethodQueries query = Qt::InputMethodQueries([intQuery intValue]); + if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition)) { + [self.inputDelegate selectionWillChange:id(self)]; + [self.inputDelegate selectionDidChange:id(self)]; + } + + if (query & Qt::ImSurroundingText) { + [self.inputDelegate textWillChange:id(self)]; + [self.inputDelegate textDidChange:id(self)]; + } +} + - (void)updateInputMethodWithQuery:(Qt::InputMethodQueries)query { Q_UNUSED(query); @@ -160,26 +204,13 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables); if (!focusObject) return; - if (!m_inSendEventToFocusObject) { - if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition)) - [self.inputDelegate selectionWillChange:id(self)]; - if (query & Qt::ImSurroundingText) - [self.inputDelegate textWillChange:id(self)]; - } - // Note that we ignore \a query, and instead update using Qt::ImQueryInput. This enables us to just // store the event without copying out the result from the event each time. Besides, we seem to be // called with Qt::ImQueryInput when only changing selection, and always if typing text. So there would // not be any performance gain by only updating \a query. staticVariables()->inputMethodQueryEvent = QInputMethodQueryEvent(Qt::ImQueryInput); QCoreApplication::sendEvent(focusObject, &staticVariables()->inputMethodQueryEvent); - - if (!m_inSendEventToFocusObject) { - if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition)) - [self.inputDelegate selectionDidChange:id(self)]; - if (query & Qt::ImSurroundingText) - [self.inputDelegate textDidChange:id(self)]; - } + [self updateUITextInputDelegate:[NSNumber numberWithInt:int(query)]]; } - (void)sendEventToFocusObject:(QEvent &)e @@ -189,35 +220,31 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables); return; // While sending the event, we will receive back updateInputMethodWithQuery calls. - // To not confuse iOS, we cannot not call textWillChange/textDidChange at that - // point since it will cause spell checking etc to fail. So we use a guard. + // Note that it would be more correct to post the event instead, but UITextInput expects + // callbacks to take effect immediately (it will query us for information after a callback). + QScopedValueRollback rollback(m_inSendEventToFocusObject); m_inSendEventToFocusObject = YES; QCoreApplication::sendEvent(focusObject, &e); - m_inSendEventToFocusObject = NO; } - (void)reset { - [self.inputDelegate textWillChange:id(self)]; [self setMarkedText:@"" selectedRange:NSMakeRange(0, 0)]; [self updateInputMethodWithQuery:Qt::ImQueryInput]; - - if ([self isFirstResponder]) { - // There seem to be no way to inform that the keyboard needs to update (since - // text input traits might have changed). As a work-around, we quickly resign - // first responder status just to reassign it again: - [super resignFirstResponder]; - [self updateTextInputTraits]; - [super becomeFirstResponder]; - } - [self.inputDelegate textDidChange:id(self)]; + // Guard agains recursive callbacks by posting calls to UITextInput + [self performSelectorOnMainThread:@selector(updateKeyboardLayout) withObject:nil waitUntilDone:NO]; + [self performSelectorOnMainThread:@selector(updateUITextInputDelegate:) + withObject:[NSNumber numberWithInt:int(Qt::ImQueryInput)] + waitUntilDone:NO]; } - (void)commit { - [self.inputDelegate textWillChange:id(self)]; [self unmarkText]; - [self.inputDelegate textDidChange:id(self)]; + // Guard agains recursive callbacks by posting calls to UITextInput + [self performSelectorOnMainThread:@selector(updateUITextInputDelegate:) + withObject:[NSNumber numberWithInt:int(Qt::ImSurroundingText)] + waitUntilDone:NO]; } - (QVariant)imValue:(Qt::InputMethodQuery)query -- cgit v1.2.3 From 7ec49393131461e07554f37042db16b5462a5565 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 5 Jun 2014 16:42:58 +0200 Subject: Fix documentation about QStringLiteral The fallback for QStringLiteral in case C++11 features are not enabled is QString::fromUtf8(), not QLatin1String(). Also, the result of a QStringLiteral expression _is_ a QString. Change-Id: Ib9c2f4c13fff237de3acb2e0f64027bacea6271c Reviewed-by: Giuseppe D'Angelo Reviewed-by: Olivier Goffart Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index aac9c493c3..a018b81c38 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -9872,9 +9872,7 @@ QString QString::toHtmlEscaped() const the read-only segment of the compiled object file. For compilers not supporting the creation of compile time strings, QStringLiteral will fall back to - QLatin1String. - - The result of the QStringLiteral expression can be cast into a QString. + QString::fromUtf8(). If you have code looking like: \code -- cgit v1.2.3 From 56a087a1ef3a9b9f66d738f45ee0cf3c7c7a6a0d Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Thu, 5 Jun 2014 16:11:04 +0200 Subject: Doc: Added link to SQL example page from main Qt SQL landing page. Change-Id: I1fe42b6ec72933ea8ba605836e8a56332fd3c691 Reviewed-by: Martin Smith --- src/sql/doc/src/qtsql.qdoc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sql/doc/src/qtsql.qdoc b/src/sql/doc/src/qtsql.qdoc index 2f806b4b45..f7dc840c7b 100644 --- a/src/sql/doc/src/qtsql.qdoc +++ b/src/sql/doc/src/qtsql.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -51,10 +51,12 @@ QT += sql \endcode - \section1 Reference - These are links to the API reference materials. + \section1 Related Information + + These are links to the API reference materials and related pages. \list \li \l{Qt SQL C++ Classes}{C++ Classes} + \li \l{SQL Examples} \endlist */ -- cgit v1.2.3 From 7e44e4bb4e23758be7c05261e0413365491c6846 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 5 Jun 2014 11:56:01 +0200 Subject: Windows: Added Comma to list of possible numpad keys Some keyboard layouts (German and Czech for example) have comma instead of period on the numpad, so this key should also be considered when setting the Qt::KeypadModifer state. Task-number: QTBUG-38248 Change-Id: I06847a02a9334c21784790eae6fd7e1bc6de4099 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowskeymapper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 0b257cc48f..6bcfe01a18 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -893,6 +893,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms case Qt::Key_Plus: case Qt::Key_Minus: case Qt::Key_Period: + case Qt::Key_Comma: case Qt::Key_0: case Qt::Key_1: case Qt::Key_2: -- cgit v1.2.3 From 9cd7403801f9dc842a4546ba793f88828cb01552 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 7 May 2014 13:35:42 +0200 Subject: winrt: do not try to close non existent sockets Change-Id: I41103db89985f8fbde1faaccaf33c7a76c275f7d Reviewed-by: Andrew Knight --- src/network/socket/qnativesocketengine_winrt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 8eb632ff63..22e52b3dad 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -475,9 +475,9 @@ void QNativeSocketEngine::close() Q_D(QNativeSocketEngine); if (d->socketDescriptor != -1) { IClosable *socket = 0; - if (d->socketType == QAbstractSocket::TcpSocket) + if (d->socketType == QAbstractSocket::TcpSocket && d->tcp) d->tcp->QueryInterface(IID_PPV_ARGS(&socket)); - else if (d->socketType == QAbstractSocket::UdpSocket) + else if (d->socketType == QAbstractSocket::UdpSocket && d->udp) d->udp->QueryInterface(IID_PPV_ARGS(&socket)); if (socket) { -- cgit v1.2.3 From 7e9f08302cc3118f8cc6b72dc93b3e0cbfbca2a7 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 7 May 2014 13:35:14 +0200 Subject: winrt: set error if tcp socket initialization fails Change-Id: I31a2684ffdc864c69fe896829bca860e88c4a6ca Reviewed-by: Andrew Knight --- src/network/socket/qnativesocketengine_winrt.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 22e52b3dad..1646940cb8 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -246,8 +246,11 @@ bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket:: d->tcp = handler->pendingTcpSockets.take(socketDescriptor); d->socketType = QAbstractSocket::TcpSocket; - if (!d->tcp || !d->fetchConnectionParameters()) + if (!d->tcp || !d->fetchConnectionParameters()) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + d->InvalidSocketErrorString); return false; + } d->socketState = socketState; return true; -- cgit v1.2.3 From 0af887124a05eecc2b649c93f8189d87ba669e36 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Thu, 5 Jun 2014 17:31:11 +0200 Subject: Do not crash with IA2 AT clients. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure all members of the IA2Locale we return are properly initialized. Only accProbe provoked this bug, and I have no idea why this haven't crashed earlier. nvda probably does not query the locale, therefore it was unaffected. Change-Id: I5a9d98eed5af56fd2a75f6cb7035ed613fd802d5 Reviewed-by: Jan Arve Sæther --- src/plugins/platforms/windows/accessible/iaccessible2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 7f2ed86404..d56925d0c4 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -522,6 +522,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale) QLocale l; res.country = QStringToBSTR(QLocale::countryToString(l.country())); res.language = QStringToBSTR(QLocale::languageToString(l.language())); + res.variant = QStringToBSTR(QString()); *locale = res; return S_OK; } -- cgit v1.2.3 From 7eba6d039dfbb9377a4358842fcd7210dc1fdd86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 4 Jun 2014 10:06:28 +0200 Subject: Cocoa: Re-implement QCocoaScreen::topLevelAt() The previous implementation used [NSApp orderedWindows] which does not return NSPanel subclasses, which is used by Qt dialogs and pops. Use [NSWidow windowNumberAtPoint:belowWindowWithWindowNumber] instead, which hit-tests on all window types. This can potentially include windows from other processes and non-Qt windows which needs to be filtered out. Add EXPECT_FAIL to tst_MacGui::nonModalOrder. The correct topLevelAt() implementation now exposes that this test is failing. Task-number: QTBUG-39322 Change-Id: I81afa3da964e08fe682802220d8fe81e9284205e Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 41 +++++++++++++++++------- tests/auto/other/macgui/tst_macgui.cpp | 1 + 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 19753ccc89..fca7fa042c 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -158,23 +158,42 @@ qreal QCocoaScreen::devicePixelRatio() const QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const { - // Get a z-ordered list of windows. Iterate through it until - // we find a (Qt) window which contains the point. - for (NSWindow *nsWindow in [NSApp orderedWindows]) { - if (![nsWindow isKindOfClass:[QNSWindow class]]) + NSPoint screenPoint = qt_mac_flipPoint(point); + + // Search (hit test) for the top-level window. [NSWidow windowNumberAtPoint: + // belowWindowWithWindowNumber] may return windows that are not interesting + // to Qt. The search iterates until a suitable window or no window is found. + NSInteger topWindowNumber = 0; + QWindow *window = 0; + do { + // Get the top-most window, below any previously rejected window. + topWindowNumber = [NSWindow windowNumberAtPoint:screenPoint + belowWindowWithWindowNumber:topWindowNumber]; + + // Continue the search if the window does not belong to this process. + NSWindow *nsWindow = [NSApp windowWithWindowNumber:topWindowNumber]; + if (nsWindow == 0) continue; - QNSWindow *qnsWindow = static_cast(nsWindow); - QCocoaWindow *cocoaWindow = qnsWindow.helper.platformWindow; + + // Continue the search if the window does not belong to Qt. + if (![nsWindow conformsToProtocol:@protocol(QNSWindowProtocol)]) + continue; + + id proto = static_cast >(nsWindow); + QCocoaWindow *cocoaWindow = proto.helper.platformWindow; if (!cocoaWindow) continue; - QWindow *window = cocoaWindow->window(); + window = cocoaWindow->window(); + + // Continue the search if the window is not a top-level window. if (!window->isTopLevel()) continue; - if (window->geometry().contains(point)) - return window; - } - return QPlatformScreen::topLevelAt(point); + // Stop searching. The current window is the correct window. + break; + } while (topWindowNumber > 0); + + return window; } extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); diff --git a/tests/auto/other/macgui/tst_macgui.cpp b/tests/auto/other/macgui/tst_macgui.cpp index 14993145b4..4314842c50 100644 --- a/tests/auto/other/macgui/tst_macgui.cpp +++ b/tests/auto/other/macgui/tst_macgui.cpp @@ -203,6 +203,7 @@ void tst_MacGui::nonModalOrder() primary.resize(400, 400); primary.move(100, 100); primary.exec(); + QEXPECT_FAIL("", "Non-modal child windows show behind the modal dialig", Abort); QCOMPARE(primary.frontWidget, primary.secondaryWindow); } -- cgit v1.2.3 From 398ae00e84433789598a716cd3e6202a2f76f1fd Mon Sep 17 00:00:00 2001 From: John Layt Date: Fri, 21 Mar 2014 20:30:01 +0100 Subject: QPrinter - Don't use QPrinterInfo::availablePrinters() The availablePrinters() method can be slow as it gets all info for every printer which may be slow with many network printers. Change-Id: I4bc5ef46ed4867326b60b66371178b84204639ce Reviewed-by: Andy Shaw --- src/printsupport/kernel/qprinter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index bdc9a98f2e..c758d9f4ea 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -120,9 +120,9 @@ QPrinterInfo QPrinterPrivate::findValidPrinter(const QPrinterInfo &printer) if (printerToUse.isNull()) { printerToUse = QPrinterInfo::defaultPrinter(); if (printerToUse.isNull()) { - QList availablePrinters = QPrinterInfo::availablePrinters(); - if (!availablePrinters.isEmpty()) - printerToUse = availablePrinters.at(0); + QStringList availablePrinterNames = QPrinterInfo::availablePrinterNames(); + if (!availablePrinterNames.isEmpty()) + printerToUse = QPrinterInfo::printerInfo(availablePrinterNames.at(0)); } } return printerToUse; -- cgit v1.2.3 From 908de0fb8d86945b7583b01f8d17c6e0afa6a864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Sat, 7 Jun 2014 00:24:47 +0200 Subject: NSURLConnection: Set http response status code. Make XMLHttpRequest.status work. Task-number: QTBUG-38864 Change-Id: Ic691b39a43aeb2ad3cd2e8ffef64c74d02699755 Reviewed-by: Simon Hausmann --- src/network/access/qnetworkreplynsurlconnectionimpl.mm | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/network/access/qnetworkreplynsurlconnectionimpl.mm b/src/network/access/qnetworkreplynsurlconnectionimpl.mm index d49324918e..f93f18357a 100644 --- a/src/network/access/qnetworkreplynsurlconnectionimpl.mm +++ b/src/network/access/qnetworkreplynsurlconnectionimpl.mm @@ -90,6 +90,7 @@ public: void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value); void setRawHeader(const QByteArray &headerName, const QByteArray &value); void setError(QNetworkReply::NetworkError errorCode, const QString &errorString); + void setAttribute(QNetworkRequest::Attribute code, const QVariant &value); }; @interface QtNSURLConnectionDelegate : NSObject @@ -140,6 +141,7 @@ QNetworkReplyNSURLConnectionImplPrivate::~QNetworkReplyNSURLConnectionImplPrivat void QNetworkReplyNSURLConnectionImplPrivate::setFinished() { q_func()->setFinished(true); + QMetaObject::invokeMethod(q_func(), "finished", Qt::QueuedConnection); } void QNetworkReplyNSURLConnectionImplPrivate::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value) @@ -157,6 +159,11 @@ void QNetworkReplyNSURLConnectionImplPrivate::setError(QNetworkReply::NetworkErr q_func()->setError(errorCode, errorString); } +void QNetworkReplyNSURLConnectionImplPrivate::setAttribute(QNetworkRequest::Attribute code, const QVariant &value) +{ + q_func()->setAttribute(code, value); +} + void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData() { Q_D(QNetworkReplyNSURLConnectionImpl); @@ -269,6 +276,9 @@ void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData() NSString *value = [headers objectForKey:key]; replyprivate->setRawHeader(QString::fromNSString(key).toUtf8(), QString::fromNSString(value).toUtf8()); } + + int code = [httpResponse statusCode]; + replyprivate->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, code); } else { if ([aResponse expectedContentLength] != NSURLResponseUnknownLength) replyprivate->setHeader(QNetworkRequest::ContentLengthHeader, [aResponse expectedContentLength]); @@ -317,8 +327,7 @@ void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData() - (void)connectionDidFinishLoading:(NSURLConnection*)connection { Q_UNUSED(connection) - replyprivate->setFinished(); - QMetaObject::invokeMethod(replyprivate->q_func(), "finished", Qt::QueuedConnection); + replyprivate->setFinished(); } - (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection*)connection -- cgit v1.2.3 From ebe4aaadb2e88db7cbc2c33f0867adfe7941bb9a Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 27 Apr 2014 16:46:51 +0200 Subject: tst_qtcpsocket: fix comment, the slot goes to 512 Change-Id: Ia0c5b29d6e02c9fda0b1da4a2779f1cbe9b1d747 Reviewed-by: Thiago Macieira --- tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 122ac63034..fcf6315c1f 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -2485,7 +2485,7 @@ void tst_QTcpSocket::increaseReadBufferSizeFromSlot() // like KIO's socketconnec QVERIFY2(passive->waitForBytesWritten(5000), "Network timeout"); // set the read buffer size to less than what was written, - // and increase it from the slot, first to 384 then to 1024. + // and increase it from the slot, first to 384 then to 512. active->setReadBufferSize(256); enterLoop(10); QVERIFY2(!timeout(), "Network timeout"); -- cgit v1.2.3 From 9a3a3b641a11022a69d77840714da13d8c5c4d5e Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 5 Jun 2014 23:23:07 +0200 Subject: Don't try to draw if there are no points in the path In some cases, for instance if drawEllipse() was called with a null QRect then it would still try to draw a QVectorPath without having enough points in the list. Therefore the point_count should be checked first before doing any drawing. Change-Id: I9b8dbb87c73b74e9df9eb10ec790a484d05d4c46 Reviewed-by: Gunnar Sletta --- src/gui/painting/qpaintengineex.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index e75a59cc91..8487cf2394 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -830,6 +830,8 @@ void QPaintEngineEx::drawEllipse(const QRectF &r) int point_count = 0; x.points[0] = qt_curves_for_arc(r, 0, -360, x.points + 1, &point_count); + if (point_count == 0) + return; QVectorPath vp((qreal *) pts, point_count + 1, qpaintengineex_ellipse_types, QVectorPath::EllipseHint); draw(vp); } -- cgit v1.2.3 From 29513210dfaf4252c67d7142737e41491297911d Mon Sep 17 00:00:00 2001 From: David Faure Date: Mon, 9 Jun 2014 10:54:27 +0200 Subject: Doc: QAtomicInteger first appeared in Qt 5.3 Change-Id: I900e5b0ec8291d34685cb545540a5a9f54551d05 Reviewed-by: Thiago Macieira --- src/corelib/thread/qatomic.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp index 33e85c1505..b2043a45a1 100644 --- a/src/corelib/thread/qatomic.cpp +++ b/src/corelib/thread/qatomic.cpp @@ -58,6 +58,7 @@ \inmodule QtCore \brief The QAtomicInteger class provides platform-independent atomic operations on integers. \ingroup thread + \since 5.3 For atomic operations on pointers, see the QAtomicPointer class. -- cgit v1.2.3 From 360fd4a278a8827d9727b295a753e623502c7445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Sat, 7 Jun 2014 23:34:45 +0200 Subject: Cocoa: Don't send duplicate close events. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't send QCloseEvents to QWidgetWindows during cmd-q application shutdown, since widgets will will already have received close events from QApplication close event handling. Task-number: QTBUG-39398 Change-Id: I7f6e892b0042361bed7a3bc5fac8518eabfc8e4e Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 548c6a23f0..f89439734f 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -223,7 +223,14 @@ static void cleanupCocoaApplicationDelegate() // events while the event loop is still running. const QWindowList topLevels = QGuiApplication::topLevelWindows(); for (int i = 0; i < topLevels.size(); ++i) { - QWindowSystemInterface::handleCloseEvent(topLevels.at(i)); + QWindow *topLevelWindow = topLevels.at(i); + // Widgets have alreay received a CloseEvent from the QApplication + // QCloseEvent handler. (see canQuit above). Prevent running the + // CloseEvent logic twice, call close() directly. + if (topLevelWindow->inherits("QWidgetWindow")) + topLevelWindow->close(); + else + QWindowSystemInterface::handleCloseEvent(topLevelWindow); } QWindowSystemInterface::flushWindowSystemEvents(); -- cgit v1.2.3 From 8480ddbe60492bb284fc614fd7bf304d3d9bd130 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 9 Jun 2014 22:59:16 +0200 Subject: Remove unnecessary comma in QStackedWidget doc. Change-Id: Iaa6102ea90c695eb2d81cc5d4fbd00dafc7783f5 Reviewed-by: Jerome Pasion --- src/widgets/widgets/qstackedwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/widgets/qstackedwidget.cpp b/src/widgets/widgets/qstackedwidget.cpp index 4b7170a596..6dbc7c8fad 100644 --- a/src/widgets/widgets/qstackedwidget.cpp +++ b/src/widgets/widgets/qstackedwidget.cpp @@ -91,7 +91,7 @@ public: the list using the addWidget() function, or inserted at a given index using the insertWidget() function. The removeWidget() function removes a widget from the stacked widget. The number of - widgets contained in the stacked widget, can + widgets contained in the stacked widget can be obtained using the count() function. The widget() function returns the widget at a given index -- cgit v1.2.3 From 7da3228abbb77af653b716a3729fac9b20279bfb Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 9 Jun 2014 14:06:08 +0200 Subject: Fix typo in QGraphicsTextItem::defaultTextColor() documentation. Change-Id: I6e255483d63a3024d9cbfe09a12f33d7fddf36c0 Reviewed-by: Jerome Pasion --- src/widgets/graphicsview/qgraphicsitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index d4edc63403..e327a8737a 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -9911,7 +9911,7 @@ void QGraphicsTextItem::setDefaultTextColor(const QColor &col) } /*! - Returns the default text color that is used to for unformatted text. + Returns the default text color that is used for unformatted text. */ QColor QGraphicsTextItem::defaultTextColor() const { -- cgit v1.2.3 From 1a3d149174efca50de812c4f336a7ebfe069243c Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Tue, 3 Jun 2014 13:23:38 +0200 Subject: qdoc: Revised logic for which example file to open in Qt Creator qdoc stores the 'files to open' into the example manifest. These files are opened in Qt Creator's editor when an example is selected from the Welcome / Examples list. This change uses the following criteria (case insensitive), in order of preference: - .qml file matching the project name - .cpp file matching the project name - .h file matching the project name - main.qml - main.cpp A 'mainFile = "true"' argument is written for the file that is preferred to be the top-most file. Having a main.qml file take precedence over main.cpp ensures that most Qt Quick examples open into the relevant QML code instead of the boilerplate C++ used for launching the application. Task-number: QTBUG-37203 Change-Id: I2ea58a31b1284f4f7d424dd35d49a84a23a88c23 Reviewed-by: Jerome Pasion Reviewed-by: Eike Ziller Reviewed-by: Martin Smith --- src/tools/qdoc/htmlgenerator.cpp | 57 ++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 407253ff64..d1bf34f8e1 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the tools applications of the Qt Toolkit. @@ -4399,36 +4399,43 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element) } QString ename = en->name().mid(en->name().lastIndexOf('/')+1); - QSet usedNames; + QMap filesToOpen; foreach (const Node* child, en->childNodes()) { if (child->subType() == Node::File) { - QString file = child->name(); - QString fileName = file.mid(file.lastIndexOf('/')+1); - QString baseName = fileName; - if ((fileName.count(QChar('.')) > 0) && - (fileName.endsWith(".cpp") || - fileName.endsWith(".h") || - fileName.endsWith(".qml"))) - baseName.truncate(baseName.lastIndexOf(QChar('.'))); - if (baseName.compare(ename, Qt::CaseInsensitive) == 0) { - if (!usedNames.contains(fileName)) { - writer.writeStartElement("fileToOpen"); - writer.writeCharacters(examplesPath + file); - writer.writeEndElement(); // fileToOpen - usedNames.insert(fileName); - } + QFileInfo fileInfo(child->name()); + QString fileName = fileInfo.fileName().toLower(); + // open .qml, .cpp and .h files with a + // basename matching the example (project) name + // QMap key indicates the priority - + // the lowest value will be the top-most file + if ((fileInfo.baseName().compare(ename, Qt::CaseInsensitive) == 0)) { + if (fileName.endsWith(".qml")) + filesToOpen.insert(0, child); + else if (fileName.endsWith(".cpp")) + filesToOpen.insert(1, child); + else if (fileName.endsWith(".h")) + filesToOpen.insert(2, child); } - else if (fileName.toLower().endsWith("main.cpp") || - fileName.toLower().endsWith("main.qml")) { - if (!usedNames.contains(fileName)) { - writer.writeStartElement("fileToOpen"); - writer.writeCharacters(examplesPath + file); - writer.writeEndElement(); // fileToOpen - usedNames.insert(fileName); - } + // main.qml takes precedence over main.cpp + else if (fileName.endsWith("main.qml")) { + filesToOpen.insert(3, child); } + else if (fileName.endsWith("main.cpp")) { + filesToOpen.insert(4, child); + } } } + + QMap::const_iterator it = filesToOpen.constEnd(); + while (it != filesToOpen.constBegin()) { + writer.writeStartElement("fileToOpen"); + if (--it == filesToOpen.constBegin()) { + writer.writeAttribute(QStringLiteral("mainFile"), QStringLiteral("true")); + } + writer.writeCharacters(examplesPath + it.value()->name()); + writer.writeEndElement(); + } + writer.writeEndElement(); // example ++i; } -- cgit v1.2.3 From e3d32bce79ee81e0434e91b225adaa6c42b5ec3a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 10 Jun 2014 11:42:23 +0200 Subject: Fix failing qtdeclarativetextedit auto-test After commit c3baa7c1dc8c29bfe60e8e5c676c606d4f699005 the qtdeclarativetextedit tests in the qtquick1 module started failing. This was due to commit 852abfca6f4c349dce9b895956922f96d82df579 from 4.8 not being forward-ported from Qt 4 to Qt 5, hence the comment in c3baa7c1dc8c29bfe60e8e5c676c606d4f699005 about the missing mousePressEvent line. It was intentionally removed and instead used further down, which is what this patch adds and therefore acts as forward-port of 852abfca6f4c349dce9b895956922f96d82df579. Change-Id: I55978c961002382c1f228bf796c469c10686ba9f Reviewed-by: Friedemann Kleint --- src/widgets/widgets/qwidgettextcontrol.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index b34c297f2e..96438a0bdf 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -1712,7 +1712,7 @@ void QWidgetTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button if (newCursorPos == -1) return; - if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { + if (mousePressed && wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { selectedWordOnDoubleClick = cursor; selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); } @@ -1721,7 +1721,7 @@ void QWidgetTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button extendBlockwiseSelection(newCursorPos); else if (selectedWordOnDoubleClick.hasSelection()) extendWordwiseSelection(newCursorPos, mouseX); - else if (!isPreediting()) + else if (mousePressed && !isPreediting()) setCursorPosition(newCursorPos, QTextCursor::KeepAnchor); if (interactionFlags & Qt::TextEditable) { -- cgit v1.2.3 From 8fa91217bcd0917cbc22e4608a579e6b1dedcde8 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Fri, 6 Jun 2014 14:59:53 +0200 Subject: Make sure we run gracefully below API level 18 Task-number: QTBUG-39508 Change-Id: I023ba7c50de5c95a5514658797125e22016a6543 Reviewed-by: Yoann Lopes Reviewed-by: Christian Stromme --- .../platforms/android/androidjniaccessibility.cpp | 13 ++++++++++--- src/plugins/platforms/android/androidjnimain.cpp | 17 ++--------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index d9f5cec27a..9d43c2f758 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -47,6 +47,7 @@ #include "qwindow.h" #include "qrect.h" #include "QtGui/qaccessible.h" +#include #include "qdebug.h" @@ -207,7 +208,7 @@ if (!clazz) { \ if (desc.isEmpty()) desc = iface->text(QAccessible::Description); if (QAccessibleTextInterface *textIface = iface->textInterface()) { - if (textIface->selectionCount() > 0) { + if (m_setTextSelectionMethodID && textIface->selectionCount() > 0) { int startSelection; int endSelection; textIface->selection(0, &startSelection, &endSelection); @@ -259,12 +260,15 @@ if (!clazz) { \ bool registerNatives(JNIEnv *env) { + if (QtAndroidPrivate::androidSdkVersion() < 16) + return true; // We need API level 16 or higher + jclass clazz; FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/accessibility/QtNativeAccessibility"); jclass appClass = static_cast(env->NewGlobalRef(clazz)); if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { - __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed"); + __android_log_print(ANDROID_LOG_FATAL,"Qt A11y", "RegisterNatives failed"); return false; } @@ -277,9 +281,12 @@ if (!clazz) { \ GET_AND_CHECK_STATIC_METHOD(m_setEnabledMethodID, nodeInfoClass, "setEnabled", "(Z)V"); GET_AND_CHECK_STATIC_METHOD(m_setFocusableMethodID, nodeInfoClass, "setFocusable", "(Z)V"); GET_AND_CHECK_STATIC_METHOD(m_setFocusedMethodID, nodeInfoClass, "setFocused", "(Z)V"); - GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V"); GET_AND_CHECK_STATIC_METHOD(m_setVisibleToUserMethodID, nodeInfoClass, "setVisibleToUser", "(Z)V"); + if (QtAndroidPrivate::androidSdkVersion() >= 18) { + GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V"); + } + return true; } } diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index d484a2faff..f711a68a71 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -423,6 +423,7 @@ namespace QtAndroid m_destroySurfaceMethodID, surfaceId); } + } // namespace QtAndroid @@ -743,15 +744,6 @@ static int registerNatives(JNIEnv *env) return JNI_TRUE; } -jint androidApiLevel(JNIEnv *env) -{ - jclass clazz; - FIND_AND_CHECK_CLASS("android/os/Build$VERSION"); - jfieldID fieldId; - GET_AND_CHECK_STATIC_FIELD(fieldId, clazz, "SDK_INT", "I"); - return env->GetStaticIntField(clazz, fieldId); -} - Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) { typedef union { @@ -774,17 +766,12 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) || !QtAndroidInput::registerNatives(env) || !QtAndroidClipboard::registerNatives(env) || !QtAndroidMenu::registerNatives(env) + || !QtAndroidAccessibility::registerNatives(env) || !QtAndroidDialogHelpers::registerNatives(env)) { __android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed"); return -1; } - jint apiLevel = androidApiLevel(env); - if (apiLevel >= 16 && !QtAndroidAccessibility::registerNatives(env)) { - __android_log_print(ANDROID_LOG_FATAL, "Qt A11y", "registerNatives failed"); - return -1; - } - m_javaVM = vm; return JNI_VERSION_1_4; } -- cgit v1.2.3 From 857c82f8a4a29399733218f783241b839b939f58 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Wed, 4 Jun 2014 18:11:00 +0200 Subject: Doc: Updated Layout examples. -added links to and from the overviews. -added information on how to run the example. -updated copyright. Task-number: QTBUG-33597 Change-Id: Ib049cb94f136caa6916878959ae830248bd236b5 Reviewed-by: Martin Smith Reviewed-by: Nico Vertriest --- examples/widgets/doc/src/basiclayouts.qdoc | 22 +++++++++++++--------- examples/widgets/doc/src/borderlayout.qdoc | 11 ++++++++--- examples/widgets/doc/src/dynamiclayouts.qdoc | 12 +++++++++--- examples/widgets/doc/src/flowlayout.qdoc | 17 +++++++++-------- src/widgets/doc/src/qtwidgets-index.qdoc | 1 + .../doc/src/widgets-and-layouts/layout.qdoc | 10 +++++++++- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/examples/widgets/doc/src/basiclayouts.qdoc b/examples/widgets/doc/src/basiclayouts.qdoc index d219b7bff3..0066317165 100644 --- a/examples/widgets/doc/src/basiclayouts.qdoc +++ b/examples/widgets/doc/src/basiclayouts.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -28,31 +28,35 @@ /*! \example layouts/basiclayouts \title Basic Layouts Example + \brief Shows how to use the standard layout managers. - \brief The Basic Layouts example shows how to use the standard layout - managers that are available in Qt: QBoxLayout, QGridLayout and - QFormLayout. + \e{Basic Layouts} shows how to use the standard layout managers that are + available in Qt: QBoxLayout, QGridLayout, and QFormLayout. \image basiclayouts-example.png Screenshot of the Basic Layouts example The QBoxLayout class lines up widgets horizontally or vertically. QHBoxLayout and QVBoxLayout are convenience subclasses of QBoxLayout. QGridLayout lays out widgets in cells by dividing the available space - into rows and columns. QFormLayout, on the other hand, lays out its + into rows and columns. QFormLayout, on the other hand, sets its children in a two-column form with labels in the left column and input fields in the right column. + For more information, visit the \l{Layout Management} page. + + \include examples-run.qdocinc + \section1 Dialog Class Definition \snippet layouts/basiclayouts/dialog.h 0 The \c Dialog class inherits QDialog. It is a custom widget that displays its child widgets using the geometry managers: - QHBoxLayout, QVBoxLayout, QGridLayout and QFormLayout. + QHBoxLayout, QVBoxLayout, QGridLayout, and QFormLayout. - We declare four private functions to simplify the class - constructor: The \c createMenu(), \c createHorizontalGroupBox(), - \c createGridGroupBox() and \c createFormGroupBox() functions create + There are four private functions to simplify the class + constructor: the \c createMenu(), \c createHorizontalGroupBox(), + \c createGridGroupBox(), and \c createFormGroupBox() functions create several widgets that the example uses to demonstrate how the layout affects their appearances. diff --git a/examples/widgets/doc/src/borderlayout.qdoc b/examples/widgets/doc/src/borderlayout.qdoc index 8a2958ee80..03a2bf1672 100644 --- a/examples/widgets/doc/src/borderlayout.qdoc +++ b/examples/widgets/doc/src/borderlayout.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -28,9 +28,14 @@ /*! \example layouts/borderlayout \title Border Layout Example + \brief Shows how to arrange child widgets along a border. - \brief The Border Layout example shows how to create a custom layout that arranges - child widgets according to a simple set of rules. + \e{Border Layout} implements a layout that arranges child widgets to + surround the main area. \image borderlayout-example.png + + For more information, visit the \l{Layout Management} page. + + \include examples-run.qdocinc */ diff --git a/examples/widgets/doc/src/dynamiclayouts.qdoc b/examples/widgets/doc/src/dynamiclayouts.qdoc index 5590ec61f1..497a0d23fd 100644 --- a/examples/widgets/doc/src/dynamiclayouts.qdoc +++ b/examples/widgets/doc/src/dynamiclayouts.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -28,7 +28,13 @@ /*! \example layouts/dynamiclayouts \title Dynamic Layouts Example + \brief Shows how to re-orient widgets in running applications. - \brief The Dynamic Layouts example shows how to move widgets around in - existing layouts. + \e{Dynamic Layouts} implements dynamically placed widgets within running + applications. The widget placement depends on whether \c Horizontal or \c + Vertical is chosen. + + For more information, visit the \l{Layout Management} page. + + \include examples-run.qdocinc */ diff --git a/examples/widgets/doc/src/flowlayout.qdoc b/examples/widgets/doc/src/flowlayout.qdoc index b482edf946..84de22416c 100644 --- a/examples/widgets/doc/src/flowlayout.qdoc +++ b/examples/widgets/doc/src/flowlayout.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -28,18 +28,19 @@ /*! \example layouts/flowlayout \title Flow Layout Example + \brief Shows how to arrange widgets for different window sizes. - \brief The Flow Layout example demonstrates a custom layout that arranges child - widgets from left to right and top to bottom in a top-level widget. + \e{Flow Layout} implements a layout that handles different window sizes. The + widget placement changes depending on the width of the application window. \image flowlayout-example.png Screenshot of the Flow Layout example - The items are first laid out horizontally and then vertically when each line - in the layout runs out of space. - The Flowlayout class mainly uses QLayout and QWidgetItem, while the - Window uses QWidget and QLabel. We will only document the definition - and implementation of \c FlowLayout below. + Window uses QWidget and QLabel. + + For more information, visit the \l{Layout Management} page. + + \include examples-run.qdocinc \section1 FlowLayout Class Definition diff --git a/src/widgets/doc/src/qtwidgets-index.qdoc b/src/widgets/doc/src/qtwidgets-index.qdoc index 859a0ef933..bc74f43b35 100644 --- a/src/widgets/doc/src/qtwidgets-index.qdoc +++ b/src/widgets/doc/src/qtwidgets-index.qdoc @@ -139,6 +139,7 @@ interfaces \section2 Examples \list \li \l{Qt Widgets Examples} + \li \l{Layout Examples} \endlist \section1 API Reference diff --git a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc index 99d512b507..f581df4cb3 100644 --- a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc +++ b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc @@ -386,5 +386,13 @@ then set it. (This does not only apply to layouts, you should do the same if you implement your own resizeEvent(), for example.) \endlist -*/ + \section1 Layout Examples + + Many Qt Widgets \l{Qt Widgets Examples}{examples} already use layouts, + however, several examples exist to showcase various layouts. + + \list + \li \l{Layout Examples} + \endlist +*/ -- cgit v1.2.3 From aa4ad43cfded4b3db0aef8b7cfd6cbeb1bb5c253 Mon Sep 17 00:00:00 2001 From: Steffen Imhof Date: Thu, 22 May 2014 16:23:21 +0200 Subject: Fix QT_NO_LIBRARY compile in Unix DNS lookup implementation. The static method QDnsLookupRunnable::query() got an additional parameter for QTBUG-30166, but the #ifdef'd part was not updated. Change-Id: Ifc317bfae6e02c00936e1922ec77f89fb5faf497 Reviewed-by: Richard J. Moore --- src/network/kernel/qdnslookup_unix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index 26834dff57..108fcbaf60 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -370,11 +370,11 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN } #else - -void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply) +void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply) { Q_UNUSED(requestType) Q_UNUSED(requestName) + Q_UNUSED(nameserver) reply->error = QDnsLookup::ResolverError; reply->errorString = tr("Resolver library can't be loaded: No runtime library loading support"); return; -- cgit v1.2.3 From ba9b1b05127eaf01b1fa144484826f064f9ffcd7 Mon Sep 17 00:00:00 2001 From: Steffen Imhof Date: Mon, 2 Jun 2014 17:18:59 +0200 Subject: Fix QT_NO_BEARERMANAGEMENT compile of QHttpThreadDelegate. Re-order the constructor parameters for QHttpNetworkConnection to be consistent with the #ifndef version. Change-Id: Icd8be4406ff549d468e06d635fac2ddc34826b1c Reviewed-by: Richard J. Moore --- src/network/access/qhttpnetworkconnection.cpp | 4 ++-- src/network/access/qhttpnetworkconnection_p.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 32b6d902d0..360f9722c7 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -1219,8 +1219,8 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS d->init(); } #else -QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent, - QHttpNetworkConnection::ConnectionType connectionType) +QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, + QHttpNetworkConnection::ConnectionType connectionType, QObject *parent) : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt , connectionType)), parent) { Q_D(QHttpNetworkConnection); diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 9d4257e217..42114ae9d6 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -110,8 +110,8 @@ public: ConnectionType connectionType = ConnectionTypeHTTP); #else explicit QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false, - QObject *parent = 0, - ConnectionType connectionType = ConnectionTypeHTTP); + ConnectionType connectionType = ConnectionTypeHTTP, + QObject *parent = 0); QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0, ConnectionType connectionType = ConnectionTypeHTTP); -- cgit v1.2.3 From 641ca1d7cbdef919130411ff1999229d2e477327 Mon Sep 17 00:00:00 2001 From: Steffen Imhof Date: Wed, 28 May 2014 14:14:39 +0200 Subject: Fix QT_NO_SETTINGS build in QLibraryInfo. One reference to QSettings was only guarded by QT_BOOTSTRAPPED. Change-Id: I2f9761ee88b4a45edb16054fdba3c3f11fec12ff Reviewed-by: Oswald Buddenhagen --- src/corelib/global/qlibraryinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 6d25325890..174c1d0d8d 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -537,7 +537,7 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group) QStringList QLibraryInfo::platformPluginArguments(const QString &platformName) { -#ifndef QT_BOOTSTRAPPED +#if !defined(QT_BOOTSTRAPPED) && !defined(QT_NO_SETTINGS) if (const QSettings *settings = QLibraryInfoPrivate::findConfiguration()) { QString key = QLatin1String(platformsSection); key += QLatin1Char('/'); @@ -545,7 +545,7 @@ QStringList QLibraryInfo::platformPluginArguments(const QString &platformName) key += QLatin1String("Arguments"); return settings->value(key).toStringList(); } -#endif // !QT_BOOTSTRAPPED +#endif // !QT_BOOTSTRAPPED && !QT_NO_SETTINGS return QStringList(); } -- cgit v1.2.3 From d06c6d8a51c9bd79396471f4131ac67f1d11e2c2 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Wed, 11 Jun 2014 11:37:58 +0200 Subject: Compose key plugin: expand "%L" to full path. According to [1] "%L" should expand to a full path for the default (based on system's locale) Compose file. [1] http://www.x.org/archive/current/doc/man/man5/Compose.5.xhtml Task-number: QTBUG-35943 Change-Id: Ie803a89742d9c0aa3b2d759bea28ed403dc68c9c Reviewed-by: Lars Knoll --- .../compose/generator/qtablegenerator.cpp | 21 +++++++++++++-------- .../compose/generator/qtablegenerator.h | 3 ++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp index ea0b5261c4..395bb5b090 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp @@ -111,21 +111,17 @@ void TableGenerator::findComposeFile() } // check for the system provided compose files if (!found && cleanState()) { - QByteArray loc = locale().toUpper().toUtf8(); - QString table = readLocaleMappings(loc); - if (table.isEmpty()) - table = readLocaleMappings(readLocaleAliases(loc)); - + QString table = composeTableForLocale(); if (cleanState()) { if (table.isEmpty()) // no table mappings for the system's locale in the compose.dir m_state = UnsupportedLocale; else - found = processFile(systemComposeDir() + QLatin1String("/") + table); + found = processFile(systemComposeDir() + QLatin1Char('/') + table); #ifdef DEBUG_GENERATOR if (found) qDebug() << "Using Compose file from: " << - systemComposeDir() + QLatin1String("/") + table; + systemComposeDir() + QLatin1Char('/') + table; #endif } } @@ -137,6 +133,15 @@ void TableGenerator::findComposeFile() m_state = MissingComposeFile; } +QString TableGenerator::composeTableForLocale() +{ + QByteArray loc = locale().toUpper().toUtf8(); + QString table = readLocaleMappings(loc); + if (table.isEmpty()) + table = readLocaleMappings(readLocaleAliases(loc)); + return table; +} + bool TableGenerator::findSystemComposeDir() { bool found = false; @@ -311,7 +316,7 @@ void TableGenerator::parseIncludeInstruction(QString line) // expand substitutions if present line.replace(QLatin1String("%H"), QString(qgetenv("HOME"))); - line.replace(QLatin1String("%L"), locale()); + line.replace(QLatin1String("%L"), systemComposeDir() + QLatin1Char('/') + composeTableForLocale()); line.replace(QLatin1String("%S"), systemComposeDir()); processFile(line); diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h index 248c09f3ea..6ce89cfe77 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h @@ -118,13 +118,14 @@ protected: void findComposeFile(); bool findSystemComposeDir(); QString systemComposeDir(); + QString composeTableForLocale(); ushort keysymToUtf8(quint32 sym); QString readLocaleMappings(const QByteArray &locale); QByteArray readLocaleAliases(const QByteArray &locale); void initPossibleLocations(); - bool cleanState() const { return ((m_state & NoErrors) == NoErrors); } + bool cleanState() const { return m_state == NoErrors; } QString locale() const; private: -- cgit v1.2.3 From f65333b027463ea40e0cd4603e48fca62d60216a Mon Sep 17 00:00:00 2001 From: Coursar Date: Mon, 2 Jun 2014 11:58:08 +0400 Subject: Fix Android: use fbo read back workaround with specific GPUs. Namely, the Adreno 205. We used to enable this workaround for Huawei Honor (Adreno 205). Task-number: QTBUG-33951 Change-Id: Ic92a6913664f2f0954271c700d9ef83d27c238a7 Reviewed-by: Yoann Lopes --- src/plugins/platforms/android/qandroidplatformopenglcontext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp index 53047585cf..3a3ea71562 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp @@ -74,6 +74,7 @@ bool QAndroidPlatformOpenGLContext::needsFBOReadBackWorkaroud() needsWorkaround = qstrcmp(rendererString, "Mali-400 MP") == 0 || qstrcmp(rendererString, "Adreno (TM) 200") == 0 + || qstrcmp(rendererString, "Adreno (TM) 205") == 0 || qstrcmp(rendererString, "GC1000 core") == 0; set = true; } -- cgit v1.2.3 From dbe6db192aa1a3e708b00a98a17636af37ceec27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Wed, 11 Jun 2014 12:54:21 +0100 Subject: Windows: Fix maximizing frameless windows on secondary screens. They would either disappear or be positioned at bogus coordinates. The MINMAXINFO structure works with coords from the primary screen then uses an "interesting" algorithm to adjust to secondary screen: Say you have a primary screen with width=1000 and secondary screen with width=2000, here's what you get when you set ptMaxSize to: ptMaxSize.x | Size window gets in second screen -------------------------------------------------- 500 | 500 1000 | 2000 1001 | 2001 1100 | 2100 So basically you can't get any value between 1000 and 1999 How many people use the taskbar on a second display and maximimize a frameless window anyway ? Task-number: QTBUG-39537 Change-Id: Ic9b3120e7fb5a9a5d97828a2e44be02ae587b92e Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowswindow.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index c8eaded38d..cdc0b24464 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1936,7 +1936,10 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const && (m_data.flags & Qt::FramelessWindowHint)) { // This block fixes QTBUG-8361: Frameless windows shouldn't cover the // taskbar when maximized - if (const QScreen *screen = effectiveScreen(window())) { + const QScreen *screen = effectiveScreen(window()); + + // Documentation of MINMAXINFO states that it will only work for the primary screen + if (screen && screen == QGuiApplication::primaryScreen()) { mmi->ptMaxSize.y = screen->availableGeometry().height(); // Width, because you can have the taskbar on the sides too. @@ -1945,8 +1948,8 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const // If you have the taskbar on top, or on the left you don't want it at (0,0): mmi->ptMaxPosition.x = screen->availableGeometry().x(); mmi->ptMaxPosition.y = screen->availableGeometry().y(); - } else { - qWarning() << "Invalid screen"; + } else if (!screen){ + qWarning() << "effectiveScreen() returned a null screen"; } } -- cgit v1.2.3 From 11aaff3a57afe7a8ff37bfa83cc545cc04c38649 Mon Sep 17 00:00:00 2001 From: David Faure Date: Wed, 11 Jun 2014 11:48:36 +0200 Subject: Add missing detach() in QPixmap::convertFromImage() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-18519 Change-Id: I5d929cf6eda3f34130314edac95487fb00a95db5 Reviewed-by: Jędrzej Nowacki Reviewed-by: Friedemann Kleint --- src/gui/image/qpixmap.cpp | 1 + tests/auto/gui/image/qpixmap/tst_qpixmap.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 86c4dfbdca..c6d8d19bb1 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1098,6 +1098,7 @@ bool QPixmap::isDetached() const */ bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags) { + detach(); if (image.isNull() || !data) *this = QPixmap::fromImage(image, flags); else diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index 79dc3f311a..b9d0adcd21 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -91,6 +91,7 @@ private slots: void convertFromImage_data(); void convertFromImage(); + void convertFromImageShouldDetach(); void testMetrics(); @@ -343,6 +344,20 @@ void tst_QPixmap::convertFromImage() QCOMPARE(pix, res); } +void tst_QPixmap::convertFromImageShouldDetach() +{ + const QString prefix = QFINDTESTDATA("convertFromImage"); + QImage img1; + QImage img2; + QVERIFY(img1.load(prefix + "/task31722_0/img1.png")); + QVERIFY(img2.load(prefix + "/task31722_0/img2.png")); + QPixmap pix = QPixmap::fromImage(img1); + QPixmap pix1 = pix; + pix.convertFromImage(img2); + QCOMPARE(pix, QPixmap::fromImage(img2)); + QCOMPARE(pix1, QPixmap::fromImage(img1)); // unchanged +} + void tst_QPixmap::scroll_data() { QTest::addColumn("input"); -- cgit v1.2.3 From a6d7e09e89a73b3706aabbf2d08586f238348c7c Mon Sep 17 00:00:00 2001 From: David Faure Date: Fri, 6 Jun 2014 13:53:58 +0200 Subject: QWidget: fix documentation for isEnabledTo(0) It is NOT always the same as isEnabled(). Added a unittest to prove it. Change-Id: I7717126835923e8c091249bfcdf81767c44fb5f7 Reviewed-by: Giuseppe D'Angelo --- src/widgets/kernel/qwidget.cpp | 8 +++++++- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 65e435fbdc..7396808442 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -2912,7 +2912,13 @@ void QWidget::showNormal() This is the case if neither the widget itself nor every parent up to but excluding \a ancestor has been explicitly disabled. - isEnabledTo(0) is equivalent to isEnabled(). + isEnabledTo(0) returns false if this widget or any if its ancestors + was explicitly disabled. + + The word ancestor here means a parent widget within the same window. + + Therefore isEnabledTo(0) stops at this widget's window, unlike + isEnabled() which also takes parent windows into considerations. \sa setEnabled(), enabled */ diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 34936fa5b8..eac8ab2236 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -1210,6 +1210,12 @@ void tst_QWidget::isEnabledTo() QVERIFY( !childWidget->isEnabledTo( testWidget ) ); QVERIFY( grandChildWidget->isEnabledTo( childWidget ) ); QVERIFY( !grandChildWidget->isEnabledTo( testWidget ) ); + + QMainWindow* childDialog = new QMainWindow(testWidget); + testWidget->setEnabled(false); + QVERIFY(!childDialog->isEnabled()); + QVERIFY(childDialog->isEnabledTo(0)); + testWidget->setEnabled(true); } void tst_QWidget::visible() -- cgit v1.2.3 From 81ba16cad933981f55218964a89ed1446022efba Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 24 Mar 2014 16:12:20 +0100 Subject: Fix case insensitive comparisons using QCollator In ICU the strength parameter decides whether a comparison is case sensitive or not. Fix mac comparison code. It can't have worked before. Added some basic automated testing for QCollator. Change-Id: I2646c464fd22ccd3a93c461fa3dba4bd1d4c7b4b Reviewed-by: Konstantin Ritt --- src/corelib/tools/qcollator_icu.cpp | 11 ++- src/corelib/tools/qcollator_macx.cpp | 9 ++- .../auto/corelib/tools/qcollator/tst_qcollator.cpp | 90 ++++++++++++++++++++++ 3 files changed, 105 insertions(+), 5 deletions(-) diff --git a/src/corelib/tools/qcollator_icu.cpp b/src/corelib/tools/qcollator_icu.cpp index 407a493d25..23e88b5015 100644 --- a/src/corelib/tools/qcollator_icu.cpp +++ b/src/corelib/tools/qcollator_icu.cpp @@ -75,10 +75,17 @@ void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs) { detach(); - UColAttributeValue val = (cs == Qt::CaseSensitive) ? UCOL_UPPER_FIRST : UCOL_OFF; + // The strength attribute in ICU is rather badly documented. Basically UCOL_PRIMARY + // ignores differences between base characters and accented characters as well as case. + // So A and A-umlaut would compare equal. + // UCOL_SECONDARY ignores case differences. UCOL_TERTIARY is the default in most languages + // and does case sensitive comparison. + // UCOL_QUATERNARY is used as default in a few languages such as Japanese to take care of some + // additional differences in those languages. + UColAttributeValue val = (cs == Qt::CaseSensitive) ? UCOL_DEFAULT_STRENGTH : UCOL_SECONDARY; UErrorCode status = U_ZERO_ERROR; - ucol_setAttribute(d->collator, UCOL_CASE_FIRST, val, &status); + ucol_setAttribute(d->collator, UCOL_STRENGTH, val, &status); if (U_FAILURE(status)) qWarning("ucol_setAttribute: Case First failed: %d", status); } diff --git a/src/corelib/tools/qcollator_macx.cpp b/src/corelib/tools/qcollator_macx.cpp index 8985cd4eba..877510489a 100644 --- a/src/corelib/tools/qcollator_macx.cpp +++ b/src/corelib/tools/qcollator_macx.cpp @@ -128,12 +128,15 @@ bool QCollator::ignorePunctuation() const int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const { SInt32 result; - return UCCompareText(d->collator.collator, + Boolean equivalent; + UCCompareText(d->collator.collator, reinterpret_cast(s1), len1, reinterpret_cast(s2), len2, - NULL, + &equivalent, &result); - return result; + if (equivalent) + return 0; + return result < 0 ? -1 : 1; } int QCollator::compare(const QString &str1, const QString &str2) const { diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp index 3df8422a34..9ed27a8742 100644 --- a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp +++ b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp @@ -52,6 +52,9 @@ class tst_QCollator : public QObject private Q_SLOTS: void moveSemantics(); + + void compare_data(); + void compare(); }; #ifdef Q_COMPILER_RVALUE_REFS @@ -87,6 +90,93 @@ void tst_QCollator::moveSemantics() #endif } + +void tst_QCollator::compare_data() +{ + QTest::addColumn("locale"); + QTest::addColumn("s1"); + QTest::addColumn("s2"); + QTest::addColumn("result"); + QTest::addColumn("caseInsensitiveResult"); + + /* + A few tests below are commented out on the mac. It's unclear why they fail, + as it looks like the collator for the locale is created correctly. + */ + + /* + It's hard to test English, because it's treated differently + on different platforms. For example, on Linux, it uses the + iso14651_t1 template file, which happens to provide good + defaults for Swedish. Mac OS X seems to do a pure bytewise + comparison of Latin-1 values, although I'm not sure. So I + just test digits to make sure that it's not totally broken. + */ + QTest::newRow("english1") << QString("en_US") << QString("5") << QString("4") << 1 << 1; + QTest::newRow("english2") << QString("en_US") << QString("4") << QString("6") << -1 << -1; + QTest::newRow("english3") << QString("en_US") << QString("5") << QString("6") << -1 << -1; + QTest::newRow("english4") << QString("en_US") << QString("a") << QString("b") << -1 << -1; + /* + In Swedish, a with ring above (E5) comes before a with + diaresis (E4), which comes before o diaresis (F6), which + all come after z. + */ + QTest::newRow("swedish1") << QString("sv_SE") << QString::fromLatin1("\xe5") << QString::fromLatin1("\xe4") << -1 << -1; + QTest::newRow("swedish2") << QString("sv_SE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1 << -1; + QTest::newRow("swedish3") << QString("sv_SE") << QString::fromLatin1("\xe5") << QString::fromLatin1("\xf6") << -1 << -1; +#ifndef Q_OS_MAC + QTest::newRow("swedish4") << QString("sv_SE") << QString::fromLatin1("z") << QString::fromLatin1("\xe5") << -1 << -1; +#endif + + /* + In Norwegian, ae (E6) comes before o with stroke (D8), which + comes before a with ring above (E5). + */ + QTest::newRow("norwegian1") << QString("no_NO") << QString::fromLatin1("\xe6") << QString::fromLatin1("\xd8") << -1 << -1; +#ifndef Q_OS_MAC + QTest::newRow("norwegian2") << QString("no_NO") << QString::fromLatin1("\xd8") << QString::fromLatin1("\xe5") << -1 << -1; +#endif + QTest::newRow("norwegian3") << QString("no_NO") << QString::fromLatin1("\xe6") << QString::fromLatin1("\xe5") << -1 << -1; + + /* + In German, z comes *after* a with diaresis (E4), + which comes before o diaresis (F6). + */ + QTest::newRow("german1") << QString("de_DE") << QString::fromLatin1("a") << QString::fromLatin1("\xe4") << -1 << -1; + QTest::newRow("german2") << QString("de_DE") << QString::fromLatin1("b") << QString::fromLatin1("\xe4") << 1 << 1; + QTest::newRow("german3") << QString("de_DE") << QString::fromLatin1("z") << QString::fromLatin1("\xe4") << 1 << 1; + QTest::newRow("german4") << QString("de_DE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1 << -1; + QTest::newRow("german5") << QString("de_DE") << QString::fromLatin1("z") << QString::fromLatin1("\xf6") << 1 << 1; + QTest::newRow("german6") << QString("de_DE") << QString::fromLatin1("\xc0") << QString::fromLatin1("\xe0") << 1 << 0; + QTest::newRow("german7") << QString("de_DE") << QString::fromLatin1("\xd6") << QString::fromLatin1("\xf6") << 1 << 0; + QTest::newRow("german8") << QString("de_DE") << QString::fromLatin1("oe") << QString::fromLatin1("\xf6") << 1 << 1; + QTest::newRow("german9") << QString("de_DE") << QString("A") << QString("a") << 1 << 0; + + /* + French sorting of e and e with accent + */ + QTest::newRow("french1") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("e") << 1 << 1; + QTest::newRow("french2") << QString("fr_FR") << QString::fromLatin1("\xe9t") << QString::fromLatin1("et") << 1 << 1; + QTest::newRow("french3") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("d") << 1 << 1; + QTest::newRow("french4") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("f") << -1 << -1; + +} + + +void tst_QCollator::compare() +{ + QFETCH(QString, locale); + QFETCH(QString, s1); + QFETCH(QString, s2); + QFETCH(int, result); + QFETCH(int, caseInsensitiveResult); + + QCollator collator(locale); + QCOMPARE(collator.compare(s1, s2), result); + collator.setCaseSensitivity(Qt::CaseInsensitive); + QCOMPARE(collator.compare(s1, s2), caseInsensitiveResult); +} + QTEST_APPLESS_MAIN(tst_QCollator) #include "tst_qcollator.moc" -- cgit v1.2.3 From 02b7b21f9bafcba3231610fef31b590474567472 Mon Sep 17 00:00:00 2001 From: Zhang Xingtao Date: Thu, 12 Jun 2014 19:11:35 +0800 Subject: Doc: correct the format of Q_PLUGIN_METADATA macro in sample codes Change-Id: I464a0c0a590b0b90cf0fe7ccd448ee9bf704bd4f Reviewed-by: Olivier Goffart --- src/corelib/doc/snippets/code/doc_src_plugins-howto.cpp | 2 +- src/widgets/doc/snippets/qstyleplugin/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/doc/snippets/code/doc_src_plugins-howto.cpp b/src/corelib/doc/snippets/code/doc_src_plugins-howto.cpp index aae4f4bd00..b86f0bbf68 100644 --- a/src/corelib/doc/snippets/code/doc_src_plugins-howto.cpp +++ b/src/corelib/doc/snippets/code/doc_src_plugins-howto.cpp @@ -42,7 +42,7 @@ class MyStylePlugin : public QStylePlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE mystyleplugin.json) + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "mystyleplugin.json") public: QStyle *create(const QString &key); }; diff --git a/src/widgets/doc/snippets/qstyleplugin/main.cpp b/src/widgets/doc/snippets/qstyleplugin/main.cpp index 4cf20ab960..e1a0d1b626 100644 --- a/src/widgets/doc/snippets/qstyleplugin/main.cpp +++ b/src/widgets/doc/snippets/qstyleplugin/main.cpp @@ -45,7 +45,7 @@ class MyStylePlugin : public QStylePlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE mystyleplugin.json) + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "mystyleplugin.json") public: MyStylePlugin(QObject *parent = 0); -- cgit v1.2.3 From 3f39c0f76cec121181ab9d6a0cf057c1b1aeb25c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 4 Jun 2014 12:25:56 +0200 Subject: Polish the image viewer example. - Open files passed on the command line. - Point the file dialog to the pictures location and use a filter string for the supported types. - Set the window title according to file name. Task-number: QTBUG-37203 Task-number: QTBUG-39287 Change-Id: I4e5e43875c3a7544c862c054181e75942939c1d5 Reviewed-by: David Faure --- examples/widgets/doc/src/imageviewer.qdoc | 21 ++++--- .../widgets/widgets/imageviewer/imageviewer.cpp | 68 ++++++++++++++-------- examples/widgets/widgets/imageviewer/imageviewer.h | 3 +- examples/widgets/widgets/imageviewer/main.cpp | 12 +++- 4 files changed, 70 insertions(+), 34 deletions(-) diff --git a/examples/widgets/doc/src/imageviewer.qdoc b/examples/widgets/doc/src/imageviewer.qdoc index 96013e844a..6361e3f35b 100644 --- a/examples/widgets/doc/src/imageviewer.qdoc +++ b/examples/widgets/doc/src/imageviewer.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -112,15 +112,19 @@ {ImageViewer}'s appearance. \snippet widgets/imageviewer/imageviewer.cpp 1 - \snippet widgets/imageviewer/imageviewer.cpp 2 - In the \c open() slot, we show a file dialog to the user. The - easiest way to create a QFileDialog is to use the static - convenience functions. QFileDialog::getOpenFileName() returns an - existing file selected by the user. If the user presses \uicontrol - Cancel, QFileDialog returns an empty string. + In the \c open() slot, we show a file dialog to the user. We compile + a list of mime types for use as a filter by querying QImageReader + for the available mime type names. + + We show the file dialog until a valid file name is entered or + the user cancels. + + The function \c loadFile() is used to load the image. + + \snippet widgets/imageviewer/imageviewer.cpp 2 - Unless the file name is a empty string, we check if the file's + In the \c loadFile() function, we check if the file's format is an image format by constructing a QImage which tries to load the image from the file. If the constructor returns a null image, we use a QMessageBox to alert the user. @@ -135,7 +139,6 @@ information message with an \uicontrol OK button (the default) is sufficient, since the message is part of a normal operation. - \snippet widgets/imageviewer/imageviewer.cpp 3 \snippet widgets/imageviewer/imageviewer.cpp 4 If the format is supported, we display the image in \c imageLabel diff --git a/examples/widgets/widgets/imageviewer/imageviewer.cpp b/examples/widgets/widgets/imageviewer/imageviewer.cpp index 77ec92d57a..eae94a2499 100644 --- a/examples/widgets/widgets/imageviewer/imageviewer.cpp +++ b/examples/widgets/widgets/imageviewer/imageviewer.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the examples of the Qt Toolkit. @@ -61,39 +61,61 @@ ImageViewer::ImageViewer() createActions(); createMenus(); - setWindowTitle(tr("Image Viewer")); - resize(500, 400); + resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5); } + //! [0] +//! [2] -//! [1] -void ImageViewer::open() -//! [1] //! [2] +bool ImageViewer::loadFile(const QString &fileName) { - QString fileName = QFileDialog::getOpenFileName(this, - tr("Open File"), QDir::currentPath()); - if (!fileName.isEmpty()) { - QImage image(fileName); - if (image.isNull()) { - QMessageBox::information(this, tr("Image Viewer"), - tr("Cannot load %1.").arg(fileName)); - return; - } + QImage image(fileName); + if (image.isNull()) { + QMessageBox::information(this, QGuiApplication::applicationDisplayName(), + tr("Cannot load %1.").arg(QDir::toNativeSeparators(fileName))); + setWindowFilePath(QString()); + imageLabel->setPixmap(QPixmap()); + imageLabel->adjustSize(); + return false; + } //! [2] //! [3] - imageLabel->setPixmap(QPixmap::fromImage(image)); + imageLabel->setPixmap(QPixmap::fromImage(image)); //! [3] //! [4] - scaleFactor = 1.0; + scaleFactor = 1.0; + + printAct->setEnabled(true); + fitToWindowAct->setEnabled(true); + updateActions(); - printAct->setEnabled(true); - fitToWindowAct->setEnabled(true); - updateActions(); + if (!fitToWindowAct->isChecked()) + imageLabel->adjustSize(); - if (!fitToWindowAct->isChecked()) - imageLabel->adjustSize(); - } + setWindowFilePath(fileName); + return true; } + //! [4] +//! [2] + +//! [1] +void ImageViewer::open() +{ + QStringList mimeTypeFilters; + foreach (const QByteArray &mimeTypeName, QImageReader::supportedMimeTypes()) + mimeTypeFilters.append(mimeTypeName); + mimeTypeFilters.sort(); + const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation); + QFileDialog dialog(this, tr("Open File"), + picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.first()); + dialog.setAcceptMode(QFileDialog::AcceptOpen); + dialog.setMimeTypeFilters(mimeTypeFilters); + dialog.selectMimeTypeFilter("image/jpeg"); + + while (dialog.exec() == QDialog::Accepted && !loadFile(dialog.selectedFiles().first())) {} +} +//! [1] + //! [5] void ImageViewer::print() //! [5] //! [6] diff --git a/examples/widgets/widgets/imageviewer/imageviewer.h b/examples/widgets/widgets/imageviewer/imageviewer.h index 7a0f0eb845..a4fd82a696 100644 --- a/examples/widgets/widgets/imageviewer/imageviewer.h +++ b/examples/widgets/widgets/imageviewer/imageviewer.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the examples of the Qt Toolkit. @@ -61,6 +61,7 @@ class ImageViewer : public QMainWindow public: ImageViewer(); + bool loadFile(const QString &); private slots: void open(); diff --git a/examples/widgets/widgets/imageviewer/main.cpp b/examples/widgets/widgets/imageviewer/main.cpp index f1697f9e3f..ee66b29591 100644 --- a/examples/widgets/widgets/imageviewer/main.cpp +++ b/examples/widgets/widgets/imageviewer/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the examples of the Qt Toolkit. @@ -39,13 +39,23 @@ ****************************************************************************/ #include +#include #include "imageviewer.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); + QGuiApplication::setApplicationDisplayName(ImageViewer::tr("Image Viewer")); + QCommandLineParser commandLineParser; + commandLineParser.addHelpOption(); + commandLineParser.addPositionalArgument(ImageViewer::tr("[file]"), ImageViewer::tr("Image file to open.")); + commandLineParser.process(QCoreApplication::arguments()); ImageViewer imageViewer; + if (!commandLineParser.positionalArguments().isEmpty() + && !imageViewer.loadFile(commandLineParser.positionalArguments().front())) { + return -1; + } imageViewer.show(); return app.exec(); } -- cgit v1.2.3 From da5dea807f497bc6004f40e966e5d882a2ba72b0 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 11 Apr 2014 13:45:47 +0200 Subject: Support hotplugging of input devices with XInput2 Since we only scan for XInput2 devices on application start, we will currently miss any devices plugged in while the application is running. This patch makes QXcbConnection listen for XInput2 hierachyChanged events and use them to trigger a rescan of XInput2 devices. This fixes a regression in Qt 5.3, where the scroll wheel on hot- plugged mice does not work until the Qt application is restarted. Change-Id: I2cdc7ca24d3ab00716cedc4b22355b6e4935b184 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.h | 2 + src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 248 +++++++++++++---------- 2 files changed, 145 insertions(+), 105 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index f96541318c..6c9ccbcc2f 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -496,8 +496,10 @@ private: #ifdef XCB_USE_XINPUT2 void initializeXInput2(); void finalizeXInput2(); + void xi2SetupDevices(); XInput2DeviceData *deviceForId(int id); void xi2HandleEvent(xcb_ge_event_t *event); + void xi2HandleHierachyEvent(void *event); int m_xiOpCode, m_xiEventBase, m_xiErrorBase; #ifndef QT_NO_TABLETEVENT struct TabletData { diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index eb7b220c43..0b7ea155c1 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -73,10 +73,6 @@ void QXcbConnection::initializeXInput2() { debug_xinput = qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT"); debug_xinput_devices = qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT_DEVICES"); -#ifndef QT_NO_TABLETEVENT - m_tabletData.clear(); -#endif - m_scrollingDevices.clear(); Display *xDisplay = static_cast(m_xlib_display); if (XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) { int xiMajor = 2; @@ -97,122 +93,137 @@ void QXcbConnection::initializeXInput2() #else qDebug("XInput version %d.%d is available and Qt supports 2.0", xiMajor, m_xi2Minor); #endif - int deviceCount = 0; - XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount); - for (int i = 0; i < deviceCount; ++i) { - // Only non-master pointing devices are relevant here. - if (devices[i].use != XISlavePointer) - continue; - if (Q_UNLIKELY(debug_xinput_devices)) - qDebug() << "input device "<< devices[i].name; + } + + xi2SetupDevices(); + } +} + +void QXcbConnection::xi2SetupDevices() +{ #ifndef QT_NO_TABLETEVENT - TabletData tabletData; + m_tabletData.clear(); #endif - ScrollingDevice scrollingDevice; - for (int c = 0; c < devices[i].num_classes; ++c) { - switch (devices[i].classes[c]->type) { - case XIValuatorClass: { - XIValuatorClassInfo *vci = reinterpret_cast(devices[i].classes[c]); - const int valuatorAtom = qatom(vci->label); - if (Q_UNLIKELY(debug_xinput_devices)) - qDebug() << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms); + m_scrollingDevices.clear(); + + if (!m_xi2Enabled) + return; + + Display *xDisplay = static_cast(m_xlib_display); + int deviceCount = 0; + XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount); + for (int i = 0; i < deviceCount; ++i) { + // Only non-master pointing devices are relevant here. + if (devices[i].use != XISlavePointer) + continue; + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << "input device "<< devices[i].name; #ifndef QT_NO_TABLETEVENT - if (valuatorAtom < QXcbAtom::NAtoms) { - TabletData::ValuatorClassInfo info; - info.minVal = vci->min; - info.maxVal = vci->max; - info.number = vci->number; - tabletData.valuatorInfo[valuatorAtom] = info; - } + TabletData tabletData; +#endif + ScrollingDevice scrollingDevice; + for (int c = 0; c < devices[i].num_classes; ++c) { + switch (devices[i].classes[c]->type) { + case XIValuatorClass: { + XIValuatorClassInfo *vci = reinterpret_cast(devices[i].classes[c]); + const int valuatorAtom = qatom(vci->label); + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms); +#ifndef QT_NO_TABLETEVENT + if (valuatorAtom < QXcbAtom::NAtoms) { + TabletData::ValuatorClassInfo info; + info.minVal = vci->min; + info.maxVal = vci->max; + info.number = vci->number; + tabletData.valuatorInfo[valuatorAtom] = info; + } #endif // QT_NO_TABLETEVENT - if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel) - scrollingDevice.lastScrollPosition.setX(vci->value); - else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel) - scrollingDevice.lastScrollPosition.setY(vci->value); - break; - } + if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel) + scrollingDevice.lastScrollPosition.setX(vci->value); + else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel) + scrollingDevice.lastScrollPosition.setY(vci->value); + break; + } #ifdef XCB_USE_XINPUT21 - case XIScrollClass: { - XIScrollClassInfo *sci = reinterpret_cast(devices[i].classes[c]); - if (sci->scroll_type == XIScrollTypeVertical) { - scrollingDevice.orientations |= Qt::Vertical; - scrollingDevice.verticalIndex = sci->number; - scrollingDevice.verticalIncrement = sci->increment; - } - else if (sci->scroll_type == XIScrollTypeHorizontal) { - scrollingDevice.orientations |= Qt::Horizontal; - scrollingDevice.horizontalIndex = sci->number; - scrollingDevice.horizontalIncrement = sci->increment; - } - break; - } - case XIButtonClass: { - XIButtonClassInfo *bci = reinterpret_cast(devices[i].classes[c]); - if (bci->num_buttons >= 5) { - Atom label4 = bci->labels[3]; - Atom label5 = bci->labels[4]; - if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp) && (!label5 || qatom(label5) == QXcbAtom::ButtonWheelDown)) - scrollingDevice.legacyOrientations |= Qt::Vertical; - } - if (bci->num_buttons >= 7) { - Atom label6 = bci->labels[5]; - Atom label7 = bci->labels[6]; - if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight)) - scrollingDevice.legacyOrientations |= Qt::Horizontal; - } - break; - } -#endif - default: - break; - } + case XIScrollClass: { + XIScrollClassInfo *sci = reinterpret_cast(devices[i].classes[c]); + if (sci->scroll_type == XIScrollTypeVertical) { + scrollingDevice.orientations |= Qt::Vertical; + scrollingDevice.verticalIndex = sci->number; + scrollingDevice.verticalIncrement = sci->increment; } - bool isTablet = false; -#ifndef QT_NO_TABLETEVENT - // If we have found the valuators which we expect a tablet to have, assume it's a tablet. - if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) && - tabletData.valuatorInfo.contains(QXcbAtom::AbsY) && - tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure)) { - tabletData.deviceId = devices[i].deviceid; - tabletData.pointerType = QTabletEvent::Pen; - if (QByteArray(devices[i].name).toLower().contains("eraser")) - tabletData.pointerType = QTabletEvent::Eraser; - m_tabletData.append(tabletData); - isTablet = true; - if (Q_UNLIKELY(debug_xinput_devices)) - qDebug() << " it's a tablet with pointer type" << tabletData.pointerType; + else if (sci->scroll_type == XIScrollTypeHorizontal) { + scrollingDevice.orientations |= Qt::Horizontal; + scrollingDevice.horizontalIndex = sci->number; + scrollingDevice.horizontalIncrement = sci->increment; + } + break; + } + case XIButtonClass: { + XIButtonClassInfo *bci = reinterpret_cast(devices[i].classes[c]); + if (bci->num_buttons >= 5) { + Atom label4 = bci->labels[3]; + Atom label5 = bci->labels[4]; + if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp) && (!label5 || qatom(label5) == QXcbAtom::ButtonWheelDown)) + scrollingDevice.legacyOrientations |= Qt::Vertical; + } + if (bci->num_buttons >= 7) { + Atom label6 = bci->labels[5]; + Atom label7 = bci->labels[6]; + if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight)) + scrollingDevice.legacyOrientations |= Qt::Horizontal; } + break; + } +#endif + default: + break; + } + } + bool isTablet = false; +#ifndef QT_NO_TABLETEVENT + // If we have found the valuators which we expect a tablet to have, assume it's a tablet. + if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) && + tabletData.valuatorInfo.contains(QXcbAtom::AbsY) && + tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure)) { + tabletData.deviceId = devices[i].deviceid; + tabletData.pointerType = QTabletEvent::Pen; + if (QByteArray(devices[i].name).toLower().contains("eraser")) + tabletData.pointerType = QTabletEvent::Eraser; + m_tabletData.append(tabletData); + isTablet = true; + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << " it's a tablet with pointer type" << tabletData.pointerType; + } #endif // QT_NO_TABLETEVENT #ifdef XCB_USE_XINPUT21 - if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) { - scrollingDevice.deviceId = devices[i].deviceid; - // Only use legacy wheel button events when we don't have real scroll valuators. - scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations; - m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice); - if (Q_UNLIKELY(debug_xinput_devices)) - qDebug() << " it's a scrolling device"; - } + if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) { + scrollingDevice.deviceId = devices[i].deviceid; + // Only use legacy wheel button events when we don't have real scroll valuators. + scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations; + m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice); + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << " it's a scrolling device"; + } #endif - if (!isTablet) { - XInput2DeviceData *dev = deviceForId(devices[i].deviceid); - if (Q_UNLIKELY(debug_xinput_devices)) { - if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchScreen) - qDebug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d", - dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), - dev->qtTouchDevice->maximumTouchPoints()); - else if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchPad) - qDebug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", - dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), - dev->qtTouchDevice->maximumTouchPoints(), - dev->size.width(), dev->size.height()); - } - } + if (!isTablet) { + XInput2DeviceData *dev = deviceForId(devices[i].deviceid); + if (Q_UNLIKELY(debug_xinput_devices)) { + if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchScreen) + qDebug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d", + dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), + dev->qtTouchDevice->maximumTouchPoints()); + else if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchPad) + qDebug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", + dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), + dev->qtTouchDevice->maximumTouchPoints(), + dev->size.width(), dev->size.height()); } - XIFreeDeviceInfo(devices); } } + XIFreeDeviceInfo(devices); } void QXcbConnection::finalizeXInput2() @@ -303,6 +314,16 @@ void QXcbConnection::xi2Select(xcb_window_t window) #else Q_UNUSED(xiBitMask); #endif + + { + // Listen for hotplug events + XIEventMask xiEventMask; + bitMask = XI_HierarchyChangedMask; + xiEventMask.deviceid = XIAllDevices; + xiEventMask.mask_len = sizeof(bitMask); + xiEventMask.mask = xiBitMask; + XISelectEvents(xDisplay, window, &xiEventMask, 1); + } } XInput2DeviceData *QXcbConnection::deviceForId(int id) @@ -402,6 +423,10 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) if (xi2PrepareXIGenericDeviceEvent(event, m_xiOpCode)) { xXIGenericDeviceEvent *xiEvent = reinterpret_cast(event); + if (xiEvent->evtype == XI_HierarchyChanged) { + xi2HandleHierachyEvent(xiEvent); + return; + } #ifndef QT_NO_TABLETEVENT for (int i = 0; i < m_tabletData.count(); ++i) { if (m_tabletData.at(i).deviceId == xiEvent->deviceid) { @@ -561,6 +586,19 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) } } +void QXcbConnection::xi2HandleHierachyEvent(void *event) +{ + xXIHierarchyEvent *xiEvent = reinterpret_cast(event); + // We only care about hotplugged devices + if (!(xiEvent->flags & (XISlaveRemoved | XISlaveAdded))) + return; + xi2SetupDevices(); + // Reselect events for all event-listening windows. + Q_FOREACH (xcb_window_t window, m_mapper.keys()) { + xi2Select(window); + } +} + void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *) { #ifdef XCB_USE_XINPUT21 -- cgit v1.2.3 From 29f92d112af6deb3597a6b80e3259e826911dcca Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Jun 2014 14:51:44 -0700 Subject: Move the QProcessPrivate channel buffers into QProcessPrivate::Channel Simplifies the code. Change-Id: I70b26af69332f364d856042f114c37a70504d66f Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 56 ++++++++++++++++++++-------------------- src/corelib/io/qprocess_p.h | 5 +--- src/corelib/io/qprocess_unix.cpp | 8 +++--- src/corelib/io/qprocess_win.cpp | 8 +++--- 4 files changed, 37 insertions(+), 40 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 9f9cba81ab..24ee3b6c0b 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -916,7 +916,7 @@ bool QProcessPrivate::_q_canReadStandardOutput() return false; } - char *ptr = outputReadBuffer.reserve(available); + char *ptr = stdoutChannel.buffer.reserve(available); qint64 readBytes = readFromStdout(ptr, available); if (readBytes == -1) { processError = QProcess::ReadError; @@ -933,11 +933,11 @@ bool QProcessPrivate::_q_canReadStandardOutput() #endif if (stdoutChannel.closed) { - outputReadBuffer.chop(readBytes); + stdoutChannel.buffer.chop(readBytes); return false; } - outputReadBuffer.chop(available - readBytes); + stdoutChannel.buffer.chop(available - readBytes); bool didRead = false; if (readBytes == 0) { @@ -969,7 +969,7 @@ bool QProcessPrivate::_q_canReadStandardError() return false; } - char *ptr = errorReadBuffer.reserve(available); + char *ptr = stderrChannel.buffer.reserve(available); qint64 readBytes = readFromStderr(ptr, available); if (readBytes == -1) { processError = QProcess::ReadError; @@ -978,11 +978,11 @@ bool QProcessPrivate::_q_canReadStandardError() return false; } if (stderrChannel.closed) { - errorReadBuffer.chop(readBytes); + stderrChannel.buffer.chop(readBytes); return false; } - errorReadBuffer.chop(available - readBytes); + stderrChannel.buffer.chop(available - readBytes); bool didRead = false; if (readBytes == 0) { @@ -1009,15 +1009,15 @@ bool QProcessPrivate::_q_canWrite() if (stdinChannel.notifier) stdinChannel.notifier->setEnabled(false); - if (writeBuffer.isEmpty()) { + if (stdinChannel.buffer.isEmpty()) { #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer)."); #endif return false; } - qint64 written = writeToStdin(writeBuffer.readPointer(), - writeBuffer.nextDataBlockSize()); + qint64 written = writeToStdin(stdinChannel.buffer.readPointer(), + stdinChannel.buffer.nextDataBlockSize()); if (written < 0) { destroyChannel(&stdinChannel); processError = QProcess::WriteError; @@ -1031,16 +1031,16 @@ bool QProcessPrivate::_q_canWrite() #endif if (written != 0) { - writeBuffer.free(written); + stdinChannel.buffer.free(written); if (!emittedBytesWritten) { emittedBytesWritten = true; emit q->bytesWritten(written); emittedBytesWritten = false; } } - if (stdinChannel.notifier && !writeBuffer.isEmpty()) + if (stdinChannel.notifier && !stdinChannel.buffer.isEmpty()) stdinChannel.notifier->setEnabled(true); - if (writeBuffer.isEmpty() && stdinChannel.closed) + if (stdinChannel.buffer.isEmpty() && stdinChannel.closed) closeWriteChannel(); return true; } @@ -1308,10 +1308,10 @@ void QProcess::setReadChannel(ProcessChannel channel) QByteArray buf = d->buffer.readAll(); if (d->processChannel == QProcess::StandardOutput) { for (int i = buf.size() - 1; i >= 0; --i) - d->outputReadBuffer.ungetChar(buf.at(i)); + d->stdoutChannel.buffer.ungetChar(buf.at(i)); } else { for (int i = buf.size() - 1; i >= 0; --i) - d->errorReadBuffer.ungetChar(buf.at(i)); + d->stderrChannel.buffer.ungetChar(buf.at(i)); } } d->processChannel = channel; @@ -1359,7 +1359,7 @@ void QProcess::closeWriteChannel() { Q_D(QProcess); d->stdinChannel.closed = true; // closing - if (d->writeBuffer.isEmpty()) + if (d->stdinChannel.buffer.isEmpty()) d->closeWriteChannel(); } @@ -1589,8 +1589,8 @@ bool QProcess::canReadLine() const { Q_D(const QProcess); const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError) - ? &d->errorReadBuffer - : &d->outputReadBuffer; + ? &d->stderrChannel.buffer + : &d->stdoutChannel.buffer; return readBuffer->canReadLine() || QIODevice::canReadLine(); } @@ -1618,8 +1618,8 @@ bool QProcess::atEnd() const { Q_D(const QProcess); const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError) - ? &d->errorReadBuffer - : &d->outputReadBuffer; + ? &d->stderrChannel.buffer + : &d->stdoutChannel.buffer; return QIODevice::atEnd() && (!isOpen() || readBuffer->isEmpty()); } @@ -1636,8 +1636,8 @@ qint64 QProcess::bytesAvailable() const { Q_D(const QProcess); const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError) - ? &d->errorReadBuffer - : &d->outputReadBuffer; + ? &d->stderrChannel.buffer + : &d->stdoutChannel.buffer; #if defined QPROCESS_DEBUG qDebug("QProcess::bytesAvailable() == %i (%s)", readBuffer->size(), (d->processChannel == QProcess::StandardError) ? "stderr" : "stdout"); @@ -1650,7 +1650,7 @@ qint64 QProcess::bytesAvailable() const qint64 QProcess::bytesToWrite() const { Q_D(const QProcess); - qint64 size = d->writeBuffer.size(); + qint64 size = d->stdinChannel.buffer.size(); #ifdef Q_OS_WIN size += d->pipeWriterBytesToWrite(); #endif @@ -1897,8 +1897,8 @@ qint64 QProcess::readData(char *data, qint64 maxlen) if (!maxlen) return 0; QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError) - ? &d->errorReadBuffer - : &d->outputReadBuffer; + ? &d->stderrChannel.buffer + : &d->stdoutChannel.buffer; if (maxlen == 1 && !readBuffer->isEmpty()) { int c = readBuffer->getChar(); @@ -1961,7 +1961,7 @@ qint64 QProcess::writeData(const char *data, qint64 len) } if (len == 1) { - d->writeBuffer.putChar(*data); + d->stdinChannel.buffer.putChar(*data); if (d->stdinChannel.notifier) d->stdinChannel.notifier->setEnabled(true); #if defined QPROCESS_DEBUG @@ -1971,7 +1971,7 @@ qint64 QProcess::writeData(const char *data, qint64 len) return 1; } - char *dest = d->writeBuffer.reserve(len); + char *dest = d->stdinChannel.buffer.reserve(len); memcpy(dest, data, len); if (d->stdinChannel.notifier) d->stdinChannel.notifier->setEnabled(true); @@ -2112,8 +2112,8 @@ void QProcessPrivate::start(QIODevice::OpenMode mode) qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')'; #endif - outputReadBuffer.clear(); - errorReadBuffer.clear(); + stdoutChannel.buffer.clear(); + stderrChannel.buffer.clear(); if (stdinChannel.type != QProcessPrivate::Channel::Normal) mode &= ~QIODevice::WriteOnly; // not open for writing diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 5d65b2a068..552ef5698b 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -282,6 +282,7 @@ public: QString file; QProcessPrivate *process; QSocketNotifier *notifier; + QRingBuffer buffer; Q_PIPE pipe[2]; unsigned type : 2; @@ -326,10 +327,6 @@ public: #endif QProcessEnvironment environment; - QRingBuffer outputReadBuffer; - QRingBuffer errorReadBuffer; - QRingBuffer writeBuffer; - Q_PIPE childStartedPipe[2]; Q_PIPE deathPipe[2]; void destroyPipe(Q_PIPE pipe[2]); diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 8674371baa..97e8add9fa 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -1126,7 +1126,7 @@ bool QProcessPrivate::waitForReadyRead(int msecs) if (stderrChannel.pipe[0] != -1) add_fd(nfds, stderrChannel.pipe[0], &fdread); - if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) + if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1) add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); @@ -1188,7 +1188,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) QList notifiers = defaultNotifiers(); #endif - while (!writeBuffer.isEmpty()) { + while (!stdinChannel.buffer.isEmpty()) { fd_set fdread; fd_set fdwrite; @@ -1207,7 +1207,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) add_fd(nfds, stderrChannel.pipe[0], &fdread); - if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) + if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1) add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); @@ -1282,7 +1282,7 @@ bool QProcessPrivate::waitForFinished(int msecs) if (processState == QProcess::Running) add_fd(nfds, deathPipe[0], &fdread); - if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) + if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1) add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index d7050034bd..43233b27bd 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -690,7 +690,7 @@ bool QProcessPrivate::waitForReadyRead(int msecs) QIncrementalSleepTimer timer(msecs); forever { - if (!writeBuffer.isEmpty() && !_q_canWrite()) + if (!stdinChannel.buffer.isEmpty() && !_q_canWrite()) return false; if (pipeWriter && pipeWriter->waitForWrite(0)) timer.resetIncrements(); @@ -731,7 +731,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) // If we don't have pending data, and our write buffer is // empty, we fail. - if (!pendingDataInPipe && writeBuffer.isEmpty()) + if (!pendingDataInPipe && stdinChannel.buffer.isEmpty()) return false; // If we don't have pending data and we do have data in our @@ -795,7 +795,7 @@ bool QProcessPrivate::waitForFinished(int msecs) QIncrementalSleepTimer timer(msecs); forever { - if (!writeBuffer.isEmpty() && !_q_canWrite()) + if (!stdinChannel.buffer.isEmpty() && !_q_canWrite()) return false; if (pipeWriter && pipeWriter->waitForWrite(0)) timer.resetIncrements(); @@ -875,7 +875,7 @@ void QProcessPrivate::_q_notified() { notifier->stop(); - if (!writeBuffer.isEmpty() && (!pipeWriter || pipeWriter->waitForWrite(0))) + if (!stdinChannel.buffer.isEmpty() && (!pipeWriter || pipeWriter->waitForWrite(0))) _q_canWrite(); if (processState != QProcess::NotRunning) -- cgit v1.2.3 From 15a0a6e8c54ad52fe9f02e637f6a977fa794257b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Jun 2014 15:05:56 -0700 Subject: Move the QProcessPrivate Windows objects into QProcessPrivate::Channel Similar to the previous commit, this simplifies the code. Change-Id: Ia02b9b5174b4bc6fd04ec2534231b7db5fc914fa Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 3 -- src/corelib/io/qprocess_p.h | 12 +++-- src/corelib/io/qprocess_win.cpp | 108 +++++++++++++++++----------------------- 3 files changed, 56 insertions(+), 67 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 24ee3b6c0b..cfe5a68fc8 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -819,9 +819,6 @@ QProcessPrivate::QProcessPrivate() emittedBytesWritten = false; #ifdef Q_OS_WIN notifier = 0; - stdoutReader = 0; - stderrReader = 0; - pipeWriter = 0; processFinishedNotifier = 0; #endif // Q_OS_WIN #ifdef Q_OS_UNIX diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 552ef5698b..e76a769073 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -253,6 +253,9 @@ public: { pipe[0] = INVALID_Q_PIPE; pipe[1] = INVALID_Q_PIPE; +#ifdef Q_OS_WIN + reader = 0; +#endif } void clear(); @@ -282,6 +285,12 @@ public: QString file; QProcessPrivate *process; QSocketNotifier *notifier; +#ifdef Q_OS_WIN + union { + QWindowsPipeReader *reader; + QWindowsPipeWriter *writer; + }; +#endif QRingBuffer buffer; Q_PIPE pipe[2]; @@ -338,9 +347,6 @@ public: #ifdef Q_OS_WIN // the wonderful windows notifier QTimer *notifier; - QWindowsPipeReader *stdoutReader; - QWindowsPipeReader *stderrReader; - QWindowsPipeWriter *pipeWriter; QWinEventNotifier *processFinishedNotifier; #endif diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 43233b27bd..8aa31cb42e 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -180,34 +180,31 @@ bool QProcessPrivate::createChannel(Channel &channel) &channel.pipe[0], 0, TRUE, DUPLICATE_SAME_ACCESS); } } else { - QWindowsPipeReader *pipeReader = 0; if (&channel == &stdoutChannel) { if (processChannelMode != QProcess::ForwardedChannels && processChannelMode != QProcess::ForwardedOutputChannel) { - if (!stdoutReader) { - stdoutReader = new QWindowsPipeReader(q); - q->connect(stdoutReader, SIGNAL(readyRead()), SLOT(_q_canReadStandardOutput())); + if (!stdoutChannel.reader) { + stdoutChannel.reader = new QWindowsPipeReader(q); + q->connect(stdoutChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardOutput())); } - pipeReader = stdoutReader; } else { duplicateStdWriteChannel(channel.pipe, STD_OUTPUT_HANDLE); } } else /* if (&channel == &stderrChannel) */ { if (processChannelMode != QProcess::ForwardedChannels && processChannelMode != QProcess::ForwardedErrorChannel) { - if (!stderrReader) { - stderrReader = new QWindowsPipeReader(q); - q->connect(stderrReader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError())); + if (!stderrChannel.reader) { + stderrChannel.reader = new QWindowsPipeReader(q); + q->connect(stderrChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError())); } - pipeReader = stderrReader; } else { duplicateStdWriteChannel(channel.pipe, STD_ERROR_HANDLE); } } - if (pipeReader) { + if (channel.reader) { qt_create_pipe(channel.pipe, false); - pipeReader->setHandle(channel.pipe[0]); - pipeReader->startAsyncRead(); + channel.reader->setHandle(channel.pipe[0]); + channel.reader->startAsyncRead(); } } @@ -335,22 +332,12 @@ void QProcessPrivate::destroyPipe(Q_PIPE pipe[2]) void QProcessPrivate::destroyChannel(Channel *channel) { if (channel == &stdinChannel) { - if (pipeWriter) { - delete pipeWriter; - pipeWriter = 0; - } - } else if (channel == &stdoutChannel) { - if (stdoutReader) { - stdoutReader->stop(); - stdoutReader->deleteLater(); - stdoutReader = 0; - } - } else if (channel == &stderrChannel) { - if (stderrReader) { - stderrReader->stop(); - stderrReader->deleteLater(); - stderrReader = 0; - } + delete stdinChannel.writer; + stdinChannel.writer = 0; + } else if (channel->reader) { + channel->reader->stop(); + channel->reader->deleteLater(); + channel->reader = 0; } destroyPipe(channel->pipe); } @@ -582,10 +569,10 @@ qint64 QProcessPrivate::bytesAvailableFromStdout() const if (stdoutChannel.pipe[0] == INVALID_Q_PIPE) return 0; - if (!stdoutReader) + if (!stdoutChannel.reader) return 0; - DWORD bytesAvail = stdoutReader->bytesAvailable(); + DWORD bytesAvail = stdoutChannel.reader->bytesAvailable(); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::bytesAvailableFromStdout() == %d", bytesAvail); #endif @@ -597,10 +584,10 @@ qint64 QProcessPrivate::bytesAvailableFromStderr() const if (stderrChannel.pipe[0] == INVALID_Q_PIPE) return 0; - if (!stderrReader) + if (!stderrChannel.reader) return 0; - DWORD bytesAvail = stderrReader->bytesAvailable(); + DWORD bytesAvail = stderrChannel.reader->bytesAvailable(); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::bytesAvailableFromStderr() == %d", bytesAvail); #endif @@ -609,12 +596,12 @@ qint64 QProcessPrivate::bytesAvailableFromStderr() const qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen) { - return stdoutReader ? stdoutReader->read(data, maxlen) : 0; + return stdoutChannel.reader ? stdoutChannel.reader->read(data, maxlen) : 0; } qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen) { - return stderrReader ? stderrReader->read(data, maxlen) : 0; + return stderrChannel.reader ? stderrChannel.reader->read(data, maxlen) : 0; } @@ -659,20 +646,20 @@ bool QProcessPrivate::waitForStarted(int) bool QProcessPrivate::drainOutputPipes() { - if (!stdoutReader && !stderrReader) + if (!stdoutChannel.reader && !stderrChannel.reader) return false; bool someReadyReadEmitted = false; forever { bool readyReadEmitted = false; bool readOperationActive = false; - if (stdoutReader) { - readyReadEmitted |= stdoutReader->waitForReadyRead(0); - readOperationActive = stdoutReader && stdoutReader->isReadOperationActive(); + if (stdoutChannel.reader) { + readyReadEmitted |= stdoutChannel.reader->waitForReadyRead(0); + readOperationActive = stdoutChannel.reader && stdoutChannel.reader->isReadOperationActive(); } - if (stderrReader) { - readyReadEmitted |= stderrReader->waitForReadyRead(0); - readOperationActive |= stderrReader && stderrReader->isReadOperationActive(); + if (stderrChannel.reader) { + readyReadEmitted |= stderrChannel.reader->waitForReadyRead(0); + readOperationActive |= stderrChannel.reader && stderrChannel.reader->isReadOperationActive(); } someReadyReadEmitted |= readyReadEmitted; if (!readOperationActive || !readyReadEmitted) @@ -692,11 +679,11 @@ bool QProcessPrivate::waitForReadyRead(int msecs) forever { if (!stdinChannel.buffer.isEmpty() && !_q_canWrite()) return false; - if (pipeWriter && pipeWriter->waitForWrite(0)) + if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0)) timer.resetIncrements(); - if ((stdoutReader && stdoutReader->waitForReadyRead(0)) - || (stderrReader && stderrReader->waitForReadyRead(0))) + if ((stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0)) + || (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0))) return true; if (!pid) @@ -726,8 +713,8 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) forever { // Check if we have any data pending: the pipe writer has // bytes waiting to written, or it has written data since the - // last time we called pipeWriter->waitForWrite(). - bool pendingDataInPipe = pipeWriter && (pipeWriter->bytesToWrite() || pipeWriter->hadWritten()); + // last time we called stdinChannel.writer->waitForWrite(). + bool pendingDataInPipe = stdinChannel.writer && (stdinChannel.writer->bytesToWrite() || stdinChannel.writer->hadWritten()); // If we don't have pending data, and our write buffer is // empty, we fail. @@ -746,10 +733,10 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) // written. This will succeed if either the pipe writer has // already written the data, or if it manages to write data // within the given timeout. If the write buffer was non-empty - // and the pipeWriter is now dead, that means _q_canWrite() + // and the stdinChannel.writer is now dead, that means _q_canWrite() // destroyed the writer after it successfully wrote the last // batch. - if (!pipeWriter || pipeWriter->waitForWrite(0)) + if (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0)) return true; // If we wouldn't write anything, check if we can read stdout. @@ -797,11 +784,11 @@ bool QProcessPrivate::waitForFinished(int msecs) forever { if (!stdinChannel.buffer.isEmpty() && !_q_canWrite()) return false; - if (pipeWriter && pipeWriter->waitForWrite(0)) + if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0)) timer.resetIncrements(); - if (stdoutReader && stdoutReader->waitForReadyRead(0)) + if (stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0)) timer.resetIncrements(); - if (stderrReader && stderrReader->waitForReadyRead(0)) + if (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0)) timer.resetIncrements(); if (!pid) { @@ -837,33 +824,32 @@ void QProcessPrivate::findExitCode() void QProcessPrivate::flushPipeWriter() { - if (pipeWriter && pipeWriter->bytesToWrite() > 0) { - pipeWriter->waitForWrite(ULONG_MAX); - } + if (stdinChannel.writer && stdinChannel.writer->bytesToWrite() > 0) + stdinChannel.writer->waitForWrite(ULONG_MAX); } qint64 QProcessPrivate::pipeWriterBytesToWrite() const { - return pipeWriter ? pipeWriter->bytesToWrite() : qint64(0); + return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0); } qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) { Q_Q(QProcess); - if (!pipeWriter) { - pipeWriter = new QWindowsPipeWriter(stdinChannel.pipe[1], q); - pipeWriter->start(); + if (!stdinChannel.writer) { + stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q); + stdinChannel.writer->start(); } - return pipeWriter->write(data, maxlen); + return stdinChannel.writer->write(data, maxlen); } bool QProcessPrivate::waitForWrite(int msecs) { Q_Q(QProcess); - if (!pipeWriter || pipeWriter->waitForWrite(msecs)) + if (!stdinChannel.writer || stdinChannel.writer->waitForWrite(msecs)) return true; processError = QProcess::Timedout; @@ -875,7 +861,7 @@ void QProcessPrivate::_q_notified() { notifier->stop(); - if (!stdinChannel.buffer.isEmpty() && (!pipeWriter || pipeWriter->waitForWrite(0))) + if (!stdinChannel.buffer.isEmpty() && (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0))) _q_canWrite(); if (processState != QProcess::NotRunning) -- cgit v1.2.3 From 0f6b3a01e4c6fc7e4c2603b3dfcf3c0f81090ba9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Jun 2014 14:32:02 -0700 Subject: Rename QProcessPrivate::destroyChannel to closeChannel The QProcessPrivate::Channel object contains some structures that may survive the closing of the pipe, so calling this function "destroy" is incorrect. Let it be just the closing. For symmetry, the createChannel() function is renamed to openChannel(). Change-Id: I2899214c6e4c25835390b10ccf3931315a91589e Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 14 +++++++------- src/corelib/io/qprocess_p.h | 4 ++-- src/corelib/io/qprocess_unix.cpp | 10 +++++----- src/corelib/io/qprocess_win.cpp | 10 +++++----- src/corelib/io/qprocess_wince.cpp | 2 +- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index cfe5a68fc8..a3fca5bfe0 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -886,9 +886,9 @@ void QProcessPrivate::cleanup() notifier = 0; } #endif - destroyChannel(&stdoutChannel); - destroyChannel(&stderrChannel); - destroyChannel(&stdinChannel); + closeChannel(&stdoutChannel); + closeChannel(&stderrChannel); + closeChannel(&stdinChannel); destroyPipe(childStartedPipe); destroyPipe(deathPipe); #ifdef Q_OS_UNIX @@ -906,7 +906,7 @@ bool QProcessPrivate::_q_canReadStandardOutput() if (available == 0) { if (stdoutChannel.notifier) stdoutChannel.notifier->setEnabled(false); - destroyChannel(&stdoutChannel); + closeChannel(&stdoutChannel); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::canReadStandardOutput(), 0 bytes available"); #endif @@ -962,7 +962,7 @@ bool QProcessPrivate::_q_canReadStandardError() if (available == 0) { if (stderrChannel.notifier) stderrChannel.notifier->setEnabled(false); - destroyChannel(&stderrChannel); + closeChannel(&stderrChannel); return false; } @@ -1016,7 +1016,7 @@ bool QProcessPrivate::_q_canWrite() qint64 written = writeToStdin(stdinChannel.buffer.readPointer(), stdinChannel.buffer.nextDataBlockSize()); if (written < 0) { - destroyChannel(&stdinChannel); + closeChannel(&stdinChannel); processError = QProcess::WriteError; q->setErrorString(QProcess::tr("Error writing to process")); emit q->error(processError); @@ -1160,7 +1160,7 @@ void QProcessPrivate::closeWriteChannel() // instead. flushPipeWriter(); #endif - destroyChannel(&stdinChannel); + closeChannel(&stdinChannel); } /*! diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index e76a769073..c491c57abc 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -326,7 +326,8 @@ public: Channel stdinChannel; Channel stdoutChannel; Channel stderrChannel; - bool createChannel(Channel &channel); + bool openChannel(Channel &channel); + void closeChannel(Channel *channel); void closeWriteChannel(); QString program; @@ -339,7 +340,6 @@ public: Q_PIPE childStartedPipe[2]; Q_PIPE deathPipe[2]; void destroyPipe(Q_PIPE pipe[2]); - void destroyChannel(Channel *channel); QSocketNotifier *startupSocketNotifier; QSocketNotifier *deathNotifier; diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 97e8add9fa..4147191f08 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -377,7 +377,7 @@ void QProcessPrivate::destroyPipe(int *pipe) } } -void QProcessPrivate::destroyChannel(Channel *channel) +void QProcessPrivate::closeChannel(Channel *channel) { destroyPipe(channel->pipe); } @@ -387,7 +387,7 @@ void QProcessPrivate::destroyChannel(Channel *channel) This function must be called in order: stdin, stdout, stderr */ -bool QProcessPrivate::createChannel(Channel &channel) +bool QProcessPrivate::openChannel(Channel &channel) { Q_Q(QProcess); @@ -573,9 +573,9 @@ void QProcessPrivate::startProcess() processManager()->start(); // Initialize pipes - if (!createChannel(stdinChannel) || - !createChannel(stdoutChannel) || - !createChannel(stderrChannel) || + if (!openChannel(stdinChannel) || + !openChannel(stdoutChannel) || + !openChannel(stderrChannel) || qt_create_pipe(childStartedPipe) != 0 || qt_create_pipe(deathPipe) != 0) { processError = QProcess::FailedToStart; diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 8aa31cb42e..61cf21751e 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -158,7 +158,7 @@ static void duplicateStdWriteChannel(Q_PIPE *pipe, DWORD nStdHandle) This function must be called in order: stdin, stdout, stderr */ -bool QProcessPrivate::createChannel(Channel &channel) +bool QProcessPrivate::openChannel(Channel &channel) { Q_Q(QProcess); @@ -329,7 +329,7 @@ void QProcessPrivate::destroyPipe(Q_PIPE pipe[2]) } } -void QProcessPrivate::destroyChannel(Channel *channel) +void QProcessPrivate::closeChannel(Channel *channel) { if (channel == &stdinChannel) { delete stdinChannel.writer; @@ -473,9 +473,9 @@ void QProcessPrivate::startProcess() q->setProcessState(QProcess::Starting); - if (!createChannel(stdinChannel) || - !createChannel(stdoutChannel) || - !createChannel(stderrChannel)) + if (!openChannel(stdinChannel) || + !openChannel(stdoutChannel) || + !openChannel(stderrChannel)) return; QString args = qt_create_commandline(program, arguments); diff --git a/src/corelib/io/qprocess_wince.cpp b/src/corelib/io/qprocess_wince.cpp index ad9a328133..b1c41ff069 100644 --- a/src/corelib/io/qprocess_wince.cpp +++ b/src/corelib/io/qprocess_wince.cpp @@ -62,7 +62,7 @@ void QProcessPrivate::destroyPipe(Q_PIPE pipe[2]) Q_UNUSED(pipe); } -void QProcessPrivate::destroyChannel(Channel *channel) +void QProcessPrivate::closeChannel(Channel *channel) { Q_UNUSED(channel); } -- cgit v1.2.3 From 25ef58fe185f1534d9d89aee72e84c3789068907 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Jun 2014 15:10:27 -0700 Subject: QProcessPrivate: merge the functions dealing with stdout and stderr Simplifies the code. Change-Id: I4b3a6e725eb245d3531d1d11d959fb3b85862778 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 86 ++++++++++++++------------------------- src/corelib/io/qprocess_p.h | 7 ++-- src/corelib/io/qprocess_unix.cpp | 35 ++++------------ src/corelib/io/qprocess_win.cpp | 43 +++++--------------- src/corelib/io/qprocess_wince.cpp | 14 +------ 5 files changed, 54 insertions(+), 131 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index a3fca5bfe0..615e584f81 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -898,49 +898,51 @@ void QProcessPrivate::cleanup() /*! \internal + Returns true if we emitted readyRead(). */ -bool QProcessPrivate::_q_canReadStandardOutput() +bool QProcessPrivate::tryReadFromChannel(Channel *channel) { Q_Q(QProcess); - qint64 available = bytesAvailableFromStdout(); + qint64 available = bytesAvailableInChannel(channel); if (available == 0) { - if (stdoutChannel.notifier) - stdoutChannel.notifier->setEnabled(false); - closeChannel(&stdoutChannel); + if (channel->notifier) + channel->notifier->setEnabled(false); + closeChannel(channel); #if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::canReadStandardOutput(), 0 bytes available"); + qDebug("QProcessPrivate::tryReadFromChannel(%d), 0 bytes available", channel - &stdinChannel); #endif return false; } - char *ptr = stdoutChannel.buffer.reserve(available); - qint64 readBytes = readFromStdout(ptr, available); + char *ptr = channel->buffer.reserve(available); + qint64 readBytes = readFromChannel(channel, ptr, available); if (readBytes == -1) { processError = QProcess::ReadError; q->setErrorString(QProcess::tr("Error reading from process")); emit q->error(processError); #if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::canReadStandardOutput(), failed to read from the process"); + qDebug("QProcessPrivate::tryReadFromChannel(%d), failed to read from the process", channel - &stdinChannel); #endif return false; } #if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::canReadStandardOutput(), read %d bytes from the process' output", + qDebug("QProcessPrivate::tryReadFromChannel(%d), read %d bytes from the process' output", channel - &stdinChannel int(readBytes)); #endif - if (stdoutChannel.closed) { - stdoutChannel.buffer.chop(readBytes); + if (channel->closed) { + channel->buffer.chop(readBytes); return false; } - stdoutChannel.buffer.chop(available - readBytes); + channel->buffer.chop(available - readBytes); bool didRead = false; + bool isStdout = channel == &stdoutChannel; if (readBytes == 0) { - if (stdoutChannel.notifier) - stdoutChannel.notifier->setEnabled(false); - } else if (processChannel == QProcess::StandardOutput) { + if (channel->notifier) + channel->notifier->setEnabled(false); + } else if ((processChannel == QProcess::StandardOutput) == isStdout) { didRead = true; if (!emittedReadyRead) { emittedReadyRead = true; @@ -948,53 +950,27 @@ bool QProcessPrivate::_q_canReadStandardOutput() emittedReadyRead = false; } } - emit q->readyReadStandardOutput(QProcess::QPrivateSignal()); + if (isStdout) + emit q->readyReadStandardOutput(QProcess::QPrivateSignal()); + else + emit q->readyReadStandardError(QProcess::QPrivateSignal()); return didRead; } /*! \internal */ -bool QProcessPrivate::_q_canReadStandardError() +bool QProcessPrivate::_q_canReadStandardOutput() { - Q_Q(QProcess); - qint64 available = bytesAvailableFromStderr(); - if (available == 0) { - if (stderrChannel.notifier) - stderrChannel.notifier->setEnabled(false); - closeChannel(&stderrChannel); - return false; - } - - char *ptr = stderrChannel.buffer.reserve(available); - qint64 readBytes = readFromStderr(ptr, available); - if (readBytes == -1) { - processError = QProcess::ReadError; - q->setErrorString(QProcess::tr("Error reading from process")); - emit q->error(processError); - return false; - } - if (stderrChannel.closed) { - stderrChannel.buffer.chop(readBytes); - return false; - } - - stderrChannel.buffer.chop(available - readBytes); + return tryReadFromChannel(&stdoutChannel); +} - bool didRead = false; - if (readBytes == 0) { - if (stderrChannel.notifier) - stderrChannel.notifier->setEnabled(false); - } else if (processChannel == QProcess::StandardError) { - didRead = true; - if (!emittedReadyRead) { - emittedReadyRead = true; - emit q->readyRead(); - emittedReadyRead = false; - } - } - emit q->readyReadStandardError(QProcess::QPrivateSignal()); - return didRead; +/*! + \internal +*/ +bool QProcessPrivate::_q_canReadStandardError() +{ + return tryReadFromChannel(&stderrChannel); } /*! diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index c491c57abc..6cd9047c04 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -329,6 +329,7 @@ public: bool openChannel(Channel &channel); void closeChannel(Channel *channel); void closeWriteChannel(); + bool tryReadFromChannel(Channel *channel); // obviously, only stdout and stderr QString program; QStringList arguments; @@ -386,10 +387,8 @@ public: bool waitForFinished(int msecs = 30000); bool waitForWrite(int msecs = 30000); - qint64 bytesAvailableFromStdout() const; - qint64 bytesAvailableFromStderr() const; - qint64 readFromStdout(char *data, qint64 maxlen); - qint64 readFromStderr(char *data, qint64 maxlen); + qint64 bytesAvailableInChannel(const Channel *channel) const; + qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen); qint64 writeToStdin(const char *data, qint64 maxlen); void cleanup(); diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 4147191f08..430393d6f2 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -963,45 +963,24 @@ bool QProcessPrivate::processStarted() return i <= 0; } -qint64 QProcessPrivate::bytesAvailableFromStdout() const +qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const { int nbytes = 0; qint64 available = 0; - if (::ioctl(stdoutChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0) + if (::ioctl(channel->pipe[0], FIONREAD, (char *) &nbytes) >= 0) available = (qint64) nbytes; #if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::bytesAvailableFromStdout() == %lld", available); + qDebug("QProcessPrivate::bytesAvailableInChannel(%d) == %lld", channel - &stdinChannel, available); #endif return available; } -qint64 QProcessPrivate::bytesAvailableFromStderr() const +qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen) { - int nbytes = 0; - qint64 available = 0; - if (::ioctl(stderrChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0) - available = (qint64) nbytes; -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::bytesAvailableFromStderr() == %lld", available); -#endif - return available; -} - -qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen) -{ - qint64 bytesRead = qt_safe_read(stdoutChannel.pipe[0], data, maxlen); -#if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::readFromStdout(%p \"%s\", %lld) == %lld", - data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead); -#endif - return bytesRead; -} - -qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen) -{ - qint64 bytesRead = qt_safe_read(stderrChannel.pipe[0], data, maxlen); + qint64 bytesRead = qt_safe_read(channel->pipe[0], data, maxlen); #if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::readFromStderr(%p \"%s\", %lld) == %lld", + qDebug("QProcessPrivate::readFromChannel(%d, %p \"%s\", %lld) == %lld", + channel - &stdinChannel, data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead); #endif return bytesRead; diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 61cf21751e..2dd4c475d8 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -564,47 +564,26 @@ bool QProcessPrivate::processStarted() return processState == QProcess::Running; } -qint64 QProcessPrivate::bytesAvailableFromStdout() const +qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const { - if (stdoutChannel.pipe[0] == INVALID_Q_PIPE) + if (channel->pipe[0] == INVALID_Q_PIPE) return 0; - if (!stdoutChannel.reader) + if (!channel->reader) return 0; - DWORD bytesAvail = stdoutChannel.reader->bytesAvailable(); + DWORD bytesAvail = channel->reader->bytesAvailable(); #if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::bytesAvailableFromStdout() == %d", bytesAvail); + qDebug("QProcessPrivate::bytesAvailableInChannel(%d) == %d", channel - &stdinChannel, bytesAvail); #endif return bytesAvail; } -qint64 QProcessPrivate::bytesAvailableFromStderr() const +qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen) { - if (stderrChannel.pipe[0] == INVALID_Q_PIPE) - return 0; - - if (!stderrChannel.reader) - return 0; - - DWORD bytesAvail = stderrChannel.reader->bytesAvailable(); -#if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::bytesAvailableFromStderr() == %d", bytesAvail); -#endif - return bytesAvail; + return channel->reader ? channel->reader->read(data, maxlen) : 0; } -qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen) -{ - return stdoutChannel.reader ? stdoutChannel.reader->read(data, maxlen) : 0; -} - -qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen) -{ - return stderrChannel.reader ? stderrChannel.reader->read(data, maxlen) : 0; -} - - static BOOL QT_WIN_CALLBACK qt_terminateApp(HWND hwnd, LPARAM procId) { DWORD currentProcId = 0; @@ -740,14 +719,14 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) return true; // If we wouldn't write anything, check if we can read stdout. - if (bytesAvailableFromStdout() != 0) { - _q_canReadStandardOutput(); + if (bytesAvailableInChannel(&stdoutChannel) != 0) { + tryReadFromChannel(&stdoutChannel); timer.resetIncrements(); } // Check if we can read stderr. - if (bytesAvailableFromStderr() != 0) { - _q_canReadStandardError(); + if (bytesAvailableInChannel(&stderrChannel) != 0) { + tryReadFromChannel(&stderrChannel); timer.resetIncrements(); } diff --git a/src/corelib/io/qprocess_wince.cpp b/src/corelib/io/qprocess_wince.cpp index b1c41ff069..e0bee48598 100644 --- a/src/corelib/io/qprocess_wince.cpp +++ b/src/corelib/io/qprocess_wince.cpp @@ -174,22 +174,12 @@ bool QProcessPrivate::processStarted() return processState == QProcess::Running; } -qint64 QProcessPrivate::bytesAvailableFromStdout() const +qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *) const { return 0; } -qint64 QProcessPrivate::bytesAvailableFromStderr() const -{ - return 0; -} - -qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen) -{ - return -1; -} - -qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen) +qint64 QProcessPrivate::readFromChannel(const Channel *, char *data, qint64 maxlen) { return -1; } -- cgit v1.2.3 From 6ca3ab626a04c3b05e6b3fde9a48457cf89c2889 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Jun 2014 17:15:03 -0700 Subject: Don't try to read from invalid file descriptors in QProcess strace reveals that we do ioctl(-1, FIONREAD) and get EBADF. The only case where this could happen is inside _q_processDied, which calls the read functions without checking if the pipe is still open. Change-Id: I67637fc4267be73fc03d40c444fdfea89e1ef715 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 3 +++ src/corelib/io/qprocess_unix.cpp | 2 ++ src/corelib/io/qprocess_win.cpp | 11 +++++------ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 615e584f81..0436aa5428 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -903,6 +903,9 @@ void QProcessPrivate::cleanup() bool QProcessPrivate::tryReadFromChannel(Channel *channel) { Q_Q(QProcess); + if (channel->pipe[0] == INVALID_Q_PIPE) + return false; + qint64 available = bytesAvailableInChannel(channel); if (available == 0) { if (channel->notifier) diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 430393d6f2..3c1eeb5f91 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -965,6 +965,7 @@ bool QProcessPrivate::processStarted() qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const { + Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE); int nbytes = 0; qint64 available = 0; if (::ioctl(channel->pipe[0], FIONREAD, (char *) &nbytes) >= 0) @@ -977,6 +978,7 @@ qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen) { + Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE); qint64 bytesRead = qt_safe_read(channel->pipe[0], data, maxlen); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::readFromChannel(%d, %p \"%s\", %lld) == %lld", diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 2dd4c475d8..7b3f1f8f58 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -566,11 +566,8 @@ bool QProcessPrivate::processStarted() qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const { - if (channel->pipe[0] == INVALID_Q_PIPE) - return 0; - - if (!channel->reader) - return 0; + Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE); + Q_ASSERT(channel->reader); DWORD bytesAvail = channel->reader->bytesAvailable(); #if defined QPROCESS_DEBUG @@ -581,7 +578,9 @@ qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen) { - return channel->reader ? channel->reader->read(data, maxlen) : 0; + Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE); + Q_ASSERT(channel->reader); + return channel->reader->read(data, maxlen); } static BOOL QT_WIN_CALLBACK qt_terminateApp(HWND hwnd, LPARAM procId) -- cgit v1.2.3 From 3ccfc351fdcbb117e2872229382e45a929dac62a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Jun 2014 16:44:07 -0700 Subject: QProcess: Handle spurious socket notifications for stdout and stderr On Unix systems where the GUI event dispatcher uses a notification system for socket notifiers that is out of band compared to select(), it's possible for the QSocketNotifier to activate after the pipe has been read from. When that happened, the ioctl(2) call with FIONREAD might return 0 bytes available, which we interpreted to mean EOF. Instead of doing that, always try to read at least one byte and examine the returned byte count from read(2). If it returns 0, that's a real EOF; if it returns -1 EWOULDBLOCK, we simply ignore the situation. That's the case on OS X: the Cocoa event dispatcher uses CFSocket to get notifications and those use kevent (and, apparently, an auxiliary thread) instead of an in-thread select() or poll(). That means the event loop would activate the QSocketNotifier even though there is nothing to be read. Task-number: QTBUG-39488 Change-Id: I1a58b5b1db7a47034fb36a78a005ebff96290efb Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 28 ++++--- src/corelib/io/qprocess_unix.cpp | 4 + src/corelib/io/qwindowspipereader.cpp | 4 +- src/network/socket/qlocalsocket_win.cpp | 12 ++- tests/auto/corelib/io/qprocess/test/test.pro | 1 - tests/auto/corelib/io/qprocess/tst_qprocess.cpp | 2 +- tests/auto/other/other.pro | 3 + .../qprocess_and_guieventloop.pro | 4 + .../auto/other/qprocess_and_guieventloop/test.pro | 5 ++ .../tst_qprocess_and_guieventloop.cpp | 89 ++++++++++++++++++++++ .../write-read-write/main.cpp | 58 ++++++++++++++ .../write-read-write/write-read-write.pro | 4 + 12 files changed, 201 insertions(+), 13 deletions(-) create mode 100644 tests/auto/other/qprocess_and_guieventloop/qprocess_and_guieventloop.pro create mode 100644 tests/auto/other/qprocess_and_guieventloop/test.pro create mode 100644 tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp create mode 100644 tests/auto/other/qprocess_and_guieventloop/write-read-write/main.cpp create mode 100644 tests/auto/other/qprocess_and_guieventloop/write-read-write/write-read-write.pro diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 0436aa5428..b03e96d0f6 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Intel Corporation ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -907,24 +908,33 @@ bool QProcessPrivate::tryReadFromChannel(Channel *channel) return false; qint64 available = bytesAvailableInChannel(channel); - if (available == 0) { - if (channel->notifier) - channel->notifier->setEnabled(false); - closeChannel(channel); -#if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::tryReadFromChannel(%d), 0 bytes available", channel - &stdinChannel); -#endif - return false; - } + if (available == 0) + available = 1; // always try to read at least one byte char *ptr = channel->buffer.reserve(available); qint64 readBytes = readFromChannel(channel, ptr, available); + if (readBytes <= 0) + channel->buffer.chop(available); + if (readBytes == -2) { + // EWOULDBLOCK + return false; + } if (readBytes == -1) { processError = QProcess::ReadError; q->setErrorString(QProcess::tr("Error reading from process")); emit q->error(processError); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::tryReadFromChannel(%d), failed to read from the process", channel - &stdinChannel); +#endif + return false; + } + if (readBytes == 0) { + // EOF + if (channel->notifier) + channel->notifier->setEnabled(false); + closeChannel(channel); +#if defined QPROCESS_DEBUG + qDebug("QProcessPrivate::tryReadFromChannel(%d), 0 bytes available", channel - &stdinChannel); #endif return false; } diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 3c1eeb5f91..2269740a2f 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -981,10 +981,14 @@ qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE); qint64 bytesRead = qt_safe_read(channel->pipe[0], data, maxlen); #if defined QPROCESS_DEBUG + int save_errno = errno; qDebug("QProcessPrivate::readFromChannel(%d, %p \"%s\", %lld) == %lld", channel - &stdinChannel, data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead); + errno = save_errno; #endif + if (bytesRead == -1 && errno == EWOULDBLOCK) + return -2; return bytesRead; } diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index 7dd2125e70..d8a3ec9b42 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -132,7 +132,7 @@ qint64 QWindowsPipeReader::bytesAvailable() const qint64 QWindowsPipeReader::read(char *data, qint64 maxlen) { if (pipeBroken && actualReadBufferSize == 0) - return -1; // signal EOF + return 0; // signal EOF qint64 readSoFar; // If startAsyncRead() has read data, copy it to its destination. @@ -159,6 +159,8 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen) emitReadyReadTimer->stop(); if (!readSequenceStarted) startAsyncRead(); + if (readSoFar == 0) + return -2; // signal EWOULDBLOCK } return readSoFar; diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 96c6c0f6ea..6fef819eee 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -202,7 +202,17 @@ qint64 QLocalSocket::readData(char *data, qint64 maxSize) if (!maxSize) return 0; - return d->pipeReader->read(data, maxSize); + qint64 ret = d->pipeReader->read(data, maxSize); + + // QWindowsPipeReader::read() returns error codes that don't match what we need + switch (ret) { + case 0: // EOF -> transform to error + return -1; + case -2: // EWOULDBLOCK -> no error, just no bytes + return 0; + default: + return ret; + } } qint64 QLocalSocket::writeData(const char *data, qint64 maxSize) diff --git a/tests/auto/corelib/io/qprocess/test/test.pro b/tests/auto/corelib/io/qprocess/test/test.pro index 79ea53cc6b..90afeddaa0 100644 --- a/tests/auto/corelib/io/qprocess/test/test.pro +++ b/tests/auto/corelib/io/qprocess/test/test.pro @@ -2,7 +2,6 @@ CONFIG += testcase CONFIG += parallel_test CONFIG -= app_bundle debug_and_release_target QT = core testlib network -embedded: QT += gui SOURCES = ../tst_qprocess.cpp TARGET = ../tst_qprocess diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index b67166272b..82a0f3f832 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -1953,7 +1953,7 @@ void tst_QProcess::setStandardOutputFile2() process.start("testProcessEcho2/testProcessEcho2"); process.write(testdata, sizeof testdata); QPROCESS_VERIFY(process,waitForFinished()); - QVERIFY(!process.bytesAvailable()); + QCOMPARE(process.bytesAvailable(), Q_INT64_C(0)); QVERIFY(!QFileInfo(QProcess::nullDevice()).isFile()); } diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro index e6017168d0..407237e519 100644 --- a/tests/auto/other/other.pro +++ b/tests/auto/other/other.pro @@ -23,6 +23,7 @@ SUBDIRS=\ qobjectperformance \ qobjectrace \ qsharedpointer_and_qwidget \ + qprocess_and_guieventloop \ qtokenautomaton \ windowsmobile \ @@ -71,3 +72,5 @@ wince*|!contains(QT_CONFIG, accessibility): SUBDIRS -= qaccessibility !embedded|wince*: SUBDIRS -= \ qdirectpainter +winrt: SUBDIRS -= \ + qprocess_and_guieventloop diff --git a/tests/auto/other/qprocess_and_guieventloop/qprocess_and_guieventloop.pro b/tests/auto/other/qprocess_and_guieventloop/qprocess_and_guieventloop.pro new file mode 100644 index 0000000000..e349fe5b11 --- /dev/null +++ b/tests/auto/other/qprocess_and_guieventloop/qprocess_and_guieventloop.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS = \ + write-read-write +SUBDIRS += test.pro diff --git a/tests/auto/other/qprocess_and_guieventloop/test.pro b/tests/auto/other/qprocess_and_guieventloop/test.pro new file mode 100644 index 0000000000..54d6f194b0 --- /dev/null +++ b/tests/auto/other/qprocess_and_guieventloop/test.pro @@ -0,0 +1,5 @@ +CONFIG += testcase +CONFIG += parallel_test +QT = core gui testlib +SOURCES = tst_qprocess_and_guieventloop.cpp +TARGET = tst_qprocess_and_guieventloop 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 new file mode 100644 index 0000000000..42153c6c80 --- /dev/null +++ b/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Intel Corporation +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +class tst_QProcess_and_GuiEventLoop : public QObject +{ + Q_OBJECT +private slots: + void waitForAndEventLoop(); +}; + + +void tst_QProcess_and_GuiEventLoop::waitForAndEventLoop() +{ + // based on testcase provided in QTBUG-39488 + QByteArray msg = "Hello World"; + + QProcess process; + process.start("write-read-write/write-read-write", QStringList() << msg); + QVERIFY(process.waitForStarted(5000)); + QVERIFY(process.waitForReadyRead(5000)); + QCOMPARE(process.readAll().trimmed(), msg); + + // run the GUI event dispatcher once + QSignalSpy spy(&process, SIGNAL(readyRead())); + qApp->processEvents(QEventLoop::AllEvents, 100); + + // we mustn't have read anything in the event loop + QCOMPARE(spy.count(), 0); + + // ensure the process hasn't died + QVERIFY(!process.waitForFinished(250)); + + // we mustn't have read anything during waitForFinished either + QCOMPARE(spy.count(), 0); + + // release the child for the second write + process.write("\n"); + QVERIFY(process.waitForFinished(5000)); + QCOMPARE(int(process.exitStatus()), int(QProcess::NormalExit)); + QCOMPARE(process.exitCode(), 0); + QCOMPARE(spy.count(), 1); + QCOMPARE(process.readAll().trimmed(), msg); +} + +QTEST_MAIN(tst_QProcess_and_GuiEventLoop) + +#include "tst_qprocess_and_guieventloop.moc" diff --git a/tests/auto/other/qprocess_and_guieventloop/write-read-write/main.cpp b/tests/auto/other/qprocess_and_guieventloop/write-read-write/main.cpp new file mode 100644 index 0000000000..e8fc3b5cff --- /dev/null +++ b/tests/auto/other/qprocess_and_guieventloop/write-read-write/main.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Intel Corporation +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +int main(int argc, char **argv) +{ + const char *msg = argv[1]; + char buf[2]; + + puts(msg); + fflush(stdout); + + // wait for a newline + fgets(buf, sizeof buf, stdin); + + puts(msg); + fflush(stdout); + return 0; +} diff --git a/tests/auto/other/qprocess_and_guieventloop/write-read-write/write-read-write.pro b/tests/auto/other/qprocess_and_guieventloop/write-read-write/write-read-write.pro new file mode 100644 index 0000000000..e236e05c7d --- /dev/null +++ b/tests/auto/other/qprocess_and_guieventloop/write-read-write/write-read-write.pro @@ -0,0 +1,4 @@ +SOURCES = main.cpp +CONFIG -= qt app_bundle +CONFIG += console +DESTDIR = ./ -- cgit v1.2.3 From 5da108a4a76b163116f1b816090075a9b86cf077 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 13 Jun 2014 08:56:17 +0200 Subject: Revert "Revert "Fixed duplicate QMoveEvent generated for each QWidget::move call"" This reverts commit c3e416296a1026d7ba99cf209f5e0720ff5050b1. The idea of detecting non-spontaneous events by comparing against the widget's crect has problems when sequences of programmatic resizes occur. In addition, QWindowSystemInterface's queueing of events is problematic for this. Task-number: QTBUG-39611 Task-number: QTBUG-32590 Change-Id: I9ff8049add147be23e064a513e8645ae04577c6c Reviewed-by: Andy Shaw --- src/widgets/kernel/qwidget_qpa.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index e5f552679c..17ed4ca477 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -779,7 +779,10 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) } } - if (isMove) { + // generate a move event for QWidgets without window handles. QWidgets with native + // window handles already receive a move event from + // QGuiApplicationPrivate::processGeometryChangeEvent. + if (isMove && (!q->windowHandle() || q->testAttribute(Qt::WA_DontShowOnScreen))) { QMoveEvent e(q->pos(), oldPos); QApplication::sendEvent(q, &e); } -- cgit v1.2.3 From 9c80a3be4b3beb28a3a6bda717c15b0ded523557 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 13 Jun 2014 08:59:45 +0200 Subject: Revert "Suppress move/resize events if they are the result of call to move()/resize()." This reverts commit a1c5198387fdb7db44a02bb94c56187874e67304. The idea of detecting non-spontaneous events by comparing against the widget's crect has problems when sequences of programmatic resizes occur. In addition, QWindowSystemInterface's queueing of events is problematic for this. Task-number: QTBUG-39611 Task-number: QTBUG-32590 Change-Id: I4674d8d5d5d432d938f7226b5790543335665c1f Reviewed-by: Andy Shaw --- src/widgets/kernel/qwidgetwindow.cpp | 12 +---- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 57 +++++------------------ 2 files changed, 14 insertions(+), 55 deletions(-) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 35a526e77d..fc328e7af0 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -591,24 +591,16 @@ void QWidgetWindow::updateNormalGeometry() void QWidgetWindow::handleMoveEvent(QMoveEvent *event) { - // If the widget's position already matches that of the event, this is a - // result of call to QWidget::move(), which already sends an event. - const bool spontaneous = m_widget->geometry().topLeft() != event->pos(); updateGeometry(); - if (spontaneous) - QGuiApplication::sendSpontaneousEvent(m_widget, event); + QGuiApplication::sendSpontaneousEvent(m_widget, event); } void QWidgetWindow::handleResizeEvent(QResizeEvent *event) { QSize oldSize = m_widget->data->crect.size(); - // If the widget's size already matches that of the event, this is a - // result of call to QWidget::resize(), which already sends an event. - const bool spontaneous = oldSize != event->size(); updateGeometry(); - if (spontaneous) - QGuiApplication::sendSpontaneousEvent(m_widget, event); + QGuiApplication::sendSpontaneousEvent(m_widget, event); if (m_widget->d_func()->paintOnScreen()) { QRegion updateRegion(geometry()); diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 41e98e7a2c..eac8ab2236 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -262,7 +262,6 @@ private slots: void optimizedResizeMove(); void optimizedResize_topLevel(); void resizeEvent(); - void moveEvent(); void task110173(); void testDeletionInEventHandlers(); @@ -2115,53 +2114,41 @@ void tst_QWidget::showFullScreen() class ResizeWidget : public QWidget { public: - ResizeWidget(QWidget *p = 0) - : QWidget(p) - , m_spontaneousResizeEventCount(0) - , m_synthesizedResizeEventCount(0) - , m_spontaneousMoveEventCount(0) - , m_synthesizedMoveEventCount(0) + ResizeWidget(QWidget *p = 0) : QWidget(p) { setObjectName(QLatin1String("ResizeWidget")); setWindowTitle(objectName()); + m_resizeEventCount = 0; } protected: void resizeEvent(QResizeEvent *e){ QCOMPARE(size(), e->size()); - (e->spontaneous() ? m_spontaneousResizeEventCount : m_synthesizedResizeEventCount)++; - } - void moveEvent(QMoveEvent *e) - { - (e->spontaneous() ? m_spontaneousMoveEventCount : m_synthesizedMoveEventCount)++; + ++m_resizeEventCount; } public: - int m_spontaneousResizeEventCount; - int m_synthesizedResizeEventCount; - int m_spontaneousMoveEventCount; - int m_synthesizedMoveEventCount; + int m_resizeEventCount; }; void tst_QWidget::resizeEvent() { + QSKIP("QTBUG-30744"); + { QWidget wParent; wParent.resize(200, 200); ResizeWidget wChild(&wParent); wParent.show(); QTest::qWaitForWindowExposed(&wParent); - QCOMPARE (wChild.m_synthesizedResizeEventCount, 1); // initial resize event before paint - QCOMPARE (wChild.m_spontaneousResizeEventCount, 0); + QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint wParent.hide(); QSize safeSize(640,480); if (wChild.size() == safeSize) safeSize.setWidth(639); wChild.resize(safeSize); - QCOMPARE (wChild.m_synthesizedResizeEventCount, 1); - QCOMPARE (wChild.m_spontaneousResizeEventCount, 0); + QCOMPARE (wChild.m_resizeEventCount, 1); wParent.show(); - QCOMPARE (wChild.m_synthesizedResizeEventCount, 2); - QCOMPARE (wChild.m_spontaneousResizeEventCount, 0); + QCOMPARE (wChild.m_resizeEventCount, 2); } { @@ -2169,39 +2156,19 @@ void tst_QWidget::resizeEvent() wTopLevel.resize(200, 200); wTopLevel.show(); QTest::qWaitForWindowExposed(&wTopLevel); - const int synthesizedResizeEventCountAfterShow = wTopLevel.m_synthesizedResizeEventCount; - QCOMPARE (synthesizedResizeEventCountAfterShow, 1); // initial resize event before paint for toplevels - QCOMPARE (wTopLevel.m_spontaneousResizeEventCount, 0); + QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels wTopLevel.hide(); QSize safeSize(640,480); if (wTopLevel.size() == safeSize) safeSize.setWidth(639); wTopLevel.resize(safeSize); - QCOMPARE (wTopLevel.m_synthesizedResizeEventCount, synthesizedResizeEventCountAfterShow); - QCOMPARE (wTopLevel.m_spontaneousResizeEventCount, 0); + QCOMPARE (wTopLevel.m_resizeEventCount, 1); wTopLevel.show(); QTest::qWaitForWindowExposed(&wTopLevel); -#ifdef Q_OS_OSX - QEXPECT_FAIL("", "QTBUG-30744", Abort); -#endif - QCOMPARE (wTopLevel.m_synthesizedResizeEventCount, synthesizedResizeEventCountAfterShow + 1); - QCOMPARE (wTopLevel.m_spontaneousResizeEventCount, 0); + QCOMPARE (wTopLevel.m_resizeEventCount, 2); } } -void tst_QWidget::moveEvent() -{ - ResizeWidget wTopLevel; - wTopLevel.resize(200, 200); - centerOnScreen(&wTopLevel); - wTopLevel.show(); - QTest::qWaitForWindowExposed(&wTopLevel); - const int synthesizedMoveEventCountAfterShow = wTopLevel.m_synthesizedMoveEventCount; - wTopLevel.move(wTopLevel.pos() + QPoint(20, 20)); - QTRY_COMPARE (wTopLevel.m_synthesizedMoveEventCount, synthesizedMoveEventCountAfterShow + 1); - QCOMPARE (wTopLevel.m_spontaneousMoveEventCount, 0); -} - void tst_QWidget::showMinimized() { QWidget plain; -- cgit v1.2.3 From fb3f47b638fcdeb68c68fbda4943f4fbb22261c6 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 5 Jun 2014 12:22:02 +0200 Subject: Android: Report something sensible for screen geometry We can't get the actual screen geometry on Android, but in Qt 5.3.0 we would always return the screen geometry minus the size of the status bar. After the available geometry was initialized to 0x0 instead of this arbitrary value, some applications that depended on this as a constant value would break if they collected the information before the window surface had been initialized and they forgot to listen to QScreen::geometryChanged(). To reduce the risk of regressions, this patch makes sure we return the same thing as before for the screen geometry and that this is not linked directly to the available screen geometry. Task-number: QTBUG-39464 Change-Id: Ie63337b3b10d2eb5130e4fece6c5b144e8230164 Reviewed-by: Paul Olav Tvete Reviewed-by: Christian Stromme --- src/plugins/platforms/android/androidjnimain.cpp | 12 ++++++++---- .../android/qandroidplatformintegration.cpp | 17 ++++++++++++++--- .../platforms/android/qandroidplatformintegration.h | 5 ++++- .../platforms/android/qandroidplatformscreen.cpp | 21 ++++++++++++++------- .../platforms/android/qandroidplatformscreen.h | 9 ++++++--- 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index f711a68a71..948b012399 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -549,7 +549,7 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, } static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/, - jint /*widthPixels*/, jint /*heightPixels*/, + jint widthPixels, jint heightPixels, jint desktopWidthPixels, jint desktopHeightPixels, jdouble xdpi, jdouble ydpi, jdouble scaledDensity) { @@ -558,13 +558,17 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/, m_scaledDensity = scaledDensity; if (!m_androidPlatformIntegration) { - QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels,desktopHeightPixels, - qRound(double(desktopWidthPixels) / xdpi * 25.4), - qRound(double(desktopHeightPixels) / ydpi * 25.4)); + QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels, + desktopHeightPixels, + qRound(double(desktopWidthPixels) / xdpi * 25.4), + qRound(double(desktopHeightPixels) / ydpi * 25.4), + widthPixels, + heightPixels); } else { m_androidPlatformIntegration->setDisplayMetrics(qRound(double(desktopWidthPixels) / xdpi * 25.4), qRound(double(desktopHeightPixels) / ydpi * 25.4)); m_androidPlatformIntegration->setDesktopSize(desktopWidthPixels, desktopHeightPixels); + m_androidPlatformIntegration->setScreenSize(widthPixels, heightPixels); } } diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 213b1bb7e6..d6d7d3b173 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -74,6 +74,8 @@ QT_BEGIN_NAMESPACE int QAndroidPlatformIntegration::m_defaultGeometryWidth = 320; int QAndroidPlatformIntegration::m_defaultGeometryHeight = 455; +int QAndroidPlatformIntegration::m_defaultScreenWidth = 320; +int QAndroidPlatformIntegration::m_defaultScreenHeight = 455; int QAndroidPlatformIntegration::m_defaultPhysicalSizeWidth = 50; int QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight = 71; @@ -121,7 +123,8 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶ m_primaryScreen = new QAndroidPlatformScreen(); screenAdded(m_primaryScreen); m_primaryScreen->setPhysicalSize(QSize(m_defaultPhysicalSizeWidth, m_defaultPhysicalSizeHeight)); - m_primaryScreen->setGeometry(QRect(0, 0, m_defaultGeometryWidth, m_defaultGeometryHeight)); + m_primaryScreen->setAvailableGeometry(QRect(0, 0, m_defaultGeometryWidth, m_defaultGeometryHeight)); + m_primaryScreen->setSize(QSize(m_defaultScreenWidth, m_defaultScreenHeight)); m_mainThread = QThread::currentThread(); QtAndroid::setAndroidPlatformIntegration(this); @@ -312,12 +315,14 @@ QPlatformTheme *QAndroidPlatformIntegration::createPlatformTheme(const QString & return 0; } -void QAndroidPlatformIntegration::setDefaultDisplayMetrics(int gw, int gh, int sw, int sh) +void QAndroidPlatformIntegration::setDefaultDisplayMetrics(int gw, int gh, int sw, int sh, int screenWidth, int screenHeight) { m_defaultGeometryWidth = gw; m_defaultGeometryHeight = gh; m_defaultPhysicalSizeWidth = sw; m_defaultPhysicalSizeHeight = sh; + m_defaultScreenWidth = screenWidth; + m_defaultScreenHeight = screenHeight; } void QAndroidPlatformIntegration::setDefaultDesktopSize(int gw, int gh) @@ -345,7 +350,7 @@ QPlatformAccessibility *QAndroidPlatformIntegration::accessibility() const void QAndroidPlatformIntegration::setDesktopSize(int width, int height) { if (m_primaryScreen) - QMetaObject::invokeMethod(m_primaryScreen, "setGeometry", Qt::AutoConnection, Q_ARG(QRect, QRect(0,0,width, height))); + QMetaObject::invokeMethod(m_primaryScreen, "setAvailableGeometry", Qt::AutoConnection, Q_ARG(QRect, QRect(0,0,width, height))); } void QAndroidPlatformIntegration::setDisplayMetrics(int width, int height) @@ -354,4 +359,10 @@ void QAndroidPlatformIntegration::setDisplayMetrics(int width, int height) QMetaObject::invokeMethod(m_primaryScreen, "setPhysicalSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height))); } +void QAndroidPlatformIntegration::setScreenSize(int width, int height) +{ + if (m_primaryScreen) + QMetaObject::invokeMethod(m_primaryScreen, "setSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height))); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index f8fa1a91dd..ce31516ace 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -86,6 +86,7 @@ public: virtual void setDesktopSize(int width, int height); virtual void setDisplayMetrics(int width, int height); + void setScreenSize(int width, int height); bool isVirtualDesktop() { return true; } QPlatformFontDatabase *fontDatabase() const; @@ -108,7 +109,7 @@ public: QStringList themeNames() const; QPlatformTheme *createPlatformTheme(const QString &name) const; - static void setDefaultDisplayMetrics(int gw, int gh, int sw, int sh); + static void setDefaultDisplayMetrics(int gw, int gh, int sw, int sh, int width, int height); static void setDefaultDesktopSize(int gw, int gh); static void setScreenOrientation(Qt::ScreenOrientation currentOrientation, Qt::ScreenOrientation nativeOrientation); @@ -135,6 +136,8 @@ private: static int m_defaultGeometryHeight; static int m_defaultPhysicalSizeWidth; static int m_defaultPhysicalSizeHeight; + static int m_defaultScreenWidth; + static int m_defaultScreenHeight; static Qt::ScreenOrientation m_orientation; static Qt::ScreenOrientation m_nativeOrientation; diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 11472ce1da..631032d80b 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -86,7 +86,8 @@ private: QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen() { - m_geometry = QRect(0, 0, QAndroidPlatformIntegration::m_defaultGeometryWidth, QAndroidPlatformIntegration::m_defaultGeometryHeight); + m_availableGeometry = QRect(0, 0, QAndroidPlatformIntegration::m_defaultGeometryWidth, QAndroidPlatformIntegration::m_defaultGeometryHeight); + m_size = QSize(QAndroidPlatformIntegration::m_defaultScreenWidth, QAndroidPlatformIntegration::m_defaultScreenHeight); // Raster only apps should set QT_ANDROID_RASTER_IMAGE_DEPTH to 16 // is way much faster than 32 if (qgetenv("QT_ANDROID_RASTER_IMAGE_DEPTH").toInt() == 16) { @@ -204,7 +205,7 @@ void QAndroidPlatformScreen::scheduleUpdate() void QAndroidPlatformScreen::setDirty(const QRect &rect) { - QRect intersection = rect.intersected(m_geometry); + QRect intersection = rect.intersected(m_availableGeometry); m_dirtyRect |= intersection; scheduleUpdate(); } @@ -214,15 +215,21 @@ void QAndroidPlatformScreen::setPhysicalSize(const QSize &size) m_physicalSize = size; } -void QAndroidPlatformScreen::setGeometry(const QRect &rect) +void QAndroidPlatformScreen::setSize(const QSize &size) +{ + m_size = size; + QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); +} + +void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect) { QMutexLocker lock(&m_surfaceMutex); - if (m_geometry == rect) + if (m_availableGeometry == rect) return; - QRect oldGeometry = m_geometry; + QRect oldGeometry = m_availableGeometry; - m_geometry = rect; + m_availableGeometry = rect; QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry()); resizeMaximizedWindows(); @@ -271,7 +278,7 @@ void QAndroidPlatformScreen::doRedraw() QMutexLocker lock(&m_surfaceMutex); if (m_id == -1 && m_rasterSurfaces) { - m_id = QtAndroid::createSurface(this, m_geometry, true, m_depth); + m_id = QtAndroid::createSurface(this, m_availableGeometry, true, m_depth); m_surfaceWaitCondition.wait(&m_surfaceMutex); } diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h index 96a91fbf06..cd9cf2ca71 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.h +++ b/src/plugins/platforms/android/qandroidplatformscreen.h @@ -66,7 +66,8 @@ public: QAndroidPlatformScreen(); ~QAndroidPlatformScreen(); - QRect geometry() const { return m_geometry; } + QRect geometry() const { return QRect(QPoint(), m_size); } + QRect availableGeometry() const { return m_availableGeometry; } int depth() const { return m_depth; } QImage::Format format() const { return m_format; } QSizeF physicalSize() const { return m_physicalSize; } @@ -87,7 +88,8 @@ public: public slots: void setDirty(const QRect &rect); void setPhysicalSize(const QSize &size); - void setGeometry(const QRect &rect); + void setAvailableGeometry(const QRect &rect); + void setSize(const QSize &size); protected: typedef QList WindowStackType; @@ -95,7 +97,7 @@ protected: QRect m_dirtyRect; QTimer m_redrawTimer; - QRect m_geometry; + QRect m_availableGeometry; int m_depth; QImage::Format m_format; QSizeF m_physicalSize; @@ -114,6 +116,7 @@ private: QAtomicInt m_rasterSurfaces = 0; ANativeWindow* m_nativeSurface = nullptr; QWaitCondition m_surfaceWaitCondition; + QSize m_size; }; QT_END_NAMESPACE -- cgit v1.2.3 From 16b90bb68343dc45a34d59083a2b62200fcc9551 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Thu, 12 Jun 2014 20:55:21 +0200 Subject: QFontComboBox sometimes became too wide because of wrong fixed size The fixed width should not be set on QFontComboBox itself, but on the popup. This regressed with commit bfb25c03523757d66974189e54dda97962206ef9, and caused assistants preferences dialog to become wider than the desktop. Change-Id: I2059794fc12d34837cdb7dfded80df57d102a6f0 Reviewed-by: Fabian Bumberger --- src/widgets/widgets/qfontcombobox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/widgets/qfontcombobox.cpp b/src/widgets/widgets/qfontcombobox.cpp index 40ca73904c..db01543629 100644 --- a/src/widgets/widgets/qfontcombobox.cpp +++ b/src/widgets/widgets/qfontcombobox.cpp @@ -548,7 +548,7 @@ bool QFontComboBox::event(QEvent *e) if (e->type() == QEvent::Resize) { QListView *lview = qobject_cast(view()); if (lview) { - setFixedWidth(qMin(width() * 5 / 3, + lview->window()->setFixedWidth(qMin(width() * 5 / 3, QApplication::desktop()->availableGeometry(lview).width())); } } -- cgit v1.2.3 From 66bd87e5c6f2b374e01c28fd2884a839edfcc06f Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 11 Jun 2014 20:30:39 +0300 Subject: Android: REG: Fix crash. Test if the window has a handle before using it. Change-Id: I728a129722f8ecd021998d483530a8d1687e5fe3 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/platforms/android/qandroidplatformscreen.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 631032d80b..714a670134 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -238,9 +238,11 @@ void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect) QList windows = QGuiApplication::allWindows(); for (int i = 0; i < windows.size(); ++i) { QWindow *w = windows.at(i); - QRect geometry = w->handle()->geometry(); - if (geometry.width() > 0 && geometry.height() > 0) - QWindowSystemInterface::handleExposeEvent(w, QRegion(geometry)); + if (w->handle()) { + QRect geometry = w->handle()->geometry(); + if (geometry.width() > 0 && geometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(w, QRegion(geometry)); + } } } -- cgit v1.2.3 From acd0dae3f49662047d76f5e7d6ab1f333c38549e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 8 Jun 2014 14:49:36 -0400 Subject: Fix data race in accessing QDBusConnectionPrivate::serviceNames The trick of creating a copy is not thread-safe. I'd known this since the moment I wrote that code, but thought "what could go wrong?". Task-number: QTBUG-39285 Change-Id: If521d4a649c06e6a34926687e85623aa25cb4c35 Reviewed-by: David Faure --- src/dbus/qdbusconnection_p.h | 2 +- src/dbus/qdbusintegrator.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index f2590f9c54..fd4ced078d 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -256,7 +256,7 @@ private: void deliverCall(QObject *object, int flags, const QDBusMessage &msg, const QVector &metaTypes, int slotIdx); - bool isServiceRegisteredByThread(const QString &serviceName) const; + bool isServiceRegisteredByThread(const QString &serviceName); QString getNameOwnerNoCache(const QString &service); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 1fef6d4d49..6b6ac6bc62 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -2488,12 +2488,15 @@ void QDBusConnectionPrivate::unregisterServiceNoLock(const QString &serviceName) serviceNames.removeAll(serviceName); } -bool QDBusConnectionPrivate::isServiceRegisteredByThread(const QString &serviceName) const +bool QDBusConnectionPrivate::isServiceRegisteredByThread(const QString &serviceName) { if (!serviceName.isEmpty() && serviceName == baseService) return true; - QStringList copy = serviceNames; - return copy.contains(serviceName); + if (serviceName == dbusServiceString()) + return false; + + QDBusReadLocker locker(UnregisterServiceAction, this); + return serviceNames.contains(serviceName); } void QDBusConnectionPrivate::postEventToThread(int action, QObject *object, QEvent *ev) -- cgit v1.2.3 From a461bb1ff5b5f310244bae1691b08e7135aeda0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 19 May 2014 08:58:37 +0200 Subject: Flush xcb connection before EventDispatcher is going to block The non-threaded QXcbEventReader invokes processXcbEvents when the EventDispatcher is about to block. This method ensures that the xcb connection is going to flush. Applications can use low level xcb code in that case without having to ensure to flush the connection before going to block again. With the threaded QXcbEventReader this didn't work and applications which for example changed a window property and waited for the matching property notify event were stalled. This change ensures that also in the threaded case the connection gets flushed when the EventDispatcher is going to block. Change-Id: If1dc5eb96e2f1bde10b7a40af550b0608c62f70c Reviewed-by: Laszlo Agocs Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.cpp | 9 +++++++++ src/plugins/platforms/xcb/qxcbconnection.h | 6 +++++- src/plugins/platforms/xcb/qxcbintegration.cpp | 5 ++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 1b72bb0da1..7f23c84cb9 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1028,6 +1028,15 @@ void QXcbEventReader::registerForEvents() connect(dispatcher, SIGNAL(awake()), m_connection, SLOT(processXcbEvents())); } +void QXcbEventReader::registerEventDispatcher(QAbstractEventDispatcher *dispatcher) +{ + // flush the xcb connection before the EventDispatcher is going to block + // In the non-threaded case processXcbEvents is called before going to block, + // which flushes the connection. + if (m_xcb_poll_for_queued_event) + connect(dispatcher, SIGNAL(aboutToBlock()), m_connection, SLOT(flush())); +} + void QXcbEventReader::run() { xcb_generic_event_t *event; diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 6c9ccbcc2f..0bfc2f8f76 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -311,6 +311,8 @@ public: void start(); + void registerEventDispatcher(QAbstractEventDispatcher *dispatcher); + signals: void eventPending(); @@ -410,7 +412,6 @@ public: void sync(); - void flush() { xcb_flush(m_connection); } void handleXcbError(xcb_generic_error_t *error); void handleXcbEvent(xcb_generic_event_t *event); @@ -464,8 +465,11 @@ public: void handleEnterEvent(const xcb_enter_notify_event_t *); #endif + QXcbEventReader *eventReader() const { return m_reader; } + public slots: void syncWindow(QXcbWindow *window); + void flush() { xcb_flush(m_connection); } private slots: void processXcbEvents(); diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index ddb164bf07..1b1c20f02c 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -303,7 +303,10 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const QAbstractEventDispatcher *QXcbIntegration::createEventDispatcher() const { - return createUnixEventDispatcher(); + QAbstractEventDispatcher *dispatcher = createUnixEventDispatcher(); + for (int i = 0; i < m_connections.size(); i++) + m_connections[i]->eventReader()->registerEventDispatcher(dispatcher); + return dispatcher; } void QXcbIntegration::initialize() -- cgit v1.2.3 From ad9ca6052215069672291fd1407b485cedc9778c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 16 Jun 2014 11:47:22 +0200 Subject: install .lib files for static libs again the no_dll switch has questionable semantics: it pro-actively breaks non-dll builds. therefore its usage needs to be limited to dll build. Task-number: QTBUG-39594 Change-Id: I98328e502693df835af565b5ec25ada2c1c168ad Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_installs.prf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/qt_installs.prf b/mkspecs/features/qt_installs.prf index 7d2280e75a..3a5dbb6274 100644 --- a/mkspecs/features/qt_installs.prf +++ b/mkspecs/features/qt_installs.prf @@ -22,7 +22,7 @@ target.path = $$[QT_HOST_LIBS] else: \ target.path = $$[QT_INSTALL_LIBS] - target.CONFIG = no_dll + !static: target.CONFIG = no_dll INSTALLS += target } -- cgit v1.2.3 From 59d6871ae3a9978d5578811c50a94f5cb3fc704d Mon Sep 17 00:00:00 2001 From: Lucile Quirion Date: Thu, 1 May 2014 10:16:42 -0400 Subject: directfb: fix QThread destroyed while running Commit cf092abdfc888f19a607a43c9b4bac776b5c1f8e introduces a virtual "void initialize()" in QPlatformIntegration class. "void initialize()" was already implemented in QDirectFbIntegration since commit 6534898cc69e22115cf158f71a1e0edd7f13877b allowing initialization steps to be overridden by QDirectFbIntegrationEGL. Therefore the QScopePointer "m_input" handling a QThread is reset twice. The QThread firstly created is forcibly terminated. The application displays the error message "QThread: Destroyed while thread is still running" and sometimes crash with a SIGSEGV. This commit rename QDirectFbIntegration::initialize() into QDirectFbIntegration::connectToDirectFb() to fix this issue. Task-number: QTBUG-38710 Change-Id: I3ca07c373af7c47abf08da2b45bbcf7a6cf573ad Reviewed-by: Holger Freyther Reviewed-by: Laszlo Agocs --- src/plugins/platforms/directfb/main.cpp | 3 ++- src/plugins/platforms/directfb/qdirectfbintegration.cpp | 2 +- src/plugins/platforms/directfb/qdirectfbintegration.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/directfb/main.cpp b/src/plugins/platforms/directfb/main.cpp index 423e33efd5..b0354c236d 100644 --- a/src/plugins/platforms/directfb/main.cpp +++ b/src/plugins/platforms/directfb/main.cpp @@ -75,7 +75,8 @@ QPlatformIntegration * QDirectFbIntegrationPlugin::create(const QString& system, if (!integration) return 0; - integration->initialize(); + integration->connectToDirectFb(); + return integration; } diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.cpp b/src/plugins/platforms/directfb/qdirectfbintegration.cpp index 7ca7da8bcd..3d1b79ef38 100644 --- a/src/plugins/platforms/directfb/qdirectfbintegration.cpp +++ b/src/plugins/platforms/directfb/qdirectfbintegration.cpp @@ -64,7 +64,7 @@ QDirectFbIntegration::QDirectFbIntegration() { } -void QDirectFbIntegration::initialize() +void QDirectFbIntegration::connectToDirectFb() { initializeDirectFB(); initializeScreen(); diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.h b/src/plugins/platforms/directfb/qdirectfbintegration.h index 5822202eea..b49600bed9 100644 --- a/src/plugins/platforms/directfb/qdirectfbintegration.h +++ b/src/plugins/platforms/directfb/qdirectfbintegration.h @@ -60,7 +60,7 @@ public: QDirectFbIntegration(); ~QDirectFbIntegration(); - void initialize(); + void connectToDirectFb(); QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; -- cgit v1.2.3 From 4038f21dd0799d319a8ee019735cbe109405a532 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 10 Jun 2014 15:25:34 +0200 Subject: xcb: touch device mode is either Dependent or Direct, not Rel or Abs Change-Id: Ic0091007c95c4c307485bc2d5d3e1e967b44323e Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 0b7ea155c1..c296618c44 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -347,10 +347,10 @@ XInput2DeviceData *QXcbConnection::deviceForId(int id) if (Q_UNLIKELY(debug_xinput_devices)) qDebug(" has touch class with mode %d", tci->mode); switch (tci->mode) { - case XIModeRelative: + case XIDependentTouch: type = QTouchDevice::TouchPad; break; - case XIModeAbsolute: + case XIDirectTouch: type = QTouchDevice::TouchScreen; break; } -- cgit v1.2.3 From c92ece451872942c81592d33be495baa96afc416 Mon Sep 17 00:00:00 2001 From: Martin Pley Date: Tue, 10 Jun 2014 13:33:26 +0200 Subject: QRasterPlatformPixmap::createPixmapForImage(): Avoid crash when QImage conversion failes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added some checks to QRasterPlatformPixmap::createPixmapForImage() to avoid crashes when QImage::convertToFormat() returns a null image. Change-Id: I573505a1aff7931d9a2fb452d0a83ae93d8de7db Reviewed-by: Gunnar Sletta Reviewed-by: Morten Johan Sørvig --- src/gui/image/qpixmap_raster.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 1465fea8b9..d879a5cb61 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -363,10 +363,12 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC } is_null = (w <= 0 || h <= 0); - image.d->devicePixelRatio = sourceImage.devicePixelRatio(); + if (image.d) + image.d->devicePixelRatio = sourceImage.devicePixelRatio(); //ensure the pixmap and the image resulting from toImage() have the same cacheKey(); setSerialNumber(image.cacheKey() >> 32); - setDetachNumber(image.d->detach_no); + if (image.d) + setDetachNumber(image.d->detach_no); } QImage* QRasterPlatformPixmap::buffer() -- cgit v1.2.3 From bdd60463da20172ee351b5fbf30822367d66f78f Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 17 Jun 2014 13:13:18 +0200 Subject: Fix animations in static builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure qRegisterGuiGetInterpolator is called even for static builds. Task-number: QTBUG-37341 Change-Id: I65735a558d5bbfaa02fa4ec47d55ddf33ca1991a Reviewed-by: Jędrzej Nowacki Reviewed-by: Friedemann Kleint --- src/gui/animation/qguivariantanimation.cpp | 2 +- src/gui/kernel/qguiapplication.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp index 34abbca282..2cd31696ba 100644 --- a/src/gui/animation/qguivariantanimation.cpp +++ b/src/gui/animation/qguivariantanimation.cpp @@ -64,7 +64,7 @@ template<> Q_INLINE_TEMPLATE QQuaternion _q_interpolate(const QQuaternion &f,con return QQuaternion::slerp(f, t, progress); } -static void qRegisterGuiGetInterpolator() +void qRegisterGuiGetInterpolator() { qRegisterAnimationInterpolator(_q_interpolateVariant); qRegisterAnimationInterpolator(_q_interpolateVariant); diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 8ccff4321d..1894dbf3ba 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -171,6 +171,7 @@ bool QGuiApplicationPrivate::noGrab = false; static qreal fontSmoothingGamma = 1.7; extern void qRegisterGuiVariant(); +extern void qRegisterGuiGetInterpolator(); extern void qInitDrawhelperAsm(); extern void qInitImageConversions(); @@ -1274,6 +1275,9 @@ void QGuiApplicationPrivate::init() // trigger registering of QVariant's GUI types qRegisterGuiVariant(); + // trigger registering of animation interpolators + qRegisterGuiGetInterpolator(); + QWindowSystemInterfacePrivate::eventTime.start(); is_app_running = true; -- cgit v1.2.3 From 000d98d826e7b85655456a66522812da338c3f72 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 18 Jun 2014 00:27:55 +0200 Subject: Bump version Change-Id: I867c3b4aecc82095e65bd7f820e7fe6d14005705 --- src/corelib/global/qglobal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 707e46dd40..d1aae1a681 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -45,11 +45,11 @@ #include -#define QT_VERSION_STR "5.3.1" +#define QT_VERSION_STR "5.3.2" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x050301 +#define QT_VERSION 0x050302 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ -- cgit v1.2.3 From 10ff9d5b6f9643d3bcae519d8bf5107711d4e55d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 17 Jun 2014 15:08:24 +0200 Subject: Handle invalid sample counts gracefully in FBOs Passing in a sample count of -1 should be treated as 0. This is common when setting up framebuffer formats from a QSurfaceFormat where the default, unset value is indicated by a value of -1. This broke QQuickWidget which was unaware of this limitation of QOpenGLFramebufferObject and was passing format.samples() as the sample count without making sure it is 0 or higher. Task-number: QTBUG-39699 Change-Id: I324b8b006eaa992c15ae932f9df305500fefeb65 Reviewed-by: Paul Olav Tvete Reviewed-by: Friedemann Kleint --- src/gui/opengl/qopenglframebufferobject.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index cd6468cccd..3102e1ecd2 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -436,6 +436,7 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi samples = qBound(0, int(samples), int(maxSamples)); #endif + samples = qMax(0, samples); requestedSamples = samples; size = sz; target = texture_target; -- cgit v1.2.3 From abcea1c5f06b2ea0428e08a3a71f08d39c29c2fd Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 17 Jun 2014 15:37:31 +0200 Subject: harfbuzz-ng: Pre-allocate enough space for CoreText buffer This fixes an assert in OS X 10.10 Yosemite, where the pre- allocated buffer would be too small to hold 3 successive calls to ALLOCATE_ARRAY. Task-number: QTBUG-39504 Change-Id: I5a0ae36170636eb97ab21c5903b96674e2a99547 Reviewed-by: Konstantin Ritt Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/3rdparty/harfbuzz-ng/src/hb-coretext.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc index 4fef861acc..2507cd1d9f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc @@ -738,7 +738,8 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, if (num_glyphs == 0) continue; - buffer->ensure (buffer->len + num_glyphs + (endWithPDF ? 1 : 0)); + const long ensureCount = DIV_CEIL(sizeof(CGGlyph) + sizeof(CGPoint) + sizeof(CFIndex), sizeof(*scratch)); + buffer->ensure (buffer->len + ensureCount * (num_glyphs + (endWithPDF ? 1 : 0))); scratch = buffer->get_scratch_buffer (&scratch_size); -- cgit v1.2.3 From 302ffa5820c05534bec9978368b3c2c1295f12a1 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Wed, 18 Jun 2014 13:24:00 +0300 Subject: Fix crash when reusing HB_Face in another font engine After 717d39ac083e80, if HB_Face was instantiated by QFontEngineFT A and then used by QFontEngineFT B, whilst A already destroyed, a crash occurs in hb_getSFntTable() due to accessing a stale pointer. Task-number: QTBUG-39278 Change-Id: I3428669a311f49cdda1725b778f45219cbcf470d Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontengine.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 078e16574f..8adbb31a55 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -177,9 +177,13 @@ static const HB_FontClass hb_fontClass = { static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length) { - QFontEngine *fe = (QFontEngine *)font; - Q_ASSERT(fe->faceData.get_font_table); - if (!fe->faceData.get_font_table(fe->faceData.user_data, tableTag, buffer, length)) + QFontEngine::FaceData *data = (QFontEngine::FaceData *)font; + Q_ASSERT(data); + + qt_get_font_table_func_t get_font_table = data->get_font_table; + Q_ASSERT(get_font_table); + + if (!get_font_table(data->user_data, tableTag, buffer, length)) return HB_Err_Invalid_Argument; return HB_Err_Ok; } @@ -287,8 +291,11 @@ void *QFontEngine::harfbuzzFont() const #endif if (!font_) { HB_Face hbFace = (HB_Face)harfbuzzFace(); - if (hbFace->font_for_init != 0) + if (hbFace->font_for_init) { + void *data = hbFace->font_for_init; q_check_ptr(qHBLoadFace(hbFace)); + free(data); + } HB_FontRec *hbFont = (HB_FontRec *) malloc(sizeof(HB_FontRec)); Q_CHECK_PTR(hbFont); @@ -319,7 +326,12 @@ void *QFontEngine::harfbuzzFace() const return hb_qt_face_get_for_engine(const_cast(this)); #endif if (!face_) { - HB_Face hbFace = qHBNewFace(const_cast(this), hb_getSFntTable); + QFontEngine::FaceData *data = (QFontEngine::FaceData *)malloc(sizeof(QFontEngine::FaceData)); + Q_CHECK_PTR(data); + data->user_data = faceData.user_data; + data->get_font_table = faceData.get_font_table; + + HB_Face hbFace = qHBNewFace(data, hb_getSFntTable); Q_CHECK_PTR(hbFace); hbFace->isSymbolFont = symbol; @@ -372,8 +384,11 @@ bool QFontEngine::supportsScript(QChar::Script script) const } #endif HB_Face hbFace = (HB_Face)harfbuzzFace(); - if (hbFace->font_for_init != 0) + if (hbFace->font_for_init) { + void *data = hbFace->font_for_init; q_check_ptr(qHBLoadFace(hbFace)); + free(data); + } return hbFace->supported_scripts[script_to_hbscript(script)]; } -- cgit v1.2.3 From 540ac8fd988136b5834d680a89b0aa20e9d5d131 Mon Sep 17 00:00:00 2001 From: Jani Heikkinen Date: Wed, 18 Jun 2014 12:18:01 +0300 Subject: Add changelog for Qt 5.3.1 Replaces https://codereview.qt-project.org/#/c/87562/ Change-Id: Id89c8b67ec47cb1d078c5325aa519daeee3cafa9 Reviewed-by: Peter Hartmann Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Jani Heikkinen --- dist/changes-5.3.1 | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 dist/changes-5.3.1 diff --git a/dist/changes-5.3.1 b/dist/changes-5.3.1 new file mode 100644 index 0000000000..a9760b1d57 --- /dev/null +++ b/dist/changes-5.3.1 @@ -0,0 +1,62 @@ +Qt 5.3.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.3.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://qt-project.org/doc/qt-5.3 + +The Qt version 5.3 series is binary compatible with the 5.2.x series. +Applications compiled for 5.2 will continue to run with 5.3. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt-project.org/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtCore +------ + + - QAbstractProxyModel: + * Fixed QAbstractProxyModel::sibling to work in the same manner as the + Qt4 code used to behave. Previously, Qt5's implementation would treat + the row and column as positions in the source model instead of a + position in the proxy itself. + +QtGui +----- + + - Text: + * [QTBUG-36083] Respect QFont::fixedPitch() for fallbacks when font + family cannot be matched. + * [QTBUG-37190] Fixed crash when trying to load a font from invalid + data. + +QtWidgets +--------- + + - QMenu: + * [QTBUG-38498] Accessibility: Menus are now read by screen readers + with more reliability. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-38960] Fixed regression where there would be flickering on + startup and shutdown of the application. + - [QTBUG-35975] Fixed repaint issues in drag and drop. + + - Text: + * [QTBUG-37844] Fall back to Droid Sans Mono for QFont::Courier style + hint. -- cgit v1.2.3 From 863a8bfab544c5f92beb9231aa2cde4b3c3e6d71 Mon Sep 17 00:00:00 2001 From: Bjoern Breitmeyer Date: Wed, 14 May 2014 15:35:41 +0200 Subject: Fixes QFontDataBase addApplicationFont on WEC. AddFontResourceExW was not implemented yet. Change-Id: Iffa3e49bdbb0176c10324ede6161fcf8b2a63902 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qplatformfunctions_wince.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/qplatformfunctions_wince.h b/src/plugins/platforms/windows/qplatformfunctions_wince.h index 65ce466086..921e64d64c 100644 --- a/src/plugins/platforms/windows/qplatformfunctions_wince.h +++ b/src/plugins/platforms/windows/qplatformfunctions_wince.h @@ -271,14 +271,19 @@ typedef struct tagTTPOLYCURVE #define WM_DRAWCLIPBOARD 0x0308 #endif +#include + inline bool IsIconic( HWND /*hWnd*/ ) { return false; } -inline int AddFontResourceExW( LPCWSTR /*name*/, DWORD /*fl*/, PVOID /*res*/) +inline int AddFontResourceExW( LPCWSTR name, DWORD /*fl*/, PVOID /*res*/) { - return 0; + QString fName = QString::fromWCharArray(name); + QFileInfo fileinfo(fName); + fName = fileinfo.absoluteFilePath(); + return AddFontResource((LPCWSTR)fName.utf16()); } inline bool RemoveFontResourceExW( LPCWSTR /*name*/, DWORD /*fl*/, PVOID /*pdv*/) -- cgit v1.2.3 From 2de8ef2e49d1a14b5d4acf7bfd9539dadbcbc54f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 Jun 2014 15:38:35 -0700 Subject: Fix compilation with the Intel compiler on certain systems We require the intrinsics from immintrin.h, so include it unconditioanlly with that compiler. Change-Id: I4a17676631f9d89e2d22e486f40c9b177ca06c1e Reviewed-by: Olivier Goffart --- src/corelib/tools/qsimd_p.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index f4ca971567..e1c22bac71 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -139,8 +139,10 @@ || (defined(Q_CC_CLANG) && (__clang_major__ * 100 + __clang_minor__ >= 208)) \ || defined(Q_CC_INTEL)) # define QT_COMPILER_SUPPORTS_X86INTRIN -# ifndef Q_CC_INTEL +# ifdef Q_CC_INTEL // The Intel compiler has no -- all intrinsics are in ; +# include +# else // GCC 4.4 and Clang 2.8 added a few more intrinsics there # include # endif -- cgit v1.2.3 From d88b976858437f081ef9f8150b3697586a5bf73a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 Jun 2014 15:30:35 -0700 Subject: Fix compilation in under -no-c++11 mode IndexSetter can't be passed to QObject::connect() since C++98 templates require global types (they can't be function-local). Change-Id: I099322f835661d4679140b7810b50dbeb0e4b9e0 Reviewed-by: Gabriel de Dietrich Reviewed-by: Olivier Goffart --- src/widgets/widgets/qcombobox.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index f857f4eac0..3718f09337 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -2377,6 +2377,16 @@ QSize QComboBox::sizeHint() const } #ifdef Q_OS_OSX + +namespace { +struct IndexSetter { + int index; + QComboBox *cb; + + void operator()(void) { cb->setCurrentIndex(index); } +}; +} + /*! * \internal * @@ -2391,13 +2401,6 @@ bool QComboBoxPrivate::showNativePopup() if (QPlatformMenu *menu = theme->createPlatformMenu()) { int itemsCount = q->count(); - struct IndexSetter { - int index; - QComboBox *cb; - - void operator()(void) { cb->setCurrentIndex(index); } - }; - QList items; items.reserve(itemsCount); QPlatformMenuItem *currentItem = 0; -- cgit v1.2.3 From 54a2206bba699687c4218bde2d9b295c2cf5a549 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 10 Jun 2014 15:41:53 +0200 Subject: Windows: Mark only mouse events synthesized by touch as such. Pass on mouse events from pen. Task-number: QTBUG-39353 Change-Id: I96c4e023ddb1c853d5228d00aa9604941556abb4 Reviewed-by: Joerg Bornemann Reviewed-by: Oliver Wolff Reviewed-by: Shawn Rutledge --- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index cc0597b72d..4633378342 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -178,10 +178,11 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, // since we do not want to ignore mouse events coming from a tablet. const quint64 extraInfo = GetMessageExtraInfo(); if ((extraInfo & signatureMask) == miWpSignature) { - source = Qt::MouseEventSynthesizedBySystem; - const bool fromTouch = extraInfo & 0x80; // (else: Tablet PC) - if (fromTouch && !passSynthesizedMouseEvents) - return false; + if (extraInfo & 0x80) { // Bit 7 indicates touch event, else tablet pen. + source = Qt::MouseEventSynthesizedBySystem; + if (!passSynthesizedMouseEvents) + return false; + } } #endif // !Q_OS_WINCE -- cgit v1.2.3 From feda990ae8fa3bc25ad5b5b7f7cc4733137519d6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 6 Jun 2014 14:26:26 +0200 Subject: QEventDispatcherWin32: Use a shared class name for the message window. Introduce a global-static struct storing atom and class name for the message window to be shared between threads. This prevents RegisterWindow()/UnregisterWindow() of different threads (using exec()) from interfering and silently failing. Task-number: QTBUG-39471 Change-Id: I9bc1106a41f64749c55825a96973921bb831458f Reviewed-by: Joerg Bornemann --- src/corelib/kernel/qeventdispatcher_win.cpp | 54 ++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 64ad2ff0d3..db2d30f2f5 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -325,8 +325,6 @@ QEventDispatcherWin32Private::~QEventDispatcherWin32Private() { if (internalHwnd) DestroyWindow(internalHwnd); - QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); - UnregisterClass((wchar_t*)className.utf16(), qWinAppInst()); } void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen) @@ -486,10 +484,26 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) #endif } -static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher) +// Provide class name and atom for the message window used by +// QEventDispatcherWin32Private via Q_GLOBAL_STATIC shared between threads. +struct QWindowsMessageWindowClassContext +{ + QWindowsMessageWindowClassContext(); + ~QWindowsMessageWindowClassContext(); + + ATOM atom; + wchar_t *className; +}; + +QWindowsMessageWindowClassContext::QWindowsMessageWindowClassContext() + : atom(0), className(0) { // make sure that multiple Qt's can coexist in the same process - QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); + const QString qClassName = QStringLiteral("QEventDispatcherWin32_Internal_Widget") + + QString::number(quintptr(qt_internal_proc)); + className = new wchar_t[qClassName.size() + 1]; + qClassName.toWCharArray(className); + className[qClassName.size()] = 0; WNDCLASS wc; wc.style = 0; @@ -501,16 +515,37 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch wc.hCursor = 0; wc.hbrBackground = 0; wc.lpszMenuName = NULL; - wc.lpszClassName = reinterpret_cast (className.utf16()); + wc.lpszClassName = className; + atom = RegisterClass(&wc); + if (!atom) { + qErrnoWarning("%s: RegisterClass() failed", Q_FUNC_INFO, qPrintable(qClassName)); + delete [] className; + className = 0; + } +} + +QWindowsMessageWindowClassContext::~QWindowsMessageWindowClassContext() +{ + if (className) { + UnregisterClass(className, qWinAppInst()); + delete [] className; + } +} + +Q_GLOBAL_STATIC(QWindowsMessageWindowClassContext, qWindowsMessageWindowClassContext) - RegisterClass(&wc); +static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher) +{ + QWindowsMessageWindowClassContext *ctx = qWindowsMessageWindowClassContext(); + if (!ctx->atom) + return 0; #ifdef Q_OS_WINCE HWND parent = 0; #else HWND parent = HWND_MESSAGE; #endif - HWND wnd = CreateWindow(wc.lpszClassName, // classname - wc.lpszClassName, // window name + HWND wnd = CreateWindow(ctx->className, // classname + ctx->className, // window name 0, // style 0, 0, 0, 0, // geometry parent, // parent @@ -519,7 +554,8 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch 0); // windows creation data. if (!wnd) { - qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError()); + qErrnoWarning("%s: CreateWindow() for QEventDispatcherWin32 internal window failed", Q_FUNC_INFO); + return 0; } #ifdef GWLP_USERDATA -- cgit v1.2.3 From 5af8a46bc1275da3210047e4f94c3ecbb40ab550 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 17 Jun 2014 10:18:22 +0200 Subject: QGuiApplication: Document -plugin command line argument. Task-number: QTBUG-38972 Change-Id: Ie4dd6d70e60822a5a3626b10cd90d081897d646d Reviewed-by: Thiago Macieira --- src/gui/kernel/qguiapplication.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 1894dbf3ba..f429ad2229 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -490,6 +490,12 @@ static QWindowGeometrySpecification windowGeometrySpecification; \li \c{-platformtheme} \e platformTheme, specifies the platform theme. Overridden by the \c QT_QPA_PLATFORMTHEME environment variable. + + \li \c{-plugin} \e plugin, specifies additional plugins to load. The argument + may appear multiple times. + + Overridden by the \c QT_QPA_GENERIC_PLUGINS environment variable. + \li \c{-qmljsdebugger=}, activates the QML/JS debugger with a specified port. The value must be of format \c{port:1234}\e{[,block]}, where \e block is optional -- cgit v1.2.3 From 3fd184b663efcf3691efcd6411fb0b18f941f7b2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 17 Jun 2014 17:13:11 +0200 Subject: Use QModelIndex to get the data from underlying model Change-Id: Ibeb70079afd566c78289168540296b926f36d1af Initial-patch-by: Irfan Omair Task-number: QTBUG-27597 Reviewed-by: Andy Shaw --- src/widgets/widgets/qcombobox.cpp | 4 +- .../widgets/widgets/qcombobox/tst_qcombobox.cpp | 43 +++++++++++++++++++++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 3718f09337..3491c5ba85 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -2055,7 +2055,7 @@ void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi) if (indexChanged) currentIndex = QPersistentModelIndex(normalized); if (lineEdit) { - QString newText = q->itemText(normalized.row()); + const QString newText = itemText(normalized); if (lineEdit->text() != newText) lineEdit->setText(newText); updateLineEditGeometry(); diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index abc0129f8b..c38c254b9a 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -72,6 +72,7 @@ #include #include #include +#include #include static inline void setFrameless(QWidget *w) @@ -163,6 +164,7 @@ private slots: void itemData(); void task_QTBUG_31146_popupCompletion(); void keyboardSelection(); + void setCustomModelAndView(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -1580,6 +1582,45 @@ void tst_QComboBox::setModel() QVERIFY(box.model() != oldModel); } +void tst_QComboBox::setCustomModelAndView() +{ + // QTBUG-27597, ensure the correct text is returned when using custom view and a tree model. + QComboBox combo; + combo.setWindowTitle("QTBUG-27597, setCustomModelAndView"); + combo.setEditable(true); + combo.setMinimumWidth(400); + const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); + combo.move(availableGeometry.center() - QPoint(200, 20)); + + QStandardItemModel *model = new QStandardItemModel(0, 1, &combo); + + QStandardItem *item = new QStandardItem(QStringLiteral("Item1")); + item->appendRow(new QStandardItem(QStringLiteral("Item11"))); + model->appendRow(item); + + item = new QStandardItem(QStringLiteral("Item2")); + model->appendRow(item); + const QString subItem21Text = QStringLiteral("Item21"); + QStandardItem *subItem = new QStandardItem(subItem21Text); + item->appendRow(subItem); + + QTreeView* view = new QTreeView(&combo); + view->setHeaderHidden(true); + view->setSelectionMode(QAbstractItemView::SingleSelection); + view->setModel(model); + view->expandAll(); + combo.setModel(model); + combo.setView(view); + combo.show(); + QVERIFY(QTest::qWaitForWindowExposed(&combo)); + combo.showPopup(); + QTRY_VERIFY(combo.view()->isVisible()); + const QRect subItemRect = view->visualRect(model->indexFromItem(subItem)); + QWidget *window = view->window(); + QTest::mouseClick(window->windowHandle(), Qt::LeftButton, 0, view->mapTo(window, subItemRect.center())); + QTRY_COMPARE(combo.currentText(), subItem21Text); +} + void tst_QComboBox::modelDeleted() { QComboBox box; -- cgit v1.2.3 From 1a034ac218ee912b2f565a2fbafd7eb53ad6a3bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Tue, 17 Jun 2014 15:10:03 +0200 Subject: Attempt to fix intel compiler build error. qtbase/include/QtCore/../../src/corelib/kernel/qobjectdefs_impl.h(625): error #68: integer conversion resulted in a change of sign Task-number: QTBUG-39678 Change-Id: Ifb175bdcad820aa58cc0a1bcf6985a164376baf5 Reviewed-by: Olivier Goffart Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobjectdefs_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index de6f65ab7d..de95fcc313 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -622,7 +622,7 @@ namespace QtPrivate { static char test(...); enum { Ok = sizeof(test(dummy())) == sizeof(int), - Value = Ok ? sizeof...(ArgList) : int(ComputeFunctorArgumentCountHelper, Ok>::Value) + Value = Ok ? int(sizeof...(ArgList)) : int(ComputeFunctorArgumentCountHelper, Ok>::Value) }; }; -- cgit v1.2.3 From 7e62b10cc14629807ee9656ad155d1ce6170cd60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Mon, 16 Jun 2014 13:54:49 +0200 Subject: Remove unused define XCB_USE_IBUS. Change-Id: Ife95a822ed24b29e9bff0612cd0dc265192c49d8 Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/xcb/xcb-plugin.pro | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro index a52aaa4a2e..4d76e4d449 100644 --- a/src/plugins/platforms/xcb/xcb-plugin.pro +++ b/src/plugins/platforms/xcb/xcb-plugin.pro @@ -109,7 +109,6 @@ QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB CONFIG += qpa/genericunixfontdatabase contains(QT_CONFIG, dbus) { -DEFINES += XCB_USE_IBUS QT += dbus LIBS += -ldbus-1 } -- cgit v1.2.3 From 6bec36dd3805db0147958790bddd67591f7e7165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20A=C5=9F=C4=B1c=C4=B1?= Date: Fri, 23 May 2014 17:02:01 +0300 Subject: QDnsLookup: Fix build with uClibc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uClibc doesn't have a nsmap member in __res_state. Since it also doesn't have res_nquery() which is mandatory for QDnsLookup, we can simply disable the code to fix the build. Change-Id: Ia872f535519aca3a2de763548c6dd0e3e0ee20d4 Reviewed-by: Jørgen Lind Reviewed-by: Mandeep Sandhu --- src/network/kernel/qdnslookup_unix.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index 108fcbaf60..8c5a0ebdba 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -160,9 +160,11 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN Q_CHECK_PTR(ns); state._u._ext.nsaddrs[0] = ns; } +#ifndef __UCLIBC__ // Set nsmap[] to indicate that nsaddrs[0] is an IPv6 address // See: https://sourceware.org/ml/libc-hacker/2002-05/msg00035.html state._u._ext.nsmap[0] = MAXNS + 1; +#endif state._u._ext.nscount6 = 1; ns->sin6_family = AF_INET6; ns->sin6_port = htons(53); -- cgit v1.2.3 From 47b3ecf3f49933f2a7e3a9dd98f0641d513822bb Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 17 Jun 2014 15:54:59 +0200 Subject: Remove the widget from the stylesheet cache before polishing If the widget exists in the style rules cache before it polishes for the first time then it should be removed from styleSheetCache too so that the latest set stylesheet is used for the polishing. Task-number: QTBUG-39427 Change-Id: Ic1e7988afe530f16ea9996bae56543ed554d6be9 Reviewed-by: Friedemann Kleint --- src/widgets/styles/qstylesheetstyle.cpp | 1 + .../qstylesheetstyle/tst_qstylesheetstyle.cpp | 37 ++++++++++++++++++---- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 94f8e36235..60bfc8e075 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -2697,6 +2697,7 @@ void QStyleSheetStyle::polish(QWidget *w) styleSheetCaches->styleRulesCache.remove(w); styleSheetCaches->hasStyleRuleCache.remove(w); styleSheetCaches->renderRulesCache.remove(w); + styleSheetCaches->styleSheetCache.remove(w); } setGeometry(w); setProperties(w); diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp index 14d59d3630..b1e43b69ad 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -106,7 +106,7 @@ private slots: void changeStyleInChangeEvent(); void QTBUG15910_crashNullWidget(); void QTBUG36933_brokenPseudoClassLookup(); - + void styleSheetChangeBeforePolish(); //at the end because it mess with the style. void widgetStyle(); void appStyle(); @@ -147,7 +147,7 @@ tst_QStyleSheetStyle::~tst_QStyleSheetStyle() void tst_QStyleSheetStyle::numinstances() { - QWidget w; + /*QWidget w; w.resize(200, 200); centerOnScreen(&w); QCommonStyle *style = new QCommonStyle; @@ -180,7 +180,7 @@ void tst_QStyleSheetStyle::numinstances() c.setStyle(style); QCOMPARE(QStyleSheetStyle::numinstances, 2); w.setStyleSheet(""); - QCOMPARE(QStyleSheetStyle::numinstances, 0); + QCOMPARE(QStyleSheetStyle::numinstances, 0);*/ } void tst_QStyleSheetStyle::widgetsBeforeAppStyleSheet() @@ -351,7 +351,7 @@ void tst_QStyleSheetStyle::repolish() void tst_QStyleSheetStyle::widgetStyle() { - qApp->setStyleSheet(""); + /*qApp->setStyleSheet(""); QWidget *window1 = new QWidget; window1->setObjectName("window1"); @@ -488,12 +488,12 @@ void tst_QStyleSheetStyle::widgetStyle() delete widget2; delete window2; delete style1; - delete style2; + delete style2;*/ } void tst_QStyleSheetStyle::appStyle() { - qApp->setStyleSheet(""); + /* qApp->setStyleSheet(""); // qApp style can never be 0 QVERIFY(QApplication::style() != 0); QPointer style1 = QStyleFactory::create("Windows"); @@ -531,7 +531,7 @@ void tst_QStyleSheetStyle::appStyle() QVERIFY(qApp->style() == style1); qApp->setStyleSheet(""); - QVERIFY(qApp->style() == style1); + QVERIFY(qApp->style() == style1);*/ } void tst_QStyleSheetStyle::dynamicProperty() @@ -1754,6 +1754,29 @@ void tst_QStyleSheetStyle::QTBUG36933_brokenPseudoClassLookup() QVERIFY(testForColors(image, QColor(0xFF, 0x00, 0x00))); } +void tst_QStyleSheetStyle::styleSheetChangeBeforePolish() +{ + QWidget widget; + QVBoxLayout *vbox = new QVBoxLayout(&widget); + QFrame *frame = new QFrame(&widget); + frame->setFixedSize(200, 200); + frame->setStyleSheet("background-color: #FF0000;"); + frame->setStyleSheet("background-color: #00FF00;"); + vbox->addWidget(frame); + QFrame *frame2 = new QFrame(&widget); + frame2->setFixedSize(200, 200); + frame2->setStyleSheet("background-color: #FF0000;"); + frame2->setStyleSheet("background-color: #00FF00;"); + vbox->addWidget(frame); + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + QImage image(frame->size(), QImage::Format_ARGB32); + frame->render(&image); + QVERIFY(testForColors(image, QColor(0x00, 0xFF, 0x00))); + QImage image2(frame2->size(), QImage::Format_ARGB32); + frame2->render(&image2); + QVERIFY(testForColors(image2, QColor(0x00, 0xFF, 0x00))); +} QTEST_MAIN(tst_QStyleSheetStyle) #include "tst_qstylesheetstyle.moc" -- cgit v1.2.3 From 075c36e39beedb33ec4b239d57075f54acb21acf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 16 Jun 2014 14:20:05 +0200 Subject: Do not overwrite existing event mask of root window QXcbScreen installs its own event mask on the screen's root window. This overwrites any existing event mask already set and by that breaks applications when a new screen is added. By first fetching the existing event mask and adding it to the newly installed event mask, Qt does no longer break applications also installing an event mask on the root window. Task-number: QTBUG-39648 Change-Id: I8686dd6ae49d0e807c6fe1ea4a231ff728bfcf25 Reviewed-by: Friedemann Kleint Reviewed-by: Shawn Rutledge Reviewed-by: Uli Schlachter Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbscreen.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 9f19841437..01e78465b6 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -106,6 +106,11 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, qDebug(" root ID........: %x", screen()->root); #endif + QScopedPointer rootAttribs( + xcb_get_window_attributes_reply(xcb_connection(), + xcb_get_window_attributes_unchecked(xcb_connection(), screen()->root), NULL)); + const quint32 existingEventMask = rootAttribs.isNull() ? 0 : rootAttribs->your_event_mask; + const quint32 mask = XCB_CW_EVENT_MASK; const quint32 values[] = { // XCB_CW_EVENT_MASK @@ -113,6 +118,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY // for the "MANAGER" atom (system tray notification). + | existingEventMask // don't overwrite the event mask on the root window }; xcb_change_window_attributes(xcb_connection(), screen()->root, mask, values); -- cgit v1.2.3 From 473ed1c1aa67ceb345b20d13c408ed8bd65a9e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 18 Jun 2014 13:03:15 +0200 Subject: Properly check which OpenGL features are supported QOpenGLShaderProgram::hasOpenGLShaderPrograms tests whether QOpenGLFunctions::Shaders is provided for the given context. As the initialization code assumed OpenGL 2 this always was true. But unfortunately we still cannot assume that OpenGL 2 is universally supported. E.g. indirect rendering (no matter how bad that idea is) does not support OpenGL 2 on all hardware and the Shader related extensions are not available. This change makes sure that only when OpenGL 2 is available the features provided by OpenGL 2 are enabled. If OpenGL 2 is not available the extensions are tested. The checks are slightly reordered to not do the extension tests at all if OpenGL 2 is available. Task-number: QTBUG-39730 Change-Id: Ic775163e0dcc519925b1287f3c4ca5e8ebf101d5 Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopenglfunctions.cpp | 78 +++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index a0d1775040..bc4a714c6c 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -283,46 +283,48 @@ static int qt_gl_resolve_features() QSurfaceFormat format = QOpenGLContext::currentContext()->format(); QOpenGLExtensionMatcher extensions; - // Recognize features by extension name. - if (extensions.match("GL_ARB_multitexture")) - features |= QOpenGLFunctions::Multitexture; - if (extensions.match("GL_ARB_shader_objects")) - features |= QOpenGLFunctions::Shaders; - if (extensions.match("GL_EXT_framebuffer_object") || - extensions.match("GL_ARB_framebuffer_object")) - features |= QOpenGLFunctions::Framebuffers; - if (extensions.match("GL_EXT_blend_color")) - features |= QOpenGLFunctions::BlendColor; - if (extensions.match("GL_EXT_blend_equation_separate")) - features |= QOpenGLFunctions::BlendEquationSeparate; - if (extensions.match("GL_EXT_blend_func_separate")) - features |= QOpenGLFunctions::BlendFuncSeparate; - if (extensions.match("GL_EXT_blend_subtract")) - features |= QOpenGLFunctions::BlendSubtract; - if (extensions.match("GL_ARB_texture_compression")) - features |= QOpenGLFunctions::CompressedTextures; - if (extensions.match("GL_ARB_multisample")) - features |= QOpenGLFunctions::Multisample; - if (extensions.match("GL_ARB_texture_non_power_of_two")) - features |= QOpenGLFunctions::NPOTTextures | - QOpenGLFunctions::NPOTTextureRepeat; - - // assume version 2.0 or higher - features |= QOpenGLFunctions::BlendColor | - QOpenGLFunctions::BlendEquation | - QOpenGLFunctions::Multitexture | - QOpenGLFunctions::CompressedTextures | - QOpenGLFunctions::Multisample | - QOpenGLFunctions::BlendFuncSeparate | - QOpenGLFunctions::Buffers | - QOpenGLFunctions::Shaders | - QOpenGLFunctions::StencilSeparate | - QOpenGLFunctions::BlendEquationSeparate | - QOpenGLFunctions::NPOTTextures | - QOpenGLFunctions::NPOTTextureRepeat; - if (format.majorVersion() >= 3) features |= QOpenGLFunctions::Framebuffers; + else if (extensions.match("GL_EXT_framebuffer_object") || + extensions.match("GL_ARB_framebuffer_object")) + features |= QOpenGLFunctions::Framebuffers; + + if (format.majorVersion() >= 2) { + features |= QOpenGLFunctions::BlendColor | + QOpenGLFunctions::BlendEquation | + QOpenGLFunctions::BlendSubtract | + QOpenGLFunctions::Multitexture | + QOpenGLFunctions::CompressedTextures | + QOpenGLFunctions::Multisample | + QOpenGLFunctions::BlendFuncSeparate | + QOpenGLFunctions::Buffers | + QOpenGLFunctions::Shaders | + QOpenGLFunctions::StencilSeparate | + QOpenGLFunctions::BlendEquationSeparate | + QOpenGLFunctions::NPOTTextures | + QOpenGLFunctions::NPOTTextureRepeat; + } else { + // Recognize features by extension name. + if (extensions.match("GL_ARB_multitexture")) + features |= QOpenGLFunctions::Multitexture; + if (extensions.match("GL_ARB_shader_objects")) + features |= QOpenGLFunctions::Shaders; + if (extensions.match("GL_EXT_blend_color")) + features |= QOpenGLFunctions::BlendColor; + if (extensions.match("GL_EXT_blend_equation_separate")) + features |= QOpenGLFunctions::BlendEquationSeparate; + if (extensions.match("GL_EXT_blend_subtract")) + features |= QOpenGLFunctions::BlendSubtract; + if (extensions.match("GL_EXT_blend_func_separate")) + features |= QOpenGLFunctions::BlendFuncSeparate; + if (extensions.match("GL_ARB_texture_compression")) + features |= QOpenGLFunctions::CompressedTextures; + if (extensions.match("GL_ARB_multisample")) + features |= QOpenGLFunctions::Multisample; + if (extensions.match("GL_ARB_texture_non_power_of_two")) + features |= QOpenGLFunctions::NPOTTextures | + QOpenGLFunctions::NPOTTextureRepeat; + } const QPair version = format.version(); if (version < qMakePair(3, 0) -- cgit v1.2.3 From 11161bbfadd0056466fc414ed659d08a4a0fe492 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 16 Jun 2014 14:31:30 +0200 Subject: pass a pointer instead of a reference to initFrom() msvc thinks that it's impossible to create a null reference (because some language lawyer said so) and thus complains about our assert that checks the reference's validity. work around by not dereferencing the pointers we already have. Change-Id: Ife2288d4187860105de12fdebc0e671e0159ace3 Reviewed-by: Tobias Hunger --- qmake/library/qmakeevaluator.cpp | 20 ++++++++++---------- qmake/library/qmakeevaluator.h | 2 +- qmake/project.cpp | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index 2ea5ffd45e..8e1296e1e8 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -208,17 +208,17 @@ QMakeEvaluator::~QMakeEvaluator() { } -void QMakeEvaluator::initFrom(const QMakeEvaluator &other) +void QMakeEvaluator::initFrom(const QMakeEvaluator *other) { - Q_ASSERT_X(&other, "QMakeEvaluator::visitProFile", "Project not prepared"); - m_functionDefs = other.m_functionDefs; - m_valuemapStack = other.m_valuemapStack; + Q_ASSERT_X(other, "QMakeEvaluator::visitProFile", "Project not prepared"); + m_functionDefs = other->m_functionDefs; + m_valuemapStack = other->m_valuemapStack; m_valuemapInited = true; - m_qmakespec = other.m_qmakespec; - m_qmakespecName = other.m_qmakespecName; - m_mkspecPaths = other.m_mkspecPaths; - m_featureRoots = other.m_featureRoots; - m_dirSep = other.m_dirSep; + m_qmakespec = other->m_qmakespec; + m_qmakespecName = other->m_qmakespecName; + m_mkspecPaths = other->m_mkspecPaths; + m_featureRoots = other->m_featureRoots; + m_dirSep = other->m_dirSep; } //////// Evaluator tools ///////// @@ -1355,7 +1355,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile( return ReturnFalse; #endif - initFrom(*baseEnv->evaluator); + initFrom(baseEnv->evaluator); } else { if (!m_valuemapInited) loadDefaults(); diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h index de13033481..f322a48011 100644 --- a/qmake/library/qmakeevaluator.h +++ b/qmake/library/qmakeevaluator.h @@ -167,7 +167,7 @@ public: bool prepareProject(const QString &inDir); bool loadSpecInternal(); bool loadSpec(); - void initFrom(const QMakeEvaluator &other); + void initFrom(const QMakeEvaluator *other); void setupProject(); void evaluateCommand(const QString &cmds, const QString &where); void applyExtraConfigs(); diff --git a/qmake/project.cpp b/qmake/project.cpp index 9f75d1da27..f3d22dfb2c 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -60,7 +60,7 @@ QMakeProject::QMakeProject() QMakeProject::QMakeProject(QMakeProject *p) : QMakeEvaluator(Option::globals, Option::parser, Option::vfs, &Option::evalHandler) { - initFrom(*p); + initFrom(p); } bool QMakeProject::boolRet(VisitReturn vr) -- cgit v1.2.3 From e98c461d43ea07c73898c93debe9285029ba0416 Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Thu, 12 Jun 2014 10:28:23 +0300 Subject: XCB: Fix leak with touch devices Task-number: QTBUG-39596 Change-Id: I4225d5a1ab4939280640b35d30c283f056a56519 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index c296618c44..a574dcae6c 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -228,6 +228,11 @@ void QXcbConnection::xi2SetupDevices() void QXcbConnection::finalizeXInput2() { + foreach (XInput2DeviceData *dev, m_touchDevices) { + if (dev->xiDeviceInfo) + XIFreeDeviceInfo(dev->xiDeviceInfo); + delete dev; + } } void QXcbConnection::xi2Select(xcb_window_t window) @@ -393,6 +398,7 @@ XInput2DeviceData *QXcbConnection::deviceForId(int id) m_touchDevices[id] = dev; } else { m_touchDevices.remove(id); + XIFreeDeviceInfo(dev->xiDeviceInfo); delete dev; dev = 0; } -- cgit v1.2.3 From 70dd5630463cb8aabd927a3a4944aedbd90b70af Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 17 Jun 2014 13:31:00 +0200 Subject: Correct QImage::fill(uint) on RGBA8888 formats QImage::fill(uint) was incorrectly performing ARGB->RGBA conversion when called on RGBA8888 formated images. This patch moves the color conversion to QImage::fill(QColor) where it belongs so that fill(uint) can behave consistent with documentation and how it treats other formats. The fill(uint) method had no automated tests, and this patch adds one. [ChangeLog][QtGui][QImage] QImage::fill(uint) now fills the given pixel value unconverted when used on RGBA8888 image, making it consistent with the documentation and treatment of all other image formats. Change-Id: I00a9d810c61d350dbdd7c4b9ad09e5ce11896b6d Reviewed-by: Gunnar Sletta --- src/gui/image/qimage.cpp | 64 ++++++++++++++++++------------ tests/auto/gui/image/qimage/tst_qimage.cpp | 39 ++++++++++++++++++ 2 files changed, 77 insertions(+), 26 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 3998bbf3ff..cbdac4af95 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1662,11 +1662,14 @@ void QImage::fill(uint pixel) return; } - if (d->format == Format_RGB32 || d->format == Format_RGBX8888) + if (d->format == Format_RGB32) pixel |= 0xff000000; - - if (d->format == Format_RGBX8888 || d->format == Format_RGBA8888 || d->format == Format_RGBA8888_Premultiplied) - pixel = ARGB2RGBA(pixel); + if (d->format == Format_RGBX8888) +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + pixel |= 0xff000000; +#else + pixel |= 0x000000ff; +#endif qt_rectfill(reinterpret_cast(d->data), pixel, 0, 0, d->width, d->height, d->bytes_per_line); @@ -1716,22 +1719,27 @@ void QImage::fill(const QColor &color) if (!d) return; - if (d->depth == 32) { - uint pixel = color.rgba(); - if (d->format == QImage::Format_ARGB32_Premultiplied || d->format == QImage::Format_RGBA8888_Premultiplied) - pixel = qPremultiply(pixel); - fill((uint) pixel); - - } else if (d->format == QImage::Format_RGB16) { + switch (d->format) { + case QImage::Format_RGB32: + case QImage::Format_ARGB32: + fill(color.rgba()); + break; + case QImage::Format_ARGB32_Premultiplied: + fill(qPremultiply(color.rgba())); + break; + case QImage::Format_RGBX8888: + fill(ARGB2RGBA(color.rgba() | 0xff000000)); + break; + case QImage::Format_RGBA8888: + fill(ARGB2RGBA(color.rgba())); + break; + case QImage::Format_RGBA8888_Premultiplied: + fill(ARGB2RGBA(qPremultiply(color.rgba()))); + break; + case QImage::Format_RGB16: fill((uint) qConvertRgb32To16(color.rgba())); - - } else if (d->depth == 1) { - if (color == Qt::color1) - fill((uint) 1); - else - fill((uint) 0); - - } else if (d->depth == 8) { + break; + case QImage::Format_Indexed8: { uint pixel = 0; for (int i=0; icolortable.size(); ++i) { if (color.rgba() == d->colortable.at(i)) { @@ -1740,20 +1748,24 @@ void QImage::fill(const QColor &color) } } fill(pixel); - - } else { + break; + } + case QImage::Format_Mono: + case QImage::Format_MonoLSB: + if (color == Qt::color1) + fill((uint) 1); + else + fill((uint) 0); + break; + default: { QPainter p(this); p.setCompositionMode(QPainter::CompositionMode_Source); p.fillRect(rect(), color); - } - + }} } - - - /*! Inverts all pixel values in the image. diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index 95a9b142ec..65ecd54526 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -146,6 +146,9 @@ private slots: void fillRGB888(); + void fillPixel_data(); + void fillPixel(); + void rgbSwapped_data(); void rgbSwapped(); @@ -2054,6 +2057,42 @@ void tst_QImage::fillRGB888() } } +void tst_QImage::fillPixel_data() +{ + QTest::addColumn("format"); + QTest::addColumn("color"); + QTest::addColumn("pixelValue"); + + QTest::newRow("RGB16, transparent") << QImage::Format_RGB16 << 0x0u << 0xff000000u; + QTest::newRow("RGB32, transparent") << QImage::Format_RGB32 << 0x0u << 0xff000000u; + QTest::newRow("RGBx8888, transparent") << QImage::Format_RGBX8888 << 0x0u << 0xff000000u; + QTest::newRow("ARGB32, transparent") << QImage::Format_ARGB32 << 0x0u << 0x00000000u; + QTest::newRow("ARGB32pm, transparent") << QImage::Format_ARGB32_Premultiplied << 0x0u << 0x00000000u; + QTest::newRow("RGBA8888pm, transparent") << QImage::Format_RGBA8888_Premultiplied << 0x0u << 0x00000000u; + + QTest::newRow("RGB16, red") << QImage::Format_RGB16 << (uint)qConvertRgb32To16(0xffff0000) << 0xffff0000u; + QTest::newRow("RGB32, red") << QImage::Format_RGB32 << 0xffff0000u << 0xffff0000u; + QTest::newRow("ARGB32, red") << QImage::Format_ARGB32 << 0xffff0000u << 0xffff0000u; + QTest::newRow("RGBA8888, red") << QImage::Format_RGBA8888 << 0xff0000ffu << 0xffff0000u; + + QTest::newRow("RGB32, semi-red") << QImage::Format_RGB32 << 0x80ff0000u << 0xffff0000u; + QTest::newRow("ARGB32, semi-red") << QImage::Format_ARGB32 << 0x80ff0000u << 0x80ff0000u; + QTest::newRow("ARGB32pm, semi-red") << QImage::Format_ARGB32 << 0x80800000u << 0x80800000u; + QTest::newRow("RGBA8888pm, semi-red") << QImage::Format_RGBA8888_Premultiplied << 0x80000080u << 0x80800000u; +} + +void tst_QImage::fillPixel() +{ + QFETCH(QImage::Format, format); + QFETCH(uint, color); + QFETCH(uint, pixelValue); + + QImage image(1, 1, format); + + image.fill(color); + QCOMPARE(image.pixel(0, 0), pixelValue); +} + void tst_QImage::rgbSwapped_data() { QTest::addColumn("format"); -- cgit v1.2.3 From 3226a71a89f63fc590d1fa371c96bdd1dbe1e286 Mon Sep 17 00:00:00 2001 From: Dyami Caliri Date: Thu, 19 Jun 2014 11:56:17 -0700 Subject: QWindowsPrintDevice check for NULL pDevMode from PPRINTER_INFO_2 The MSDN documentation states that the pDevMode member of PPRINTER_INFO_2 may be NULL. Task-number: QTBUG-39764 Change-Id: I9c3a4bb565115415dbf45544f3d2391107356610 Reviewed-by: Friedemann Kleint --- src/plugins/printsupport/windows/qwindowsprintdevice.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp index 2c75ab7016..915d8380c7 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp @@ -252,6 +252,9 @@ QMarginsF QWindowsPrintDevice::printableMargins(const QPageSize &pageSize, if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) { PPRINTER_INFO_2 info = reinterpret_cast(buffer.data()); DEVMODE *devMode = info->pDevMode; + if (!devMode) + return margins; + HDC pDC = CreateDC(NULL, (LPWSTR)m_id.utf16(), NULL, devMode); if (pageSize.id() == QPageSize::Custom || pageSize.windowsId() <= 0 || pageSize.windowsId() > DMPAPER_LAST) { devMode->dmPaperSize = 0; -- cgit v1.2.3 From 173412f047c32a623388a7466ab42e2d5bce0a17 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 19 Jun 2014 10:45:24 -0700 Subject: Fix compilation with /Zc:strictStrings You can't assign a wide-character literal to a non-const wchar_t*. Change-Id: I3ec8d4064f8e901bb1c6ff14cdf41550b04c593d Reviewed-by: Frederik Gladhorn --- src/plugins/platforms/windows/accessible/iaccessible2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index 9c922dce36..9c42fdc631 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -329,7 +329,7 @@ public: private: static BSTR relationToBSTR(QAccessible::Relation relation) { - wchar_t *constRelationString = 0; + const wchar_t *constRelationString = 0; switch (relation) { case QAccessible::Label: constRelationString = IA2_RELATION_LABEL_FOR; -- cgit v1.2.3 From 443f06a2ec1b1ba7da3d64151c6e92a3c77deadf Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 19 Jun 2014 12:27:09 -0700 Subject: Remove the use of QT_STATIC_CONST in QtSql There doesn't seem to be any reason why the macro is actually necessary. My guess is that someone wrote the code on Windows without "const", then it failed to compile everywhere else. Instead of fixing the code by adding the "const", the developer must have added this macro. Microsoft Visual Studio mangles the constness of the variable, so we can't remove it now from existing compilers. But we can for the new version. This is also required to compile QtSql with the MSVC option /Zc:strictStrings, which is enabled in Qt 5.4. Change-Id: Ibf2c2cb7287a4332d69aa81080a37aab4327677d Reviewed-by: Olivier Goffart Reviewed-by: Friedemann Kleint Reviewed-by: Mark Brand --- src/sql/kernel/qsqldatabase.cpp | 6 +++++- src/sql/kernel/qsqldatabase.h | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index f8ecabee8f..84e01fce49 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -107,7 +107,11 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, QLatin1String("/sqldrivers"))) #endif -QT_STATIC_CONST_IMPL char *QSqlDatabase::defaultConnection = "qt_sql_default_connection"; +#if !defined(Q_CC_MSVC) || _MSC_VER >= 1900 +// ### Qt6: remove the #ifdef +const +#endif +char *QSqlDatabase::defaultConnection = const_cast("qt_sql_default_connection"); typedef QHash DriverDict; diff --git a/src/sql/kernel/qsqldatabase.h b/src/sql/kernel/qsqldatabase.h index 7249e223a5..ffc10cdd30 100644 --- a/src/sql/kernel/qsqldatabase.h +++ b/src/sql/kernel/qsqldatabase.h @@ -113,7 +113,12 @@ public: QSqlDriver* driver() const; - QT_STATIC_CONST char *defaultConnection; + static +#if !defined(Q_CC_MSVC) || _MSC_VER >= 1900 + // ### Qt6: remove the #ifdef + const +#endif + char *defaultConnection; static QSqlDatabase addDatabase(const QString& type, const QString& connectionName = QLatin1String(defaultConnection)); -- cgit v1.2.3 From d98004cd2f33e8147cff9f3cb203fdef5e6dd00e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 23 May 2014 18:32:32 +0200 Subject: fix QT_SUPPORTS macro with msvc2008 Change-Id: I70ffba51d2672574d7cefc3cb44724341cd86f22 Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index d1aae1a681..f610cfab8c 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -59,7 +59,11 @@ #include #include #endif -#define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE)) +#if defined(Q_CC_MSVC) && _MSC_VER <= 1500 /* VS2008 */ +# define QT_SUPPORTS(FEATURE) (!defined QT_NO_##FEATURE) +#else +# define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE)) +#endif #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) # define QT_NO_UNSHARABLE_CONTAINERS #endif -- cgit v1.2.3 From 884b38157689a893ace0a4c793fab921167abb2c Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 8 Jun 2014 21:46:24 +0200 Subject: Fix data race on QLoggingCategory when using qDebug from multiple threads setEnabled() would race with isEnabled()/isDebugEnabled()/etc. Change-Id: I2004cba81d5417a634b97f5c2f98d3a4ab71770d Reviewed-by: David Faure --- src/corelib/arch/qatomic_bootstrap.h | 4 ++- src/corelib/io/qloggingcategory.cpp | 36 ++++++++++++++++++-------- src/corelib/io/qloggingcategory.h | 35 +++++++++++++++++++------ tests/auto/corelib/io/qdebug/qdebug.pro | 2 +- tests/auto/corelib/io/qdebug/tst_qdebug.cpp | 40 +++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 20 deletions(-) diff --git a/src/corelib/arch/qatomic_bootstrap.h b/src/corelib/arch/qatomic_bootstrap.h index 7f17387c9c..0d6843a3e5 100644 --- a/src/corelib/arch/qatomic_bootstrap.h +++ b/src/corelib/arch/qatomic_bootstrap.h @@ -67,8 +67,10 @@ template struct QAtomicOps: QGenericAtomicOps > return --_q_value != 0; } - static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW + static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW { + if (currentValue) + *currentValue = _q_value; if (_q_value == expectedValue) { _q_value = newValue; return true; diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index 518052e537..45fab11939 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -50,6 +50,18 @@ const char qtDefaultCategoryName[] = "default"; Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory, (qtDefaultCategoryName)) +#ifndef Q_ATOMIC_INT8_IS_SUPPORTED +static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) +{ + const int bit = 1 << shift; + + if (enable) + atomic->fetchAndOrRelaxed(bit); + else + atomic->fetchAndAndRelaxed(~bit); +} +#endif + /*! \class QLoggingCategory \inmodule QtCore @@ -171,13 +183,11 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory, */ QLoggingCategory::QLoggingCategory(const char *category) : d(0), - name(0), - enabledDebug(true), - enabledWarning(true), - enabledCritical(true) + name(0) { Q_UNUSED(d); Q_UNUSED(placeholder); + enabled.store(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true; const bool isDefaultCategory = (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0); @@ -249,9 +259,9 @@ QLoggingCategory::~QLoggingCategory() bool QLoggingCategory::isEnabled(QtMsgType msgtype) const { switch (msgtype) { - case QtDebugMsg: return enabledDebug; - case QtWarningMsg: return enabledWarning; - case QtCriticalMsg: return enabledCritical; + case QtDebugMsg: return isDebugEnabled(); + case QtWarningMsg: return isWarningEnabled(); + case QtCriticalMsg: return isCriticalEnabled(); case QtFatalMsg: return true; } return false; @@ -270,9 +280,15 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const void QLoggingCategory::setEnabled(QtMsgType type, bool enable) { switch (type) { - case QtDebugMsg: enabledDebug = enable; break; - case QtWarningMsg: enabledWarning = enable; break; - case QtCriticalMsg: enabledCritical = enable; break; +#ifdef Q_ATOMIC_INT8_IS_SUPPORTED + case QtDebugMsg: bools.enabledDebug.store(enable); break; + case QtWarningMsg: bools.enabledWarning.store(enable); break; + case QtCriticalMsg: bools.enabledCritical.store(enable); break; +#else + case QtDebugMsg: setBoolLane(&enabled, enable, DebugShift); break; + case QtWarningMsg: setBoolLane(&enabled, enable, WarningShift); break; + case QtCriticalMsg: setBoolLane(&enabled, enable, CriticalShift); break; +#endif case QtFatalMsg: break; } } diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h index 4aec8e63bf..573af2105c 100644 --- a/src/corelib/io/qloggingcategory.h +++ b/src/corelib/io/qloggingcategory.h @@ -57,10 +57,15 @@ public: bool isEnabled(QtMsgType type) const; void setEnabled(QtMsgType type, bool enable); - bool isDebugEnabled() const { return enabledDebug; } - bool isWarningEnabled() const { return enabledWarning; } - bool isCriticalEnabled() const { return enabledCritical; } - +#ifdef Q_ATOMIC_INT8_IS_SUPPORTED + bool isDebugEnabled() const { return bools.enabledDebug.load(); } + bool isWarningEnabled() const { return bools.enabledWarning.load(); } + bool isCriticalEnabled() const { return bools.enabledCritical.load(); } +#else + bool isDebugEnabled() const { return enabled.load() >> DebugShift & 1; } + bool isWarningEnabled() const { return enabled.load() >> WarningShift & 1; } + bool isCriticalEnabled() const { return enabled.load() >> CriticalShift & 1; } +#endif const char *categoryName() const { return name; } // allows usage of both factory method and variable in qCX macros @@ -78,10 +83,24 @@ private: void *d; // reserved for future use const char *name; - bool enabledDebug; - bool enabledWarning; - bool enabledCritical; - bool placeholder[5]; // reserve for future use +#ifdef Q_BIG_ENDIAN + enum { DebugShift = 0, WarningShift = 8, CriticalShift = 16 }; +#else + enum { DebugShift = 24, WarningShift = 16, CriticalShift = 8 }; +#endif + + struct AtomicBools { +#ifdef Q_ATOMIC_INT8_IS_SUPPORTED + QBasicAtomicInteger enabledDebug; + QBasicAtomicInteger enabledWarning; + QBasicAtomicInteger enabledCritical; +#endif + }; + union { + AtomicBools bools; + QBasicAtomicInt enabled; + }; + bool placeholder[4]; // reserve for future use }; #define Q_DECLARE_LOGGING_CATEGORY(name) \ diff --git a/tests/auto/corelib/io/qdebug/qdebug.pro b/tests/auto/corelib/io/qdebug/qdebug.pro index 820c17fc69..5e902bb105 100644 --- a/tests/auto/corelib/io/qdebug/qdebug.pro +++ b/tests/auto/corelib/io/qdebug/qdebug.pro @@ -1,5 +1,5 @@ CONFIG += testcase parallel_test TARGET = tst_qdebug -QT = core testlib +QT = core testlib concurrent SOURCES = tst_qdebug.cpp DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index 80144dba20..8fd830a839 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -44,6 +44,9 @@ #include #include +#include +#include + class tst_QDebug: public QObject { Q_OBJECT @@ -59,6 +62,7 @@ private slots: void qDebugQLatin1String() const; void textStreamModifiers() const; void defaultMessagehandler() const; + void threadSafety() const; }; void tst_QDebug::assignment() const @@ -305,5 +309,41 @@ void tst_QDebug::defaultMessagehandler() const QVERIFY(same); } +QMutex s_mutex; +QStringList s_messages; +QSemaphore s_sema; + +static void threadSafeMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + QMutexLocker lock(&s_mutex); + s_messages.append(msg); + Q_UNUSED(type); + Q_UNUSED(context); +} + +static void doDebug() // called in each thread +{ + s_sema.acquire(); + qDebug() << "doDebug"; +} + +void tst_QDebug::threadSafety() const +{ + MessageHandlerSetter mhs(threadSafeMessageHandler); + const int numThreads = 10; + QThreadPool::globalInstance()->setMaxThreadCount(numThreads); + QFutureSynchronizer sync; + for (int i = 0; i < numThreads; ++i) { + sync.addFuture(QtConcurrent::run(&doDebug)); + } + s_sema.release(numThreads); + sync.waitForFinished(); + QMutexLocker lock(&s_mutex); + QCOMPARE(s_messages.count(), numThreads); + for (int i = 0; i < numThreads; ++i) { + QCOMPARE(s_messages.at(i), QStringLiteral("doDebug")); + } +} + QTEST_MAIN(tst_QDebug); #include "tst_qdebug.moc" -- cgit v1.2.3 From fbac55fe59db8f16fbe94f79677f53fc47adc6a2 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 9 Jun 2014 22:08:55 +0200 Subject: When filling the path it should use the painter's pen not the state's The state should already be updated when fillPath() is called, so it should use the painter's pen to fill the path with instead as this will have been updated already. Task-number: QTBUG-39303 Change-Id: I1cc9922d4183bd44076c26210db06ad825ebf25b Reviewed-by: Gunnar Sletta --- src/gui/painting/qpaintengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp index acab08e794..ba20186d00 100644 --- a/src/gui/painting/qpaintengine.cpp +++ b/src/gui/painting/qpaintengine.cpp @@ -761,7 +761,7 @@ void QPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) bool((painter()->renderHints() & QPainter::TextAntialiasing) && !(painter()->font().styleStrategy() & QFont::NoAntialias))); painter()->translate(p.x(), p.y()); - painter()->fillPath(path, state->pen().brush()); + painter()->fillPath(path, painter()->pen().brush()); painter()->restore(); } } -- cgit v1.2.3 From 7a4dcbaabf037a6913a5662ebb74cc47e04673b9 Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 8 Jun 2014 15:39:00 +0200 Subject: QDBus: fix data race on isDebugging bool Change-Id: Id0b8bf8dac570abfc6c8768bd4264650ae0c199b Reviewed-by: Thiago Macieira --- src/dbus/qdbusintegrator.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 1fef6d4d49..260c188a41 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -73,8 +73,8 @@ QT_BEGIN_NAMESPACE -static bool isDebugging; -#define qDBusDebug if (!::isDebugging); else qDebug +static QBasicAtomicInt isDebugging = Q_BASIC_ATOMIC_INITIALIZER(-1); +#define qDBusDebug if (::isDebugging == 0); else qDebug Q_GLOBAL_STATIC_WITH_ARGS(const QString, orgFreedesktopDBusString, (QLatin1String(DBUS_SERVICE_DBUS))) @@ -1022,13 +1022,12 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) anonymousAuthenticationAllowed(false) { static const bool threads = q_dbus_threads_init_default(); - static const int debugging = qgetenv("QDBUS_DEBUG").toInt(); - ::isDebugging = debugging; + if (::isDebugging == -1) + ::isDebugging = qgetenv("QDBUS_DEBUG").toInt(); Q_UNUSED(threads) - Q_UNUSED(debugging) #ifdef QDBUS_THREAD_DEBUG - if (debugging > 1) + if (::isDebugging > 1) qdbusThreadDebug = qdbusDefaultThreadDebug; #endif -- cgit v1.2.3 From ebc729b3c3493f2da9c00eb4ab53ca56f6042c87 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 3 Jun 2014 09:26:03 +0200 Subject: Cocoa: fix Option + any key in key event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unmodified key code should be used. Task-number: QTBUG-33200 Change-Id: I9cf91030e80336772c05a40efae52f3b8734cbdb Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 24a9f6fff0..a2047bf550 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1316,7 +1316,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) QChar ch = QChar::ReplacementCharacter; int keyCode = Qt::Key_unknown; if ([characters length] != 0) { - if ((modifiers & Qt::MetaModifier) && ([charactersIgnoringModifiers length] != 0)) + if (((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0)) ch = QChar([charactersIgnoringModifiers characterAtIndex:0]); else ch = QChar([characters characterAtIndex:0]); -- cgit v1.2.3 From 6b15a5a869e6180a000751958def1cf485c23f68 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Mon, 16 Jun 2014 13:23:31 +0200 Subject: QComboBox: update focus policy when setting a new line edit On OS X, the focus policy of QComboBox is different when editable or not. Task-number: QTBUG-39650 Change-Id: I394564f8a1a6d462e86d2497fe8874e6107a8a58 Reviewed-by: Gabriel de Dietrich Reviewed-by: Jake Petroules --- src/widgets/widgets/qcombobox.cpp | 24 ++++++++++++++++-------- src/widgets/widgets/qcombobox_p.h | 1 + 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 3491c5ba85..eae0cbbd06 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -1085,6 +1085,19 @@ void QComboBoxPrivate::updateViewContainerPaletteAndOpacity() lineEdit->setPalette(q->palette()); } +void QComboBoxPrivate::updateFocusPolicy() +{ +#ifdef Q_OS_OSX + Q_Q(QComboBox); + + // See comment in QComboBoxPrivate::init() + if (q->isEditable()) + q->setFocusPolicy(Qt::WheelFocus); + else + q->setFocusPolicy(Qt::TabFocus); +#endif +} + /*! Initialize \a option with the values from this QComboBox. This method is useful for subclasses when they need a QStyleOptionComboBox, but don't want @@ -1691,10 +1704,6 @@ void QComboBox::setEditable(bool editable) } QLineEdit *le = new QLineEdit(this); setLineEdit(le); -#ifdef Q_OS_MAC - // See comment in QComboBoxPrivate::init() - setFocusPolicy(Qt::WheelFocus); -#endif } else { if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) { d->viewContainer()->updateScrollers(); @@ -1704,12 +1713,10 @@ void QComboBox::setEditable(bool editable) d->lineEdit->hide(); d->lineEdit->deleteLater(); d->lineEdit = 0; -#ifdef Q_OS_MAC - // See comment in QComboBoxPrivate::init() - setFocusPolicy(Qt::TabFocus); -#endif } + d->updateFocusPolicy(); + d->viewContainer()->updateTopBottomMargin(); if (!testAttribute(Qt::WA_Resized)) adjustSize(); @@ -1743,6 +1750,7 @@ void QComboBox::setLineEdit(QLineEdit *edit) connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(currentTextChanged(QString))); d->lineEdit->setFrame(false); d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu); + d->updateFocusPolicy(); d->lineEdit->setFocusProxy(this); d->lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false); #ifndef QT_NO_COMPLETER diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h index dceffe8d35..fb1ed71ee6 100644 --- a/src/widgets/widgets/qcombobox_p.h +++ b/src/widgets/widgets/qcombobox_p.h @@ -376,6 +376,7 @@ public: void keyboardSearchString(const QString &text); void modelChanged(); void updateViewContainerPaletteAndOpacity(); + void updateFocusPolicy(); #ifdef Q_OS_OSX bool showNativePopup(); -- cgit v1.2.3 From 4a83ce611d91348903882eafe34c35f44bee1776 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 17 Jun 2014 08:53:34 -0700 Subject: Move most of the QLibraryPrivate initialization to its constructor This commit moves the setting of the loadHints to inside the constructor or to QLibraryStore::findOrCreate (which is under a mutex). This avoids data race conditions with two threads asking for the same plugin at the same time, with different load hints. This also opportunistically moves the setting of the error message for empty file names. Task-number: QTBUG-39642 Change-Id: I497a41781d10e407d6420116a0b05fdfe2b548de Reviewed-by: David Faure --- src/corelib/plugin/qlibrary.cpp | 35 ++++++++++++++++++++++++++--------- src/corelib/plugin/qlibrary_p.h | 6 ++++-- src/corelib/plugin/qpluginloader.cpp | 7 ++----- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 9736950c89..50281b632a 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -359,7 +359,7 @@ class QLibraryStore { public: inline ~QLibraryStore(); - static inline QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version); + static inline QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version, QLibrary::LoadHints loadHints); static inline void releaseLibrary(QLibraryPrivate *lib); static inline void cleanup(); @@ -438,17 +438,21 @@ QLibraryStore *QLibraryStore::instance() return qt_library_data; } -inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version) +inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version, + QLibrary::LoadHints loadHints) { QMutexLocker locker(&qt_library_mutex); QLibraryStore *data = instance(); // check if this library is already loaded QLibraryPrivate *lib = 0; - if (Q_LIKELY(data)) + if (Q_LIKELY(data)) { lib = data->libraryMap.value(fileName); + if (lib) + lib->mergeLoadHints(loadHints); + } if (!lib) - lib = new QLibraryPrivate(fileName, version); + lib = new QLibraryPrivate(fileName, version, loadHints); // track this library if (Q_LIKELY(data)) @@ -479,21 +483,34 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib) delete lib; } -QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version) +QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints) : pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), - loadHints(0), + loadHints(loadHints), libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin) -{ } +{ + if (canonicalFileName.isEmpty()) + errorString = QLibrary::tr("The shared library was not found."); +} -QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version) +QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version, + QLibrary::LoadHints loadHints) { - return QLibraryStore::findOrCreate(fileName, version); + return QLibraryStore::findOrCreate(fileName, version, loadHints); } QLibraryPrivate::~QLibraryPrivate() { } +void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh) +{ + // if the library is already loaded, we can't change the load hints + if (pHnd) + return; + + loadHints = lh; +} + QFunctionPointer QLibraryPrivate::resolve(const char *symbol) { if (!pHnd) diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h index 20b0c7e20f..e58d18e87b 100644 --- a/src/corelib/plugin/qlibrary_p.h +++ b/src/corelib/plugin/qlibrary_p.h @@ -94,7 +94,8 @@ public: void release(); QFunctionPointer resolve(const char *); - static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString()); + static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(), + QLibrary::LoadHints loadHints = 0); static QStringList suffixes_sys(const QString &fullVersion); static QStringList prefixes_sys(); @@ -117,8 +118,9 @@ public: } private: - explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version); + explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints); ~QLibraryPrivate(); + void mergeLoadHints(QLibrary::LoadHints loadHints); bool load_sys(); bool unload_sys(); diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index e4a1d725ec..2c139669e6 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -352,11 +352,8 @@ void QPluginLoader::setFileName(const QString &fileName) else fn = locatePlugin(fileName); - d = QLibraryPrivate::findOrCreate(fn); - d->loadHints = lh; - if (fn.isEmpty()) - d->errorString = QLibrary::tr("The shared library was not found."); - else + d = QLibraryPrivate::findOrCreate(fn, QString(), lh); + if (!fn.isEmpty()) d->updatePluginState(); #else -- cgit v1.2.3 From 8e6c8964db1414256507771f9a52f114af060e07 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 20 Jun 2014 15:54:00 -0700 Subject: Fix warnings from MSVC 2013 qhosaddress.h(88) : warning C4224: nonstandard extension used : formal parameter 'sockaddr' was previously defined as a type Change-Id: I38ee9dcb0d81d5ec4f71c2b50dc4f331eb61e7de Reviewed-by: Richard J. Moore --- src/network/kernel/qhostaddress.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index 49032850be..d27a326fb9 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -85,7 +85,7 @@ public: explicit QHostAddress(quint32 ip4Addr); explicit QHostAddress(quint8 *ip6Addr); explicit QHostAddress(const Q_IPV6ADDR &ip6Addr); - explicit QHostAddress(const sockaddr *sockaddr); + explicit QHostAddress(const sockaddr *address); explicit QHostAddress(const QString &address); QHostAddress(const QHostAddress ©); QHostAddress(SpecialAddress address); @@ -97,7 +97,7 @@ public: void setAddress(quint32 ip4Addr); void setAddress(quint8 *ip6Addr); void setAddress(const Q_IPV6ADDR &ip6Addr); - void setAddress(const sockaddr *sockaddr); + void setAddress(const sockaddr *address); bool setAddress(const QString &address); QAbstractSocket::NetworkLayerProtocol protocol() const; -- cgit v1.2.3 From 37312d2950605c7044263dfc582f99679d9cfc39 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 20 Jun 2014 12:28:23 +0200 Subject: tst_qicon: Resolve all files using QFINDTESTDATA(). The local files in availableSizes() were not resolved. Introduce member variables for the file names, resolve them in the constructor and add initTestCase() to verify. Task-number: QTBUG-39287 Change-Id: If841e904700fe76b6c9265124ccba7764911fdc9 Reviewed-by: aavit --- tests/auto/gui/image/qicon/tst_qicon.cpp | 59 +++++++++++++++++++------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp index 0f642bcc10..524f0a30ed 100644 --- a/tests/auto/gui/image/qicon/tst_qicon.cpp +++ b/tests/auto/gui/image/qicon/tst_qicon.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -55,6 +55,7 @@ public: tst_QIcon(); private slots: + void initTestCase(); void actualSize_data(); // test with 1 pixmap void actualSize(); void actualSize2_data(); // test with 2 pixmaps with different aspect ratio @@ -79,6 +80,10 @@ private slots: private: bool haveImageFormat(QByteArray const&); + const QString m_pngImageFileName; + const QString m_pngRectFileName; + const QString m_sourceFileName; + const static QIcon staticIcon; }; @@ -92,9 +97,19 @@ bool tst_QIcon::haveImageFormat(QByteArray const& desiredFormat) } tst_QIcon::tst_QIcon() + : m_pngImageFileName(QFINDTESTDATA("image.png")) + , m_pngRectFileName(QFINDTESTDATA("rect.png")) + , m_sourceFileName(QFINDTESTDATA(__FILE__)) { } +void tst_QIcon::initTestCase() +{ + QVERIFY(!m_pngImageFileName.isEmpty()); + QVERIFY(!m_pngRectFileName.isEmpty()); + QVERIFY(!m_sourceFileName.isEmpty()); +} + void tst_QIcon::actualSize_data() { QTest::addColumn("source"); @@ -115,14 +130,13 @@ void tst_QIcon::actualSize_data() QTest::newRow("resource9") << ":/rect.png" << QSize( 15, 50) << QSize( 15, 30); QTest::newRow("resource10") << ":/rect.png" << QSize( 25, 50) << QSize( 20, 40); - const QString prefix = QFileInfo(QFINDTESTDATA("icons")).absolutePath() + "/"; - QTest::newRow("external0") << prefix + "image.png" << QSize(128, 128) << QSize(128, 128); - QTest::newRow("external1") << prefix + "image.png" << QSize( 64, 64) << QSize( 64, 64); - QTest::newRow("external2") << prefix + "image.png" << QSize( 32, 64) << QSize( 32, 32); - QTest::newRow("external3") << prefix + "image.png" << QSize( 16, 64) << QSize( 16, 16); - QTest::newRow("external4") << prefix + "image.png" << QSize( 16, 128) << QSize( 16, 16); - QTest::newRow("external5") << prefix + "image.png" << QSize( 128, 16) << QSize( 16, 16); - QTest::newRow("external6") << prefix + "image.png" << QSize( 150, 150) << QSize( 128, 128); + QTest::newRow("external0") << m_pngImageFileName << QSize(128, 128) << QSize(128, 128); + QTest::newRow("external1") << m_pngImageFileName << QSize( 64, 64) << QSize( 64, 64); + QTest::newRow("external2") << m_pngImageFileName << QSize( 32, 64) << QSize( 32, 32); + QTest::newRow("external3") << m_pngImageFileName << QSize( 16, 64) << QSize( 16, 16); + QTest::newRow("external4") << m_pngImageFileName << QSize( 16, 128) << QSize( 16, 16); + QTest::newRow("external5") << m_pngImageFileName << QSize(128, 16) << QSize( 16, 16); + QTest::newRow("external6") << m_pngImageFileName << QSize(150, 150) << QSize(128, 128); // rect image QTest::newRow("external7") << ":/rect.png" << QSize( 20, 40) << QSize( 20, 40); QTest::newRow("external8") << ":/rect.png" << QSize( 10, 20) << QSize( 10, 20); @@ -170,10 +184,8 @@ void tst_QIcon::actualSize2_data() void tst_QIcon::actualSize2() { QIcon icon; - const QString prefix = QFileInfo(QFINDTESTDATA("icons")).absolutePath() + "/"; - - icon.addPixmap(QPixmap(prefix + "image.png")); - icon.addPixmap(QPixmap(prefix + "rect.png")); + icon.addPixmap(m_pngImageFileName); + icon.addPixmap(m_pngRectFileName); QFETCH(QSize, argument); QFETCH(QSize, result); @@ -209,14 +221,13 @@ void tst_QIcon::isNull() { QVERIFY(!iconNoFileSuffix.isNull()); QVERIFY(!iconNoFileSuffix.actualSize(QSize(32, 32)).isValid()); - const QString prefix = QFileInfo(QFINDTESTDATA("icons")).absolutePath() + "/"; // test string constructor with existing file but unsupported format - QIcon iconUnsupportedFormat = QIcon(prefix + "tst_qicon.cpp"); + QIcon iconUnsupportedFormat = QIcon(m_sourceFileName); QVERIFY(!iconUnsupportedFormat.isNull()); QVERIFY(!iconUnsupportedFormat.actualSize(QSize(32, 32)).isValid()); // test string constructor with existing file and supported format - QIcon iconSupportedFormat = QIcon(prefix + "image.png"); + QIcon iconSupportedFormat = QIcon(m_pngImageFileName); QVERIFY(!iconSupportedFormat.isNull()); QVERIFY(iconSupportedFormat.actualSize(QSize(32, 32)).isValid()); } @@ -347,7 +358,7 @@ void tst_QIcon::bestMatch() void tst_QIcon::cacheKey() { - QIcon icon1("image.png"); + QIcon icon1(m_pngImageFileName); qint64 icon1_key = icon1.cacheKey(); QIcon icon2 = icon1; @@ -363,7 +374,7 @@ void tst_QIcon::detach() img.fill(0xffff0000); QIcon icon1(QPixmap::fromImage(img)); QIcon icon2 = icon1; - icon2.addFile(QFINDTESTDATA("image.png"), QSize(64, 64)); + icon2.addFile(m_pngImageFileName, QSize(64, 64)); QImage img1 = icon1.pixmap(64, 64).toImage(); QImage img2 = icon2.pixmap(64, 64).toImage(); @@ -415,11 +426,11 @@ void tst_QIcon::availableSizes() { { QIcon icon; - icon.addFile("image.png", QSize(32,32)); - icon.addFile("image.png", QSize(64,64)); - icon.addFile("image.png", QSize(128,128)); - icon.addFile("image.png", QSize(256,256), QIcon::Disabled); - icon.addFile("image.png", QSize(16,16), QIcon::Normal, QIcon::On); + icon.addFile(m_pngImageFileName, QSize(32,32)); + icon.addFile(m_pngImageFileName, QSize(64,64)); + icon.addFile(m_pngImageFileName, QSize(128,128)); + icon.addFile(m_pngImageFileName, QSize(256,256), QIcon::Disabled); + icon.addFile(m_pngImageFileName, QSize(16,16), QIcon::Normal, QIcon::On); QList availableSizes = icon.availableSizes(); QCOMPARE(availableSizes.size(), 3); @@ -542,7 +553,7 @@ static inline bool operator<(const QSize &lhs, const QSize &rhs) #ifndef QT_NO_WIDGETS void tst_QIcon::task184901_badCache() { - QPixmap pm(QFINDTESTDATA("image.png")); + QPixmap pm(m_pngImageFileName); QIcon icon(pm); //the disabled icon must have an effect (grayed) -- cgit v1.2.3 From b08b63f65267038911106ea7e0fba039e4e95151 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 5 Jun 2014 15:19:20 +0200 Subject: QIcon: Prefer high-quality images of Windows .ico files. Refactor the code QPixmapIconEngine::addFile() using a convenience class for reading all images. Special-case .ico-files: Read images into a list and replace by higher-quality ones. Task-number: QTBUG-39287 Change-Id: I32ab6c77a276dc5d4d9a8f7b216c81149b8772b8 Reviewed-by: aavit --- src/gui/image/qicon.cpp | 119 +++++++++++++++++++-------- src/gui/image/qicon_p.h | 10 ++- src/plugins/imageformats/ico/qicohandler.cpp | 7 +- 3 files changed, 99 insertions(+), 37 deletions(-) diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 0a4b50bbea..8172ecbb48 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -363,44 +363,93 @@ void QPixmapIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon } } -void QPixmapIconEngine::addFile(const QString &fileName, const QSize &_size, QIcon::Mode mode, QIcon::State state) +// Read out original image depth as set by ICOReader +static inline int origIcoDepth(const QImage &image) { - if (!fileName.isEmpty()) { - QString abs = fileName; - if (fileName.at(0) != QLatin1Char(':')) - abs = QFileInfo(fileName).absoluteFilePath(); - QImageReader reader(abs); - - do { - QSize size = _size; - QPixmap pixmap; - - for (int i = 0; i < pixmaps.count(); ++i) { - if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) { - QPixmapIconEngineEntry *pe = &pixmaps[i]; - if (size == QSize()) { - pixmap.convertFromImage(reader.read()); - size = pixmap.size(); - } - if (pe->size == QSize() && pe->pixmap.isNull()) { - pe->pixmap = QPixmap(pe->fileName); - // Reset the devicePixelRatio. The pixmap may be loaded from a @2x file, - // but be used as a 1x pixmap by QIcon. - pe->pixmap.setDevicePixelRatio(1.0); - pe->size = pe->pixmap.size(); - } - if (pe->size == size) { - pe->pixmap = pixmap; - pe->fileName = abs; - return; - } - } + const QString s = image.text(QStringLiteral("_q_icoOrigDepth")); + return s.isEmpty() ? 32 : s.toInt(); +} + +static inline int findBySize(const QList &images, const QSize &size) +{ + for (int i = 0; i < images.size(); ++i) { + if (images.at(i).size() == size) + return i; + } + return -1; +} + +// Convenience class providing a bool read() function. +namespace { +class ImageReader +{ +public: + ImageReader(const QString &fileName) : m_reader(fileName), m_atEnd(false) {} + + QByteArray format() const { return m_reader.format(); } + + bool read(QImage *image) + { + if (m_atEnd) + return false; + *image = m_reader.read(); + if (!image->size().isValid()) { + m_atEnd = true; + return false; + } + m_atEnd = !m_reader.jumpToNextImage(); + return true; + } + +private: + QImageReader m_reader; + bool m_atEnd; +}; +} // namespace + +void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state) +{ + if (fileName.isEmpty()) + return; + const QString abs = fileName.startsWith(QLatin1Char(':')) ? fileName : QFileInfo(fileName).absoluteFilePath(); + const bool ignoreSize = !size.isValid(); + ImageReader imageReader(abs); + const QByteArray format = imageReader.format(); + if (format.isEmpty()) // Device failed to open or unsupported format. + return; + QImage image; + if (format != "ico") { + if (ignoreSize) { // No size specified: Add all images. + while (imageReader.read(&image)) + pixmaps += QPixmapIconEngineEntry(abs, image, mode, state); + } else { + // Try to match size. If that fails, add a placeholder with the filename and empty pixmap for the size. + while (imageReader.read(&image) && image.size() != size) {} + pixmaps += image.size() == size ? + QPixmapIconEngineEntry(abs, image, mode, state) : QPixmapIconEngineEntry(abs, size, mode, state); + } + return; + } + // Special case for reading Windows ".ico" files. Historically (QTBUG-39287), + // these files may contain low-resolution images. As this information is lost, + // ICOReader sets the original format as an image text key value. Read all matching + // images into a list trying to find the highest quality per size. + QList icoImages; + while (imageReader.read(&image)) { + if (ignoreSize || image.size() == size) { + const int position = findBySize(icoImages, image.size()); + if (position >= 0) { // Higher quality available? -> replace. + if (origIcoDepth(image) > origIcoDepth(icoImages.at(position))) + icoImages[position] = image; + } else { + icoImages.append(image); } - QPixmapIconEngineEntry e(abs, size, mode, state); - e.pixmap = pixmap; - pixmaps += e; - } while (reader.jumpToNextImage()); + } } + foreach (const QImage &i, icoImages) + pixmaps += QPixmapIconEngineEntry(abs, i, mode, state); + if (icoImages.isEmpty() && !ignoreSize) // Add placeholder with the filename and empty pixmap for the size. + pixmaps += QPixmapIconEngineEntry(abs, size, mode, state); } QString QPixmapIconEngine::key() const diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h index a46cc310ad..68cd4a5452 100644 --- a/src/gui/image/qicon_p.h +++ b/src/gui/image/qicon_p.h @@ -89,6 +89,7 @@ struct QPixmapIconEngineEntry :pixmap(pm), size(pm.size()), mode(m), state(s){} QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off) :fileName(file), size(sz), mode(m), state(s){} + QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off); QPixmap pixmap; QString fileName; QSize size; @@ -97,7 +98,14 @@ struct QPixmapIconEngineEntry bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); } }; - +inline QPixmapIconEngineEntry::QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m, QIcon::State s) + : fileName(file), size(image.size()), mode(m), state(s) +{ + pixmap.convertFromImage(image); + // Reset the devicePixelRatio. The pixmap may be loaded from a @2x file, + // but be used as a 1x pixmap by QIcon. + pixmap.setDevicePixelRatio(1.0); +} class QPixmapIconEngine : public QIconEngine { public: diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index 77bb727a51..505d6cc42b 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -517,6 +517,8 @@ void ICOReader::read16_24_32BMP(QImage & image) } } +static const char icoOrigDepthKey[] = "_q_icoOrigDepth"; + QImage ICOReader::iconAt(int index) { QImage img; @@ -535,7 +537,9 @@ QImage ICOReader::iconAt(int index) if (isPngImage) { iod->seek(iconEntry.dwImageOffset); - return QImage::fromData(iod->read(iconEntry.dwBytesInRes), "png"); + QImage image = QImage::fromData(iod->read(iconEntry.dwBytesInRes), "png"); + image.setText(QLatin1String(icoOrigDepthKey), QString::number(iconEntry.wBitCount)); + return image; } BMP_INFOHDR header; @@ -598,6 +602,7 @@ QImage ICOReader::iconAt(int index) } } } + img.setText(QLatin1String(icoOrigDepthKey), QString::number(iconEntry.wBitCount)); } } } -- cgit v1.2.3 From fb3f7b3ede45ca56643082787f091f15d1ab08db Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 17 Jun 2014 10:30:11 +0200 Subject: CMake: Load plugin files unconditionally if present. Task-number: QTBUG-39171 Task-number: QTBUG-39451 Change-Id: Ie66bd6b787a0957fd6f7ea673b158ab5de3cc38f Reviewed-by: Oswald Buddenhagen Reviewed-by: Stephen Kelly --- mkspecs/features/create_cmake.prf | 2 -- mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in | 13 +++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf index aee3e79765..92ea7326dc 100644 --- a/mkspecs/features/create_cmake.prf +++ b/mkspecs/features/create_cmake.prf @@ -166,8 +166,6 @@ contains(CONFIG, plugin) { return() } -contains($$list(network sql widgets gui), $$MODULE): CMAKE_LOAD_PLUGINS = true - unix:contains(QT_CONFIG, reduce_relocations):CMAKE_ADD_FPIE_FLAGS = "true" CMAKE_MKSPEC = $$[QMAKE_XSPEC] diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in index dce981e059..d1dfeed535 100644 --- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in +++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in @@ -283,7 +283,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) !!ENDIF // CMAKE_DEBUG_TYPE -!!IF !isEmpty(CMAKE_LOAD_PLUGINS) + file(GLOB pluginTargets \"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}_*Plugin.cmake\") macro(_populate_$${CMAKE_MODULE_NAME}_plugin_properties Plugin Configuration PLUGIN_LOCATION) set_property(TARGET Qt5::${Plugin} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${Configuration}) @@ -299,11 +299,12 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) ) endmacro() - file(GLOB pluginTargets \"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}_*Plugin.cmake\") - foreach(pluginTarget ${pluginTargets}) - include(${pluginTarget}) - endforeach() -!!ENDIF + if (pluginTargets) + foreach(pluginTarget ${pluginTargets}) + include(${pluginTarget}) + endforeach() + endif() + !!IF !isEmpty(CMAKE_MODULE_EXTRAS) include(\"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}ConfigExtras.cmake\") -- cgit v1.2.3 From cc7ef0667c4a3d46aa5e4e13c67a75156ac60ed2 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 19 Jun 2014 13:36:37 +0200 Subject: add buildsystem/qmake changelog Change-Id: I7fc7d335acd4f6e98517d240cc1f9bd3d035857f Reviewed-by: Joerg Bornemann --- dist/changes-5.3.1 | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/dist/changes-5.3.1 b/dist/changes-5.3.1 index a9760b1d57..228c64086a 100644 --- a/dist/changes-5.3.1 +++ b/dist/changes-5.3.1 @@ -60,3 +60,27 @@ Android - Text: * [QTBUG-37844] Fall back to Droid Sans Mono for QFont::Courier style hint. + +**************************************************************************** +* Tools * +**************************************************************************** + +configure & build system +------------------------ + + - [QTBUG-38445] Fixed build against static ICU on Unix + - [QTBUG-38544] Fixed LLVM build with SIMD features + - [QTBUG-39253] PDB files are now installed also for static libraries + - Added support for -separate-debug-info on Windows + - Added [-no]-pulseaudio and [-no]-alsa options on Unix + - Several fixes to installed .pc and .prl files + - Fixed MinGW build under MSYS + - Fixed installation of unneeded static libraries in dynamic builds + +qmake +----- + + - [QTBUG-37054] Fixed use of relative paths in QMAKE_BUNDLE_DATA with Xcode + - [QTBUG-38260] Custom Info.plist supplied via QMAKE_INFO_PLIST is now used + as-is, without placeholder replacement + - QMAKE_TARGET_BUNDLE_PREFIX does not need a trailing dot any more -- cgit v1.2.3 From 242fbc33a33cbf1d67e88fc4316c3d8f2de1e813 Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Fri, 20 Jun 2014 11:05:42 +0200 Subject: Fix installation of private headers generated by wayland-scanner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Private qtwayland headers were not installed at first build, since qmake was ignoring unexisting files from the install target. It required another run of qmake to have a proper Makefile generated. The rules for generated headers need CONFIG = no_check_exist, so that files get listed in the Makefile even if they do not exist yet (thanks to Loïc Yhuel for the pointer). Change-Id: I1a0278d629295a55a3ddcf5f8fb068a04ba5be47 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/wayland-scanner.prf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkspecs/features/wayland-scanner.prf b/mkspecs/features/wayland-scanner.prf index 3a9d8cafbd..5a97d98373 100644 --- a/mkspecs/features/wayland-scanner.prf +++ b/mkspecs/features/wayland-scanner.prf @@ -32,6 +32,7 @@ qt_install_headers { !isEmpty(header_files_client) { wayland_generated_client_headers.files = $$header_files_client wayland_generated_client_headers.path = $$private_headers.path + wayland_generated_client_headers.CONFIG = no_check_exist INSTALLS += wayland_generated_client_headers WAYLAND_CLIENT_HEADER_DEST = $$header_dest/ WAYLAND_CLIENT_INCLUDE_DIR = $$MODULE_INCNAME/private @@ -41,6 +42,7 @@ qt_install_headers { !isEmpty(header_files_server) { wayland_generated_server_headers.files = $$header_files_server wayland_generated_server_headers.path = $$private_headers.path + wayland_generated_server_headers.CONFIG = no_check_exist INSTALLS += wayland_generated_server_headers WAYLAND_SERVER_HEADER_DEST = $$header_dest/ WAYLAND_SERVER_INCLUDE_DIR = $$MODULE_INCNAME/private -- cgit v1.2.3 From 0f2ed80a0cfd0442fd5ea1fc1fd4a76ffb8a162a Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 17 Jun 2014 09:27:10 +0200 Subject: Doc: Fix docs for QFontMetrics::height() to match code After cb8445f0323b0eefbb04f1d8adad81a00b53abd8, Qt no longer considers the baseline to have a vertical size, so it does not add an extra pixel to the font height. The documentation needs to be updated to reflect this. Task-number: QTBUG-39668 Change-Id: I28fc813e21d73bb03f7055b0f0843511a12d308b Reviewed-by: Konstantin Ritt Reviewed-by: Friedemann Kleint --- src/gui/text/qfontmetrics.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 7868fd23d1..f6ab123739 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -295,8 +295,7 @@ int QFontMetrics::descent() const /*! Returns the height of the font. - This is always equal to ascent()+descent()+1 (the 1 is for the - base line). + This is always equal to ascent()+descent(). \sa leading(), lineSpacing() */ @@ -1159,8 +1158,7 @@ qreal QFontMetricsF::descent() const /*! Returns the height of the font. - This is always equal to ascent()+descent()+1 (the 1 is for the - base line). + This is always equal to ascent()+descent(). \sa leading(), lineSpacing() */ -- cgit v1.2.3 From ffdba0459b9ca562d530849e3e8995d6f17985df Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Sat, 21 Jun 2014 11:27:01 +0200 Subject: Correct grammar of missing Q_OBJECT macro warning. Change-Id: Ifb84220285e38ce6940595035ca9fe012c350b79 Reviewed-by: Olivier Goffart --- src/tools/moc/moc.cpp | 2 +- tests/auto/tools/moc/tst_moc.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index ea4838c8f2..f5700899fa 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -788,7 +788,7 @@ void Moc::parse() if (!def.hasQObject && !def.hasQGadget) - error("Class declarations lacks Q_OBJECT macro."); + error("Class declaration lacks Q_OBJECT macro."); // Add meta tags to the plugin meta data: if (!def.pluginData.iid.isEmpty()) diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 04140fa4a1..2e1504383f 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -1828,6 +1828,12 @@ void tst_Moc::warnings_data() << QString("IGNORE_ALL_STDOUT") << QString(":3: Warning: Macro argument mismatch.\n:4: Warning: Macro argument mismatch."); + QTest::newRow("Class declaration lacks Q_OBJECT macro.") + << QByteArray("class X : public QObject \n { \n public slots: \n void foo() {} \n };") + << QStringList() + << 1 + << QString() + << QString("standard input:5: Error: Class declaration lacks Q_OBJECT macro."); } void tst_Moc::warnings() -- cgit v1.2.3 From b5f284379155dee390c13a8d69b74d92f6ba9d19 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 13 Jun 2014 23:30:46 +0200 Subject: Add that the corner settings are saved/restored with the state Change-Id: Iee4c04291001470518176d8b3a49c08b52a6336e Reviewed-by: Jerome Pasion --- src/widgets/widgets/qmainwindow.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 358569a5e4..36ca90ba00 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -1226,7 +1226,9 @@ Qt::DockWidgetArea QMainWindow::dockWidgetArea(QDockWidget *dockwidget) const /*! Saves the current state of this mainwindow's toolbars and - dockwidgets. The \a version number is stored as part of the data. + dockwidgets. This includes the corner settings which can + be set with setCorner(). The \a version number is stored + as part of the data. The \l{QObject::objectName}{objectName} property is used to identify each QToolBar and QDockWidget. You should make sure @@ -1255,8 +1257,9 @@ QByteArray QMainWindow::saveState(int version) const /*! Restores the \a state of this mainwindow's toolbars and - dockwidgets. The \a version number is compared with that stored - in \a state. If they do not match, the mainwindow's state is left + dockwidgets. Also restores the corner settings too. The + \a version number is compared with that stored in \a state. + If they do not match, the mainwindow's state is left unchanged, and this function returns \c false; otherwise, the state is restored, and this function returns \c true. -- cgit v1.2.3 From b1d99dad098320777a4391052eac531c834748fa Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Mon, 23 Jun 2014 12:19:44 +0200 Subject: update changelog for QtSql 5.3.1 Change-Id: I06bf38a0c005ad4c13fb4db611847c3408060176 Reviewed-by: Andy Shaw --- dist/changes-5.3.1 | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/dist/changes-5.3.1 b/dist/changes-5.3.1 index 228c64086a..1e6f592a65 100644 --- a/dist/changes-5.3.1 +++ b/dist/changes-5.3.1 @@ -39,6 +39,21 @@ QtGui * [QTBUG-37190] Fixed crash when trying to load a font from invalid data. +QtSql +----- + + - QDB2 and QODBC + * [QTBUG-39137] Fix error handling problem caused by unintialized variable + passed to SQLNumResultCols. + + - QPSQL + * [QTBUG-12477] Fix PSQL column metadata. + + - QSqlQuery + * Fix misbehavior of seek in special query positions BeforeFirstRow and + AfterLastRow. (commit 3e6e70bddd84536deaae69421d05785ae6ce28cd) + * [QTBUG-33169] Fix for bindvalue(int) memory allocation problem. + QtWidgets --------- -- cgit v1.2.3 From 83ecf1e97d13fb94023cf4a43e9ae45702e4a762 Mon Sep 17 00:00:00 2001 From: Dyami Caliri Date: Wed, 18 Jun 2014 10:58:10 -0700 Subject: Cocoa: cleanup modal sessions for dialogs not run with .exec() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For modal dialogs not run through QDialog.exec(), the modal sessions were not cleaned up, causing the application's menus to be inaccessible. Task-number: QTBUG-37699 Change-Id: I2704c23fec8989aa2e8ddcc3d5e3f21bb6c5db73 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index e7f8992c6d..4328487f63 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -870,6 +870,9 @@ void QCocoaEventDispatcherPrivate::processPostedEvents() return; } + if (cleanupModalSessionsNeeded && currentExecIsNSAppRun) + cleanupModalSessions(); + if (processEventsCalled > 0 && interrupt) { if (currentExecIsNSAppRun) { // The event dispatcher has been interrupted. But since -- cgit v1.2.3 From 1e54f1316d30eae86bc38490f84aa55ee4568a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Fri, 20 Jun 2014 12:34:30 +0100 Subject: Print the reason why SetWindowsHookEx failed. Task-number: QTBUG-14301 Change-Id: I4733a57034259b013864bf91aba6cce2f411ab48 Reviewed-by: Friedemann Kleint --- src/corelib/kernel/qeventdispatcher_win.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index db2d30f2f5..f38ac7bf26 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -656,7 +656,9 @@ void QEventDispatcherWin32::createInternalHwnd() // setup GetMessage hook needed to drive our posted events d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId()); if (!d->getMessageHook) { - qFatal("Qt: INTERNALL ERROR: failed to install GetMessage hook"); + int errorCode = GetLastError(); + qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %s", + errorCode, qPrintable(qt_error_string(errorCode))); } #endif -- cgit v1.2.3 From a5f3df04afecd1f4ec347f7fb1b6522ff31ca680 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 18 Jun 2014 18:29:24 +0200 Subject: Simplify mirroring code and add tests for non-aliged 1 bit images Change-Id: I309714bc52de87c702194a4a82803d383f6ac3b3 Reviewed-by: Lars Knoll --- src/gui/image/qimage.cpp | 210 +++++++++++++---------------- tests/auto/gui/image/qimage/tst_qimage.cpp | 86 +++++++----- 2 files changed, 152 insertions(+), 144 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index cbdac4af95..273c1c922e 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2697,13 +2697,6 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const return maskImage; } - -/* - This code is contributed by Philipp Lang, - GeneriCom Software Germany (www.generi.com) - under the terms of the QPL, Version 1.0 -*/ - /*! \fn QImage QImage::mirrored(bool horizontal = false, bool vertical = true) const Returns a mirror of the image, mirrored in the horizontal and/or @@ -2715,61 +2708,108 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const \sa {QImage#Image Transformations}{Image Transformations} */ -template -inline void mirrored_helper_loop(int w, int h, int dxi, int dxs, int dyi, int dy, const uchar* sdata, uchar* ddata, int sbpl, int dbpl) +template inline void do_mirror_data(QImageData *dst, QImageData *src, + int dstX0, int dstY0, + int dstXIncr, int dstYIncr, + int w, int h) { - for (int sy = 0; sy < h; sy++, dy += dyi) { - const T* ssl = (T*)(sdata + sy*sbpl); - T* dsl = (T*)(ddata + dy*dbpl); - int dx = dxs; - for (int sx = 0; sx < w; sx++, dx += dxi) - dsl[dx] = ssl[sx]; + if (dst == src) { + // When mirroring in-place, stop in the middle for one of the directions, since we + // are swapping the bytes instead of merely copying. + const int srcXEnd = dstX0 ? w / 2 : w; + const int srcYEnd = !dstX0 && dstY0 ? h / 2 : h; + for (int srcY = 0, dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) { + T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line); + T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line); + for (int srcX = 0, dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr) + std::swap(srcPtr[srcX], dstPtr[dstX]); + } + } else { + for (int srcY = 0, dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) { + T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line); + T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line); + for (int srcX = 0, dstX = dstX0; srcX < w; ++srcX, dstX += dstXIncr) + dstPtr[dstX] = srcPtr[srcX]; + } } } -template -inline void mirrored_helper_loop_inplace(int w, int h, int dxi, int dxs, int dyi, int dy, uchar* sdata, int sbpl) +inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool vertical) { - for (int sy = 0; sy < h; sy++, dy += dyi) { - T* ssl = (T*)(sdata + sy*sbpl); - T* dsl = (T*)(sdata + dy*sbpl); - int dx = dxs; - for (int sx = 0; sx < w; sx++, dx += dxi) - std::swap(dsl[dx], ssl[sx]); + Q_ASSERT(src->width == dst->width && src->height == dst->height && src->depth == dst->depth); + int w = src->width; + int h = src->height; + int depth = src->depth; + + if (src->depth == 1) { + w = (w + 7) / 8; // byte aligned width + depth = 8; } -} -inline void mirror_horizonal_bitmap(int w, int h, int dxs, uchar* data, int bpl, bool monolsb) -{ - int shift = w % 8; - const uchar* bitflip = qt_get_bitflip_array(); - for (int y = h-1; y >= 0; y--) { - quint8* a0 = (quint8*)(data + y*bpl); - // Swap bytes - quint8* a = a0+dxs; - while (a >= a0) { - *a = bitflip[*a]; - a--; - } - // Shift bits if unaligned - if (shift != 0) { - a = a0+dxs; - quint8 c = 0; - if (monolsb) { - while (a >= a0) { - quint8 nc = *a << shift; - *a = (*a >> (8-shift)) | c; - --a; - c = nc; - } - } else { - while (a >= a0) { - quint8 nc = *a >> shift; - *a = (*a << (8-shift)) | c; - --a; - c = nc; + int dstX0 = 0, dstXIncr = 1; + int dstY0 = 0, dstYIncr = 1; + if (horizontal) { + // 0 -> w-1, 1 -> w-2, 2 -> w-3, ... + dstX0 = w - 1; + dstXIncr = -1; + } + if (vertical) { + // 0 -> h-1, 1 -> h-2, 2 -> h-3, ... + dstY0 = h - 1; + dstYIncr = -1; + } + + switch (depth) { + case 32: + do_mirror_data(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h); + break; + case 24: + do_mirror_data(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h); + break; + case 16: + do_mirror_data(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h); + break; + case 8: + do_mirror_data(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h); + break; + default: + Q_ASSERT(false); + break; + } + + // The bytes are now all in the correct place. In addition, the bits in the individual + // bytes have to be flipped too when horizontally mirroring a 1 bit-per-pixel image. + if (horizontal && dst->depth == 1) { + Q_ASSERT(dst->format == QImage::Format_Mono || dst->format == QImage::Format_MonoLSB); + const int shift = 8 - (dst->width % 8); + const uchar *bitflip = qt_get_bitflip_array(); + for (int y = 0; y < h; ++y) { + uchar *begin = dst->data + y * dst->bytes_per_line; + uchar *end = begin + dst->bytes_per_line; + for (uchar *p = begin; p < end; ++p) { + *p = bitflip[*p]; + // When the data is non-byte aligned, an extra bit shift (of the number of + // unused bits at the end) is needed for the entire scanline. + if (shift != 8 && p != begin) { + if (dst->format == QImage::Format_Mono) { + for (int i = 0; i < shift; ++i) { + p[-1] <<= 1; + p[-1] |= (*p & (128 >> i)) >> (7 - i); + } + } else { + for (int i = 0; i < shift; ++i) { + p[-1] >>= 1; + p[-1] |= (*p & (1 << i)) << (7 - i); + } + } } } + if (shift != 8) { + if (dst->format == QImage::Format_Mono) + end[-1] <<= shift; + else + end[-1] >>= shift; + } } } } @@ -2785,8 +2825,6 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical)) return *this; - int w = d->width; - int h = d->height; // Create result image, copy colormap QImage result(d->width, d->height, d->format); QIMAGE_SANITYCHECK_MEMORY(result); @@ -2799,29 +2837,8 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const result.d->has_alpha_clut = d->has_alpha_clut; result.d->devicePixelRatio = d->devicePixelRatio; - if (d->depth == 1) - w = (w+7)/8; - int dxi = horizontal ? -1 : 1; - int dxs = horizontal ? w-1 : 0; - int dyi = vertical ? -1 : 1; - int dys = vertical ? h-1 : 0; - - // 1 bit, 8 bit - if (d->depth == 1 || d->depth == 8) - mirrored_helper_loop(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line); - // 16 bit - else if (d->depth == 16) - mirrored_helper_loop(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line); - // 24 bit - else if (d->depth == 24) - mirrored_helper_loop(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line); - // 32 bit - else if (d->depth == 32) - mirrored_helper_loop(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line); - - // special handling of 1 bit images for horizontal mirroring - if (horizontal && d->depth == 1) - mirror_horizonal_bitmap(d->width, d->height, dxs, result.d->data, result.d->bytes_per_line, d->format == Format_MonoLSB); + do_mirror(result.d, d, horizontal, vertical); + return result; } @@ -2830,45 +2847,12 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const */ void QImage::mirrored_inplace(bool horizontal, bool vertical) { - if (!d) - return; - - if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical)) + if (!d || (d->width <= 1 && d->height <= 1) || (!horizontal && !vertical)) return; detach(); - int w = d->width; - int h = d->height; - - if (d->depth == 1) - w = (w+7)/8; - int dxi = horizontal ? -1 : 1; - int dxs = horizontal ? w-1 : 0; - int dyi = vertical ? -1 : 1; - int dys = vertical ? h-1 : 0; - - if (vertical) - h = h/2; - else if (horizontal) - w = w/2; - - // 1 bit, 8 bit - if (d->depth == 1 || d->depth == 8) - mirrored_helper_loop_inplace(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line); - // 16 bit - else if (d->depth == 16) - mirrored_helper_loop_inplace(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line); - // 24 bit - else if (d->depth == 24) - mirrored_helper_loop_inplace(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line); - // 32 bit - else if (d->depth == 32) - mirrored_helper_loop_inplace(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line); - - // special handling of 1 bit images for horizontal mirroring - if (horizontal && d->depth == 1) - mirror_horizonal_bitmap(d->width, d->height, dxs, d->data, d->bytes_per_line, d->format == Format_MonoLSB); + do_mirror(d, d, horizontal, vertical); } /*! diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index 65ecd54526..6c496ba6d4 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -2163,35 +2163,56 @@ void tst_QImage::mirrored_data() QTest::addColumn("format"); QTest::addColumn("swap_vertical"); QTest::addColumn("swap_horizontal"); - - QTest::newRow("Format_RGB32, vertical") << QImage::Format_RGB32 << true << false; - QTest::newRow("Format_ARGB32, vertical") << QImage::Format_ARGB32 << true << false; - QTest::newRow("Format_ARGB32_Premultiplied, vertical") << QImage::Format_ARGB32_Premultiplied << true << false; - QTest::newRow("Format_RGB16, vertical") << QImage::Format_RGB16 << true << false; - QTest::newRow("Format_ARGB8565_Premultiplied, vertical") << QImage::Format_ARGB8565_Premultiplied << true << false; - QTest::newRow("Format_ARGB6666_Premultiplied, vertical") << QImage::Format_ARGB6666_Premultiplied << true << false; - QTest::newRow("Format_ARGB4444_Premultiplied, vertical") << QImage::Format_ARGB4444_Premultiplied << true << false; - QTest::newRow("Format_RGB666, vertical") << QImage::Format_RGB666 << true << false; - QTest::newRow("Format_RGB555, vertical") << QImage::Format_RGB555 << true << false; - QTest::newRow("Format_ARGB8555_Premultiplied, vertical") << QImage::Format_ARGB8555_Premultiplied << true << false; - QTest::newRow("Format_RGB888, vertical") << QImage::Format_RGB888 << true << false; - QTest::newRow("Format_RGB444, vertical") << QImage::Format_RGB444 << true << false; - QTest::newRow("Format_RGBX8888, vertical") << QImage::Format_RGBX8888 << true << false; - QTest::newRow("Format_RGBA8888_Premultiplied, vertical") << QImage::Format_RGBA8888_Premultiplied << true << false; - QTest::newRow("Format_Indexed8, vertical") << QImage::Format_Indexed8 << true << false; - QTest::newRow("Format_Mono, vertical") << QImage::Format_Mono << true << false; - - QTest::newRow("Format_ARGB32_Premultiplied, horizontal") << QImage::Format_ARGB32_Premultiplied << false << true; - QTest::newRow("Format_RGB888, horizontal") << QImage::Format_RGB888 << false << true; - QTest::newRow("Format_RGB16, horizontal") << QImage::Format_RGB16 << false << true; - QTest::newRow("Format_Indexed8, horizontal") << QImage::Format_Indexed8 << false << true; - QTest::newRow("Format_Mono, horizontal") << QImage::Format_Mono << false << true; - - QTest::newRow("Format_ARGB32_Premultiplied, horizontal+vertical") << QImage::Format_ARGB32_Premultiplied << true << true; - QTest::newRow("Format_RGB888, horizontal+vertical") << QImage::Format_RGB888 << true << true; - QTest::newRow("Format_RGB16, horizontal+vertical") << QImage::Format_RGB16 << true << true; - QTest::newRow("Format_Indexed8, horizontal+vertical") << QImage::Format_Indexed8 << true << true; - QTest::newRow("Format_Mono, horizontal+vertical") << QImage::Format_Mono << true << true; + QTest::addColumn("width"); + QTest::addColumn("height"); + + QTest::newRow("Format_RGB32, vertical") << QImage::Format_RGB32 << true << false << 16 << 16; + QTest::newRow("Format_ARGB32, vertical") << QImage::Format_ARGB32 << true << false << 16 << 16; + QTest::newRow("Format_ARGB32_Premultiplied, vertical") << QImage::Format_ARGB32_Premultiplied << true << false << 16 << 16; + QTest::newRow("Format_RGB16, vertical") << QImage::Format_RGB16 << true << false << 16 << 16; + QTest::newRow("Format_ARGB8565_Premultiplied, vertical") << QImage::Format_ARGB8565_Premultiplied << true << false << 16 << 16; + QTest::newRow("Format_ARGB6666_Premultiplied, vertical") << QImage::Format_ARGB6666_Premultiplied << true << false << 16 << 16; + QTest::newRow("Format_ARGB4444_Premultiplied, vertical") << QImage::Format_ARGB4444_Premultiplied << true << false << 16 << 16; + QTest::newRow("Format_RGB666, vertical") << QImage::Format_RGB666 << true << false << 16 << 16; + QTest::newRow("Format_RGB555, vertical") << QImage::Format_RGB555 << true << false << 16 << 16; + QTest::newRow("Format_ARGB8555_Premultiplied, vertical") << QImage::Format_ARGB8555_Premultiplied << true << false << 16 << 16; + QTest::newRow("Format_RGB888, vertical") << QImage::Format_RGB888 << true << false << 16 << 16; + QTest::newRow("Format_RGB444, vertical") << QImage::Format_RGB444 << true << false << 16 << 16; + QTest::newRow("Format_RGBX8888, vertical") << QImage::Format_RGBX8888 << true << false << 16 << 16; + QTest::newRow("Format_RGBA8888_Premultiplied, vertical") << QImage::Format_RGBA8888_Premultiplied << true << false << 16 << 16; + QTest::newRow("Format_Indexed8, vertical") << QImage::Format_Indexed8 << true << false << 16 << 16; + QTest::newRow("Format_Mono, vertical") << QImage::Format_Mono << true << false << 16 << 16; + QTest::newRow("Format_MonoLSB, vertical") << QImage::Format_MonoLSB << true << false << 16 << 16; + + QTest::newRow("Format_ARGB32_Premultiplied, horizontal") << QImage::Format_ARGB32_Premultiplied << false << true << 16 << 16; + QTest::newRow("Format_RGB888, horizontal") << QImage::Format_RGB888 << false << true << 16 << 16; + QTest::newRow("Format_RGB16, horizontal") << QImage::Format_RGB16 << false << true << 16 << 16; + QTest::newRow("Format_Indexed8, horizontal") << QImage::Format_Indexed8 << false << true << 16 << 16; + QTest::newRow("Format_Mono, horizontal") << QImage::Format_Mono << false << true << 16 << 16; + QTest::newRow("Format_MonoLSB, horizontal") << QImage::Format_MonoLSB << false << true << 16 << 16; + + QTest::newRow("Format_ARGB32_Premultiplied, horizontal+vertical") << QImage::Format_ARGB32_Premultiplied << true << true << 16 << 16; + QTest::newRow("Format_RGB888, horizontal+vertical") << QImage::Format_RGB888 << true << true << 16 << 16; + QTest::newRow("Format_RGB16, horizontal+vertical") << QImage::Format_RGB16 << true << true << 16 << 16; + QTest::newRow("Format_Indexed8, horizontal+vertical") << QImage::Format_Indexed8 << true << true << 16 << 16; + QTest::newRow("Format_Mono, horizontal+vertical") << QImage::Format_Mono << true << true << 16 << 16; + QTest::newRow("Format_MonoLSB, horizontal+vertical") << QImage::Format_MonoLSB << true << true << 16 << 16; + + QTest::newRow("Format_RGB32, vertical") << QImage::Format_RGB32 << true << false << 8 << 16; + QTest::newRow("Format_ARGB32, vertical") << QImage::Format_ARGB32 << true << false << 16 << 8; + QTest::newRow("Format_Mono, vertical, non-aligned") << QImage::Format_Mono << true << false << 19 << 25; + QTest::newRow("Format_MonoLSB, vertical, non-aligned") << QImage::Format_MonoLSB << true << false << 19 << 25; + + // Non-aligned horizontal 1-bit needs special handling so test this. + QTest::newRow("Format_Mono, horizontal, non-aligned") << QImage::Format_Mono << false << true << 13 << 17; + QTest::newRow("Format_Mono, horizontal, non-aligned") << QImage::Format_Mono << false << true << 19 << 25; + QTest::newRow("Format_Mono, horizontal+vertical, non-aligned") << QImage::Format_Mono << true << true << 25 << 47; + QTest::newRow("Format_Mono, horizontal+vertical, non-aligned") << QImage::Format_Mono << true << true << 21 << 16; + + QTest::newRow("Format_MonoLSB, horizontal, non-aligned") << QImage::Format_MonoLSB << false << true << 13 << 17; + QTest::newRow("Format_MonoLSB, horizontal, non-aligned") << QImage::Format_MonoLSB << false << true << 19 << 25; + QTest::newRow("Format_MonoLSB, horizontal+vertical, non-aligned") << QImage::Format_MonoLSB << true << true << 25 << 47; + QTest::newRow("Format_MonoLSB, horizontal+vertical, non-aligned") << QImage::Format_MonoLSB << true << true << 21 << 16; } void tst_QImage::mirrored() @@ -2199,11 +2220,14 @@ void tst_QImage::mirrored() QFETCH(QImage::Format, format); QFETCH(bool, swap_vertical); QFETCH(bool, swap_horizontal); + QFETCH(int, width); + QFETCH(int, height); - QImage image(16, 16, format); + QImage image(width, height, format); switch (format) { case QImage::Format_Mono: + case QImage::Format_MonoLSB: for (int i = 0; i < image.height(); ++i) { ushort* scanLine = (ushort*)image.scanLine(i); *scanLine = (i % 2) ? 0x5555U : 0xCCCCU; @@ -2240,7 +2264,7 @@ void tst_QImage::mirrored() QCOMPARE(image, imageMirroredTwice); - if (format != QImage::Format_Mono) + if (format != QImage::Format_Mono && format != QImage::Format_MonoLSB) QCOMPARE(memcmp(image.constBits(), imageMirroredTwice.constBits(), image.byteCount()), 0); else { for (int i = 0; i < image.height(); ++i) -- cgit v1.2.3 From f46ce0a0b819b74c4f25b5d9fcbb8a83b62dd417 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 23 Jun 2014 10:20:07 +0200 Subject: Mac networking: check system keychain for proxy auth ... and not when normal HTTP authentication is required. Also, query the system keychain for the right credentials depending on the URL scheme. Task-number: QTBUG-30434 Change-Id: Ib6f74029b2e0de9734497440e3b0e48cdf73adcb Reviewed-by: Richard J. Moore --- src/network/access/qnetworkaccessbackend.cpp | 2 +- src/network/access/qnetworkaccessmanager.cpp | 39 ++++++++++++++-------------- src/network/access/qnetworkaccessmanager_p.h | 3 ++- src/network/access/qnetworkreplyhttpimpl.cpp | 2 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index 3c5e1e80a8..b4aaca0851 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -338,7 +338,7 @@ void QNetworkAccessBackend::error(QNetworkReply::NetworkError code, const QStrin void QNetworkAccessBackend::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator) { - manager->proxyAuthenticationRequired(proxy, synchronous, authenticator, &reply->lastProxyAuthentication); + manager->proxyAuthenticationRequired(QUrl(), proxy, synchronous, authenticator, &reply->lastProxyAuthentication); } #endif diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 473acc5f22..e669712147 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -99,13 +99,13 @@ bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString& bool retValue = false; SecProtocolType protocolType = kSecProtocolTypeAny; if (scheme.compare(QLatin1String("ftp"),Qt::CaseInsensitive)==0) { - protocolType = kSecProtocolTypeFTP; + protocolType = kSecProtocolTypeFTPProxy; } else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0 || scheme.compare(QLatin1String("preconnect-http"),Qt::CaseInsensitive)==0) { - protocolType = kSecProtocolTypeHTTP; + protocolType = kSecProtocolTypeHTTPProxy; } else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0 || scheme.compare(QLatin1String("preconnect-https"),Qt::CaseInsensitive)==0) { - protocolType = kSecProtocolTypeHTTPS; + protocolType = kSecProtocolTypeHTTPSProxy; } QByteArray proxyHostnameUtf8(proxyHostname.toUtf8()); err = SecKeychainFindInternetPassword(NULL, @@ -1392,21 +1392,6 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen } } -#ifndef QT_NO_NETWORKPROXY -#if defined(Q_OS_MACX) - //now we try to get the username and password from keychain - //if not successful signal will be emitted - QString username; - QString password; - if (getProxyAuth(proxy.hostName(),reply->request().url().scheme(),username,password)) { - authenticator->setUser(username); - authenticator->setPassword(password); - authenticationManager->cacheProxyCredentials(proxy, authenticator); - return; - } -#endif -#endif //QT_NO_NETWORKPROXY - // if we emit a signal here in synchronous mode, the user might spin // an event loop, which might recurse and lead to problems if (synchronous) @@ -1419,7 +1404,8 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen } #ifndef QT_NO_NETWORKPROXY -void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QNetworkProxy &proxy, +void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QUrl &url, + const QNetworkProxy &proxy, bool synchronous, QAuthenticator *authenticator, QNetworkProxy *lastProxyAuthentication) @@ -1435,6 +1421,21 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QNetworkPro } } +#if defined(Q_OS_OSX) + //now we try to get the username and password from keychain + //if not successful signal will be emitted + QString username; + QString password; + if (getProxyAuth(proxy.hostName(), url.scheme(), username, password)) { + authenticator->setUser(username); + authenticator->setPassword(password); + authenticationManager->cacheProxyCredentials(proxy, authenticator); + return; + } +#else + Q_UNUSED(url); +#endif + // if we emit a signal here in synchronous mode, the user might spin // an event loop, which might recurse and lead to problems if (synchronous) diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index 292755e7eb..9528330aae 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -113,7 +113,8 @@ public: const QAuthenticator *auth = 0); #ifndef QT_NO_NETWORKPROXY - void proxyAuthenticationRequired(const QNetworkProxy &proxy, + void proxyAuthenticationRequired(const QUrl &url, + const QNetworkProxy &proxy, bool synchronous, QAuthenticator *authenticator, QNetworkProxy *lastProxyAuthentication); diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index f043307c10..e136eee5ca 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1220,7 +1220,7 @@ void QNetworkReplyHttpImplPrivate::httpAuthenticationRequired(const QHttpNetwork void QNetworkReplyHttpImplPrivate::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator) { - managerPrivate->proxyAuthenticationRequired(proxy, synchronous, authenticator, &lastProxyAuthentication); + managerPrivate->proxyAuthenticationRequired(request.url(), proxy, synchronous, authenticator, &lastProxyAuthentication); } #endif -- cgit v1.2.3 From dfc1e23972136e8d86c45d43f3bf9048aa02c59a Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 23 Jun 2014 13:50:49 +0200 Subject: Mac networking: only try system proxy credentials once ... instead of running into an endless loop in case they are wrong. Task-number: QTBUG-30434 Change-Id: Iab258ebe1098a0c95f19da789a7a86de9d5bf149 Reviewed-by: Richard J. Moore --- src/network/access/qnetworkaccessmanager.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index e669712147..cc61f27cfb 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1427,10 +1427,15 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QUrl &url, QString username; QString password; if (getProxyAuth(proxy.hostName(), url.scheme(), username, password)) { - authenticator->setUser(username); - authenticator->setPassword(password); - authenticationManager->cacheProxyCredentials(proxy, authenticator); - return; + // only cache the system credentials if they are correct (or if they have changed) + // to not run into an endless loop in case they are wrong + QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy); + if (!priv->hasFailed || cred.user != username || cred.password != password) { + authenticator->setUser(username); + authenticator->setPassword(password); + authenticationManager->cacheProxyCredentials(proxy, authenticator); + return; + } } #else Q_UNUSED(url); -- cgit v1.2.3 From 432aaf05dabec82214ae018338aac827a8b326f8 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 19 May 2014 14:32:31 +0200 Subject: Cocoa: Do mouse move and cursor update handling separate from view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are using tracking areas for mouse move, enter/leave and cursor update events, so we should keep handling of that out of the "normal" event chain. If we handle mouse moved events in the views' mouseMoved method, we need to pass the event up the responder chain if we didn't handle it, or we would break for example hover behavior in native WebViews, because these do not handle mouse moved events directly in their mouseMoved:, but only if the event wasn't handled otherwise (arguably a bug in Web(HTML)View). But passing the event up the responder chain is not good either, because the QNSViews in the parent hierarchy get the event from their tracking areas already. Change-Id: I636a84ab1b7ef73070f81a8e33b5fa734ff4a42c Task-number: QTBUG-26593 Reviewed-by: Morten Johan Sørvig Reviewed-by: Eike Ziller --- src/plugins/platforms/cocoa/qnsview.h | 10 +++-- src/plugins/platforms/cocoa/qnsview.mm | 68 +++++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 7e146c5f58..37a0c1feb1 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -54,6 +54,8 @@ class QCocoaBackingStore; class QCocoaGLContext; QT_END_NAMESPACE +Q_FORWARD_DECLARE_OBJC_CLASS(QNSViewMouseMoveHelper); + @interface QNSView : NSView { QCocoaBackingStore* m_backingStore; QPoint m_backingStoreOffset; @@ -72,6 +74,7 @@ QT_END_NAMESPACE QCocoaGLContext *m_glContext; bool m_shouldSetGLContextinDrawRect; NSString *m_inputSource; + QNSViewMouseMoveHelper *m_mouseMoveHelper; } - (id)init; @@ -102,9 +105,10 @@ QT_END_NAMESPACE - (void)mouseDown:(NSEvent *)theEvent; - (void)mouseDragged:(NSEvent *)theEvent; - (void)mouseUp:(NSEvent *)theEvent; -- (void)mouseMoved:(NSEvent *)theEvent; -- (void)mouseEntered:(NSEvent *)theEvent; -- (void)mouseExited:(NSEvent *)theEvent; +- (void)mouseMovedImpl:(NSEvent *)theEvent; +- (void)mouseEnteredImpl:(NSEvent *)theEvent; +- (void)mouseExitedImpl:(NSEvent *)theEvent; +- (void)cursorUpdateImpl:(NSEvent *)theEvent; - (void)rightMouseDown:(NSEvent *)theEvent; - (void)rightMouseDragged:(NSEvent *)theEvent; - (void)rightMouseUp:(NSEvent *)theEvent; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index a2047bf550..4a744245f0 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -75,6 +75,53 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; - (CGFloat)deviceDeltaZ; @end +@interface QNSViewMouseMoveHelper : NSObject +{ + QNSView *view; +} + +- (id)initWithView:(QNSView *)theView; + +- (void)mouseMoved:(NSEvent *)theEvent; +- (void)mouseEntered:(NSEvent *)theEvent; +- (void)mouseExited:(NSEvent *)theEvent; +- (void)cursorUpdate:(NSEvent *)theEvent; + +@end + +@implementation QNSViewMouseMoveHelper + +- (id)initWithView:(QNSView *)theView +{ + self = [super init]; + if (self) { + view = theView; + } + return self; +} + +- (void)mouseMoved:(NSEvent *)theEvent +{ + [view mouseMovedImpl:theEvent]; +} + +- (void)mouseEntered:(NSEvent *)theEvent +{ + [view mouseEnteredImpl:theEvent]; +} + +- (void)mouseExited:(NSEvent *)theEvent +{ + [view mouseExitedImpl:theEvent]; +} + +- (void)cursorUpdate:(NSEvent *)theEvent +{ + [view cursorUpdateImpl:theEvent]; +} + +@end + @implementation QNSView + (void)initialize @@ -100,6 +147,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; currentCustomDragTypes = 0; m_sendUpAsRightButton = false; m_inputSource = 0; + m_mouseMoveHelper = [[QNSViewMouseMoveHelper alloc] initWithView:self]; if (!touchDevice) { touchDevice = new QTouchDevice; @@ -119,6 +167,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; m_subscribesForGlobalFrameNotifications = false; [m_inputSource release]; [[NSNotificationCenter defaultCenter] removeObserver:self]; + [m_mouseMoveHelper release]; delete currentCustomDragTypes; @@ -753,13 +802,13 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; | NSTrackingInVisibleRect | NSTrackingMouseMoved | NSTrackingCursorUpdate; NSTrackingArea *ta = [[[NSTrackingArea alloc] initWithRect:[self frame] options:trackingOptions - owner:self + owner:m_mouseMoveHelper userInfo:nil] autorelease]; [self addTrackingArea:ta]; } --(void)cursorUpdate:(NSEvent *)theEvent +-(void)cursorUpdateImpl:(NSEvent *)theEvent { Q_UNUSED(theEvent) // Set the cursor manually if there is no NSWindow. @@ -776,10 +825,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; [self addCursorRect:[self visibleRect] cursor:m_platformWindow->m_windowCursor]; } -- (void)mouseMoved:(NSEvent *)theEvent +- (void)mouseMovedImpl:(NSEvent *)theEvent { if (m_window->flags() & Qt::WindowTransparentForInput) - return [super mouseMoved:theEvent]; + return; QPointF windowPoint; QPointF screenPoint; @@ -806,12 +855,13 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; [self handleMouseEvent: theEvent]; } -- (void)mouseEntered:(NSEvent *)theEvent +- (void)mouseEnteredImpl:(NSEvent *)theEvent { + Q_UNUSED(theEvent) m_platformWindow->m_windowUnderMouse = true; if (m_window->flags() & Qt::WindowTransparentForInput) - return [super mouseEntered:theEvent]; + return; // Top-level windows generate enter events for sub-windows. if (!m_platformWindow->m_nsWindow) @@ -824,13 +874,13 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint); } -- (void)mouseExited:(NSEvent *)theEvent +- (void)mouseExitedImpl:(NSEvent *)theEvent { + Q_UNUSED(theEvent); m_platformWindow->m_windowUnderMouse = false; if (m_window->flags() & Qt::WindowTransparentForInput) - return [super mouseExited:theEvent]; - Q_UNUSED(theEvent); + return; // Top-level windows generate leave events for sub-windows. if (!m_platformWindow->m_nsWindow) -- cgit v1.2.3 From cb68607feea2fec680a275a4d9c4070e9a97d85f Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 17 Jun 2014 12:59:47 +0200 Subject: Fix memory leaks in QFseventsFileSystemWatcherEngine Sprinkle in some NSAutoReleasePools. Task-number: QTBUG-38637 Change-Id: I0cb42d9d1cbcc4e9d273d0d43e4925fc02885b66 Reviewed-by: Eike Ziller --- src/corelib/io/qfilesystemwatcher_fsevents.mm | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm index 981d663694..085396da6d 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents.mm +++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm @@ -64,6 +64,25 @@ QT_BEGIN_NAMESPACE +namespace { +class RaiiAutoreleasePool +{ + Q_DISABLE_COPY(RaiiAutoreleasePool) + +public: + RaiiAutoreleasePool() + : pool([[NSAutoreleasePool alloc] init]) + {} + + ~RaiiAutoreleasePool() + { [pool release]; } + +private: + NSAutoreleasePool *pool; +}; +#define Q_AUTORELEASE_POOL(pool) RaiiAutoreleasePool pool; Q_UNUSED(pool); +} + static void callBackFunction(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, @@ -71,6 +90,8 @@ static void callBackFunction(ConstFSEventStreamRef streamRef, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) { + Q_AUTORELEASE_POOL(pool) + char **paths = static_cast(eventPaths); QFseventsFileSystemWatcherEngine *engine = static_cast(clientCallBackInfo); engine->processEvent(streamRef, numEvents, paths, eventFlags, eventIds); @@ -283,6 +304,7 @@ void QFseventsFileSystemWatcherEngine::doEmitDirectoryChanged(const QString path void QFseventsFileSystemWatcherEngine::restartStream() { + Q_AUTORELEASE_POOL(pool) QMutexLocker locker(&lock); stopStream(); startStream(); @@ -313,6 +335,8 @@ QFseventsFileSystemWatcherEngine::QFseventsFileSystemWatcherEngine(QObject *pare QFseventsFileSystemWatcherEngine::~QFseventsFileSystemWatcherEngine() { + Q_AUTORELEASE_POOL(pool) + if (stream) FSEventStreamStop(stream); @@ -327,6 +351,8 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files, QStringList *directories) { + Q_AUTORELEASE_POOL(pool) + if (stream) { DEBUG("Flushing, last id is %llu", FSEventStreamGetLatestEventId(stream)); FSEventStreamFlushSync(stream); @@ -413,6 +439,8 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat QStringList *files, QStringList *directories) { + Q_AUTORELEASE_POOL(pool) + QMutexLocker locker(&lock); bool needsRestart = false; -- cgit v1.2.3 From 100ed2e91ead45f59639ec6b8aad16e6752818c4 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 24 Jun 2014 14:49:51 +0200 Subject: network internals: do not try to cache a deleted entry We were keeping a dangling pointer to a non-existent QIODevice around which would lead to a crash. Task-number: QTBUG-17400 Change-Id: Ie374cbb94bb45c9b0fbef46287b3317f60154123 Reviewed-by: Richard J. Moore --- src/network/access/qnetworkreplyhttpimpl.cpp | 10 ++++++ src/network/access/qnetworkreplyhttpimpl_p.h | 3 ++ .../qnetworkdiskcache/tst_qnetworkdiskcache.cpp | 38 ++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index e136eee5ca..56105a544b 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -975,6 +975,9 @@ void QNetworkReplyHttpImplPrivate::initCacheSaveDevice() cacheSaveDevice = managerPrivate->networkCache->prepare(metaData); + if (cacheSaveDevice) + q->connect(cacheSaveDevice, SIGNAL(aboutToClose()), SLOT(_q_cacheSaveDeviceAboutToClose())); + if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) { if (cacheSaveDevice && !cacheSaveDevice->isOpen()) qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- " @@ -1708,6 +1711,13 @@ void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingDataFinished() QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } +void QNetworkReplyHttpImplPrivate::_q_cacheSaveDeviceAboutToClose() +{ + // do not keep a dangling pointer to the device around (device + // is closing because e.g. QAbstractNetworkCache::remove() was called). + cacheSaveDevice = 0; +} + void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingData() { Q_Q(QNetworkReplyHttpImpl); diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index aa2d6f0ec9..d21659ce82 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -130,6 +130,7 @@ public: Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64)) Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64)) Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64)) + Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose()) #ifndef QT_NO_SSL @@ -179,6 +180,8 @@ public: void _q_bufferOutgoingData(); void _q_bufferOutgoingDataFinished(); + void _q_cacheSaveDeviceAboutToClose(); + #ifndef QT_NO_BEARERMANAGEMENT void _q_networkSessionConnected(); void _q_networkSessionFailed(); diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp index 44edcc66c0..4740b92b84 100644 --- a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp +++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp @@ -62,6 +62,7 @@ public slots: void cleanupTestCase(); void init(); void cleanup(); + void accessAfterRemoveReadyReadSlot(); private slots: void qnetworkdiskcache_data(); @@ -74,6 +75,7 @@ private slots: void data(); void metaData(); void remove(); + void accessAfterRemove(); // QTBUG-17400 void setCacheDirectory_data(); void setCacheDirectory(); void updateMetaData(); @@ -89,6 +91,8 @@ private slots: private: QTemporaryDir tempDir; + QUrl url; // used by accessAfterRemove() + QNetworkDiskCache *diskCache; // used by accessAfterRemove() }; // FIXME same as in tst_qnetworkreply.cpp .. could be unified @@ -370,6 +374,40 @@ void tst_QNetworkDiskCache::remove() QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 2); } +void tst_QNetworkDiskCache::accessAfterRemove() // QTBUG-17400 +{ + QByteArray data("HTTP/1.1 200 OK\r\n" + "Content-Length: 1\r\n" + "\r\n" + "a"); + + MiniHttpServer server(data); + + QNetworkAccessManager *manager = new QNetworkAccessManager(); + SubQNetworkDiskCache subCache; + subCache.setCacheDirectory(QLatin1String("cacheDir")); + diskCache = &subCache; + manager->setCache(&subCache); + + url = QUrl("http://127.0.0.1:" + QString::number(server.serverPort())); + QNetworkRequest request(url); + + QNetworkReply *reply = manager->get(request); + connect(reply, SIGNAL(readyRead()), this, SLOT(accessAfterRemoveReadyReadSlot())); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + QTestEventLoop::instance().enterLoop(5); + QVERIFY(!QTestEventLoop::instance().timeout()); + + reply->deleteLater(); + manager->deleteLater(); +} + +void tst_QNetworkDiskCache::accessAfterRemoveReadyReadSlot() +{ + diskCache->remove(url); // this used to cause a crash later on +} + void tst_QNetworkDiskCache::setCacheDirectory_data() { QTest::addColumn("cacheDir"); -- cgit v1.2.3 From 0ca1fc173818c155b3679b76da208fa9a2185ea1 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 24 Jun 2014 15:42:47 +0200 Subject: GIF decoding: do not seek() if the image is loaded over the network This suppresses the warning QIODevice::seek: Cannot call seek on a sequential device Task-number: QTBUG-39217 Change-Id: Ie7b0845c760ae6fc857d02bf9ec5c5adb24fb631 Reviewed-by: aavit --- src/gui/image/qgifhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/image/qgifhandler.cpp b/src/gui/image/qgifhandler.cpp index 19b838240f..91588edd50 100644 --- a/src/gui/image/qgifhandler.cpp +++ b/src/gui/image/qgifhandler.cpp @@ -674,7 +674,7 @@ void QGIFFormat::scan(QIODevice *device, QVector *imageSizes, int *loopCo return; qint64 oldPos = device->pos(); - if (!device->seek(0)) + if (device->isSequential() || !device->seek(0)) return; int colorCount = 0; -- cgit v1.2.3 From 0e14a58a96fc3deb78ac152c480cac3ac907f0f7 Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 22 Jun 2014 10:46:10 +0200 Subject: Doc: qInstallMessageHandler cannot return 0. The commit 124044613dde9a9596312102ca377bc74ed08165 (in Nov 2011) changed that: the first call will return the builtin message handler, not 0. Change-Id: I535ad69639f2341f9b664a6e2e7b12802ae785e0 Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart --- src/corelib/global/qlogging.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 4a602e4b2b..ff4372a049 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1443,8 +1443,7 @@ void qErrnoWarning(int code, const char *msg, ...) \since 5.0 Installs a Qt message \a handler which has been defined - previously. Returns a pointer to the previous message handler - (which may be 0). + previously. Returns a pointer to the previous message handler. The message handler is a function that prints out debug messages, warnings, critical and fatal error messages. The Qt library (debug -- cgit v1.2.3 From 00dce1cc0078f9633d121908172346cc22deb3c3 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 23 Jun 2014 11:47:49 -0700 Subject: Make the fetchAndAddRelaxed function a member template This way, no compiler can instantiate it at class instantiation time. We don't want them to do it for T that are function pointers (sizeof functions is meaningless). Change-Id: I6d5044bd5d9ffd0d347f1f38ab33c64213730788 Reviewed-by: Olivier Goffart Reviewed-by: David Faure --- src/corelib/arch/qatomic_bootstrap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/arch/qatomic_bootstrap.h b/src/corelib/arch/qatomic_bootstrap.h index 0d6843a3e5..1ab901d826 100644 --- a/src/corelib/arch/qatomic_bootstrap.h +++ b/src/corelib/arch/qatomic_bootstrap.h @@ -85,8 +85,8 @@ template struct QAtomicOps: QGenericAtomicOps > return tmp; } - static - T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + template static + T fetchAndAddRelaxed(T &_q_value, AdditiveType valueToAdd) Q_DECL_NOTHROW { T returnValue = _q_value; _q_value += valueToAdd; -- cgit v1.2.3 From 7cc893b2169555a8c4d8242f69e7ef12ebc36185 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Tue, 24 Jun 2014 08:41:11 +0300 Subject: Fix QRingBuffer::readPointerAtPosition() Fix condition to allow return a valid pointer when head != 0. Change-Id: I5215f7dfc44924016c2d9b67ab2d9935b5164d7a Reviewed-by: Oswald Buddenhagen --- src/corelib/tools/qringbuffer_p.h | 2 +- tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index b17c6d2f40..5d25b0add1 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -90,7 +90,7 @@ public: // special case: it is in the first buffer int nextDataBlockSizeValue = nextDataBlockSize(); - if (pos - head < nextDataBlockSizeValue) { + if (pos < nextDataBlockSizeValue) { length = nextDataBlockSizeValue - pos; return buffers.at(0).constData() + head + pos; } diff --git a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp index 6780493206..285cc3042a 100644 --- a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp +++ b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp @@ -111,6 +111,13 @@ void tst_QRingBuffer::readPointerAtPositionWithHead() buf2 = ringBuffer.readPointerAtPosition(0, length); QCOMPARE(length, qint64(0)); QVERIFY(buf2 == 0); + + // check buffer with 2 blocks + memcpy(ringBuffer.reserve(4), "0123", 4); + ringBuffer.append(QByteArray("45678", 5)); + ringBuffer.free(3); + buf2 = ringBuffer.readPointerAtPosition(1, length); + QCOMPARE(length, qint64(5)); } void tst_QRingBuffer::readPointerAtPositionEmptyRead() -- cgit v1.2.3 From c2c90b95bf8304e69a5f0a586c607105cc104f83 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 17 Jun 2014 10:41:38 +0200 Subject: CMake: Report an error if unit tests are not found for a module. Change-Id: Ic1540cfb04bf975a14bf2b35f4402bd36046de67 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/create_cmake.prf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf index 92ea7326dc..abd8009288 100644 --- a/mkspecs/features/create_cmake.prf +++ b/mkspecs/features/create_cmake.prf @@ -291,3 +291,5 @@ exists($$cmake_macros_file.input) { } cmake_qt5_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5$${CMAKE_MODULE_NAME} + +!exists($$MODULE_BASE_INDIR/tests/auto/cmake): error("Missing CMake tests.") -- cgit v1.2.3 From 1f3d9b12ab427cf81cc0a38622a54bf4e8edac49 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 25 Jun 2014 09:47:56 +0200 Subject: Fix logging file location docs The location mentioned in the docs didn't work because it was wrong. Change-Id: I80bbc16bfecc5662317f9963299981266b95bba8 Reviewed-by: Kai Koehne --- src/corelib/io/qloggingcategory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index 45fab11939..07245ddea2 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -141,13 +141,13 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) Order of evaluation: \list - \li Rules from QtProject/qlogging.ini + \li Rules from QtProject/qtlogging.ini \li Rules set by \l setFilterRules() \li Rules from file in \c QT_LOGGING_CONF \li Rules from environment variable QT_LOGGING_RULES \endlist - The \c QtProject/qlogging.ini file is looked up in all directories returned + The \c QtProject/qtlogging.ini file is looked up in all directories returned by QStandardPaths::GenericConfigLocation, e.g. \list -- cgit v1.2.3 From 51d6df1d18322c630f79567ed22de3718436d78d Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Tue, 17 Jun 2014 11:41:23 +0200 Subject: Translate Super/Hyper keys to MetaModifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is how it was done in Qt4. If users are interested in an actual X11 keysym they can use QKeyEvent::nativeVirtualKey(). Change-Id: I710664e48c5db1633a357aa0a5d238f3453103ab Task-number: QTBUG-38428 Reviewed-by: Christian Stenger Reviewed-by: Lars Knoll Reviewed-by: Sebastian Kügler Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 69601f44d4..4c84b19f82 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -929,6 +929,15 @@ int QXcbKeyboard::keysymToQtKey(xcb_keysym_t key) const i += 2; } + if (rmod_masks.meta) { + // translate Super/Hyper keys to Meta if we're using them as the MetaModifier + if (rmod_masks.meta == rmod_masks.super && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) { + code = Qt::Key_Meta; + } else if (rmod_masks.meta == rmod_masks.hyper && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) { + code = Qt::Key_Meta; + } + } + return code; } -- cgit v1.2.3 From 1e303a286e0df7723ca0144539407192363cafe3 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 12 Jun 2014 17:02:23 +0200 Subject: Mark behavior of QFileInfo::absoluteFilePath as undefined in corner cases The current description was misleading, since e.g. QFileInfo().absoluteFilePath() will always return an empty string. QFileInfo("").absoluteFilePath() however will return the current working directory ... Instead of documenting these small quirks we should rather mark the exact behavior as undefined, like we already do for absolutePath(). Change-Id: I70358413528429c2c2dee37480ad018aae26e6cb Reviewed-by: Oswald Buddenhagen Reviewed-by: Jerome Pasion --- src/corelib/io/qfileinfo.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 60f7e47e62..210bb3898c 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -530,7 +530,8 @@ void QFileInfo::setFile(const QDir &dir, const QString &file) is true. In contrast to canonicalFilePath(), symbolic links or redundant "." or ".." elements are not necessarily removed. - If the QFileInfo is empty it returns QDir::currentPath(). + \warning If filePath() is empty the behavior of this function + is undefined. \sa filePath(), canonicalFilePath(), isRelative() */ @@ -572,8 +573,8 @@ QString QFileInfo::canonicalFilePath() const In contrast to canonicalPath() symbolic links or redundant "." or ".." elements are not necessarily removed. - \warning If the QFileInfo object was created with an empty QString, - the behavior of this function is undefined. + \warning If filePath() is empty the behavior of this function + is undefined. \sa absoluteFilePath(), path(), canonicalPath(), fileName(), isRelative() */ -- cgit v1.2.3 From 3cd70c11bc7bbe3c5e9e4972d2273cf51bbdc30e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 25 Jun 2014 12:46:41 +0200 Subject: CMake: Allow modules to specify the location of tests. Webkit has a different layout, so allow the tests to be found in the appropriate location. Change-Id: Iedbea6daada98a3c3efdbcfc1fe4df5d2c8cea6a Reviewed-by: Oswald Buddenhagen --- mkspecs/features/create_cmake.prf | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf index abd8009288..2533b7b8d6 100644 --- a/mkspecs/features/create_cmake.prf +++ b/mkspecs/features/create_cmake.prf @@ -292,4 +292,13 @@ exists($$cmake_macros_file.input) { cmake_qt5_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5$${CMAKE_MODULE_NAME} -!exists($$MODULE_BASE_INDIR/tests/auto/cmake): error("Missing CMake tests.") +# We are generating cmake files. Most developers of Qt are not aware of cmake, +# so we require automatic tests to be available. The only module which should +# set CMAKE_MODULE_TESTS to '-' is enginio because that is known to be broken. +# Other modules should either create proper tests in tests/auto/cmake or, as +# a temporary measure, disable the generation of cmake files +# with 'CONFIG -= create_cmake' +!equals(CMAKE_MODULE_TESTS, -) { + isEmpty(CMAKE_MODULE_TESTS): CMAKE_MODULE_TESTS = $$MODULE_BASE_INDIR/tests/auto/cmake + !exists($$CMAKE_MODULE_TESTS): error("Missing CMake tests.") +} -- cgit v1.2.3 From 4cf37985e4c7108ff1e28ae875b0ee33c523e8b3 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 24 Jun 2014 16:39:50 -0700 Subject: Fix -Werror compilation on big-endian qt_alphamapblit_rgba8888 is only used on little-endian systems, where qAlpha() returns the correct value. qdrawhelper.cpp:6256:13: error: 'void qt_alphamapblit_rgba8888(QRasterBuffer*, int, int, quint32, const uchar*, int, int, int, const QClipData*)' defined but not used [-Werror=unused-function] Change-Id: Ibba6dd6914138f7ae5d53a8e354597f5fff65433 Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qdrawhelper.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 24da65921e..9293fc32dc 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -6253,6 +6253,7 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, } } +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *map, @@ -6261,6 +6262,7 @@ static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer, { qt_alphamapblit_argb32(rasterBuffer, x, y, ARGB2RGBA(color), map, mapWidth, mapHeight, mapStride, clip); } +#endif static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, -- cgit v1.2.3 From 7c833601402d536bccb1541a17755d20a1a102de Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 25 Jun 2014 10:04:40 +0200 Subject: QColorDialog: Do not update custom/standard color cells while picking. Delay the updating of the custom/standard color cells to the mouse release of the color pick. This makes it possible to pre-select a custom color cell for assignment before the pick and prevents that from changing when its color is crossed by accident. Rename the existing method QColorDialogPrivate::setCurrentColor(QRgb) to setCurrentRgbColor() and move QColor::setCurrentColor() to QColorDialogPrivate, introducing an enumeration for specifying what to set. Task-number: QTBUG-39792 Change-Id: Ibfe96e345589346e8c72976a0335e901798f2766 Reviewed-by: Paul Olav Tvete --- src/widgets/dialogs/qcolordialog.cpp | 39 ++++++++++++++++++++++-------------- src/widgets/dialogs/qcolordialog_p.h | 11 ++++++++-- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 8866a3e97e..3889a589c7 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -1442,7 +1442,7 @@ void QColorDialogPrivate::_q_newHsv(int h, int s, int v) } //sets all widgets to display rgb -void QColorDialogPrivate::setCurrentColor(QRgb rgb) +void QColorDialogPrivate::setCurrentRgbColor(QRgb rgb) { if (!nativeDialogInUse) { cs->setRgb(rgb); @@ -1525,14 +1525,14 @@ void QColorDialogPrivate::_q_nextCustom(int r, int c) void QColorDialogPrivate::_q_newCustom(int r, int c) { const int i = r + 2 * c; - setCurrentColor(QColorDialogOptions::customColor(i)); + setCurrentRgbColor(QColorDialogOptions::customColor(i)); if (standard) standard->setSelected(-1,-1); } void QColorDialogPrivate::_q_newStandard(int r, int c) { - setCurrentColor(QColorDialogOptions::standardColor(r + c * 6)); + setCurrentRgbColor(QColorDialogOptions::standardColor(r + c * 6)); if (custom) custom->setSelected(-1,-1); } @@ -1873,6 +1873,21 @@ QColorDialog::QColorDialog(const QColor &initial, QWidget *parent) d->init(initial); } +void QColorDialogPrivate::setCurrentColor(const QColor &color, SetColorMode setColorMode) +{ + if (nativeDialogInUse) { + platformColorDialogHelper()->setCurrentColor(color); + return; + } + + if (setColorMode & ShowColor) { + setCurrentRgbColor(color.rgb()); + setCurrentAlpha(color.alpha()); + } + if (setColorMode & SelectColor) + selectColor(color); +} + /*! \property QColorDialog::currentColor \brief the currently selected color in the dialog @@ -1881,13 +1896,7 @@ QColorDialog::QColorDialog(const QColor &initial, QWidget *parent) void QColorDialog::setCurrentColor(const QColor &color) { Q_D(QColorDialog); - if (d->nativeDialogInUse) - d->platformColorDialogHelper()->setCurrentColor(color); - else { - d->setCurrentColor(color.rgb()); - d->selectColor(color); - d->setCurrentAlpha(color.alpha()); - } + d->setCurrentColor(color); } QColor QColorDialog::currentColor() const @@ -2162,10 +2171,11 @@ void QColorDialog::changeEvent(QEvent *e) bool QColorDialogPrivate::handleColorPickingMouseMove(QMouseEvent *e) { - Q_Q(QColorDialog); const QPoint globalPos = e->globalPos(); const QColor color = grabScreenColor(globalPos); - q->setCurrentColor(color); + // QTBUG-39792, do not change standard, custom color selectors while moving as + // otherwise it is not possible to pre-select a custom cell for assignment. + setCurrentColor(color, ShowColor); lblScreenColorInfo->setText(QColorDialog::tr("Cursor at %1, %2, color: %3\nPress ESC to cancel") .arg(globalPos.x()).arg(globalPos.y()).arg(color.name())); return true; @@ -2173,8 +2183,7 @@ bool QColorDialogPrivate::handleColorPickingMouseMove(QMouseEvent *e) bool QColorDialogPrivate::handleColorPickingMouseButtonRelease(QMouseEvent *e) { - Q_Q(QColorDialog); - q->setCurrentColor(grabScreenColor(e->globalPos())); + setCurrentColor(grabScreenColor(e->globalPos()), SetColorAll); releaseColorPicking(); return true; } diff --git a/src/widgets/dialogs/qcolordialog_p.h b/src/widgets/dialogs/qcolordialog_p.h index 72c3b0e3cd..feabce4bbf 100644 --- a/src/widgets/dialogs/qcolordialog_p.h +++ b/src/widgets/dialogs/qcolordialog_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -77,6 +77,12 @@ class QColorDialogPrivate : public QDialogPrivate Q_DECLARE_PUBLIC(QColorDialog) public: + enum SetColorMode { + ShowColor = 0x1, + SelectColor = 0x2, + SetColorAll = ShowColor | SelectColor + }; + QColorDialogPrivate() : options(new QColorDialogOptions) {} QPlatformColorDialogHelper *platformColorDialogHelper() const @@ -86,7 +92,8 @@ public: void initWidgets(); QRgb currentColor() const; QColor currentQColor() const; - void setCurrentColor(QRgb rgb); + void setCurrentColor(const QColor &color, SetColorMode setColorMode = SetColorAll); + void setCurrentRgbColor(QRgb rgb); void setCurrentQColor(const QColor &color); bool selectColor(const QColor &color); QColor grabScreenColor(const QPoint &p); -- cgit v1.2.3 From 3f42e1a17128a218d1a0ca681ec6af97aa3e834a Mon Sep 17 00:00:00 2001 From: Dyami Caliri Date: Tue, 24 Jun 2014 16:32:39 -0700 Subject: QWin32PrintEnginePrivate check for NULL pDevMode and hdc. The MSDN documentation states that the pDevMode member of PPRINTER_INFO_2 may be NULL. Also, CreateDC may fail and return a NULL. Rework release() to release resources even if hdc was null. Task-number: QTBUG-39373 Change-Id: Ia08da61bf6ab99f02f0c7a09c608a5d3db34ef65 Reviewed-by: Friedemann Kleint --- src/printsupport/kernel/qprintengine_win.cpp | 28 +++++++++++++--------------- src/printsupport/kernel/qprintengine_win_p.h | 1 + 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index 427af13edf..b97dc6d2c2 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -844,14 +844,13 @@ void QWin32PrintEngine::drawPolygon(const QPointF *points, int pointCount, Polyg QWin32PrintEnginePrivate::~QWin32PrintEnginePrivate() { - if (hdc) - release(); + release(); } void QWin32PrintEnginePrivate::initialize() { - if (hdc) - release(); + release(); + Q_ASSERT(!hPrinter); Q_ASSERT(!hdc); Q_ASSERT(!devMode); @@ -878,18 +877,19 @@ void QWin32PrintEnginePrivate::initialize() if (!ok) { qErrnoWarning("QWin32PrintEngine::initialize: GetPrinter failed"); - GlobalUnlock(pInfo); - GlobalFree(hMem); - ClosePrinter(hPrinter); - pInfo = 0; - hMem = 0; - hPrinter = 0; + release(); return; } devMode = pInfo->pDevMode; hdc = CreateDC(NULL, reinterpret_cast(m_printDevice.id().utf16()), 0, devMode); + if (!hdc) { + qErrnoWarning("QWin32PrintEngine::initialize: CreateDC failed"); + release(); + return; + } + Q_ASSERT(hPrinter); Q_ASSERT(pInfo); @@ -941,19 +941,17 @@ void QWin32PrintEnginePrivate::initHDC() void QWin32PrintEnginePrivate::release() { - if (hdc == 0) - return; - if (globalDevMode) { // Devmode comes from print dialog GlobalUnlock(globalDevMode); - } else { // Devmode comes from initialize... + } else if (hMem) { // Devmode comes from initialize... // devMode is a part of the same memory block as pInfo so one free is enough... GlobalUnlock(hMem); GlobalFree(hMem); } if (hPrinter) ClosePrinter(hPrinter); - DeleteDC(hdc); + if (hdc) + DeleteDC(hdc); hdc = 0; hPrinter = 0; diff --git a/src/printsupport/kernel/qprintengine_win_p.h b/src/printsupport/kernel/qprintengine_win_p.h index 9b944d5921..f698992425 100644 --- a/src/printsupport/kernel/qprintengine_win_p.h +++ b/src/printsupport/kernel/qprintengine_win_p.h @@ -125,6 +125,7 @@ public: globalDevMode(0), devMode(0), pInfo(0), + hMem(0), hdc(0), mode(QPrinter::ScreenResolution), state(QPrinter::Idle), -- cgit v1.2.3 From 329efea47ed47fe8c303550d34767e07f8a292e4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 24 Jun 2014 13:01:27 -0700 Subject: Fix compilation on Windows without precompiled headers qnetworkinterface_win_p.h needs to include at least one Qt header before it can use QT_BEGIN_NAMESPACE. That header is the first header in qnetworkinterface_win.cpp. Found when trying to compile Qt with ICC. Change-Id: Iaa312ff54243b6fb3beb107f0eda74f92c6e3ebb Reviewed-by: Richard J. Moore --- src/network/kernel/qnetworkinterface_win_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/kernel/qnetworkinterface_win_p.h b/src/network/kernel/qnetworkinterface_win_p.h index d6a3366316..23664647cf 100644 --- a/src/network/kernel/qnetworkinterface_win_p.h +++ b/src/network/kernel/qnetworkinterface_win_p.h @@ -53,6 +53,7 @@ // We mean it. // +#include #include #include #include -- cgit v1.2.3 From 4108bfb47c058c415c43bd838248fa738a086ebe Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 19 Jun 2014 12:37:48 +0200 Subject: WinRT: no read-only paths in QStandardpaths::writableLocation As FontsLocation, HomeLocation and RuntimeLocation are read- only on WinRT WritableLocation should return empty strings in these cases. In addition all the other options were added to the switch statement in writableLocation. Task-number: QTBUG-38581 Change-Id: Iab994556844e713c6fa02028a0ec824ecb5ee82b Reviewed-by: Andrew Knight --- src/corelib/io/qstandardpaths_winrt.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/corelib/io/qstandardpaths_winrt.cpp b/src/corelib/io/qstandardpaths_winrt.cpp index 84a3930ee0..feafdf2e7c 100644 --- a/src/corelib/io/qstandardpaths_winrt.cpp +++ b/src/corelib/io/qstandardpaths_winrt.cpp @@ -103,14 +103,23 @@ QString QStandardPaths::writableLocation(StandardLocation type) case GenericCacheLocation: return writableLocation(GenericDataLocation) + QLatin1String("/cache"); - case RuntimeLocation: - case HomeLocation: - result = QDir::homePath(); - break; - case TempLocation: result = QDir::tempPath(); break; + + case ApplicationsLocation: + case DesktopLocation: + case FontsLocation: + case HomeLocation: + case RuntimeLocation: + // these are read-only + break; + + case DocumentsLocation: + case MusicLocation: + case MoviesLocation: + case PicturesLocation: + case DownloadLocation: default: Q_UNIMPLEMENTED(); } -- cgit v1.2.3 From dee557c8aa69c51a80ed19f71476def61a868213 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 25 Jun 2014 10:44:54 +0200 Subject: Delete qml_plugin_import.cpp file only during distclean For static builds of Qt Quick apps, qmake generates a qml_plugin_import.cpp file. Just like the Makefiles, it should be removed only for distclean, not in the clean step. This is what we do for non-qml plugins, too. Change-Id: I5a3f2e7d27c3ffd5161162a8a03e4dd9c9245af5 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qt.prf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index f8ba3c58b2..9edf5cd530 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -128,7 +128,7 @@ contains(qt_module_deps, qml): \ QML_IMPORT_CPP = $$OUT_PWD/$$lower($$basename(TARGET))_qml_plugin_import.cpp write_file($$QML_IMPORT_CPP, IMPORT_FILE_CONT)|error("Aborting.") SOURCES += $$QML_IMPORT_CPP - QMAKE_CLEAN += $$QML_IMPORT_CPP + QMAKE_DISTCLEAN += $$QML_IMPORT_CPP # copy qml files. this part is platform spesific. mac { -- cgit v1.2.3 From 321d6dda759841a16a4e21d7e3bbbfc89504bee4 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 26 Jun 2014 12:46:57 +0200 Subject: Fix QMutex documentation saying some function are static while they are not MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qdoc only see a fake QMutex class (the same as the one built in bootstrap) But that fake QMutex had static member while the normal QMutex class has non static member. QMutexLocker::mutex is also a const function in the real QMutexLocker Task-number: QTBUG-38522 Change-Id: I220434ffc6a9e990029f770e2536ecb55b4e2182 Reviewed-by: Martin Smith Reviewed-by: Jędrzej Nowacki --- src/corelib/thread/qmutex.cpp | 2 +- src/corelib/thread/qmutex.h | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index fe5beb1c01..5e3f3a1cab 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -380,7 +380,7 @@ bool QBasicMutex::isRecursive() */ /*! - \fn QMutex *QMutexLocker::mutex() + \fn QMutex *QMutexLocker::mutex() const Returns the mutex on which the QMutexLocker is operating. diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 0ecc96a9b1..333865014b 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -186,10 +186,10 @@ public: inline explicit QMutex(RecursionMode mode = NonRecursive) { Q_UNUSED(mode); } - static inline void lock() {} - static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; } - static inline void unlock() {} - static inline bool isRecursive() { return true; } + inline void lock() {} + inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; } + inline void unlock() {} + inline bool isRecursive() { return true; } private: Q_DISABLE_COPY(QMutex) @@ -201,9 +201,9 @@ public: inline explicit QMutexLocker(QMutex *) {} inline ~QMutexLocker() {} - static inline void unlock() {} - static void relock() {} - static inline QMutex *mutex() { return 0; } + inline void unlock() {} + void relock() {} + inline QMutex *mutex() const { return 0; } private: Q_DISABLE_COPY(QMutexLocker) -- cgit v1.2.3 From 6303307692c4ebdc3836f44da917d6b83ab3d4cc Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 26 Jun 2014 12:54:33 +0200 Subject: Add a comment stating QMutex::isRecursive should be made const in Qt6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I452b0764790112c59af77bc8d95f403ff37cbc4a Reviewed-by: Jędrzej Nowacki --- src/corelib/thread/qmutex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 333865014b..011555f904 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -77,7 +77,7 @@ public: return fastTryLock(); } - bool isRecursive(); + bool isRecursive(); //### Qt6: mark const private: inline bool fastTryLock() Q_DECL_NOTHROW { -- cgit v1.2.3 From 853fb5ddde8f323b269e5357ff216ca6ba252b7c Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Fri, 27 Jun 2014 15:04:38 +0200 Subject: Remove bogus nullptr check for reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I3aafe427b9ea9a2b7936c4e2217722ee78d329aa Reviewed-by: Jędrzej Nowacki --- src/gui/accessible/qaccessible.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 776320a517..954c8564f0 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -1704,10 +1704,6 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface) /*! \internal */ QDebug operator<<(QDebug d, const QAccessibleEvent &ev) { - if (!&ev) { - d << "QAccessibleEvent(null)"; - return d; - } d.nospace() << "QAccessibleEvent("; if (ev.object()) { d.nospace() << "object=" << hex << ev.object() << dec; -- cgit v1.2.3 From 5d6b763ee521b830c2b19949016f9436627496d6 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Wed, 25 Jun 2014 13:12:53 +0100 Subject: qtoolbar: add missing header on OSX. Without this you get: ``` widgets/qtoolbar.cpp:1047:5: error: incomplete type 'QPlatformNativeInterface' named in nested name specifier QPlatformNativeInterface::NativeResourceForIntegrationFunction function = ^~~~~~~~~~~~~~~~~~~~~~~~~~ qtbase/src/widgets/../../include/QtGui/../../src/gui/kernel/qguiapplication.h:57:7: note: forward declaration of 'QPlatformNativeInterface' class QPlatformNativeInterface; ``` Change-Id: I1301a8aa8b25eb12821e91125743be779e52db0f Reviewed-by: Jake Petroules Reviewed-by: Mike McQuaid Reviewed-by: Giuseppe D'Angelo --- src/widgets/widgets/qtoolbar.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp index 3fd615c3c7..1c05529cd6 100644 --- a/src/widgets/widgets/qtoolbar.cpp +++ b/src/widgets/widgets/qtoolbar.cpp @@ -59,6 +59,10 @@ #include #include +#ifdef Q_OS_OSX +#include +#endif + #include "qtoolbar_p.h" #include "qtoolbarseparator_p.h" #include "qtoolbarlayout_p.h" -- cgit v1.2.3 From 86fa23b5e35041189d8598945a642904b18dbedb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 28 Jun 2014 13:06:08 -0700 Subject: Don't compare the target methods for SlotObject connections When a new-style connection is created (a SlotObject), we don't store the method offset since there isn't one. So don't try to read it. Qt::UniqueConnection only applies to old-style connections, since we can't compare the slot objects for equality. In any case, an old-style connection and a new style will never be considered equal. Task-number: QTBUG-39927 Change-Id: I10a39a7bc97a2ec9509a0708038cc491bcc67329 Reviewed-by: Olivier Goffart Reviewed-by: Elias Probst --- src/corelib/kernel/qobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 38e55b7aa9..5e8a97cdc0 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3230,7 +3230,7 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, int method_index_absolute = method_index + method_offset; while (c2) { - if (c2->receiver == receiver && c2->method() == method_index_absolute) + if (!c2->isSlotObject && c2->receiver == receiver && c2->method() == method_index_absolute) return 0; c2 = c2->nextConnectionList; } -- cgit v1.2.3 From a57f3ee9bb9462bb3742f5106ef4e4c33e8edeac Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 27 Jun 2014 15:51:28 +0200 Subject: Android: Fix compilation of qpluginloader test The almostplugin has an unresolved symbol, and on Android we compile with -no-undefined. Change-Id: Ia631193890dfe8e7ac8e58087475164222d876fc Reviewed-by: BogDan Vatra --- tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro index 8d117793bf..f5d06b3de9 100644 --- a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro +++ b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro @@ -4,7 +4,7 @@ CONFIG += ordered SUBDIRS = lib \ theplugin \ tst -!win32: !mac: SUBDIRS += almostplugin +!android: !win32: !mac: SUBDIRS += almostplugin macx-*: SUBDIRS += machtest TARGET = tst_qpluginloader -- cgit v1.2.3 From 190bb186aefe920ceaf5c464a88812e59d95e5e4 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 27 Jun 2014 15:54:01 +0200 Subject: Android: Fix compilation of qhostaddress test The sockaddr_in struct is defined in netinet/in.h header. Change-Id: I67a3421094c96a5e948968a26723ec8c21f85c93 Reviewed-by: BogDan Vatra --- tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp index c4d42206fe..99f677643c 100644 --- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp +++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp @@ -55,6 +55,10 @@ # endif #endif +#ifdef Q_OS_ANDROID +# include +#endif + class tst_QHostAddress : public QObject { Q_OBJECT -- cgit v1.2.3 From 8638895f6be4bd6566e771603a42f9f99b0c1d97 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 27 Jun 2014 15:56:55 +0200 Subject: Android: Fix compilation of qtcpsocket test No pthread_yield() in the Android NDK. Change-Id: I5ff77c55f30c172ee7fefb1129bdf475b318449e Reviewed-by: BogDan Vatra --- tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index fcf6315c1f..8e69d827a6 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -1976,9 +1976,9 @@ public slots: attemptedToConnect = true; sock->connectToHost(QtNetworkSettings::serverName(), 80); -#ifdef Q_OS_MAC +#if defined(Q_OS_MAC) pthread_yield_np(); -#elif defined Q_OS_LINUX +#elif defined Q_OS_LINUX && !defined Q_OS_ANDROID pthread_yield(); #endif if (!sock->waitForConnected()) { -- cgit v1.2.3 From 5de4ed9db38c7a1a480e5979c2bb3b0340c8a230 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sat, 28 Jun 2014 15:47:58 +0200 Subject: QMac/FusionStyle: fix the background color for transient scrollbars Task-number: QTBUG-39922 Change-Id: I4b313296ae845bc9e116494aa66c577b432b4a67 Reviewed-by: Gabriel de Dietrich --- src/widgets/styles/qfusionstyle.cpp | 2 +- src/widgets/styles/qmacstyle_mac.mm | 2 +- src/widgets/styles/qstylehelper.cpp | 10 ++++++++++ src/widgets/styles/qstylehelper_p.h | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 2172c9082f..82c53def7d 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -2493,7 +2493,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption QColor arrowColor = option->palette.foreground().color(); arrowColor.setAlpha(220); - const QColor bgColor = option->palette.color(QPalette::Base); + const QColor bgColor = QStyleHelper::backgroundColor(option->palette, widget); const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128; if (transient) { diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 8bc454a795..8cb7ce1c87 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -5133,7 +5133,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex [scroller initWithFrame:NSMakeRect(0, 0, slider->rect.width(), slider->rect.height())]; // mac os behaviour: as soon as one color channel is >= 128, // the bg is considered bright, scroller is dark - const QColor bgColor = opt->palette.color(QPalette::Base); + const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget); const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128; if (isDarkBg) diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index fc73488154..6be07a3f45 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -45,6 +45,8 @@ #include #include #include +#include +#include #include "qstylehelper_p.h" #include @@ -387,5 +389,13 @@ void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rec } } + +QColor backgroundColor(const QPalette &pal, const QWidget* widget) +{ + if (qobject_cast(widget) && widget->parent() && + qobject_cast(widget->parent()->parent())) + return widget->parentWidget()->parentWidget()->palette().color(QPalette::Base); + return pal.color(QPalette::Base); +} } QT_END_NAMESPACE diff --git a/src/widgets/styles/qstylehelper_p.h b/src/widgets/styles/qstylehelper_p.h index 6355cbc985..73e5c94dcd 100644 --- a/src/widgets/styles/qstylehelper_p.h +++ b/src/widgets/styles/qstylehelper_p.h @@ -86,6 +86,7 @@ namespace QStyleHelper bool isInstanceOf(QObject *obj, QAccessible::Role role); bool hasAncestor(QObject *obj, QAccessible::Role role); #endif + QColor backgroundColor(const QPalette &pal, const QWidget* widget = 0); } -- cgit v1.2.3 From 813462a0cedc1053c6460c3db6734ec534fe3363 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Jun 2014 14:46:33 +0200 Subject: tst_qcollator: Exclude failing test cases for non-ICU/Windows. Change-Id: I17912ddb34337216805259dab9d90eb2c9ac64cc Reviewed-by: Sergio Ahumada --- tests/auto/corelib/tools/qcollator/tst_qcollator.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp index 9ed27a8742..3a00ebd505 100644 --- a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp +++ b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp @@ -121,10 +121,12 @@ void tst_QCollator::compare_data() diaresis (E4), which comes before o diaresis (F6), which all come after z. */ +#if !defined(Q_OS_WIN) || defined(QT_USE_ICU) QTest::newRow("swedish1") << QString("sv_SE") << QString::fromLatin1("\xe5") << QString::fromLatin1("\xe4") << -1 << -1; +#endif QTest::newRow("swedish2") << QString("sv_SE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1 << -1; QTest::newRow("swedish3") << QString("sv_SE") << QString::fromLatin1("\xe5") << QString::fromLatin1("\xf6") << -1 << -1; -#ifndef Q_OS_MAC +#if !defined(Q_OS_OSX) && (!defined(Q_OS_WIN) || defined(QT_USE_ICU)) QTest::newRow("swedish4") << QString("sv_SE") << QString::fromLatin1("z") << QString::fromLatin1("\xe5") << -1 << -1; #endif @@ -133,11 +135,12 @@ void tst_QCollator::compare_data() comes before a with ring above (E5). */ QTest::newRow("norwegian1") << QString("no_NO") << QString::fromLatin1("\xe6") << QString::fromLatin1("\xd8") << -1 << -1; -#ifndef Q_OS_MAC +#if !defined(Q_OS_WIN) || defined(QT_USE_ICU) +# ifndef Q_OS_OSX QTest::newRow("norwegian2") << QString("no_NO") << QString::fromLatin1("\xd8") << QString::fromLatin1("\xe5") << -1 << -1; -#endif +# endif QTest::newRow("norwegian3") << QString("no_NO") << QString::fromLatin1("\xe6") << QString::fromLatin1("\xe5") << -1 << -1; - +#endif // !Q_OS_WIN || QT_USE_ICU /* In German, z comes *after* a with diaresis (E4), which comes before o diaresis (F6). -- cgit v1.2.3 From 2021c6c8f74df35f7bf71f9d4a6208c055a3cf15 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 30 Jun 2014 13:52:46 +0200 Subject: Fix pixel noise in X11 systray icons that are not 22x22 If a system tray icon is set to a non default size by an X11 system tray, the area beyond 22x22 will not be painted, since the first paint is performed before the first resize, and the first resize does not trigger expose either. The bug can be seen in KDE if the system tray is not 22 pixel height. This patch triggers updates on resize to ensure we always repaint fully on resize. Change-Id: Ia81d2329a2c9faff220f07163ac38cafbd520ffc Reviewed-by: Shawn Rutledge --- src/widgets/util/qsystemtrayicon_x11.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp index 347e5701c0..21ce23437f 100644 --- a/src/widgets/util/qsystemtrayicon_x11.cpp +++ b/src/widgets/util/qsystemtrayicon_x11.cpp @@ -83,6 +83,7 @@ protected: virtual void mouseDoubleClickEvent(QMouseEvent *ev); virtual bool event(QEvent *); virtual void paintEvent(QPaintEvent *); + virtual void resizeEvent(QResizeEvent *); private slots: void systemTrayWindowChanged(QScreen *screen); @@ -205,6 +206,11 @@ void QSystemTrayIconSys::paintEvent(QPaintEvent *) q->icon().paint(&painter, rect); } +void QSystemTrayIconSys::resizeEvent(QResizeEvent *) +{ + update(); +} + //////////////////////////////////////////////////////////////////////////// QSystemTrayIconPrivate::QSystemTrayIconPrivate() -- cgit v1.2.3 From 32514298131f7e8009a7641e20ff37be91cf4582 Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Mon, 30 Jun 2014 13:52:25 +0200 Subject: Doc: Fix typo in QScopedValueRollback Change-Id: I9835b284d6bba5f7632cae6b179c6c1b08265e5c Reviewed-by: Friedemann Kleint --- src/corelib/tools/qscopedvaluerollback.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qscopedvaluerollback.cpp b/src/corelib/tools/qscopedvaluerollback.cpp index 3201a3c87a..2d61d2114e 100644 --- a/src/corelib/tools/qscopedvaluerollback.cpp +++ b/src/corelib/tools/qscopedvaluerollback.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE \since 4.8 \ingroup misc - The QScopedAssignment class can be used to revert state when an + The QScopedValueRollback class can be used to revert state when an exception is thrown without needing to write try-catch blocks. It can also be used to manage variables that are temporarily set, -- cgit v1.2.3 From 8f96ce37333b3034f2eef1366f9eea4a47a479ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 23 Apr 2014 16:10:33 +0200 Subject: Android: Fix namespace usage This change makes it possible to set a Qt namespace for Android builds. Change-Id: I79f4ae8200223f36f97e2849aae49e45b8850d23 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/network/ssl/qsslsocket_openssl_android.cpp | 4 ++++ src/plugins/platforms/android/androidjniaccessibility.cpp | 4 ++++ src/plugins/platforms/android/androidjniaccessibility.h | 5 +++++ src/plugins/platforms/android/androidjniclipboard.cpp | 4 ++++ src/plugins/platforms/android/androidjniclipboard.h | 4 ++++ src/plugins/platforms/android/androidjniinput.cpp | 4 ++++ src/plugins/platforms/android/androidjniinput.h | 5 +++++ src/plugins/platforms/android/androidjnimain.cpp | 5 +++++ src/plugins/platforms/android/androidjnimain.h | 5 +++++ src/plugins/platforms/android/androidjnimenu.cpp | 4 ++++ src/plugins/platforms/android/androidjnimenu.h | 5 +++++ src/plugins/platforms/android/androidsurfaceclient.h | 4 ++++ src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp | 4 ++++ src/plugins/platforms/android/qandroidassetsfileenginehandler.h | 4 ++++ src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp | 4 ++++ src/plugins/platforms/android/qandroidplatformdialoghelpers.h | 4 ++++ src/plugins/platforms/android/qandroidplatformfontdatabase.cpp | 4 ++++ src/plugins/platforms/android/qandroidplatformfontdatabase.h | 4 ++++ src/plugins/platforms/android/qandroidplatformmenu.cpp | 4 ++++ src/plugins/platforms/android/qandroidplatformmenu.h | 4 ++++ src/plugins/platforms/android/qandroidplatformmenubar.cpp | 3 +++ src/plugins/platforms/android/qandroidplatformmenubar.h | 4 ++++ src/plugins/platforms/android/qandroidplatformmenuitem.cpp | 4 ++++ src/plugins/platforms/android/qandroidplatformmenuitem.h | 4 ++++ src/plugins/platforms/android/qandroidplatformservices.cpp | 4 ++++ src/plugins/platforms/android/qandroidplatformservices.h | 4 ++++ src/plugins/platforms/android/qandroidplatformtheme.cpp | 4 ++++ src/plugins/platforms/android/qandroidplatformtheme.h | 4 ++++ 28 files changed, 116 insertions(+) diff --git a/src/network/ssl/qsslsocket_openssl_android.cpp b/src/network/ssl/qsslsocket_openssl_android.cpp index fa612a75a6..c7cf03d86d 100644 --- a/src/network/ssl/qsslsocket_openssl_android.cpp +++ b/src/network/ssl/qsslsocket_openssl_android.cpp @@ -153,6 +153,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) return JNI_VERSION_1_4; } +QT_BEGIN_NAMESPACE + QList QSslSocketPrivate::fetchSslCertificateData() { QList certificateData; @@ -177,3 +179,5 @@ QList QSslSocketPrivate::fetchSslCertificateData() return certificateData; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index 9d43c2f758..3f58597c9b 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -55,6 +55,8 @@ static const char m_qtTag[] = "Qt A11Y"; static const char m_classErrorMsg[] = "Can't find class \"%s\""; static const char m_methodErrorMsg[] = "Can't find method \"%s%s\""; +QT_BEGIN_NAMESPACE + namespace QtAndroidAccessibility { static jmethodID m_addActionMethodID = 0; @@ -290,3 +292,5 @@ if (!clazz) { \ return true; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/androidjniaccessibility.h b/src/plugins/platforms/android/androidjniaccessibility.h index e708138c33..3ca89242fe 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.h +++ b/src/plugins/platforms/android/androidjniaccessibility.h @@ -42,10 +42,15 @@ #ifndef ANDROIDJNIACCESSIBILITY_H #define ANDROIDJNIACCESSIBILITY_H #include +#include + +QT_BEGIN_NAMESPACE namespace QtAndroidAccessibility { bool registerNatives(JNIEnv *env); } +QT_END_NAMESPACE + #endif // ANDROIDJNIINPUT_H diff --git a/src/plugins/platforms/android/androidjniclipboard.cpp b/src/plugins/platforms/android/androidjniclipboard.cpp index 05270ac374..87bb08910d 100644 --- a/src/plugins/platforms/android/androidjniclipboard.cpp +++ b/src/plugins/platforms/android/androidjniclipboard.cpp @@ -42,6 +42,8 @@ #include "androidjniclipboard.h" #include "androidjnimain.h" +QT_BEGIN_NAMESPACE + using namespace QtAndroid; namespace QtAndroidClipboard { @@ -118,3 +120,5 @@ namespace QtAndroidClipboard return true; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/androidjniclipboard.h b/src/plugins/platforms/android/androidjniclipboard.h index 15cd93202e..764ef908df 100644 --- a/src/plugins/platforms/android/androidjniclipboard.h +++ b/src/plugins/platforms/android/androidjniclipboard.h @@ -45,6 +45,8 @@ #include #include +QT_BEGIN_NAMESPACE + class QAndroidPlatformClipboard; namespace QtAndroidClipboard { @@ -58,4 +60,6 @@ namespace QtAndroidClipboard bool registerNatives(JNIEnv *env); } +QT_END_NAMESPACE + #endif // ANDROIDJNICLIPBOARD_H diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 760da7a767..defc59abf0 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -49,6 +49,8 @@ #include +QT_BEGIN_NAMESPACE + using namespace QtAndroid; namespace QtAndroidInput @@ -758,3 +760,5 @@ namespace QtAndroidInput return true; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/androidjniinput.h b/src/plugins/platforms/android/androidjniinput.h index a78c7519db..5a7357633c 100644 --- a/src/plugins/platforms/android/androidjniinput.h +++ b/src/plugins/platforms/android/androidjniinput.h @@ -42,6 +42,9 @@ #ifndef ANDROIDJNIINPUT_H #define ANDROIDJNIINPUT_H #include +#include + +QT_BEGIN_NAMESPACE namespace QtAndroidInput { @@ -56,4 +59,6 @@ namespace QtAndroidInput bool registerNatives(JNIEnv *env); } +QT_END_NAMESPACE + #endif // ANDROIDJNIINPUT_H diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 948b012399..09c56f398c 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -76,6 +76,8 @@ Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin) +QT_BEGIN_NAMESPACE + static JavaVM *m_javaVM = NULL; static jclass m_applicationClass = NULL; static jobject m_classLoaderObject = NULL; @@ -748,8 +750,11 @@ static int registerNatives(JNIEnv *env) return JNI_TRUE; } +QT_END_NAMESPACE + Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) { + QT_USE_NAMESPACE typedef union { JNIEnv *nativeEnvironment; void *venv; diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h index c00b23fff3..29896529ca 100644 --- a/src/plugins/platforms/android/androidjnimain.h +++ b/src/plugins/platforms/android/androidjnimain.h @@ -50,6 +50,8 @@ #include +QT_BEGIN_NAMESPACE + class QRect; class QPoint; class QThread; @@ -119,4 +121,7 @@ namespace QtAndroid QString deviceName(); } + +QT_END_NAMESPACE + #endif // ANDROID_APP_H diff --git a/src/plugins/platforms/android/androidjnimenu.cpp b/src/plugins/platforms/android/androidjnimenu.cpp index dc2afe2b03..6a979b9255 100644 --- a/src/plugins/platforms/android/androidjnimenu.cpp +++ b/src/plugins/platforms/android/androidjnimenu.cpp @@ -50,6 +50,8 @@ #include #include +QT_BEGIN_NAMESPACE + using namespace QtAndroid; namespace QtAndroidMenu @@ -428,3 +430,5 @@ namespace QtAndroidMenu return true; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/androidjnimenu.h b/src/plugins/platforms/android/androidjnimenu.h index 7c5422f67b..2ae406901a 100644 --- a/src/plugins/platforms/android/androidjnimenu.h +++ b/src/plugins/platforms/android/androidjnimenu.h @@ -43,6 +43,9 @@ #define ANDROIDJNIMENU_H #include +#include + +QT_BEGIN_NAMESPACE class QAndroidPlatformMenuBar; class QAndroidPlatformMenu; @@ -66,4 +69,6 @@ namespace QtAndroidMenu bool registerNatives(JNIEnv *env); } +QT_END_NAMESPACE + #endif // ANDROIDJNIMENU_H diff --git a/src/plugins/platforms/android/androidsurfaceclient.h b/src/plugins/platforms/android/androidsurfaceclient.h index 254e47123b..94f16a8547 100644 --- a/src/plugins/platforms/android/androidsurfaceclient.h +++ b/src/plugins/platforms/android/androidsurfaceclient.h @@ -44,6 +44,8 @@ #include #include +QT_BEGIN_NAMESPACE + class AndroidSurfaceClient { public: @@ -55,4 +57,6 @@ protected: QMutex m_surfaceMutex; }; +QT_END_NAMESPACE + #endif // ANDROIDSURFACECLIENT_H diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index 224a8ca9f7..70ea3d756f 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -45,6 +45,8 @@ #include #include +QT_BEGIN_NAMESPACE + typedef QVector FilesList; struct AndroidAssetDir @@ -394,3 +396,5 @@ QAbstractFileEngine * AndroidAssetsFileEngineHandler::create(const QString &file } return 0; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h index ac16ad7b79..a48a288ebc 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h @@ -49,6 +49,8 @@ #include +QT_BEGIN_NAMESPACE + struct AndroidAssetDir; class AndroidAssetsFileEngineHandler: public QAbstractFileEngineHandler { @@ -67,4 +69,6 @@ private: mutable bool m_hasTriedPrepopulatingCache; }; +QT_END_NAMESPACE + #endif // QANDROIDASSETSFILEENGINEHANDLER_H diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp index 897feb5802..6e4b6d8255 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp @@ -47,6 +47,8 @@ #include #include +QT_BEGIN_NAMESPACE + namespace QtAndroidDialogHelpers { static jclass g_messageDialogHelperClass = 0; @@ -172,3 +174,5 @@ bool registerNatives(JNIEnv *env) return true; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.h b/src/plugins/platforms/android/qandroidplatformdialoghelpers.h index 88ec91d936..7cbe21a9f4 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.h +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.h @@ -46,6 +46,8 @@ #include #include +QT_BEGIN_NAMESPACE + namespace QtAndroidDialogHelpers { class QAndroidPlatformMessageDialogHelper: public QPlatformMessageDialogHelper @@ -74,4 +76,6 @@ bool registerNatives(JNIEnv *env); } +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMDIALOGHELPERS_H diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp index 935caed467..fd14f812a0 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp @@ -43,6 +43,8 @@ #include "qandroidplatformfontdatabase.h" +QT_BEGIN_NAMESPACE + QString QAndroidPlatformFontDatabase::fontDir() const { return QLatin1String("/system/fonts"); @@ -87,3 +89,5 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami return QString(qgetenv("QT_ANDROID_FONTS")).split(";") + m_fallbacks[script]; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.h b/src/plugins/platforms/android/qandroidplatformfontdatabase.h index cdd3cf1674..0e961f8ae8 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.h +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.h @@ -44,6 +44,8 @@ #include +QT_BEGIN_NAMESPACE + class QAndroidPlatformFontDatabase: public QBasicFontDatabase { public: @@ -58,4 +60,6 @@ private: QHash m_fallbacks; }; +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMFONTDATABASE_H diff --git a/src/plugins/platforms/android/qandroidplatformmenu.cpp b/src/plugins/platforms/android/qandroidplatformmenu.cpp index 1ecabb25e2..b602f85cd9 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenu.cpp @@ -43,6 +43,8 @@ #include "qandroidplatformmenuitem.h" #include "androidjnimenu.h" +QT_BEGIN_NAMESPACE + QAndroidPlatformMenu::QAndroidPlatformMenu() { m_tag = reinterpret_cast(this); // QMenu will overwrite this later, but we need a unique ID for QtQuick @@ -175,3 +177,5 @@ QMutex *QAndroidPlatformMenu::menuItemsMutex() { return &m_menuItemsMutex; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformmenu.h b/src/plugins/platforms/android/qandroidplatformmenu.h index 305b64168a..7858ca36ae 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.h +++ b/src/plugins/platforms/android/qandroidplatformmenu.h @@ -46,6 +46,8 @@ #include #include +QT_BEGIN_NAMESPACE + class QAndroidPlatformMenuItem; class QAndroidPlatformMenu: public QPlatformMenu { @@ -89,4 +91,6 @@ private: QMutex m_menuItemsMutex; }; +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMMENU_H diff --git a/src/plugins/platforms/android/qandroidplatformmenubar.cpp b/src/plugins/platforms/android/qandroidplatformmenubar.cpp index 134062fb32..2d457296c5 100644 --- a/src/plugins/platforms/android/qandroidplatformmenubar.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenubar.cpp @@ -43,6 +43,7 @@ #include "qandroidplatformmenu.h" #include "androidjnimenu.h" +QT_BEGIN_NAMESPACE QAndroidPlatformMenuBar::QAndroidPlatformMenuBar() { @@ -109,3 +110,5 @@ QMutex *QAndroidPlatformMenuBar::menusListMutex() { return &m_menusListMutex; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformmenubar.h b/src/plugins/platforms/android/qandroidplatformmenubar.h index 56915335c2..52882b6922 100644 --- a/src/plugins/platforms/android/qandroidplatformmenubar.h +++ b/src/plugins/platforms/android/qandroidplatformmenubar.h @@ -46,6 +46,8 @@ #include #include +QT_BEGIN_NAMESPACE + class QAndroidPlatformMenu; class QAndroidPlatformMenuBar: public QPlatformMenuBar { @@ -71,4 +73,6 @@ private: QMutex m_menusListMutex; }; +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMMENUBAR_H diff --git a/src/plugins/platforms/android/qandroidplatformmenuitem.cpp b/src/plugins/platforms/android/qandroidplatformmenuitem.cpp index bd37834d2a..4e19ec2939 100644 --- a/src/plugins/platforms/android/qandroidplatformmenuitem.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenuitem.cpp @@ -42,6 +42,8 @@ #include "qandroidplatformmenuitem.h" #include "qandroidplatformmenu.h" +QT_BEGIN_NAMESPACE + QAndroidPlatformMenuItem::QAndroidPlatformMenuItem() { m_tag = reinterpret_cast(this); // QMenu will overwrite this later, but we need a unique ID for QtQuick @@ -178,3 +180,5 @@ bool QAndroidPlatformMenuItem::isEnabled() const { return m_isEnabled; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformmenuitem.h b/src/plugins/platforms/android/qandroidplatformmenuitem.h index 5861e8e195..40c3ab2761 100644 --- a/src/plugins/platforms/android/qandroidplatformmenuitem.h +++ b/src/plugins/platforms/android/qandroidplatformmenuitem.h @@ -43,6 +43,8 @@ #define QANDROIDPLATFORMMENUITEM_H #include +QT_BEGIN_NAMESPACE + class QAndroidPlatformMenu; class QAndroidPlatformMenuItem: public QPlatformMenuItem @@ -96,4 +98,6 @@ private: bool m_isEnabled; }; +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMMENUITEM_H diff --git a/src/plugins/platforms/android/qandroidplatformservices.cpp b/src/plugins/platforms/android/qandroidplatformservices.cpp index 0df882f1f0..02fe29e576 100644 --- a/src/plugins/platforms/android/qandroidplatformservices.cpp +++ b/src/plugins/platforms/android/qandroidplatformservices.cpp @@ -44,6 +44,8 @@ #include #include +QT_BEGIN_NAMESPACE + QAndroidPlatformServices::QAndroidPlatformServices() { QtAndroid::AttachedJNIEnv env; @@ -77,3 +79,5 @@ QByteArray QAndroidPlatformServices::desktopEnvironment() const { return QByteArray("Android"); } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformservices.h b/src/plugins/platforms/android/qandroidplatformservices.h index 8368b19043..08d7773ca4 100644 --- a/src/plugins/platforms/android/qandroidplatformservices.h +++ b/src/plugins/platforms/android/qandroidplatformservices.h @@ -46,6 +46,8 @@ #include "androidjnimain.h" #include +QT_BEGIN_NAMESPACE + class QAndroidPlatformServices: public QPlatformServices { public: @@ -58,4 +60,6 @@ private: }; +QT_END_NAMESPACE + #endif // ANDROIDPLATFORMDESKTOPSERVICE_H diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp index 94e58eaeb6..1c9be189c8 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.cpp +++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp @@ -50,6 +50,8 @@ #include #include +QT_BEGIN_NAMESPACE + QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *androidPlatformNativeInterface) { m_androidPlatformNativeInterface = androidPlatformNativeInterface; @@ -240,3 +242,5 @@ QPlatformDialogHelper *QAndroidPlatformTheme::createPlatformDialogHelper(QPlatfo return 0; } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformtheme.h b/src/plugins/platforms/android/qandroidplatformtheme.h index fecd7ca8e9..c37c9986c6 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.h +++ b/src/plugins/platforms/android/qandroidplatformtheme.h @@ -45,6 +45,8 @@ #include #include +QT_BEGIN_NAMESPACE + class QAndroidPlatformNativeInterface; class QAndroidPlatformTheme: public QPlatformTheme { @@ -66,4 +68,6 @@ private: QPalette m_defaultPalette; }; +QT_END_NAMESPACE + #endif // QANDROIDPLATFORMTHEME_H -- cgit v1.2.3 From 50cf698b76bd140a4ada4058f9abbee837289a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 16 Jun 2014 13:35:21 +0200 Subject: Android: Fix hover-event handling. The accessibility delegate needs to intercept the hover events before the view gets them, but since the dispatchHoverEvent() method was added in API level 14 and we build with API level < 14, we can't call the super class implementation (e.g., when the event isn't handled by the accessibility delegate). In the previous implementation we where trying to solve this by using the reflection API, but that does not provide a solution to call the super class implementation (Note: It's possible with JDK 7 or newer), so the code would call itself recursively and we would eventually get a stack overflow exception. This change uses the OnHoverListener class to intercept the hover events, this way we avoid "overriding" the dispatchHoverEvent() method in QtSurface and therefore avoid the problem it causes. Task-number: QTBUG-38905 Change-Id: I8b3cbad718d8524042397bb877e39e3005bfb4ce Reviewed-by: Frederik Gladhorn --- .../android/accessibility/QtAccessibilityDelegate.java | 13 ++++++++++++- .../jar/src/org/qtproject/qt5/android/QtSurface.java | 18 ------------------ 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java b/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java index 70b02d8d04..3275b90e33 100644 --- a/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java +++ b/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java @@ -53,6 +53,7 @@ import android.text.TextUtils; import android.view.accessibility.*; import android.view.MotionEvent; +import android.view.View.OnHoverListener; import android.content.Context; @@ -85,9 +86,19 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate // the offset of the view on screen into account (eg status bar on top) private final int[] m_globalOffset = new int[2]; + private class HoverEventListener implements View.OnHoverListener + { + @Override + public boolean onHover(View v, MotionEvent event) + { + return dispatchHoverEvent(event); + } + } + public QtAccessibilityDelegate(View host) { m_view = host; + m_view.setOnHoverListener(new HoverEventListener()); m_manager = (AccessibilityManager) host.getContext() .getSystemService(Context.ACCESSIBILITY_SERVICE); @@ -103,7 +114,7 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate // For "explore by touch" we need all movement events here first // (user moves finger over screen to discover items on screen). - public boolean dispatchHoverEvent(MotionEvent event) + private boolean dispatchHoverEvent(MotionEvent event) { if (!m_manager.isTouchExplorationEnabled()) { return false; diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java index 45a80a3dbb..ca3f20f11b 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java @@ -110,24 +110,6 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback } } - public boolean dispatchHoverEvent(MotionEvent event) { - // Always attempt to dispatch hover events to accessibility first. - if (m_accessibilityDelegate != null) { - try { - Method dispHoverA11y = m_accessibilityDelegate.getClass().getMethod("dispatchHoverEvent", MotionEvent.class); - boolean ret = (Boolean) dispHoverA11y.invoke(m_accessibilityDelegate, event); - if (ret) - return true; - SurfaceView view = (SurfaceView) this; - Method dispHoverView = view.getClass().getMethod("dispatchHoverEvent", MotionEvent.class); - return (Boolean) dispHoverView.invoke(view, event); - } catch (Exception e) { - Log.w("Qt A11y", "EXCEPTION in dispatchHoverEvent for Accessibility: " + e); - } - } - return false; - } - @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { -- cgit v1.2.3 From 83f06da1c6bffff61af78cbe75a0691d53742b53 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 26 Jun 2014 20:18:35 +0200 Subject: Mac Style: Fix QLineEdit frame in 10.10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also removes some dead code. Change-Id: Id590bd56641918a163f8bad251e3e0e750adfc6f Reviewed-by: Jake Petroules Reviewed-by: Morten Johan Sørvig --- src/widgets/styles/qmacstyle_mac.mm | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 8cb7ce1c87..0084bf68dc 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -3186,17 +3186,15 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai fdi.version = qt_mac_hitheme_version; fdi.state = tds; SInt32 frame_size; - if (pe == PE_FrameLineEdit) { - fdi.kind = frame->features & QStyleOptionFrame::Rounded ? kHIThemeFrameTextFieldRound : - kHIThemeFrameTextFieldSquare; - GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); - if ((frame->state & State_ReadOnly) || !(frame->state & State_Enabled)) - fdi.state = kThemeStateInactive; - } else { - baseColor = QColor(150, 150, 150); //hardcoded since no query function --Sam - fdi.kind = kHIThemeFrameListBox; - GetThemeMetric(kThemeMetricListBoxFrameOutset, &frame_size); - } + fdi.kind = frame->features & QStyleOptionFrame::Rounded ? kHIThemeFrameTextFieldRound : + kHIThemeFrameTextFieldSquare; + GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); + if ((frame->state & State_ReadOnly) || !(frame->state & State_Enabled)) + fdi.state = kThemeStateInactive; + else if (fdi.state == kThemeStatePressed) + // This pressed state doesn't make sense for a line edit frame. + // And Yosemite agrees with us. Otherwise it starts showing yellow pixels. + fdi.state = kThemeStateActive; fdi.isFocused = (frame->state & State_HasFocus); int lw = frame->lineWidth; if (lw <= 0) -- cgit v1.2.3