From 4ccfb1eb926e8a6b26ea11e3e38df5b2dd3d0de4 Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Sat, 12 Mar 2016 10:33:19 +0100 Subject: Fix tests for build with -no-gui Change-Id: I48d5452daeaf3490ed7a5b8c30953da019bb33af Reviewed-by: Oswald Buddenhagen Reviewed-by: Kevin Funk --- tests/auto/auto.pro | 2 +- tests/auto/other/other.pro | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 9cab3c9e42..cc916edbad 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -24,7 +24,7 @@ ios: SUBDIRS = corelib gui wince: SUBDIRS -= printsupport cross_compile: SUBDIRS -= tools !qtHaveModule(opengl): SUBDIRS -= opengl -!qtHaveModule(gui): SUBDIRS -= gui cmake +!qtHaveModule(gui): SUBDIRS -= gui cmake installed_cmake !qtHaveModule(widgets): SUBDIRS -= widgets !qtHaveModule(printsupport): SUBDIRS -= printsupport !qtHaveModule(concurrent): SUBDIRS -= concurrent diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro index 673e922fdd..0e9f054a01 100644 --- a/tests/auto/other/other.pro +++ b/tests/auto/other/other.pro @@ -24,6 +24,10 @@ SUBDIRS=\ windowsmobile \ toolsupport \ +!qtHaveModule(gui): SUBDIRS -= \ + qcomplextext \ + qprocess_and_guieventloop \ + !qtHaveModule(widgets): SUBDIRS -= \ gestures \ lancelot \ -- cgit v1.2.3 From 1bbbb682b56df0a212dc5a7e249fa3b630111a10 Mon Sep 17 00:00:00 2001 From: Marko Kangas Date: Tue, 22 Mar 2016 12:47:11 +0200 Subject: Initialize input method for read-only QTextBrowser Set input method attribute to be aligned with read-only value in QTextBrowser initialization Task-number: QTBUG-52071 Change-Id: If0e64bf09e2a2d505ed66fcbfb8cd12ae39844d3 Reviewed-by: Andy Shaw --- src/widgets/widgets/qtextbrowser.cpp | 1 + tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/widgets/widgets/qtextbrowser.cpp b/src/widgets/widgets/qtextbrowser.cpp index 2c073342b0..206667c651 100644 --- a/src/widgets/widgets/qtextbrowser.cpp +++ b/src/widgets/widgets/qtextbrowser.cpp @@ -653,6 +653,7 @@ void QTextBrowserPrivate::init() #ifndef QT_NO_CURSOR viewport->setCursor(oldCursor); #endif + q->setAttribute(Qt::WA_InputMethodEnabled, !q->isReadOnly()); q->setUndoRedoEnabled(false); viewport->setMouseTracking(true); QObject::connect(q->document(), SIGNAL(contentsChanged()), q, SLOT(_q_documentModified())); diff --git a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp index adc768f828..8c9e908228 100644 --- a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp +++ b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp @@ -92,6 +92,7 @@ private slots: void clearHistory(); void sourceInsideLoadResource(); void textInteractionFlags_vs_readOnly(); + void inputMethodAttribute_vs_readOnly(); void anchorsWithSelfBuiltHtml(); void relativeNonLocalUrls(); void adjacentAnchors(); @@ -455,6 +456,16 @@ void tst_QTextBrowser::textInteractionFlags_vs_readOnly() QCOMPARE(browser->textInteractionFlags(), Qt::TextBrowserInteraction); } +void tst_QTextBrowser::inputMethodAttribute_vs_readOnly() +{ + QVERIFY(browser->isReadOnly()); + QVERIFY(!browser->testAttribute(Qt::WA_InputMethodEnabled)); + browser->setReadOnly(false); + QVERIFY(browser->testAttribute(Qt::WA_InputMethodEnabled)); + browser->setReadOnly(true); + QVERIFY(!browser->testAttribute(Qt::WA_InputMethodEnabled)); +} + void tst_QTextBrowser::anchorsWithSelfBuiltHtml() { browser->setHtml("

Hello Link" -- cgit v1.2.3 From 7565b734342facf9a848aced2d8f2a006a99f5a0 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 21 Mar 2016 14:45:14 +0100 Subject: winrt: Enable windeployqt by default for Visual Studio projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using Visual Studio a user very seldom wants to disable the automatic invocation of windeployqt. Hence switch from opt-in behavior to opt-out. This also fixes first user experience to invoke qmake –tp vc and then hit run on examples. [ChangeLog][Platform Specific Changes][qmake] qmake-generated Visual Studio projects now automatically invoke windeployqt by default. Task-number: QTBUG-52008 Change-Id: Iee1607269c38c7f6c726f554978ac05477bebe5e Reviewed-by: Oswald Buddenhagen --- mkspecs/features/winrt/default_pre.prf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkspecs/features/winrt/default_pre.prf b/mkspecs/features/winrt/default_pre.prf index 44e3c94b8a..8299950d8b 100644 --- a/mkspecs/features/winrt/default_pre.prf +++ b/mkspecs/features/winrt/default_pre.prf @@ -9,4 +9,6 @@ QMAKE_LIBS = ucrt.lib $$QMAKE_LIBS } +equals(TEMPLATE, "vcapp"): CONFIG += windeployqt + load(default_pre) -- cgit v1.2.3 From d3d78c81754f2737b7686c8989460105a0a0c0e7 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 18 Mar 2016 08:45:27 +0100 Subject: configure: Appending compiler and linker flags... ...instead of overwriting when building qmake for windows. Change-Id: I89eb33439b03a0ad33d006d12c9896c87d271c4f Reviewed-by: Oswald Buddenhagen --- configure | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 8d7772ac5b..1cafa98c3b 100755 --- a/configure +++ b/configure @@ -4042,8 +4042,8 @@ if true; then ###[ '!' -f "$outpath/bin/qmake" ]; done fi if [ "$BUILD_ON_MSYS" = "yes" ]; then - EXTRA_CFLAGS="-DUNICODE" - EXTRA_CXXFLAGS="-DUNICODE" + EXTRA_CFLAGS="$EXTRA_CFLAGS -DUNICODE" + EXTRA_CXXFLAGS="$EXTRA_CXXFLAGS -DUNICODE" EXTRA_OBJS="qfilesystemengine_win.o \ qfilesystemiterator_win.o \ qfsfileengine_win.o \ @@ -4058,7 +4058,7 @@ if true; then ###[ '!' -f "$outpath/bin/qmake" ]; \"\$(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp\" \ \"\$(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp\" \ \"\$(SOURCE_PATH)/tools/shared/windows/registry.cpp\"" - EXTRA_LFLAGS="-static -s -lole32 -luuid -ladvapi32 -lkernel32" + EXTRA_LFLAGS="$EXTRA_LFLAGS -static -s -lole32 -luuid -ladvapi32 -lkernel32" EXEEXT=".exe" else EXTRA_OBJS="qfilesystemengine_unix.o \ -- cgit v1.2.3 From c5e6f7d57208c04715dbc00b03e4e4a49f145ca6 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 23 Mar 2016 09:39:21 +0100 Subject: Hide mixed comparisons with QT_RESTRICTED_CAST_FROM_ASCII While the implementation of the QByteArray::operatorX(const QString &s2) for X \in { ==, !=, <, <=, >, >=} was already inavailable when QT_RESTRICTED_CAST_FROM_ASCII was defined, the declaration was still visible, leading effectively to a linking error. This change hides the declaration, too, creating a compiler error as intended, and as present with the QString::operatorX(const QByteArray &s2) functions. Change-Id: Ifdb0b85b7423b3b9c69212639b1512b0808a7983 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qbytearray.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index f0032227e8..eb826bae4e 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -327,7 +327,7 @@ public: QT_ASCII_CAST_WARN int indexOf(const QString &s, int from = 0) const; QT_ASCII_CAST_WARN int lastIndexOf(const QString &s, int from = -1) const; #endif -#ifndef QT_NO_CAST_FROM_ASCII +#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) inline QT_ASCII_CAST_WARN bool operator==(const QString &s2) const; inline QT_ASCII_CAST_WARN bool operator!=(const QString &s2) const; inline QT_ASCII_CAST_WARN bool operator<(const QString &s2) const; -- cgit v1.2.3 From 282cf63554fa55b43147f6377525ad990b14ec56 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Wed, 23 Mar 2016 12:25:39 +0300 Subject: QtActivity.java: fix typo Replace QtApplication.onKeyDown with QtApplication.onKeyUp Task-number: QTBUG-42204 Change-Id: I458dce23ca22fe381fcaebc94a1edab91f69a57f Reviewed-by: BogDan Vatra --- src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java index f370b4f667..9fc903af8e 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -1067,7 +1067,7 @@ public class QtActivity extends Activity @Override public boolean onKeyUp(int keyCode, KeyEvent event) { - if (QtApplication.m_delegateObject != null && QtApplication.onKeyDown != null) + if (QtApplication.m_delegateObject != null && QtApplication.onKeyUp != null) return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyUp, keyCode, event); else return super.onKeyUp(keyCode, event); -- cgit v1.2.3 From 2119b86db25fac3165c562f9d40e5874de824c80 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 7 Mar 2016 16:29:31 +0100 Subject: QRawFont: fix UB in supportedWritingSystems() Found by UBSan: src/gui/text/qrawfont.cpp:647:55: runtime error: load of misaligned address 0x000001eeed26 for type 'quint32', which requires 4 byte alignment src/gui/text/qrawfont.cpp:648:50: runtime error: load of misaligned address 0x000001eeed02 for type 'quint32', which requires 4 byte alignment Fix by using the qFromBigEndian() overload that can read from unaligned memory. While touching the code, also disentangle the two loops so that operations are now performed in memory order instead of inter- leaved, use less magic numbers, and avoid a QByteArray detach. Change-Id: I26fa39726f6fa2e957b60863fa160280cf1dc9ac Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Konstantin Ritt --- src/gui/text/qrawfont.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index 59f13581dd..5d4044b096 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -627,18 +627,18 @@ QList QRawFont::supportedWritingSystems() const if (d->isValid()) { QByteArray os2Table = fontTable("OS/2"); if (os2Table.size() > 86) { - char *data = os2Table.data(); - quint32 *bigEndianUnicodeRanges = reinterpret_cast(data + 42); - quint32 *bigEndianCodepageRanges = reinterpret_cast(data + 78); + const uchar * const data = reinterpret_cast(os2Table.constData()); + const uchar * const bigEndianUnicodeRanges = data + 42; + const uchar * const bigEndianCodepageRanges = data + 78; quint32 unicodeRanges[4]; quint32 codepageRanges[2]; - for (int i=0; i<4; ++i) { - if (i < 2) - codepageRanges[i] = qFromBigEndian(bigEndianCodepageRanges[i]); - unicodeRanges[i] = qFromBigEndian(bigEndianUnicodeRanges[i]); - } + for (size_t i = 0; i < sizeof unicodeRanges / sizeof *unicodeRanges; ++i) + unicodeRanges[i] = qFromBigEndian(bigEndianUnicodeRanges + i * sizeof(quint32)); + + for (size_t i = 0; i < sizeof codepageRanges / sizeof *codepageRanges; ++i) + codepageRanges[i] = qFromBigEndian(bigEndianCodepageRanges + i * sizeof(quint32)); QSupportedWritingSystems ws = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRanges, codepageRanges); for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { -- cgit v1.2.3 From fce83bd9f84883f93829e6ca9eacf098b018a02d Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 22 Mar 2016 11:59:56 +0100 Subject: QAbstractItemView: trigger handlers (and redraw) when changing selection model The most visible problem is that changing selection model didn't update() the view, resulting in the old selection/current item still being drawn. In general trigger the handlers for when the selection/current item changes. Change-Id: Ib3b2ad70412e6a21a182d4c173e617710bcc630d Task-number: QTBUG-50535 Reviewed-by: Stephen Kelly --- src/widgets/itemviews/qabstractitemview.cpp | 9 ++++ .../qabstractitemview/tst_qabstractitemview.cpp | 54 ++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index a126fef65e..251b09ce7d 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -765,7 +765,13 @@ void QAbstractItemView::setSelectionModel(QItemSelectionModel *selectionModel) return; } + QItemSelection oldSelection; + QModelIndex oldCurrentIndex; + if (d->selectionModel) { + oldSelection = d->selectionModel->selection(); + oldCurrentIndex = d->selectionModel->currentIndex(); + disconnect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged(QItemSelection,QItemSelection))); disconnect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), @@ -779,6 +785,9 @@ void QAbstractItemView::setSelectionModel(QItemSelectionModel *selectionModel) this, SLOT(selectionChanged(QItemSelection,QItemSelection))); connect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(currentChanged(QModelIndex,QModelIndex))); + + selectionChanged(d->selectionModel->selection(), oldSelection); + currentChanged(d->selectionModel->currentIndex(), oldCurrentIndex); } } diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 3a17f7c690..2b2f130060 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -251,6 +252,7 @@ private slots: void sizeHintChangeTriggersLayout(); void shiftSelectionAfterChangingModelContents(); void QTBUG48968_reentrant_updateEditorGeometries(); + void QTBUG50535_update_on_new_selection_model(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -2028,5 +2030,57 @@ void tst_QAbstractItemView::QTBUG48968_reentrant_updateEditorGeometries() // No crash, all fine. } +void tst_QAbstractItemView::QTBUG50535_update_on_new_selection_model() +{ + QStandardItemModel model; + for (int i = 0; i < 10; ++i) + model.appendRow(new QStandardItem(QStringLiteral("%1").arg(i))); + + class ListView : public QListView + { + public: + ListView() + : m_paintEventsCount(0) + { + } + + int m_paintEventsCount; + + protected: + bool viewportEvent(QEvent *event) Q_DECL_OVERRIDE + { + if (event->type() == QEvent::Paint) + ++m_paintEventsCount; + return QListView::viewportEvent(event); + } + }; + + // keep the current/selected row in the "low range", i.e. be sure it's visible, otherwise we + // don't get updates and the test fails. + + ListView view; + view.setModel(&model); + view.selectionModel()->setCurrentIndex(model.index(1, 0), QItemSelectionModel::SelectCurrent); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + + QItemSelectionModel selectionModel(&model); + selectionModel.setCurrentIndex(model.index(2, 0), QItemSelectionModel::Current); + + int oldPaintEventsCount = view.m_paintEventsCount; + view.setSelectionModel(&selectionModel); + QTRY_VERIFY(view.m_paintEventsCount > oldPaintEventsCount); + + + QItemSelectionModel selectionModel2(&model); + selectionModel2.select(model.index(0, 0), QItemSelectionModel::ClearAndSelect); + selectionModel2.setCurrentIndex(model.index(1, 0), QItemSelectionModel::Current); + + oldPaintEventsCount = view.m_paintEventsCount; + view.setSelectionModel(&selectionModel2); + QTRY_VERIFY(view.m_paintEventsCount > oldPaintEventsCount); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" -- cgit v1.2.3 From 060e0f6628fd185994911307c59f5355acaaf18f Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 7 Mar 2016 14:34:40 -0800 Subject: minimal QPA plugin: Use fontconfig DB if available This makes minimal a bit more useful for apps needing to access QFonts from non-UI environments. Change-Id: Idc5ca13f0c385ab9b4258e11fea7ec886515eea4 Reviewed-by: Friedemann Kleint Reviewed-by: Louai Al-Khanji --- src/plugins/platforms/minimal/minimal.pro | 2 ++ .../platforms/minimal/qminimalintegration.cpp | 25 ++++++++++++++++------ .../platforms/minimal/qminimalintegration.h | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/minimal/minimal.pro b/src/plugins/platforms/minimal/minimal.pro index d6914026ae..0d31d6605b 100644 --- a/src/plugins/platforms/minimal/minimal.pro +++ b/src/plugins/platforms/minimal/minimal.pro @@ -10,6 +10,8 @@ HEADERS = qminimalintegration.h \ OTHER_FILES += minimal.json +CONFIG += qpa/genericunixfontdatabase + PLUGIN_TYPE = platforms PLUGIN_CLASS_NAME = QMinimalIntegrationPlugin !equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp index 45301f4caf..ac819b9282 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.cpp +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -37,7 +37,14 @@ #include #include #include + +#if defined(Q_OS_WIN) +#include +#elif defined(QT_NO_FONTCONFIG) #include +#else +#include +#endif #if !defined(Q_OS_WIN) #include @@ -62,7 +69,7 @@ static inline unsigned parseOptions(const QStringList ¶mList) } QMinimalIntegration::QMinimalIntegration(const QStringList ¶meters) - : m_dummyFontDatabase(0) + : m_fontDatabase(0) , m_options(parseOptions(parameters)) { if (qEnvironmentVariableIsSet(debugBackingStoreEnvironmentVariable) @@ -81,7 +88,7 @@ QMinimalIntegration::QMinimalIntegration(const QStringList ¶meters) QMinimalIntegration::~QMinimalIntegration() { - delete m_dummyFontDatabase; + delete m_fontDatabase; } bool QMinimalIntegration::hasCapability(QPlatformIntegration::Capability cap) const @@ -104,11 +111,17 @@ public: QPlatformFontDatabase *QMinimalIntegration::fontDatabase() const { - if (m_options & EnableFonts) + if (m_options & EnableFonts) { +#ifndef QT_NO_FONTCONFIG + if (!m_fontDatabase) + m_fontDatabase = new QGenericUnixFontDatabase; +#else return QPlatformIntegration::fontDatabase(); - if (!m_dummyFontDatabase) - m_dummyFontDatabase = new DummyFontDatabase; - return m_dummyFontDatabase; +#endif + } + if (!m_fontDatabase) + m_fontDatabase = new DummyFontDatabase; + return m_fontDatabase; } QPlatformWindow *QMinimalIntegration::createPlatformWindow(QWindow *window) const diff --git a/src/plugins/platforms/minimal/qminimalintegration.h b/src/plugins/platforms/minimal/qminimalintegration.h index eb7d81dc6d..672fecfae0 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.h +++ b/src/plugins/platforms/minimal/qminimalintegration.h @@ -79,7 +79,7 @@ public: static QMinimalIntegration *instance(); private: - mutable QPlatformFontDatabase *m_dummyFontDatabase; + mutable QPlatformFontDatabase *m_fontDatabase; unsigned m_options; }; -- cgit v1.2.3 From 4ca77851612a1b89f3e403db356641f3919304fd Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 22 Mar 2016 15:53:36 +0100 Subject: QAbstractItemView test: check that the selection model is in sync with the view Change-Id: Ifca91154b47184a9d9a1979e1fba471517e16698 Reviewed-by: Stephen Kelly --- .../qabstractitemview/tst_qabstractitemview.cpp | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 2b2f130060..6cbf51efd9 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -253,6 +253,7 @@ private slots: void shiftSelectionAfterChangingModelContents(); void QTBUG48968_reentrant_updateEditorGeometries(); void QTBUG50535_update_on_new_selection_model(); + void testSelectionModelInSyncWithView(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -2082,5 +2083,59 @@ void tst_QAbstractItemView::QTBUG50535_update_on_new_selection_model() QTRY_VERIFY(view.m_paintEventsCount > oldPaintEventsCount); } +void tst_QAbstractItemView::testSelectionModelInSyncWithView() +{ + QStandardItemModel model; + for (int i = 0; i < 10; ++i) + model.appendRow(new QStandardItem(QStringLiteral("%1").arg(i))); + + class ListView : public QListView + { + public: + using QListView::selectedIndexes; + }; + + ListView view; + QVERIFY(!view.selectionModel()); + + view.setModel(&model); + QVERIFY(view.selectionModel()); + QVERIFY(view.selectedIndexes().isEmpty()); + QVERIFY(view.selectionModel()->selection().isEmpty()); + + view.setCurrentIndex(model.index(0, 0)); + QCOMPARE(view.currentIndex(), model.index(0, 0)); + QCOMPARE(view.selectionModel()->currentIndex(), model.index(0, 0)); + + view.selectionModel()->setCurrentIndex(model.index(1, 0), QItemSelectionModel::SelectCurrent); + QCOMPARE(view.currentIndex(), model.index(1, 0)); + QCOMPARE(view.selectedIndexes(), QModelIndexList() << model.index(1, 0)); + QCOMPARE(view.selectionModel()->currentIndex(), model.index(1, 0)); + QCOMPARE(view.selectionModel()->selection().indexes(), QModelIndexList() << model.index(1, 0)); + + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QItemSelectionModel selectionModel(&model); + selectionModel.setCurrentIndex(model.index(2, 0), QItemSelectionModel::Current); + + view.setSelectionModel(&selectionModel); + QCOMPARE(view.currentIndex(), model.index(2, 0)); + QCOMPARE(view.selectedIndexes(), QModelIndexList()); + QCOMPARE(view.selectionModel()->currentIndex(), model.index(2, 0)); + QCOMPARE(view.selectionModel()->selection().indexes(), QModelIndexList()); + + + QItemSelectionModel selectionModel2(&model); + selectionModel2.select(model.index(0, 0), QItemSelectionModel::ClearAndSelect); + selectionModel2.setCurrentIndex(model.index(1, 0), QItemSelectionModel::Current); + + view.setSelectionModel(&selectionModel2); + QCOMPARE(view.currentIndex(), model.index(1, 0)); + QCOMPARE(view.selectedIndexes(), QModelIndexList() << model.index(0, 0)); + QCOMPARE(view.selectionModel()->currentIndex(), model.index(1, 0)); + QCOMPARE(view.selectionModel()->selection().indexes(), QModelIndexList() << model.index(0, 0)); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" -- cgit v1.2.3 From b7022d782abded800e6759ce91bcd13d22ed4854 Mon Sep 17 00:00:00 2001 From: Marko Kangas Date: Wed, 15 Apr 2015 16:29:54 +0300 Subject: Fix Fusion style combobox dirty lines in HiDPI mode. Tuned combobox item highlight outline to avoid dirty lines when painting in HiDPI mode. Task-number: QTBUG-45600 Change-Id: I3c4aab91b2d32733bd2561424052034a3d9c26a3 Reviewed-by: Marko Kangas Reviewed-by: Kai Koehne --- src/widgets/styles/qfusionstyle.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index e4302247f5..8405b5ce97 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -1536,13 +1536,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio QRect r = option->rect; painter->fillRect(r, highlight); painter->setPen(QPen(highlightOutline)); - const QLine lines[4] = { - QLine(QPoint(r.left() + 1, r.bottom()), QPoint(r.right() - 1, r.bottom())), - QLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top())), - QLine(QPoint(r.left(), r.top()), QPoint(r.left(), r.bottom())), - QLine(QPoint(r.right() , r.top()), QPoint(r.right(), r.bottom())), - }; - painter->drawLines(lines, 4); + painter->drawRect(QRectF(r).adjusted(0.5, 0.5, -0.5, -0.5)); } bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable; bool checked = menuItem->checked; -- cgit v1.2.3 From f75d950bd4353c436f9863d06af65b6cbc672c76 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 Mar 2016 11:04:06 +0100 Subject: Fix typo in QLocalServer documentation Change-Id: Iceababb1e137c2363ee8a75476ecb4f5dba53b28 Reviewed-by: Oswald Buddenhagen --- src/network/socket/qlocalserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp index 0f49cb986e..1c60cba903 100644 --- a/src/network/socket/qlocalserver.cpp +++ b/src/network/socket/qlocalserver.cpp @@ -178,7 +178,7 @@ QLocalServer::SocketOptions QLocalServer::socketOptions() const /*! Stop listening for incoming connections. Existing connections are not - effected, but any new connections will be refused. + affected, but any new connections will be refused. \sa isListening(), listen() */ -- cgit v1.2.3 From 24411e9743735d6323f1d3686f8b989a5122f83b Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 23 Mar 2016 15:45:12 +0100 Subject: Add a write buffer to QLocalSocket/Win Commit 0307c008 removed the buffering of data-to-be-written from QWindowsPipeWriter, because it was assumed that users of this class (QProcess and QLocalSocket) already buffer data internally. This assumption was wrong for QLocalSocket. The following sequence localSocket->write(someData); localSocket->write(someMoreData); would not write anything on the second write. Add a write buffer to the Windows implementation of QLocalSocket. Task-number: QTBUG-52073 Change-Id: I6d0f03a722ec48138cbde3e2f69aae7dafe790d3 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qwindowspipewriter_p.h | 1 + src/network/socket/qlocalsocket.h | 2 +- src/network/socket/qlocalsocket_p.h | 5 ++- src/network/socket/qlocalsocket_win.cpp | 48 ++++++++++++++++------ .../socket/qlocalsocket/tst_qlocalsocket.cpp | 20 +++++++-- 5 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h index 808d303262..a78ab61adf 100644 --- a/src/corelib/io/qwindowspipewriter_p.h +++ b/src/corelib/io/qwindowspipewriter_p.h @@ -109,6 +109,7 @@ public: qint64 write(const char *data, qint64 maxlen); void stop(); bool waitForWrite(int msecs); + bool isWriteOperationActive() const { return writeSequenceStarted; } qint64 bytesToWrite() const; Q_SIGNALS: diff --git a/src/network/socket/qlocalsocket.h b/src/network/socket/qlocalsocket.h index 4b39a7c562..09828c8b0d 100644 --- a/src/network/socket/qlocalsocket.h +++ b/src/network/socket/qlocalsocket.h @@ -124,7 +124,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QAbstractSocket::SocketState)) Q_PRIVATE_SLOT(d_func(), void _q_error(QAbstractSocket::SocketError)) #elif defined(Q_OS_WIN) - Q_PRIVATE_SLOT(d_func(), void _q_canWrite()) + Q_PRIVATE_SLOT(d_func(), void _q_bytesWritten(qint64)) Q_PRIVATE_SLOT(d_func(), void _q_pipeClosed()) Q_PRIVATE_SLOT(d_func(), void _q_winError(ulong, const QString &)) #else diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index 46c93c01f7..a594605ae0 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -55,6 +55,7 @@ #if defined(QT_LOCALSOCKET_TCP) # include "qtcpsocket.h" #elif defined(Q_OS_WIN) +# include # include "private/qwindowspipereader_p.h" # include "private/qwindowspipewriter_p.h" # include @@ -123,10 +124,12 @@ public: ~QLocalSocketPrivate(); void destroyPipeHandles(); void setErrorString(const QString &function); - void _q_canWrite(); + void startNextWrite(); + void _q_bytesWritten(qint64 bytes); void _q_pipeClosed(); void _q_winError(ulong windowsError, const QString &function); HANDLE handle; + QRingBuffer writeBuffer; QWindowsPipeWriter *pipeWriter; QWindowsPipeReader *pipeReader; QLocalSocket::LocalSocketError error; diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 03ad2b6654..d477de9c47 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -207,15 +207,21 @@ qint64 QLocalSocket::readData(char *data, qint64 maxSize) } } -qint64 QLocalSocket::writeData(const char *data, qint64 maxSize) +qint64 QLocalSocket::writeData(const char *data, qint64 len) { Q_D(QLocalSocket); + if (len == 0) + return 0; + char *dest = d->writeBuffer.reserve(len); + memcpy(dest, data, len); if (!d->pipeWriter) { d->pipeWriter = new QWindowsPipeWriter(d->handle, this); - connect(d->pipeWriter, SIGNAL(canWrite()), this, SLOT(_q_canWrite())); - connect(d->pipeWriter, SIGNAL(bytesWritten(qint64)), this, SIGNAL(bytesWritten(qint64))); + QObjectPrivate::connect(d->pipeWriter, &QWindowsPipeWriter::bytesWritten, + d, &QLocalSocketPrivate::_q_bytesWritten); } - return d->pipeWriter->write(data, maxSize); + if (!d->pipeWriter->isWriteOperationActive()) + d->startNextWrite(); + return len; } void QLocalSocket::abort() @@ -224,6 +230,7 @@ void QLocalSocket::abort() if (d->pipeWriter) { delete d->pipeWriter; d->pipeWriter = 0; + d->writeBuffer.clear(); } close(); } @@ -266,7 +273,7 @@ qint64 QLocalSocket::bytesAvailable() const qint64 QLocalSocket::bytesToWrite() const { Q_D(const QLocalSocket); - return (d->pipeWriter) ? d->pipeWriter->bytesToWrite() : 0; + return d->writeBuffer.size(); } bool QLocalSocket::canReadLine() const @@ -298,9 +305,12 @@ void QLocalSocket::close() bool QLocalSocket::flush() { Q_D(QLocalSocket); - if (d->pipeWriter) - return d->pipeWriter->waitForWrite(0); - return false; + bool written = false; + if (d->pipeWriter) { + while (d->pipeWriter->waitForWrite(0)) + written = true; + } + return written; } void QLocalSocket::disconnectFromServer() @@ -313,10 +323,11 @@ void QLocalSocket::disconnectFromServer() // It must be destroyed before close() to prevent an infinite loop. delete d->pipeWriter; d->pipeWriter = 0; + d->writeBuffer.clear(); } flush(); - if (d->pipeWriter && d->pipeWriter->bytesToWrite() != 0) { + if (bytesToWrite() != 0) { d->state = QLocalSocket::ClosingState; emit stateChanged(d->state); } else { @@ -345,11 +356,24 @@ bool QLocalSocket::setSocketDescriptor(qintptr socketDescriptor, return true; } -void QLocalSocketPrivate::_q_canWrite() +void QLocalSocketPrivate::startNextWrite() +{ + Q_Q(QLocalSocket); + if (writeBuffer.isEmpty()) { + if (state == QLocalSocket::ClosingState) + q->close(); + } else { + Q_ASSERT(pipeWriter); + pipeWriter->write(writeBuffer.readPointer(), writeBuffer.nextDataBlockSize()); + } +} + +void QLocalSocketPrivate::_q_bytesWritten(qint64 bytes) { Q_Q(QLocalSocket); - if (state == QLocalSocket::ClosingState) - q->close(); + writeBuffer.free(bytes); + startNextWrite(); + emit q->bytesWritten(bytes); } qintptr QLocalSocket::socketDescriptor() const diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp index d12a6b53c3..bfe43673d2 100644 --- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp @@ -102,7 +102,10 @@ private slots: void multiConnect(); void writeOnlySocket(); + + void writeToClientAndDisconnect_data(); void writeToClientAndDisconnect(); + void debug(); void bytesWrittenSignal(); void syncDisconnectNotify(); @@ -1034,8 +1037,16 @@ void tst_QLocalSocket::writeOnlySocket() QCOMPARE(client.state(), QLocalSocket::ConnectedState); } +void tst_QLocalSocket::writeToClientAndDisconnect_data() +{ + QTest::addColumn("chunks"); + QTest::newRow("one chunk") << 1; + QTest::newRow("several chunks") << 20; +} + void tst_QLocalSocket::writeToClientAndDisconnect() { + QFETCH(int, chunks); QLocalServer server; QLocalSocket client; QSignalSpy readChannelFinishedSpy(&client, SIGNAL(readChannelFinished())); @@ -1049,14 +1060,17 @@ void tst_QLocalSocket::writeToClientAndDisconnect() char buffer[100]; memset(buffer, 0, sizeof(buffer)); - QCOMPARE(clientSocket->write(buffer, sizeof(buffer)), (qint64)sizeof(buffer)); - clientSocket->waitForBytesWritten(); + for (int i = 0; i < chunks; ++i) + QCOMPARE(clientSocket->write(buffer, sizeof(buffer)), qint64(sizeof(buffer))); + while (clientSocket->bytesToWrite()) + QVERIFY(clientSocket->waitForBytesWritten()); clientSocket->close(); server.close(); client.waitForDisconnected(); QCOMPARE(readChannelFinishedSpy.count(), 1); - QCOMPARE(client.read(buffer, sizeof(buffer)), (qint64)sizeof(buffer)); + const QByteArray received = client.readAll(); + QCOMPARE(received.size(), qint64(sizeof(buffer) * chunks)); QCOMPARE(client.state(), QLocalSocket::UnconnectedState); } -- cgit v1.2.3 From aedda12ef1a2a9945d32afbc7e46f21773aed223 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 9 Mar 2016 16:22:35 +0100 Subject: tst_QAtomicInteger: fix UBs (signed overflow) Drop addSub() test. It executes exactly the union of fetchAndAdd() and fetchAndSub(), which have already had their UBs fixed. No need to do fixes in duplicated code. Change-Id: Ib72caab0310fce3ff9a40c261d8a38518f91ecaf Reviewed-by: David Faure --- .../thread/qatomicinteger/tst_qatomicinteger.cpp | 93 ---------------------- 1 file changed, 93 deletions(-) diff --git a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp index ff41ccf26b..6b3a99100b 100644 --- a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp +++ b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp @@ -179,9 +179,6 @@ private Q_SLOTS: void fetchAndSub_data() { addData(); } void fetchAndSub(); - void addSub_data() { addData(); } - void addSub(); - void fetchAndOr_data() { addData(); } void fetchAndOr(); @@ -661,96 +658,6 @@ void tst_QAtomicIntegerXX::fetchAndSub() } } -void tst_QAtomicIntegerXX::addSub() -{ - QFETCH(LargeInt, value); - QAtomicInteger atomic(value); - - // note: this test has undefined behavior for signed max and min - T parcel1 = 42; - T parcel2 = T(0-parcel1); - T newValue1 = T(value) + parcel1; - T newValue2 = T(value) - parcel1; - - QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), T(value)); - QCOMPARE(atomic.load(), newValue1); - QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), newValue1); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), T(value)); - QCOMPARE(atomic.load(), newValue2); - QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), newValue2); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), T(value)); - QCOMPARE(atomic.load(), newValue2); - QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), newValue2); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), T(value)); - QCOMPARE(atomic.load(), newValue1); - QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), newValue1); - QCOMPARE(atomic.load(), T(value)); - - QCOMPARE(atomic.fetchAndAddAcquire(parcel1), T(value)); - QCOMPARE(atomic.load(), newValue1); - QCOMPARE(atomic.fetchAndSubAcquire(parcel1), newValue1); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndSubAcquire(parcel1), T(value)); - QCOMPARE(atomic.load(), newValue2); - QCOMPARE(atomic.fetchAndAddAcquire(parcel1), newValue2); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndAddAcquire(parcel2), T(value)); - QCOMPARE(atomic.load(), newValue2); - QCOMPARE(atomic.fetchAndSubAcquire(parcel2), newValue2); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndSubAcquire(parcel2), T(value)); - QCOMPARE(atomic.load(), newValue1); - QCOMPARE(atomic.fetchAndAddAcquire(parcel2), newValue1); - QCOMPARE(atomic.load(), T(value)); - - QCOMPARE(atomic.fetchAndAddRelease(parcel1), T(value)); - QCOMPARE(atomic.load(), newValue1); - QCOMPARE(atomic.fetchAndSubRelease(parcel1), newValue1); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndSubRelease(parcel1), T(value)); - QCOMPARE(atomic.load(), newValue2); - QCOMPARE(atomic.fetchAndAddRelease(parcel1), newValue2); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndAddRelease(parcel2), T(value)); - QCOMPARE(atomic.load(), newValue2); - QCOMPARE(atomic.fetchAndSubRelease(parcel2), newValue2); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndSubRelease(parcel2), T(value)); - QCOMPARE(atomic.load(), newValue1); - QCOMPARE(atomic.fetchAndAddRelease(parcel2), newValue1); - QCOMPARE(atomic.load(), T(value)); - - QCOMPARE(atomic.fetchAndAddOrdered(parcel1), T(value)); - QCOMPARE(atomic.load(), newValue1); - QCOMPARE(atomic.fetchAndSubOrdered(parcel1), newValue1); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndSubOrdered(parcel1), T(value)); - QCOMPARE(atomic.load(), newValue2); - QCOMPARE(atomic.fetchAndAddOrdered(parcel1), newValue2); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndAddOrdered(parcel2), T(value)); - QCOMPARE(atomic.load(), newValue2); - QCOMPARE(atomic.fetchAndSubOrdered(parcel2), newValue2); - QCOMPARE(atomic.load(), T(value)); - QCOMPARE(atomic.fetchAndSubOrdered(parcel2), T(value)); - QCOMPARE(atomic.load(), newValue1); - QCOMPARE(atomic.fetchAndAddOrdered(parcel2), newValue1); - QCOMPARE(atomic.load(), T(value)); - - // operator+= and operator-= - QCOMPARE(atomic += parcel1, newValue1); - QCOMPARE(atomic -= parcel1, T(value)); - QCOMPARE(atomic -= parcel1, newValue2); - QCOMPARE(atomic += parcel1, T(value)); - QCOMPARE(atomic += parcel2, newValue2); - QCOMPARE(atomic -= parcel2, T(value)); - QCOMPARE(atomic -= parcel2, newValue1); - QCOMPARE(atomic += parcel2, T(value)); -} - void tst_QAtomicIntegerXX::fetchAndOr() { QFETCH(LargeInt, value); -- cgit v1.2.3 From 6cacd19db56b632964c3b2453bc273dac50446c9 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Mon, 22 Feb 2016 12:47:19 +0300 Subject: Don't propagate unsolicited events from QWidgetWindow to QWidget Show and Hide events were not propagated before this change. Add Timer, DynamicPropertyChange, ChildAdded, and ChildRemoved, because they are supposed to be delivered to one QObject. Also don't propagate these events if WA_DontShowOnScreen is set. Change-Id: I134bf3909d46141e4d3e39f41983f493a4f35478 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/kernel/qwidgetwindow.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 01832a4f2b..b638c6c377 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -156,11 +156,29 @@ QObject *QWidgetWindow::focusObject() const return widget; } +static inline bool shouldBePropagatedToWidget(QEvent *event) +{ + switch (event->type()) { + // Handing show events to widgets would cause them to be triggered twice + case QEvent::Show: + case QEvent::Hide: + case QEvent::Timer: + case QEvent::DynamicPropertyChange: + case QEvent::ChildAdded: + case QEvent::ChildRemoved: + return false; + default: + return true; + } +} + bool QWidgetWindow::event(QEvent *event) { if (m_widget->testAttribute(Qt::WA_DontShowOnScreen)) { // \a event is uninteresting for QWidgetWindow, the event was probably // generated before WA_DontShowOnScreen was set + if (!shouldBePropagatedToWidget(event)) + return true; return QCoreApplication::sendEvent(m_widget, event); } @@ -285,10 +303,6 @@ bool QWidgetWindow::event(QEvent *event) return true; #endif - // Handing show events to widgets (see below) here would cause them to be triggered twice - case QEvent::Show: - case QEvent::Hide: - return QWindow::event(event); case QEvent::WindowBlocked: qt_button_down = 0; break; @@ -303,7 +317,7 @@ bool QWidgetWindow::event(QEvent *event) break; } - if (QCoreApplication::sendEvent(m_widget, event) && event->type() != QEvent::Timer) + if (shouldBePropagatedToWidget(event) && QCoreApplication::sendEvent(m_widget, event)) return true; return QWindow::event(event); -- cgit v1.2.3