From 56cdd12649ce194911bafab1914abba5332d7260 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 21 Apr 2015 10:37:38 +0200 Subject: [PATCH 01/52] Cocoa: fix compiler warning. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /Users/erik/dev/qt5-stable/qtbase/src/plugins/platforms/cocoa/qnsview.mm:702:22: warning: incompatible pointer types assigning to 'QNSView_QtNS *' from 'NSView *' [-Wincompatible-pointer-types] targetView = popup->contentView(); ^~~~~~~~~~~~~~~~~~~~ Change-Id: I9e7e25ee9b6dc80ee6f438dc85417838039d440a Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 04f7119730..12854593f8 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -698,8 +698,10 @@ QT_WARNING_POP } // Popups implicitly grap mouse events; forward to the active popup if there is one - if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) - targetView = popup->contentView(); + if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) { + if (QNSView *popupView = popup->qtView()) + targetView = popupView; + } [targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; ulong timestamp = [theEvent timestamp] * 1000; From 5350ee7ad5570bd659c4e259d618ceadd3a72d43 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 21 Apr 2015 11:26:03 +0200 Subject: [PATCH 02/52] Cocoa: fix compiler warning. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /Users/erik/dev/qt5-stable/qtbase/src/plugins/platforms/cocoa/qcocoaapplication.mm:137:18: warning: case value not in enumerated type 'NSEventSubtype' [-Wswitch] case QtCocoaEventSubTypePostMessage: ^ Change-Id: Ib496e61a6939f021c90234fef3689b1643003ddd Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaapplication.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoaapplication.mm b/src/plugins/platforms/cocoa/qcocoaapplication.mm index 79399e4183..227ab05c25 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplication.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplication.mm @@ -133,7 +133,7 @@ static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSE return true; if ([event type] == NSApplicationDefined) { - switch ([event subtype]) { + switch (static_cast([event subtype])) { case QtCocoaEventSubTypePostMessage: [NSApp QT_MANGLE_NAMESPACE(qt_sendPostedMessage):event]; return true; From 1fe23497625617cac6e1481f8f2d8d085a876550 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 21 Apr 2015 11:27:07 +0200 Subject: [PATCH 03/52] Cocoa: stop using the deprecated NSInputManager. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced by NSTextInputContext. Change-Id: I694b28b766f8bf1d37e0ee87ff503e33d205f8ab Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoainputcontext.mm | 5 ++--- src/plugins/platforms/cocoa/qnsview.mm | 5 +---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm index 0eafae1f2d..c22fe8774b 100644 --- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -99,9 +99,8 @@ void QCocoaInputContext::reset() return; QCocoaAutoReleasePool pool; - NSInputManager *currentIManager = [NSInputManager currentInputManager]; - if (currentIManager) { - [currentIManager markedTextAbandoned:view]; + if (NSTextInputContext *ctxt = [NSTextInputContext currentInputContext]) { + [ctxt discardMarkedText]; [view unmarkText]; } } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 12854593f8..ad81c396f9 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -804,10 +804,7 @@ QT_WARNING_POP } if ([self hasMarkedText]) { - NSInputManager* inputManager = [NSInputManager currentInputManager]; - if ([inputManager wantsToHandleMouseEvents]) { - [inputManager handleMouseEvent:theEvent]; - } + [[NSTextInputContext currentInputContext] handleEvent:theEvent]; } else { if ([QNSView convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) { m_buttons |= Qt::RightButton; From 7d84eb70259b6481d5cf5cff4714029680beaaf6 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 21 Apr 2015 11:28:01 +0200 Subject: [PATCH 04/52] Cocoa: Stop using deprecated -convertBaseToScreen:. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced by -convertRectToScreen:. Change-Id: I38e2b5918a5ee528d6ce65f676e542e365d610a3 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index ad81c396f9..cb8c6ec11a 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -753,12 +753,13 @@ QT_WARNING_POP NSPoint windowPoint = [theEvent locationInWindow]; int windowScreenY = [window frame].origin.y + [window frame].size.height; - int viewScreenY = [window convertBaseToScreen:[self convertPoint:[self frame].origin toView:nil]].y; + NSPoint windowCoord = [self convertPoint:[self frame].origin toView:nil]; + int viewScreenY = [window convertRectToScreen:NSMakeRect(windowCoord.x, windowCoord.y, 0, 0)].origin.y; int titleBarHeight = windowScreenY - viewScreenY; NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil]; QPoint qtWindowPoint = QPoint(nsViewPoint.x, titleBarHeight + nsViewPoint.y); - NSPoint screenPoint = [window convertBaseToScreen:windowPoint]; + NSPoint screenPoint = [window convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 0, 0)].origin; QPoint qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y)); ulong timestamp = [theEvent timestamp] * 1000; @@ -1976,7 +1977,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin QPoint qtWindowPoint(windowPoint.x, windowPoint.y); NSWindow *window = [self window]; - NSPoint screenPoint = [window convertBaseToScreen :point]; + NSPoint screenPoint = [window convertRectToScreen:NSMakeRect(point.x, point.y, 0, 0)].origin; QPoint qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y)); QWindowSystemInterface::handleMouseEvent(target, mapWindowCoordinates(m_window, target, qtWindowPoint), qtScreenPoint, m_buttons); From e2405dd63fae0eb6c3b6feb0d2979ab4bf1a64d2 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 20 Mar 2015 10:36:16 +0100 Subject: [PATCH 05/52] QStateMachine: replaced Q_FOREACH with foreach. Change-Id: I2bd0f9d7ef1d6f236e2afa9fc5b75c5a6f61a250 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qstatemachine.cpp | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index eec3febbfe..dd0ba9260e 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -198,7 +198,7 @@ static inline bool isDescendant(const QAbstractState *state1, const QAbstractSta static bool containsDecendantOf(const QSet &states, const QAbstractState *node) { - Q_FOREACH (QAbstractState *s, states) + foreach (QAbstractState *s, states) if (isDescendant(s, node)) return true; @@ -490,11 +490,11 @@ void QStateMachinePrivate::removeConflictingTransitions(QList transitionsToRemove; QSet exitSetT1 = computeExitSet_Unordered(QList() << t1); - Q_FOREACH (QAbstractTransition *t2, filteredTransitions) { + foreach (QAbstractTransition *t2, filteredTransitions) { QSet exitSetT2 = computeExitSet_Unordered(QList() << t2); if (!exitSetT1.intersect(exitSetT2).isEmpty()) { if (isDescendant(t1->sourceState(), t2->sourceState())) { @@ -506,7 +506,7 @@ void QStateMachinePrivate::removeConflictingTransitions(QList QStateMachinePrivate::computeExitSet_Unordered(const QList Q_ASSERT(domain != 0); } - Q_FOREACH (QAbstractState* s, configuration) { + foreach (QAbstractState* s, configuration) { if (isDescendant(s, domain)) statesToExit.insert(s); } @@ -685,14 +685,14 @@ QList QStateMachinePrivate::computeEntrySet(const QList statesToEnter; if (pendingErrorStates.isEmpty()) { - Q_FOREACH (QAbstractTransition *t, enabledTransitions) { - Q_FOREACH (QAbstractState *s, t->targetStates()) { + foreach (QAbstractTransition *t, enabledTransitions) { + foreach (QAbstractState *s, t->targetStates()) { addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry); } QList effectiveTargetStates = getEffectiveTargetStates(t).toList(); QAbstractState *ancestor = getTransitionDomain(t, effectiveTargetStates); - Q_FOREACH (QAbstractState *s, effectiveTargetStates) { + foreach (QAbstractState *s, effectiveTargetStates) { addAncestorStatesToEnter(s, ancestor, statesToEnter, statesForDefaultEntry); } } @@ -738,7 +738,7 @@ QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t if (QState *tSource = t->sourceState()) { if (isCompound(tSource)) { bool allDescendants = true; - Q_FOREACH (QAbstractState *s, effectiveTargetStates) { + foreach (QAbstractState *s, effectiveTargetStates) { if (!isDescendant(s, tSource)) { allDescendants = false; break; @@ -970,9 +970,9 @@ void QStateMachinePrivate::addDescendantStatesToEnter(QAbstractState *state, if (QHistoryState *h = toHistoryState(state)) { QList historyConfiguration = QHistoryStatePrivate::get(h)->configuration; if (!historyConfiguration.isEmpty()) { - Q_FOREACH (QAbstractState *s, historyConfiguration) + foreach (QAbstractState *s, historyConfiguration) addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry); - Q_FOREACH (QAbstractState *s, historyConfiguration) + foreach (QAbstractState *s, historyConfiguration) addAncestorStatesToEnter(s, state->parentState(), statesToEnter, statesForDefaultEntry); #ifdef QSTATEMACHINE_DEBUG @@ -988,9 +988,9 @@ void QStateMachinePrivate::addDescendantStatesToEnter(QAbstractState *state, if (defaultHistoryContent.isEmpty()) { setError(QStateMachine::NoDefaultStateInHistoryStateError, h); } else { - Q_FOREACH (QAbstractState *s, defaultHistoryContent) + foreach (QAbstractState *s, defaultHistoryContent) addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry); - Q_FOREACH (QAbstractState *s, defaultHistoryContent) + foreach (QAbstractState *s, defaultHistoryContent) addAncestorStatesToEnter(s, state->parentState(), statesToEnter, statesForDefaultEntry); #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": initial history targets for" << state << ':' << defaultHistoryContent; @@ -1021,7 +1021,7 @@ void QStateMachinePrivate::addDescendantStatesToEnter(QAbstractState *state, } } else if (isParallel(state)) { QState *grp = toStandardState(state); - Q_FOREACH (QAbstractState *child, QStatePrivate::get(grp)->childStates()) { + foreach (QAbstractState *child, QStatePrivate::get(grp)->childStates()) { if (!containsDecendantOf(statesToEnter, child)) addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry); } @@ -1044,12 +1044,12 @@ void QStateMachinePrivate::addAncestorStatesToEnter(QAbstractState *s, QAbstract QSet &statesToEnter, QSet &statesForDefaultEntry) { - Q_FOREACH (QState *anc, getProperAncestors(s, ancestor)) { + foreach (QState *anc, getProperAncestors(s, ancestor)) { if (!anc->parentState()) continue; statesToEnter.insert(anc); if (isParallel(anc)) { - Q_FOREACH (QAbstractState *child, QStatePrivate::get(anc)->childStates()) { + foreach (QAbstractState *child, QStatePrivate::get(anc)->childStates()) { if (!containsDecendantOf(statesToEnter, child)) addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry); } From 9ff550807db324c2c14ba3ffdc69c5703deeb610 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 20 Mar 2015 11:12:43 +0100 Subject: [PATCH 06/52] Remove unused private field from test. Change-Id: I6f991f35a035ed9ff28ff8548b647916db85db39 Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Kevin Funk --- tests/auto/corelib/statemachine/qstate/tst_qstate.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/auto/corelib/statemachine/qstate/tst_qstate.cpp b/tests/auto/corelib/statemachine/qstate/tst_qstate.cpp index 1e885ddf92..ac3374b6a3 100644 --- a/tests/auto/corelib/statemachine/qstate/tst_qstate.cpp +++ b/tests/auto/corelib/statemachine/qstate/tst_qstate.cpp @@ -41,24 +41,14 @@ class tst_QState : public QObject { Q_OBJECT -public: - tst_QState(); - private slots: void assignProperty(); void assignPropertyTwice(); void historyInitialState(); void transitions(); void privateSignals(); - -private: - bool functionCalled; }; -tst_QState::tst_QState() : functionCalled(false) -{ -} - class TestClass: public QObject { Q_OBJECT From e0c83fb658bb352974f5485dd09df2de02ae8d92 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 20 Apr 2015 18:02:56 +0200 Subject: [PATCH 07/52] qsystemdetection.h: Check existence of define WINAPI_FAMILY_PHONE_APP. It is missing in MinGW and causes warnings like: src/corelib/global/qsystemdetection.h:109:24: error: "WINAPI_FAMILY_PHONE_APP" is not defined [-Werror=undef] in QtScript and headersclean failures in Active Qt. Task-number: QTBUG-45666 Change-Id: I167d9d5b33faddfbbcf44bdcce5e86fb43614fa9 Reviewed-by: Thiago Macieira --- src/corelib/global/qsystemdetection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index eb9c4ff04f..64f9d91ec7 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -106,7 +106,7 @@ # if defined(WINCE) || defined(_WIN32_WCE) # define Q_OS_WINCE # elif defined(WINAPI_FAMILY) -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP +# if defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP # define Q_OS_WINPHONE # define Q_OS_WINRT # elif WINAPI_FAMILY==WINAPI_FAMILY_APP From e1350c56c14a5948830203023ed5d4d4221a0f87 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 17 Apr 2015 11:59:53 +0200 Subject: [PATCH 08/52] fixqt4headers.pl: Improve detection of Qt 5 location. Obtain the location of the include files by querying the qmake variable QT_INSTALL_HEADERS by default, which can be overridden by the command line option. Task-number: QTBUG-45662 Change-Id: I03a781e9b98f5e2980dbaef86eedd05aec0103ce Reviewed-by: Oswald Buddenhagen --- bin/fixqt4headers.pl | 49 +++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/bin/fixqt4headers.pl b/bin/fixqt4headers.pl index b08deb0ba2..59daecae86 100755 --- a/bin/fixqt4headers.pl +++ b/bin/fixqt4headers.pl @@ -47,7 +47,8 @@ my $stripModule = 0; my $fixedFileCount = 0; my $fileCount = 0; my $verbose = 0; -my $qtdir = $ENV{'QTDIR'}; +my $qtdir; +my $qtIncludeDir; my $USAGE=< Date: Mon, 20 Apr 2015 16:03:34 +0200 Subject: [PATCH 09/52] Improve tst_uic. - Make the version regexp a member variable, avoiding repeated construction. - Use QVERIFY2() with error message for opening files. - On failure, try to locate the standard diff tool and produce diff output for comparison, which should make for example copyright header changes much easier. Task-number: QTBUG-44406 Change-Id: Ic759899c1da3394e3eb0cee7b1c722f0945714d3 Reviewed-by: Marc Mutz --- tests/auto/tools/uic/tst_uic.cpp | 102 +++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 32 deletions(-) diff --git a/tests/auto/tools/uic/tst_uic.cpp b/tests/auto/tools/uic/tst_uic.cpp index 1d1e327641..eac80bed7a 100644 --- a/tests/auto/tools/uic/tst_uic.cpp +++ b/tests/auto/tools/uic/tst_uic.cpp @@ -39,6 +39,7 @@ #include #include #include +#include class tst_uic : public QObject { @@ -67,10 +68,12 @@ private: const QString m_command; QString m_baseline; QTemporaryDir m_generated; + QRegExp m_versionRegexp; }; tst_uic::tst_uic() : m_command(QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/uic")) + , m_versionRegexp(QLatin1String("Created by: Qt User Interface Compiler version [.\\d]{5,5}")) { } @@ -83,6 +86,7 @@ static QByteArray msgProcessStartFailed(const QString &command, const QString &w void tst_uic::initTestCase() { + QVERIFY(m_versionRegexp.isValid()); m_baseline = QFINDTESTDATA("baseline"); QVERIFY2(!m_baseline.isEmpty(), "Could not find 'baseline'."); QProcess process; @@ -171,6 +175,37 @@ void tst_uic::run_data() const } } +// Helpers to generate a diff using the standard diff tool if present for failures. +static inline QString diffBinary() +{ + QString binary = QLatin1String("diff"); +#ifdef Q_OS_WIN + binary += QLatin1String(".exe"); +#endif + return QStandardPaths::findExecutable(binary); +} + +static QString generateDiff(const QString &originalFile, const QString &generatedFile) +{ + static const QString diff = diffBinary(); + if (diff.isEmpty()) + return QString(); + const QStringList args = QStringList() << QLatin1String("-u") + << QDir::toNativeSeparators(originalFile) + << QDir::toNativeSeparators(generatedFile); + QProcess diffProcess; + diffProcess.start(diff, args); + return diffProcess.waitForStarted() && diffProcess.waitForFinished() + ? QString::fromLocal8Bit(diffProcess.readAllStandardOutput()) : QString(); +} + +static QByteArray msgCannotReadFile(const QFile &file) +{ + const QString result = QLatin1String("Could not read file: ") + + QDir::toNativeSeparators(file.fileName()) + + QLatin1String(": ") + file.errorString(); + return result.toLocal8Bit(); +} void tst_uic::compare() { @@ -180,23 +215,23 @@ void tst_uic::compare() QFile orgFile(originalFile); QFile genFile(generatedFile); - if (!orgFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - QString err(QLatin1String("Could not read file: %1...")); - QFAIL(err.arg(orgFile.fileName()).toUtf8()); + QVERIFY2(orgFile.open(QIODevice::ReadOnly | QIODevice::Text), msgCannotReadFile(orgFile)); + + QVERIFY2(genFile.open(QIODevice::ReadOnly | QIODevice::Text), msgCannotReadFile(genFile)); + + QString originalFileContents = orgFile.readAll(); + originalFileContents.replace(m_versionRegexp, QString()); + + QString generatedFileContents = genFile.readAll(); + generatedFileContents.replace(m_versionRegexp, QString()); + + if (generatedFileContents != originalFileContents) { + const QString diff = generateDiff(originalFile, generatedFile); + if (!diff.isEmpty()) + qWarning().noquote().nospace() << "Difference:\n" << diff; } - if (!genFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - QString err(QLatin1String("Could not read file: %1...")); - QFAIL(err.arg(genFile.fileName()).toUtf8()); - } - - originalFile = orgFile.readAll(); - originalFile.replace(QRegExp(QLatin1String("Created by: Qt User Interface Compiler version [.\\d]{5,5}")), ""); - - generatedFile = genFile.readAll(); - generatedFile.replace(QRegExp(QLatin1String("Created by: Qt User Interface Compiler version [.\\d]{5,5}")), ""); - - QCOMPARE(generatedFile, originalFile); + QCOMPARE(generatedFileContents, originalFileContents); } void tst_uic::compare_data() const @@ -240,28 +275,31 @@ void tst_uic::runTranslation() void tst_uic::runCompare() { - QFile orgFile(m_baseline + QLatin1String("/translation/Dialog_without_Buttons_tr.h")); + const QString dialogFile = QLatin1String("/translation/Dialog_without_Buttons_tr.h"); + const QString originalFile = m_baseline + dialogFile; + QFile orgFile(originalFile); QDir generated(m_generated.path()); - QFile genFile(generated.absolutePath() + QLatin1String("/translation/Dialog_without_Buttons_tr.h")); + const QString generatedFile = generated.absolutePath() + dialogFile; + QFile genFile(generatedFile); - if (!orgFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - QString err(QLatin1String("Could not read file: %1...")); - QFAIL(err.arg(orgFile.fileName()).toUtf8()); + QVERIFY2(orgFile.open(QIODevice::ReadOnly | QIODevice::Text), msgCannotReadFile(orgFile)); + + QVERIFY2(genFile.open(QIODevice::ReadOnly | QIODevice::Text), msgCannotReadFile(genFile)); + + QString originalFileContents = orgFile.readAll(); + originalFileContents.replace(m_versionRegexp, QString()); + + QString generatedFileContents = genFile.readAll(); + generatedFileContents.replace(m_versionRegexp, QString()); + + if (generatedFileContents != originalFileContents) { + const QString diff = generateDiff(originalFile, generatedFile); + if (!diff.isEmpty()) + qWarning().noquote().nospace() << "Difference:\n" << diff; } - if (!genFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - QString err(QLatin1String("Could not read file: %1...")); - QFAIL(err.arg(genFile.fileName()).toUtf8()); - } - - QString originalFile = orgFile.readAll(); - originalFile.replace(QRegExp(QLatin1String("Created by: Qt User Interface Compiler version [.\\d]{5,5}")), ""); - - QString generatedFile = genFile.readAll(); - generatedFile.replace(QRegExp(QLatin1String("Created by: Qt User Interface Compiler version [.\\d]{5,5}")), ""); - - QCOMPARE(generatedFile, originalFile); + QCOMPARE(generatedFileContents, originalFileContents); } QTEST_MAIN(tst_uic) From 5a3a59b1c157049a7871b09abf474b75a76eb4d5 Mon Sep 17 00:00:00 2001 From: Caroline Chao Date: Mon, 13 Apr 2015 15:54:18 +0200 Subject: [PATCH 10/52] Tests: Blacklist tst_QGraphicItem::ensureUpdateOnTextItem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On OS X 10.10. This test is currently failing in CI. Change-Id: I1b3a33b404c915e83c5e4fa0a7af69d1b941d93c Task-number: QTBUG-41342 Reviewed-by: Morten Johan Sørvig --- tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST index edaa450731..56f643162b 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST @@ -1,2 +1,4 @@ [sorting] osx +[ensureUpdateOnTextItem] +osx-10.10 From 6535912add3444544c9403e5ecb2b8910ec6e2f5 Mon Sep 17 00:00:00 2001 From: Caroline Chao Date: Tue, 21 Apr 2015 12:33:25 +0200 Subject: [PATCH 11/52] Tests: Remove tst_QGraphicsIten::sorting from the BLACKLIST file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test tst_QGraphicsIten::sorting is blacklisted but always passing. Change-Id: I69bbd4b4bbe227267e16ab5558ddabe7d2c0b1b3 Task-number: QTBUG-41342 Reviewed-by: Morten Johan Sørvig --- tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST index 56f643162b..abfa7a3329 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST @@ -1,4 +1,2 @@ -[sorting] -osx [ensureUpdateOnTextItem] osx-10.10 From 63d5a42b59149bfdebc9a5a123e7115a813bcaa4 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 22 Apr 2015 19:22:26 +0000 Subject: [PATCH 12/52] Revert "Remove separate SSE4 unpremultiply function" Could causedSSE4 instructions to be used on non SSE4 machines in cases when qUnpremultiplywas not inlined. This reverts commit 964ccc58534aac436529007000d1c38d76c88834. Change-Id: Ic676ade8f75129e8d37c4d96cbfb2bdb5b794919 Task-number: QTBUG-45741 Reviewed-by: Thiago Macieira --- src/gui/image/qimage_conversions.cpp | 6 +-- src/gui/image/qimage_sse4.cpp | 3 +- src/gui/painting/qdrawhelper.cpp | 10 +++-- src/gui/painting/qdrawhelper_sse4.cpp | 7 ++-- src/gui/painting/qdrawingprimitive_sse2_p.h | 21 +++++++++++ src/gui/painting/qrgb.h | 37 ++----------------- tests/auto/gui/painting/qcolor/tst_qcolor.cpp | 19 ++++++++++ 7 files changed, 58 insertions(+), 45 deletions(-) diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 8cb886e09b..28e3a48689 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -117,7 +117,7 @@ static const uint *QT_FASTCALL convertRGB32ToARGB32PM(uint *buffer, const uint * return buffer; } -#if defined(QT_COMPILER_SUPPORTS_SSE4_1) && !defined(__SSE4_1__) +#ifdef QT_COMPILER_SUPPORTS_SSE4_1 extern const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); #endif @@ -144,7 +144,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio if (src->format == QImage::Format_RGB32) convertToARGB32PM = convertRGB32ToARGB32PM; if (dest->format == QImage::Format_RGB32) { -#if defined(QT_COMPILER_SUPPORTS_SSE4_1) && !defined(__SSE4_1__) +#ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) convertFromARGB32PM = convertRGB32FromARGB32PM_sse4; else @@ -193,7 +193,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im if (data->format == QImage::Format_RGB32) convertToARGB32PM = convertRGB32ToARGB32PM; if (dst_format == QImage::Format_RGB32) { -#if defined(QT_COMPILER_SUPPORTS_SSE4_1) && !defined(__SSE4_1__) +#ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) convertFromARGB32PM = convertRGB32FromARGB32PM_sse4; else diff --git a/src/gui/image/qimage_sse4.cpp b/src/gui/image/qimage_sse4.cpp index fb63f5bff9..5fad4f572a 100644 --- a/src/gui/image/qimage_sse4.cpp +++ b/src/gui/image/qimage_sse4.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -44,7 +45,7 @@ const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint * const QPixelLayout *, const QRgb *) { for (int i = 0; i < count; ++i) - buffer[i] = 0xff000000 | qUnpremultiply(src[i]); + buffer[i] = 0xff000000 | qUnpremultiply_sse4(src[i]); return buffer; } diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 2817a4a145..37f2de98b6 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -6704,22 +6704,24 @@ void qInitDrawhelperAsm() } #endif // SSSE3 -#if defined(QT_COMPILER_SUPPORTS_SSE4_1) && !defined(__SSE4_1__) +#if QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) { +#if !defined(__SSE4_1__) extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); extern const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); + qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_sse4; + qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_sse4; +#endif extern const uint *QT_FASTCALL convertARGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); extern const uint *QT_FASTCALL convertRGBA8888FromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); extern const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); - qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_sse4; - qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_sse4; qPixelLayouts[QImage::Format_ARGB32].convertFromARGB32PM = convertARGB32FromARGB32PM_sse4; qPixelLayouts[QImage::Format_RGBA8888].convertFromARGB32PM = convertRGBA8888FromARGB32PM_sse4; qPixelLayouts[QImage::Format_RGBX8888].convertFromARGB32PM = convertRGBXFromARGB32PM_sse4; } #endif -#if defined(QT_COMPILER_SUPPORTS_AVX2) && !defined(__AVX2__) +#if QT_COMPILER_SUPPORTS_AVX2 && !defined(__AVX2__) if (qCpuHasFeature(AVX2)) { extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); extern const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); diff --git a/src/gui/painting/qdrawhelper_sse4.cpp b/src/gui/painting/qdrawhelper_sse4.cpp index 8e0b2cbb18..43a3958997 100644 --- a/src/gui/painting/qdrawhelper_sse4.cpp +++ b/src/gui/painting/qdrawhelper_sse4.cpp @@ -32,6 +32,7 @@ ****************************************************************************/ #include +#include #if defined(QT_COMPILER_SUPPORTS_SSE4_1) @@ -53,7 +54,7 @@ const uint *QT_FASTCALL convertARGB32FromARGB32PM_sse4(uint *buffer, const uint const QPixelLayout *, const QRgb *) { for (int i = 0; i < count; ++i) - buffer[i] = qUnpremultiply(src[i]); + buffer[i] = qUnpremultiply_sse4(src[i]); return buffer; } @@ -61,7 +62,7 @@ const uint *QT_FASTCALL convertRGBA8888FromARGB32PM_sse4(uint *buffer, const uin const QPixelLayout *, const QRgb *) { for (int i = 0; i < count; ++i) - buffer[i] = ARGB2RGBA(qUnpremultiply(src[i])); + buffer[i] = ARGB2RGBA(qUnpremultiply_sse4(src[i])); return buffer; } @@ -69,7 +70,7 @@ const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *s const QPixelLayout *, const QRgb *) { for (int i = 0; i < count; ++i) - buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply(src[i])); + buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply_sse4(src[i])); return buffer; } diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h index fbee06e157..4d0790a502 100644 --- a/src/gui/painting/qdrawingprimitive_sse2_p.h +++ b/src/gui/painting/qdrawingprimitive_sse2_p.h @@ -236,4 +236,25 @@ QT_END_NAMESPACE #endif // __SSE2__ +QT_BEGIN_NAMESPACE +#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) +QT_FUNCTION_TARGET(SSE4_1) +inline QRgb qUnpremultiply_sse4(QRgb p) +{ + const uint alpha = qAlpha(p); + const uint invAlpha = qt_inv_premul_factor[alpha]; + const __m128i via = _mm_set1_epi32(invAlpha); + const __m128i vr = _mm_set1_epi32(0x8000); + __m128i vl = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(p)); + vl = _mm_mullo_epi32(vl, via); + vl = _mm_add_epi32(vl, vr); + vl = _mm_srai_epi32(vl, 16); + vl = _mm_insert_epi32(vl, alpha, 3); + vl = _mm_packus_epi32(vl, _mm_setzero_si128()); + vl = _mm_packus_epi16(vl, _mm_setzero_si128()); + return _mm_cvtsi128_si32(vl); +} +#endif +QT_END_NAMESPACE + #endif // QDRAWINGPRIMITIVE_SSE2_P_H diff --git a/src/gui/painting/qrgb.h b/src/gui/painting/qrgb.h index 05b3a76bce..f7f2185bef 100644 --- a/src/gui/painting/qrgb.h +++ b/src/gui/painting/qrgb.h @@ -36,11 +36,6 @@ #include #include -#if defined(__SSE4_1__) -#include -#elif defined(__SSE2__) -#include -#endif QT_BEGIN_NAMESPACE @@ -92,45 +87,19 @@ inline Q_DECL_RELAXED_CONSTEXPR QRgb qPremultiply(QRgb x) Q_GUI_EXPORT extern const uint qt_inv_premul_factor[]; -#if defined(__SSE2__) -inline QRgb qUnpremultiply(QRgb p) -{ - const uint alpha = qAlpha(p); - if (alpha == 255 || alpha == 0) - return p; - const uint invAlpha = qt_inv_premul_factor[alpha]; - const __m128i via = _mm_set1_epi32(invAlpha); - const __m128i vr = _mm_set1_epi32(0x8000); -#ifdef __SSE4_1__ - __m128i vl = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(p)); - vl = _mm_mullo_epi32(vl, via); -#else - __m128i vl = _mm_unpacklo_epi8(_mm_cvtsi32_si128(p), _mm_setzero_si128()); - vl = _mm_unpacklo_epi16(vl, vl); - __m128i vll = _mm_mullo_epi16(vl, via); - __m128i vlh = _mm_mulhi_epu16(vl, via); - vl = _mm_add_epi32(vll, _mm_slli_epi32(vlh, 16)); -#endif - vl = _mm_add_epi32(vl, vr); - vl = _mm_srli_epi32(vl, 16); - vl = _mm_packs_epi32(vl, _mm_setzero_si128()); - vl = _mm_insert_epi16(vl, alpha, 3); - vl = _mm_packus_epi16(vl, _mm_setzero_si128()); - return _mm_cvtsi128_si32(vl); -} -#else inline QRgb qUnpremultiply(QRgb p) { const uint alpha = qAlpha(p); // Alpha 255 and 0 are the two most common values, which makes them beneficial to short-cut. - if (alpha == 255 || alpha == 0) + if (alpha == 255) return p; + if (alpha == 0) + return 0; // (p*(0x00ff00ff/alpha)) >> 16 == (p*255)/alpha for all p and alpha <= 256. const uint invAlpha = qt_inv_premul_factor[alpha]; // We add 0x8000 to get even rounding. The rounding also ensures that qPremultiply(qUnpremultiply(p)) == p for all p. return qRgba((qRed(p)*invAlpha + 0x8000)>>16, (qGreen(p)*invAlpha + 0x8000)>>16, (qBlue(p)*invAlpha + 0x8000)>>16, alpha); } -#endif QT_END_NAMESPACE diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp index c34b1639cc..4fafbf9827 100644 --- a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp +++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp @@ -38,6 +38,7 @@ #include #include +#include class tst_QColor : public QObject { @@ -103,6 +104,7 @@ private slots: void achromaticHslHue(); void premultiply(); + void unpremultiply_sse4(); #ifdef Q_DEAD_CODE_FROM_QT4_X11 void setallowX11ColorNames(); @@ -1445,5 +1447,22 @@ void tst_QColor::premultiply() } } +void tst_QColor::unpremultiply_sse4() +{ + // Tests that qUnpremultiply_sse4 returns the same as qUnpremultiply. +#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) + if (qCpuHasFeature(SSE4_1)) { + for (uint a = 0; a < 256; a++) { + for (uint c = 0; c <= a; c++) { + QRgb p = qRgba(c, a-c, c, a); + QCOMPARE(qUnpremultiply(p), qUnpremultiply_sse4(p)); + } + } + return; + } +#endif + QSKIP("SSE4 not supported on this CPU."); +} + QTEST_MAIN(tst_QColor) #include "tst_qcolor.moc" From 32341e8ef85f593358db47b3ea58875708f24cda Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 22 Apr 2015 16:16:32 +0200 Subject: [PATCH 13/52] Fix FPE in QApplicationPrivate::dispatchEnterLeave() due to invalid cursor position. QGuiApplicationPrivate::lastCursorPosition is initialized to qInf(), qIn(). Under some circumstances, this is passed to dispatchEnterLeave() which causes an FPE in QPointF::toPoint(). Move the invocation of QPointF::toPoint() to the if-branch handling the enter list, which already fixes the FPE. To be extra sure, clamp to QWIDGETSIZE_MAX. Task-number: QTBUG-45501 Change-Id: I2d1407415e6360196730d23ee319d1ee6981d1f5 Reviewed-by: Marc Mutz --- src/widgets/kernel/qapplication.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index ed10beddd4..dd7474b930 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -2312,7 +2312,6 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool */ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF) { - const QPoint globalPos = globalPosF.toPoint(); #if 0 if (leave) { QEvent e(QEvent::Leave); @@ -2399,6 +2398,10 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con } } if (!enterList.isEmpty()) { + // Guard against QGuiApplicationPrivate::lastCursorPosition initialized to qInf(), qInf(). + const QPoint globalPos = qIsInf(globalPosF.x()) + ? QPoint(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX) + : globalPosF.toPoint(); const QPoint windowPos = enterList.front()->window()->mapFromGlobal(globalPos); for (int i = 0; i < enterList.size(); ++i) { w = enterList.at(i); From 3c1cb24fe4c0cde0cfe4b18f13fea4966ace8a41 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 21 Apr 2015 15:43:29 +0200 Subject: [PATCH 14/52] fix extra compilers with indirect outputs in VS projects Evaluate the .output variable of the extra compiler to determine the file extension of its output. The VS project generator needs it to determine the filter that will contain the output file. Change-Id: Iab1e154a712342401e17421c08975fad13967a5b Task-number: QTBUG-45717 Reviewed-by: Oswald Buddenhagen --- qmake/generators/win32/msvc_vcproj.cpp | 21 +++++++++++++++++++-- qmake/generators/win32/msvc_vcproj.h | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 0d78766606..1fa117afda 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -421,6 +421,24 @@ bool VcprojGenerator::isStandardSuffix(const QString &suffix) const return false; } +ProString VcprojGenerator::firstInputFileName(const ProString &extraCompilerName) const +{ + foreach (const ProString &var, project->values(ProKey(extraCompilerName + ".input"))) { + const ProStringList &files = project->values(var.toKey()); + if (!files.isEmpty()) + return files.first(); + } + return ProString(); +} + +QString VcprojGenerator::firstExpandedOutputFileName(const ProString &extraCompilerName) +{ + const ProString firstOutput = project->first(ProKey(extraCompilerName + ".output")); + return replaceExtraCompilerVariables(firstOutput.toQString(), + firstInputFileName(extraCompilerName).toQString(), + QString(), NoShell); +} + ProStringList VcprojGenerator::collectDependencies(QMakeProject *proj, QHash &projLookup, QHash &projGuids, QHash &extraSubdirs, @@ -1642,10 +1660,9 @@ void VcprojGenerator::initExtraCompilerOutputs() extraCompile.Filter = ""; extraCompile.Guid = QString(_GUIDExtraCompilerFiles) + "-" + (*it); - // If the extra compiler has a variable_out set the output file // is added to an other file list, and does not need its own.. - bool addOnInput = hasBuiltinCompiler(project->first(ProKey(*it + ".output")).toQString()); + bool addOnInput = hasBuiltinCompiler(firstExpandedOutputFileName(*it)); const ProString &tmp_other_out = project->first(ProKey(*it + ".variable_out")); if (!tmp_other_out.isEmpty() && !addOnInput) continue; diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h index 3396ea4986..3f99e02e92 100644 --- a/qmake/generators/win32/msvc_vcproj.h +++ b/qmake/generators/win32/msvc_vcproj.h @@ -135,6 +135,8 @@ private: QUuid increaseUUID(const QUuid &id); QString retrievePlatformToolSet() const; bool isStandardSuffix(const QString &suffix) const; + ProString firstInputFileName(const ProString &extraCompilerName) const; + QString firstExpandedOutputFileName(const ProString &extraCompilerName); friend class VCFilter; }; From 9e410d9cd4f7d5aba5445f15b1f384214765578c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 22 Apr 2015 20:11:24 +0200 Subject: [PATCH 15/52] cmake: Don't populate legacy variables for header-only modules. As these are a new type, there is no legacy code to support. Change-Id: Ie5abd353563d68d0449a07e06065f34db805f710 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in index 70b9ed941a..0befa803a5 100644 --- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in +++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in @@ -33,10 +33,12 @@ get_filename_component(_qt5$${CMAKE_MODULE_NAME}_install_prefix \"${CMAKE_CURREN set(_qt5$${CMAKE_MODULE_NAME}_install_prefix \"$$[QT_INSTALL_PREFIX]\") !!ENDIF +!!IF !equals(TEMPLATE, aux) # For backwards compatibility only. Use Qt5$${CMAKE_MODULE_NAME}_VERSION instead. set(Qt5$${CMAKE_MODULE_NAME}_VERSION_STRING "$$eval(QT.$${MODULE}.MAJOR_VERSION).$$eval(QT.$${MODULE}.MINOR_VERSION).$$eval(QT.$${MODULE}.PATCH_VERSION)") set(Qt5$${CMAKE_MODULE_NAME}_LIBRARIES Qt5::$${CMAKE_MODULE_NAME}) +!!ENDIF // TEMPLATE != aux macro(_qt5_$${CMAKE_MODULE_NAME}_check_file_exists file) if(NOT EXISTS \"${file}\" ) From c4d82dbfc0400113fdae391ae46fa4c383d8ffe9 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 22 Apr 2015 19:37:48 +0200 Subject: [PATCH 16/52] make diff between aux and app TEMPLATEs smaller people may use extra compilers which refer to CXXFLAGS & co., so set them up "as normal". Change-Id: I858ca63370a7aed66e04f5417da078b896feefc4 Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake2.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index d873e91170..3c3189317e 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -1160,10 +1160,9 @@ void UnixMakefileGenerator::init2() if(project->isEmpty("QMAKE_FRAMEWORK_VERSION")) project->values("QMAKE_FRAMEWORK_VERSION").append(project->first("VER_MAJ")); - if (project->first("TEMPLATE") == "aux") - return; - - if (!project->values("QMAKE_APP_FLAG").isEmpty()) { + if (project->first("TEMPLATE") == "aux") { + // nothing + } else if (!project->values("QMAKE_APP_FLAG").isEmpty()) { if(!project->isEmpty("QMAKE_BUNDLE")) { ProString bundle_loc = project->first("QMAKE_BUNDLE_LOCATION"); if(!bundle_loc.isEmpty() && !bundle_loc.startsWith("/")) @@ -1335,7 +1334,7 @@ void UnixMakefileGenerator::init2() project->values("QMAKE_LINK_SHLIB_CMD").append( "$(LINK) $(LFLAGS) " + project->first("QMAKE_LINK_O_FLAG") + "$(TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP)"); } - if (!project->values("QMAKE_APP_FLAG").isEmpty()) { + if (!project->values("QMAKE_APP_FLAG").isEmpty() || project->first("TEMPLATE") == "aux") { project->values("QMAKE_CFLAGS") += project->values("QMAKE_CFLAGS_APP"); project->values("QMAKE_CXXFLAGS") += project->values("QMAKE_CXXFLAGS_APP"); project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_APP"); From 12ffa5853928c04cb8bcb487eafd3624d27a9b8b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 15 Apr 2015 13:59:39 +0200 Subject: [PATCH 17/52] don't overengineer DESTDIR calculation just like in qt_plugin.prf, the DESTDIR setting is actually fixed per module type. Change-Id: I5837b5884699f0d50e4067733af8aacbab93bc42 Reviewed-by: Stephen Kelly --- mkspecs/features/create_cmake.prf | 14 ++++++++------ mkspecs/features/qt_module.prf | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf index 395d6f247c..11fb52a0b1 100644 --- a/mkspecs/features/create_cmake.prf +++ b/mkspecs/features/create_cmake.prf @@ -24,6 +24,8 @@ 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_OUT_DIR = $$MODULE_BASE_OUTDIR/lib/cmake + CMAKE_MODULE_NAME = $$cmakeModuleName($${MODULE}) split_incpath { @@ -36,7 +38,7 @@ split_incpath { $$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION)/Qt$${CMAKE_MODULE_NAME}) cmake_extra_source_includes.input = $$PWD/data/cmake/ExtraSourceIncludes.cmake.in - cmake_extra_source_includes.output = $$DESTDIR/cmake/Qt5$${CMAKE_MODULE_NAME}/ExtraSourceIncludes.cmake + cmake_extra_source_includes.output = $$CMAKE_OUT_DIR/Qt5$${CMAKE_MODULE_NAME}/ExtraSourceIncludes.cmake !build_pass:QMAKE_SUBSTITUTES += \ cmake_extra_source_includes @@ -159,7 +161,7 @@ contains(CONFIG, plugin) { } } cmake_target_file.input = $$PWD/data/cmake/Qt5PluginTarget.cmake.in - cmake_target_file.output = $$DESTDIR/../../$${CMAKE_LIB_DIR}cmake/Qt5$${CMAKE_MODULE_NAME}/Qt5$${CMAKE_MODULE_NAME}_$${PLUGIN_CLASS_NAME}.cmake + cmake_target_file.output = $$CMAKE_OUT_DIR/Qt5$${CMAKE_MODULE_NAME}/Qt5$${CMAKE_MODULE_NAME}_$${PLUGIN_CLASS_NAME}.cmake !build_pass:QMAKE_SUBSTITUTES += \ cmake_target_file @@ -273,12 +275,12 @@ mac { INSTALLS += cmake_qt5_module_files cmake_config_file.input = $$PWD/data/cmake/Qt5BasicConfig.cmake.in -cmake_config_file.output = $$DESTDIR/cmake/Qt5$${CMAKE_MODULE_NAME}/Qt5$${CMAKE_MODULE_NAME}Config.cmake +cmake_config_file.output = $$CMAKE_OUT_DIR/Qt5$${CMAKE_MODULE_NAME}/Qt5$${CMAKE_MODULE_NAME}Config.cmake CMAKE_PACKAGE_VERSION = $$eval(QT.$${MODULE}.VERSION) cmake_config_version_file.input = $$PWD/data/cmake/Qt5ConfigVersion.cmake.in -cmake_config_version_file.output = $$DESTDIR/cmake/Qt5$${CMAKE_MODULE_NAME}/Qt5$${CMAKE_MODULE_NAME}ConfigVersion.cmake +cmake_config_version_file.output = $$CMAKE_OUT_DIR/Qt5$${CMAKE_MODULE_NAME}/Qt5$${CMAKE_MODULE_NAME}ConfigVersion.cmake !build_pass:QMAKE_SUBSTITUTES += \ cmake_config_file \ @@ -292,7 +294,7 @@ cmake_extras_file.input = $$_PRO_FILE_PWD_/Qt5$${CMAKE_MODULE_NAME}ConfigExtras. exists($$cmake_extras_file.input) { CMAKE_MODULE_EXTRAS = "true" - cmake_extras_file.output = $$DESTDIR/cmake/Qt5$${CMAKE_MODULE_NAME}/Qt5$${CMAKE_MODULE_NAME}ConfigExtras.cmake + cmake_extras_file.output = $$CMAKE_OUT_DIR/Qt5$${CMAKE_MODULE_NAME}/Qt5$${CMAKE_MODULE_NAME}ConfigExtras.cmake !build_pass:QMAKE_SUBSTITUTES += cmake_extras_file @@ -304,7 +306,7 @@ cmake_macros_file.input = $$_PRO_FILE_PWD_/Qt5$${CMAKE_MODULE_NAME}Macros.cmake exists($$cmake_macros_file.input) { CMAKE_MODULE_MACROS = "true" - cmake_macros_file.output = $$DESTDIR/cmake/Qt5$${CMAKE_MODULE_NAME}/Qt5$${CMAKE_MODULE_NAME}Macros.cmake + cmake_macros_file.output = $$CMAKE_OUT_DIR/Qt5$${CMAKE_MODULE_NAME}/Qt5$${CMAKE_MODULE_NAME}Macros.cmake cmake_macros_file.CONFIG = verbatim !build_pass:QMAKE_SUBSTITUTES += cmake_macros_file diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 7ed5ea0561..7c4d574874 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -62,8 +62,8 @@ load(qt_module_pris) #other TEMPLATE = lib -DESTDIR = $$eval(QT.$${MODULE_ID}.libs) -win32:!wince*:!prefix_build: DLLDESTDIR = $$eval(QT.$${MODULE_ID}.bins) +DESTDIR = $$MODULE_BASE_OUTDIR/lib +win32:!wince*:!prefix_build: DLLDESTDIR = $$MODULE_BASE_OUTDIR/bin CONFIG += qmake_cache target_qt From 5fb0b71a12e5eade128125f283c9457f25793742 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 22 Apr 2015 23:59:01 +0200 Subject: [PATCH 18/52] fix {ALL,CLEAN,DISTCLEAN}_DEPS writeout to makefile it helps enormously to put spaces between target names ... Task-number: QTBUG-45533 Change-Id: Ic41f8287c6c37761b1be3ad7c383b5c7fb714b12 Reviewed-by: Joerg Bornemann --- qmake/generators/makefile.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 5aaaf49334..70e7545526 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -2569,11 +2569,11 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList Date: Wed, 22 Apr 2015 23:44:20 +0200 Subject: [PATCH 19/52] untangle handling extra compiler .clean member, take 2 fixes clean targets of (most) extra compilers being empty. amends commit 0812b5b3188. Task-number: QTBUG-45132 Change-Id: I069bca124587df261597a4f8183a4695cd834e29 Reviewed-by: Joerg Bornemann --- qmake/generators/makefile.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 70e7545526..2904f01c5f 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -1850,7 +1850,9 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) t << endl; if (config.indexOf("no_clean") == -1) { - const ProStringList &raw_clean = project->values(ProKey(*it + ".clean")); + QStringList raw_clean = project->values(ProKey(*it + ".clean")).toQStringList(); + if (raw_clean.isEmpty()) + raw_clean << tmp_out; QString tmp_clean = escapeFilePaths(raw_clean).join(' '); QString tmp_clean_cmds = project->values(ProKey(*it + ".clean_commands")).join(' '); if(!tmp_inputs.isEmpty()) @@ -1863,14 +1865,11 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) t << "\n\t" << tmp_clean_cmds; wrote_clean_cmds = true; } - if(tmp_clean.isEmpty()) - tmp_clean = escapeFilePath(tmp_out); if(tmp_clean.indexOf("${QMAKE_") == -1) { t << "\n\t-$(DEL_FILE) " << tmp_clean; wrote_clean = true; } if(!wrote_clean_cmds || !wrote_clean) { - QStringList q_raw_clean = raw_clean.toQStringList(); QStringList cleans; const QString del_statement("-$(DEL_FILE)"); if(!wrote_clean) { @@ -1878,7 +1877,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) { QString tinp = (*input).toQString(); QString out = replaceExtraCompilerVariables(tmp_out, tinp, QString(), NoShell); - foreach (const QString &rc, q_raw_clean) { + foreach (const QString &rc, raw_clean) { dels << ' ' + escapeFilePath(Option::fixPathToTargetOS( replaceExtraCompilerVariables(rc, tinp, out, NoShell), false)); } From e8dc128d1d327bbd6168e4321a67c2b074ffa726 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 22 Apr 2015 23:49:22 +0200 Subject: [PATCH 20/52] don't fail to fix path separators in extra compilers' clean targets this affects only files explicitly listed via the .clean member without placeholders, so more or less a corner case. Change-Id: I7bd55948130aaee116d1a4bebbad0c445b76197b Reviewed-by: Joerg Bornemann --- qmake/generators/makefile.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 2904f01c5f..2106d0869b 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -1853,7 +1853,9 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) QStringList raw_clean = project->values(ProKey(*it + ".clean")).toQStringList(); if (raw_clean.isEmpty()) raw_clean << tmp_out; - QString tmp_clean = escapeFilePaths(raw_clean).join(' '); + QString tmp_clean; + foreach (const QString &rc, raw_clean) + tmp_clean += ' ' + escapeFilePath(Option::fixPathToTargetOS(rc)); QString tmp_clean_cmds = project->values(ProKey(*it + ".clean_commands")).join(' '); if(!tmp_inputs.isEmpty()) clean_targets += QString("compiler_" + (*it) + "_clean "); @@ -1866,7 +1868,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) wrote_clean_cmds = true; } if(tmp_clean.indexOf("${QMAKE_") == -1) { - t << "\n\t-$(DEL_FILE) " << tmp_clean; + t << "\n\t-$(DEL_FILE)" << tmp_clean; wrote_clean = true; } if(!wrote_clean_cmds || !wrote_clean) { From 319f3c89b15aa3978877df976aa2bd740082ff50 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 21 Apr 2015 15:00:13 +0200 Subject: [PATCH 21/52] Add debug operator for QPrinterInfo. Add formatting helper to private class QPrintDevice and use that to implement debug operators for QPrintDevice and QPrinterInfo. Sample output: (QPrinterInfo(id="HP_Color_LaserJet_CM6030_MFP", state=0, name="HP Color LaserJet CM6030 MFP", makeAndModel="HP Color LaserJet CM6030 MFP Postscript (recommended)", default, defaultPageSize=QPageSize("Letter", "Letter", 612x792pt, 2), supportsCustomPageSizes, physicalPageSize=(278, 396)..(907, 1296), defaultResolution=600, defaultDuplexMode=0, defaultColorMode=1, supportedMimeTypes=( "application/pdf" "application/postscript" "image/gif" "image/png" "image/jpeg" "image/tiff" "text/html" "text/plain"))) Task-number: QTBUG-44991 Change-Id: I187414d2f68871e38ace0bd66661d2e37712f662 Reviewed-by: Andy Shaw --- src/printsupport/kernel/qprintdevice.cpp | 55 ++++++++++++++++++++++++ src/printsupport/kernel/qprintdevice_p.h | 8 ++++ src/printsupport/kernel/qprinterinfo.cpp | 17 ++++++++ src/printsupport/kernel/qprinterinfo.h | 4 ++ 4 files changed, 84 insertions(+) diff --git a/src/printsupport/kernel/qprintdevice.cpp b/src/printsupport/kernel/qprintdevice.cpp index e645442be2..7c18b53e09 100644 --- a/src/printsupport/kernel/qprintdevice.cpp +++ b/src/printsupport/kernel/qprintdevice.cpp @@ -34,6 +34,8 @@ #include "qprintdevice_p.h" #include "qplatformprintdevice.h" +#include + QT_BEGIN_NAMESPACE #ifndef QT_NO_PRINTER @@ -244,6 +246,59 @@ QList QPrintDevice::supportedMimeTypes() const } #endif // QT_NO_MIMETYPE +# ifndef QT_NO_DEBUG_STREAM +void QPrintDevice::format(QDebug debug) const +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + if (isValid()) { + const QString deviceId = id(); + const QString deviceName = name(); + debug << "id=\"" << deviceId << "\", state=" << state(); + if (!deviceName.isEmpty() && deviceName != deviceId) + debug << ", name=\"" << deviceName << '"'; + if (!location().isEmpty()) + debug << ", location=\"" << location() << '"'; + debug << ", makeAndModel=\"" << makeAndModel() << '"'; + if (isDefault()) + debug << ", default"; + if (isRemote()) + debug << ", remote"; + debug << ", defaultPageSize=" << defaultPageSize(); + if (supportsCustomPageSizes()) + debug << ", supportsCustomPageSizes"; + debug << ", physicalPageSize=("; + QtDebugUtils::formatQSize(debug, minimumPhysicalPageSize()); + debug << ")..("; + QtDebugUtils::formatQSize(debug, maximumPhysicalPageSize()); + debug << "), defaultResolution=" << defaultResolution() + << ", defaultDuplexMode=" << defaultDuplexMode() + << ", defaultColorMode="<< defaultColorMode(); +# ifndef QT_NO_MIMETYPE + const QList mimeTypes = supportedMimeTypes(); + if (const int mimeTypeCount = mimeTypes.size()) { + debug << ", supportedMimeTypes=("; + for (int i = 0; i < mimeTypeCount; ++i) + debug << " \"" << mimeTypes.at(i).name() << '"'; + debug << ')'; + } +# endif // !QT_NO_MIMETYPE + } else { + debug << "null"; + } +} + +QDebug operator<<(QDebug debug, const QPrintDevice &p) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "QPrintDevice("; + p.format(debug); + debug << ')'; + return debug; +} +# endif // QT_NO_DEBUG_STREAM #endif // QT_NO_PRINTER QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qprintdevice_p.h b/src/printsupport/kernel/qprintdevice_p.h index 6117239ac7..ad55cded0e 100644 --- a/src/printsupport/kernel/qprintdevice_p.h +++ b/src/printsupport/kernel/qprintdevice_p.h @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE class QPlatformPrintDevice; class QMarginsF; class QMimeType; +class QDebug; class Q_PRINTSUPPORT_EXPORT QPrintDevice { @@ -127,6 +128,10 @@ public: QList supportedMimeTypes() const; #endif +# ifndef QT_NO_DEBUG_STREAM + void format(QDebug debug) const; +# endif + private: friend class QPlatformPrinterSupport; friend class QPlatformPrintDevice; @@ -136,6 +141,9 @@ private: Q_DECLARE_SHARED(QPrintDevice) +# ifndef QT_NO_DEBUG_STREAM +Q_PRINTSUPPORT_EXPORT QDebug operator<<(QDebug debug, const QPrintDevice &); +# endif #endif // QT_NO_PRINTER QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qprinterinfo.cpp b/src/printsupport/kernel/qprinterinfo.cpp index 33d67e3a55..ad488a10ed 100644 --- a/src/printsupport/kernel/qprinterinfo.cpp +++ b/src/printsupport/kernel/qprinterinfo.cpp @@ -31,6 +31,8 @@ #ifndef QT_NO_PRINTER +#include + #include #include @@ -469,6 +471,21 @@ QPrinterInfo QPrinterInfo::printerInfo(const QString &printerName) return QPrinterInfo(printerName); } +# ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QPrinterInfo &p) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "QPrinterInfo("; + if (p.isNull()) + debug << "null"; + else + p.d_ptr->m_printDevice.format(debug); + debug << ')'; + return debug; +} +# endif // !QT_NO_DEBUG_STREAM + QT_END_NAMESPACE #endif // QT_NO_PRINTER diff --git a/src/printsupport/kernel/qprinterinfo.h b/src/printsupport/kernel/qprinterinfo.h index f13dbc5cd6..39e44d4a0c 100644 --- a/src/printsupport/kernel/qprinterinfo.h +++ b/src/printsupport/kernel/qprinterinfo.h @@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_PRINTER class QPrinterInfoPrivate; class QPrinterInfoPrivateDeleter; +class QDebug; class Q_PRINTSUPPORT_EXPORT QPrinterInfo { public: @@ -98,6 +99,9 @@ private: private: friend class QPlatformPrinterSupport; +# ifndef QT_NO_DEBUG_STREAM + friend Q_PRINTSUPPORT_EXPORT QDebug operator<<(QDebug debug, const QPrinterInfo &); +# endif Q_DECLARE_PRIVATE(QPrinterInfo) QScopedPointer d_ptr; }; From 1f2ce78f16a3a8b5d182fbb9c03c373efaa136d8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 17 Apr 2015 15:29:20 +0200 Subject: [PATCH 22/52] tst_QFileSystemWatcher: Improve diagnostics. Add a special signal spy that records the time and path received to obtain information on what triggered it for the flaky cases where more than the expected signals were emitted. Task-number: QTBUG-30943 Change-Id: I67510ce5e8e19b49c0ca41457f8357b720cade76 Reviewed-by: Simon Hausmann --- .../tst_qfilesystemwatcher.cpp | 74 +++++++++++++++++-- 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp index 458dbc532d..0ebfd2ae35 100644 --- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp +++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp @@ -36,6 +36,9 @@ #include #include +#include +#include +#include /* All tests need to run in temporary directories not used * by the application to avoid non-deterministic failures on Windows @@ -387,6 +390,60 @@ void tst_QFileSystemWatcher::addPaths() QCOMPARE(watcher.addPaths(paths), QStringList()); } +// A signal spy that records the paths and times received for better diagnostics. +class FileSystemWatcherSpy : public QObject { + Q_OBJECT +public: + enum Mode { + SpyOnDirectoryChanged, + SpyOnFileChanged + }; + + explicit FileSystemWatcherSpy(QFileSystemWatcher *watcher, Mode mode) + { + connect(watcher, mode == SpyOnDirectoryChanged ? + &QFileSystemWatcher::directoryChanged : &QFileSystemWatcher::fileChanged, + this, &FileSystemWatcherSpy::spySlot); + m_elapsedTimer.start(); + } + + int count() const { return m_entries.size(); } + void clear() + { + m_entries.clear(); + m_elapsedTimer.restart(); + } + + QByteArray receivedFilesMessage() const + { + QString result; + QTextStream str(&result); + str << "At " << m_elapsedTimer.elapsed() << "ms, received " + << count() << " changes: "; + for (int i =0, e = m_entries.size(); i < e; ++i) { + if (i) + str << ", "; + str << m_entries.at(i).timeStamp << "ms: " << QDir::toNativeSeparators(m_entries.at(i).path); + } + return result.toLocal8Bit(); + } + +private slots: + void spySlot(const QString &p) { m_entries.append(Entry(m_elapsedTimer.elapsed(), p)); } + +private: + struct Entry { + Entry() : timeStamp(0) {} + Entry(qint64 t, const QString &p) : timeStamp(t), path(p) {} + + qint64 timeStamp; + QString path; + }; + + QElapsedTimer m_elapsedTimer; + QList m_entries; +}; + void tst_QFileSystemWatcher::removePaths() { QFileSystemWatcher watcher; @@ -438,9 +495,8 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory() QVERIFY(watcher.addPath(testFileName)); QSignalSpy fileChangedSpy(&watcher, &QFileSystemWatcher::fileChanged); - QSignalSpy dirChangedSpy(&watcher, &QFileSystemWatcher::directoryChanged); + FileSystemWatcherSpy dirChangedSpy(&watcher, FileSystemWatcherSpy::SpyOnDirectoryChanged); QVERIFY(fileChangedSpy.isValid()); - QVERIFY(dirChangedSpy.isValid()); QEventLoop eventLoop; QTimer timer; connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); @@ -460,7 +516,7 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory() #endif QTRY_VERIFY(fileChangedSpy.count() > 0); - QCOMPARE(dirChangedSpy.count(), 0); + QVERIFY2(dirChangedSpy.count() == 0, dirChangedSpy.receivedFilesMessage()); fileChangedSpy.clear(); QFile secondFile(secondFileName); @@ -640,13 +696,14 @@ private: // emitted with the destination path instead of the starting path void tst_QFileSystemWatcher::signalsEmittedAfterFileMoved() { + const int fileCount = 10; QTemporaryDir temporaryDirectory(m_tempDirPattern); QVERIFY(temporaryDirectory.isValid()); QDir testDir(temporaryDirectory.path()); QVERIFY(testDir.mkdir("movehere")); QString movePath = testDir.filePath("movehere"); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < fileCount; ++i) { QFile f(testDir.filePath(QString("test%1.txt").arg(i))); QVERIFY(f.open(QIODevice::WriteOnly)); f.write(QByteArray("i am ") + QByteArray::number(i)); @@ -659,6 +716,7 @@ void tst_QFileSystemWatcher::signalsEmittedAfterFileMoved() // add files to watcher QFileInfoList files = testDir.entryInfoList(QDir::Files | QDir::NoSymLinks); + QCOMPARE(files.size(), fileCount); foreach (const QFileInfo &finfo, files) QVERIFY(watcher.addPath(finfo.absoluteFilePath())); @@ -667,14 +725,16 @@ void tst_QFileSystemWatcher::signalsEmittedAfterFileMoved() connect(&watcher, SIGNAL(fileChanged(QString)), &signalReceiver, SLOT(fileChanged(QString))); // watch signals - QSignalSpy changedSpy(&watcher, &QFileSystemWatcher::fileChanged); - QVERIFY(changedSpy.isValid()); + FileSystemWatcherSpy changedSpy(&watcher, FileSystemWatcherSpy::SpyOnFileChanged); + QCOMPARE(changedSpy.count(), 0); // move files to second directory foreach (const QFileInfo &finfo, files) QVERIFY(testDir.rename(finfo.fileName(), QString("movehere/%2").arg(finfo.fileName()))); - QTRY_COMPARE(changedSpy.count(), 10); + QCoreApplication::processEvents(); + QVERIFY2(changedSpy.count() <= fileCount, changedSpy.receivedFilesMessage()); + QTRY_COMPARE(changedSpy.count(), fileCount); } #endif // QT_NO_FILESYSTEMWATCHER From 6545404afad30b60d1a8e9a2abaf301abaf8f6a5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 20 Apr 2015 10:57:20 +0200 Subject: [PATCH 23/52] Windows: Fix QLockFile hanging when file cannot be created. Return QLockFile::PermissionError when file does not exist, preventing the stale file detection logic from triggering. Add Windows-only autotest trying to create a lock file in a system folder guarded with checks for elevated processes and UAC virtualization. Task-number: QTBUG-45631 Change-Id: I1790f8f925660f6bf1df94c2ced901e6ec57cbb0 Reviewed-by: Joerg Bornemann Reviewed-by: Oliver Wolff --- src/corelib/io/qlockfile_win.cpp | 13 +++- .../corelib/io/qlockfile/tst_qlockfile.cpp | 65 +++++++++++++++++++ .../corelib/io/qlockfile/tst_qlockfile.pro | 1 + 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index a36e6e93b8..9fe86e1ad8 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -48,6 +48,12 @@ static inline QByteArray localHostName() return qgetenv("COMPUTERNAME"); } +static inline bool fileExists(const wchar_t *fileName) +{ + WIN32_FILE_ATTRIBUTE_DATA data; + return GetFileAttributesEx(fileName, GetFileExInfoStandard, &data); +} + QLockFile::LockError QLockFilePrivate::tryLock_sys() { const QFileSystemEntry fileEntry(fileName); @@ -79,8 +85,13 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() case ERROR_SHARING_VIOLATION: case ERROR_ALREADY_EXISTS: case ERROR_FILE_EXISTS: - case ERROR_ACCESS_DENIED: // readonly file, or file still in use by another process. Assume the latter, since we don't create it readonly. return QLockFile::LockFailedError; + case ERROR_ACCESS_DENIED: + // readonly file, or file still in use by another process. + // Assume the latter if the file exists, since we don't create it readonly. + return fileExists((const wchar_t*)fileEntry.nativeFilePath().utf16()) + ? QLockFile::LockFailedError + : QLockFile::PermissionError; default: qWarning() << "Got unexpected locking error" << lastError; return QLockFile::UnknownError; diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp index 90f65e9dbc..bef3d3a012 100644 --- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp +++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp @@ -36,8 +36,11 @@ #include #include #include +#include #if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS) #include +#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +# include #endif class tst_QLockFile : public QObject @@ -58,6 +61,7 @@ private slots: void staleLongLockFromBusyProcess(); void staleLockRace(); void noPermissions(); + void noPermissionsWindows(); public: QString m_helperApp; @@ -415,5 +419,66 @@ void tst_QLockFile::noPermissions() QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError)); } +enum ProcessProperty { + ElevatedProcess = 0x1, + VirtualStore = 0x2 +}; + +Q_DECLARE_FLAGS(ProcessProperties, ProcessProperty) +Q_DECLARE_OPERATORS_FOR_FLAGS(ProcessProperties) + +static inline ProcessProperties processProperties() +{ + ProcessProperties result; +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) + HANDLE processToken = NULL; + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &processToken)) { + DWORD elevation; // struct containing a DWORD, not present in some MinGW headers. + DWORD cbSize = sizeof(elevation); + if (GetTokenInformation(processToken, TokenElevation, &elevation, cbSize, &cbSize) + && elevation) { + result |= ElevatedProcess; + } + // Check for UAC virtualization (compatibility mode for old software + // allowing it to write to system folders by mirroring them under + // "\Users\...\AppData\Local\VirtualStore\", which is typically the case + // for MinGW). + DWORD virtualStoreEnabled = 0; + cbSize = sizeof(virtualStoreEnabled); + if (GetTokenInformation(processToken, TokenVirtualizationEnabled, &virtualStoreEnabled, cbSize, &cbSize) + && virtualStoreEnabled) { + result |= VirtualStore; + } + CloseHandle(processToken); + } +#endif + return result; +} + +void tst_QLockFile::noPermissionsWindows() +{ + // Windows: Do the permissions test in a system directory in which + // files cannot be created. +#if !defined(Q_OS_WIN) || defined(Q_OS_WINCE) || defined(Q_OS_WINRT) + QSKIP("This test is for desktop Windows only"); +#endif +#ifdef Q_OS_WIN + if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7) + QSKIP("This test requires at least Windows 7"); +#endif + if (const int p = processProperties()) { + const QByteArray message = "This test cannot be run (properties=0x" + + QByteArray::number(p, 16) + ')'; + QSKIP(message.constData()); + } + + const QString fileName = QFile::decodeName(qgetenv("ProgramFiles")) + + QLatin1Char('/') + QCoreApplication::applicationName() + + QDateTime::currentDateTime().toString(QStringLiteral("yyMMddhhmm")); + QLockFile lockFile(fileName); + QVERIFY(!lockFile.lock()); + QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError)); +} + QTEST_MAIN(tst_QLockFile) #include "tst_qlockfile.moc" diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro index 2f7009b736..6eb72343bc 100644 --- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro +++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro @@ -4,3 +4,4 @@ TARGET = tst_qlockfile SOURCES += tst_qlockfile.cpp QT = core testlib concurrent +win32:!wince:!winrt:LIBS += -ladvapi32 From c3737573ced4dc2217f31aac627fa8070e7512c8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 21 Apr 2015 08:25:28 +0200 Subject: [PATCH 24/52] uic: Delay the setting of QPushButton::default. For the property to take effect, the button must have its parent set. This might not be the case when a container like for example QTabWidget is involved. Move the setting of the property to the bottom of setupUi. Task-number: QTBUG-44406 Change-Id: Ic2013865a020986475fa28f2e3805c63d4de8ed0 Reviewed-by: Marc Mutz --- src/tools/uic/cpp/cppwriteinitialization.cpp | 7 ++++++- tests/auto/tools/uic/baseline/addtorrentform.ui.h | 4 +++- tests/auto/tools/uic/baseline/config.ui.h | 4 +++- tests/auto/tools/uic/baseline/finddialog.ui.h | 4 +++- tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h | 4 +++- tests/auto/tools/uic/baseline/sslclient.ui.h | 6 ++++-- tests/auto/tools/uic/baseline/topicchooser.ui.h | 4 +++- tests/auto/tools/uic/baseline/translatedialog.ui.h | 4 +++- 8 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index 78f243a6d3..b02e2dc0ed 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -1176,6 +1176,7 @@ void WriteInitialization::writeProperties(const QString &varName, continue; QString propertyName = p->attributeName(); QString propertyValue; + bool delayProperty = false; // special case for the property `geometry': Do not use position if (isTopLevel && propertyName == QLatin1String("geometry") && p->elementRect()) { @@ -1204,6 +1205,10 @@ void WriteInitialization::writeProperties(const QString &varName, && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QAxWidget"))) { // already done ;) continue; + } else if (propertyName == QLatin1String("default") + && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QPushButton"))) { + // QTBUG-44406: Setting of QPushButton::default needs to be delayed until the parent is set + delayProperty = true; } else if (propertyName == QLatin1String("database") && p->elementStringList()) { // Sql support @@ -1479,7 +1484,7 @@ void WriteInitialization::writeProperties(const QString &varName, else if (propertyName == QLatin1String("accessibleName") || propertyName == QLatin1String("accessibleDescription")) defineC = accessibilityDefineC; - QTextStream &o = autoTrOutput(p); + QTextStream &o = delayProperty ? m_delayedOut : autoTrOutput(p); if (defineC) openIfndef(o, QLatin1String(defineC)); diff --git a/tests/auto/tools/uic/baseline/addtorrentform.ui.h b/tests/auto/tools/uic/baseline/addtorrentform.ui.h index 29bae9735c..5aca0c4e47 100644 --- a/tests/auto/tools/uic/baseline/addtorrentform.ui.h +++ b/tests/auto/tools/uic/baseline/addtorrentform.ui.h @@ -97,7 +97,6 @@ public: browseTorrents = new QPushButton(groupBox); browseTorrents->setObjectName(QStringLiteral("browseTorrents")); - browseTorrents->setDefault(true); gridLayout->addWidget(browseTorrents, 0, 3, 1, 1); @@ -205,6 +204,9 @@ public: QObject::connect(okButton, SIGNAL(clicked()), AddTorrentFile, SLOT(accept())); QObject::connect(cancelButton, SIGNAL(clicked()), AddTorrentFile, SLOT(reject())); + browseTorrents->setDefault(true); + + QMetaObject::connectSlotsByName(AddTorrentFile); } // setupUi diff --git a/tests/auto/tools/uic/baseline/config.ui.h b/tests/auto/tools/uic/baseline/config.ui.h index 0775c02346..2d9003b4b9 100644 --- a/tests/auto/tools/uic/baseline/config.ui.h +++ b/tests/auto/tools/uic/baseline/config.ui.h @@ -688,7 +688,6 @@ public: buttonOk = new QPushButton(Config); buttonOk->setObjectName(QStringLiteral("buttonOk")); buttonOk->setAutoDefault(true); - buttonOk->setDefault(true); hboxLayout3->addWidget(buttonOk); @@ -706,6 +705,9 @@ public: QObject::connect(size_width, SIGNAL(valueChanged(int)), size_custom, SLOT(click())); QObject::connect(size_height, SIGNAL(valueChanged(int)), size_custom, SLOT(click())); + buttonOk->setDefault(true); + + QMetaObject::connectSlotsByName(Config); } // setupUi diff --git a/tests/auto/tools/uic/baseline/finddialog.ui.h b/tests/auto/tools/uic/baseline/finddialog.ui.h index 50595edc8a..259d36569f 100644 --- a/tests/auto/tools/uic/baseline/finddialog.ui.h +++ b/tests/auto/tools/uic/baseline/finddialog.ui.h @@ -164,7 +164,6 @@ public: vboxLayout1->setObjectName(QStringLiteral("vboxLayout1")); findNxt = new QPushButton(FindDialog); findNxt->setObjectName(QStringLiteral("findNxt")); - findNxt->setDefault(true); findNxt->setFlat(false); vboxLayout1->addWidget(findNxt); @@ -194,6 +193,9 @@ public: retranslateUi(FindDialog); QObject::connect(cancel, SIGNAL(clicked()), FindDialog, SLOT(reject())); + findNxt->setDefault(true); + + QMetaObject::connectSlotsByName(FindDialog); } // setupUi diff --git a/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h b/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h index 484c0877bc..31edb426fe 100644 --- a/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h +++ b/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h @@ -171,7 +171,6 @@ public: okButton = new QPushButton(QSqlConnectionDialogUi); okButton->setObjectName(QStringLiteral("okButton")); - okButton->setDefault(true); hboxLayout1->addWidget(okButton); @@ -202,6 +201,9 @@ public: retranslateUi(QSqlConnectionDialogUi); + okButton->setDefault(true); + + QMetaObject::connectSlotsByName(QSqlConnectionDialogUi); } // setupUi diff --git a/tests/auto/tools/uic/baseline/sslclient.ui.h b/tests/auto/tools/uic/baseline/sslclient.ui.h index a74a465955..f2071d8780 100644 --- a/tests/auto/tools/uic/baseline/sslclient.ui.h +++ b/tests/auto/tools/uic/baseline/sslclient.ui.h @@ -86,7 +86,6 @@ public: connectButton = new QPushButton(Form); connectButton->setObjectName(QStringLiteral("connectButton")); connectButton->setEnabled(true); - connectButton->setDefault(true); vboxLayout->addWidget(connectButton); @@ -136,7 +135,6 @@ public: sendButton->setObjectName(QStringLiteral("sendButton")); sendButton->setEnabled(false); sendButton->setFocusPolicy(Qt::TabFocus); - sendButton->setDefault(true); hboxLayout1->addWidget(sendButton); @@ -151,6 +149,10 @@ public: QObject::connect(hostNameEdit, SIGNAL(returnPressed()), connectButton, SLOT(animateClick())); QObject::connect(sessionInput, SIGNAL(returnPressed()), sendButton, SLOT(animateClick())); + connectButton->setDefault(true); + sendButton->setDefault(true); + + QMetaObject::connectSlotsByName(Form); } // setupUi diff --git a/tests/auto/tools/uic/baseline/topicchooser.ui.h b/tests/auto/tools/uic/baseline/topicchooser.ui.h index 06d34e9c63..3935a7a87b 100644 --- a/tests/auto/tools/uic/baseline/topicchooser.ui.h +++ b/tests/auto/tools/uic/baseline/topicchooser.ui.h @@ -77,7 +77,6 @@ public: buttonDisplay = new QPushButton(Layout16); buttonDisplay->setObjectName(QStringLiteral("buttonDisplay")); buttonDisplay->setAutoDefault(true); - buttonDisplay->setDefault(true); hboxLayout->addWidget(buttonDisplay); @@ -96,6 +95,9 @@ public: retranslateUi(TopicChooser); + buttonDisplay->setDefault(true); + + QMetaObject::connectSlotsByName(TopicChooser); } // setupUi diff --git a/tests/auto/tools/uic/baseline/translatedialog.ui.h b/tests/auto/tools/uic/baseline/translatedialog.ui.h index 72a2b48f2e..c494ca77c3 100644 --- a/tests/auto/tools/uic/baseline/translatedialog.ui.h +++ b/tests/auto/tools/uic/baseline/translatedialog.ui.h @@ -164,7 +164,6 @@ public: vboxLayout2->setContentsMargins(0, 0, 0, 0); findNxt = new QPushButton(TranslateDialog); findNxt->setObjectName(QStringLiteral("findNxt")); - findNxt->setDefault(true); findNxt->setFlat(false); vboxLayout2->addWidget(findNxt); @@ -206,6 +205,9 @@ public: retranslateUi(TranslateDialog); QObject::connect(cancel, SIGNAL(clicked()), TranslateDialog, SLOT(reject())); + findNxt->setDefault(true); + + QMetaObject::connectSlotsByName(TranslateDialog); } // setupUi From f657ecdc5ddef611a503ce460dc81fe2f0bbc2d6 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 20 Apr 2015 16:53:25 +0200 Subject: [PATCH 25/52] Fix inplace double mirroring on odd sized images The QImage inplace mirroring method, failed to handle the middle line when mirroring both ways (rotate 180). In both other mirroring cases the middle can be left untouched, but in this case it needs to be mirrored half way. To make the logic simpler, double mirroring will now mirror half the lines instead of half of every line. Change-Id: Iaa1f1e1c3f7dedfb78891fc93207f6d0c64bcafe Reviewed-by: Konstantin Ritt Reviewed-by: Gunnar Sletta --- src/gui/image/qimage.cpp | 12 ++++- tests/auto/gui/image/qimage/tst_qimage.cpp | 51 ++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index f20800440d..f09e73f214 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2825,14 +2825,22 @@ template inline void do_mirror_data(QImageData *dst, QImageData *src, if (dst == src) { // When mirroring in-place, stop in the middle for one of the directions, since we // are swapping the bytes instead of merely copying. - const int srcXEnd = dstX0 ? w / 2 : w; - const int srcYEnd = !dstX0 && dstY0 ? h / 2 : h; + const int srcXEnd = (dstX0 && !dstY0) ? w / 2 : w; + const int srcYEnd = dstY0 ? h / 2 : h; for (int srcY = 0, dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) { T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line); T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line); for (int srcX = 0, dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr) std::swap(srcPtr[srcX], dstPtr[dstX]); } + // If mirroring both ways, the middle line needs to be mirrored horizontally only. + if (dstX0 && dstY0 && (h & 1)) { + int srcY = h / 2; + int srcXEnd2 = w / 2; + T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line); + for (int srcX = 0, dstX = dstX0; srcX < srcXEnd2; ++srcX, dstX += dstXIncr) + std::swap(srcPtr[srcX], srcPtr[dstX]); + } } else { for (int srcY = 0, dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) { T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line); diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index 525d5b33a0..5691a654d7 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -155,6 +155,9 @@ private slots: void inplaceMirrored_data(); void inplaceMirrored(); + void inplaceMirroredOdd_data(); + void inplaceMirroredOdd(); + void inplaceRgbMirrored(); void inplaceConversion_data(); @@ -2471,6 +2474,54 @@ void tst_QImage::inplaceMirrored() #endif } +void tst_QImage::inplaceMirroredOdd_data() +{ + QTest::addColumn("format"); + QTest::addColumn("swap_vertical"); + QTest::addColumn("swap_horizontal"); + + QTest::newRow("Format_ARGB32, vertical") << QImage::Format_ARGB32 << true << false; + QTest::newRow("Format_RGB888, vertical") << QImage::Format_RGB888 << true << false; + QTest::newRow("Format_RGB16, vertical") << QImage::Format_RGB16 << true << false; + + QTest::newRow("Format_ARGB32, horizontal") << QImage::Format_ARGB32 << false << true; + QTest::newRow("Format_RGB888, horizontal") << QImage::Format_RGB888 << false << true; + QTest::newRow("Format_RGB16, horizontal") << QImage::Format_RGB16 << false << true; + + QTest::newRow("Format_ARGB32, horizontal+vertical") << QImage::Format_ARGB32 << true << true; + QTest::newRow("Format_RGB888, horizontal+vertical") << QImage::Format_RGB888 << true << true; + QTest::newRow("Format_RGB16, horizontal+vertical") << QImage::Format_RGB16 << true << true; +} + +void tst_QImage::inplaceMirroredOdd() +{ +#if defined(Q_COMPILER_REF_QUALIFIERS) + QFETCH(QImage::Format, format); + QFETCH(bool, swap_vertical); + QFETCH(bool, swap_horizontal); + + QImage image(15, 15, format); + + for (int i = 0; i < image.height(); ++i) + for (int j = 0; j < image.width(); ++j) + image.setPixel(j, i, qRgb(j*16, i*16, 0)); + + const uchar* originalPtr = image.constScanLine(0); + + QImage imageMirrored = std::move(image).mirrored(swap_horizontal, swap_vertical); + for (int i = 0; i < imageMirrored.height(); ++i) { + int mirroredI = swap_vertical ? (imageMirrored.height() - i - 1) : i; + for (int j = 0; j < imageMirrored.width(); ++j) { + int mirroredJ = swap_horizontal ? (imageMirrored.width() - j - 1) : j; + QRgb mirroredColor = imageMirrored.pixel(mirroredJ, mirroredI); + QCOMPARE(qRed(mirroredColor) & 0xF8, j * 16); + QCOMPARE(qGreen(mirroredColor) & 0xF8, i * 16); + } + } + QCOMPARE(imageMirrored.constScanLine(0), originalPtr); +#endif +} + void tst_QImage::inplaceRgbMirrored() { #if defined(Q_COMPILER_REF_QUALIFIERS) From c33f2032229c9304e5ed9bb620d6b580ed26cbe4 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 17 Apr 2015 15:08:56 +0200 Subject: [PATCH 26/52] Fix typo when resolving EGL extension. Change-Id: I28a237660e0f6b2583014f79a3a13edc46ef6d0e Reviewed-by: Sean Harmer --- src/openglextensions/qopenglextensions.cpp | 2 +- util/glgen/qopenglextensions.cpp.footer | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openglextensions/qopenglextensions.cpp b/src/openglextensions/qopenglextensions.cpp index 2101e5546c..37c5a5d1f0 100644 --- a/src/openglextensions/qopenglextensions.cpp +++ b/src/openglextensions/qopenglextensions.cpp @@ -6941,7 +6941,7 @@ bool QOpenGLExtension_OES_EGL_image::initializeOpenGLFunctions() Q_D(QOpenGLExtension_OES_EGL_image); d->EGLImageTargetTexture2DOES = (void (QOPENGLF_APIENTRYP)(GLenum target, GLeglImageOES image))context->getProcAddress("glEGLImageTargetTexture2DOES"); - d->EGLImageTargetRenderbufferStorageOES = (void (QOPENGLF_APIENTRYP)(GLenum target, GLeglImageOES image))context->getProcAddress("glEGLImageTargetRenderbufferStorageOESs"); + d->EGLImageTargetRenderbufferStorageOES = (void (QOPENGLF_APIENTRYP)(GLenum target, GLeglImageOES image))context->getProcAddress("glEGLImageTargetRenderbufferStorageOES"); return QAbstractOpenGLExtension::initializeOpenGLFunctions(); } diff --git a/util/glgen/qopenglextensions.cpp.footer b/util/glgen/qopenglextensions.cpp.footer index d7bd157743..64dac25f5c 100644 --- a/util/glgen/qopenglextensions.cpp.footer +++ b/util/glgen/qopenglextensions.cpp.footer @@ -21,7 +21,7 @@ bool QOpenGLExtension_OES_EGL_image::initializeOpenGLFunctions() Q_D(QOpenGLExtension_OES_EGL_image); d->EGLImageTargetTexture2DOES = (void (QOPENGLF_APIENTRYP)(GLenum target, GLeglImageOES image))context->getProcAddress("glEGLImageTargetTexture2DOES"); - d->EGLImageTargetRenderbufferStorageOES = (void (QOPENGLF_APIENTRYP)(GLenum target, GLeglImageOES image))context->getProcAddress("glEGLImageTargetRenderbufferStorageOESs"); + d->EGLImageTargetRenderbufferStorageOES = (void (QOPENGLF_APIENTRYP)(GLenum target, GLeglImageOES image))context->getProcAddress("glEGLImageTargetRenderbufferStorageOES"); return QAbstractOpenGLExtension::initializeOpenGLFunctions(); } From f99a270f104ef9460481271ab86d311d2e8f198a Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Thu, 23 Apr 2015 14:36:09 +0200 Subject: [PATCH 27/52] Remove unused counter variable Change-Id: I4069fdb75c2ef27fd4ac30de0963472c89165b20 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 94f4c2a2d3..92d064df9b 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -306,7 +306,6 @@ void QXcbConnection::initializeScreens() m_virtualDesktops.append(virtualDesktop); QList siblings; int outputCount = 0; - int connectedOutputCount = 0; if (has_randr_extension) { xcb_generic_error_t *error = NULL; // RRGetScreenResourcesCurrent is fast but it may return nothing if the @@ -375,7 +374,6 @@ void QXcbConnection::initializeScreens() QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data()); siblings << screen; - ++connectedOutputCount; hasOutputs = true; m_screens << screen; From 8f3b2f9f02968328950170c1783968536176fd06 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 22 Apr 2015 12:39:23 +0200 Subject: [PATCH 28/52] compilerSupportsFlag(): remove bogus .o suffix from test executables this function does not just compile, but it also links, so the output file should have no object file extension. Change-Id: I65dd9bd334478545ceeabe9d1aacb44d9583cdd7 Reviewed-by: Joerg Bornemann --- configure | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 03421dfc4c..b0c6ac0bc2 100755 --- a/configure +++ b/configure @@ -357,12 +357,12 @@ compilerSupportsFlag() int main() { return 0; } EOF if [ "$OPT_VERBOSE" = "yes" ]; then - "$@" -o conftest-out.o conftest.cpp + "$@" -o conftest-out conftest.cpp else - "$@" -o conftest-out.o conftest.cpp >/dev/null 2>&1 + "$@" -o conftest-out conftest.cpp >/dev/null 2>&1 fi ret=$? - rm -f conftest.cpp conftest-out.o + rm -f conftest.cpp conftest-out return $ret } From 6d1ea28aa3924aaa716bc9f1c7e467be00af87d4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 22 Apr 2015 12:37:15 +0200 Subject: [PATCH 29/52] make linkerSupportsFlag() use gold linker if detected subsequent tests should depend on the detected linker, obviously. Change-Id: I09aa9f1f2ef789f0ae0829f9122211fc4e1ad518 Reviewed-by: Joerg Bornemann --- configure | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure b/configure index b0c6ac0bc2..6b59a888d4 100755 --- a/configure +++ b/configure @@ -376,6 +376,9 @@ linkerSupportsFlag() safe_flag=`shellEscape "$flag"` lflags=$lflags,$safe_flag done + if [ $CFG_USE_GOLD_LINKER = yes ]; then + lflags="-fuse-ld=gold $lflags" + fi compilerSupportsFlag $compiler $lflags } From 455ae6a32c1c4b35e359f88d1f8ac2b85f0db689 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 15 Apr 2015 12:35:41 +0200 Subject: [PATCH 30/52] support headers-only modules automatically set TEMPLATE=aux if qt_no_install_library is set. Change-Id: Iccceda468da762b181fdd5c8e511bf6ed19af599 Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_module.prf | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 7c4d574874..afa20a9ab1 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -58,10 +58,14 @@ else: \ MODULE_DEFINE = QT_$${ucmodule}_LIB MODULE_DEFINES = $$MODULE_DEFINE $$MODULE_DEFINES -load(qt_module_pris) +load(qt_build_paths) -#other -TEMPLATE = lib +qt_no_install_library { + TEMPLATE = aux + CONFIG += force_qt # Needed for the headers_clean tests. +} else { + TEMPLATE = lib +} DESTDIR = $$MODULE_BASE_OUTDIR/lib win32:!wince*:!prefix_build: DLLDESTDIR = $$MODULE_BASE_OUTDIR/bin @@ -69,6 +73,7 @@ CONFIG += qmake_cache target_qt QMAKE_DOCS_TARGETDIR = qt$${MODULE} +load(qt_module_pris) load(qt_common) !no_module_headers: load(qt_module_headers) From 0ce189d20f0c7307382c868eafb10c4744347b56 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Apr 2015 13:41:42 +0200 Subject: [PATCH 31/52] fix distclean target for plugins under unix Change-Id: I5ebaba8575dfac9597e1ead92d42955ff626e1b1 Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 3c3189317e..5058ce2914 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -1041,9 +1041,9 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "\t-$(DEL_FILE) -r " << bundlePath << endl; } else if(project->isActiveConfig("compile_libtool")) { t << "\t-$(LIBTOOL) --mode=clean $(DEL_FILE) $(TARGET)\n"; - } else if (project->isActiveConfig("staticlib")) { + } else if (project->isActiveConfig("staticlib") || project->isActiveConfig("plugin")) { t << "\t-$(DEL_FILE) " << escapeFilePath(destdir) << "$(TARGET) \n"; - } else if (project->values("QMAKE_APP_FLAG").isEmpty() && !project->isActiveConfig("plugin")) { + } else if (project->values("QMAKE_APP_FLAG").isEmpty()) { destdir = escapeFilePath(destdir); t << "\t-$(DEL_FILE) " << destdir << "$(TARGET) \n"; if (!project->isActiveConfig("unversioned_libname")) { From 6e2e0e061ff1974b35cd171e085b9920d770e7d9 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Apr 2015 13:43:30 +0200 Subject: [PATCH 32/52] automatically distclean internally generated artifacts specifically, .prl, .pc, and .la files, and QMAKE_SUBSTITUTES outputs. Change-Id: I27685125668f0ec2aa81a8f003d3605accf2ab36 Reviewed-by: Joerg Bornemann --- qmake/generators/makefile.cpp | 10 ++++++++-- qmake/generators/unix/unixmake2.cpp | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 2106d0869b..f5e8248af5 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -573,10 +573,12 @@ MakefileGenerator::init() contentBytes = contents.toUtf8(); } QFile out(outn); + QFileInfo outfi(out); if (out.exists() && out.open(QFile::ReadOnly)) { QByteArray old = out.readAll(); if (contentBytes == old) { v["QMAKE_INTERNAL_INCLUDED_FILES"].append(in.fileName()); + v["QMAKE_DISTCLEAN"].append(outfi.absoluteFilePath()); continue; } out.close(); @@ -586,9 +588,10 @@ MakefileGenerator::init() continue; } } - mkdir(QFileInfo(out).absolutePath()); + mkdir(outfi.absolutePath()); if(out.open(QFile::WriteOnly)) { v["QMAKE_INTERNAL_INCLUDED_FILES"].append(in.fileName()); + v["QMAKE_DISTCLEAN"].append(outfi.absoluteFilePath()); out.write(contentBytes); } else { warn_msg(WarnLogic, "Cannot open substitute for output '%s'", @@ -1121,6 +1124,7 @@ MakefileGenerator::writePrlFile() if(ft.open(QIODevice::WriteOnly)) { project->values("ALL_DEPS").append(prl); project->values("QMAKE_INTERNAL_PRL_FILE").append(prl); + project->values("QMAKE_DISTCLEAN").append(prl); QTextStream t(&ft); writePrlFile(t); } @@ -3160,7 +3164,9 @@ MakefileGenerator::writePkgConfigFile() QFile ft(fname); if(!ft.open(QIODevice::WriteOnly)) return; - project->values("ALL_DEPS").append(fileFixify(fname)); + QString ffname(fileFixify(fname)); + project->values("ALL_DEPS").append(ffname); + project->values("QMAKE_DISTCLEAN").append(ffname); QTextStream t(&ft); QString prefix = pkgConfigPrefix(); diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 5058ce2914..50eb93cda9 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -1411,7 +1411,9 @@ UnixMakefileGenerator::writeLibtoolFile() QFile ft(fname); if(!ft.open(QIODevice::WriteOnly)) return; - project->values("ALL_DEPS").append(fileFixify(fname)); + QString ffname(fileFixify(fname)); + project->values("ALL_DEPS").append(ffname); + project->values("QMAKE_DISTCLEAN").append(ffname); QTextStream t(&ft); t << "# " << lname << " - a libtool library file\n"; From 3378aa45c27052510c244f935639d65bdf9275f4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Apr 2015 13:40:49 +0200 Subject: [PATCH 33/52] fix distclean targets this makes the distclean targets work throughout qt. the dreaded confclean target is aliased to distclean. Task-number: QTBUG-8202 Task-number: QTBUG-20566 Change-Id: I7ac8e3b5b0110825dc93e4fa885281db91c6cf83 Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_module_headers.prf | 7 ++ mkspecs/features/qt_parts.prf | 18 ++++ qmake/Makefile.unix | 2 + qmake/Makefile.win32 | 4 +- qtbase.pro | 86 +++++++------------ .../io/qresourceengine/qresourceengine.pro | 1 + 6 files changed, 62 insertions(+), 56 deletions(-) diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index aed04c3c1c..3f2383c120 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -24,6 +24,10 @@ load(qt_build_paths) -outdir $$system_quote($$MODULE_BASE_OUTDIR) $$MODULE_SYNCQT_DIR !silent: message($$QMAKE_SYNCQT) system($$QMAKE_SYNCQT)|error("Failed to run: $$QMAKE_SYNCQT") + + include-distclean.commands = $$QMAKE_DEL_TREE $$shell_quote($$shell_path($$MODULE_BASE_OUTDIR/include/$$MODULE_INCNAME)) + QMAKE_EXTRA_TARGETS += include-distclean + DISTCLEAN_DEPS += include-distclean } minimal_syncqt: return() @@ -41,11 +45,13 @@ for (injection, SYNCQT.INJECTIONS) { MAIN_FWD = $$INC_PATH/include/$$MODULE_INCNAME/$$fwd_hdr MAIN_FWD_CONT = '$${LITERAL_HASH}include "$$member(injects, 0)"' write_file($$MAIN_FWD, MAIN_FWD_CONT)|error("Aborting.") + !git_build: QMAKE_DISTCLEAN += $$MAIN_FWD injects = $$member(injects, 2, -1) for (inject, injects) { CLASS_FWD = $$INC_PATH/include/$$MODULE_INCNAME/$$inject CLASS_FWD_CONT = '$${LITERAL_HASH}include "$$fwd_hdr"' write_file($$CLASS_FWD, CLASS_FWD_CONT)|error("Aborting.") + !git_build: QMAKE_DISTCLEAN += $$CLASS_FWD } } @@ -65,6 +71,7 @@ MODULE_MASTER_DEPS_HEADER = $$MODULE_BASE_OUTDIR/include/$$MODULE_INCNAME/$${MOD } MODULE_MASTER_DEPS_HEADER_CONT += "$${LITERAL_HASH}endif" write_file($$MODULE_MASTER_DEPS_HEADER, MODULE_MASTER_DEPS_HEADER_CONT)|error("Aborting.") + !git_build: QMAKE_DISTCLEAN += $$MODULE_MASTER_DEPS_HEADER } SYNCQT.HEADER_FILES += $$MODULE_MASTER_DEPS_HEADER diff --git a/mkspecs/features/qt_parts.prf b/mkspecs/features/qt_parts.prf index fee711aeb8..877bd60321 100644 --- a/mkspecs/features/qt_parts.prf +++ b/mkspecs/features/qt_parts.prf @@ -71,3 +71,21 @@ exists($$_PRO_FILE_PWD_/tests/tests.pro) { QT_BUILD_PARTS -= libs tools examples tests !isEmpty(QT_BUILD_PARTS): warning("Unknown build part(s): $$QT_BUILD_PARTS") + +QMAKE_DISTCLEAN += \ + .qmake.cache \ + config.log \ + mkspecs/modules/*.pri \ + mkspecs/modules-inst/*.pri + +tests = $$files($$_PRO_FILE_PWD_/config.tests/*.pro, true) +testdirs = +for (t, tests): \ + testdirs += $$relative_path($$dirname(t), $$_PRO_FILE_PWD_) +testdirs = $$unique(testdirs) +for (td, testdirs) { + t = $$basename(td)-distclean + $${t}.commands = -cd $$shell_path($$td) && $(MAKE) distclean + QMAKE_EXTRA_TARGETS += $$t + DISTCLEAN_DEPS += $$t +} diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 873d65a97c..86f884fe20 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -123,9 +123,11 @@ clean:: distclean:: clean $(RM_RF) .deps $(RM_F) $(BUILD_PATH)/bin/qmake$(EXEEXT) + $(RM_F) Makefile depend: makedepend -D__MAKEDEPEND__ $(CPPFLAGS) $(DEPEND_SRC) + $(RM_F) Makefile.bak ioutils.o: $(QMKLIBSRC)/ioutils.cpp diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index f84c30d4af..9dda6ca1e7 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -140,7 +140,9 @@ clean:: -del qmake.tds distclean:: clean - -del qmake + -del qmake.exe + -del $(BUILD_PATH)\bin\qmake.exe + -del Makefile .c.obj: $(CXX) $(CFLAGS) $< diff --git a/qtbase.pro b/qtbase.pro index 6d0de44f6d..bae2641404 100644 --- a/qtbase.pro +++ b/qtbase.pro @@ -8,62 +8,30 @@ SUBDIRS += qmake/qmake-docs.pro cross_compile: CONFIG += nostrip -confclean.depends += clean -confclean.commands = -unix { - confclean.commands += (cd config.tests/unix/stl && $(MAKE) distclean); \ - (cd config.tests/unix/ptrsize && $(MAKE) distclean); \ - (cd config.tests/x11/notype && $(MAKE) distclean); \ - (cd config.tests/unix/getaddrinfo && $(MAKE) distclean); \ - (cd config.tests/unix/cups && $(MAKE) distclean); \ - (cd config.tests/unix/psql && $(MAKE) distclean); \ - (cd config.tests/unix/mysql && $(MAKE) distclean); \ - (cd config.tests/unix/mysql_r && $(MAKE) distclean); \ - (cd config.tests/unix/nis && $(MAKE) distclean); \ - (cd config.tests/unix/iodbc && $(MAKE) distclean); \ - (cd config.tests/unix/odbc && $(MAKE) distclean); \ - (cd config.tests/unix/oci && $(MAKE) distclean); \ - (cd config.tests/unix/tds && $(MAKE) distclean); \ - (cd config.tests/unix/db2 && $(MAKE) distclean); \ - (cd config.tests/unix/ibase && $(MAKE) distclean); \ - (cd config.tests/unix/ipv6ifname && $(MAKE) distclean); \ - (cd config.tests/unix/zlib && $(MAKE) distclean); \ - (cd config.tests/unix/sqlite2 && $(MAKE) distclean); \ - (cd config.tests/unix/libjpeg && $(MAKE) distclean); \ - (cd config.tests/unix/libpng && $(MAKE) distclean); \ - (cd config.tests/unix/slog2 && $(MAKE) distclean); \ - (cd config.tests/unix/lgmon && $(MAKE) distclean); \ - (cd config.tests/x11/xcursor && $(MAKE) distclean); \ - (cd config.tests/x11/xrender && $(MAKE) distclean); \ - (cd config.tests/x11/xrandr && $(MAKE) distclean); \ - (cd config.tests/x11/xkb && $(MAKE) distclean); \ - (cd config.tests/x11/xinput && $(MAKE) distclean); \ - (cd config.tests/x11/fontconfig && $(MAKE) distclean); \ - (cd config.tests/x11/xinerama && $(MAKE) distclean); \ - (cd config.tests/x11/xshape && $(MAKE) distclean); \ - (cd config.tests/x11/opengl && $(MAKE) distclean); \ - $(DEL_FILE) config.tests/.qmake.cache; \ - $(DEL_FILE) src/corelib/global/qconfig.h; \ - $(DEL_FILE) src/corelib/global/qconfig.cpp; \ - $(DEL_FILE) mkspecs/qconfig.pri; \ - $(DEL_FILE) mkspecs/qdevice.pri; \ - $(DEL_FILE) mkspecs/qmodule.pri; \ - $(DEL_FILE) .qmake.cache; \ - (cd qmake && $(MAKE) distclean); -} -win32 { - confclean.commands += -$(DEL_FILE) src\\corelib\\global\\qconfig.h $$escape_expand(\\n\\t) \ - -$(DEL_FILE) src\\corelib\\global\\qconfig.cpp $$escape_expand(\\n\\t) \ - -$(DEL_FILE) mkspecs\\qconfig.pri $$escape_expand(\\n\\t) \ - -$(DEL_FILE) mkspecs\\qdevice.pri $$escape_expand(\\n\\t) \ - -$(DEL_FILE) mkspecs\\qmodule.pri $$escape_expand(\\n\\t) \ - -$(DEL_FILE) .qmake.cache $$escape_expand(\\n\\t) \ - (cd qmake && $(MAKE) distclean) -} +confclean.depends += distclean +confclean.commands = echo The confclean target is obsolete. Please use distclean instead. QMAKE_EXTRA_TARGETS += confclean -qmakeclean.commands += (cd qmake && $(MAKE) clean) -QMAKE_EXTRA_TARGETS += qmakeclean -CLEAN_DEPS += qmakeclean + +qmake-clean.commands += (cd qmake && $(MAKE) clean) +QMAKE_EXTRA_TARGETS += qmake-clean +CLEAN_DEPS += qmake-clean + +# We don't distclean qmake, as it may be needed for rebuilding Makefiles as a +# recursive distclean proceeds, including beyond qtbase. +DISTCLEAN_DEPS += qmake-clean + +# Files created by configure. +# config.status (and configure.cache, which is the same for Windows) +# are omitted for convenience of rebuilds. +QMAKE_DISTCLEAN += \ + config.summary \ + config.tests/.qmake.cache \ + mkspecs/qconfig.pri \ + mkspecs/qdevice.pri \ + mkspecs/qmodule.pri \ + src/corelib/global/qconfig.h \ + src/corelib/global/qconfig.cpp \ + bin/qt.conf CONFIG -= qt @@ -186,6 +154,14 @@ FWD_QTCONFIG = \ '$${LITERAL_HASH}include "qconfig.h"' write_file($$OUT_PWD/include/QtCore/QtConfig, FWD_QTCONFIG)|error("Aborting.") +# Files created by us +QMAKE_DISTCLEAN += \ + src/corelib/global/qfeatures.h \ + include/QtCore/qfeatures.h \ + mkspecs/qfeatures.pri \ + include/QtCore/qconfig.h \ + include/QtCore/QtConfig + #mkspecs mkspecs.path = $$[QT_HOST_DATA]/mkspecs mkspecs.files = \ diff --git a/tests/auto/corelib/io/qresourceengine/qresourceengine.pro b/tests/auto/corelib/io/qresourceengine/qresourceengine.pro index 92d0952b89..64f5cb46e0 100644 --- a/tests/auto/corelib/io/qresourceengine/qresourceengine.pro +++ b/tests/auto/corelib/io/qresourceengine/qresourceengine.pro @@ -10,6 +10,7 @@ runtime_resource.depends = $$PWD/testqrc/test.qrc runtime_resource.commands = $$QMAKE_RCC -root /runtime_resource/ -binary $${runtime_resource.depends} -o $${runtime_resource.target} QMAKE_EXTRA_TARGETS = runtime_resource PRE_TARGETDEPS += $${runtime_resource.target} +QMAKE_DISTCLEAN += $${runtime_resource.target} TESTDATA += \ parentdir.txt \ From 1c33c37d4c237a1e43b431f95a827dd219a1f10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Tue, 21 Apr 2015 21:32:19 +0100 Subject: [PATCH 34/52] QVector: Save one copy-CTOR call if we don't realloc Change-Id: Ie0f2eb922500bc3d76852939cf2c5d28d65a43ae Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qvector.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 9d5b749e79..eed5d17cad 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -600,16 +600,23 @@ Q_OUTOFLINE_TEMPLATE T QVector::value(int i, const T &defaultValue) const template void QVector::append(const T &t) { - const T copy(t); const bool isTooSmall = uint(d->size + 1) > d->alloc; if (!isDetached() || isTooSmall) { + const T copy(t); QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default); reallocData(d->size, isTooSmall ? d->size + 1 : d->alloc, opt); + + if (QTypeInfo::isComplex) + new (d->end()) T(copy); + else + *d->end() = copy; + + } else { + if (QTypeInfo::isComplex) + new (d->end()) T(t); + else + *d->end() = t; } - if (QTypeInfo::isComplex) - new (d->end()) T(copy); - else - *d->end() = copy; ++d->size; } From cf5e3f37f477d8f7e1dacc92767756c284c67696 Mon Sep 17 00:00:00 2001 From: Caroline Chao Date: Mon, 13 Apr 2015 15:25:23 +0200 Subject: [PATCH 35/52] Tests: Blacklist task260974_menuItemRectangleForComboBoxPopup On OS X 10.10. This test in tst_QComboBox is currently failing in CI. Change-Id: Ie326f79a900c3ae926c7ebe5bb5880dd422cee60 Task-number: QTBUG-45531 Reviewed-by: David Faure --- tests/auto/widgets/widgets/qcombobox/BLACKLIST | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/auto/widgets/widgets/qcombobox/BLACKLIST diff --git a/tests/auto/widgets/widgets/qcombobox/BLACKLIST b/tests/auto/widgets/widgets/qcombobox/BLACKLIST new file mode 100644 index 0000000000..4a270c085b --- /dev/null +++ b/tests/auto/widgets/widgets/qcombobox/BLACKLIST @@ -0,0 +1,3 @@ +QTBUG-45531 +[task260974_menuItemRectangleForComboBoxPopup] +osx-10.10 From ce302a53df8ecbbab4c30fea05753c3b1060fa56 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 23 Apr 2015 12:31:53 +0200 Subject: [PATCH 36/52] Simplify QQuaternion::operator!=() Change-Id: I5043c86362f5126c52d768b51774086869429e08 Reviewed-by: Konstantin Ritt --- src/gui/math3d/qquaternion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h index 240e31a5c2..52c717072d 100644 --- a/src/gui/math3d/qquaternion.h +++ b/src/gui/math3d/qquaternion.h @@ -266,7 +266,7 @@ inline bool operator==(const QQuaternion &q1, const QQuaternion &q2) inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2) { - return q1.xp != q2.xp || q1.yp != q2.yp || q1.zp != q2.zp || q1.wp != q2.wp; + return !operator==(q1, q2); } inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2) From bc162382e5aef0b796582340beb866fb7c55a289 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 23 Apr 2015 15:31:28 +0200 Subject: [PATCH 37/52] Short-cut SSE4 unpremultiply Even with SSE4 optimized unpremultiply it is still significantly faster to skip the calculation on alpha values 0 and 255. Change-Id: Iafe658fea8eacf35a857f292952b0c1ee056139c Reviewed-by: Gunnar Sletta --- src/gui/painting/qdrawingprimitive_sse2_p.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h index 4d0790a502..1a7dddf0d5 100644 --- a/src/gui/painting/qdrawingprimitive_sse2_p.h +++ b/src/gui/painting/qdrawingprimitive_sse2_p.h @@ -242,6 +242,8 @@ QT_FUNCTION_TARGET(SSE4_1) inline QRgb qUnpremultiply_sse4(QRgb p) { const uint alpha = qAlpha(p); + if (alpha == 255 || alpha == 0) + return p; const uint invAlpha = qt_inv_premul_factor[alpha]; const __m128i via = _mm_set1_epi32(invAlpha); const __m128i vr = _mm_set1_epi32(0x8000); @@ -250,8 +252,8 @@ inline QRgb qUnpremultiply_sse4(QRgb p) vl = _mm_add_epi32(vl, vr); vl = _mm_srai_epi32(vl, 16); vl = _mm_insert_epi32(vl, alpha, 3); - vl = _mm_packus_epi32(vl, _mm_setzero_si128()); - vl = _mm_packus_epi16(vl, _mm_setzero_si128()); + vl = _mm_packus_epi32(vl, vl); + vl = _mm_packus_epi16(vl, vl); return _mm_cvtsi128_si32(vl); } #endif From b089579dc32a3893ad89c9c180933339e387627a Mon Sep 17 00:00:00 2001 From: Nikita Baryshnikov Date: Tue, 21 Apr 2015 13:28:19 +0300 Subject: [PATCH 38/52] QDir: sort-by-size remove two unconditional branches recent change ad03511256a8279a8f55069e5a3a3465a9e122ec made r be arbitrary, not just -1, 0, +1, and now it doesn't make sense to have two unneeded unconditional branches in the sort-by-size case Change-Id: I9d80210846e89e3e8c574f0c32e04b05202b8a5b Reviewed-by: Marc Mutz --- src/corelib/io/qdir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 3a9ae2ee6d..9b1ec3917a 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -239,7 +239,7 @@ bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortIt break; } case QDir::Size: - r = int(qBound(-1, f2->item.size() - f1->item.size(), 1)); + r = f2->item.size() - f1->item.size(); break; case QDir::Type: { From 2447dd26590df3a58adbaee67e960f9ba75c130a Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 23 Apr 2015 13:12:11 +0200 Subject: [PATCH 39/52] QGenericMatrix: remove copy ctor The compiler-generated one is just fine. Change-Id: Iaacc56d4224c69b66823cc64640a00117c44d3cc Reviewed-by: Konstantin Ritt Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/gui/math3d/qgenericmatrix.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h index 89bc09f544..d23ff86f64 100644 --- a/src/gui/math3d/qgenericmatrix.h +++ b/src/gui/math3d/qgenericmatrix.h @@ -47,7 +47,6 @@ class QGenericMatrix public: QGenericMatrix(); explicit QGenericMatrix(Qt::Initialization) {} - QGenericMatrix(const QGenericMatrix& other); explicit QGenericMatrix(const T *values); const T& operator()(int row, int column) const; @@ -107,14 +106,6 @@ Q_INLINE_TEMPLATE QGenericMatrix::QGenericMatrix() setToIdentity(); } -template -Q_INLINE_TEMPLATE QGenericMatrix::QGenericMatrix(const QGenericMatrix& other) -{ - for (int col = 0; col < N; ++col) - for (int row = 0; row < M; ++row) - m[col][row] = other.m[col][row]; -} - template Q_OUTOFLINE_TEMPLATE QGenericMatrix::QGenericMatrix(const T *values) { From 9c4cbc0cc768fe8694d6e19b62b8ea8f4fb9d966 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 23 Apr 2015 13:15:40 +0200 Subject: [PATCH 40/52] QGenericMatrix: remove one of two non-initializing ctors ...and port to the remaining one. Can't do the same for QMatrix4x4, because that class is exported. Change-Id: I5448921af9e9194532be1b9f8d739b5c418a5e0b Reviewed-by: Konstantin Ritt --- src/gui/math3d/qgenericmatrix.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h index d23ff86f64..c08faaaa8b 100644 --- a/src/gui/math3d/qgenericmatrix.h +++ b/src/gui/math3d/qgenericmatrix.h @@ -92,8 +92,6 @@ private: #endif T m[N][M]; // Column-major order to match OpenGL. - explicit QGenericMatrix(int) {} // Construct without initializing identity matrix. - #if !defined(Q_NO_TEMPLATE_FRIENDS) template friend class QGenericMatrix; @@ -169,7 +167,7 @@ Q_OUTOFLINE_TEMPLATE void QGenericMatrix::fill(T value) template Q_OUTOFLINE_TEMPLATE QGenericMatrix QGenericMatrix::transposed() const { - QGenericMatrix result(1); + QGenericMatrix result(Qt::Uninitialized); for (int row = 0; row < M; ++row) for (int col = 0; col < N; ++col) result.m[row][col] = m[col][row]; @@ -237,7 +235,7 @@ Q_OUTOFLINE_TEMPLATE QGenericMatrix& QGenericMatrix::operator/ template Q_OUTOFLINE_TEMPLATE QGenericMatrix operator+(const QGenericMatrix& m1, const QGenericMatrix& m2) { - QGenericMatrix result(1); + QGenericMatrix result(Qt::Uninitialized); for (int row = 0; row < M; ++row) for (int col = 0; col < N; ++col) result.m[col][row] = m1.m[col][row] + m2.m[col][row]; @@ -247,7 +245,7 @@ Q_OUTOFLINE_TEMPLATE QGenericMatrix operator+(const QGenericMatrix Q_OUTOFLINE_TEMPLATE QGenericMatrix operator-(const QGenericMatrix& m1, const QGenericMatrix& m2) { - QGenericMatrix result(1); + QGenericMatrix result(Qt::Uninitialized); for (int row = 0; row < M; ++row) for (int col = 0; col < N; ++col) result.m[col][row] = m1.m[col][row] - m2.m[col][row]; @@ -257,7 +255,7 @@ Q_OUTOFLINE_TEMPLATE QGenericMatrix operator-(const QGenericMatrix Q_OUTOFLINE_TEMPLATE QGenericMatrix operator*(const QGenericMatrix& m1, const QGenericMatrix& m2) { - QGenericMatrix result(1); + QGenericMatrix result(Qt::Uninitialized); for (int row = 0; row < M2; ++row) { for (int col = 0; col < M1; ++col) { T sum(0.0f); @@ -272,7 +270,7 @@ Q_OUTOFLINE_TEMPLATE QGenericMatrix operator*(const QGenericMatrix Q_OUTOFLINE_TEMPLATE QGenericMatrix operator-(const QGenericMatrix& matrix) { - QGenericMatrix result(1); + QGenericMatrix result(Qt::Uninitialized); for (int row = 0; row < M; ++row) for (int col = 0; col < N; ++col) result.m[col][row] = -matrix.m[col][row]; @@ -282,7 +280,7 @@ Q_OUTOFLINE_TEMPLATE QGenericMatrix operator-(const QGenericMatrix Q_OUTOFLINE_TEMPLATE QGenericMatrix operator*(T factor, const QGenericMatrix& matrix) { - QGenericMatrix result(1); + QGenericMatrix result(Qt::Uninitialized); for (int row = 0; row < M; ++row) for (int col = 0; col < N; ++col) result.m[col][row] = matrix.m[col][row] * factor; @@ -292,7 +290,7 @@ Q_OUTOFLINE_TEMPLATE QGenericMatrix operator*(T factor, const QGenericM template Q_OUTOFLINE_TEMPLATE QGenericMatrix operator*(const QGenericMatrix& matrix, T factor) { - QGenericMatrix result(1); + QGenericMatrix result(Qt::Uninitialized); for (int row = 0; row < M; ++row) for (int col = 0; col < N; ++col) result.m[col][row] = matrix.m[col][row] * factor; @@ -302,7 +300,7 @@ Q_OUTOFLINE_TEMPLATE QGenericMatrix operator*(const QGenericMatrix Q_OUTOFLINE_TEMPLATE QGenericMatrix operator/(const QGenericMatrix& matrix, T divisor) { - QGenericMatrix result(1); + QGenericMatrix result(Qt::Uninitialized); for (int row = 0; row < M; ++row) for (int col = 0; col < N; ++col) result.m[col][row] = matrix.m[col][row] / divisor; From 4bafef9890a1dc42a5e95a348ace9bdd70b1fc61 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 24 Apr 2015 10:57:24 +0200 Subject: [PATCH 41/52] QMainWindow::restoreDockWidget(): Fix positioning of floating docks with native decoration. Use QWidget::move() to position floating dock widgets. Add a test for QMainWindow::restoreDockWidget(). Task-number: QTBUG-45780 Change-Id: I945917728a663916e8c225b9d3d2a75fa508d68f Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/widgets/qdockwidget.cpp | 10 ++- .../widgets/qdockwidget/tst_qdockwidget.cpp | 73 +++++++++++++++++-- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index db8d167b0d..21b0904cc0 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -1031,8 +1031,14 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect q->setWindowFlags(flags); - if (!rect.isNull()) - q->setGeometry(rect); + if (!rect.isNull()) { + if (floating) { + q->resize(rect.size()); + q->move(rect.topLeft()); + } else { + q->setGeometry(rect); + } + } updateButtons(); diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp index 0521a9bd99..ade9f72543 100644 --- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp +++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp @@ -72,6 +72,7 @@ private slots: void setTitleBarWidget(); void titleBarDoubleClick(); void restoreStateOfFloating(); + void restoreDockWidget(); // task specific tests: void task165177_deleteFocusWidget(); void task169808_setFloating(); @@ -694,20 +695,78 @@ void tst_QDockWidget::titleBarDoubleClick() QCOMPARE(win.dockWidgetArea(&dock), Qt::TopDockWidgetArea); } +static QDockWidget *createTestDock(QMainWindow &parent) +{ + const QString title = QStringLiteral("dock1"); + QDockWidget *dock = new QDockWidget(title, &parent); + dock->setObjectName(title); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); + return dock; +} + void tst_QDockWidget::restoreStateOfFloating() { QMainWindow mw; - QDockWidget dock; - dock.setObjectName("dock1"); - mw.addDockWidget(Qt::TopDockWidgetArea, &dock); - QVERIFY(!dock.isFloating()); + QDockWidget *dock = createTestDock(mw); + mw.addDockWidget(Qt::TopDockWidgetArea, dock); + QVERIFY(!dock->isFloating()); QByteArray ba = mw.saveState(); - dock.setFloating(true); - QVERIFY(dock.isFloating()); + dock->setFloating(true); + QVERIFY(dock->isFloating()); QVERIFY(mw.restoreState(ba)); - QVERIFY(!dock.isFloating()); + QVERIFY(!dock->isFloating()); } +void tst_QDockWidget::restoreDockWidget() +{ + QByteArray geometry; + QByteArray state; + const QString name = QStringLiteral("main"); + const QRect availableGeometry = QApplication::desktop()->availableGeometry(); + const QSize size = availableGeometry.size() / 5; + const QPoint mainWindowPos = availableGeometry.bottomRight() - QPoint(size.width(), size.height()) - QPoint(100, 100); + const QPoint dockPos = availableGeometry.center(); + + { + QMainWindow saveWindow; + saveWindow.setObjectName(name); + saveWindow.setWindowTitle(QTest::currentTestFunction() + QStringLiteral(" save")); + saveWindow.resize(size); + saveWindow.move(mainWindowPos); + saveWindow.restoreState(QByteArray()); + QDockWidget *dock = createTestDock(saveWindow); + QVERIFY(!saveWindow.restoreDockWidget(dock)); // Not added, no placeholder + saveWindow.addDockWidget(Qt::TopDockWidgetArea, dock); + dock->setFloating(true); + dock->resize(size); + dock->move(dockPos); + saveWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&saveWindow)); + QVERIFY(dock->isFloating()); + state = saveWindow.saveState(); + geometry = saveWindow.saveGeometry(); + } + + QVERIFY(!geometry.isEmpty()); + QVERIFY(!state.isEmpty()); + + { + QMainWindow restoreWindow; + restoreWindow.setObjectName(name); + restoreWindow.setWindowTitle(QTest::currentTestFunction() + QStringLiteral(" restore")); + QVERIFY(restoreWindow.restoreState(state)); + QVERIFY(restoreWindow.restoreGeometry(geometry)); + + // QMainWindow::restoreDockWidget() restores the state when adding the dock + // after restoreState(). + QDockWidget *dock = createTestDock(restoreWindow); + QVERIFY(restoreWindow.restoreDockWidget(dock)); + restoreWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&restoreWindow)); + QTRY_VERIFY(dock->isFloating()); + QTRY_COMPARE(dock->pos(), dockPos); + } +} void tst_QDockWidget::task165177_deleteFocusWidget() { From 4dd896785b0b1a3bc6c0fd5380f9b7753fbee9e6 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 13 Mar 2015 12:26:22 +0100 Subject: [PATCH 42/52] MySQL: Add support for the timeout options via the connectionOptions Task-number: QTBUG-321 Change-Id: I0bbc1ae713fb0278a9973f8e87f28f1b3f1c49ce Reviewed-by: Giuseppe D'Angelo --- src/sql/drivers/mysql/qsql_mysql.cpp | 41 ++++++++++++++++++++-------- src/sql/kernel/qsqldatabase.cpp | 3 ++ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index b8f9c472b9..d901008e00 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -1237,6 +1237,9 @@ bool QMYSQLDriver::open(const QString& db, QString unixSocket; #if MYSQL_VERSION_ID >= 50000 my_bool reconnect=false; + uint connectTimeout = 0; + uint readTimeout = 0; + uint writeTimeout = 0; #endif // extract the real options from the string @@ -1252,6 +1255,12 @@ bool QMYSQLDriver::open(const QString& db, else if (opt == QLatin1String("MYSQL_OPT_RECONNECT")) { if (val == QLatin1String("TRUE") || val == QLatin1String("1") || val.isEmpty()) reconnect = true; + } else if (opt == QLatin1String("MYSQL_OPT_CONNECT_TIMEOUT")) { + connectTimeout = val.toInt(); + } else if (opt == QLatin1String("MYSQL_OPT_READ_TIMEOUT")) { + readTimeout = val.toInt(); + } else if (opt == QLatin1String("MYSQL_OPT_WRITE_TIMEOUT")) { + writeTimeout = val.toInt(); } #endif else if (val == QLatin1String("TRUE") || val == QLatin1String("1")) @@ -1264,8 +1273,16 @@ bool QMYSQLDriver::open(const QString& db, } } - if ((d->mysql = mysql_init((MYSQL*) 0)) && - mysql_real_connect(d->mysql, + if ((d->mysql = mysql_init((MYSQL*) 0))) { +#if MYSQL_VERSION_ID >= 50000 + if (connectTimeout != 0) + mysql_options(d->mysql, MYSQL_OPT_CONNECT_TIMEOUT, &connectTimeout); + if (readTimeout != 0) + mysql_options(d->mysql, MYSQL_OPT_READ_TIMEOUT, &readTimeout); + if (writeTimeout != 0) + mysql_options(d->mysql, MYSQL_OPT_WRITE_TIMEOUT, &writeTimeout); +#endif + if (mysql_real_connect(d->mysql, host.isNull() ? static_cast(0) : host.toLocal8Bit().constData(), user.isNull() ? static_cast(0) @@ -1277,18 +1294,18 @@ bool QMYSQLDriver::open(const QString& db, (port > -1) ? port : 0, unixSocket.isNull() ? static_cast(0) : unixSocket.toLocal8Bit().constData(), - optionFlags)) - { - if (!db.isEmpty() && mysql_select_db(d->mysql, db.toLocal8Bit().constData())) { - setLastError(qMakeError(tr("Unable to open database '%1'").arg(db), QSqlError::ConnectionError, d)); - mysql_close(d->mysql); - setOpenError(true); - return false; - } + optionFlags)) { + if (!db.isEmpty() && mysql_select_db(d->mysql, db.toLocal8Bit().constData())) { + setLastError(qMakeError(tr("Unable to open database '%1'").arg(db), QSqlError::ConnectionError, d)); + mysql_close(d->mysql); + setOpenError(true); + return false; + } #if MYSQL_VERSION_ID >= 50000 - if(reconnect) - mysql_options(d->mysql, MYSQL_OPT_RECONNECT, &reconnect); + if (reconnect) + mysql_options(d->mysql, MYSQL_OPT_RECONNECT, &reconnect); #endif + } } else { setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d)); diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 7bffb05a08..240e19bf20 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -1224,6 +1224,9 @@ QSqlRecord QSqlDatabase::record(const QString& tablename) const \li CLIENT_INTERACTIVE \li UNIX_SOCKET \li MYSQL_OPT_RECONNECT + \li MYSQL_OPT_CONNECT_TIMEOUT + \li MYSQL_OPT_READ_TIMEOUT + \li MYSQL_OPT_WRITE_TIMEOUT \endlist \li From 21c90bcc989cc18ba926cf4dbfbc9d2fce78dd63 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 17 Apr 2015 14:57:21 +0200 Subject: [PATCH 43/52] qdoc: Sanitize anchors in URLs for functions When QDoc constructs the full path to a documentation node, it must construct a clean anchor reference. Intra-page links use a different code path, so the links e.g. from Member Functions list to their detailed descriptions always work, but using the link command to link to functions with certain characters (such as 'operator==') failed because the node name was used as-is and not sanitized ('operator-eq-eq'). This change moves HtmlGenerator::cleanRef() static function to its parent class, Generator, and takes it into use in Generator::fullDocumentLocation(). Change-Id: Ic939ffa3ae0f4495ef2a30eff0d4a1de65ea3e8f Task-number: QTBUG-45629 Reviewed-by: Martin Smith --- src/tools/qdoc/generator.cpp | 57 ++++++++++++++++++++++++++++++-- src/tools/qdoc/generator.h | 1 + src/tools/qdoc/htmlgenerator.cpp | 57 ++------------------------------ src/tools/qdoc/htmlgenerator.h | 1 - 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index 2ff4df9bd7..d22ec507f6 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -419,6 +419,59 @@ QString Generator::fileName(const Node* node) const return name; } +QString Generator::cleanRef(const QString& ref) +{ + QString clean; + + if (ref.isEmpty()) + return clean; + + clean.reserve(ref.size() + 20); + const QChar c = ref[0]; + const uint u = c.unicode(); + + if ((u >= 'a' && u <= 'z') || + (u >= 'A' && u <= 'Z') || + (u >= '0' && u <= '9')) { + clean += c; + } else if (u == '~') { + clean += "dtor."; + } else if (u == '_') { + clean += "underscore."; + } else { + clean += QLatin1Char('A'); + } + + for (int i = 1; i < (int) ref.length(); i++) { + const QChar c = ref[i]; + const uint u = c.unicode(); + if ((u >= 'a' && u <= 'z') || + (u >= 'A' && u <= 'Z') || + (u >= '0' && u <= '9') || u == '-' || + u == '_' || u == ':' || u == '.') { + clean += c; + } else if (c.isSpace()) { + clean += QLatin1Char('-'); + } else if (u == '!') { + clean += "-not"; + } else if (u == '&') { + clean += "-and"; + } else if (u == '<') { + clean += "-lt"; + } else if (u == '=') { + clean += "-eq"; + } else if (u == '>') { + clean += "-gt"; + } else if (u == '#') { + clean += QLatin1Char('#'); + } else { + clean += QLatin1Char('-'); + clean += QString::number((int)u, 16); + } + } + return clean; +} + QMap& Generator::formattingLeftMap() { return fmtLeftMaps[format()]; @@ -521,10 +574,10 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir) return fullDocumentLocation(functionNode->associatedProperty()); else if (functionNode->overloadNumber() > 1) - anchorRef = QLatin1Char('#') + functionNode->name() + anchorRef = QLatin1Char('#') + cleanRef(functionNode->name()) + QLatin1Char('-') + QString::number(functionNode->overloadNumber()); else - anchorRef = QLatin1Char('#') + functionNode->name(); + anchorRef = QLatin1Char('#') + cleanRef(functionNode->name()); break; } /* diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h index 6d0de8df44..9a1672dac4 100644 --- a/src/tools/qdoc/generator.h +++ b/src/tools/qdoc/generator.h @@ -103,6 +103,7 @@ public: static bool useOutputSubdirs() { return useOutputSubdirs_; } static void setQmlTypeContext(QmlTypeNode* t) { qmlTypeContext_ = t; } static QmlTypeNode* qmlTypeContext() { return qmlTypeContext_; } + static QString cleanRef(const QString& ref); protected: virtual void beginSubPage(const InnerNode* node, const QString& fileName); diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index f0a23ac65e..710ce08abb 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -3355,7 +3355,7 @@ void HtmlGenerator::generateSectionInheritedList(const Section& section, const N out() << section.pluralMember; } out() << " inherited from " + << '#' << Generator::cleanRef(section.name.toLower()) << "\">" << protectEnc((*p).first->plainFullName(relative)) << "\n"; ++p; @@ -3610,62 +3610,9 @@ void HtmlGenerator::generateLink(const Atom* atom, CodeMarker* marker) } } -QString HtmlGenerator::cleanRef(const QString& ref) -{ - QString clean; - - if (ref.isEmpty()) - return clean; - - clean.reserve(ref.size() + 20); - const QChar c = ref[0]; - const uint u = c.unicode(); - - if ((u >= 'a' && u <= 'z') || - (u >= 'A' && u <= 'Z') || - (u >= '0' && u <= '9')) { - clean += c; - } else if (u == '~') { - clean += "dtor."; - } else if (u == '_') { - clean += "underscore."; - } else { - clean += QLatin1Char('A'); - } - - for (int i = 1; i < (int) ref.length(); i++) { - const QChar c = ref[i]; - const uint u = c.unicode(); - if ((u >= 'a' && u <= 'z') || - (u >= 'A' && u <= 'Z') || - (u >= '0' && u <= '9') || u == '-' || - u == '_' || u == ':' || u == '.') { - clean += c; - } else if (c.isSpace()) { - clean += QLatin1Char('-'); - } else if (u == '!') { - clean += "-not"; - } else if (u == '&') { - clean += "-and"; - } else if (u == '<') { - clean += "-lt"; - } else if (u == '=') { - clean += "-eq"; - } else if (u == '>') { - clean += "-gt"; - } else if (u == '#') { - clean += QLatin1Char('#'); - } else { - clean += QLatin1Char('-'); - clean += QString::number((int)u, 16); - } - } - return clean; -} - QString HtmlGenerator::registerRef(const QString& ref) { - QString clean = HtmlGenerator::cleanRef(ref); + QString clean = Generator::cleanRef(ref); for (;;) { QString& prevRef = refMap[clean.toLower()]; diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h index efd38ea104..4a2e158252 100644 --- a/src/tools/qdoc/htmlgenerator.h +++ b/src/tools/qdoc/htmlgenerator.h @@ -85,7 +85,6 @@ public: QString protectEnc(const QString &string); static QString protect(const QString &string, const QString &encoding = "ISO-8859-1"); - static QString cleanRef(const QString& ref); static QString sinceTitle(int i) { return sinceTitles[i]; } protected: From b71535a9236a33371da36d89d38872d3ae91fbf0 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 17 Apr 2015 14:32:02 +0200 Subject: [PATCH 44/52] Doc: Bring QSizeF/QPointF::isNull() documentation up to date Since Qt 5.0 (commit 09dd19df) sign is ignored when testing whether a QPointF or QSizeF is null. This updates the documentation accordingly. Change-Id: I3de1c748f3caa63b8bd8990006de5ba572eac83e Task-number: QTBUG-45669 Reviewed-by: Mitch Curtis Reviewed-by: Venugopal Shivashankar --- src/corelib/tools/qpoint.cpp | 8 ++------ src/corelib/tools/qsize.cpp | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp index dc2a2d9739..94a245375b 100644 --- a/src/corelib/tools/qpoint.cpp +++ b/src/corelib/tools/qpoint.cpp @@ -528,12 +528,8 @@ QDebug operator<<(QDebug dbg, const QPointF &p) /*! \fn bool QPointF::isNull() const - Returns \c true if both the x and y coordinates are set to +0.0; - otherwise returns \c false. - - \note Since this function treats +0.0 and -0.0 differently, points - with zero-valued coordinates where either or both values have a - negative sign are not defined to be null points. + Returns \c true if both the x and y coordinates are set to 0.0 (ignoring + the sign); otherwise returns \c false. */ diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp index 19227432f2..24a29f0213 100644 --- a/src/corelib/tools/qsize.cpp +++ b/src/corelib/tools/qsize.cpp @@ -517,12 +517,8 @@ QDebug operator<<(QDebug dbg, const QSize &s) /*! \fn bool QSizeF::isNull() const - Returns \c true if both the width and height are +0.0; otherwise returns - false. - - \note Since this function treats +0.0 and -0.0 differently, sizes with - zero width and height where either or both values have a negative - sign are not defined to be null sizes. + Returns \c true if both the width and height are 0.0 (ignoring the sign); + otherwise returns \c false. \sa isValid(), isEmpty() */ From 3e7cf5981aa536c18aee814b9f5e221c5a8a4d1a Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 15 Apr 2015 14:14:30 +0200 Subject: [PATCH 45/52] qdoc: Resolve base classes for a class declared in a namespace For classes declared in a namespace, QDoc needs to take account the fact that its base classes typically are not qualified with the namespace name if those base classes are from the same namespace. There already was code for this, but it was disabled by a macro. This change re-enables it, and adds an additional check to restart the search in valid namespaces only. Change-Id: Ia07dcb783b59de5fc9ddcfd43000a63c6c74ebe1 Reviewed-by: Martin Smith --- src/tools/qdoc/tree.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp index d0d0bcbb5a..420396e51c 100644 --- a/src/tools/qdoc/tree.cpp +++ b/src/tools/qdoc/tree.cpp @@ -388,7 +388,6 @@ void Tree::resolveInheritanceHelper(int pass, ClassNode* cn) while (b != bases.end()) { if (!(*b).node_) { Node* n = qdb_->findClassNode((*b).path_); -#if 0 /* If the node for the base class was not found, the reason might be that the subclass is in a @@ -401,9 +400,11 @@ void Tree::resolveInheritanceHelper(int pass, ClassNode* cn) */ if (!n) { InnerNode* parent = cn->parent(); - n = findClassNode((*b).path_, parent); + if (parent) + // Exclude the root namespace + if (parent->isNamespace() && !parent->name().isEmpty()) + n = findClassNode((*b).path_, parent); } -#endif if (n) { ClassNode* bcn = static_cast(n); (*b).node_ = bcn; From 291eb172e36705125d6d3d84095d7a3dce3274ce Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 21 Apr 2015 12:34:53 +0200 Subject: [PATCH 46/52] Avoid setting a swap interval for pbuffers As per GL_EXT_swap_control this results in BadWindow. Task-number: QTBUG-45705 Change-Id: Ia3e3f66f326d8f6145d82f33f964b0d6996f0959 Reviewed-by: Gunnar Sletta --- .../platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 0caec50c94..5166372364 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -481,7 +481,7 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface) success = glXMakeContextCurrent(m_display, glxDrawable, glxDrawable, m_context); } - if (success) { + if (success && surfaceClass == QSurface::Window) { int interval = surface->format().swapInterval(); QXcbScreen *screen = screenForPlatformSurface(surface); if (interval >= 0 && m_swapInterval != interval && screen) { From 411a3490fd4111c9b253d00c228e9e75f80abd87 Mon Sep 17 00:00:00 2001 From: Caroline Chao Date: Fri, 24 Apr 2015 12:48:08 +0200 Subject: [PATCH 47/52] Tests: Blacklist tst_QHostInfo::abortHostLookupInDifferentThread Remove the insignificant_test CONFIG option in favor of a BLACKLIST file. This test has been found failing on OpenSuse in CI. Change-Id: Ibc6af3c30277fec7e422e8bbeccd9437de2a61ce Task-number: QTBUG-23837 Reviewed-by: Kai Koehne Reviewed-by: Frederik Gladhorn --- tests/auto/network/kernel/qhostinfo/BLACKLIST | 3 +++ tests/auto/network/kernel/qhostinfo/qhostinfo.pro | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 tests/auto/network/kernel/qhostinfo/BLACKLIST diff --git a/tests/auto/network/kernel/qhostinfo/BLACKLIST b/tests/auto/network/kernel/qhostinfo/BLACKLIST new file mode 100644 index 0000000000..ea4b64d7c2 --- /dev/null +++ b/tests/auto/network/kernel/qhostinfo/BLACKLIST @@ -0,0 +1,3 @@ +# QTBUG-23837 +[abortHostLookupInDifferentThread] +opensuse-13.1 64bit diff --git a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro index a95a6bc2d6..4fca7950dd 100644 --- a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro +++ b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro @@ -14,5 +14,3 @@ wince*: { # needed for getaddrinfo with official MinGW mingw:DEFINES += _WIN32_WINNT=0x0501 - -linux-*:CONFIG+=insignificant_test # QTBUG-23837 - test is unstable From 3753667b2b7384277650323b35e07c877e241d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 20 Apr 2015 16:50:52 +0200 Subject: [PATCH 48/52] Android: Make foreign windows expect global coordinates. The foreign window implementation was trying to handle parent/child relationships, but it's not supported by the platform implementation and was therefore causing more problems then it was solving. E.g., even simple use cases, such as the parent moving or re-sizing its geometry would not be handle correctly. With this change the parent/child relationship is removed and the geometry of the foreign window will always expect the geometry to be in the global coordinate system. Task-number: QTBUG-43391 Change-Id: I02a1f9cb9eb9fb5ace9b7e912c523bda7c5bfd5c Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../android/qandroidplatformforeignwindow.cpp | 26 +++---------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp b/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp index ec80bf0f8c..315a0faac0 100644 --- a/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp @@ -73,19 +73,10 @@ void QAndroidPlatformForeignWindow::raise() void QAndroidPlatformForeignWindow::setGeometry(const QRect &rect) { - QWindow *parent = window()->parent(); - QRect newGeometry = rect; - - if (parent != 0) - newGeometry.moveTo(parent->mapToGlobal(rect.topLeft())); - - if (newGeometry == geometry()) - return; - - QAndroidPlatformWindow::setGeometry(newGeometry); + QAndroidPlatformWindow::setGeometry(rect); if (m_surfaceId != -1) - QtAndroid::setSurfaceGeometry(m_surfaceId, newGeometry); + QtAndroid::setSurfaceGeometry(m_surfaceId, rect); } void QAndroidPlatformForeignWindow::setVisible(bool visible) @@ -118,18 +109,7 @@ void QAndroidPlatformForeignWindow::applicationStateChanged(Qt::ApplicationState void QAndroidPlatformForeignWindow::setParent(const QPlatformWindow *window) { - QRect newGeometry = geometry(); - - if (window != 0) - newGeometry.moveTo(window->mapToGlobal(geometry().topLeft())); - - if (newGeometry != geometry()) - QAndroidPlatformWindow::setGeometry(newGeometry); - - if (m_surfaceId == -1) - return; - - QtAndroid::setSurfaceGeometry(m_surfaceId, newGeometry); + Q_UNUSED(window); } QT_END_NAMESPACE From fc08ac53a0d0c6d8a21e8372370fa7548857da37 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 21 Apr 2015 15:24:24 +0200 Subject: [PATCH 49/52] remove superfluous method re-implementation Remove a superfluous implementation of VcprojGenerator::replaceExtraCompilerVariables. The implementation in the base class is exactly the same. Use that instead. Change-Id: Ie7d995be1b0d55fbefd15ae6b7a992237d97839c Reviewed-by: Oswald Buddenhagen --- qmake/generators/win32/msvc_vcproj.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h index 3f99e02e92..35dc1e8937 100644 --- a/qmake/generators/win32/msvc_vcproj.h +++ b/qmake/generators/win32/msvc_vcproj.h @@ -76,10 +76,8 @@ protected: virtual VCProjectWriter *createProjectWriter(); virtual bool doDepends() const { return false; } //never necesary virtual void processSources() { filterIncludedFiles("SOURCES"); filterIncludedFiles("GENERATED_SOURCES"); } - using MakefileGenerator::ReplaceFor; + using Win32MakefileGenerator::replaceExtraCompilerVariables; virtual QString replaceExtraCompilerVariables(const QString &, const QStringList &, const QStringList &, ReplaceFor); - inline QString replaceExtraCompilerVariables(const QString &val, const QString &in, const QString &out, ReplaceFor forShell) - { return MakefileGenerator::replaceExtraCompilerVariables(val, in, out, forShell); } virtual bool supportsMetaBuild() { return true; } virtual bool supportsMergedBuilds() { return true; } virtual bool mergeBuildProject(MakefileGenerator *other); From d1e4ba06928f93026627d21eff61d95b6b0f49c0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 27 Apr 2015 09:48:17 +0200 Subject: [PATCH 50/52] Windows: Add "Segoe UI Emoji" and "Segoe UI Symbol" as fallback fonts. This enables rendering of Emoji symbols. Task-number: QTBUG-45811 Change-Id: I7cb128dab717870929e02ea9ec253f36fef29804 Reviewed-by: Konstantin Ritt --- src/plugins/platforms/windows/qwindowsfontdatabase.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index b979dc6c4e..28fb3b6498 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1631,6 +1631,8 @@ QStringList QWindowsFontDatabase::extraTryFontsForFamily(const QString &family) ++tf; } } + result.append(QStringLiteral("Segoe UI Emoji")); + result.append(QStringLiteral("Segoe UI Symbol")); return result; } From 2886935f96e5f817ba3d4b62dbc78bd722123c1f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 24 Apr 2015 20:33:05 +0200 Subject: [PATCH 51/52] cmake: Don't mark header-only frameworks with the FRAMEWORK property. CMake INTERFACE targets may only have whitelisted properties, and FRAMEWORK is not in the whitelist in released CMake versions. Change-Id: I27cd0cfbe1b52f25c91bf1b3c0d55879bed91bdf Reviewed-by: Oswald Buddenhagen Reviewed-by: Stephen Kelly --- mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in index 0befa803a5..d2358cae4b 100644 --- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in +++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in @@ -232,9 +232,11 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) add_library(Qt5::$${CMAKE_MODULE_NAME} SHARED IMPORTED) !!ENDIF !!ENDIF +!!IF !equals(TEMPLATE, aux) !!IF !isEmpty(CMAKE_BUILD_IS_FRAMEWORK) set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY FRAMEWORK 1) !!ENDIF +!!ENDIF // TEMPLATE != aux set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS}) From 0635b1a69dd666f5eed4b096895bd80b1a9420ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Ca=C5=82usi=C5=84ski?= Date: Fri, 24 Apr 2015 11:26:01 +0200 Subject: [PATCH 52/52] Moc: test if superclass list is not empty before accessing first() Accessing QList().first() with an empty superclassList caused assertion fail. Added check to fix it. Change-Id: I1aff35e0d267fc0e670beadba1bd196b175a4da8 Co-authored-with: Olivier Goffart Task-number: QTBUG-45790 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/tools/moc/moc.cpp | 3 ++- tests/auto/tools/moc/tst_moc.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index a9e33da01d..7300429fe0 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -140,7 +140,8 @@ bool Moc::parseClassHead(ClassDef *def) } } while (test(COMMA)); - if (knownGadgets.contains(def->superclassList.first().first)) { + if (!def->superclassList.isEmpty() + && knownGadgets.contains(def->superclassList.first().first)) { // Q_GADGET subclasses are treated as Q_GADGETs knownGadgets.insert(def->classname, def->qualified); knownGadgets.insert(def->qualified, def->qualified); diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 08dc9581e1..00e5c60b29 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -83,6 +83,10 @@ QT_USE_NAMESPACE template struct QTBUG_31218 {}; struct QTBUG_31218_Derived : QTBUG_31218<-1<0> {}; +#if defined(Q_MOC_RUN) + class QTBUG_45790 : Bug() { }; +#endif + struct MyStruct {}; struct MyStruct2 {};