From 05ddae12d18a348afd942fd85a8d8773698da3a1 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 15 Aug 2013 10:45:51 +0200 Subject: Android: Fix orientation change on Android 4.3 In Android 4.3, we will get a new native window pointer for the same surface (the old surface has not been destroyed), whereas before we would get the same pointer, thus hitting the "sameNativeWindow" branch. This revealed some bugs in the surfaceChanged code path when the old surface had not been destroyed. This path is now taken both when there's no old surface (the app has been suspended in the mean time) and when the orientation changes. To handle the second case, we need to make sure: 1. We update the static pointer 2. We update the pointers in the platform windows 3. We don't add a second reference to the static data for windows 4. We schedule an update of the window size Task-number: QTBUG-32878 Change-Id: I47257615f9ba820315fc98d7a804e52223f430bf Reviewed-by: Christian Stromme Reviewed-by: Frederik Gladhorn --- .../platforms/android/src/androidjnimain.cpp | 40 ++++++++++++---------- .../src/opengl/qandroidopenglplatformwindow.cpp | 21 ++++++++++-- .../src/opengl/qandroidopenglplatformwindow.h | 2 ++ .../android/src/qandroidplatformintegration.cpp | 1 + 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/plugins/platforms/android/src/androidjnimain.cpp b/src/plugins/platforms/android/src/androidjnimain.cpp index 162a8aa977..74183b3107 100644 --- a/src/plugins/platforms/android/src/androidjnimain.cpp +++ b/src/plugins/platforms/android/src/androidjnimain.cpp @@ -555,33 +555,37 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jobject jSurface) m_nativeWindow = nativeWindow; if (m_waitForWindow) m_waitForWindowSemaphore.release(); - if (m_androidPlatformIntegration && !sameNativeWindow) { - m_surfaceMutex.unlock(); - m_androidPlatformIntegration->surfaceChanged(); - } else if (m_androidPlatformIntegration && sameNativeWindow) { - QPlatformScreen *screen = m_androidPlatformIntegration->screen(); + + if (m_androidPlatformIntegration) { QSize size = QtAndroid::nativeWindowSize(); + QPlatformScreen *screen = m_androidPlatformIntegration->screen(); QRect geometry(QPoint(0, 0), size); QWindowSystemInterface::handleScreenAvailableGeometryChange(screen->screen(), geometry); QWindowSystemInterface::handleScreenGeometryChange(screen->screen(), geometry); - // Resize all top level windows, since they share the same surface - foreach (QWindow *w, QGuiApplication::topLevelWindows()) { - QAndroidOpenGLPlatformWindow *window = - static_cast(w->handle()); - - if (window != 0) { - window->lock(); - window->scheduleResize(size); - - QWindowSystemInterface::handleExposeEvent(window->window(), - QRegion(window->window()->geometry())); - window->unlock(); + if (!sameNativeWindow) { + m_surfaceMutex.unlock(); + m_androidPlatformIntegration->surfaceChanged(); + } else { + // Resize all top level windows, since they share the same surface + foreach (QWindow *w, QGuiApplication::topLevelWindows()) { + QAndroidOpenGLPlatformWindow *window = + static_cast(w->handle()); + + if (window != 0) { + window->lock(); + window->scheduleResize(size); + + QWindowSystemInterface::handleExposeEvent(window->window(), + QRegion(window->window()->geometry())); + window->unlock(); + } } + + m_surfaceMutex.unlock(); } - m_surfaceMutex.unlock(); } else { m_surfaceMutex.unlock(); } diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp index 5362906e0e..b1a2231ff5 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp @@ -85,9 +85,19 @@ void QAndroidOpenGLPlatformWindow::invalidateSurface() } } +void QAndroidOpenGLPlatformWindow::updateStaticNativeWindow() +{ + QWriteLocker locker(&m_staticSurfaceLock); + m_staticNativeWindow = QtAndroid::nativeWindow(false); +} + void QAndroidOpenGLPlatformWindow::resetSurface() { - m_referenceCount.ref(); + // Only add a reference if we're not already holding one, otherwise we're just updating + // the native window pointer + if (m_window == 0) + m_referenceCount.ref(); + if (m_staticSurface == 0) { QWriteLocker locker(&m_staticSurfaceLock); QEglFSWindow::resetSurface(); @@ -95,12 +105,17 @@ void QAndroidOpenGLPlatformWindow::resetSurface() m_staticNativeWindow = m_window; } else { QReadLocker locker(&m_staticSurfaceLock); - Q_ASSERT(m_staticSurface != m_surface); m_window = m_staticNativeWindow; m_surface = m_staticSurface; } - QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); // Expose event + { + lock(); + scheduleResize(QtAndroid::nativeWindowSize()); + QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); // Expose event + unlock(); + } + QWindowSystemInterface::flushWindowSystemEvents(); } diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h index 36a110e1a8..9a25957ccd 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h @@ -71,6 +71,8 @@ public: void destroy(); + static void updateStaticNativeWindow(); + private: QSize m_scheduledResize; QMutex m_lock; diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp index 91ad2b368f..636a2b3853 100644 --- a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp @@ -162,6 +162,7 @@ void QAndroidPlatformIntegration::invalidateNativeSurface() void QAndroidPlatformIntegration::surfaceChanged() { + QAndroidOpenGLPlatformWindow::updateStaticNativeWindow(); foreach (QWindow *w, QGuiApplication::topLevelWindows()) { QAndroidOpenGLPlatformWindow *window = static_cast(w->handle()); -- cgit v1.2.3 From f9da1a21a862ab2964c0e9f366a6cc6e4932ad21 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Mon, 19 Aug 2013 12:30:38 +0200 Subject: Add changes-5.1.1 file Change-Id: I8b447d1f30918fd31f00bd56cc3eb2f203b847a3 Reviewed-by: Jani Heikkinen Reviewed-by: Iikka Eklund --- dist/changes-5.1.1 | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 dist/changes-5.1.1 diff --git a/dist/changes-5.1.1 b/dist/changes-5.1.1 new file mode 100644 index 0000000000..85309074ed --- /dev/null +++ b/dist/changes-5.1.1 @@ -0,0 +1,206 @@ +Qt 5.1.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.1.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.1/ + +The Qt version 5.1 series is binary compatible with the 5.0.x series. +Applications compiled for 5.0 will continue to run with 5.1. + +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. + + +**************************************************************************** +* General * +**************************************************************************** + + - Add support for Visual Studio 2013 + - Remove obsolete 'register' C keyword + - Speed up font database loading with fontconfig + - [QTBUG-32284] Fix incomplete override of QIODevice::open in QProcess and QLocalSocket + +**************************************************************************** +* Library * +**************************************************************************** + +QtCore +------ + + - Add basic conversion functions from QVariant(QJsonValue) + - Fix crash when re-creating QThreadData after initially destroying it + - Fix the host_bins variable in the QtCore pkg-config file + - QUrl stringprep: fix handling of U+0080: it's prohibited + - QUrl stringprep: avoid recalculating the surrogates we already know + - QUrl stringprep: fix handling of prohibited characters + - QUrl stringprep: fix case folding from non-BMP to BMP + - QUrl stringprep: recalculate the current position if the size changes + - [QTBUG-24345] Prevent negative size in QBitArray, QVector and QVarLengthArray ctors + - [QTBUG-25732] Mention QRect's int min/max constraints in detailed description + - [QTBUG-29391] fix infinite loop in QProcessPrivate::drainOutputPipes + - [QTBUG-29391] QWinOverlappedIoNotifier: fix race condition + - [QTBUG-31341] Fix watch of files/folders with special characters + - [QTBUG-31606] Fix dead lock in the Qt event handling + - [QTBUG-31926] Fix the number precision in QJsonDocument.toJson() again + - [QTBUG-32100] Remove default argument from declarations of qHash as friend + - [QTBUG-32314] QDir::mkpath shouldn't fail if parent directory denies access + - [QTBUG-32354] fix endless loop in QProcess/Win drainOutputPipes + - [QTBUG-32500] Ensure that the user codecs are listed in QTextCodec::availableCodecs + +QtDBus +------ + + - [QTBUG-27973] Fix disconnectFrom{Peer,Bus} when the connection failed + - [QTBUG-31932] Don't crash if the relayed signal was emitted from the wrong thread + - [QTBUG-32374] Fix QDBusAbstractInterface::isValid() for peer connections + +QtGui +----- + + - Restore smooth-scaled drawing of 0.5x-2.0x scaled glyphs in the GL engine + - QIcon: Avoid fetching twice the same pixmap + - Fix FBO restoring in QOpenGLTextureGlyphCache + - [QTBUG-28284] Set projection matrix for systems with OpenGL 3.1 + - [QTBUG-31443] QPdfWriter: Fix setting of paper size + - [QTBUG-32193] REG: Fix crash when mixing projected/unprojected text painting + - [QTBUG-32433] Detect popup window correctly in modal window blocked handling + +QtNetwork +--------- + + - Correct algorithm for digest auth when using the CONNECT verb + - Add reconnect attempts in more cases in QHttpNetworkConnectionChannel + - [QTBUG-32404] HTTP internals: do not access reply that was deleted already + - [QTBUG-32534] QHttpMultiPart: fix data corruption in readData method + +QtPrintSupport +-------------- + + - [QTBUG-31790] Initialize UI of widget-based dialog. + +QtWidgets +--------- + + - Display sizegrip on QMdiSubWindows, even on OS X 10.7 and later + - Check if widget inherits from QTextEdit when drawing the frame + - Fix QWidget::isActiveWindow for window containers + - Hide placeholder text when QLineEdit has preedit text + - [QTBUG-19036] Make *ItemBoundingRect modes work with custom shapes. + - [QTBUG-29945] Fix dropshadow and blur graphics effects + - [QTBUG-31044] QDockWidget: Keep position when undocking + - [QTBUG-31569] If a QWidget is ignored for auto-quit, ignore its corresponding QWindow + - [QTBUG-31664] Recognize separator item in QMenu + - [QTBUG-31904] Fix rotation of text in vertical QDockWidget titlebars in QFusionStyle + - [QTBUG-32054] Set correct cell when selecting custom color cell with arrow keys + - [QTBUG-32061] Fix the cursor position of an empty QLineEdit with a placeholder text + - [QTBUG-32177] Search toplevel when setting the active window from focus window + - [QTBUG-32260] Consider virtual screen when determining dock widget visibility + + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Qt for Linux +------------ + + - XCB: Don't use Xlib's XBell() function + - XCB: Append 0-character to atom name string + - Resolve modifier mask conflicts on X11 + - Fix system tray icon on X11 + - [QTBUG-31418] Fix for when we don't have XSettings + - [QTBUG-32274] Fix handling of non-latin1 shortcuts + +Qt for Mac +---------- + + - Disable window restoration for the Mac font panel + - Simplify qt_mac_cgimage_to_nsimage code + - QMacStyle: fix auto-default button animation + - Make the macx-xcode spec a wrapper around the default spec + - Scope cached Mac SDK tool values by mkspec + - Further followup to Q_OS_MACX changes + - Fix QSpinBox clipping issue on Mac when frame=false + - QMacStyle: enable scroll style changes for non-QScrollBars + - Support Mac key equivalent Cmd+Period + - Re-establish platform menu QObject hierarchy + - [QTBUG-28336] Fixed broken prl files in debug-and-release framework builds of qt + - [QTBUG-31477] Let Cocoa pick the right pixmap for menu item icons + - [QTBUG-31532] Don't update the menubar when popups are shown + - [QTBUG-31619] Cocoa save file dialog behavior fix + - [QTBUG-31819] Fix shared color panel usage + - [QTBUG-31562] Fix for OS X QFileDialog showing bundle as directory + - [QTBUG-32440] Avoid a potential crash in unignoredChildren + - [QTBUG-32831] Don't release the printer after using it to change a property + +Qt for Windows +-------------- + + - Clear window under mouse in destruction of platform window + - Prevent activation of windows with Qt::WindowDoesNotAcceptFocus + - Better errorhandling for the fontengine on WINCE + - Windows: Synthesize expose event for shrinking windows + - Windows font database: Resolve aliases for extra fonts + - Bugfix QDesktopServices on Windows + - ActiveQt: Pass native parent handle property from widget to widget window + - REG: Fix character size when exporting PDF on Windows + - Fix crash caused by ~QWindowsWindow flushing the event queue + - Show native file dialog on Windows XP Professional x64 Edition + - Fix detection of synthesized mouse events for MSVC / 64bit + - Display a message box if platform plugin cannot be found + - Fix auto-enabling of windows style + - Fixes QKeyEvent::count() on Windows + +Qt for BlackBerry +----------------- + + - Disable xkbcommon when building for QNX from Windows + - [QTBUG-32385] Handle Qt::WindowDoesNotAcceptFocus correctly + +Qt for Android +-------------- + + - Get SSL root certificates from TrustManager + - Adjust to new SDK layout on Windows + - Make PCRE's JIT work on Android devices + +Qt for iOS +---------- + + - iOS: Make sure we're deleting framebuffers in the right context + +**************************************************************************** +* Tools * +**************************************************************************** + +- configure + + * [QTBUG-5366] Complain about bad arguments to -make/-nomake + * [QTBUG-21778] Catch accidental use of -no-make + * [QTBUG-28763] Don't enable EGL support if OpenGL is disabled + +- cmake config files + + * Use absolute path in the /usr move workaround if -libdir is specified + * Always use forward slashes in paths passed to cmake + * Make clients use the QT_NO_DEBUG flag when using QtCore in release mode + * [QTBUG-32134] Add path to the headers in frameworks to the include dirs + * [QTBUG-32466] Don't check for the existence of private include directories + +- qmake + + * [QTBUG-5301] basic manifest tool support in vc(x)proj generator + * [QTBUG-19352] Resolve output of .depend_command relative to $$OUT_PWD + * [QTBUG-29826] Only add the res_file to the generated files if there is no rc_file + * [QTBUG-29988] VPATH resolution: don't crash when $(FOO) expands to nothing + * [QTBUG-30993] Changed project dependencies for solution files + * [QTBUG-31877] Make $$list() more backwards-compatible regarding backslashes + * [QTBUG-31975] MANIFEST:NO is not written to vcproj + * [QTBUG-32326] Escape paths coming from prl files -- cgit v1.2.3 From c15a8cc283d5d7b26677b9c71cabb1f5f47494f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 21 Aug 2013 15:05:19 +0200 Subject: Don't use qt_mac_get_fixed_pitch() to resolve fixed pitch fonts on OSX The call was resulting in inifinite recursion on OSX 10.9 when Qt was built against the 10.7 SDK, as qt_mac_get_fixed_pitch uses QFontMetrics to resolve the pitch, and we would end up in the font resolver again when asking for the metrics. The CoreText font-database already takes care of resolving whether or not a font family is fixed-pitch, so the code is likely a leftover from the ATSUI-days, and can be removed. Task-number: QTBUG-31803 Change-Id: I37c90fa637927eb4adc16c0fd556c4c46c456034 Reviewed-by: Gabriel de Dietrich (cherry picked from commit bd9a023a41209a216eec28bd25a20372a5172b6a) Reviewed-by: Jani Heikkinen Reviewed-by: Iikka Eklund --- src/gui/text/qfontdatabase.cpp | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 62379cd592..54b4629ca0 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -314,9 +314,6 @@ struct QtFontFamily QtFontFamily(const QString &n) : fixedPitch(false), -#if !defined(QWS) && defined(Q_OS_MAC) - fixedPitchComputed(false), -#endif name(n), count(0), foundries(0) , bogusWritingSystems(false) , askedForFallback(false) @@ -330,9 +327,6 @@ struct QtFontFamily } bool fixedPitch : 1; -#if !defined(QWS) && defined(Q_OS_MAC) - bool fixedPitchComputed : 1; -#endif QString name; QStringList aliases; @@ -348,18 +342,6 @@ struct QtFontFamily QtFontFoundry *foundry(const QString &f, bool = false); }; -#if !defined(QWS) && defined(Q_OS_MAC) -inline static void qt_mac_get_fixed_pitch(QtFontFamily *f) -{ - if(f && !f->fixedPitchComputed) { - QFontMetrics fm(f->name); - f->fixedPitch = fm.width(QLatin1Char('i')) == fm.width(QLatin1Char('m')); - f->fixedPitchComputed = true; - } -} -#endif - - QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) { if (f.isNull() && count == 1) @@ -823,9 +805,6 @@ unsigned int bestFoundry(int script, unsigned int score, int styleStrategy, EncodingMismatch = 0x0002 }; if (pitch != '*') { -#if !defined(QWS) && defined(Q_OS_MAC) - qt_mac_get_fixed_pitch(const_cast(family)); -#endif if ((pitch == 'm' && !family->fixedPitch) || (pitch == 'p' && family->fixedPitch)) this_score += PitchMismatch; @@ -1263,9 +1242,6 @@ bool QFontDatabase::isFixedPitch(const QString &family, QT_PREPEND_NAMESPACE(load)(familyName); QtFontFamily *f = d->family(familyName); -#if !defined(QWS) && defined(Q_OS_MAC) - qt_mac_get_fixed_pitch(f); -#endif return (f && f->fixedPitch); } -- cgit v1.2.3 From be72ea7e35d611c9fef453b1e7dd36f89d166ff7 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 27 Aug 2013 12:03:42 +0200 Subject: Do not attempt to save a file in the resources A wrong code path caused the textedit example to attempting to try to save the file it was currently editing even if it was loaded from the resource system. Task-number: QTBUG-33105 Change-Id: I9e03168968a98a421e8ab93a8d06f808b72ac3b0 Reviewed-by: Friedemann Kleint --- examples/widgets/richtext/textedit/textedit.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp index ae2bdedf13..873a29eb0e 100644 --- a/examples/widgets/richtext/textedit/textedit.cpp +++ b/examples/widgets/richtext/textedit/textedit.cpp @@ -436,8 +436,7 @@ bool TextEdit::maybeSave() { if (!textEdit->document()->isModified()) return true; - if (fileName.startsWith(QLatin1String(":/"))) - return true; + QMessageBox::StandardButton ret; ret = QMessageBox::warning(this, tr("Application"), tr("The document has been modified.\n" @@ -485,6 +484,8 @@ bool TextEdit::fileSave() { if (fileName.isEmpty()) return fileSaveAs(); + if (fileName.startsWith(QStringLiteral(":/"))) + return fileSaveAs(); QTextDocumentWriter writer(fileName); bool success = writer.write(textEdit->document()); -- cgit v1.2.3 From 5cb6260a36d2e98e72c828b7e2559fa3e7a35361 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 26 Aug 2013 16:22:24 +0200 Subject: QNetworkReply auto test: Skip tests failing due to Squid issues This test works with no Qt version (4 or 5) when testing with the Squid (HTTP proxy) version deployed on the new test server image. Task-number: QTBUG-33180 Change-Id: If244526a4baed9f3836dade007fe0f15649a8f86 Reviewed-by: Thiago Macieira --- tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index ce8293edbc..5d81367620 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -4387,6 +4387,10 @@ void tst_QNetworkReply::ioPostToHttpFromSocket_data() void tst_QNetworkReply::ioPostToHttpFromSocket() { + if (QTest::currentDataTag() == QByteArray("128k+1+proxyauth") + || QTest::currentDataTag() == QByteArray("128k+1+auth+proxyauth")) + QSKIP("Squid cannot handle authentication with POST data >= 64K (QTBUG-33180)"); + QFETCH(QByteArray, data); QFETCH(QUrl, url); QFETCH(QNetworkProxy, proxy); -- cgit v1.2.3 From 2109965a4e4e54a264c7bcb8a89a27194870a73a Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 27 Aug 2013 14:29:15 +0200 Subject: QTcpSocket auto test: rely on IMAP port, not SMTP port The new test server image will not have a SMTP service installed, and the network self test does not check for that either. Change-Id: I1063777832148e184de4ddf21d9154364f644e1e Reviewed-by: Richard J. Moore --- 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 2b9dfc5081..9135ec3d19 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -1578,7 +1578,7 @@ void tst_QTcpSocket::recursiveReadyRead() QSignalSpy spy(testSocket, SIGNAL(readyRead())); - testSocket->connectToHost(QtNetworkSettings::serverName(), 25); + testSocket->connectToHost(QtNetworkSettings::serverName(), 143); enterLoop(30); QVERIFY2(!timeout(), "Timed out when connecting to QtNetworkSettings::serverName()."); -- cgit v1.2.3 From 5bb4817142f47326a320b316cd1967ecfd501c13 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 27 Aug 2013 14:10:53 +0200 Subject: Center widgets using UpdateWidgets in tst_qwidget. Try to stabilize doubleRepaint and others, try to get them away from taskbar areas. Change-Id: Icae8da575999afccb314edafd7deb16446e3d1c2 Reviewed-by: Frederik Gladhorn --- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 0085b75299..227f61b0a3 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -164,6 +164,12 @@ static inline void setFrameless(QWidget *w) w->setWindowFlags(flags); } +static inline void centerOnScreen(QWidget *w) +{ + const QPoint offset = QPoint(w->width() / 2, w->height() / 2); + w->move(QGuiApplication::primaryScreen()->availableGeometry().center() - offset); +} + class tst_QWidget : public QObject { Q_OBJECT @@ -4004,7 +4010,8 @@ void tst_QWidget::update() Q_CHECK_PAINTEVENTS UpdateWidget w; - w.setGeometry(50, 50, 100, 100); + w.resize(100, 100); + centerOnScreen(&w); w.show(); QVERIFY(QTest::qWaitForWindowExposed(&w)); @@ -7647,6 +7654,7 @@ void tst_QWidget::doubleRepaint() QSKIP("QTBUG-30566 - Unstable auto-test"); #endif UpdateWidget widget; + centerOnScreen(&widget); widget.setFocusPolicy(Qt::StrongFocus); // Filter out activation change and focus events to avoid update() calls in QWidget. widget.updateOnActivationChangeAndFocusIn = false; @@ -7774,6 +7782,7 @@ void tst_QWidget::setMaskInResizeEvent() UpdateWidget w; w.reset(); w.resize(200, 200); + centerOnScreen(&w); w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); w.raise(); @@ -7851,6 +7860,7 @@ void tst_QWidget::immediateRepaintAfterShow() QSKIP("We don't support immediate repaint right after show on other platforms."); UpdateWidget widget; + centerOnScreen(&widget); widget.show(); qApp->processEvents(); // On X11 in particular, we are now waiting for a MapNotify event before @@ -7867,6 +7877,7 @@ void tst_QWidget::immediateRepaintAfterInvalidateBuffer() QSKIP("We don't support immediate repaint right after show on other platforms."); QScopedPointer widget(new UpdateWidget); + centerOnScreen(widget.data()); widget->show(); QVERIFY(QTest::qWaitForWindowExposed(widget.data())); QTest::qWait(200); @@ -8282,6 +8293,7 @@ void tst_QWidget::setClearAndResizeMask() { UpdateWidget topLevel; topLevel.resize(160, 160); + centerOnScreen(&topLevel); topLevel.show(); qApp->setActiveWindow(&topLevel); QVERIFY(QTest::qWaitForWindowActive(&topLevel)); @@ -8434,6 +8446,7 @@ void tst_QWidget::maskedUpdate() { UpdateWidget topLevel; topLevel.resize(200, 200); + centerOnScreen(&topLevel); const QRegion topLevelMask(50, 50, 70, 70); topLevel.setMask(topLevelMask); @@ -8859,6 +8872,7 @@ void tst_QWidget::focusWidget_task254563() void tst_QWidget::destroyBackingStore() { UpdateWidget w; + centerOnScreen(&w); w.reset(); w.show(); -- cgit v1.2.3 From 78d7192338e2cbba0c9b53c429d35b9437b7e1cd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 27 Aug 2013 11:58:34 +0200 Subject: Close menu on 2nd click on QMenuBar. Task-number: QTBUG-32807 Change-Id: I0c3c25c6acf92bc30c1bcfc09003209b572ec777 Reviewed-by: Joerg Bornemann --- src/widgets/widgets/qmenubar.cpp | 1 + .../auto/widgets/widgets/qmenubar/tst_qmenubar.cpp | 25 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index f22c48b26f..a7cad28df3 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -1054,6 +1054,7 @@ void QMenuBar::mousePressEvent(QMouseEvent *e) if(QMenu *menu = d->activeMenu) { d->activeMenu = 0; menu->hide(); + d->closePopupMode = 1; } } else { d->setCurrentAction(action, true); diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp index e7450fdd2c..174753d8be 100644 --- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp +++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include @@ -145,6 +146,7 @@ private slots: void taskQTBUG4965_escapeEaten(); #endif void taskQTBUG11823_crashwithInvisibleActions(); + void closeOnSecondClick(); protected slots: void onActivated( QAction*); @@ -1318,5 +1320,28 @@ void tst_QMenuBar::taskQTBUG11823_crashwithInvisibleActions() QCOMPARE(menubar.activeAction(), m); //the active action shouldn't have changed } +void tst_QMenuBar::closeOnSecondClick() // QTBUG-32807, menu should close on 2nd click. +{ + QMainWindow mainWindow; + mainWindow.resize(300, 200); + mainWindow.move(QGuiApplication::primaryScreen()->geometry().center() - QPoint(150, 100)); +#ifndef QT_NO_CURSOR + QCursor::setPos(mainWindow.geometry().topLeft() - QPoint(100, 0)); +#endif + QMenuBar *menuBar = mainWindow.menuBar(); + menuBar->setNativeMenuBar(false); + QMenu *fileMenu = menuBar->addMenu(QStringLiteral("closeOnSecondClick")); + fileMenu->addAction(QStringLiteral("Quit")); + mainWindow.show(); + QApplication::setActiveWindow(&mainWindow); + QVERIFY(QTest::qWaitForWindowActive(&mainWindow)); + const QPoint center = menuBar->actionGeometry(fileMenu->menuAction()).center(); + QTest::mouseMove(menuBar, center); + QTest::mouseClick(menuBar, Qt::LeftButton, 0, center); + QTRY_VERIFY(fileMenu->isVisible()); + QTest::mouseClick(menuBar, Qt::LeftButton, 0, center); + QTRY_VERIFY(!fileMenu->isVisible()); +} + QTEST_MAIN(tst_QMenuBar) #include "tst_qmenubar.moc" -- cgit v1.2.3 From 59ee3e5db6cf0b97682cd1b3bc2a6decbca1cb1d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 26 Aug 2013 16:13:54 +0200 Subject: export QT_TOOL_ENV to the tool module pri file fixes "make ts" in qttranslations in a non-installed prefix build. amends 13e01fda1 Change-Id: I2547d825c1c71e42fdacab5edaace67247ef69e7 Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_functions.prf | 1 + mkspecs/features/qt_tool.prf | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 07821fd09b..31b7607d6e 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -206,6 +206,7 @@ defineTest(qtPrepareTool) { } } } + QT_TOOL_ENV += $$eval(QT_TOOL.$${2}.envvars) !isEmpty(3) { $$1$$3 = $$system_path($$eval($$1)) qtAddTargetEnv($$1$$3, QT_TOOL.$${2}.depends, system) diff --git a/mkspecs/features/qt_tool.prf b/mkspecs/features/qt_tool.prf index 9a6b9634e0..f0f0fe567b 100644 --- a/mkspecs/features/qt_tool.prf +++ b/mkspecs/features/qt_tool.prf @@ -27,9 +27,28 @@ CONFIG += console TOOL_PRI = $$MODULE_QMAKE_OUTDIR/mkspecs/modules/qt_tool_$${MODULE}.pri + vars = binary depends + !isEmpty(QT_TOOL_ENV) { + vars += envvars + module_var_names = + module_var_sets = + for(var, QT_TOOL_ENV) { + vars += env.$${var}.name env.$${var}.value + module_var_names += QT_TOOL.$${MODULE}.env.$${var} + module_var_sets += \ + "QT_TOOL.$${MODULE}.env.$${var}.name = $$val_escape($${var}.name)" \ + "QT_TOOL.$${MODULE}.env.$${var}.value = $$val_escape($${var}.value)" + } + module_envvars = \ + "QT_TOOL.$${MODULE}.envvars = $$module_var_names" \ + $$module_var_sets + } else { + module_envvars = + } TOOL_PRI_CONT = \ "QT_TOOL.$${MODULE}.binary = $$QMAKE_RESOLVED_TARGET" \ - "QT_TOOL.$${MODULE}.depends =$$join(MODULE_DEPENDS, " ", " ")" + "QT_TOOL.$${MODULE}.depends =$$join(MODULE_DEPENDS, " ", " ")" \ + $$module_envvars write_file($$TOOL_PRI, TOOL_PRI_CONT)|error("Aborting.") # Then, inject the new tool into the current cache state @@ -39,7 +58,7 @@ CONFIG += console unset(added) } include($$TOOL_PRI) - for(var, $$list(binary depends)): \ + for(var, vars): \ cache(QT_TOOL.$${MODULE}.$$var, transient) } -- cgit v1.2.3 From ad4bda8b754a5fb4f7c6d5c4c3b941579df83c41 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 22 Aug 2013 15:25:29 +0200 Subject: Doc: update Project Options section in qmake Manual Explain which mkspecs have the configuration option precompile_header set. Task-number: QTBUG-25683 Change-Id: I9b11eafad16b65523cbb90897fe88829add58bea Reviewed-by: Oswald Buddenhagen --- qmake/doc/src/qmake-manual.qdoc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index 38217cb891..b4af1cd8b8 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -4005,8 +4005,10 @@ include the precompiled header file in \c HEADERS, as qmake will do this if the configuration supports precompiled headers. - All platforms that support precompiled headers have the configuration - option \c precompile_header set. Using this option, you may trigger + The MSVC and g++ specs targeting Windows (and Windows CE) enable + \c precompile_header by default. + + Using this option, you may trigger conditional blocks in your project file to add settings when using precompiled headers. For example: -- cgit v1.2.3 From b7f7edfae4d5dc7e7547c3377c73129a9c6fdae0 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 26 Aug 2013 19:51:57 +0200 Subject: de-duplicate code for writing dummy makefiles as a side effect, this fixes the generators that were more bitrotted (nmake and even more mingw). Task-number: QTBUG-30644 #close Change-Id: Iefa3f07125884412d091aa12b44935e5b1fb858a Reviewed-by: Rafael Roquetto Reviewed-by: Joerg Bornemann --- qmake/generators/makefile.cpp | 18 ++++++++++++++++++ qmake/generators/makefile.h | 1 + qmake/generators/unix/unixmake2.cpp | 13 +------------ qmake/generators/win32/mingw_make.cpp | 8 +------- qmake/generators/win32/msvc_nmake.cpp | 11 +---------- 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 98b5a328e4..f68e283862 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -2202,6 +2202,24 @@ MakefileGenerator::writeExtraVariables(QTextStream &t) } } +bool +MakefileGenerator::writeDummyMakefile(QTextStream &t) +{ + if (project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) + return false; + t << "QMAKE = " << var("QMAKE_QMAKE") << endl; + const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); + for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) + t << *it << " "; + t << "first all clean install distclean uninstall qmake_all:\n\t" + << "@echo \"Some of the required modules (" + << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"\n\t" + << "@echo \"Skipped.\"\n\n"; + writeMakeQmake(t); + t << "FORCE:\n\n"; + return true; +} + bool MakefileGenerator::writeStubMakefile(QTextStream &t) { diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index 47acc8098f..09327c599c 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -104,6 +104,7 @@ protected: void writeExtraTargets(QTextStream &t); void writeExtraCompilerTargets(QTextStream &t); void writeExtraCompilerVariables(QTextStream &t); + bool writeDummyMakefile(QTextStream &t); virtual bool writeStubMakefile(QTextStream &t); virtual bool writeMakefile(QTextStream &t); diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index cd6f441472..2373059f79 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -80,19 +80,8 @@ UnixMakefileGenerator::writeMakefile(QTextStream &t) { writeHeader(t); - if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) { - t << "QMAKE = " << var("QMAKE_QMAKE") << endl; - const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); - for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) - t << *it << " "; - t << "first all clean install distclean uninstall qmake_all:\n\t" - << "@echo \"Some of the required modules (" - << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"\n\t" - << "@echo \"Skipped.\"\n\n"; - writeMakeQmake(t); - t << "FORCE:\n\n"; + if (writeDummyMakefile(t)) return true; - } if (project->values("TEMPLATE").first() == "app" || project->values("TEMPLATE").first() == "lib" || diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 38e6c56bb5..29b27cb7d7 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -114,14 +114,8 @@ bool MingwMakefileGenerator::findLibraries() bool MingwMakefileGenerator::writeMakefile(QTextStream &t) { writeHeader(t); - if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) { - t << "all clean:\n\t" - << "@echo \"Some of the required modules (" - << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"\n\t" - << "@echo \"Skipped.\"\n\n"; - writeMakeQmake(t); + if (writeDummyMakefile(t)) return true; - } if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib" || diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 8af80e572e..f7b85d3621 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -58,17 +58,8 @@ bool NmakeMakefileGenerator::writeMakefile(QTextStream &t) { writeHeader(t); - if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) { - const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); - for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) - t << *it << " "; - t << "all first clean:\n\t" - << "@echo \"Some of the required modules (" - << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"\n\t" - << "@echo \"Skipped.\"\n\n"; - writeMakeQmake(t); + if (writeDummyMakefile(t)) return true; - } if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib" || -- cgit v1.2.3 From 198d2f6d3e1f622e1f168ff7e6aea7d1f05b80ed Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 26 Aug 2013 17:54:32 +0200 Subject: Activate Qt::WidgetWithChildrenShortcut shortcuts in MDI subwindows If a MDI subwindow is focused and an ancestor has a QShortCut set with the Qt::WidgetWithChildrenShortcut flag, it should trigger, as MDI subwindows are not top-level widgets. Task-number: QTBUG-32788 Change-Id: I7ec76d493b827ae6678209a56015ab6b432c1ed9 Reviewed-by: Friedemann Kleint --- src/widgets/kernel/qshortcut.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp index 471b054a99..678e6f25d1 100644 --- a/src/widgets/kernel/qshortcut.cpp +++ b/src/widgets/kernel/qshortcut.cpp @@ -158,7 +158,7 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge if (context == Qt::WidgetWithChildrenShortcut) { const QWidget *tw = QApplication::focusWidget(); - while (tw && tw != w && (tw->windowType() == Qt::Widget || tw->windowType() == Qt::Popup)) + while (tw && tw != w && (tw->windowType() == Qt::Widget || tw->windowType() == Qt::Popup || tw->windowType() == Qt::SubWindow)) tw = tw->parentWidget(); return tw == w; } -- cgit v1.2.3 From 627a394fb7ba1507bd028f81522244e7e085ef8d Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 27 Aug 2013 14:58:49 +0200 Subject: network test settings: support newer FTP server versions ... which are used by the new test server image. Change-Id: I72ffa73d3e254b278fb9063d32b633b156bd3ec0 Reviewed-by: Richard J. Moore --- tests/auto/network-settings.h | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/tests/auto/network-settings.h b/tests/auto/network-settings.h index 2ffb89241c..ad51df9090 100644 --- a/tests/auto/network-settings.h +++ b/tests/auto/network-settings.h @@ -103,20 +103,9 @@ public: static bool compareReplyFtp(QByteArray const& actual) { - QList expected; - - // A few different vsFTPd versions. - // Feel free to add more as needed - expected << QByteArray( "220 (vsFTPd 2.0.5)\r\n221 Goodbye.\r\n" ); - expected << QByteArray( "220 (vsFTPd 2.2.2)\r\n221 Goodbye.\r\n" ); - - Q_FOREACH (QByteArray const& ba, expected) { - if (ba == actual) { - return true; - } - } - - return false; + // output would be e.g. "220 (vsFTPd 2.3.5)\r\n221 Goodbye.\r\n" + QRegExp ftpVersion(QStringLiteral("220 \\(vsFTPd \\d+\\.\\d+.\\d+\\)\\r\\n221 Goodbye.\\r\\n")); + return ftpVersion.exactMatch(actual); } static bool hasIPv6() -- cgit v1.2.3 From 5a04101de680940f68735dcb6cfdf7f67eea0968 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 28 Aug 2013 15:09:08 +0200 Subject: Android: Make qmake.conf usable for getting arch in Qt Creator Qt Creator needs to parse the qmake.conf in order to get the architecture for this Qt build when the Qt build is added. At this point it does not know that it's reading an android project, so it can't set the right environment variables. By moving the error to the bottom, we let Creator parse the whole file before getting an error, so that it can detect the options it needs to define the Qt version. Change-Id: I119523cb21e330dc5e957a6992476c4c3d4ab7b5 Reviewed-by: Daniel Teske --- mkspecs/android-g++/qmake.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mkspecs/android-g++/qmake.conf b/mkspecs/android-g++/qmake.conf index 8c0e8c91f6..4ff5341837 100644 --- a/mkspecs/android-g++/qmake.conf +++ b/mkspecs/android-g++/qmake.conf @@ -37,7 +37,6 @@ contains(QMAKE_HOST.os,Windows) { NDK_ROOT = $$(ANDROID_NDK_ROOT) !exists($$NDK_ROOT) { NDK_ROOT = $$DEFAULT_ANDROID_NDK_ROOT - !exists($$NDK_ROOT): error("You need to set the ANDROID_NDK_ROOT environment variable to point to your Android NDK.") } NDK_HOST = $$(ANDROID_NDK_HOST) @@ -187,4 +186,6 @@ QMAKE_LIBS_OPENGL = QMAKE_LIBS_OPENGL_ES1 = -lGLESv1_CM QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 +!exists($$NDK_ROOT): error("You need to set the ANDROID_NDK_ROOT environment variable to point to your Android NDK.") + load(qt_config) -- cgit v1.2.3 From e9c771d6cce35746fceeb9a2bed9f522a8d7f34c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 28 Aug 2013 09:08:29 +0200 Subject: Stabilize tst_qmenubar. The test was re-using a main window and menu bars for all tests, clearing and repopulating them. Rewrite the code to be able to use menu bars and windows on the stack separately for each test. Change-Id: I13ab31b26b70bc8537e8d8ab164051b3197cd68e Reviewed-by: Frederik Gladhorn --- .../auto/widgets/widgets/qmenubar/tst_qmenubar.cpp | 816 ++++++++++----------- 1 file changed, 403 insertions(+), 413 deletions(-) diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp index 174753d8be..2b8e735a0e 100644 --- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp +++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp @@ -58,23 +58,6 @@ QT_FORWARD_DECLARE_CLASS(QMainWindow) #include -class QtTestSlot : public QObject -{ - Q_OBJECT - -public: - QtTestSlot( QObject* parent = 0 ): QObject( parent ) { clear(); }; - virtual ~QtTestSlot() {}; - - void clear() { sel_count = 0; }; - uint selCount() { return sel_count; }; - -public slots: - void selected() { sel_count++; }; - -private: - uint sel_count; -}; class Menu : public QMenu { @@ -88,20 +71,24 @@ class Menu : public QMenu } }; +static inline void centerOnScreen(QWidget *w) +{ + const QPoint offset = QPoint(w->width() / 2, w->height() / 2); + w->move(QGuiApplication::primaryScreen()->availableGeometry().center() - offset); +} + +struct TestMenu +{ + QList menus; + QList actions; +}; + class tst_QMenuBar : public QObject { Q_OBJECT public: tst_QMenuBar(); - virtual ~tst_QMenuBar(); - - void initSimpleMenubar(); - void initComplexMenubar(); -public slots: - void initTestCase(); - void cleanupTestCase(); - void init(); private slots: void getSetCheck(); @@ -149,37 +136,20 @@ private slots: void closeOnSecondClick(); protected slots: - void onActivated( QAction*); + void onSimpleActivated( QAction*); + void onComplexActionTriggered(); private: - QtTestSlot *menu1; - QtTestSlot *menu2; - QtTestSlot *menu3; - QtTestSlot *menu4; - - QtTestSlot *item1_A; - QtTestSlot *item1_B; - QtTestSlot *item2_C; - QtTestSlot *item2_D; - QtTestSlot *item2_E; - QtTestSlot *item2_F; - QtTestSlot *item2_G; - QtTestSlot *item2_H; - - void resetSlots(); - void resetCount(); - - void reset() { resetSlots(); resetCount(); }; - - QAction* last_accel_id; - int activated_count; - - QAction *action; - QAction *action1; - QMainWindow *mw; - QMenuBar *mb; - QMenu *pm1; - QMenu *pm2; + TestMenu initSimpleMenuBar(QMenuBar *mb); + TestMenu initWindowWithSimpleMenuBar(QMainWindow &w); + QAction *createCharacterAction(QMenu *menu, char lowerAscii); + QMenu *addNumberedMenu(QMenuBar *mb, int n); + TestMenu initComplexMenuBar(QMenuBar *mb); + TestMenu initWindowWithComplexMenuBar(QMainWindow &w); + + QAction* m_lastSimpleAcceleratorId; + int m_simpleActivatedCount; + int m_complexTriggerCount['k']; }; // Testing get/set functions @@ -222,116 +192,119 @@ const int RESET = 0; */ -tst_QMenuBar::tst_QMenuBar() - +tst_QMenuBar::tst_QMenuBar() : m_lastSimpleAcceleratorId(0), m_simpleActivatedCount(0) { QApplication::setEffectEnabled(Qt::UI_AnimateMenu, false); - - - activated_count = 0; - mb = 0; - pm1 = 0; - pm2 = 0; - last_accel_id = 0; } -tst_QMenuBar::~tst_QMenuBar() +void tst_QMenuBar::onSimpleActivated( QAction* action ) { - //delete mw; //#### cannot do that AFTER qapplication was destroyed! - mw = 0; + m_lastSimpleAcceleratorId = action; + m_simpleActivatedCount++; } -void tst_QMenuBar::initTestCase() +// Create a simple menu bar and connect its actions to onSimpleActivated(). + +TestMenu tst_QMenuBar::initSimpleMenuBar(QMenuBar *mb) { - // create a default mainwindow - // If you run a widget test, this will be replaced in the testcase by the - // widget under test - mw = new QMainWindow(0, Qt::X11BypassWindowManagerHint); - mb = new QMenuBar( mw ); - connect( mb, SIGNAL(triggered(QAction*)), this, SLOT(onActivated(QAction*)) ); - - initSimpleMenubar(); - mw->show(); - mw->activateWindow(); - QVERIFY(QTest::qWaitForWindowActive(mw)); - - menu1 = new QtTestSlot( mw ); - menu2 = new QtTestSlot( mw ); - menu3 = new QtTestSlot( mw ); - menu4 = new QtTestSlot( mw ); - item1_A = new QtTestSlot( mw ); - item1_B = new QtTestSlot( mw ); - item2_C = new QtTestSlot( mw ); - item2_D = new QtTestSlot( mw ); - item2_E = new QtTestSlot( mw ); - item2_F = new QtTestSlot( mw ); - item2_G = new QtTestSlot( mw ); - item2_H = new QtTestSlot( mw ); + TestMenu result; + connect(mb, SIGNAL(triggered(QAction*)), this, SLOT(onSimpleActivated(QAction*))); + QMenu *menu = mb->addMenu(QStringLiteral("&accel")); + QAction *action = menu->addAction(QStringLiteral("menu1") ); + action->setShortcut(QKeySequence(Qt::ALT + Qt::Key_A)); + action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_A)); + connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(onSimpleActivated(QAction*))); + result.menus << menu; + result.actions << action; + + menu = mb->addMenu(QStringLiteral("accel1")); + action = menu->addAction(QStringLiteral("&Open...") ); + action->setShortcut(Qt::Key_O); + result.menus << menu; + connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(onSimpleActivated(QAction*))); + result.actions << action; + + m_lastSimpleAcceleratorId = 0; + m_simpleActivatedCount = 0; + + return result; } - -void tst_QMenuBar::cleanupTestCase() +inline TestMenu tst_QMenuBar::initWindowWithSimpleMenuBar(QMainWindow &w) { - delete mw; + w.resize(200, 200); + centerOnScreen(&w); + return initSimpleMenuBar(w.menuBar()); } -void tst_QMenuBar::initSimpleMenubar() +// add a menu with number n, set number as data. +QMenu *tst_QMenuBar::addNumberedMenu(QMenuBar *mb, int n) { - mb->hide(); - mb->clear(); - - delete pm1; - pm1 = mb->addMenu("&accel"); - action = pm1->addAction( "menu1" ); - action->setShortcut(QKeySequence("ALT+A")); - action->setShortcut(QKeySequence("CTRL+A")); - - connect( pm1, SIGNAL(triggered(QAction*)), this, SLOT(onActivated(QAction*))); - - delete pm2; - pm2 = mb->addMenu("accel1"); - - action1 = pm2->addAction( "&Open..." ); - action1->setShortcut(Qt::Key_O); - connect(pm2, SIGNAL(triggered(QAction*)), this, SLOT(onActivated(QAction*))); - - mb->show(); - qApp->processEvents(); + const QString text = QStringLiteral("Menu &") + QString::number(n); + QMenu *menu = mb->addMenu(text); + menu->setObjectName(text); + QAction *action = menu->menuAction(); + action->setObjectName(text + QStringLiteral("Action")); + action->setData(QVariant(n)); + connect(action, SIGNAL(triggered()), this, SLOT(onComplexActionTriggered())); + return menu; } -void tst_QMenuBar::init() +// Create an action triggering on Ctrl+character, set number as data. +QAction *tst_QMenuBar::createCharacterAction(QMenu *menu, char lowerAscii) { - resetSlots(); - resetCount(); + const QString text = QStringLiteral("Item ") + QChar(QLatin1Char(lowerAscii)).toUpper(); + QAction *action = menu->addAction(text); + action->setObjectName(text); + action->setData(QVariant(int(lowerAscii))); + action->setShortcut(Qt::CTRL + (lowerAscii - 'a' + Qt::Key_A)); + connect(action, SIGNAL(triggered()), this, SLOT(onComplexActionTriggered())); + return action; } -void tst_QMenuBar::resetSlots() +void tst_QMenuBar::onComplexActionTriggered() { - menu1->clear(); - menu2->clear(); - menu3->clear(); - menu4->clear(); - item1_A->clear(); - item1_B->clear(); - item2_C->clear(); - item2_D->clear(); - item2_E->clear(); - item2_F->clear(); - item2_G->clear(); - item2_H->clear(); + if (QAction *a = qobject_cast(sender())) + m_complexTriggerCount[a->data().toInt()]++; } -void tst_QMenuBar::resetCount() +// Create a complex menu bar and connect its actions to onComplexActionTriggered() +// for their invocations to be counted in m_complexTriggerCount. The index is the +// menu number (1..n) for the menu bar actions and the ASCII-code of the shortcut +// character for the actions in the menus. +TestMenu tst_QMenuBar::initComplexMenuBar(QMenuBar *mb) { - last_accel_id = 0; - activated_count = 0; + TestMenu result; + QMenu *menu = addNumberedMenu(mb, 1); + result.menus << menu; + for (char c = 'a'; c < 'c'; ++c) + result.actions << createCharacterAction(menu, c); + + menu = addNumberedMenu(mb, 2); + menu->menuAction()->setData(QVariant(2)); + result.menus << menu; + for (char c = 'c'; c < 'g'; ++c) + result.actions << createCharacterAction(menu, c); + menu->addSeparator(); + for (char c = 'g'; c < 'i'; ++c) + result.actions << createCharacterAction(menu, c); + + QAction *action = mb->addAction(QStringLiteral("M&enu 3")); + action->setData(QVariant(3)); + action->setShortcut(Qt::ALT + Qt::Key_J); + connect(action, SIGNAL(triggered()), this, SLOT(onComplexActionTriggered())); + result.actions << action; + + qFill(m_complexTriggerCount, m_complexTriggerCount + sizeof(m_complexTriggerCount) / sizeof(int), 0); + + return result; } -void tst_QMenuBar::onActivated( QAction* action ) +inline TestMenu tst_QMenuBar::initWindowWithComplexMenuBar(QMainWindow &w) { - last_accel_id = action; - activated_count++; -// printf( QString("acceleratorId: %1, count: %1\n").arg( i ).arg(activated_count) ); + w.resize(400, 200); + centerOnScreen(&w); + return initComplexMenuBar(w.menuBar()); } // On Mac/WinCE, native key events are needed to test menu action activation @@ -339,15 +312,16 @@ void tst_QMenuBar::onActivated( QAction* action ) void tst_QMenuBar::accel() { // create a popup menu with menu items set the accelerators later... - initSimpleMenubar(); - + QMainWindow w; + const TestMenu menu = initWindowWithSimpleMenuBar(w); + w.show(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); // shortcuts won't work unless the window is active - QTRY_VERIFY( QApplication::activeWindow() ); -// QTest::keyClick(static_cast(0), Qt::Key_A, AltKey ); QTest::keyClick(static_cast(0), Qt::Key_A, Qt::ControlModifier ); QTest::qWait(300); - QCOMPARE( last_accel_id, action ); + QCOMPARE( m_lastSimpleAcceleratorId, menu.actions.front() ); } #endif @@ -356,40 +330,45 @@ void tst_QMenuBar::accel() void tst_QMenuBar::activatedCount() { // create a popup menu with menu items set the accelerators later... - initSimpleMenubar(); + QMainWindow w; + initWindowWithSimpleMenuBar(w); + w.show(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); QTest::keyClick(static_cast(0), Qt::Key_A, Qt::ControlModifier ); //wait(5000); - QCOMPARE( activated_count, 2 ); //1 from the popupmenu and 1 from the menubar + QCOMPARE( m_simpleActivatedCount, 2 ); //1 from the popupmenu and 1 from the menubar } #endif void tst_QMenuBar::clear() { - mb->clear(); - QVERIFY( (uint) mb->actions().size() == 0 ); - - mb->clear(); - for (uint i=0; i<10; i++) { - QMenu *menu = mb->addMenu( QString("Menu %1")); - for (uint k=0; kaddAction( QString("Item %1")); - QCOMPARE( (uint) mb->actions().size(), (uint)i+1 ); + QMenuBar menuBar; + initSimpleMenuBar(&menuBar); + menuBar.clear(); + QCOMPARE( menuBar.actions().size(), 0 ); + + menuBar.clear(); + for (int i = 0; i < 10; i++) { + QMenu *menu = menuBar.addMenu( QStringLiteral("Menu ") + QString::number(i)); + for (int k = 0; k < i; k++) + menu->addAction( QStringLiteral("Item ") + QString::number(k)); + QCOMPARE( menuBar.actions().size(), i + 1 ); } - QCOMPARE( (uint) mb->actions().size(), 10u ); - - mb->clear(); - QVERIFY( (uint) mb->actions().size() == 0 ); + QCOMPARE( menuBar.actions().size(), 10 ); + menuBar.clear(); + QCOMPARE( menuBar.actions().size(), 0 ); } void tst_QMenuBar::count() { - mb->clear(); - QVERIFY( mb->actions().size() == 0 ); + QMenuBar menuBar; + QCOMPARE( menuBar.actions().size(), 0 ); - for (uint i=0; i<10; i++) { - mb->addAction( QString("Menu %1")); - QCOMPARE( (uint) mb->actions().size(), (uint) i+1 ); + for (int i = 0; i < 10; i++) { + menuBar.addAction( QStringLiteral("Menu ") + QString::number(i)); + QCOMPARE( menuBar.actions().size(), i + 1 ); } } @@ -404,27 +383,26 @@ void tst_QMenuBar::removeItem_data() // Basically the same test as removeItemAt, except that we remember and remove id's. void tst_QMenuBar::removeItem() { - mb->clear(); + QMenuBar menuBar; - QMenu *pm; - pm = new QMenu( "stuff", mb ); + QMenu *pm = new QMenu( "stuff", &menuBar ); pm->setTitle("Menu 1"); pm->addAction( QString("Item 10") ); - QAction* action1 = mb->addMenu( pm ); + QAction* action1 = menuBar.addMenu( pm ); - pm = new QMenu( mb ); + pm = new QMenu( &menuBar ); pm->setTitle("Menu 2"); pm->addAction( QString("Item 20") ); pm->addAction( QString("Item 21") ); - QAction *action2 = mb->addMenu( pm ); + QAction *action2 = menuBar.addMenu( pm ); - pm = new QMenu( "Menu 3", mb ); + pm = new QMenu( "Menu 3", &menuBar ); pm->addAction( QString("Item 30") ); pm->addAction( QString("Item 31") ); pm->addAction( QString("Item 32") ); - QAction *action3 = mb->addMenu( pm ); + QAction *action3 = menuBar.addMenu( pm ); - QList menuBarActions = mb->actions(); + const QList menuBarActions = menuBar.actions(); QCOMPARE( action1->text(), QString("Menu 1") ); QCOMPARE( action2->text(), QString("Menu 2") ); @@ -439,28 +417,28 @@ void tst_QMenuBar::removeItem() switch (removeIndex ) { case 0: { - mb->removeAction(action1); - QList menuBarActions2 = mb->actions(); + menuBar.removeAction(action1); + const QList menuBarActions2 = menuBar.actions(); QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 2") ); QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 3") ); } break; case 1: { - mb->removeAction(action2); - QList menuBarActions2 = mb->actions(); + menuBar.removeAction(action2); + const QList menuBarActions2 = menuBar.actions(); QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") ); QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 3") ); } break; case 2: { - mb->removeAction(action3); - QList menuBarActions2 = mb->actions(); + menuBar.removeAction(action3); + const QList menuBarActions2 = menuBar.actions(); QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") ); QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 2") ); } break; } - QList menuBarActions2 = mb->actions(); + QList menuBarActions2 = menuBar.actions(); QVERIFY( menuBarActions2.size() == 2 ); } @@ -474,25 +452,23 @@ void tst_QMenuBar::removeItemAt_data() void tst_QMenuBar::removeItemAt() { - mb->clear(); - - QMenu *pm; - pm = new QMenu("Menu 1", mb); + QMenuBar menuBar; + QMenu *pm = new QMenu("Menu 1", &menuBar); pm->addAction( QString("Item 10") ); - mb->addMenu( pm ); + menuBar.addMenu( pm ); - pm = new QMenu( "Menu 2", mb ); + pm = new QMenu( "Menu 2", &menuBar); pm->addAction( QString("Item 20") ); pm->addAction( QString("Item 21") ); - mb->addMenu( pm ); + menuBar.addMenu( pm ); - pm = new QMenu( "Menu 3", mb ); + pm = new QMenu( "Menu 3", &menuBar); pm->addAction( QString("Item 30") ); pm->addAction( QString("Item 31") ); pm->addAction( QString("Item 32") ); - mb->addMenu( pm ); + menuBar.addMenu( pm ); - QList menuBarActions = mb->actions(); + QList menuBarActions = menuBar.actions(); QCOMPARE( menuBarActions.at(0)->text(), QString("Menu 1") ); QCOMPARE( menuBarActions.at(1)->text(), QString("Menu 2") ); @@ -500,8 +476,8 @@ void tst_QMenuBar::removeItemAt() // Ok, now that we know we have created the menu we expect, lets remove an item... QFETCH( int, removeIndex ); - mb->removeAction(menuBarActions.at(removeIndex)); - QList menuBarActions2 = mb->actions(); + menuBar.removeAction(menuBarActions.at(removeIndex)); + const QList menuBarActions2 = menuBar.actions(); switch (removeIndex ) { case 0: @@ -521,32 +497,6 @@ void tst_QMenuBar::removeItemAt() QVERIFY( menuBarActions2.size() == 2 ); } -void tst_QMenuBar::initComplexMenubar() // well, complex.... -{ - mb->hide(); - mb->clear(); - - delete pm1; - pm1 = mb->addMenu("Menu &1"); - pm1->addAction( QString("Item A"), item1_A, SLOT(selected()), Qt::CTRL+Qt::Key_A ); - pm1->addAction( QString("Item B"), item1_B, SLOT(selected()), Qt::CTRL+Qt::Key_B ); - - delete pm2; - pm2 = mb->addMenu("Menu &2"); - pm2->addAction( QString("Item C"), item2_C, SLOT(selected()), Qt::CTRL+Qt::Key_C ); - pm2->addAction( QString("Item D"), item2_D, SLOT(selected()), Qt::CTRL+Qt::Key_D ); - pm2->addAction( QString("Item E"), item2_E, SLOT(selected()), Qt::CTRL+Qt::Key_E ); - pm2->addAction( QString("Item F"), item2_F, SLOT(selected()), Qt::CTRL+Qt::Key_F ); - pm2->addSeparator(); - pm2->addAction( QString("Item G"), item2_G, SLOT(selected()), Qt::CTRL+Qt::Key_G ); - pm2->addAction( QString("Item H"), item2_H, SLOT(selected()), Qt::CTRL+Qt::Key_H ); - - QAction *ac = mb->addAction( QString("M&enu 3"), menu3, SLOT(selected())); - ac->setShortcut(Qt::ALT+Qt::Key_J); - mb->show(); -} - - /* Check the insert functions that create menu items. For the moment i only check the strings and pixmaps. The rest are special cases which are @@ -555,9 +505,10 @@ void tst_QMenuBar::initComplexMenubar() // well, complex.... void tst_QMenuBar::insertItem_QString_QObject() { - initComplexMenubar(); + QMenuBar menuBar; + initComplexMenuBar(&menuBar); - QList actions = mb->actions(); + const QList actions = menuBar.actions(); QCOMPARE(actions.at(0)->text(), QString("Menu &1") ); QCOMPARE(actions.at(1)->text(), QString("Menu &2") ); @@ -569,68 +520,72 @@ void tst_QMenuBar::insertItem_QString_QObject() #if !defined(Q_OS_MAC) && !defined(Q_OS_WINCE) void tst_QMenuBar::check_accelKeys() { - initComplexMenubar(); + QMainWindow w; + initWindowWithComplexMenuBar(w); + w.show(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); // start with a bogus key that shouldn't trigger anything QTest::keyClick(static_cast(0), Qt::Key_I, Qt::ControlModifier); - QCOMPARE(menu1->selCount(), 0u); - QCOMPARE(menu2->selCount(), 0u); - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 0u); - QCOMPARE(item1_B->selCount(), 0u); - QCOMPARE(item2_C->selCount(), 0u); - QCOMPARE(item2_D->selCount(), 0u); + QCOMPARE(m_complexTriggerCount[1], 0); + QCOMPARE(m_complexTriggerCount[2], 0); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 0); + QCOMPARE(m_complexTriggerCount['b'], 0); + QCOMPARE(m_complexTriggerCount['c'], 0); + QCOMPARE(m_complexTriggerCount['d'], 0); QTest::keyClick(static_cast(0), Qt::Key_A, Qt::ControlModifier); - QCOMPARE(menu1->selCount(), 0u); - QCOMPARE(menu2->selCount(), 0u); - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 1u); - QCOMPARE(item1_B->selCount(), 0u); - QCOMPARE(item2_C->selCount(), 0u); - QCOMPARE(item2_D->selCount(), 0u); + QCOMPARE(m_complexTriggerCount[1], 0); + QCOMPARE(m_complexTriggerCount[2], 0); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 1); + QCOMPARE(m_complexTriggerCount['b'], 0); + QCOMPARE(m_complexTriggerCount['c'], 0); + QCOMPARE(m_complexTriggerCount['d'], 0); QTest::keyClick(static_cast(0), Qt::Key_C, Qt::ControlModifier); - QCOMPARE(menu1->selCount(), 0u); - QCOMPARE(menu2->selCount(), 0u); - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 1u); - QCOMPARE(item1_B->selCount(), 0u); - QCOMPARE(item2_C->selCount(), 1u); - QCOMPARE(item2_D->selCount(), 0u); + QCOMPARE(m_complexTriggerCount[1], 0); + QCOMPARE(m_complexTriggerCount[2], 0); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 1); + QCOMPARE(m_complexTriggerCount['b'], 0); + QCOMPARE(m_complexTriggerCount['c'], 1); + QCOMPARE(m_complexTriggerCount['d'], 0); QTest::keyClick(static_cast(0), Qt::Key_B, Qt::ControlModifier); - QCOMPARE(menu1->selCount(), 0u); - QCOMPARE(menu2->selCount(), 0u); - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 1u); - QCOMPARE(item1_B->selCount(), 1u); - QCOMPARE(item2_C->selCount(), 1u); - QCOMPARE(item2_D->selCount(), 0u); + QCOMPARE(m_complexTriggerCount[1], 0); + QCOMPARE(m_complexTriggerCount[2], 0); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 1); + QCOMPARE(m_complexTriggerCount['b'], 1); + QCOMPARE(m_complexTriggerCount['c'], 1); + QCOMPARE(m_complexTriggerCount['d'], 0); QTest::keyClick(static_cast(0), Qt::Key_D, Qt::ControlModifier); - QCOMPARE(menu1->selCount(), 0u); - QCOMPARE(menu2->selCount(), 0u); - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 1u); - QCOMPARE(item1_B->selCount(), 1u); - QCOMPARE(item2_C->selCount(), 1u); - QCOMPARE(item2_D->selCount(), 1u); + QCOMPARE(m_complexTriggerCount[1], 0); + QCOMPARE(m_complexTriggerCount[2], 0); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 1); + QCOMPARE(m_complexTriggerCount['b'], 1); + QCOMPARE(m_complexTriggerCount['c'], 1); + QCOMPARE(m_complexTriggerCount['d'], 1); QTest::keyClick(static_cast(0), Qt::Key_J, Qt::AltModifier); - QCOMPARE(menu1->selCount(), 0u); - QCOMPARE(menu2->selCount(), 0u); - QCOMPARE(menu3->selCount(), 1u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 1u); - QCOMPARE(item1_B->selCount(), 1u); - QCOMPARE(item2_C->selCount(), 1u); - QCOMPARE(item2_D->selCount(), 1u); + QCOMPARE(m_complexTriggerCount[1], 0); + QCOMPARE(m_complexTriggerCount[2], 0); + QCOMPARE(m_complexTriggerCount[3], 1); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 1); + QCOMPARE(m_complexTriggerCount['b'], 1); + QCOMPARE(m_complexTriggerCount['c'], 1); + QCOMPARE(m_complexTriggerCount['d'], 1); } #endif @@ -638,29 +593,33 @@ void tst_QMenuBar::check_accelKeys() #if !defined(Q_OS_MAC) && !defined(Q_OS_WINCE) void tst_QMenuBar::check_cursorKeys1() { - initComplexMenubar(); + QMainWindow w; + initWindowWithComplexMenuBar(w); + w.show(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); // start with a ALT + 1 that activates the first popupmenu QTest::keyClick(static_cast(0), Qt::Key_1, Qt::AltModifier ); // the Popupmenu should be visible now - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 0u); - QCOMPARE(item1_B->selCount(), 0u); - QCOMPARE(item2_C->selCount(), 0u); - QCOMPARE(item2_D->selCount(), 0u); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 0); + QCOMPARE(m_complexTriggerCount['b'], 0); + QCOMPARE(m_complexTriggerCount['c'], 0); + QCOMPARE(m_complexTriggerCount['d'], 0); // Simulate a cursor key down click QTest::keyClick(static_cast(0), Qt::Key_Down ); // and an Enter key QTest::keyClick(static_cast(0), Qt::Key_Enter ); // Let's see if the correct slot is called... - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 0u); // this shouldn't have been called - QCOMPARE(item1_B->selCount(), 1u); // and this should have been called by a signal now - QCOMPARE(item2_C->selCount(), 0u); - QCOMPARE(item2_D->selCount(), 0u); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 0); // this shouldn't have been called + QCOMPARE(m_complexTriggerCount['b'], 1); // and this should have been called by a signal now + QCOMPARE(m_complexTriggerCount['c'], 0); + QCOMPARE(m_complexTriggerCount['d'], 0); } #endif @@ -668,7 +627,11 @@ void tst_QMenuBar::check_cursorKeys1() #if !defined(Q_OS_MAC) && !defined(Q_OS_WINCE) void tst_QMenuBar::check_cursorKeys2() { - initComplexMenubar(); + QMainWindow w; + initWindowWithComplexMenuBar(w); + w.show(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); // select popupmenu2 QTest::keyClick(static_cast(0), Qt::Key_2, Qt::AltModifier ); @@ -681,12 +644,12 @@ void tst_QMenuBar::check_cursorKeys2() // and an Enter key QTest::keyClick(static_cast(0), Qt::Key_Enter ); // Let's see if the correct slot is called... - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 0u); // this shouldn't have been caled - QCOMPARE(item1_B->selCount(), 0u); // and this should have been called by a signal ow - QCOMPARE(item2_C->selCount(), 0u); - QCOMPARE(item2_D->selCount(), 1u); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 0); // this shouldn't have been caled + QCOMPARE(m_complexTriggerCount['b'], 0); // and this should have been called by a signal ow + QCOMPARE(m_complexTriggerCount['c'], 0); + QCOMPARE(m_complexTriggerCount['d'], 1); } #endif @@ -697,7 +660,11 @@ void tst_QMenuBar::check_cursorKeys2() #if !defined(Q_OS_MAC) && !defined(Q_OS_WINCE) void tst_QMenuBar::check_cursorKeys3() { - initComplexMenubar(); + QMainWindow w; + initWindowWithComplexMenuBar(w); + w.show(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); // select Popupmenu 2 QTest::keyClick(static_cast(0), Qt::Key_2, Qt::AltModifier ); @@ -708,12 +675,12 @@ void tst_QMenuBar::check_cursorKeys3() // and press ENTER QTest::keyClick(static_cast(0), Qt::Key_Enter ); // Let's see if the correct slot is called... - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 0u); // this shouldn't have been called - QCOMPARE(item1_B->selCount(), 1u); // and this should have been called by a signal now - QCOMPARE(item2_C->selCount(), 0u); - QCOMPARE(item2_D->selCount(), 0u); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 0); // this shouldn't have been called + QCOMPARE(m_complexTriggerCount['b'], 1); // and this should have been called by a signal now + QCOMPARE(m_complexTriggerCount['c'], 0); + QCOMPARE(m_complexTriggerCount['d'], 0); } #endif @@ -729,7 +696,11 @@ void tst_QMenuBar::check_homeKey() QEXPECT_FAIL( "0", "Popupmenu should respond to a Home key", Abort ); - initComplexMenubar(); + QMainWindow w; + initWindowWithComplexMenuBar(w); + w.show(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); // select Popupmenu 2 QTest::keyClick(static_cast(0), Qt::Key_2, Qt::AltModifier ); @@ -742,17 +713,17 @@ void tst_QMenuBar::check_homeKey() // and press ENTER QTest::keyClick(static_cast(0), Qt::Key_Enter ); // Let's see if the correct slot is called... -// QVERIFY2( item2_C->selCount() == 1, "Popupmenu should respond to a Home key" ); - QCOMPARE(item2_C->selCount(), 1u); - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 0u); - QCOMPARE(item1_B->selCount(), 0u); - QCOMPARE(item2_D->selCount(), 0u); - QCOMPARE(item2_E->selCount(), 0u); - QCOMPARE(item2_F->selCount(), 0u); - QCOMPARE(item2_G->selCount(), 0u); - QCOMPARE(item2_H->selCount(), 0u); +// QVERIFY2( m_complexActionTriggerCount['c'] == 1, "Popupmenu should respond to a Home key" ); + QCOMPARE(m_complexTriggerCount['c'], 1); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 0); + QCOMPARE(m_complexTriggerCount['b'], 0); + QCOMPARE(m_complexTriggerCount['d'], 0); + QCOMPARE(m_complexTriggerCount['e'], 0); + QCOMPARE(m_complexTriggerCount['f'], 0); + QCOMPARE(m_complexTriggerCount['g'], 0); + QCOMPARE(m_complexTriggerCount['h'], 0); } /*! @@ -767,7 +738,11 @@ void tst_QMenuBar::check_endKey() QEXPECT_FAIL( "0", "Popupmenu should respond to an End key", Abort ); - initComplexMenubar(); + QMainWindow w; + initWindowWithComplexMenuBar(w); + w.show(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); // select Popupmenu 2 QTest::keyClick(static_cast(0), Qt::Key_2, Qt::AltModifier ); @@ -777,17 +752,17 @@ void tst_QMenuBar::check_endKey() // and press ENTER QTest::keyClick(static_cast(0), Qt::Key_Enter ); // Let's see if the correct slot is called... -// QVERIFY2( item2_H->selCount() == 1, "Popupmenu should respond to an End key" ); - QCOMPARE(item2_H->selCount(), 1u);//, "Popupmenu should respond to an End key"); - QCOMPARE(menu3->selCount(), 0u); - QCOMPARE(menu4->selCount(), 0u); - QCOMPARE(item1_A->selCount(), 0u); - QCOMPARE(item1_B->selCount(), 0u); - QCOMPARE(item2_C->selCount(), 0u); - QCOMPARE(item2_D->selCount(), 0u); - QCOMPARE(item2_E->selCount(), 0u); - QCOMPARE(item2_F->selCount(), 0u); - QCOMPARE(item2_G->selCount(), 0u); +// QVERIFY2( m_complexActionTriggerCount['h'] == 1, "Popupmenu should respond to an End key" ); + QCOMPARE(m_complexTriggerCount['h'], 1);//, "Popupmenu should respond to an End key"); + QCOMPARE(m_complexTriggerCount[3], 0); + QCOMPARE(m_complexTriggerCount[4], 0); + QCOMPARE(m_complexTriggerCount['a'], 0); + QCOMPARE(m_complexTriggerCount['b'], 0); + QCOMPARE(m_complexTriggerCount['c'], 0); + QCOMPARE(m_complexTriggerCount['d'], 0); + QCOMPARE(m_complexTriggerCount['e'], 0); + QCOMPARE(m_complexTriggerCount['f'], 0); + QCOMPARE(m_complexTriggerCount['g'], 0); } /*! @@ -800,33 +775,38 @@ void tst_QMenuBar::check_endKey() #if !defined(Q_OS_MAC) && !defined(Q_OS_WINCE) void tst_QMenuBar::check_escKey() { - initComplexMenubar(); + QMainWindow w; + const TestMenu menu = initWindowWithComplexMenuBar(w); + w.show(); + w.setFocus(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); - QVERIFY( !pm1->isActiveWindow() ); - QVERIFY( !pm2->isActiveWindow() ); + QVERIFY( !menu.menus.at(0)->isActiveWindow() ); + QVERIFY( !menu.menus.at(1)->isActiveWindow() ); // select Popupmenu 2 QTest::keyClick(static_cast(0), Qt::Key_2, Qt::AltModifier ); - QVERIFY( !pm1->isActiveWindow() ); - QVERIFY( pm2->isActiveWindow() ); + QVERIFY( !menu.menus.at(0)->isActiveWindow() ); + QVERIFY( menu.menus.at(1)->isActiveWindow() ); // If we press ESC, the popup should disappear QTest::keyClick(static_cast(0), Qt::Key_Escape ); - QVERIFY( !pm1->isActiveWindow() ); - QVERIFY( !pm2->isActiveWindow() ); + QVERIFY( !menu.menus.at(0)->isActiveWindow() ); + QVERIFY( !menu.menus.at(1)->isActiveWindow() ); if (!QApplication::style()->inherits("QWindowsStyle")) return; // If we press Down the popupmenu should be active again QTest::keyClick(static_cast(0), Qt::Key_Down ); - QVERIFY( !pm1->isActiveWindow() ); - QVERIFY( pm2->isActiveWindow() ); + QVERIFY( !menu.menus.at(0)->isActiveWindow() ); + QVERIFY( menu.menus.at(1)->isActiveWindow() ); // and press ENTER - QTest::keyClick( pm2, Qt::Key_Enter ); + QTest::keyClick( menu.menus.at(1), Qt::Key_Enter ); // Let's see if the correct slot is called... - QVERIFY2( item2_C->selCount() == 1, "Expected item 2C to be selected" ); + QVERIFY2( m_complexTriggerCount['c'] == 1, "Expected item 2C to be selected" ); } #endif @@ -852,7 +832,7 @@ void tst_QMenuBar::check_escKey() // QFETCH( int, itemA_count ); // QFETCH( int, itemB_count ); -// initComplexMenubar(); +// // initComplexMenubar(); // QVERIFY( !pm1->isActiveWindow() ); // QVERIFY( !pm2->isActiveWindow() ); @@ -866,15 +846,15 @@ void tst_QMenuBar::check_escKey() // QTest::qWait(1000); // mouse.mouseEvent( QtTestMouse::MouseClick, pm1, popup_item, Qt::LeftButton ); -// QCOMPARE(menu3->selCount(), 0u); -// QCOMPARE(menu4->selCount(), 0u); -// QCOMPARE(item1_A->selCount(), (uint)itemA_count); // this option should have fired -// QCOMPARE(item1_B->selCount(), (uint)itemB_count); -// QCOMPARE(item2_C->selCount(), 0u); -// QCOMPARE(item2_D->selCount(), 0u); -// QCOMPARE(item2_E->selCount(), 0u); -// QCOMPARE(item2_F->selCount(), 0u); -// QCOMPARE(item2_G->selCount(), 0u); +// QCOMPARE(m_complexActionTriggerCount[3], 0); +// QCOMPARE(m_complexActionTriggerCount[4], 0); +// QCOMPARE(m_complexActionTriggerCount['a'], (uint)itemA_count); // this option should have fired +// QCOMPARE(m_complexActionTriggerCount['b'], (uint)itemB_count); +// QCOMPARE(m_complexActionTriggerCount['c'], 0); +// QCOMPARE(m_complexActionTriggerCount['d'], 0); +// QCOMPARE(m_complexActionTriggerCount['e'], 0); +// QCOMPARE(m_complexActionTriggerCount['f'], 0); +// QCOMPARE(m_complexActionTriggerCount['g'], 0); // } // void tst_QMenuBar::check_mouse2_data() @@ -920,28 +900,27 @@ void tst_QMenuBar::check_escKey() // QFETCH( int, itemH_count ); // QFETCH( int, menu3_count ); -// initComplexMenubar(); +// // initComplexMenubar(); // QtTestMouse mouse; // mouse.click( QtTestMouse::Menu, label, Qt::LeftButton ); // // check if the correct signals have fired -// QCOMPARE(menu3->selCount(), (uint)menu3_count); -// QCOMPARE(menu4->selCount(), 0u); -// QCOMPARE(item1_A->selCount(), (uint)itemA_count); -// QCOMPARE(item1_B->selCount(), (uint)itemB_count); -// QCOMPARE(item2_C->selCount(), (uint)itemC_count); -// QCOMPARE(item2_D->selCount(), (uint)itemD_count); -// QCOMPARE(item2_E->selCount(), (uint)itemE_count); -// QCOMPARE(item2_F->selCount(), (uint)itemF_count); -// QCOMPARE(item2_G->selCount(), (uint)itemG_count); -// QCOMPARE(item2_H->selCount(), (uint)itemH_count); +// QCOMPARE(m_complexActionTriggerCount[3], (uint)menu3_count); +// QCOMPARE(m_complexActionTriggerCount[4], 0); +// QCOMPARE(m_complexActionTriggerCount['a'], (uint)itemA_count); +// QCOMPARE(m_complexActionTriggerCount['b'], (uint)itemB_count); +// QCOMPARE(m_complexActionTriggerCount['c'], (uint)itemC_count); +// QCOMPARE(m_complexActionTriggerCount['d'], (uint)itemD_count); +// QCOMPARE(m_complexActionTriggerCount['e'], (uint)itemE_count); +// QCOMPARE(m_complexActionTriggerCount['f'], (uint)itemF_count); +// QCOMPARE(m_complexActionTriggerCount['g'], (uint)itemG_count); +// QCOMPARE(m_complexActionTriggerCount['h'], (uint)itemH_count); // } #if !defined(Q_OS_MAC) && !defined(Q_OS_WINCE) void tst_QMenuBar::allowActiveAndDisabled() { - mb->hide(); - mb->clear(); + QMenuBar menuBar; // Task 241043 : check that second menu is activated if only // disabled menu items are added @@ -952,31 +931,30 @@ void tst_QMenuBar::allowActiveAndDisabled() QAction *act = fileMenu.addAction("Disabled"); act->setEnabled(false); - mb->addMenu(&fileMenu); + menuBar.addMenu(&fileMenu); QMenu disabledMenu("Disabled"); disabledMenu.setEnabled(false); QMenu activeMenu("Active"); - mb->addMenu(&disabledMenu); - mb->addMenu(&activeMenu); - mb->show(); - + menuBar.addMenu(&disabledMenu); + menuBar.addMenu(&activeMenu); + centerOnScreen(&menuBar); + menuBar.show(); + QVERIFY(QTest::qWaitForWindowExposed(&menuBar)); // Here we verify that AllowActiveAndDisabled correctly skips // the disabled menu entry - QTest::keyClick(mb, Qt::Key_F, Qt::AltModifier ); + QTest::keyClick(&menuBar, Qt::Key_F, Qt::AltModifier ); QTest::keyClick(&fileMenu, (Qt::Key_Right)); if (qApp->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled)) - QCOMPARE(mb->activeAction()->text(), disabledMenu.title()); + QCOMPARE(menuBar.activeAction()->text(), disabledMenu.title()); else - QCOMPARE(mb->activeAction()->text(), activeMenu.title()); + QCOMPARE(menuBar.activeAction()->text(), activeMenu.title()); - QTest::keyClick(mb, (Qt::Key_Left)); + QTest::keyClick(&menuBar, (Qt::Key_Left)); if (qApp->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled)) - QCOMPARE(mb->activeAction()->text(), fileMenu.title()); + QCOMPARE(menuBar.activeAction()->text(), fileMenu.title()); else - QCOMPARE(mb->activeAction()->text(), fileMenu.title()); - - mb->hide(); + QCOMPARE(menuBar.activeAction()->text(), fileMenu.title()); } #endif @@ -987,33 +965,38 @@ void tst_QMenuBar::check_altPress() arg( qApp->style()->objectName() ).toLatin1()); } - initSimpleMenubar(); - - qApp->setActiveWindow(mw); - mw->setFocus(); + QMainWindow w; + initWindowWithSimpleMenuBar(w); + w.show(); + w.setFocus(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); - QTest::keyClick( mw, Qt::Key_Alt ); - - QVERIFY( ::qobject_cast(qApp->focusWidget()) ); + QTest::keyClick( &w, Qt::Key_Alt ); + QTRY_VERIFY( ::qobject_cast(qApp->focusWidget()) ); } // Qt/Mac,WinCE does not use the native popups/menubar #if !defined(Q_OS_MAC) && !defined(Q_OS_WINCE) void tst_QMenuBar::check_shortcutPress() { - initComplexMenubar(); - - qApp->setActiveWindow(mw); - QCOMPARE(menu3->selCount(), 0u); - QTest::keyClick(mw, Qt::Key_E, Qt::AltModifier); + QMainWindow w; + const TestMenu menu = initWindowWithComplexMenuBar(w); + w.show(); + w.setFocus(); + QApplication::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); + + QCOMPARE(m_complexTriggerCount[3], 0); + QTest::keyClick(&w, Qt::Key_E, Qt::AltModifier); QTest::qWait(200); - QCOMPARE(menu3->selCount(), 1u); - QVERIFY(!mb->activeAction()); + QCOMPARE(m_complexTriggerCount[3], 1); + QVERIFY(!w.menuBar()->activeAction()); - QTest::keyClick(mw, Qt::Key_1, Qt::AltModifier ); - QVERIFY(pm1->isActiveWindow()); - QTest::keyClick(mb, Qt::Key_2); - QVERIFY(pm1->isActiveWindow()); + QTest::keyClick(&w, Qt::Key_1, Qt::AltModifier ); + QVERIFY(menu.menus.at(0)->isActiveWindow()); + QTest::keyClick(&w, Qt::Key_2); + QVERIFY(menu.menus.at(0)->isActiveWindow()); } #endif @@ -1040,27 +1023,29 @@ private: #if !defined(Q_OS_MAC) && !defined(Q_OS_WINCE) void tst_QMenuBar::check_menuPosition() { + QMainWindow w; + Menu menu; - initComplexMenubar(); menu.setTitle("&menu"); - QRect availRect = QApplication::desktop()->availableGeometry(mw); - QRect screenRect = QApplication::desktop()->screenGeometry(mw); + QRect availRect = QApplication::desktop()->availableGeometry(&w); + QRect screenRect = QApplication::desktop()->screenGeometry(&w); while(menu.sizeHint().height() < (screenRect.height()*2/3)) { menu.addAction("item"); } - QAction *menu_action = mw->menuBar()->addMenu(&menu); - - qApp->setActiveWindow(mw); - qApp->processEvents(); + QAction *menu_action = w.menuBar()->addMenu(&menu); + centerOnScreen(&w); + w.show(); + qApp->setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); //the menu should be below the menubar item { - mw->move(availRect.topLeft()); - QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action); - mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft())); - QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier ); + w.move(availRect.topLeft()); + QRect mbItemRect = w.menuBar()->actionGeometry(menu_action); + mbItemRect.moveTo(w.menuBar()->mapToGlobal(mbItemRect.topLeft())); + QTest::keyClick(&w, Qt::Key_M, Qt::AltModifier ); QVERIFY(menu.isActiveWindow()); QCOMPARE(menu.pos(), QPoint(mbItemRect.x(), mbItemRect.bottom() + 1)); menu.close(); @@ -1068,10 +1053,10 @@ void tst_QMenuBar::check_menuPosition() //the menu should be above the menubar item { - mw->move(0,screenRect.bottom() - screenRect.height()/4); //just leave some place for the menubar - QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action); - mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft())); - QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier ); + w.move(0,screenRect.bottom() - screenRect.height()/4); //just leave some place for the menubar + QRect mbItemRect = w.menuBar()->actionGeometry(menu_action); + mbItemRect.moveTo(w.menuBar()->mapToGlobal(mbItemRect.topLeft())); + QTest::keyClick(&w, Qt::Key_M, Qt::AltModifier ); QVERIFY(menu.isActiveWindow()); QCOMPARE(menu.pos(), QPoint(mbItemRect.x(), mbItemRect.top() - menu.height())); menu.close(); @@ -1079,10 +1064,10 @@ void tst_QMenuBar::check_menuPosition() //the menu should be on the side of the menubar item and should be "stuck" to the bottom of the screen { - mw->move(0,screenRect.y() + screenRect.height()/2); //put it in the middle - QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action); - mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft())); - QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier ); + w.move(0,screenRect.y() + screenRect.height()/2); //put it in the middle + QRect mbItemRect = w.menuBar()->actionGeometry(menu_action); + mbItemRect.moveTo(w.menuBar()->mapToGlobal(mbItemRect.topLeft())); + QTest::keyClick(&w, Qt::Key_M, Qt::AltModifier ); QVERIFY(menu.isActiveWindow()); QPoint firstPoint = QPoint(mbItemRect.right()+1, screenRect.bottom() - menu.height() + 1); QPoint secondPoint = QPoint(mbItemRect.right()+1, availRect.bottom() - menu.height() + 1); @@ -1095,9 +1080,9 @@ void tst_QMenuBar::check_menuPosition() LayoutDirectionSaver directionSaver(Qt::RightToLeft); menu.clear(); QObject::connect(&menu, SIGNAL(aboutToShow()), &menu, SLOT(addActions())); - QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action); - mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft())); - QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier ); + QRect mbItemRect = w.menuBar()->actionGeometry(menu_action); + mbItemRect.moveTo(w.menuBar()->mapToGlobal(mbItemRect.topLeft())); + QTest::keyClick(&w, Qt::Key_M, Qt::AltModifier ); QVERIFY(menu.isActiveWindow()); QCOMPARE(menu.geometry().right(), mbItemRect.right()); menu.close(); @@ -1106,9 +1091,9 @@ void tst_QMenuBar::check_menuPosition() # ifndef QTEST_NO_CURSOR // QTBUG-28031: Click at bottom-right corner. { - mw->move(400, 200); + w.move(400, 200); LayoutDirectionSaver directionSaver(Qt::RightToLeft); - QMenuBar *mb = mw->menuBar(); + QMenuBar *mb = w.menuBar(); const QPoint localPos = mb->actionGeometry(menu.menuAction()).bottomRight() - QPoint(1, 1); const QPoint globalPos = mb->mapToGlobal(localPos); QCursor::setPos(globalPos); @@ -1125,6 +1110,7 @@ void tst_QMenuBar::task223138_triggered() { //we create a window with submenus and we check that both menubar and menus get the triggered signal QMainWindow win; + centerOnScreen(&win); QMenu *menu = win.menuBar()->addMenu("test"); QAction *top = menu->addAction("toplevelaction"); QMenu *submenu = menu->addMenu("nested menu"); @@ -1164,8 +1150,10 @@ void tst_QMenuBar::task256322_highlight() file2->setText("file2"); QAction *nothing = win.menuBar()->addAction("nothing"); + centerOnScreen(&win); win.show(); - QTest::qWait(200); + QApplication::setActiveWindow(&win); + QVERIFY(QTest::qWaitForWindowActive(&win)); QTest::mousePress(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file).center()); QTest::mouseMove(win.menuBar(), win.menuBar()->actionGeometry(file).center()); @@ -1186,12 +1174,11 @@ void tst_QMenuBar::task256322_highlight() QTest::mouseMove(win.menuBar(), nothingCenter); QTRY_VERIFY(!menu2.isVisible()); QVERIFY(!menu.isVisible()); - QAction *activeAction = win.menuBar()->activeAction(); #ifdef Q_OS_MAC - if ((QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) && (activeAction != nothing)) + if ((QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) && (win.menuBar()->activeAction() != nothing)) QEXPECT_FAIL("", "QTBUG-30565: Unstable test", Continue); #endif - QCOMPARE(activeAction, nothing); + QTRY_COMPARE(win.menuBar()->activeAction(), nothing); QTest::mouseRelease(win.menuBar(), Qt::LeftButton, 0, nothingCenter); } @@ -1234,6 +1221,7 @@ void tst_QMenuBar::menubarSizeHint() const int vmargin = style.pixelMetric(QStyle::PM_MenuBarVMargin); const int spacing = style.pixelMetric(QStyle::PM_MenuBarItemSpacing); + centerOnScreen(&mb); mb.show(); QRect result; foreach(QAction *action, mb.actions()) { @@ -1274,6 +1262,7 @@ void tst_QMenuBar::taskQTBUG4965_escapeEaten() QMenu menu("menu1"); QAction *first = menubar.addMenu(&menu); menu.addAction("quit", &menubar, SLOT(close()), QKeySequence("ESC")); + centerOnScreen(&menubar); menubar.show(); QApplication::setActiveWindow(&menubar); QVERIFY(QTest::qWaitForWindowExposed(&menubar)); @@ -1301,6 +1290,7 @@ void tst_QMenuBar::taskQTBUG11823_crashwithInvisibleActions() QAction * m = menubar.addAction( "&m" ); QAction * a = menubar.addAction( "&a" ); + centerOnScreen(&menubar); menubar.show(); QApplication::setActiveWindow(&menubar); QVERIFY(QTest::qWaitForWindowActive(&menubar)); @@ -1324,7 +1314,7 @@ void tst_QMenuBar::closeOnSecondClick() // QTBUG-32807, menu should close on 2nd { QMainWindow mainWindow; mainWindow.resize(300, 200); - mainWindow.move(QGuiApplication::primaryScreen()->geometry().center() - QPoint(150, 100)); + centerOnScreen(&mainWindow); #ifndef QT_NO_CURSOR QCursor::setPos(mainWindow.geometry().topLeft() - QPoint(100, 0)); #endif -- cgit v1.2.3 From 62645266590cfff620c4629ba85d8b9903c1f313 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Thu, 29 Aug 2013 13:12:41 +0200 Subject: Doc: minor language and layout edits Task-number: QTBUG-31801 Change-Id: I99043ba5d1a417e093ae2e4bc7d2967ec9d095fc Reviewed-by: Jerome Pasion --- src/tools/qdoc/doc/qdoc-minimum-qdocconf.qdoc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tools/qdoc/doc/qdoc-minimum-qdocconf.qdoc b/src/tools/qdoc/doc/qdoc-minimum-qdocconf.qdoc index 4289f357e9..20e0b86b6c 100644 --- a/src/tools/qdoc/doc/qdoc-minimum-qdocconf.qdoc +++ b/src/tools/qdoc/doc/qdoc-minimum-qdocconf.qdoc @@ -26,12 +26,15 @@ ****************************************************************************/ /*! \page qdoc-minimum-qdocconf.html -\title A minimal qdocconf file with comments +\title A minimal qdocconf file with Comments \brief Describes a minimal .qdocconf file -Below you will find the full contents of qtgui.qdocconf. The subsequent section will discuss -every statement in the qdocconf file. +Below you will find the full contents of qtgui.qdocconf. The subsequent section +will discuss every statement in the qdocconf file. + +Each line from the qdocconf file is first quoted. Below each statement you will +find the meaning. \code #include(compat.qdocconf) @@ -83,4 +86,6 @@ The source code of the example files can be found in the current directory. The image files can be found in the underlying directory "images". +\note Please take care with this minimal qdocconf file. Using it in the wrong directory +could cause qdoc to include a large number of files. */ -- cgit v1.2.3 From 4ffa60e03a6ef1a7b8c8458377697b25c07eda8b Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 29 Aug 2013 12:40:47 +0200 Subject: Update QLineEdit::placeholderText property documentation eeb31ad10a1c1b26233f383de6d1b2b217cde08f changed the behavior and allowed the placeholder text to stay visible even if the lineedit has focus. Task-number: QTBUG-33237 Change-Id: I733331be1d3225eb28390b21eb9a7e4971bfdc31 Reviewed-by: Olivier Goffart --- src/widgets/widgets/qlineedit.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 70083d7267..816e7be8fd 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -333,8 +333,7 @@ void QLineEdit::setText(const QString& text) \brief the line edit's placeholder text Setting this property makes the line edit display a grayed-out - placeholder text as long as the text() is empty and the widget doesn't - have focus. + placeholder text as long as the text() is empty. By default, this property contains an empty string. -- cgit v1.2.3 From e59a5f9fdcec5df2f54e88d75a75fcb4a2fe577b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 26 Aug 2013 11:52:47 +0200 Subject: Windows: Fix compilation with MinGW-64, gcc 4.8.1 A definition for FILE_ID_128 was added. Change-Id: Ifdfe5da1b15a90afdf5cf09d92838a04b1cf5c19 Reviewed-by: Kai Koehne --- src/corelib/io/qfilesystemengine_win.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index e8904b0ab7..57231b57a9 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -573,9 +573,12 @@ typedef enum { Q_FileIdInfo = 18 } Q_FILE_INFO_BY_HANDLE_CLASS; # if defined(Q_CC_MINGW) || (defined(Q_CC_MSVC) && _MSC_VER < 1700) +// MinGW-64 defines FILE_ID_128 as of gcc-4.8.1 along with FILE_SUPPORTS_INTEGRITY_STREAMS +# if !(defined(Q_CC_MINGW) && defined(FILE_SUPPORTS_INTEGRITY_STREAMS)) typedef struct _FILE_ID_128 { BYTE Identifier[16]; } FILE_ID_128, *PFILE_ID_128; +# endif // !(Q_CC_MINGW && FILE_SUPPORTS_INTEGRITY_STREAMS) typedef struct _FILE_ID_INFO { ULONGLONG VolumeSerialNumber; @@ -614,7 +617,8 @@ QByteArray fileIdWin8(HANDLE handle) &infoEx, sizeof(FILE_ID_INFO))) { result = QByteArray::number(infoEx.VolumeSerialNumber, 16); result += ':'; - result += QByteArray((char *)infoEx.FileId.Identifier, sizeof(infoEx.FileId.Identifier)).toHex(); + // Note: MinGW-64's definition of FILE_ID_128 differs from the MSVC one. + result += QByteArray((char *)&infoEx.FileId, sizeof(infoEx.FileId)).toHex(); } } return result; -- cgit v1.2.3 From b49327145eb984c2051585d89f0826c58d35c116 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 29 Aug 2013 12:53:18 +0200 Subject: QMetaMethod::invoke: compare the QMetaType id of the return types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since Qt5, the QMetaObject do not contains the string name of the builtin types, but only the QMetaType id. QMetaMethod::typeName convert back from the id to the string. But if the type is aliased, the string of the main type is returned. This was the case for example for qint64 which is transformed to "qlonglong". This causes a regression in QMetaType::invoke when trying to invoke a method which return an aliased type, since the string comparison would fail. Fix the problem by also comparing the metatype id. Changelog: QMetaMethod::invoke: Fix return of aliased meta type Task-number: QTBUG-33222 Change-Id: Iec7b99dcbf7b23eb818de74f413e4451ce510ac4 Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qmetaobject.cpp | 9 +++++++-- tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 4dc766ecc5..8d6cf5beb5 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -42,6 +42,7 @@ #include "qmetaobject.h" #include "qmetatype.h" #include "qobject.h" +#include "qmetaobject_p.h" #include #include @@ -2098,8 +2099,12 @@ bool QMetaMethod::invoke(QObject *object, if (qstrcmp(returnValue.name(), retType) != 0) { // normalize the return value as well QByteArray normalized = QMetaObject::normalizedType(returnValue.name()); - if (qstrcmp(normalized.constData(), retType) != 0) - return false; + if (qstrcmp(normalized.constData(), retType) != 0) { + // String comparison failed, try compare the metatype. + int t = returnType(); + if (t == QMetaType::UnknownType || t != QMetaType::type(normalized)) + return false; + } } } diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index ca80c8926f..4f1320e375 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -328,6 +328,7 @@ public slots: QObject *sl11(); const char *sl12(); QList sl13(QList l1); + qint64 sl14(); void testSender(); void testReference(QString &str); @@ -395,6 +396,9 @@ const char *QtTestObject::sl12() { slotResult = "sl12"; return "foo"; } QList QtTestObject::sl13(QList l1) { slotResult = "sl13"; return l1; } +qint64 QtTestObject::sl14() +{ slotResult = "sl14"; return Q_INT64_C(123456789)*123456789; } + void QtTestObject::testReference(QString &str) { slotResult = "testReference:" + str; str = "gotcha"; } @@ -513,6 +517,13 @@ void tst_QMetaObject::invokeMetaMember() QCOMPARE(returnValue, argument); QCOMPARE(obj.slotResult, QString("sl13")); + // return qint64 + qint64 return64; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl14", + Q_RETURN_ARG(qint64, return64))); + QCOMPARE(return64, Q_INT64_C(123456789)*123456789); + QCOMPARE(obj.slotResult, QString("sl14")); + //test signals QVERIFY(QMetaObject::invokeMethod(&obj, "sig0")); QCOMPARE(obj.slotResult, QString("sl0")); -- cgit v1.2.3 From 0ab3e290c4808f73d46903a5274929e3833d8d3c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 28 Aug 2013 12:20:17 +0200 Subject: Initialize variables to fix valgrind warning in pnghandler. Conditional jump or move depends on uninitialised value(s) ==7986== at 0x5B838E8: QPngHandlerPrivate::readPngImage(QImage*) (qpnghandler.cpp:617) Change-Id: Ie739ca1665ce600426e2816a6229145d814125cb Reviewed-by: aavit --- src/gui/image/qpnghandler.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index e43ac666c7..7838b7df8e 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -591,14 +591,14 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) if (doScaledRead) { read_image_scaled(outImage, png_ptr, info_ptr, amp, scaledSize); } else { - png_uint_32 width; - png_uint_32 height; - png_int_32 offset_x; - png_int_32 offset_y; - - int bit_depth; - int color_type; - int unit_type; + png_uint_32 width = 0; + png_uint_32 height = 0; + png_int_32 offset_x = 0; + png_int_32 offset_y = 0; + + int bit_depth = 0; + int color_type = 0; + int unit_type = PNG_OFFSET_PIXEL; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type); uchar *data = outImage->bits(); -- cgit v1.2.3 From 99362fb7f25a88829c2d824ebfe6da61d4d7b35f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 30 Aug 2013 12:08:47 +0200 Subject: Windows XP file dialog: Fix appending the selected filter suffix. The mechanism is triggered by always setting lpstrDefExt, Task-number: QTBUG-33156 Change-Id: Ib3a49410a1ad78fb433a4e0803a0751ec8c2a51e Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowsdialoghelpers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 27a7044868..9a7d03c0c2 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -1818,8 +1818,8 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow QString defaultSuffix = m_options->defaultSuffix(); if (defaultSuffix.startsWith(QLatin1Char('.'))) defaultSuffix.remove(0, 1); - if (!defaultSuffix.isEmpty()) - ofn->lpstrDefExt = qStringToWCharArray(defaultSuffix); + // QTBUG-33156, also create empty strings to trigger the appending mechanism. + ofn->lpstrDefExt = qStringToWCharArray(defaultSuffix); } // Flags. ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_PATHMUSTEXIST); -- cgit v1.2.3 From 16f3c84e30ba82481d0d8ffdc6a239452a45c8bf Mon Sep 17 00:00:00 2001 From: Leonard Lee Date: Thu, 22 Aug 2013 16:37:17 +0200 Subject: Remove the size limit of QByteArray information. The information is explaining implementation details rather than on how to use it effectively. The size limit of QByteArray may vary depending on available memory. Task-number: QTBUG-33037 Change-Id: I361316422ade3624a0c2864d93f87caeb654f4d7 Reviewed-by: Thiago Macieira --- src/corelib/tools/qbytearray.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index e993855e7e..6ce17e5e13 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -645,8 +645,6 @@ static inline char qToLower(char c) store raw binary data, and when memory conservation is critical (e.g., with Qt for Embedded Linux). - The maximum array size of a QByteArray is under 2^30. - One way to initialize a QByteArray is simply to pass a \c{const char *} to its constructor. For example, the following code creates a byte array of size 5 containing the data "Hello": -- cgit v1.2.3 From 0ed30cbf09db591b46370888fa2f687310bf5cff Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 2 Sep 2013 10:20:37 +0200 Subject: Fix compilation with latest Mingw-w64 headers Fix compilation with e.g. mingw-builds 4.8.1-rev4 package. The Mingw-W64 headers define SHSTOCKICONINFO only for vista and newer. Task-number: QTBUG-33225 Change-Id: I30a62c642ae017c7eafb99b1efb06578fd61a12e Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowstheme.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 0fcd20f7bb..9f6e6b18e7 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -39,6 +39,12 @@ ** ****************************************************************************/ +// SHSTOCKICONINFO is only available since Vista +#if _WIN32_WINNT < 0x0600 +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0600 +#endif + #include "qwindowstheme.h" #include "qwindowsdialoghelpers.h" #include "qwindowscontext.h" -- cgit v1.2.3 From 0278310f9e27b1c6aca6bd70dc5415a240cd33c3 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 7 Aug 2013 09:09:13 +0200 Subject: Ensure the input file is first in the list of dependencies When building a project in VS then it would cause a rebuild under certain situations even though a rebuild is not actually required. The root problem exists in VS in the following configuration: 1. A file has a custom build tool specified 2. The custom build tool has additional dependencies 3. The input file is specified in the additional dependencies 4. There are files in the additional dependency list This is the situation with form files in Qt that have include hints specified in Qt Designer. The include hints get specified in the additional dependencies for the custom build tool. What happens is that VS will process files in the additional dependency list differently based on where they appear in the list relative to the input file. If a dependency appears before the input file, VS will require the file as a build input. If you just specify a file name, VS looks in the project directory (and only the project directory) for that file. You have to specify the path (relative or absolute) to get VS to look elsewhere. If VS does not find the dependency, VS thinks the project is out of date (since the missing dependency is a required build input) and will rebuild the input file. If the dependency appears after the input file and the file doesn't exist, VS does not include the dependency as a build input. Since the file is not a build input, no rebuild is required. Change-Id: I5af460d21ad049ed7819746fd60c98677b810692 Reviewed-by: Oswald Buddenhagen Reviewed-by: Joerg Bornemann --- qmake/generators/win32/msvc_objectmodel.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 8c25ab6f9b..d6d40bcc68 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -2311,7 +2311,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) inputs += Option::fixPathToTargetOS(file, false); } } - deps += inputs; // input files themselves too.. + deps = inputs + deps; // input files themselves too.. // Replace variables for command w/all input files // ### join gives path issues with directories containing spaces! @@ -2319,7 +2319,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) inputs.join(' '), out); } else { - deps += inFile; // input file itself too.. + deps.prepend(inFile); // input file itself too.. cmd = Project->replaceExtraCompilerVariables(tmp_cmd, inFile, out); @@ -2356,14 +2356,14 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) deps += CustomBuildTool.AdditionalDependencies; // Make sure that all deps are only once - QHash uniqDeps; + QStringList uniqDeps; for (int c = 0; c < deps.count(); ++c) { QString aDep = deps.at(c).trimmed(); if (!aDep.isEmpty()) - uniqDeps[aDep] = false; + uniqDeps << aDep; } - CustomBuildTool.AdditionalDependencies = uniqDeps.keys(); - CustomBuildTool.AdditionalDependencies.sort(); + uniqDeps.removeDuplicates(); + CustomBuildTool.AdditionalDependencies = uniqDeps; } // Ensure that none of the output files are also dependencies. Or else, the custom buildstep -- cgit v1.2.3 From cdbf8dd276a2b6f3544a4e67e1216a1b8ca9f29e Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 26 Aug 2013 12:05:54 +0200 Subject: Ensure the timer is killed when appropriate before starting a new one When the mouse moves while the sloppy menu timer is still running then it would end up just creating a new one and the old one would continue to run. If the action that it is relevant for is different then it should restart the timer, otherwise it should just ignore the mouse move and let the other timer continue. Change-Id: Id03014fa05596bd6ede887fa917e21ca5a7690d8 Reviewed-by: Friedemann Kleint --- src/widgets/widgets/qmenu.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 4df89a5ede..c305748c7d 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -2864,8 +2864,15 @@ void QMenu::mouseMoveEvent(QMouseEvent *e) d->mouseDown = this; } if (d->sloppyRegion.contains(e->pos())) { - d->sloppyAction = action; - QMenuPrivate::sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)*6); + // If the timer is already running then don't start a new one unless the action is the same + if (d->sloppyAction != action && QMenuPrivate::sloppyDelayTimer != 0) { + killTimer(QMenuPrivate::sloppyDelayTimer); + QMenuPrivate::sloppyDelayTimer = 0; + } + if (QMenuPrivate::sloppyDelayTimer == 0) { + d->sloppyAction = action; + QMenuPrivate::sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this) * 6); + } } else if (action != d->currentAction) { d->setCurrentAction(action, style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)); } -- cgit v1.2.3 From 5236f74942f0df8a74b696f133cbbac763e6950e Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 3 Sep 2013 13:44:34 +0200 Subject: Fix regression in QListView The fix was originally applied to Qt 4.8 (4c64464), but missed Qt 5 which had already been branched at that point of time. Task-number: QTBUG-33089 Task-number: QTBUG-21433 Change-Id: Ia3cd35d29dbdc70ba55b6f0840c4082e232c24ae Reviewed-by: Jens Bache-Wiig --- src/widgets/itemviews/qlistview.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 8ccb0557cb..3690b15650 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1456,7 +1456,7 @@ void QListView::doItemsLayout() void QListView::updateGeometries() { Q_D(QListView); - if (d->model->rowCount(d->root) <= 0 || d->model->columnCount(d->root) <= 0) { + if (geometry().isEmpty() || d->model->rowCount(d->root) <= 0 || d->model->columnCount(d->root) <= 0) { horizontalScrollBar()->setRange(0, 0); verticalScrollBar()->setRange(0, 0); } else { @@ -1471,15 +1471,15 @@ void QListView::updateGeometries() // if the scroll bars are turned off, we resize the contents to the viewport if (d->movement == Static && !d->isWrapping()) { - const QSize maxSize = maximumViewportSize(); + d->layoutChildren(); // we need the viewport size to be updated if (d->flow == TopToBottom) { if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) { - d->setContentsSize(maxSize.width(), contentsSize().height()); + d->setContentsSize(viewport()->width(), contentsSize().height()); horizontalScrollBar()->setRange(0, 0); // we see all the contents anyway } } else { // LeftToRight if (verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) { - d->setContentsSize(contentsSize().width(), maxSize.height()); + d->setContentsSize(contentsSize().width(), viewport()->height()); verticalScrollBar()->setRange(0, 0); // we see all the contents anyway } } -- cgit v1.2.3 From 86f8bee96b658d1712733477e26e70a1fd723102 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 3 Sep 2013 16:25:53 +0200 Subject: OSX: clicking outside a popup: don't propagate the event elsewhere If you click outside a popup window, it only closes the popup; any other widget that was under the cursor at that time should not get the event. The bug was about the popup list on a combobox, but this patch assumes that this rule is universal; can't think of any exceptions at this time. (E.g. a tooltip is not a popup) Clicking on the application menubar still does not close the popup though. Task-number: QTBUG-33241 Change-Id: I2444b7cfd40cf75ff7b70e3fecfeceb2fd4623bf Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qnsview.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 4505f8b8cf..c6dce8b6f6 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -600,6 +600,7 @@ static QTouchDevice *touchDevice = 0; QWindowSystemInterface::handleCloseEvent(m_platformWindow->m_activePopupWindow); QWindowSystemInterface::flushWindowSystemEvents(); m_platformWindow->m_activePopupWindow = 0; + return; } if ([self hasMarkedText]) { NSInputManager* inputManager = [NSInputManager currentInputManager]; -- cgit v1.2.3 From a2bdda8e3ba324a51620d9e758e444d02c4fd061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 30 Aug 2013 14:20:21 +0200 Subject: Fix event delivery for apps with native widgets. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Native widgets, which have a NSView but not a NSWindow, must be created in the hidden state to prevent Cocoa from selecting them for event delivery. Change-Id: I741e52729047ad4e03959f2244abe5b14b5df46b Reviewed-by: Gabriel de Dietrich Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 86f12e0e5f..a3797682a3 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -792,6 +792,7 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) QRect rect = window()->geometry(); NSRect frame = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); [m_contentView setFrame:frame]; + [m_contentView setHidden: YES]; } const qreal opacity = qt_window_private(window())->opacity; -- cgit v1.2.3 From 8fd71914b43350a21c0c05051c1a6e24e9d8cb85 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 20 Aug 2013 16:55:17 +0200 Subject: Cocoa: Unregister view from window's notifications only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise the view will miss its own frame change notifications. And we must unregister from all the notifications during dealloc. This would also reveal a bug where we would expose an NSView before its super view is visible, leading to those "invalid drawable" warnings when using QQuickViews. Therefore, we add this extra check in QCocoaWindow::exposeWindow(). Task-number: QTBUG-32826 Change-Id: I69018cb6f199b242768d114b2aa34c7f2d243196 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 5 +++-- src/plugins/platforms/cocoa/qnsview.mm | 9 +++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index a3797682a3..c239aedb05 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -911,7 +911,8 @@ void QCocoaWindow::clearNSWindow(NSWindow *window) [window setContentView:nil]; [window setDelegate:nil]; [window clearPlatformWindow]; - [[NSNotificationCenter defaultCenter] removeObserver:m_contentView]; + [[NSNotificationCenter defaultCenter] removeObserver:m_contentView + name:nil object:window]; } // Returns the current global screen geometry for the nswindow associated with this window. @@ -1023,7 +1024,7 @@ qreal QCocoaWindow::devicePixelRatio() const void QCocoaWindow::exposeWindow() { - if (!m_isExposed) { + if (!m_isExposed && ![[m_contentView superview] isHidden]) { m_isExposed = true; QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index c6dce8b6f6..c2ffe96f8c 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -107,12 +107,9 @@ static QTouchDevice *touchDevice = 0; m_maskImage = 0; m_maskData = 0; m_window = 0; - if (m_subscribesForGlobalFrameNotifications) { - m_subscribesForGlobalFrameNotifications = false; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSViewGlobalFrameDidChangeNotification - object:self]; -} + m_subscribesForGlobalFrameNotifications = false; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + delete currentCustomDragTypes; [super dealloc]; -- cgit v1.2.3 From 9554088557571d5c6b96c710424e591ab8db4e0d Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 3 Sep 2013 14:23:33 +0200 Subject: Cocoa: Fix NSMenu popup coordinates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those should be in window coordinates (or rather, its content view) not view coordinates. Task-number: QTBUG-32826 Change-Id: I52dddeccf17b359163ad477ce4299b934633b4fa Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoamenu.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index f9e033d21b..2e53000596 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -455,7 +455,9 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, QPoint pos, const QPlatf // Else, we need to transform 'pos' to window or screen coordinates. NSPoint nsPos = NSMakePoint(pos.x() - 1, pos.y()); if (view) { + // Flip y-coordinate first, the convert to content view space. nsPos.y = view.frame.size.height - nsPos.y; + nsPos = [view convertPoint:nsPos toView:view.window.contentView]; } else if (!QGuiApplication::screens().isEmpty()) { QScreen *screen = QGuiApplication::screens().at(0); nsPos.y = screen->availableVirtualSize().height() - nsPos.y; -- cgit v1.2.3 From 5ca5f4d344f6eb644a9b56f8b1ad166582bb8483 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 29 Aug 2013 20:43:50 +0200 Subject: build glxconvenience also without Xrender it contains #ifdefs for that, no need to disable it completely. Change-Id: I4a7d03e09fefded966e2c3fec58a470b4f1d3300 Reviewed-by: Giuseppe D'Angelo --- src/platformsupport/glxconvenience/glxconvenience.pri | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platformsupport/glxconvenience/glxconvenience.pri b/src/platformsupport/glxconvenience/glxconvenience.pri index d325f5adf9..cc5b198f6c 100644 --- a/src/platformsupport/glxconvenience/glxconvenience.pri +++ b/src/platformsupport/glxconvenience/glxconvenience.pri @@ -1,6 +1,7 @@ -contains(QT_CONFIG,xlib):contains(QT_CONFIG,xrender) { +contains(QT_CONFIG, xlib) { contains(QT_CONFIG,opengl):!contains(QT_CONFIG,opengles2) { - LIBS_PRIVATE += $$QMAKE_LIBS_X11 -lXrender + contains(QT_CONFIG, xrender): LIBS_PRIVATE += -lXrender + LIBS_PRIVATE += $$QMAKE_LIBS_X11 HEADERS += $$PWD/qglxconvenience_p.h SOURCES += $$PWD/qglxconvenience.cpp } -- cgit v1.2.3 From ac327aa3af8d934abb1d605541d9b6f8d1cfdc27 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 29 Aug 2013 20:45:26 +0200 Subject: the condition for building the x11 offscreen plugin is ... having xlib Task-number: QTBUG-33240 Change-Id: Idc96239b0bcbe98d1519c239600aebcda42e8818 Reviewed-by: Giuseppe D'Angelo --- src/plugins/platforms/offscreen/offscreen.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/offscreen/offscreen.pro b/src/plugins/platforms/offscreen/offscreen.pro index 270e3ce228..9f10eaad94 100644 --- a/src/plugins/platforms/offscreen/offscreen.pro +++ b/src/plugins/platforms/offscreen/offscreen.pro @@ -16,7 +16,7 @@ HEADERS = qoffscreenintegration.h \ OTHER_FILES += offscreen.json -contains(QT_CONFIG, xcb):contains(QT_CONFIG, opengl):!contains(QT_CONFIG, opengles2) { +contains(QT_CONFIG, xlib):contains(QT_CONFIG, opengl):!contains(QT_CONFIG, opengles2) { SOURCES += qoffscreenintegration_x11.cpp HEADERS += qoffscreenintegration_x11.h system(echo "Using X11 offscreen integration with GLX") -- cgit v1.2.3 From 239fe290ad241aac3d6b86ce598f679a0a72fd11 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 5 Sep 2013 14:36:59 +0200 Subject: Center the QColumnView on-screen, in case that helps avoid the test failure. Task-number: QTBUG-32927 Change-Id: Icf0301d583b2ca6e2e099a19eb1f91feac1fb975 Reviewed-by: Friedemann Kleint --- tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp b/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp index d3191b2206..6c04e5b39a 100644 --- a/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp +++ b/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #define ANIMATION_DELAY 300 @@ -387,6 +388,12 @@ void tst_QColumnView::scrollTo_data() QTest::newRow("reverse") << true << false; } +static inline void centerOnScreen(QWidget *w) +{ + const QPoint offset = QPoint(w->width() / 2, w->height() / 2); + w->move(QGuiApplication::primaryScreen()->availableGeometry().center() - offset); +} + void tst_QColumnView::scrollTo() { QFETCH(bool, reverse); @@ -397,6 +404,7 @@ void tst_QColumnView::scrollTo() ColumnView view(&topLevel); view.resize(200, 200); topLevel.show(); + centerOnScreen(&topLevel); view.scrollTo(QModelIndex(), QAbstractItemView::EnsureVisible); QCOMPARE(view.HorizontalOffset(), 0); -- cgit v1.2.3 From 21fd5baf804ca9dfe5a52924a9c421951db8fd4f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 4 Sep 2013 22:01:47 +0200 Subject: Add source directories to include paths if needed. Task-number: QTBUG-33145 Change-Id: I555064cd92691459222463df9917f8222e31323b Reviewed-by: Oswald Buddenhagen Reviewed-by: Stephen Kelly --- mkspecs/features/create_cmake.prf | 15 +++++++++++++-- mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in | 8 ++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf index d8bef46481..1d56223118 100644 --- a/mkspecs/features/create_cmake.prf +++ b/mkspecs/features/create_cmake.prf @@ -24,6 +24,19 @@ load(cmake_functions) CMAKE_INSTALL_LIBS_DIR = $$cmakeTargetPath($$[QT_INSTALL_LIBS]) contains(CMAKE_INSTALL_LIBS_DIR, ^(/usr)?/lib(64)?.*): CMAKE_USR_MOVE_WORKAROUND = $$CMAKE_INSTALL_LIBS_DIR +CMAKE_MODULE_NAME = $$cmakeModuleName($${MODULE}) + +split_incpath { + CMAKE_ADD_SOURCE_INCLUDE_DIRS = true + CMAKE_NO_PRIVATE_INCLUDES = true # Don't add private includes in the build dir which don't exist + CMAKE_SOURCE_INCLUDES = \ + $$cmakeTargetPath($$QT_MODULE_INCLUDE_BASE) \ + $$cmakeTargetPath($$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}) + CMAKE_SOURCE_PRIVATE_INCLUDES = \ + $$cmakeTargetPath($$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION)) \ + $$cmakeTargetPath($$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION)/Qt$${CMAKE_MODULE_NAME}) +} + CMAKE_INCLUDE_DIR = $$cmakeRelativePath($$[QT_INSTALL_HEADERS], $$[QT_INSTALL_PREFIX]) contains(CMAKE_INCLUDE_DIR, "^\\.\\./.*") { CMAKE_INCLUDE_DIR = $$[QT_INSTALL_HEADERS]/ @@ -93,8 +106,6 @@ unix:contains(QT_CONFIG, reduce_relocations):CMAKE_ADD_FPIE_FLAGS = "true" CMAKE_MKSPEC = $$[QMAKE_XSPEC] -CMAKE_MODULE_NAME = $$cmakeModuleName($${MODULE}) - CMAKE_MODULE_DEPS = $$cmakeModuleList($$sort_depends(QT.$${MODULE}.depends, QT.)) CMAKE_PARTIAL_MODULE_DEPS = $$replace(CMAKE_MODULE_DEPS, ";", ";Qt5::") !isEmpty(CMAKE_PARTIAL_MODULE_DEPS):CMAKE_QT5_MODULE_DEPS = "Qt5::$${CMAKE_PARTIAL_MODULE_DEPS}" diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in index 2ffb980156..9da827ca34 100644 --- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in +++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in @@ -120,6 +120,14 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) !!ENDIF !!ENDIF !!ENDIF +!!IF !isEmpty(CMAKE_ADD_SOURCE_INCLUDE_DIRS) + list(APPEND _Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS + $$CMAKE_SOURCE_INCLUDES + ) + set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS + $$CMAKE_SOURCE_PRIVATE_INCLUDES + ) +!!ENDIF !!ELSE set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS) set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS) -- cgit v1.2.3 From 018c4850c9d8c6a806d40a6a0da14855f071d4fe Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 30 Aug 2013 16:09:06 +0200 Subject: Fix usr-move workaround in the presence of multi-arch. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cmake directory may not be $PREFIX/lib/cmake, but instead $PREFIX/lib//cmake. Getting the PATH of such a directory will not lead us to $PREFIX/, but to $PREFIX/lib. Use a relative calculation instead. Task-number: QTBUG-33223 Change-Id: Ice4e0f859ab1df238bad4eb942f073e84dd86cc3 Reviewed-by: Oswald Buddenhagen Reviewed-by: Lisandro Damián Nicanor Pérez Meyer Reviewed-by: Stephen Kelly --- mkspecs/features/create_cmake.prf | 4 ++-- mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf index 1d56223118..6b0f98711e 100644 --- a/mkspecs/features/create_cmake.prf +++ b/mkspecs/features/create_cmake.prf @@ -50,10 +50,10 @@ contains(CMAKE_LIB_DIR,"^\\.\\./.*") { CMAKE_LIB_DIR = $$[QT_INSTALL_LIBS]/ CMAKE_LIB_DIR_IS_ABSOLUTE = True } else { - CMAKE_RELATIVE_INSTALL_DIR = $$cmakeRelativePath($$[QT_INSTALL_PREFIX], $$[QT_INSTALL_LIBS]) + CMAKE_RELATIVE_INSTALL_LIBS_DIR = $$cmakeRelativePath($$[QT_INSTALL_PREFIX], $$[QT_INSTALL_LIBS]) # We need to go up another two levels because the CMake files are # installed in $${CMAKE_LIB_DIR}/cmake/Qt5$${CMAKE_MODULE_NAME} - CMAKE_RELATIVE_INSTALL_DIR = "$${CMAKE_RELATIVE_INSTALL_DIR}../../" + CMAKE_RELATIVE_INSTALL_DIR = "$${CMAKE_RELATIVE_INSTALL_LIBS_DIR}../../" } CMAKE_BIN_DIR = $$cmakeRelativePath($$[QT_HOST_BINS], $$[QT_INSTALL_PREFIX]) diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in index 9da827ca34..657c7c642d 100644 --- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in +++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in @@ -13,7 +13,7 @@ get_filename_component(_IMPORT_PREFIX \"${CMAKE_CURRENT_LIST_FILE}\" PATH) get_filename_component(_realCurr \"${_IMPORT_PREFIX}\" REALPATH) get_filename_component(_realOrig \"$$CMAKE_INSTALL_LIBS_DIR/cmake/Qt5$${CMAKE_MODULE_NAME}\" REALPATH) if(_realCurr STREQUAL _realOrig) - get_filename_component(_qt5$${CMAKE_MODULE_NAME}_install_prefix \"$$CMAKE_INSTALL_LIBS_DIR\" PATH) + get_filename_component(_qt5$${CMAKE_MODULE_NAME}_install_prefix \"$$CMAKE_INSTALL_LIBS_DIR/$${CMAKE_RELATIVE_INSTALL_LIBS_DIR}\" ABSOLUTE) else() get_filename_component(_qt5$${CMAKE_MODULE_NAME}_install_prefix \"${CMAKE_CURRENT_LIST_DIR}/$${CMAKE_RELATIVE_INSTALL_DIR}\" ABSOLUTE) endif() -- cgit v1.2.3 From ba43b70132b661d1b8d99af5258fca3567fe776c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Sep 2013 16:59:46 -0700 Subject: Compile in strict-iterator mode under MSVC MSVC doesn't like operator->() returning a pointer to non-aggregate. So we must make sure that the expanded code does not try to call it by doing: abegin->~T(); Instead, we make an implicit call to operator T*() with that static_cast. If abegin is a non-strict iterator, it's already a T*, so the static_cast is a no-op. qvector.h(645) : error C2839: invalid return type 'int *' for overloaded 'operator ->' Change-Id: I06f983bab7677cb60ef3913cdce349e26896bfb6 Reviewed-by: Olivier Goffart --- src/corelib/tools/qvector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 489ee821b9..4ff2b9f8e0 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -634,7 +634,7 @@ typename QVector::iterator QVector::erase(iterator abegin, iterator aend) iterator moveEnd = d->end(); while (moveBegin != moveEnd) { if (QTypeInfo::isComplex) - abegin->~T(); + static_cast(abegin)->~T(); new (abegin++) T(*moveBegin++); } if (abegin < d->end()) { -- cgit v1.2.3 From 730bc064a070e886e10950ccfd59780e8976f5fd Mon Sep 17 00:00:00 2001 From: Marcel Krems Date: Sat, 31 Aug 2013 16:42:43 +0200 Subject: Forward QGraphicsView::mouseDoubleClickEvent Do the same as in mousePressEvent. Otherwise it is not possible to handle the event in one of the graphics views parents. Task-number: QTBUG-8061 Change-Id: I67c7635361a9ed595c513c28ea016e6253fa2101 Reviewed-by: Andreas Aardal Hanssen --- src/widgets/graphicsview/qgraphicsview.cpp | 7 ++ .../qgraphicsview/tst_qgraphicsview.cpp | 114 ++++++++++++++++++++- 2 files changed, 116 insertions(+), 5 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp index 846858ab31..a39c084798 100644 --- a/src/widgets/graphicsview/qgraphicsview.cpp +++ b/src/widgets/graphicsview/qgraphicsview.cpp @@ -3221,6 +3221,13 @@ void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event) qt_sendSpontaneousEvent(d->scene, &mouseEvent); else QApplication::sendEvent(d->scene, &mouseEvent); + + // Update the original mouse event accepted state. + const bool isAccepted = mouseEvent.isAccepted(); + event->setAccepted(isAccepted); + + // Update the last mouse event accepted state. + d->lastMouseEvent.setAccepted(isAccepted); } /*! diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 9e06435ca7..7a0ba50ff0 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -221,6 +221,9 @@ private slots: void scrollBarRanges_data(); void scrollBarRanges(); void acceptMousePressEvent(); + void acceptMouseDoubleClickEvent(); + void forwardMousePress(); + void forwardMouseDoubleClick(); void replayMouseMove(); void itemsUnderMouse(); void embeddedViews(); @@ -2832,16 +2835,22 @@ class TestView : public QGraphicsView { public: TestView(QGraphicsScene *scene) - : QGraphicsView(scene), accepted(false) + : QGraphicsView(scene), pressAccepted(false), doubleClickAccepted(false) { } - bool accepted; + bool pressAccepted; + bool doubleClickAccepted; protected: void mousePressEvent(QMouseEvent *event) { QGraphicsView::mousePressEvent(event); - accepted = event->isAccepted(); + pressAccepted = event->isAccepted(); + } + void mouseDoubleClickEvent(QMouseEvent *event) + { + QGraphicsView::mouseDoubleClickEvent(event); + doubleClickAccepted = event->isAccepted(); } }; @@ -2859,14 +2868,109 @@ void tst_QGraphicsView::acceptMousePressEvent() Qt::LeftButton, 0, 0); event.setAccepted(false); QApplication::sendEvent(view.viewport(), &event); - QVERIFY(!view.accepted); + QVERIFY(!view.pressAccepted); scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable); qApp->processEvents(); // ensure scene rect is updated QApplication::sendEvent(view.viewport(), &event); - QVERIFY(view.accepted); + QVERIFY(view.pressAccepted); +} + +void tst_QGraphicsView::acceptMouseDoubleClickEvent() +{ + QGraphicsScene scene; + + TestView view(&scene); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QMouseEvent event(QEvent::MouseButtonDblClick, + view.viewport()->rect().center(), + view.viewport()->mapToGlobal(view.viewport()->rect().center()), + Qt::LeftButton, 0, 0); + event.setAccepted(false); + QApplication::sendEvent(view.viewport(), &event); + QVERIFY(!view.doubleClickAccepted); + + scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable); + + qApp->processEvents(); // ensure scene rect is updated + + QApplication::sendEvent(view.viewport(), &event); + QVERIFY(view.doubleClickAccepted); +} + +class TestWidget : public QWidget +{ +public: + TestWidget() + : QWidget(), pressForwarded(false), doubleClickForwarded(false) + { } + + bool pressForwarded; + bool doubleClickForwarded; + +protected: + void mousePressEvent(QMouseEvent *event) + { + QWidget::mousePressEvent(event); + pressForwarded = true; + } + void mouseDoubleClickEvent(QMouseEvent *event) + { + QWidget::mouseDoubleClickEvent(event); + doubleClickForwarded = true; + } +}; + +void tst_QGraphicsView::forwardMousePress() +{ + TestWidget widget; + QGraphicsScene scene; + QGraphicsView view(&scene); + QHBoxLayout layout; + widget.setLayout(&layout); + layout.addWidget(&view); + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + widget.pressForwarded = false; + QTest::mouseClick(view.viewport(), Qt::LeftButton); + QVERIFY(widget.pressForwarded); + + scene.addRect(0, 0, 2000, 2000); + + qApp->processEvents(); // ensure scene rect is updated + + widget.pressForwarded = false; + QTest::mouseClick(view.viewport(), Qt::LeftButton); + QVERIFY(widget.pressForwarded); +} + +void tst_QGraphicsView::forwardMouseDoubleClick() +{ + TestWidget widget; + QGraphicsScene scene; + QGraphicsView view(&scene); + QHBoxLayout layout; + widget.setLayout(&layout); + layout.addWidget(&view); + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + widget.doubleClickForwarded = false; + QTest::mouseDClick(view.viewport(), Qt::LeftButton); + QVERIFY(widget.doubleClickForwarded); + + scene.addRect(0, 0, 2000, 2000); + + qApp->processEvents(); // ensure scene rect is updated + + widget.doubleClickForwarded = false; + QTest::mouseDClick(view.viewport(), Qt::LeftButton); + QVERIFY(widget.doubleClickForwarded); } void tst_QGraphicsView::replayMouseMove() -- cgit v1.2.3