summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/widgets')
-rw-r--r--tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp25
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp16
-rw-r--r--tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp15
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout/BLACKLIST3
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST4
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp55
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp134
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp155
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST1
-rw-r--r--tests/auto/widgets/itemviews/qlistview/BLACKLIST3
-rw-r--r--tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp301
-rw-r--r--tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp54
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp24
-rw-r--r--tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp16
-rw-r--r--tests/auto/widgets/kernel/qapplication/BLACKLIST3
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp109
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST3
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp2
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp51
-rw-r--r--tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp24
-rw-r--r--tests/auto/widgets/kernel/qtooltip/BLACKLIST2
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST10
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp287
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/BLACKLIST7
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp1
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp80
-rw-r--r--tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp23
-rw-r--r--tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp39
-rw-r--r--tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp4
-rw-r--r--tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp83
-rw-r--r--tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp48
-rw-r--r--tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp14
-rw-r--r--tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp2
-rw-r--r--tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp13
-rw-r--r--tests/auto/widgets/widgets/qlineedit/BLACKLIST12
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp68
-rw-r--r--tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp5
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/BLACKLIST3
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp43
-rw-r--r--tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp2
-rw-r--r--tests/auto/widgets/widgets/qmenubar/BLACKLIST1
-rw-r--r--tests/auto/widgets/widgets/qopenglwidget/BLACKLIST1
-rw-r--r--tests/auto/widgets/widgets/qplaintextedit/BLACKLIST6
-rw-r--r--tests/auto/widgets/widgets/qplaintextedit/qplaintextedit.pro2
-rw-r--r--tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp6
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp18
-rw-r--r--tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp58
-rw-r--r--tests/auto/widgets/widgets/qspinbox/BLACKLIST1
-rw-r--r--tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp2
-rw-r--r--tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp149
-rw-r--r--tests/auto/widgets/widgets/qtextedit/BLACKLIST6
-rw-r--r--tests/auto/widgets/widgets/qtextedit/qtextedit.pro2
-rw-r--r--tests/auto/widgets/widgets/qtoolbutton/BLACKLIST1
53 files changed, 1888 insertions, 109 deletions
diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
index 10a3746e36..3bdca59dd3 100644
--- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
+++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
@@ -90,6 +90,7 @@ private slots:
void transientParent_data();
void transientParent();
void dialogInGraphicsView();
+ void keepPositionOnClose();
};
// Testing get/set functions
@@ -677,5 +678,29 @@ void tst_QDialog::dialogInGraphicsView()
}
}
+// QTBUG-79147 (Windows): Closing a dialog by clicking the 'X' in the title
+// bar would offset the dialog position when shown next time.
+void tst_QDialog::keepPositionOnClose()
+{
+#ifdef Q_OS_WINRT
+ QSKIP("Does not work on winrt", Continue);
+#endif
+ QDialog dialog;
+ dialog.setWindowTitle(QTest::currentTestFunction());
+ const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
+ dialog.resize(availableGeometry.size() / 4);
+ const QPoint pos = availableGeometry.topLeft() + QPoint(100, 100);
+ dialog.move(pos);
+ dialog.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&dialog));
+ dialog.close();
+ dialog.windowHandle()->destroy(); // Emulate a click on close by destroying the window.
+ QTest::qWait(50);
+ dialog.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&dialog));
+ QTest::qWait(50);
+ QCOMPARE(dialog.pos(), pos);
+}
+
QTEST_MAIN(tst_QDialog)
#include "tst_qdialog.moc"
diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
index afb24bc528..455159299d 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -137,6 +137,7 @@ private slots:
void clearLineEdit();
void enableChooseButton();
void selectedFilesWithoutWidgets();
+ void selectedFileWithDefaultSuffix();
void trailingDotsAndSpaces();
#ifdef Q_OS_UNIX
#ifdef QT_BUILD_INTERNAL
@@ -1475,6 +1476,21 @@ void tst_QFiledialog::selectedFilesWithoutWidgets()
QVERIFY(fd.selectedFiles().size() >= 0);
}
+void tst_QFiledialog::selectedFileWithDefaultSuffix()
+{
+ // QTBUG-59401: dot in file path should not prevent default suffix from being added
+ QTemporaryDir tempDir(QDir::tempPath() + "/abcXXXXXX.def");
+ QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString()));
+
+ QFileDialog fd;
+ fd.setDirectory(tempDir.path());
+ fd.setDefaultSuffix(".txt");
+ fd.selectFile("xxx");
+ const auto selectedFiles = fd.selectedFiles();
+ QCOMPARE(selectedFiles.size(), 1);
+ QVERIFY(selectedFiles.first().endsWith(".txt"));
+}
+
void tst_QFiledialog::trailingDotsAndSpaces()
{
#ifndef Q_OS_WIN
diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
index 2c0b3f2bcb..51bed6ddfe 100644
--- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
+++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
@@ -226,6 +226,21 @@ void tst_QFileSystemModel::rootPath()
QCOMPARE(rootChanged.count(), oldCount + 1);
QCOMPARE(model->rootDirectory().absolutePath(), newdir.path());
}
+
+#ifdef Q_OS_WIN
+ // check case insensitive root node on windows, tests QTBUG-71701
+ QModelIndex index = model->setRootPath(QString("\\\\localhost\\c$"));
+ QVERIFY(index.isValid());
+ QCOMPARE(model->rootPath(), QString("//localhost/c$"));
+
+ index = model->setRootPath(QString("\\\\localhost\\C$"));
+ QVERIFY(index.isValid());
+ QCOMPARE(model->rootPath(), QString("//localhost/C$"));
+
+ index = model->setRootPath(QString("\\\\LOCALHOST\\C$"));
+ QVERIFY(index.isValid());
+ QCOMPARE(model->rootPath(), QString("//LOCALHOST/C$"));
+#endif
}
void tst_QFileSystemModel::readOnly()
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/BLACKLIST
new file mode 100644
index 0000000000..94483628fd
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/BLACKLIST
@@ -0,0 +1,3 @@
+[layoutDirection]
+ubuntu-20.04
+sles-15.4
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST
new file mode 100644
index 0000000000..754014501b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST
@@ -0,0 +1,4 @@
+[scrollUpdate]
+android
+[forwardTouchEvent]
+android
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index db7d1449d3..f1efeebd91 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -223,6 +223,7 @@ private slots:
void replayMouseMove();
void itemsUnderMouse();
void embeddedViews();
+ void embeddedViewsWithFocus();
void scrollAfterResize_data();
void scrollAfterResize();
void moveItemWhileScrolling_data();
@@ -3519,6 +3520,60 @@ void tst_QGraphicsView::embeddedViews()
delete v1;
}
+/*!
+ Verify that a nested graphics view and embedded widgets receive window
+ activation and focus correctly.
+
+ See QTBUG-94091.
+*/
+void tst_QGraphicsView::embeddedViewsWithFocus()
+{
+ class FocusWidget : public QWidget
+ {
+ public:
+ FocusWidget() { setFocusPolicy(Qt::StrongFocus); }
+ QSize sizeHint() const override { return QSize(100, 100); }
+
+ int focusCount = 0;
+ protected:
+ void mousePressEvent(QMouseEvent *) override {} // accept event to avoid warning
+ void focusInEvent(QFocusEvent *) override { ++focusCount; }
+ void focusOutEvent(QFocusEvent *) override { --focusCount; }
+ };
+
+ QGraphicsScene innerScene;
+ FocusWidget *innerWidget = new FocusWidget;
+ innerScene.addWidget(innerWidget);
+ QGraphicsView *innerView = new QGraphicsView(&innerScene);
+
+ QGraphicsScene outerScene;
+ FocusWidget *outerWidget = new FocusWidget;
+ QGraphicsProxyWidget *outerProxy = outerScene.addWidget(outerWidget);
+ QGraphicsProxyWidget *nestedProxy = outerScene.addWidget(innerView);
+ outerProxy->setPos(0, 0);
+ nestedProxy->setPos(0, outerWidget->sizeHint().height());
+ QGraphicsView outerView(&outerScene);
+ outerView.show();
+ outerView.activateWindow();
+ QVERIFY(QTest::qWaitForWindowActive(&outerView));
+ const QPoint outerCenter(QPoint(innerWidget->sizeHint().width() / 2,
+ innerWidget->sizeHint().height() / 2));
+ const QPoint innerCenter(outerCenter + QPoint(0, innerWidget->sizeHint().height()));
+ QCOMPARE(outerView.itemAt(outerCenter), outerProxy);
+ QCOMPARE(outerView.itemAt(innerCenter), nestedProxy);
+ QVERIFY(outerScene.isActive());
+ QVERIFY(innerScene.isActive());
+
+ QCOMPARE(outerWidget->focusCount, 0);
+ QCOMPARE(innerWidget->focusCount, 0);
+ QTest::mouseClick(outerView.viewport(), Qt::LeftButton, {}, outerCenter);
+ QCOMPARE(outerWidget->focusCount, 1);
+ QCOMPARE(innerWidget->focusCount, 0);
+ QTest::mouseClick(outerView.viewport(), Qt::LeftButton, {}, innerCenter);
+ QCOMPARE(outerWidget->focusCount, 0);
+ QCOMPARE(innerWidget->focusCount, 1);
+}
+
void tst_QGraphicsView::scrollAfterResize_data()
{
QTest::addColumn<bool>("reverse");
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index 0bdf61e1e1..56448c1723 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -47,6 +47,7 @@
#include <QStringListModel>
#include <QStyledItemDelegate>
#include <QTableWidget>
+#include <QTimer>
#include <QTreeWidget>
#include <QTest>
#include <QVBoxLayout>
@@ -150,6 +151,10 @@ private slots:
void checkFocusAfterActivationChanges_data();
void checkFocusAfterActivationChanges();
void dragSelectAfterNewPress();
+ void dragWithSecondClick_data();
+ void dragWithSecondClick();
+ void clickAfterDoubleClick();
+
private:
static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr)
{
@@ -2511,5 +2516,134 @@ void tst_QAbstractItemView::dragSelectAfterNewPress()
QVERIFY(selected.contains(model.index(i, 0)));
}
+void tst_QAbstractItemView::dragWithSecondClick_data()
+{
+ QTest::addColumn<QString>("viewClass");
+ QTest::addColumn<bool>("doubleClick");
+ for (QString viewClass : {"QListView", "QTreeView"}) {
+ QTest::addRow("DoubleClick") << viewClass << true;
+ QTest::addRow("Two Single Clicks") << viewClass << false;
+ }
+}
+
+// inject the ability to record which indexes get dragged into any QAbstractItemView class
+struct DragRecorder
+{
+ virtual ~DragRecorder() = default;
+ bool dragStarted = false;
+ QModelIndexList draggedIndexes;
+ QAbstractItemView *view;
+};
+
+template<class ViewClass>
+class DragRecorderView : public ViewClass, public DragRecorder
+{
+public:
+ DragRecorderView()
+ { view = this; }
+protected:
+ void startDrag(Qt::DropActions) override
+ {
+ draggedIndexes = ViewClass::selectedIndexes();
+ dragStarted = true;
+ }
+};
+
+void tst_QAbstractItemView::dragWithSecondClick()
+{
+ QFETCH(QString, viewClass);
+ QFETCH(bool, doubleClick);
+
+ QStandardItemModel model;
+ QStandardItem *parentItem = model.invisibleRootItem();
+ for (int i = 0; i < 10; ++i) {
+ QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
+ item->setDragEnabled(true);
+ item->setEditable(false);
+ parentItem->appendRow(item);
+ }
+
+ std::unique_ptr<DragRecorder> dragRecorder;
+ if (viewClass == "QTreeView")
+ dragRecorder.reset(new DragRecorderView<QTreeView>);
+ else if (viewClass == "QListView")
+ dragRecorder.reset(new DragRecorderView<QListView>);
+
+ QAbstractItemView *view = dragRecorder->view;
+ view->setModel(&model);
+ view->setFixedSize(160, 650); // Minimum width for windows with frame on Windows 8
+ view->setSelectionMode(QAbstractItemView::MultiSelection);
+ view->setDragDropMode(QAbstractItemView::InternalMove);
+ centerOnScreen(view);
+ moveCursorAway(view);
+ view->show();
+ QVERIFY(QTest::qWaitForWindowExposed(view));
+
+ QModelIndex index0 = model.index(0, 0);
+ QModelIndex index1 = model.index(1, 0);
+ // Select item 0 using a single click
+ QTest::mouseClick(view->viewport(), Qt::LeftButton, Qt::NoModifier,
+ view->visualRect(index0).center());
+ QCOMPARE(view->currentIndex(), index0);
+
+ if (doubleClick) {
+ // press on same item within the double click interval
+ QTest::mouseDClick(view->viewport(), Qt::LeftButton, Qt::NoModifier,
+ view->visualRect(index0).center());
+ } else {
+ // or on different item with a slow second press
+ QTest::mousePress(view->viewport(), Qt::LeftButton, Qt::NoModifier,
+ view->visualRect(index1).center());
+ }
+ // then drag far enough with left button held
+ const QPoint dragTo = view->visualRect(index1).center()
+ + QPoint(2 * QApplication::startDragDistance(),
+ 2 * QApplication::startDragDistance());
+ QMouseEvent mouseMoveEvent(QEvent::MouseMove, dragTo,
+ Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
+ QVERIFY(QApplication::sendEvent(view->viewport(), &mouseMoveEvent));
+ // twice since the view will first enter dragging state, then start the drag
+ // (not necessary to actually move the mouse)
+ QVERIFY(QApplication::sendEvent(view->viewport(), &mouseMoveEvent));
+ QVERIFY(dragRecorder->dragStarted);
+ QTest::mouseRelease(view->viewport(), Qt::LeftButton, Qt::NoModifier, dragTo);
+}
+
+void tst_QAbstractItemView::clickAfterDoubleClick()
+{
+ QTableWidget view(5, 5);
+ view.horizontalHeader()->hide();
+ view.verticalHeader()->hide();
+ view.setEditTriggers(QAbstractItemView::NoEditTriggers);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ const QModelIndex index = view.model()->index(1, 1);
+ QVERIFY(index.isValid());
+ const QPoint clickPoint = view.visualRect(index).center();
+
+ // must use the QWindow overloads so that modality is respected
+ QWindow *window = view.window()->windowHandle();
+ int clickCount = 0;
+
+ connect(&view, &QAbstractItemView::doubleClicked, [&]{
+ QDialog dialog(&view);
+ dialog.setModal(true);
+ QTimer::singleShot(0, [&]{ dialog.close(); });
+ dialog.exec();
+ });
+ connect(&view, &QAbstractItemView::clicked, [&]{
+ ++clickCount;
+ });
+
+ QTest::mouseClick(window, Qt::LeftButton, {}, clickPoint);
+ QCOMPARE(clickCount, 1);
+ // generates a click followed by a double click; double click opens
+ // dialog that eats second release
+ QTest::mouseDClick(window, Qt::LeftButton, {}, clickPoint);
+ QCOMPARE(clickCount, 2);
+ QTest::mouseClick(window, Qt::LeftButton, {}, clickPoint);
+ QCOMPARE(clickCount, 3);
+}
+
QTEST_MAIN(tst_QAbstractItemView)
#include "tst_qabstractitemview.moc"
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index d5813d64ff..88c09de8e0 100644
--- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -218,6 +218,7 @@ private slots:
void QTBUG75615_sizeHintWithStylesheet();
void ensureNoIndexAtLength();
void offsetConsistent();
+ void sectionsDontSortWhenNotClickingInThem();
void initialSortOrderRole();
@@ -250,6 +251,7 @@ private slots:
void testResetCachedSizeHint();
void statusTips();
void testRemovingColumnsViaLayoutChanged();
+ void testModelMovingColumns();
protected:
void setupTestData(bool use_reset_model = false);
@@ -359,6 +361,12 @@ public:
endRemoveColumns();
}
+ void moveColumn(int from, int to)
+ {
+ beginMoveColumns(QModelIndex(), from, from, QModelIndex(), to);
+ endMoveColumns();
+ }
+
void cleanup()
{
emit layoutAboutToBeChanged();
@@ -2628,6 +2636,140 @@ void tst_QHeaderView::offsetConsistent()
QVERIFY(offset2 > offset1);
}
+void tst_QHeaderView::sectionsDontSortWhenNotClickingInThem()
+{
+ QTableView qtv;
+ QStandardItemModel amodel(1000, 4);
+ qtv.setModel(&amodel);
+ QHeaderView *hv = qtv.horizontalHeader();
+ hv->setSectionsClickable(true);
+ hv->setFirstSectionMovable(true);
+ hv->setSectionsMovable(false);
+
+ enum { DefaultYOffset = 5, OutOfRangeYOffset = 10000 };
+
+ const auto pressOnSection = [&](int section, int yOffset = DefaultYOffset)
+ {
+ QTest::mousePress(hv->viewport(), Qt::LeftButton, Qt::NoModifier,
+ QPoint(hv->sectionViewportPosition(section) + hv->sectionSize(section) / 2, yOffset));
+ };
+ const auto moveOntoSection = [&](int section, int yOffset = DefaultYOffset)
+ {
+ QTest::mouseMove(hv->viewport(),
+ QPoint(hv->sectionViewportPosition(section) + hv->sectionSize(section) / 2, yOffset));
+ };
+ const auto releaseOnSection = [&](int section, int yOffset = DefaultYOffset)
+ {
+ QTest::mouseRelease(hv->viewport(), Qt::LeftButton, Qt::NoModifier,
+ QPoint(hv->sectionViewportPosition(section) + hv->sectionSize(section) / 2, yOffset));
+ };
+
+ hv->setSortIndicator(-1, Qt::AscendingOrder);
+ QCOMPARE(hv->sortIndicatorSection(), -1);
+
+ pressOnSection(0);
+ releaseOnSection(0);
+ // RESULT: sorting
+ QCOMPARE(hv->sortIndicatorSection(), 0);
+
+ hv->setSortIndicator(-1, Qt::AscendingOrder);
+ QCOMPARE(hv->sortIndicatorSection(), -1);
+
+ pressOnSection(0);
+ moveOntoSection(1);
+ releaseOnSection(1);
+ // RESULT: no sorting
+ QCOMPARE(hv->sortIndicatorSection(), -1);
+
+ pressOnSection(0);
+ moveOntoSection(1);
+ moveOntoSection(2);
+ releaseOnSection(2);
+ // RESULT: no sorting
+ QCOMPARE(hv->sortIndicatorSection(), -1);
+
+ pressOnSection(0);
+ moveOntoSection(1);
+ moveOntoSection(0);
+ releaseOnSection(0);
+ // RESULT: sorting by 0
+ QCOMPARE(hv->sortIndicatorSection(), 0);
+
+ pressOnSection(0);
+ moveOntoSection(1);
+ releaseOnSection(1);
+ // RESULT: no change, still sorting by 0
+ QCOMPARE(hv->sortIndicatorSection(), 0);
+
+ auto sortOrder = hv->sortIndicatorOrder();
+ pressOnSection(1);
+ moveOntoSection(0);
+ releaseOnSection(0);
+ // RESULT: no change, still sorting by 0
+ QCOMPARE(hv->sortIndicatorSection(), 0);
+ QCOMPARE(hv->sortIndicatorOrder(), sortOrder);
+
+ pressOnSection(1);
+ moveOntoSection(0);
+ moveOntoSection(1);
+ releaseOnSection(1);
+ // RESULT: sorting by 1
+ QCOMPARE(hv->sortIndicatorSection(), 1);
+
+ pressOnSection(1);
+ moveOntoSection(0);
+ releaseOnSection(0);
+ // RESULT: no change, still sorting by 1
+ QCOMPARE(hv->sortIndicatorSection(), 1);
+
+ hv->setSortIndicator(-1, Qt::AscendingOrder);
+ QCOMPARE(hv->sortIndicatorSection(), -1);
+
+ pressOnSection(0);
+ releaseOnSection(0, OutOfRangeYOffset);
+ // RESULT: no sorting
+ QCOMPARE(hv->sortIndicatorSection(), -1);
+
+ pressOnSection(0);
+ moveOntoSection(0, OutOfRangeYOffset);
+ releaseOnSection(0, OutOfRangeYOffset);
+ // RESULT: no sorting
+ QCOMPARE(hv->sortIndicatorSection(), -1);
+
+ pressOnSection(0);
+ moveOntoSection(0, OutOfRangeYOffset);
+ moveOntoSection(0);
+ releaseOnSection(0);
+ // RESULT: sorting by 0
+ QCOMPARE(hv->sortIndicatorSection(), 0);
+
+ pressOnSection(1);
+ releaseOnSection(1, OutOfRangeYOffset);
+ // RESULT: no change, still sorting by 0
+ QCOMPARE(hv->sortIndicatorSection(), 0);
+
+ pressOnSection(1);
+ moveOntoSection(1, OutOfRangeYOffset);
+ releaseOnSection(1, OutOfRangeYOffset);
+ // RESULT: no change, still sorting by 0
+ QCOMPARE(hv->sortIndicatorSection(), 0);
+
+ pressOnSection(1);
+ moveOntoSection(1, OutOfRangeYOffset);
+ moveOntoSection(1);
+ releaseOnSection(1);
+ // RESULT: sorting by 1
+ QCOMPARE(hv->sortIndicatorSection(), 1);
+
+ pressOnSection(2);
+ moveOntoSection(1);
+ moveOntoSection(2);
+ moveOntoSection(2, OutOfRangeYOffset);
+ releaseOnSection(2, OutOfRangeYOffset);
+ // RESULT: no change, still sorting by 1
+ QCOMPARE(hv->sortIndicatorSection(), 1);
+}
+
void tst_QHeaderView::initialSortOrderRole()
{
QTableView view; // ### Shadowing member view (of type QHeaderView)
@@ -3492,5 +3634,18 @@ void tst_QHeaderView::testRemovingColumnsViaLayoutChanged()
// The main point of this test is that the section-size restoring code didn't go out of bounds.
}
+void tst_QHeaderView::testModelMovingColumns()
+{
+ QtTestModel model(10, 10);
+ QHeaderView hv(Qt::Horizontal);
+ hv.setModel(&model);
+ hv.resizeSections(QHeaderView::ResizeToContents);
+ hv.show();
+
+ QPersistentModelIndex index3 = model.index(0, 3);
+ model.moveColumn(3, 1);
+ QCOMPARE(index3.column(), 1);
+}
+
QTEST_MAIN(tst_QHeaderView)
#include "tst_qheaderview.moc"
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST b/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST
index 5eda888af6..d73129ee40 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST
+++ b/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST
@@ -4,3 +4,4 @@ opensuse-42.3 ci
opensuse-42.3 ci
[editorKeyPress]
ubuntu-20.04
+sles-15.4
diff --git a/tests/auto/widgets/itemviews/qlistview/BLACKLIST b/tests/auto/widgets/itemviews/qlistview/BLACKLIST
new file mode 100644
index 0000000000..4925d0bdc4
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qlistview/BLACKLIST
@@ -0,0 +1,3 @@
+[internalDragDropMove]
+opensuse ci
+sles-15.4
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
index 941ff52373..b038245610 100644
--- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
+++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -166,9 +166,12 @@ private slots:
void taskQTBUG_7232_AllowUserToControlSingleStep();
void taskQTBUG_51086_skippingIndexesInSelectedIndexes();
void taskQTBUG_47694_indexOutOfBoundBatchLayout();
+ void moveLastRow();
void itemAlignment();
void internalDragDropMove_data();
void internalDragDropMove();
+ void scrollOnRemove_data();
+ void scrollOnRemove();
};
// Testing get/set functions
@@ -2512,6 +2515,222 @@ void tst_QListView::taskQTBUG_47694_indexOutOfBoundBatchLayout()
view.scrollTo(model.index(batchSize - 1, 0));
}
+class TstMoveItem
+{
+ friend class TstMoveModel;
+public:
+ TstMoveItem(TstMoveItem *parent = nullptr)
+ : parentItem(parent)
+ {
+ if (parentItem)
+ parentItem->childItems.append(this);
+ }
+
+ ~TstMoveItem()
+ {
+ QList<TstMoveItem *> delItms;
+ delItms.swap(childItems);
+ qDeleteAll(delItms);
+
+ if (parentItem)
+ parentItem->childItems.removeAll(this);
+ }
+
+ int row()
+ {
+ if (parentItem)
+ return parentItem->childItems.indexOf(this);
+ return -1;
+ }
+
+public:
+ TstMoveItem *parentItem = nullptr;
+ QList<TstMoveItem *> childItems;
+ QHash<int, QVariant> data;
+};
+
+/*!
+ Test that removing the last row in an IconView mode QListView
+ doesn't crash. The model is specifically crafted to provoke a
+ stale QBspTree by returning a 0 column count for indexes without
+ children, which changes the column count after moving the last row.
+
+ See QTBUG_95463.
+*/
+class TstMoveModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ TstMoveModel(QObject *parent = nullptr)
+ : QAbstractItemModel(parent)
+ {
+ rootItem = new TstMoveItem;
+ rootItem->data.insert(Qt::DisplayRole, "root");
+
+ TstMoveItem *itm = new TstMoveItem(rootItem);
+ itm->data.insert(Qt::DisplayRole, "parentItem1");
+
+ TstMoveItem *itmCh = new TstMoveItem(itm);
+ itmCh->data.insert(Qt::DisplayRole, "childItem");
+
+ itm = new TstMoveItem(rootItem);
+ itm->data.insert(Qt::DisplayRole, "parentItem2");
+ }
+
+ ~TstMoveModel()
+ {
+ delete rootItem;
+ }
+
+ QModelIndex index(int row, int column, const QModelIndex &idxPar = QModelIndex()) const override
+ {
+ QModelIndex idx;
+ if (hasIndex(row, column, idxPar)) {
+ TstMoveItem *parentItem = nullptr;
+ if (idxPar.isValid())
+ parentItem = static_cast<TstMoveItem *>(idxPar.internalPointer());
+ else
+ parentItem = rootItem;
+
+ Q_ASSERT(parentItem);
+ TstMoveItem *childItem = parentItem->childItems.at(row);
+ if (childItem)
+ idx = createIndex(row, column, childItem);
+ }
+ return idx;
+ }
+
+ QModelIndex parent(const QModelIndex &index) const override
+ {
+ QModelIndex idxPar;
+ if (index.isValid()) {
+ TstMoveItem *childItem = static_cast<TstMoveItem *>(index.internalPointer());
+ TstMoveItem *parentItem = childItem->parentItem;
+ if (parentItem != rootItem)
+ idxPar = createIndex(parentItem->row(), 0, parentItem);
+ }
+ return idxPar;
+ }
+
+ int columnCount(const QModelIndex &idxPar = QModelIndex()) const override
+ {
+ int cnt = 0;
+ if (idxPar.isValid()) {
+ TstMoveItem *parentItem = static_cast<TstMoveItem *>(idxPar.internalPointer());
+ Q_ASSERT(parentItem);
+ cnt = parentItem->childItems.isEmpty() ? 0 : 1;
+ } else {
+ cnt = rootItem->childItems.isEmpty() ? 0 : 1;
+ }
+ return cnt;
+ }
+
+ int rowCount(const QModelIndex &idxPar = QModelIndex()) const override
+ {
+ int cnt = 0;
+ if (idxPar.isValid()) {
+ TstMoveItem *parentItem = static_cast<TstMoveItem *>(idxPar.internalPointer());
+ Q_ASSERT(parentItem);
+ cnt = parentItem->childItems.count();
+ } else {
+ cnt = rootItem->childItems.count();
+ }
+ return cnt;
+ }
+
+ Qt::ItemFlags flags(const QModelIndex &index) const override
+ {
+ Q_UNUSED(index)
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ }
+
+ bool hasChildren(const QModelIndex &parent = QModelIndex()) const override
+ {
+ bool ret = false;
+ if (parent.isValid()) {
+ TstMoveItem *parentItem = static_cast<TstMoveItem *>(parent.internalPointer());
+ Q_ASSERT(parentItem);
+ ret = parentItem->childItems.count() > 0;
+ } else {
+ ret = rootItem->childItems.count() > 0;
+ }
+ return ret;
+ }
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
+ {
+ QVariant dt;
+ if (index.isValid()) {
+ TstMoveItem *item = static_cast<TstMoveItem *>(index.internalPointer());
+ if (item)
+ dt = item->data.value(role);
+ }
+ return dt;
+ }
+
+ bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override
+ {
+ TstMoveItem *itmSrcParent = itemAt(sourceParent);
+ TstMoveItem *itmDestParent = itemAt(destinationParent);
+
+ if (itmSrcParent && sourceRow >= 0
+ && sourceRow + count <= itmSrcParent->childItems.count()
+ && itmDestParent && destinationChild <= itmDestParent->childItems.count()) {
+ beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1,
+ destinationParent, destinationChild);
+ QList<TstMoveItem *> itemsToMove;
+ for (int i = 0; i < count; ++i) {
+ TstMoveItem *itm = itmSrcParent->childItems.at(sourceRow+i);
+ itemsToMove.append(itm);
+ }
+ for (int i = itemsToMove.count() -1; i >= 0; --i) {
+ TstMoveItem *itm = itemsToMove.at(i);
+ itm->parentItem->childItems.removeAll(itm);
+ itm->parentItem = itmDestParent;
+ itmDestParent->childItems.insert(destinationChild, itm);
+ }
+ endMoveRows();
+ return true;
+ }
+ return false;
+ }
+
+private:
+ TstMoveItem *itemAt(const QModelIndex &index) const
+ {
+ TstMoveItem *item = nullptr;
+ if (index.isValid()) {
+ Q_ASSERT(index.model() == this);
+ item = static_cast<TstMoveItem *>(index.internalPointer());
+ } else {
+ item = rootItem;
+ }
+ return item;
+ }
+
+private:
+ TstMoveItem *rootItem = nullptr;
+};
+
+void tst_QListView::moveLastRow()
+{
+ TstMoveModel model;
+ QListView view;
+ view.setModel(&model);
+ view.setRootIndex(model.index(0, 0, QModelIndex()));
+ view.setViewMode(QListView::IconMode);
+ view.show();
+
+ QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+
+ QModelIndex sourceParent = model.index(0, 0);
+ QModelIndex destinationParent = model.index(1, 0);
+ // must not crash when paint event is processed
+ model.moveRow(sourceParent, 0, destinationParent, 0);
+ QTest::qWait(100);
+}
+
void tst_QListView::itemAlignment()
{
auto item1 = new QStandardItem("111");
@@ -2550,6 +2769,7 @@ void tst_QListView::internalDragDropMove_data()
| Qt::ItemIsEditable
| Qt::ItemIsDragEnabled;
+ const QStringList unchanged = QStringList{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
const QStringList reordered = QStringList{"0", "2", "3", "4", "5", "6", "7", "8", "9", "1"};
const QStringList replaced = QStringList{"0", "2", "3", "4", "1", "6", "7", "8", "9"};
@@ -2564,7 +2784,8 @@ void tst_QListView::internalDragDropMove_data()
<< Qt::MoveAction
<< defaultFlags
<< modelMoves
- << reordered;
+ // listview in IconMode doesn't change the model
+ << ((viewMode == QListView::IconMode && !modelMoves) ? unchanged : reordered);
QTest::newRow((rowName + ", only move").constData())
<< viewMode
@@ -2573,7 +2794,8 @@ void tst_QListView::internalDragDropMove_data()
<< Qt::MoveAction
<< defaultFlags
<< modelMoves
- << reordered;
+ // listview in IconMode doesn't change the model
+ << ((viewMode == QListView::IconMode && !modelMoves) ? unchanged : reordered);
QTest::newRow((rowName + ", replace item").constData())
<< viewMode
@@ -2683,7 +2905,9 @@ void tst_QListView::internalDragDropMove()
selectedTexts << data.itemData(index).value(Qt::DisplayRole).toString();
return selectedTexts;
};
- QVERIFY(QTest::qWaitForWindowExposed(&list));
+ // The test relies on the global position of mouse events; make sure
+ // the window is properly mapped on X11.
+ QVERIFY(QTest::qWaitForWindowActive(&list));
// execute as soon as the eventloop is running again
// which is the case inside list.startDrag()
QTimer::singleShot(0, [&]()
@@ -2707,15 +2931,82 @@ void tst_QListView::internalDragDropMove()
list.startDrag(Qt::MoveAction);
- QCOMPARE(data.stringList(), expectedData);
+ QTRY_COMPARE(data.stringList(), expectedData);
// if the model doesn't implement moveRows, or if items are replaced, then selection is lost
if (modelMoves && !(itemFlags & Qt::ItemIsDropEnabled)) {
const QStringList actualSelected = getSelectedTexts();
- QCOMPARE(actualSelected, expectedSelected);
+ QTRY_COMPARE(actualSelected, expectedSelected);
}
}
+void tst_QListView::scrollOnRemove_data()
+{
+ QTest::addColumn<QListView::ViewMode>("viewMode");
+ QTest::addColumn<QAbstractItemView::SelectionMode>("selectionMode");
+
+ const QMetaObject &mo = QListView::staticMetaObject;
+ const auto viewModeEnum = mo.enumerator(mo.indexOfEnumerator("ViewMode"));
+ const auto selectionModeEnum = mo.enumerator(mo.indexOfEnumerator("SelectionMode"));
+ for (auto viewMode : { QListView::ListMode, QListView::IconMode }) {
+ const char *viewModeName = viewModeEnum.valueToKey(viewMode);
+ for (int index = 0; index < selectionModeEnum.keyCount(); ++index) {
+ const auto selectionMode = QAbstractItemView::SelectionMode(selectionModeEnum.value(index));
+ const char *selectionModeName = selectionModeEnum.valueToKey(selectionMode);
+ QTest::addRow("%s, %s", viewModeName, selectionModeName) << viewMode << selectionMode;
+ }
+ }
+}
+
+void tst_QListView::scrollOnRemove()
+{
+ QFETCH(QListView::ViewMode, viewMode);
+ QFETCH(QAbstractItemView::SelectionMode, selectionMode);
+
+ QPixmap pixmap;
+ if (viewMode == QListView::IconMode) {
+ pixmap = QPixmap(25, 25);
+ pixmap.fill(Qt::red);
+ }
+
+ QStandardItemModel model;
+ for (int i = 0; i < 50; ++i) {
+ QStandardItem *item = new QStandardItem(QString::number(i));
+ item->setIcon(pixmap);
+ model.appendRow(item);
+ }
+
+ QWidget widget;
+ QListView view(&widget);
+ view.setFixedSize(100, 100);
+ view.setAutoScroll(true);
+ if (viewMode == QListView::IconMode)
+ view.setWrapping(true);
+ view.setModel(&model);
+ view.setSelectionMode(selectionMode);
+ view.setViewMode(viewMode);
+
+ widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
+
+ QCOMPARE(view.verticalScrollBar()->value(), 0);
+ const QModelIndex item25 = model.index(25, 0);
+ view.scrollTo(item25);
+ QTRY_VERIFY(view.verticalScrollBar()->value() > 0); // layout and scrolling are delayed
+ const int item25Position = view.verticalScrollBar()->value();
+ // selecting a fully visible item shouldn't scroll
+ view.selectionModel()->setCurrentIndex(item25, QItemSelectionModel::SelectCurrent);
+ QTRY_COMPARE(view.verticalScrollBar()->value(), item25Position);
+
+ // removing the selected item might scroll if another item is selected
+ model.removeRow(25);
+
+ // if nothing is selected now, then the view should not have scrolled
+ if (!view.selectionModel()->selectedIndexes().count())
+ QTRY_COMPARE(view.verticalScrollBar()->value(), item25Position);
+}
+
+
QTEST_MAIN(tst_QListView)
#include "tst_qlistview.moc"
diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
index 67d8764b61..c7cde7e65a 100644
--- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
@@ -33,6 +33,7 @@
#include <QSignalSpy>
#include <QStyledItemDelegate>
#include <QTest>
+#include <QLabel>
#include <private/qlistwidget_p.h>
using IntList = QVector<int>;
@@ -126,6 +127,7 @@ private slots:
void moveRows();
void moveRowsInvalid_data();
void moveRowsInvalid();
+ void noopDragDrop();
protected slots:
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
@@ -1852,6 +1854,58 @@ void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet()
}
+// Test that dropping an item on or beneath itself remains a no-op
+void tst_QListWidget::noopDragDrop() // QTBUG-100128
+{
+ QListWidget listWidget;
+ QList<QListWidgetItem *> items;
+ for (int i = 0; i < 5; ++i) {
+ const QString number = QString::number(i);
+ QListWidgetItem *item = new QListWidgetItem(&listWidget);
+ item->setData(Qt::UserRole, number);
+ QLabel *label = new QLabel(number);
+ listWidget.setItemWidget(item, label);
+ items.append(item);
+ }
+
+ listWidget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&listWidget));
+
+ const QRect &lastItemRect = listWidget.visualItemRect(items.at(4));
+ const QPoint &dragStart = lastItemRect.center();
+ const QPoint &dropPointNirvana = lastItemRect.center() + QPoint(20, 2 * lastItemRect.height());
+
+ // Implement check as a macro (not a method) to safely determine the error location.
+ // The macro checks that item data and item widget remain unchanged when drag&drop are executed.
+ // In order to verify that the assets do *not* change, we can't use QTRY*: These macros would
+ // spin the event loop only once, while 3/4 mouse events need to get processed.
+ // That's why we spin the event loop 13 times, to make sure other unexpected or pending events
+ // get processed.
+#define CHECK_ITEM {\
+ const QString number = QString::number(4);\
+ for (int i = 0; i < 13; ++i)\
+ QApplication::processEvents();\
+ QLabel *label = qobject_cast<QLabel *>(listWidget.itemWidget(items.at(4)));\
+ QVERIFY(label);\
+ QCOMPARE(label->text(), number);\
+ const QString &data = items.at(4)->data(Qt::UserRole).toString();\
+ QCOMPARE(data, number);\
+ }
+
+ // Test dropping last item beneath itself
+ QTest::mousePress(&listWidget, Qt::LeftButton, Qt::KeyboardModifiers(), dragStart);
+ QTest::mouseMove(&listWidget, dropPointNirvana);
+ QTest::mouseRelease(&listWidget, Qt::LeftButton);
+ CHECK_ITEM;
+
+ // Test dropping last item on itself
+ QTest::mousePress(&listWidget, Qt::LeftButton, Qt::KeyboardModifiers(), dragStart);
+ QTest::mouseMove(&listWidget, dropPointNirvana);
+ QTest::mouseMove(&listWidget, dragStart);
+ QTest::mouseRelease(&listWidget, Qt::LeftButton);
+ CHECK_ITEM;
+}
+
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void tst_QListWidget::clearItemData()
{
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index 52fac891c0..b75defe168 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -241,6 +241,7 @@ private slots:
void taskQTBUG_7232_AllowUserToControlSingleStep();
void taskQTBUG_8376();
void taskQTBUG_61476();
+ void taskQTBUG_42469_crash();
void testInitialFocus();
void fetchUntilScreenFull();
};
@@ -4966,6 +4967,29 @@ void tst_QTreeView::taskQTBUG_61476()
QCOMPARE(lastTopLevel->checkState(), Qt::Checked);
}
+void tst_QTreeView::taskQTBUG_42469_crash()
+{
+ QTreeWidget treeWidget;
+ QTreeWidgetItem *itemOne = new QTreeWidgetItem(QStringList("item1"));
+ QTreeWidgetItem *itemTwo = new QTreeWidgetItem(QStringList("item2"));
+ treeWidget.addTopLevelItem(itemOne);
+ treeWidget.addTopLevelItem(itemTwo);
+ treeWidget.topLevelItem(1)->addChild(new QTreeWidgetItem(QStringList("child1")));
+
+ treeWidget.setAnimated(true);
+ QObject::connect(&treeWidget, &QTreeWidget::itemExpanded, [&](QTreeWidgetItem* p_item) {
+ auto tempCount = treeWidget.topLevelItemCount();
+ for (int j = 0; j < tempCount; ++j)
+ if (treeWidget.topLevelItem(j) != p_item) {
+ auto temp = treeWidget.topLevelItem(j);
+ temp->setHidden(true);
+ }
+ });
+
+ treeWidget.show();
+ itemTwo->setExpanded(true);
+}
+
void tst_QTreeView::fetchUntilScreenFull()
{
class TreeModel : public QAbstractItemModel
diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
index 7da56ab797..b129868bbd 100644
--- a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
@@ -151,6 +151,7 @@ private slots:
void getMimeDataWithInvalidItem();
void testVisualItemRect();
void reparentHiddenItem();
+ void persistentChildIndex();
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void clearItemData();
#endif
@@ -3597,6 +3598,21 @@ void tst_QTreeWidget::reparentHiddenItem()
QVERIFY(grandChild->isHidden());
}
+void tst_QTreeWidget::persistentChildIndex() // QTBUG-90030
+{
+ QTreeWidget tree;
+ QTreeWidgetItem *toplevel = new QTreeWidgetItem(QStringList{QStringLiteral("toplevel")});
+ tree.addTopLevelItem(toplevel);
+ QModelIndex firstIndex = tree.model()->index(0, 0);
+ QTreeWidgetItem *child1 = new QTreeWidgetItem(QStringList{QStringLiteral("child1")});
+ QTreeWidgetItem *child2 = new QTreeWidgetItem(QStringList{QStringLiteral("child2")});
+ toplevel->addChildren({child1, child2});
+ QPersistentModelIndex persistentIdx = tree.model()->index(1, 0, firstIndex);
+ QCOMPARE(persistentIdx.data().toString(), QStringLiteral("child2"));
+ tree.model()->removeRows(0, 1, firstIndex);
+ QCOMPARE(persistentIdx.data().toString(), QStringLiteral("child2"));
+}
+
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void tst_QTreeWidget::clearItemData()
{
diff --git a/tests/auto/widgets/kernel/qapplication/BLACKLIST b/tests/auto/widgets/kernel/qapplication/BLACKLIST
index cce10602e4..e04cceeea2 100644
--- a/tests/auto/widgets/kernel/qapplication/BLACKLIST
+++ b/tests/auto/widgets/kernel/qapplication/BLACKLIST
@@ -1,5 +1,8 @@
[sendEventsOnProcessEvents]
ubuntu-20.04
+ubuntu-22.04
+rhel-9.0
+sles-15.4
[touchEventPropagation]
# QTBUG-66745
opensuse-leap
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index e159e22d2a..60259f6beb 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -54,9 +54,11 @@
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QScrollArea>
#include <QtWidgets/QScrollBar>
+#include <QtWidgets/QHeaderView>
#include <QtWidgets/private/qapplication_p.h>
#include <QtWidgets/QStyle>
#include <QtWidgets/qproxystyle.h>
+#include <QtWidgets/QTextEdit>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qwindowsysteminterface_p.h>
@@ -89,6 +91,7 @@ private slots:
void setFont_data();
void setFont();
+ void setFontForClass();
void args_data();
void args();
@@ -117,6 +120,7 @@ private slots:
void setActiveWindow();
+ void focusWidget();
void focusChanged();
void focusOut();
void focusMouseClick();
@@ -385,6 +389,46 @@ void tst_QApplication::setFont()
QCOMPARE( app.font(), font );
}
+class tstHeaderView : public QHeaderView
+{
+ Q_OBJECT
+public:
+ explicit tstHeaderView(Qt::Orientation orientation, QWidget *parent = nullptr)
+ : QHeaderView(orientation, parent)
+ {}
+};
+class tstFrame : public QFrame { Q_OBJECT };
+class tstWidget : public QWidget { Q_OBJECT };
+
+void tst_QApplication::setFontForClass()
+{
+ // QTBUG-89910
+ // If a default font was not registered for the widget's class,
+ // it returns the default font of its nearest registered superclass.
+ int argc = 0;
+ QApplication app(argc, nullptr);
+
+ QFont font;
+ int pointSize = 10;
+ const QByteArrayList classNames{"QHeaderView", "QAbstractItemView", "QAbstractScrollView", "QFrame", "QWidget", "QObject"};
+ for (auto className : classNames) {
+ font.setPointSizeF(pointSize++);
+ app.setFont(font, className.constData());
+ }
+
+ tstHeaderView headView(Qt::Horizontal);
+ tstFrame frame;
+ tstWidget widget;
+
+ QFont headViewFont = QApplication::font(&headView);
+ QFont frameFont = QApplication::font(&frame);
+ QFont widgetFont = QApplication::font(&widget);
+
+ QCOMPARE(headViewFont.pointSize(), QApplication::font("QHeaderView").pointSize());
+ QCOMPARE(frameFont.pointSize(), QApplication::font("QFrame").pointSize());
+ QCOMPARE(widgetFont.pointSize(), QApplication::font("QWidget").pointSize());
+}
+
void tst_QApplication::args_data()
{
QTest::addColumn<int>("argc_in");
@@ -1449,6 +1493,22 @@ void tst_QApplication::desktopSettingsAware()
{
#if QT_CONFIG(process)
QProcess testProcess;
+#ifdef Q_OS_MACOS
+ QStringList environment = QProcess::systemEnvironment();
+ environment += QLatin1String("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM=1");
+ testProcess.setEnvironment(environment);
+#endif
+ // Add the executable's directory to path so that we can find the test helper next to it
+ // in a cross-platform way. We must do this because the CWD is not pointing to this directory
+ // in debug-and-release builds.
+ int argc = 0;
+ QApplication app(argc, nullptr);
+ QByteArray path = qgetenv("PATH");
+ qputenv("PATH",
+ path + QDir::listSeparator().toLatin1()
+ + QCoreApplication::applicationDirPath().toLocal8Bit());
+ auto restore = qScopeGuard([&] { qputenv("PATH", path); });
+
testProcess.start("desktopsettingsaware_helper");
QVERIFY2(testProcess.waitForStarted(),
qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString())));
@@ -1482,6 +1542,44 @@ void tst_QApplication::setActiveWindow()
delete w;
}
+void tst_QApplication::focusWidget()
+{
+ int argc = 0;
+ QApplication app(argc, nullptr);
+
+ // The focus widget is the active window itself
+ {
+ QTextEdit te;
+ te.show();
+
+ QApplication::setActiveWindow(&te);
+ QVERIFY(QTest::qWaitForWindowActive(&te));
+
+ const auto focusWidget = QApplication::focusWidget();
+ QVERIFY(focusWidget);
+ QVERIFY(focusWidget->hasFocus());
+ QVERIFY(te.hasFocus());
+ QCOMPARE(focusWidget, te.focusWidget());
+ }
+
+ // The focus widget is a child of the active window
+ {
+ QWidget w;
+ QTextEdit te(&w);
+ w.show();
+
+ QApplication::setActiveWindow(&w);
+ QVERIFY(QTest::qWaitForWindowActive(&w));
+
+ const auto focusWidget = QApplication::focusWidget();
+ QVERIFY(focusWidget);
+ QVERIFY(focusWidget->hasFocus());
+ QVERIFY(!w.hasFocus());
+ QVERIFY(te.hasFocus());
+ QCOMPARE(te.focusWidget(), w.focusWidget());
+ QCOMPARE(focusWidget, w.focusWidget());
+ }
+}
/* This might fail on some X11 window managers? */
void tst_QApplication::focusChanged()
@@ -2365,6 +2463,17 @@ void tst_QApplication::qtbug_12673()
#if QT_CONFIG(process)
QProcess testProcess;
QStringList arguments;
+ // Add the executable's directory to path so that we can find the test helper next to it
+ // in a cross-platform way. We must do this because the CWD is not pointing to this directory
+ // in debug-and-release builds.
+ int argc = 0;
+ QApplication app(argc, nullptr);
+ QByteArray path = qgetenv("PATH");
+ qputenv("PATH",
+ path + QDir::listSeparator().toLatin1()
+ + QCoreApplication::applicationDirPath().toLocal8Bit());
+ auto restore = qScopeGuard([&] { qputenv("PATH", path); });
+
testProcess.start("modal_helper", arguments);
QVERIFY2(testProcess.waitForStarted(),
qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString())));
diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST b/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST
new file mode 100644
index 0000000000..f9104cc307
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST
@@ -0,0 +1,3 @@
+# See qtbase/src/testlib/qtestblacklist.cpp for format
+[panGesture]
+linux
diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
index bcf48c21df..db71e86d7e 100644
--- a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
@@ -297,7 +297,7 @@ void tst_QGestureRecognizer::swipeGesture()
// Press point #3
points.append(points.last() + fingerDistance);
- swipeSequence.press(points.size() - 1, points.last(), &widget);
+ swipeSequence.stationary(0).stationary(1).press(points.size() - 1, points.last(), &widget);
swipeSequence.commit();
Q_ASSERT(points.size() == swipePoints);
diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
index 1d63d140fb..d57da3c78f 100644
--- a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
+++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
@@ -75,6 +75,7 @@ private slots:
void taskQTBUG_40609_addingWidgetToItsOwnLayout();
void taskQTBUG_40609_addingLayoutToItself();
void taskQTBUG_52357_spacingWhenItemIsHidden();
+ void taskQTBUG_91261_itemIndexRange();
void replaceWidget();
void dontCrashWhenExtendsToEnd();
};
@@ -1666,6 +1667,56 @@ void tst_QGridLayout::taskQTBUG_52357_spacingWhenItemIsHidden()
QTRY_COMPARE_WITH_TIMEOUT(tempWidth, button1.width() + button3.width() + layout.spacing(), 1000);
}
+void tst_QGridLayout::taskQTBUG_91261_itemIndexRange()
+{
+ QWidget widget;
+ QGridLayout lay(&widget);
+ QPushButton *btn = new QPushButton(&widget);
+ lay.addWidget(btn, 0, 0);
+
+ {
+ auto ptr = lay.itemAt(-1);
+ QCOMPARE(ptr, nullptr);
+
+ ptr = lay.itemAt(0);
+ QCOMPARE(ptr->widget(), btn);
+
+ ptr = lay.itemAt(1);
+ QCOMPARE(ptr, nullptr);
+ }
+
+ {
+ int row = -1;
+ int column = -1;
+ int rowSpan;
+ int columnSpan;
+
+ lay.getItemPosition(-1, &row, &column, &rowSpan, &columnSpan);
+ QCOMPARE(row, -1);
+ QCOMPARE(column, -1);
+
+ lay.getItemPosition(1, &row, &column, &rowSpan, &columnSpan);
+ QCOMPARE(row, -1);
+ QCOMPARE(column, -1);
+
+ lay.getItemPosition(0, &row, &column, &rowSpan, &columnSpan);
+ QCOMPARE(row, 0);
+ QCOMPARE(column, 0);
+ }
+
+ {
+ auto ptr = lay.takeAt(-1);
+ QCOMPARE(ptr, nullptr);
+
+ ptr = lay.takeAt(1);
+ QCOMPARE(ptr, nullptr);
+
+ ptr = lay.takeAt(0);
+ QCOMPARE(ptr->widget(), btn);
+ delete ptr;
+ }
+}
+
void tst_QGridLayout::replaceWidget()
{
QWidget wdg;
diff --git a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
index c8fe1841c8..c38ddbf4dc 100644
--- a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
+++ b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
@@ -69,6 +69,7 @@ private slots:
void controlTypes2();
void adjustSizeShouldMakeSureLayoutIsActivated();
void testRetainSizeWhenHidden();
+ void removeWidget();
};
tst_QLayout::tst_QLayout()
@@ -381,5 +382,28 @@ void tst_QLayout::testRetainSizeWhenHidden()
QCOMPARE(widget.sizeHint().height(), normalHeight);
}
+void tst_QLayout::removeWidget()
+{
+ QHBoxLayout layout;
+ QCOMPARE(layout.count(), 0);
+ QWidget w;
+ layout.addWidget(&w);
+ QCOMPARE(layout.count(), 1);
+ layout.removeWidget(&w);
+ QCOMPARE(layout.count(), 0);
+
+ QPointer<QLayout> childLayout(new QHBoxLayout);
+ layout.addLayout(childLayout);
+ QCOMPARE(layout.count(), 1);
+
+ layout.removeWidget(nullptr);
+ QCOMPARE(layout.count(), 1);
+
+ layout.removeItem(childLayout);
+ QCOMPARE(layout.count(), 0);
+
+ QVERIFY(!childLayout.isNull());
+}
+
QTEST_MAIN(tst_QLayout)
#include "tst_qlayout.moc"
diff --git a/tests/auto/widgets/kernel/qtooltip/BLACKLIST b/tests/auto/widgets/kernel/qtooltip/BLACKLIST
new file mode 100644
index 0000000000..8fa085a72c
--- /dev/null
+++ b/tests/auto/widgets/kernel/qtooltip/BLACKLIST
@@ -0,0 +1,2 @@
+[task183679]
+winrt
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index 70ea8433a6..a4337d15bc 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -8,10 +8,6 @@ b2qt
opensuse-42.3
[restoreVersion1Geometry]
ubuntu-16.04
-[focusProxyAndInputMethods]
-rhel-7.6
-opensuse-leap
-ubuntu
[raise]
opensuse-leap
# QTBUG-68175
@@ -24,6 +20,8 @@ macos
osx
[optimizedResize_topLevel]
osx
+[render_windowOpacity]
+macos arm
[render_systemClip]
osx
[showMinimizedKeepsFocus]
@@ -37,10 +35,12 @@ ubuntu-16.04
rhel-7.6
opensuse-leap
ubuntu
+sles-15
[windowState]
# QTBUG-75270
winrt
-
+[widgetAt]
+sles-15.4 # QTBUG-112760
[syntheticEnterLeave]
macos # Can't move cursor (QTBUG-76312)
[taskQTBUG_4055_sendSyntheticEnterLeave]
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 8596f94092..30e828369c 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -186,6 +186,7 @@ private slots:
void defaultTabOrder();
void reverseTabOrder();
void tabOrderWithProxy();
+ void tabOrderWithProxyDisabled();
void tabOrderWithCompoundWidgets();
void tabOrderWithCompoundWidgetsNoFocusPolicy();
void tabOrderNoChange();
@@ -193,6 +194,7 @@ private slots:
void appFocusWidgetWithFocusProxyLater();
void appFocusWidgetWhenLosingFocusProxy();
void explicitTabOrderWithComplexWidget();
+ void explicitTabOrderWithSpinBox_QTBUG81097();
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
void activation();
#endif
@@ -365,6 +367,8 @@ private slots:
void focusWidget_task254563();
void rectOutsideCoordinatesLimit_task144779();
void setGraphicsEffect();
+ void render_graphicsEffect_data();
+ void render_graphicsEffect();
#ifdef QT_BUILD_INTERNAL
void destroyBackingStore();
@@ -375,7 +379,6 @@ private slots:
void openModal_taskQTBUG_5804();
void focusProxy();
- void focusProxyAndInputMethods();
#ifdef QT_BUILD_INTERNAL
void scrollWithoutBackingStore();
#endif
@@ -420,6 +423,8 @@ private slots:
void receivesLanguageChangeEvent();
void deleteWindowInCloseEvent();
+ void activateWhileModalHidden();
+
private:
bool ensureScreenSize(int width, int height);
@@ -2003,6 +2008,57 @@ void tst_QWidget::tabOrderWithProxy()
QVERIFY(firstEdit->hasFocus());
}
+void tst_QWidget::tabOrderWithProxyDisabled()
+{
+ Container container;
+ container.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
+
+ QLineEdit lineEdit1;
+ lineEdit1.setObjectName("lineEdit1");
+
+ QWidget containingWidget;
+ containingWidget.setFocusPolicy(Qt::StrongFocus);
+ auto *containingLayout = new QVBoxLayout;
+ QLineEdit lineEdit2;
+ lineEdit2.setObjectName("lineEdit2");
+ QLineEdit lineEdit3;
+ lineEdit3.setObjectName("lineEdit3");
+ containingLayout->addWidget(&lineEdit2);
+ containingLayout->addWidget(&lineEdit3);
+ containingWidget.setLayout(containingLayout);
+ containingWidget.setFocusProxy(&lineEdit2);
+ lineEdit2.setEnabled(false);
+
+ container.box->addWidget(&lineEdit1);
+ container.box->addWidget(&containingWidget);
+
+ container.show();
+ container.activateWindow();
+
+ QApplication::setActiveWindow(&container);
+ if (!QTest::qWaitForWindowActive(&container))
+ QSKIP("Window failed to activate, skipping test");
+
+ QVERIFY2(lineEdit1.hasFocus(),
+ qPrintable(QApplication::focusWidget()->objectName()));
+ container.tab();
+ QVERIFY2(!lineEdit2.hasFocus(),
+ qPrintable(QApplication::focusWidget()->objectName()));
+ QVERIFY2(lineEdit3.hasFocus(),
+ qPrintable(QApplication::focusWidget()->objectName()));
+ container.tab();
+ QVERIFY2(lineEdit1.hasFocus(),
+ qPrintable(QApplication::focusWidget()->objectName()));
+ container.backTab();
+ QVERIFY2(lineEdit3.hasFocus(),
+ qPrintable(QApplication::focusWidget()->objectName()));
+ container.backTab();
+ QVERIFY2(!lineEdit2.hasFocus(),
+ qPrintable(QApplication::focusWidget()->objectName()));
+ QVERIFY2(lineEdit1.hasFocus(),
+ qPrintable(QApplication::focusWidget()->objectName()));
+}
+
void tst_QWidget::tabOrderWithCompoundWidgets()
{
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
@@ -2320,6 +2376,37 @@ void tst_QWidget::explicitTabOrderWithComplexWidget()
QTRY_COMPARE(QApplication::focusWidget(), lineEditOne);
}
+void tst_QWidget::explicitTabOrderWithSpinBox_QTBUG81097()
+{
+ // Check the special case of QAbstractSpinBox-like widgets, that have a
+ // child widget with a focusPolicy() set to its parent.
+ Container window;
+ auto spinBoxOne = new QDoubleSpinBox;
+ auto spinBoxTwo = new QDoubleSpinBox;
+ auto lineEdit = new QLineEdit;
+ window.box->addWidget(spinBoxOne);
+ window.box->addWidget(spinBoxTwo);
+ window.box->addWidget(lineEdit);
+ QWidget::setTabOrder(spinBoxOne, spinBoxTwo);
+ QWidget::setTabOrder(spinBoxTwo, lineEdit);
+ spinBoxOne->setFocus();
+ window.show();
+ QApplication::setActiveWindow(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ QTRY_COMPARE(QApplication::focusWidget(), spinBoxOne);
+
+ window.tab();
+ QTRY_COMPARE(QApplication::focusWidget(), spinBoxTwo);
+ window.tab();
+ QTRY_COMPARE(QApplication::focusWidget(), lineEdit);
+ window.backTab();
+ QTRY_COMPARE(QApplication::focusWidget(), spinBoxTwo);
+ window.backTab();
+ QTRY_COMPARE(QApplication::focusWidget(), spinBoxOne);
+ window.backTab();
+ QTRY_COMPARE(QApplication::focusWidget(), lineEdit);
+}
+
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
void tst_QWidget::activation()
{
@@ -10062,6 +10149,157 @@ void tst_QWidget::setGraphicsEffect()
QVERIFY(!blurEffect);
}
+
+class TestGraphicsEffect : public QGraphicsEffect
+{
+public:
+ TestGraphicsEffect(QObject *parent = nullptr)
+ : QGraphicsEffect(parent)
+ {
+ m_pattern = QPixmap(10, 10);
+ m_pattern.fill(Qt::lightGray);
+ QPainter p(&m_pattern);
+ p.fillRect(QRectF(0, 0, 5, 5), QBrush(Qt::darkGray));
+ p.fillRect(QRectF(5, 5, 5, 5), QBrush(Qt::darkGray));
+ }
+ void setExtent(int extent)
+ {
+ m_extent = extent;
+ }
+ QRectF boundingRectFor(const QRectF &sr) const override
+ {
+ return QRectF(sr.x() - m_extent, sr.y() - m_extent,
+ sr.width() + 2 * m_extent, sr.height() + 2 * m_extent);
+ }
+protected:
+ void draw(QPainter *painter) override
+ {
+ QBrush brush;
+ brush.setTexture(m_pattern);
+ brush.setStyle(Qt::TexturePattern);
+ QPaintDevice *p = painter->device();
+ painter->fillRect(QRect(-m_extent, -m_extent,
+ p->width() + m_extent, p->height() + m_extent), brush);
+ }
+ QPixmap m_pattern;
+ int m_extent = 0;
+};
+
+static QImage fillExpected1()
+{
+ QImage expected(QSize(40, 40), QImage::Format_RGB32);
+ QPainter p(&expected);
+ p.fillRect(QRect{{0, 0}, expected.size()}, QBrush(Qt::gray));
+ p.fillRect(QRect(10, 10, 10, 10), QBrush(Qt::red));
+ p.fillRect(QRect(20, 20, 10, 10), QBrush(Qt::blue));
+ return expected;
+}
+static QImage fillExpected2()
+{
+ QImage expected = fillExpected1();
+ QPainter p(&expected);
+ p.fillRect(QRect(10, 10, 5, 5), QBrush(Qt::darkGray));
+ p.fillRect(QRect(15, 15, 5, 5), QBrush(Qt::darkGray));
+ p.fillRect(QRect(15, 10, 5, 5), QBrush(Qt::lightGray));
+ p.fillRect(QRect(10, 15, 5, 5), QBrush(Qt::lightGray));
+ return expected;
+}
+static QImage fillExpected3()
+{
+ QImage expected(QSize(40, 40), QImage::Format_RGB32);
+ QPixmap pattern;
+ pattern = QPixmap(10, 10);
+ pattern.fill(Qt::lightGray);
+ QPainter p(&pattern);
+ p.fillRect(QRectF(0, 0, 5, 5), QBrush(Qt::darkGray));
+ p.fillRect(QRectF(5, 5, 5, 5), QBrush(Qt::darkGray));
+ QBrush brush;
+ brush.setTexture(pattern);
+ brush.setStyle(Qt::TexturePattern);
+ QPainter p2(&expected);
+ p2.fillRect(QRect{{0, 0}, expected.size()}, brush);
+ return expected;
+}
+static QImage fillExpected4()
+{
+ QImage expected = fillExpected1();
+ QPixmap pattern;
+ pattern = QPixmap(10, 10);
+ pattern.fill(Qt::lightGray);
+ QPainter p(&pattern);
+ p.fillRect(QRectF(0, 0, 5, 5), QBrush(Qt::darkGray));
+ p.fillRect(QRectF(5, 5, 5, 5), QBrush(Qt::darkGray));
+ QBrush brush;
+ brush.setTexture(pattern);
+ brush.setStyle(Qt::TexturePattern);
+ QPainter p2(&expected);
+ p2.fillRect(QRect{{15, 15}, QSize{20, 20}}, brush);
+ return expected;
+}
+
+void tst_QWidget::render_graphicsEffect_data()
+{
+ QTest::addColumn<QImage>("expected");
+ QTest::addColumn<bool>("topLevelEffect");
+ QTest::addColumn<bool>("child1Effect");
+ QTest::addColumn<bool>("child2Effect");
+ QTest::addColumn<int>("extent");
+
+ QTest::addRow("no_effect") << fillExpected1() << false << false << false << 0;
+ QTest::addRow("first_child_effect") << fillExpected2() << false << true << false << 0;
+ QTest::addRow("top_level_effect") << fillExpected3() << true << false << false << 0;
+ QTest::addRow("effect_with_extent") << fillExpected4() << false << false << true << 5;
+}
+
+void tst_QWidget::render_graphicsEffect()
+{
+ QFETCH(QImage, expected);
+ QFETCH(bool, topLevelEffect);
+ QFETCH(bool, child1Effect);
+ QFETCH(bool, child2Effect);
+ QFETCH(int, extent);
+
+ QScopedPointer<QWidget> topLevel(new QWidget);
+ topLevel->setPalette(Qt::gray);
+ topLevel->resize(40, 40);
+ topLevel->setWindowTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1String("::")
+ + QLatin1String(QTest::currentDataTag()));
+
+ // Render widget with 2 child widgets
+ QImage image(topLevel->size(), QImage::Format_RGB32);
+ image.fill(QColor(Qt::gray).rgb());
+
+ QPainter painter(&image);
+
+ QWidget *childWidget1(new QWidget(topLevel.data()));
+ childWidget1->setAutoFillBackground(true);
+ childWidget1->setPalette(Qt::red);
+ childWidget1->resize(10, 10);
+ childWidget1->move(10, 10);
+ QWidget *childWidget2(new QWidget(topLevel.data()));
+ childWidget2->setAutoFillBackground(true);
+ childWidget2->setPalette(Qt::blue);
+ childWidget2->resize(10, 10);
+ childWidget2->move(20, 20);
+
+ TestGraphicsEffect *graphicsEffect(new TestGraphicsEffect(topLevel.data()));
+ if (topLevelEffect)
+ topLevel->setGraphicsEffect(graphicsEffect);
+ if (child1Effect)
+ childWidget1->setGraphicsEffect(graphicsEffect);
+ if (child2Effect)
+ childWidget2->setGraphicsEffect(graphicsEffect);
+ graphicsEffect->setExtent(extent);
+
+ // Render without effect
+ topLevel->render(&painter);
+#ifdef RENDER_DEBUG
+ image.save("render_GraphicsEffect" + QTest::currentDataTag() + ".png");
+ expected.save("render_GraphicsEffect_expected" + QTest::currentDataTag() + ".png");
+#endif
+ QCOMPARE(image, expected);
+}
+
void tst_QWidget::activateWindow()
{
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
@@ -10249,34 +10487,6 @@ void tst_QWidget::focusProxy()
QCOMPARE(container2->focusOutCount, 1);
}
-void tst_QWidget::focusProxyAndInputMethods()
-{
- if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
- QSKIP("Window activation is not supported.");
- QScopedPointer<QWidget> toplevel(new QWidget(nullptr, Qt::X11BypassWindowManagerHint));
- toplevel->setWindowTitle(QLatin1String(QTest::currentTestFunction()));
- toplevel->resize(200, 200);
- toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
-
- QWidget *child = new QWidget(toplevel.data());
- child->setFocusProxy(toplevel.data());
- child->setAttribute(Qt::WA_InputMethodEnabled, true);
-
- toplevel->setFocusPolicy(Qt::WheelFocus);
- child->setFocusPolicy(Qt::WheelFocus);
-
- QVERIFY(!child->hasFocus());
- QVERIFY(!toplevel->hasFocus());
-
- toplevel->show();
- QVERIFY(QTest::qWaitForWindowExposed(toplevel.data()));
- QApplication::setActiveWindow(toplevel.data());
- QVERIFY(QTest::qWaitForWindowActive(toplevel.data()));
- QVERIFY(toplevel->hasFocus());
- QVERIFY(child->hasFocus());
- QCOMPARE(qApp->focusObject(), toplevel.data());
-}
-
#ifdef QT_BUILD_INTERNAL
class scrollWidgetWBS : public QWidget
{
@@ -11771,5 +11981,24 @@ void tst_QWidget::deleteWindowInCloseEvent()
QVERIFY(true);
}
+void tst_QWidget::activateWhileModalHidden()
+{
+ QDialog dialog;
+ dialog.setWindowModality(Qt::ApplicationModal);
+ dialog.show();
+ QVERIFY(QTest::qWaitForWindowActive(&dialog));
+ QVERIFY(dialog.isActiveWindow());
+ QCOMPARE(QApplication::activeWindow(), &dialog);
+
+ dialog.hide();
+ QTRY_VERIFY(!dialog.isVisible());
+
+ QMainWindow window;
+ window.show();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ QVERIFY(window.isActiveWindow());
+ QCOMPARE(QApplication::activeWindow(), &window);
+}
+
QTEST_MAIN(tst_QWidget)
#include "tst_qwidget.moc"
diff --git a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
index 70a7889257..cea1f26e53 100644
--- a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
@@ -5,3 +5,10 @@ ubuntu-16.04
[mouseMoveWithPopup]
winrt
+
+[tst_dnd_events]
+sles-15.4 # QTBUG-112760
+
+# QTBUG-96270
+[tst_paintEventOnSecondShow]
+opensuse
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
index b11faef30a..586b429338 100644
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -405,6 +405,7 @@ void tst_QWidget_window::tst_paintEventOnSecondShow()
{
PaintTestWidget w;
w.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
w.hide();
w.paintEventCount = 0;
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
index 82527849b0..a527d7c0fc 100644
--- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
+++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
@@ -94,6 +94,7 @@ private slots:
void layoutSpacing();
#endif
void qproperty();
+ void qproperty_styleSheet();
void palettePropagation_data();
void palettePropagation();
void fontPropagation_data();
@@ -126,6 +127,9 @@ private slots:
void QTBUG15910_crashNullWidget();
void QTBUG36933_brokenPseudoClassLookup();
void styleSheetChangeBeforePolish();
+ void placeholderColor();
+ void enumPropertySelector_data();
+ void enumPropertySelector();
//at the end because it mess with the style.
void widgetStyle();
void appStyle();
@@ -677,6 +681,23 @@ void tst_QStyleSheetStyle::qproperty()
QCOMPARE(pb.isChecked(), false);
}
+void tst_QStyleSheetStyle::qproperty_styleSheet()
+{
+ QWidget w;
+ auto checkBox = new QCheckBox("check", &w);
+ QString sheet = R"(QCheckBox { qproperty-styleSheet: "QCheckBox { qproperty-text: foobar; }"; })";
+
+ QVERIFY(w.property("styleSheet").toString().isEmpty());
+
+ w.setStyleSheet(sheet);
+ QCOMPARE(checkBox->text(), "check");
+
+ //recursion crash
+ w.ensurePolished();
+ QCOMPARE(w.property("styleSheet").toString(), sheet);
+ QCOMPARE(checkBox->text(), "foobar");
+}
+
namespace ns {
class PushButton1 : public QPushButton {
Q_OBJECT
@@ -2229,6 +2250,65 @@ void tst_QStyleSheetStyle::highdpiImages()
QHighDpiScaling::updateHighDpiScaling(); // reset to normal
}
+void tst_QStyleSheetStyle::placeholderColor()
+{
+ const QColor red(Qt::red);
+ qApp->setStyleSheet("* { color: red; }");
+ QLineEdit le1;
+ QLineEdit le2;
+ le2.setEnabled(false);
+ le1.ensurePolished();
+ QColor phColor = le1.palette().placeholderText().color();
+ QCOMPARE(phColor.rgb(), red.rgb());
+ QVERIFY(phColor.alpha() < red.alpha());
+
+ le2.ensurePolished();
+ phColor = le2.palette().placeholderText().color();
+ QCOMPARE(phColor.rgb(), red.rgb());
+ QVERIFY(phColor.alpha() < red.alpha());
+
+ le2.setEnabled(true);
+ phColor = le2.palette().placeholderText().color();
+ QCOMPARE(phColor.rgb(), red.rgb());
+ QVERIFY(phColor.alpha() < red.alpha());
+}
+
+void tst_QStyleSheetStyle::enumPropertySelector_data()
+{
+ QTest::addColumn<QString>("styleSheet");
+
+ QTest::addRow("Enum value") << R"(QToolButton[popupMode=MenuButtonPopup] { padding-right: 40px; })";
+ QTest::addRow("Int value") << R"(QToolButton[popupMode="1"] { padding-right: 40px; })";
+}
+
+void tst_QStyleSheetStyle::enumPropertySelector()
+{
+ QFETCH(QString, styleSheet);
+
+ QToolButton button;
+ QMenu menu;
+ menu.addAction("Action1");
+ QPixmap pm(50, 50);
+ pm.fill(Qt::red);
+ button.setIcon(pm);
+ button.setMenu(&menu);
+ button.setPopupMode(QToolButton::MenuButtonPopup);
+
+ button.show();
+ const QSize unstyledSizeHint = button.sizeHint();
+
+ qApp->setStyleSheet(styleSheet);
+ const QSize styledSizeHint = button.sizeHint();
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ QEXPECT_FAIL("Enum value", "In Qt 5, style sheet selectors have to use integer enum values", Continue);
+#else
+ QEXPECT_FAIL("Int value", "In Qt 6, style sheet selectors must use the enum value name", Continue);
+#endif
+
+ QVERIFY(styledSizeHint.width() > unstyledSizeHint.width());
+}
+
QTEST_MAIN(tst_QStyleSheetStyle)
#include "tst_qstylesheetstyle.moc"
diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
index 89c4a74739..364bc36dff 100644
--- a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
+++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
@@ -113,6 +113,8 @@ private slots:
#endif
void fileSystemModel_data();
void fileSystemModel();
+ void fileDialog_data();
+ void fileDialog();
void changingModel_data();
void changingModel();
@@ -695,7 +697,26 @@ void tst_QCompleter::fileSystemModel()
#ifdef Q_OS_WINRT
QSKIP("WinRT cannot access directories outside of the application's sandbox");
#endif
- //QFileSystemModel is assync.
+ //QFileSystemModel is async.
+ filter(true);
+}
+
+/*!
+ In the file dialog, the completer uses the EditRole.
+ See QTBUG-94799
+*/
+void tst_QCompleter::fileDialog_data()
+{
+ fileSystemModel_data();
+ completer->setCompletionRole(Qt::EditRole);
+}
+
+void tst_QCompleter::fileDialog()
+{
+#ifdef Q_OS_WINRT
+ QSKIP("WinRT cannot access directories outside of the application's sandbox");
+#endif
+ //QFileSystemModel is async.
filter(true);
}
diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
index 01ecfb2ca9..ec1013a078 100644
--- a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
+++ b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
@@ -37,6 +37,7 @@
#include <qlabel.h>
#include <qwidget.h>
#include <qdialog.h>
+#include <qscroller.h>
class tst_QAbstractScrollArea : public QObject
{
@@ -57,6 +58,7 @@ private slots:
void task214488_layoutDirection();
void margins();
+ void resizeWithOvershoot();
};
tst_QAbstractScrollArea::tst_QAbstractScrollArea()
@@ -398,5 +400,42 @@ void tst_QAbstractScrollArea::margins()
QCOMPARE(area.viewportMargins(), margins);
}
+void tst_QAbstractScrollArea::resizeWithOvershoot()
+{
+ QWidget window;
+
+ QScrollArea scrollArea(&window);
+ scrollArea.setWidget([]{
+ QWidget *widget = new QWidget;
+ widget->setFixedSize(QSize(0, 200));
+ return widget;
+ }());
+ scrollArea.setGeometry(0, 20, 100, 100);
+
+ QScroller::grabGesture(&scrollArea, QScroller::LeftMouseButtonGesture);
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ const QPoint originAtRest = scrollArea.viewport()->pos();
+
+ QPoint center = scrollArea.viewport()->mapToGlobal(scrollArea.viewport()->rect().center());
+ center = window.windowHandle()->mapFromGlobal(center);
+ QTest::mousePress(window.windowHandle(), Qt::LeftButton, {}, center);
+ QTest::mouseMove(window.windowHandle(), center + QPoint(0, 50));
+ QTRY_COMPARE(scrollArea.viewport()->pos(), originAtRest + QPoint(0, 25));
+ QPoint overshootPosition = scrollArea.viewport()->pos();
+
+ // trigger a layout of the scroll area while there's overshoot
+ scrollArea.setGeometry(0, 0, 100, 120);
+ QCOMPARE(scrollArea.viewport()->pos(), overshootPosition);
+ QTest::mouseRelease(window.windowHandle(), Qt::LeftButton, {}, center + QPoint(0, 50));
+ QTRY_COMPARE(scrollArea.viewport()->pos(), originAtRest);
+ // Process a few more events and verify that the scroll area
+ // doesn't overcompensate for the overshoot.
+ QApplication::processEvents();
+ QTRY_COMPARE(scrollArea.viewport()->pos(), originAtRest);
+}
+
QTEST_MAIN(tst_QAbstractScrollArea)
#include "tst_qabstractscrollarea.moc"
diff --git a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
index c3ae2ea541..2d74e71302 100644
--- a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
+++ b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
@@ -188,6 +188,10 @@ void tst_QCalendarWidget::buttonClickCheck()
QTest::mouseMove(widget);
QTest::mouseClick(widget, Qt::LeftButton);
QCOMPARE(2006, object.yearShown());
+ QTest::mouseClick(button, Qt::LeftButton, Qt::NoModifier, button->rect().center(), 2);
+ QTest::mouseMove(widget);
+ QTest::mouseClick(widget, Qt::LeftButton);
+ QCOMPARE(button->text(), "2006"); // Check that it is shown as a year should be
object.setSelectedDate(selectedDate);
object.showSelectedDate();
QTest::keyClick(widget, Qt::Key_Down);
diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
index 86a7b112d2..7af60ed757 100644
--- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
+++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -166,6 +166,8 @@ private slots:
void inputMethodUpdate();
void task_QTBUG_52027_mapCompleterIndex();
void checkMenuItemPosWhenStyleSheetIsSet();
+ void checkEmbeddedLineEditWhenStyleSheetIsSet();
+ void propagateStyleChanges();
private:
PlatformInputContext m_platformInputContext;
@@ -1680,6 +1682,16 @@ void tst_QComboBox::setModel()
QCOMPARE(box.rootModelIndex(), rootModelIndex);
box.setModel(box.model());
QCOMPARE(box.rootModelIndex(), rootModelIndex);
+
+ // check that setting the same model as the completer's doesn't crash
+ QCompleter *completer = new QCompleter(&box);
+ box.setEditable(true);
+ box.setCompleter(completer);
+ auto *listModel = new QStringListModel({ "one", "two" }, completer);
+ completer->setModel(listModel);
+ QCOMPARE(listModel->rowCount(), 2); // make sure it wasn't deleted
+ box.setModel(listModel);
+ QCOMPARE(listModel->rowCount(), 2); // make sure it wasn't deleted
}
void tst_QComboBox::setCustomModelAndView()
@@ -3559,5 +3571,76 @@ void tst_QComboBox::checkMenuItemPosWhenStyleSheetIsSet()
qApp->setStyleSheet(oldCss);
}
+void tst_QComboBox::checkEmbeddedLineEditWhenStyleSheetIsSet()
+{
+ QString newCss = "QWidget { background-color: red; color: white; }";
+ QString oldCss = qApp->styleSheet();
+ qApp->setStyleSheet(newCss);
+
+ QWidget topLevel;
+ auto layout = new QVBoxLayout(&topLevel);
+ topLevel.setLayout(layout);
+ auto comboBox = new QComboBox;
+ layout->addWidget(comboBox);
+ topLevel.show();
+ comboBox->setEditable(true);
+ QApplication::setActiveWindow(&topLevel);
+ QVERIFY(QTest::qWaitForWindowActive(&topLevel));
+
+ QImage grab = comboBox->grab().toImage();
+ auto color = grab.pixelColor(grab.rect().center());
+
+ QVERIFY(color.red() > 240);
+ QVERIFY(color.green() < 20);
+ QVERIFY(color.blue() < 20);
+
+ qApp->setStyleSheet(oldCss);
+}
+
+/*!
+ Tests that the style-based frame style propagates to the internal container
+ widget of QComboBox when the style changes by verifying that the respective
+ styleHint is asked for when the style changes.
+
+ See QTBUG-92488
+*/
+void tst_QComboBox::propagateStyleChanges()
+{
+ class FrameStyle : public QProxyStyle
+ {
+ public:
+ FrameStyle(int frameStyle, QStyle *style = nullptr)
+ : QProxyStyle(style), frameStyle(frameStyle)
+ {}
+
+ int styleHint(QStyle::StyleHint hint, const QStyleOption *opt,
+ const QWidget *widget, QStyleHintReturn *returnData) const
+ {
+ if (hint == QStyle::SH_ComboBox_PopupFrameStyle) {
+ inquired = true;
+ return frameStyle;
+ }
+ return QProxyStyle::styleHint(hint, opt, widget, returnData);
+ }
+
+ int frameStyle;
+ mutable bool inquired = false;
+ };
+
+ FrameStyle framelessStyle(QFrame::NoFrame);
+ FrameStyle frameStyle(QFrame::Plain | QFrame::Sunken);
+
+ QComboBox combo;
+ // container will be created and take settings from this style
+ combo.setStyle(&framelessStyle);
+ QVERIFY(framelessStyle.inquired);
+ combo.addItem(QLatin1String("Open"));
+ combo.addItem(QLatin1String("Close"));
+ // needed because of QComboBox's adjustSizeTimer not doing anything otherwise
+ combo.setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ combo.setStyle(&frameStyle);
+ QVERIFY(frameStyle.inquired);
+}
+
QTEST_MAIN(tst_QComboBox)
#include "tst_qcombobox.moc"
diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
index 1582835fda..c670147920 100644
--- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
+++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -1370,19 +1370,19 @@ void tst_QDateTimeEdit::editingRanged()
QFETCH(QString, userInput);
QFETCH(QDateTime, expected);
- QDateTimeEdit *edit;
+ QScopedPointer<QDateTimeEdit> edit;
if (minTime.isValid()) {
- edit = new QDateTimeEdit;
+ edit.reset(new QDateTimeEdit);
edit->setDisplayFormat("dd.MM.yyyy hh:mm");
edit->setDateTimeRange(QDateTime(minDate, minTime), QDateTime(maxDate, maxTime));
} else {
- edit = new QDateEdit;
+ edit.reset(new QDateEdit);
edit->setDisplayFormat("dd.MM.yyyy");
edit->setDateRange(minDate, maxDate);
}
int callCount = 0;
- connect(edit, &QDateTimeEdit::dateTimeChanged, [&](const QDateTime &dateTime) {
+ connect(edit.get(), &QDateTimeEdit::dateTimeChanged, [&](const QDateTime &dateTime) {
++callCount;
if (minTime.isValid()) {
QVERIFY(dateTime >= QDateTime(minDate, minTime));
@@ -1394,15 +1394,15 @@ void tst_QDateTimeEdit::editingRanged()
});
edit->show();
- QApplication::setActiveWindow(edit);
- if (!QTest::qWaitForWindowActive(edit))
+ QApplication::setActiveWindow(edit.get());
+ if (!QTest::qWaitForWindowActive(edit.get()))
QSKIP("Failed to make window active, aborting");
edit->setFocus();
// with keyboard tracking, never get a signal with an out-of-range value
edit->setKeyboardTracking(true);
- QTest::keyClicks(edit, userInput);
- QTest::keyClick(edit, Qt::Key_Return);
+ QTest::keyClicks(edit.get(), userInput);
+ QTest::keyClick(edit.get(), Qt::Key_Return);
QVERIFY(callCount > 0);
// QDateTimeEdit blocks these dates from being entered - see QTBUG-65
@@ -1418,12 +1418,10 @@ void tst_QDateTimeEdit::editingRanged()
callCount = 0;
edit->setKeyboardTracking(false);
- QTest::keyClicks(edit, userInput);
- QTest::keyClick(edit, Qt::Key_Return);
+ QTest::keyClicks(edit.get(), userInput);
+ QTest::keyClick(edit.get(), Qt::Key_Return);
QCOMPARE(edit->dateTime(), expected);
QCOMPARE(callCount, 1);
-
- delete edit;
}
void tst_QDateTimeEdit::wrappingTime_data()
@@ -3807,7 +3805,6 @@ void tst_QDateTimeEdit::deleteCalendarWidget()
{
{
// setup
- QCalendarWidget *cw = 0;
QDateEdit edit;
QVERIFY(!edit.calendarWidget());
edit.setCalendarPopup(true);
@@ -3815,8 +3812,7 @@ void tst_QDateTimeEdit::deleteCalendarWidget()
edit.calendarWidget()->setObjectName("cw1");;
// delete
- cw = edit.calendarWidget();
- delete cw;
+ delete edit.calendarWidget();
// it should create a new widget
QVERIFY(edit.calendarWidget());
@@ -4475,7 +4471,7 @@ static QDateTime findSpring(int year, const QTimeZone &timeZone)
return QDateTime();
// Southern hemisphere spring is after midsummer
- const QDateTime midSummer = QDate(year, 6, 21).startOfDay();
+ const QDateTime midSummer = QDate(year, 6, 21).startOfDay(timeZone);
const QTimeZone::OffsetData transition =
midSummer.isDaylightTime() ? timeZone.previousTransition(midSummer)
: timeZone.nextTransition(midSummer);
@@ -4596,7 +4592,7 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data()
QTest::addColumn<int>("steps");
QTest::addColumn<QDateTime>("end");
- const QTimeZone timeZone = QTimeZone::systemTimeZone();
+ const QTimeZone timeZone = QTimeZone("Europe/Oslo");
if (!timeZone.hasDaylightTime())
QSKIP("This test needs to run in a timezone that observes DST!");
@@ -4611,14 +4607,14 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data()
// change hour
if (springGap.hour() != 0) {
QTest::addRow("hour up into %s gap", qPrintable(springGap.toString("hh:mm")))
- << QDateTime(spring, springGap.addSecs(-3600))
+ << QDateTime(spring, springGap.addSecs(-3600), timeZone)
<< QDateTimeEdit::HourSection
<< +1
<< springTransition;
// 3:00:10 into 2:00:10 should get us to 1:00:10
QTest::addRow("hour down into %s gap", qPrintable(springGap.toString("hh:mm")))
- << QDateTime(spring, springGap.addSecs(3610))
+ << QDateTime(spring, springGap.addSecs(3610), timeZone)
<< QDateTimeEdit::HourSection
<< -1
<< QDateTime(spring, springGap.addSecs(-3590));
@@ -4628,7 +4624,7 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data()
if (spring.day() != 1) {
// today's 2:05 is tomorrow's 3:05
QTest::addRow("day up into %s gap", qPrintable(springGap.toString("hh:mm")))
- << QDateTime(spring.addDays(-1), springGap.addSecs(300))
+ << QDateTime(spring.addDays(-1), springGap.addSecs(300), timeZone)
<< QDateTimeEdit::DaySection
<< +1
<< springTransition.addSecs(300);
@@ -4636,7 +4632,7 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data()
if (spring.day() != spring.daysInMonth()) {
QTest::addRow("day down into %s gap", qPrintable(springGap.toString("hh:mm")))
- << QDateTime(spring.addDays(1), springGap)
+ << QDateTime(spring.addDays(1), springGap, timeZone)
<< QDateTimeEdit::DaySection
<< -1
<< springTransition;
@@ -4644,24 +4640,24 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data()
// 2018-03-25 - change month
QTest::addRow("month up into %s gap", qPrintable(springGap.toString("hh:mm")))
- << QDateTime(spring.addMonths(-1), springGap)
+ << QDateTime(spring.addMonths(-1), springGap, timeZone)
<< QDateTimeEdit::MonthSection
<< +1
<< springTransition;
QTest::addRow("month down into %s gap", qPrintable(springGap.toString("hh:mm")))
- << QDateTime(spring.addMonths(1), springGap)
+ << QDateTime(spring.addMonths(1), springGap, timeZone)
<< QDateTimeEdit::MonthSection
<< -1
<< springTransition;
// 2018-03-25 - change year
QTest::addRow("year up into %s gap", qPrintable(springGap.toString("hh:mm")))
- << QDateTime(spring.addYears(-1), springGap)
+ << QDateTime(spring.addYears(-1), springGap, timeZone)
<< QDateTimeEdit::YearSection
<< +1
<< springTransition;
QTest::addRow("year down into %s gap", qPrintable(springGap.toString("hh:mm")))
- << QDateTime(spring.addYears(1), springGap)
+ << QDateTime(spring.addYears(1), springGap, timeZone)
<< QDateTimeEdit::YearSection
<< -1
<< springTransition;
diff --git a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
index c293a4bdd2..986a830b8b 100644
--- a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
+++ b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
@@ -777,17 +777,17 @@ void tst_QDoubleSpinBox::valueFromTextAndValidate_data()
QTest::newRow("data1") << QString() << Intermediate << 0.0 << 100.0 << (int)QLocale::C << QString();
QTest::newRow("data2") << QString("asd") << Invalid << 0.0 << 100.0 << (int)QLocale::C << QString();
QTest::newRow("data3") << QString("2.2") << Acceptable << 0.0 << 100.0 << (int)QLocale::C << QString();
- QTest::newRow("data4") << QString(" ") << Intermediate << 0.0 << 100.0 << (int)QLocale::Norwegian << QString();
+ QTest::newRow("data4") << QString(" ") << Intermediate << 0.0 << 100.0 << (int)QLocale::NorwegianBokmal << QString();
QTest::newRow("data5") << QString(" ") << Intermediate << 0.0 << 100.0 << (int)QLocale::C << QString();
- QTest::newRow("data6") << QString(",") << Intermediate << 0.0 << 100.0 << (int)QLocale::Norwegian << QString();
+ QTest::newRow("data6") << QString(",") << Intermediate << 0.0 << 100.0 << (int)QLocale::NorwegianBokmal << QString();
QTest::newRow("data7") << QString(",") << Invalid << 0.0 << 100.0 << (int)QLocale::C << QString();
- QTest::newRow("data8") << QString("1 ") << Acceptable << 0.0 << 1000.0 << (int)QLocale::Norwegian << QString("1");
+ QTest::newRow("data8") << QString("1 ") << Acceptable << 0.0 << 1000.0 << (int)QLocale::NorwegianBokmal << QString("1");
QTest::newRow("data9") << QString("1 ") << Acceptable << 0.0 << 100.0 << (int)QLocale::C << QString("1");
- QTest::newRow("data10") << QString(" 1") << Acceptable << 0.0 << 100.0 << (int)QLocale::Norwegian << QString("1");
+ QTest::newRow("data10") << QString(" 1") << Acceptable << 0.0 << 100.0 << (int)QLocale::NorwegianBokmal << QString("1");
QTest::newRow("data11") << QString(" 1") << Acceptable << 0.0 << 100.0 << (int)QLocale::C << QString("1");
- QTest::newRow("data12") << QString("1,") << Acceptable << 0.0 << 100.0 << (int)QLocale::Norwegian << QString();
+ QTest::newRow("data12") << QString("1,") << Acceptable << 0.0 << 100.0 << (int)QLocale::NorwegianBokmal << QString();
QTest::newRow("data13") << QString("1,") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString();
- QTest::newRow("data14") << QString("1, ") << Acceptable << 0.0 << 100.0 << (int)QLocale::Norwegian << QString("1,");
+ QTest::newRow("data14") << QString("1, ") << Acceptable << 0.0 << 100.0 << (int)QLocale::NorwegianBokmal << QString("1,");
QTest::newRow("data15") << QString("1, ") << Invalid << 0.0 << 100.0 << (int)QLocale::C << QString();
QTest::newRow("data16") << QString("2") << Intermediate << 100.0 << 102.0 << (int)QLocale::C << QString();
QTest::newRow("data17") << QString("22.0") << Intermediate << 100.0 << 102.0 << (int)QLocale::C << QString();
@@ -826,7 +826,7 @@ void tst_QDoubleSpinBox::valueFromTextAndValidate_data()
QTest::newRow("data50") << QString("2.2") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString();
QTest::newRow("data51") << QString("2.2,00") << Invalid << 0.0 << 1000.0 << (int)QLocale::C << QString();
QTest::newRow("data52") << QString("2..2,00") << Invalid << 0.0 << 1000.0 << (int)QLocale::German << QString();
- QTest::newRow("data53") << QString("2.2") << Invalid << 0.0 << 1000.0 << (int)QLocale::Norwegian << QString();
+ QTest::newRow("data53") << QString("2.2") << Invalid << 0.0 << 1000.0 << (int)QLocale::NorwegianBokmal << QString();
QTest::newRow("data54") << QString(" 2.2") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString();
QTest::newRow("data55") << QString("2.2 ") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString("2.2");
QTest::newRow("data56") << QString(" 2.2 ") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString("2.2");
diff --git a/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp b/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp
index 657a1ea55c..c1c0cdaef3 100644
--- a/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp
+++ b/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp
@@ -95,7 +95,7 @@ void tst_QFocusFrame::focusFrameInsideScrollview()
window.show();
QFocusFrame *focusFrame = nullptr;
- QTRY_VERIFY(focusFrame = window.findChild<QFocusFrame *>());
+ QTRY_VERIFY((focusFrame = window.findChild<QFocusFrame *>()));
const QPoint initialOffset = focusFrame->widget()->mapToGlobal(QPoint()) - focusFrame->mapToGlobal(QPoint());
tableView.scrollTo(itemModel->index(40, 0));
diff --git a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
index bd3ea5686a..75f595e959 100644
--- a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
+++ b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
@@ -261,15 +261,18 @@ void tst_QFontComboBox::writingSystem()
// protected void currentFontChanged(QFont const& f)
void tst_QFontComboBox::currentFontChanged()
{
- SubQFontComboBox box;
- QSignalSpy spy0(&box, SIGNAL(currentFontChanged(QFont)));
+ // The absence of this file does not affect the test results
+ QFontDatabase::addApplicationFont("ArianaVioleta-dz2K.ttf");
+
+ SubQFontComboBox *box = new SubQFontComboBox;
+ QSignalSpy spy0(box, SIGNAL(currentFontChanged(QFont)));
- if (box.model()->rowCount() > 2) {
- QTest::keyPress(&box, Qt::Key_Down);
+ if (box->model()->rowCount() > 2) {
+ QTest::keyPress(box, Qt::Key_Down);
QCOMPARE(spy0.count(), 1);
QFont f( "Sans Serif" );
- box.setCurrentFont(f);
+ box->setCurrentFont(f);
QCOMPARE(spy0.count(), 2);
} else
qWarning("Not enough fonts installed on test system. Consider adding some");
diff --git a/tests/auto/widgets/widgets/qlineedit/BLACKLIST b/tests/auto/widgets/widgets/qlineedit/BLACKLIST
index 537c81413e..fdb097ee09 100644
--- a/tests/auto/widgets/widgets/qlineedit/BLACKLIST
+++ b/tests/auto/widgets/widgets/qlineedit/BLACKLIST
@@ -29,3 +29,15 @@ android
# QTBUG-69115
[testQuickSelectionWithMouse]
android
+
+[inputRejected]
+winrt
+
+[QTBUG5786_undoPaste]
+winrt
+
+[cut]
+winrt
+
+[cutWithoutSelection]
+winrt
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index 6408df3f11..2f1a095f91 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -292,6 +292,7 @@ private slots:
void clearButtonVisibleAfterSettingText_QTBUG_45518();
void sideWidgets();
void sideWidgetsActionEvents();
+ void sideWidgetsEffectiveMargins();
void shouldShowPlaceholderText_data();
void shouldShowPlaceholderText();
@@ -4646,6 +4647,71 @@ void tst_QLineEdit::sideWidgetsActionEvents()
QCOMPARE(toolButton2->x(), toolButton1X);
}
+/*!
+ Verify that side widgets are positioned correctly and result in
+ correct effective text margins.
+*/
+void tst_QLineEdit::sideWidgetsEffectiveMargins()
+{
+#ifndef QT_BUILD_INTERNAL
+ QSKIP("This test requires a developer build.");
+#else
+ QLineEdit edit;
+ edit.setPlaceholderText("placeholder");
+ edit.setClearButtonEnabled(true);
+ edit.show();
+ QLineEditPrivate *priv = QLineEditPrivate::get(&edit);
+ const auto sideWidgetParameters = priv->sideWidgetParameters();
+ const int sideWidgetWidth = sideWidgetParameters.widgetWidth + sideWidgetParameters.margin;
+ QVERIFY(QTest::qWaitForWindowExposed(&edit));
+
+ QCOMPARE(priv->effectiveTextMargins().left(), 0);
+ QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+ edit.setText("Left to right"); // clear button fades in on the right
+ QCOMPARE(priv->effectiveTextMargins().left(), 0);
+ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+ edit.clear();
+ QCOMPARE(priv->effectiveTextMargins().left(), 0);
+ QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+ edit.setLayoutDirection(Qt::RightToLeft);
+ edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), 0);
+ edit.clear();
+ QCOMPARE(priv->effectiveTextMargins().left(), 0);
+ QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+ edit.setLayoutDirection(Qt::LeftToRight);
+
+ const QIcon leftIcon = edit.style()->standardIcon(QStyle::SP_FileIcon);
+ const QIcon rightIcon = edit.style()->standardIcon(QStyle::SP_DirIcon);
+ edit.addAction(leftIcon, QLineEdit::ActionPosition::LeadingPosition);
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+ edit.addAction(rightIcon, QLineEdit::ActionPosition::TrailingPosition);
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+
+ edit.setText("Left to right"); // clear button on the right
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), 2 * sideWidgetWidth);
+ edit.clear();
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+
+ edit.setLayoutDirection(Qt::RightToLeft);
+ edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left
+ QCOMPARE(priv->effectiveTextMargins().left(), 2 * sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+ edit.clear();
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+#endif
+}
+
Q_DECLARE_METATYPE(Qt::AlignmentFlag)
void tst_QLineEdit::shouldShowPlaceholderText_data()
{
@@ -4893,7 +4959,7 @@ void tst_QLineEdit::testQuickSelectionWithMouse()
QVERIFY(lineEdit.selectedText().endsWith(suffix));
QTest::mouseMove(lineEdit.windowHandle(), center + QPoint(20, 0));
qCDebug(lcTests) << "Selected text:" << lineEdit.selectedText();
-#ifdef Q_PROCESSOR_ARM
+#if defined(Q_PROCESSOR_ARM) && !defined(Q_OS_MACOS)
QEXPECT_FAIL("", "Currently fails on gcc-armv7, needs investigation.", Continue);
#endif
QCOMPARE(lineEdit.selectedText(), partialSelection);
diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
index 01d625d091..6f4431ab92 100644
--- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
+++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
@@ -1349,14 +1349,19 @@ void tst_QMainWindow::restoreState()
dw.setObjectName(QLatin1String("dock"));
mw.addDockWidget(Qt::LeftDockWidgetArea, &dw);
+ QWidgetPrivate *tbp = QWidgetPrivate::get(&tb);
+ QVERIFY(tbp->widgetItem);
+
QByteArray state;
state = mw.saveState();
QVERIFY(mw.restoreState(state));
+ QVERIFY(tbp->widgetItem);
state = mw.saveState(1);
QVERIFY(!mw.restoreState(state));
QVERIFY(mw.restoreState(state, 1));
+ QVERIFY(tbp->widgetItem);
}
//tests the restoration of the previous versions of window settings
diff --git a/tests/auto/widgets/widgets/qmdiarea/BLACKLIST b/tests/auto/widgets/widgets/qmdiarea/BLACKLIST
index 6010772be7..1108acd027 100644
--- a/tests/auto/widgets/widgets/qmdiarea/BLACKLIST
+++ b/tests/auto/widgets/widgets/qmdiarea/BLACKLIST
@@ -11,3 +11,6 @@ opensuse-42.3
[resizeTimer]
macos
+[updateScrollBars]
+macos
+
diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
index e3b046e448..91bc638257 100644
--- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
+++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
@@ -1,4 +1,4 @@
-/****************************************************************************
+/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
@@ -282,6 +282,8 @@ private slots:
void nativeSubWindows();
void task_209615();
void task_236750();
+ void qtbug92240_title_data();
+ void qtbug92240_title();
private:
QMdiSubWindow *activeWindow;
@@ -2749,6 +2751,45 @@ void tst_QMdiArea::task_236750()
subWindow->showMinimized();
}
+// QTBUG-92240: When subwindows are maximized, their title is supposed to
+// appear on the main window. When DontMaximizeSubWindowOnActivation was set,
+// titles of previously created maximized windows interfered, resulting in
+// "QTBUG-92240 - [1] - [2]".
+void tst_QMdiArea::qtbug92240_title_data()
+{
+ QTest::addColumn<bool>("dontMaximize");
+ QTest::newRow("default") << false;
+ QTest::newRow("dontMaximize") << true;
+}
+
+void tst_QMdiArea::qtbug92240_title()
+{
+ QFETCH(bool, dontMaximize);
+
+#ifdef Q_OS_MACOS
+ QSKIP("Not supported on macOS");
+#endif
+
+ QMainWindow w;
+ const QString title = QStringLiteral("QTBUG-92240");
+ w.setWindowTitle(title);
+ w.menuBar()->addMenu(QStringLiteral("File"));
+ w.show();
+
+ auto *mdiArea = new QMdiArea;
+ w.setCentralWidget(mdiArea);
+ if (dontMaximize)
+ mdiArea->setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+ auto *sw1 = mdiArea->addSubWindow(new QWidget);
+ sw1->setWindowTitle(QStringLiteral("1"));
+ sw1->showMaximized();
+ QTRY_COMPARE(w.windowTitle(), QLatin1String("QTBUG-92240 - [1]"));
+ auto *sw2 = mdiArea->addSubWindow(new QWidget);
+ sw2->setWindowTitle(QStringLiteral("2"));
+ sw2->showMaximized();
+ QTRY_COMPARE(w.windowTitle(), QLatin1String("QTBUG-92240 - [2]"));
+}
+
QTEST_MAIN(tst_QMdiArea)
#include "tst_qmdiarea.moc"
diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
index 5a24995caf..48b171f234 100644
--- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
+++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
@@ -174,7 +174,9 @@ void tst_QMenu::getSetCheck()
tst_QMenu::tst_QMenu()
: m_onStatusTipTimerExecuted(false)
{
+ QApplication::setEffectEnabled(Qt::UI_FadeTooltip, false);
QApplication::setEffectEnabled(Qt::UI_AnimateMenu, false);
+ QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, false);
}
void tst_QMenu::initTestCase()
diff --git a/tests/auto/widgets/widgets/qmenubar/BLACKLIST b/tests/auto/widgets/widgets/qmenubar/BLACKLIST
index c9e15e531c..4e48ba05d3 100644
--- a/tests/auto/widgets/widgets/qmenubar/BLACKLIST
+++ b/tests/auto/widgets/widgets/qmenubar/BLACKLIST
@@ -2,6 +2,7 @@
ubuntu-16.04
#QTBUG-66255
ubuntu-18.04
+ubuntu-22.04
[activatedCount]
opensuse-42.3
[QTBUG_65488_hiddenActionTriggered]
diff --git a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST
index b281eca3bf..6c31a8d1d6 100644
--- a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST
+++ b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST
@@ -1,3 +1,4 @@
[stackWidgetOpaqueChildIsVisible]
windows-10 msvc-2017
+sles-15.4 # QTBUG-104241
diff --git a/tests/auto/widgets/widgets/qplaintextedit/BLACKLIST b/tests/auto/widgets/widgets/qplaintextedit/BLACKLIST
new file mode 100644
index 0000000000..a402cee376
--- /dev/null
+++ b/tests/auto/widgets/widgets/qplaintextedit/BLACKLIST
@@ -0,0 +1,6 @@
+[clearMustNotChangeClipboard]
+winrt
+[undoAvailableAfterPaste]
+winrt
+[copyAndSelectAllInReadonly]
+winrt
diff --git a/tests/auto/widgets/widgets/qplaintextedit/qplaintextedit.pro b/tests/auto/widgets/widgets/qplaintextedit/qplaintextedit.pro
index be4102ec75..19a5aaa13c 100644
--- a/tests/auto/widgets/widgets/qplaintextedit/qplaintextedit.pro
+++ b/tests/auto/widgets/widgets/qplaintextedit/qplaintextedit.pro
@@ -10,3 +10,5 @@ HEADERS +=
SOURCES += tst_qplaintextedit.cpp
osx: LIBS += -framework AppKit
+
+winrt:CONFIG += insignificant_test #QTBUG-90441
diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
index a86784f2ec..64c709d72f 100644
--- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
+++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
@@ -148,7 +148,7 @@ private slots:
void layoutAfterMultiLineRemove();
void undoCommandRemovesAndReinsertsBlock();
void taskQTBUG_43562_lineCountCrash();
-#ifndef QT_NO_CONTEXTMENU
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
void contextMenu();
#endif
void inputMethodCursorRect();
@@ -1740,7 +1740,7 @@ void tst_QPlainTextEdit::taskQTBUG_43562_lineCountCrash()
disconnect(ed->document(), SIGNAL(contentsChange(int, int, int)), 0, 0);
}
-#ifndef QT_NO_CONTEXTMENU
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
void tst_QPlainTextEdit::contextMenu()
{
ed->appendHtml(QStringLiteral("Hello <a href='http://www.qt.io'>Qt</a>"));
@@ -1774,7 +1774,7 @@ void tst_QPlainTextEdit::contextMenu()
delete menu;
QVERIFY(!ed->findChild<QAction *>(QStringLiteral("link-copy")));
}
-#endif // QT_NO_CONTEXTMENU
+#endif // QT_NO_CONTEXTMENU && QT_NO_CLIPBOARD
// QTBUG-51923: Verify that the cursor rectangle returned by the input
// method query correctly reflects the viewport offset.
diff --git a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
index 94cb42cc00..e818514a79 100644
--- a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
+++ b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
@@ -68,6 +68,7 @@ private slots:
void taskQTBUG_20191_shortcutWithKeypadModifer();
void emitReleasedAfterChange();
void hitButton();
+ void iconOnlyStyleSheet();
protected slots:
void resetCounters();
@@ -695,5 +696,22 @@ void tst_QPushButton::hitButton()
QVERIFY(!button2->hitButton(QPoint(2, 2)));
}
+/*
+ Test that a style sheet with only icon doesn't crash.
+ QTBUG-91735
+*/
+void tst_QPushButton::iconOnlyStyleSheet()
+{
+ QIcon icon(":/qt-project.org/styles/commonstyle/images/dvd-32.png");
+ QVERIFY(!icon.isNull());
+ QPushButton pb;
+ pb.setStyleSheet("QPushButton {"
+ "icon: url(:/qt-project.org/styles/commonstyle/images/dvd-32.png);"
+ "border: red;"
+ "}");
+ pb.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&pb));
+}
+
QTEST_MAIN(tst_QPushButton)
#include "tst_qpushbutton.moc"
diff --git a/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp b/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
index 9f08bd337b..d817d84710 100644
--- a/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
+++ b/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
@@ -33,6 +33,7 @@
#include <qdebug.h>
#include <qscrollarea.h>
#include <qlayout.h>
+#include <qscrollbar.h>
class tst_QScrollArea : public QObject
{
@@ -46,6 +47,7 @@ private slots:
void getSetCheck();
void ensureMicroFocusVisible_Task_167838();
void checkHFW_Task_197736();
+ void stableHeightForWidth();
};
tst_QScrollArea::tst_QScrollArea()
@@ -165,5 +167,61 @@ void tst_QScrollArea::checkHFW_Task_197736()
QCOMPARE(w->height(), 200);
}
+
+/*
+ If the scroll area rides the size where, due to the height-for-width
+ implementation of the widget, the vertical scrollbar is needed only
+ if the vertical scrollbar is visible, then we don't want it to flip
+ back and forth, but rather constrain the width of the widget.
+ See QTBUG-92958.
+*/
+void tst_QScrollArea::stableHeightForWidth()
+{
+ struct HeightForWidthWidget : public QWidget
+ {
+ HeightForWidthWidget()
+ {
+ QSizePolicy policy = sizePolicy();
+ policy.setHeightForWidth(true);
+ setSizePolicy(policy);
+ }
+ // Aspect ratio 1:1
+ int heightForWidth(int width) const override { return width; }
+ };
+
+ class HeightForWidthArea : public QScrollArea
+ {
+ public:
+ HeightForWidthArea()
+ {
+ this->verticalScrollBar()->installEventFilter(this);
+ }
+ protected:
+ bool eventFilter(QObject *obj, QEvent *e) override
+ {
+ if (obj == verticalScrollBar() && e->type() == QEvent::Hide)
+ ++m_hideCount;
+ return QScrollArea::eventFilter(obj,e);
+ }
+ public:
+ int m_hideCount = 0;
+ };
+
+ HeightForWidthArea area;
+ HeightForWidthWidget equalWHWidget;
+ area.setWidget(&equalWHWidget);
+ area.setWidgetResizable(true);
+ // at this size, the widget wants to be 501 pixels high,
+ // requiring a vertical scrollbar in a 499 pixel high area.
+ // but the width resulting from showing the scrollbar would
+ // be less than 499, so no scrollbars would be needed anymore.
+ area.resize(501, 499);
+ area.show();
+ QTest::qWait(500);
+ // if the scrollbar got hidden more than once, then the layout
+ // isn't stable.
+ QVERIFY(area.m_hideCount <= 1);
+}
+
QTEST_MAIN(tst_QScrollArea)
#include "tst_qscrollarea.moc"
diff --git a/tests/auto/widgets/widgets/qspinbox/BLACKLIST b/tests/auto/widgets/widgets/qspinbox/BLACKLIST
index 96a7732165..a92a94c232 100644
--- a/tests/auto/widgets/widgets/qspinbox/BLACKLIST
+++ b/tests/auto/widgets/widgets/qspinbox/BLACKLIST
@@ -1,2 +1,3 @@
[stepModifierPressAndHold]
opensuse-42.3
+winrt
diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
index f8022559b2..0516bf5a16 100644
--- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
+++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
@@ -877,7 +877,7 @@ void tst_QSpinBox::locale_data()
QTest::addColumn<QString>("text");
QTest::addColumn<int>("valFromText");
- QTest::newRow("data0") << QLocale(QLocale::Norwegian, QLocale::Norway) << 1234 << QString("1234") << QString("2345") << 2345;
+ QTest::newRow("data0") << QLocale(QLocale::NorwegianBokmal, QLocale::Norway) << 1234 << QString("1234") << QString("2345") << 2345;
QTest::newRow("data1") << QLocale(QLocale::German, QLocale::Germany) << 1234 << QString("1234") << QString("2345") << 2345;
}
diff --git a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp
index ce1b8a430c..f04f803ecf 100644
--- a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp
+++ b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp
@@ -35,6 +35,8 @@
#include <qstyle.h>
#include <qstyleoption.h>
+class TabBar;
+
class tst_QTabBar : public QObject
{
Q_OBJECT
@@ -57,6 +59,7 @@ private slots:
void testCurrentChanged();
void insertAtCurrentIndex();
+ void insertAfterCurrentIndex();
void removeTab_data();
void removeTab();
@@ -94,6 +97,12 @@ private slots:
void autoHide();
void mouseReleaseOutsideTabBar();
+
+ void scrollButtons_data();
+ void scrollButtons();
+
+private:
+ void checkPositions(const TabBar &tabbar, const QList<int> &positions);
};
// Testing get/set functions
@@ -210,6 +219,14 @@ void tst_QTabBar::testCurrentChanged()
QCOMPARE(spy.count(), expectedCount);
}
+class TabBar : public QTabBar
+{
+public:
+ using QTabBar::initStyleOption;
+ using QTabBar::moveTab;
+ using QTabBar::QTabBar;
+};
+
void tst_QTabBar::insertAtCurrentIndex()
{
QTabBar tabBar;
@@ -223,6 +240,31 @@ void tst_QTabBar::insertAtCurrentIndex()
QCOMPARE(tabBar.currentIndex(), 3);
}
+void tst_QTabBar::insertAfterCurrentIndex()
+{
+ TabBar tabBar;
+
+ tabBar.addTab("Tab10");
+ checkPositions(tabBar, { QStyleOptionTab::OnlyOneTab });
+
+ tabBar.addTab("Tab20");
+ checkPositions(tabBar, { QStyleOptionTab::Beginning, QStyleOptionTab::End });
+
+ tabBar.insertTab(1, "Tab15");
+ checkPositions(tabBar,
+ { QStyleOptionTab::Beginning, QStyleOptionTab::Middle, QStyleOptionTab::End });
+
+ tabBar.insertTab(3, "Tab30");
+ checkPositions(tabBar,
+ { QStyleOptionTab::Beginning, QStyleOptionTab::Middle, QStyleOptionTab::Middle,
+ QStyleOptionTab::End });
+
+ tabBar.insertTab(3, "Tab25");
+ checkPositions(tabBar,
+ { QStyleOptionTab::Beginning, QStyleOptionTab::Middle, QStyleOptionTab::Middle,
+ QStyleOptionTab::Middle, QStyleOptionTab::End });
+}
+
void tst_QTabBar::removeTab_data()
{
QTest::addColumn<int>("currentIndex");
@@ -282,53 +324,36 @@ void tst_QTabBar::hideTab()
QTEST(tabbar.currentIndex(), "finalIndex");
}
-class TabBar : public QTabBar
-{
-public:
- using QTabBar::QTabBar;
- using QTabBar::initStyleOption;
- using QTabBar::moveTab;
-};
-
void tst_QTabBar::hideAllTabs()
{
TabBar tabbar;
- auto checkPositions = [&tabbar](const QVector<int> &positions)
- {
- QStyleOptionTab option;
- int iPos = 0;
- for (int i = 0; i < tabbar.count(); ++i) {
- if (!tabbar.isTabVisible(i))
- continue;
- tabbar.initStyleOption(&option, i);
- QCOMPARE(option.position, positions.at(iPos++));
- }
- };
tabbar.addTab("foo");
tabbar.addTab("bar");
tabbar.addTab("baz");
tabbar.setCurrentIndex(0);
- checkPositions({QStyleOptionTab::Beginning, QStyleOptionTab::Middle, QStyleOptionTab::End});
+ checkPositions(tabbar,
+ { QStyleOptionTab::Beginning, QStyleOptionTab::Middle, QStyleOptionTab::End });
// Check we don't crash trying to hide an unexistant tab
QSize prevSizeHint = tabbar.sizeHint();
tabbar.setTabVisible(3, false);
- checkPositions({QStyleOptionTab::Beginning, QStyleOptionTab::Middle, QStyleOptionTab::End});
+ checkPositions(tabbar,
+ { QStyleOptionTab::Beginning, QStyleOptionTab::Middle, QStyleOptionTab::End });
QCOMPARE(tabbar.currentIndex(), 0);
QSize sizeHint = tabbar.sizeHint();
QVERIFY(sizeHint.width() == prevSizeHint.width());
prevSizeHint = sizeHint;
tabbar.setTabVisible(1, false);
- checkPositions({QStyleOptionTab::Beginning, QStyleOptionTab::End});
+ checkPositions(tabbar, { QStyleOptionTab::Beginning, QStyleOptionTab::End });
QCOMPARE(tabbar.currentIndex(), 0);
sizeHint = tabbar.sizeHint();
QVERIFY(sizeHint.width() < prevSizeHint.width());
prevSizeHint = sizeHint;
tabbar.setTabVisible(2, false);
- checkPositions({QStyleOptionTab::OnlyOneTab});
+ checkPositions(tabbar, { QStyleOptionTab::OnlyOneTab });
QCOMPARE(tabbar.currentIndex(), 0);
sizeHint = tabbar.sizeHint();
QVERIFY(sizeHint.width() < prevSizeHint.width());
@@ -835,5 +860,83 @@ void tst_QTabBar::mouseReleaseOutsideTabBar()
QTRY_VERIFY(repaintChecker.repainted);
}
+void tst_QTabBar::checkPositions(const TabBar &tabbar, const QList<int> &positions)
+{
+ QStyleOptionTab option;
+ int iPos = 0;
+ for (int i = 0; i < tabbar.count(); ++i) {
+ if (!tabbar.isTabVisible(i))
+ continue;
+ tabbar.initStyleOption(&option, i);
+ QCOMPARE(option.position, positions.at(iPos++));
+ }
+}
+
+void tst_QTabBar::scrollButtons_data()
+{
+ QTest::addColumn<QTabWidget::TabPosition>("tabPosition");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+
+ for (auto ld : {Qt::LeftToRight, Qt::RightToLeft}) {
+ const char *ldStr = ld == Qt::LeftToRight ? "LTR" : "RTL";
+ QTest::addRow("North, %s", ldStr) << QTabWidget::North << ld;
+ QTest::addRow("South, %s", ldStr) << QTabWidget::South << ld;
+ QTest::addRow("West, %s", ldStr) << QTabWidget::West << ld;
+ QTest::addRow("East, %s", ldStr) << QTabWidget::East << ld;
+ }
+}
+
+void tst_QTabBar::scrollButtons()
+{
+ QFETCH(QTabWidget::TabPosition, tabPosition);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+
+ QWidget window;
+ QTabWidget tabWidget(&window);
+ tabWidget.setLayoutDirection(layoutDirection);
+ tabWidget.setTabPosition(tabPosition);
+ tabWidget.setElideMode(Qt::ElideNone);
+ tabWidget.setUsesScrollButtons(true);
+
+ const int tabCount = 5;
+ for (int i = 0; i < tabCount; ++i)
+ {
+ const QString num = QString::number(i);
+ tabWidget.addTab(new QPushButton(num), num + " - Really long tab name to force arrows");
+ }
+ tabWidget.move(0, 0);
+ tabWidget.resize(tabWidget.minimumSizeHint());
+ window.show();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+
+ auto *leftB = tabWidget.tabBar()->findChild<QAbstractButton*>(QStringLiteral("ScrollLeftButton"));
+ auto *rightB = tabWidget.tabBar()->findChild<QAbstractButton*>(QStringLiteral("ScrollRightButton"));
+
+ QVERIFY(leftB->isVisible());
+ QVERIFY(!leftB->isEnabled());
+ QVERIFY(rightB->isVisible());
+ QVERIFY(rightB->isEnabled());
+ QVERIFY(!tabWidget.tabBar()->tabRect(1).intersects(tabWidget.tabBar()->rect()));
+
+ int index = 0;
+ for (; index < tabWidget.count(); ++index) {
+ QCOMPARE(leftB->isEnabled(), index > 0);
+ QCOMPARE(rightB->isEnabled(), index < tabWidget.count() - 1);
+ QVERIFY(tabWidget.tabBar()->tabRect(index).intersects(tabWidget.tabBar()->rect()));
+ QCOMPARE(tabWidget.tabBar()->tabAt(tabWidget.tabBar()->rect().center()), index);
+ if (rightB->isEnabled())
+ rightB->click();
+ }
+ for (--index; index >= 0; --index) {
+ QCOMPARE(leftB->isEnabled(), index >= 0);
+ QCOMPARE(rightB->isEnabled(), index < tabWidget.count() - 1);
+
+ QVERIFY(tabWidget.tabBar()->tabRect(index).intersects(tabWidget.tabBar()->rect()));
+ if (leftB->isEnabled())
+ leftB->click();
+ }
+ QVERIFY(!leftB->isEnabled());
+}
+
QTEST_MAIN(tst_QTabBar)
#include "tst_qtabbar.moc"
diff --git a/tests/auto/widgets/widgets/qtextedit/BLACKLIST b/tests/auto/widgets/widgets/qtextedit/BLACKLIST
new file mode 100644
index 0000000000..a402cee376
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextedit/BLACKLIST
@@ -0,0 +1,6 @@
+[clearMustNotChangeClipboard]
+winrt
+[undoAvailableAfterPaste]
+winrt
+[copyAndSelectAllInReadonly]
+winrt
diff --git a/tests/auto/widgets/widgets/qtextedit/qtextedit.pro b/tests/auto/widgets/widgets/qtextedit/qtextedit.pro
index de8531daec..ca79a720ef 100644
--- a/tests/auto/widgets/widgets/qtextedit/qtextedit.pro
+++ b/tests/auto/widgets/widgets/qtextedit/qtextedit.pro
@@ -8,3 +8,5 @@ SOURCES += tst_qtextedit.cpp
osx: LIBS += -framework AppKit
TESTDATA += fullWidthSelection
+
+winrt:CONFIG += insignificant_test #QTBUG-90441
diff --git a/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST b/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST
index 315e179d0a..b641e471cd 100644
--- a/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST
+++ b/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST
@@ -1,2 +1,3 @@
[task176137_autoRepeatOfAction]
macos
+winrt