mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-05 08:45:25 +08:00
qt 6.5.1 original
This commit is contained in:
@ -0,0 +1,15 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qdatawidgetmapper Test:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test(tst_qdatawidgetmapper
|
||||
SOURCES
|
||||
tst_qdatawidgetmapper.cpp
|
||||
LIBRARIES
|
||||
Qt::Gui
|
||||
Qt::Widgets
|
||||
Qt::WidgetsPrivate
|
||||
)
|
@ -0,0 +1,458 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDataWidgetMapper>
|
||||
#include <QLineEdit>
|
||||
#include <QMetaType>
|
||||
#include <QStandardItemModel>
|
||||
#include <QSignalSpy>
|
||||
#include <QTest>
|
||||
#include <QTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <QtWidgets/private/qapplication_p.h>
|
||||
|
||||
class tst_QDataWidgetMapper: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void initTestCase();
|
||||
|
||||
void setModel();
|
||||
void navigate();
|
||||
void addMapping();
|
||||
void currentIndexChanged();
|
||||
void changingValues();
|
||||
void setData();
|
||||
void mappedWidgetAt();
|
||||
|
||||
void comboBox();
|
||||
|
||||
void textEditDoesntChangeFocusOnTab_qtbug3305();
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QAbstractItemDelegate::EndEditHint)
|
||||
|
||||
static QStandardItemModel *testModel(QObject *parent)
|
||||
{
|
||||
QStandardItemModel *model = new QStandardItemModel(10, 10, parent);
|
||||
|
||||
for (int row = 0; row < 10; ++row) {
|
||||
const QString prefix = QLatin1String("item ") + QString::number(row)
|
||||
+ QLatin1Char(' ');
|
||||
for (int col = 0; col < 10; ++col)
|
||||
model->setData(model->index(row, col), prefix + QString::number(col));
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
void tst_QDataWidgetMapper::initTestCase()
|
||||
{
|
||||
qRegisterMetaType<QAbstractItemDelegate::EndEditHint>();
|
||||
}
|
||||
|
||||
void tst_QDataWidgetMapper::setModel()
|
||||
{
|
||||
QDataWidgetMapper mapper;
|
||||
|
||||
QCOMPARE(mapper.model(), nullptr);
|
||||
|
||||
{ // let the model go out of scope firstma
|
||||
QStandardItemModel model;
|
||||
mapper.setModel(&model);
|
||||
QCOMPARE(mapper.model(), &model);
|
||||
}
|
||||
|
||||
QCOMPARE(mapper.model(), nullptr);
|
||||
|
||||
{ // let the mapper go out of scope first
|
||||
QStandardItemModel model2;
|
||||
QDataWidgetMapper mapper2;
|
||||
mapper2.setModel(&model2);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QDataWidgetMapper::navigate()
|
||||
{
|
||||
QDataWidgetMapper mapper;
|
||||
QAbstractItemModel *model = testModel(&mapper);
|
||||
mapper.setModel(model);
|
||||
|
||||
QLineEdit edit1;
|
||||
QLineEdit edit2;
|
||||
QLineEdit edit3;
|
||||
|
||||
mapper.addMapping(&edit1, 0);
|
||||
mapper.toFirst();
|
||||
mapper.addMapping(&edit2, 1);
|
||||
mapper.addMapping(&edit3, 2);
|
||||
|
||||
QCOMPARE(edit1.text(), QString("item 0 0"));
|
||||
QVERIFY(edit2.text().isEmpty());
|
||||
QVERIFY(edit3.text().isEmpty());
|
||||
QVERIFY(mapper.submit());
|
||||
edit2.setText(QString("item 0 1"));
|
||||
edit3.setText(QString("item 0 2"));
|
||||
QVERIFY(mapper.submit());
|
||||
|
||||
mapper.toFirst(); //this will repopulate
|
||||
QCOMPARE(edit1.text(), QString("item 0 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 0 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 0 2"));
|
||||
|
||||
|
||||
mapper.toFirst();
|
||||
QCOMPARE(edit1.text(), QString("item 0 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 0 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 0 2"));
|
||||
|
||||
mapper.toPrevious(); // should do nothing
|
||||
QCOMPARE(edit1.text(), QString("item 0 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 0 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 0 2"));
|
||||
|
||||
mapper.toNext();
|
||||
QCOMPARE(edit1.text(), QString("item 1 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 1 2"));
|
||||
|
||||
mapper.toLast();
|
||||
QCOMPARE(edit1.text(), QString("item 9 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 9 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 9 2"));
|
||||
|
||||
mapper.toNext(); // should do nothing
|
||||
QCOMPARE(edit1.text(), QString("item 9 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 9 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 9 2"));
|
||||
|
||||
mapper.setCurrentIndex(4);
|
||||
QCOMPARE(edit1.text(), QString("item 4 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 4 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 4 2"));
|
||||
|
||||
mapper.setCurrentIndex(-1); // should do nothing
|
||||
QCOMPARE(edit1.text(), QString("item 4 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 4 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 4 2"));
|
||||
|
||||
mapper.setCurrentIndex(10); // should do nothing
|
||||
QCOMPARE(edit1.text(), QString("item 4 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 4 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 4 2"));
|
||||
|
||||
mapper.setCurrentModelIndex(QModelIndex()); // should do nothing
|
||||
QCOMPARE(edit1.text(), QString("item 4 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 4 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 4 2"));
|
||||
|
||||
mapper.setCurrentModelIndex(model->index(6, 0));
|
||||
QCOMPARE(edit1.text(), QString("item 6 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 6 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 6 2"));
|
||||
|
||||
/* now try vertical navigation */
|
||||
|
||||
mapper.setOrientation(Qt::Vertical);
|
||||
|
||||
mapper.addMapping(&edit1, 0);
|
||||
mapper.addMapping(&edit2, 1);
|
||||
mapper.addMapping(&edit3, 2);
|
||||
|
||||
mapper.toFirst();
|
||||
QCOMPARE(edit1.text(), QString("item 0 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 0"));
|
||||
QCOMPARE(edit3.text(), QString("item 2 0"));
|
||||
|
||||
mapper.toPrevious(); // should do nothing
|
||||
QCOMPARE(edit1.text(), QString("item 0 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 0"));
|
||||
QCOMPARE(edit3.text(), QString("item 2 0"));
|
||||
|
||||
mapper.toNext();
|
||||
QCOMPARE(edit1.text(), QString("item 0 1"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 2 1"));
|
||||
|
||||
mapper.toLast();
|
||||
QCOMPARE(edit1.text(), QString("item 0 9"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 9"));
|
||||
QCOMPARE(edit3.text(), QString("item 2 9"));
|
||||
|
||||
mapper.toNext(); // should do nothing
|
||||
QCOMPARE(edit1.text(), QString("item 0 9"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 9"));
|
||||
QCOMPARE(edit3.text(), QString("item 2 9"));
|
||||
|
||||
mapper.setCurrentIndex(4);
|
||||
QCOMPARE(edit1.text(), QString("item 0 4"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 4"));
|
||||
QCOMPARE(edit3.text(), QString("item 2 4"));
|
||||
|
||||
mapper.setCurrentIndex(-1); // should do nothing
|
||||
QCOMPARE(edit1.text(), QString("item 0 4"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 4"));
|
||||
QCOMPARE(edit3.text(), QString("item 2 4"));
|
||||
|
||||
mapper.setCurrentIndex(10); // should do nothing
|
||||
QCOMPARE(edit1.text(), QString("item 0 4"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 4"));
|
||||
QCOMPARE(edit3.text(), QString("item 2 4"));
|
||||
|
||||
mapper.setCurrentModelIndex(QModelIndex()); // should do nothing
|
||||
QCOMPARE(edit1.text(), QString("item 0 4"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 4"));
|
||||
QCOMPARE(edit3.text(), QString("item 2 4"));
|
||||
|
||||
mapper.setCurrentModelIndex(model->index(0, 6));
|
||||
QCOMPARE(edit1.text(), QString("item 0 6"));
|
||||
QCOMPARE(edit2.text(), QString("item 1 6"));
|
||||
QCOMPARE(edit3.text(), QString("item 2 6"));
|
||||
}
|
||||
|
||||
void tst_QDataWidgetMapper::addMapping()
|
||||
{
|
||||
QDataWidgetMapper mapper;
|
||||
QAbstractItemModel *model = testModel(&mapper);
|
||||
mapper.setModel(model);
|
||||
|
||||
QLineEdit edit1;
|
||||
mapper.addMapping(&edit1, 0);
|
||||
mapper.toFirst();
|
||||
QCOMPARE(edit1.text(), QString("item 0 0"));
|
||||
|
||||
mapper.addMapping(&edit1, 1);
|
||||
mapper.toFirst();
|
||||
QCOMPARE(edit1.text(), QString("item 0 1"));
|
||||
|
||||
QCOMPARE(mapper.mappedSection(&edit1), 1);
|
||||
|
||||
edit1.clear();
|
||||
mapper.removeMapping(&edit1);
|
||||
mapper.toFirst();
|
||||
QCOMPARE(edit1.text(), QString());
|
||||
|
||||
{
|
||||
QLineEdit edit2;
|
||||
mapper.addMapping(&edit2, 2);
|
||||
mapper.toFirst();
|
||||
QCOMPARE(edit2.text(), QString("item 0 2"));
|
||||
} // let the edit go out of scope
|
||||
|
||||
QCOMPARE(mapper.mappedWidgetAt(2), nullptr);
|
||||
mapper.toLast();
|
||||
}
|
||||
|
||||
void tst_QDataWidgetMapper::currentIndexChanged()
|
||||
{
|
||||
QDataWidgetMapper mapper;
|
||||
QAbstractItemModel *model = testModel(&mapper);
|
||||
mapper.setModel(model);
|
||||
|
||||
QSignalSpy spy(&mapper, &QDataWidgetMapper::currentIndexChanged);
|
||||
|
||||
mapper.toFirst();
|
||||
QCOMPARE(spy.size(), 1);
|
||||
QCOMPARE(spy.takeFirst().at(0).toInt(), 0);
|
||||
|
||||
mapper.toNext();
|
||||
QCOMPARE(spy.size(), 1);
|
||||
QCOMPARE(spy.takeFirst().at(0).toInt(), 1);
|
||||
|
||||
mapper.setCurrentIndex(7);
|
||||
QCOMPARE(spy.size(), 1);
|
||||
QCOMPARE(spy.takeFirst().at(0).toInt(), 7);
|
||||
|
||||
mapper.setCurrentIndex(-1);
|
||||
QCOMPARE(spy.size(), 0);
|
||||
|
||||
mapper.setCurrentIndex(42);
|
||||
QCOMPARE(spy.size(), 0);
|
||||
}
|
||||
|
||||
void tst_QDataWidgetMapper::changingValues()
|
||||
{
|
||||
QDataWidgetMapper mapper;
|
||||
QAbstractItemModel *model = testModel(&mapper);
|
||||
mapper.setModel(model);
|
||||
|
||||
QLineEdit edit1;
|
||||
mapper.addMapping(&edit1, 0);
|
||||
mapper.toFirst();
|
||||
QCOMPARE(edit1.text(), QString("item 0 0"));
|
||||
|
||||
QLineEdit edit2;
|
||||
mapper.addMapping(&edit2, 0, "text");
|
||||
mapper.toFirst();
|
||||
QCOMPARE(edit2.text(), QString("item 0 0"));
|
||||
|
||||
model->setData(model->index(0, 0), QString("changed"));
|
||||
QCOMPARE(edit1.text(), QString("changed"));
|
||||
QCOMPARE(edit2.text(), QString("changed"));
|
||||
}
|
||||
|
||||
void tst_QDataWidgetMapper::setData()
|
||||
{
|
||||
QDataWidgetMapper mapper;
|
||||
QAbstractItemModel *model = testModel(&mapper);
|
||||
mapper.setModel(model);
|
||||
|
||||
QLineEdit edit1;
|
||||
QLineEdit edit2;
|
||||
QLineEdit edit3;
|
||||
|
||||
mapper.addMapping(&edit1, 0);
|
||||
mapper.addMapping(&edit2, 1);
|
||||
mapper.addMapping(&edit3, 0, "text");
|
||||
mapper.toFirst();
|
||||
QCOMPARE(edit1.text(), QString("item 0 0"));
|
||||
QCOMPARE(edit2.text(), QString("item 0 1"));
|
||||
QCOMPARE(edit3.text(), QString("item 0 0"));
|
||||
|
||||
edit1.setText("new text");
|
||||
|
||||
mapper.submit();
|
||||
QCOMPARE(model->data(model->index(0, 0)).toString(), QString("new text"));
|
||||
|
||||
edit3.setText("more text");
|
||||
|
||||
mapper.submit();
|
||||
QCOMPARE(model->data(model->index(0, 0)).toString(), QString("more text"));
|
||||
}
|
||||
|
||||
void tst_QDataWidgetMapper::comboBox()
|
||||
{
|
||||
QDataWidgetMapper mapper;
|
||||
QAbstractItemModel *model = testModel(&mapper);
|
||||
mapper.setModel(model);
|
||||
mapper.setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
|
||||
|
||||
QComboBox readOnlyBox;
|
||||
readOnlyBox.setEditable(false);
|
||||
readOnlyBox.addItem("read only item 0");
|
||||
readOnlyBox.addItem("read only item 1");
|
||||
readOnlyBox.addItem("read only item 2");
|
||||
|
||||
QComboBox readWriteBox;
|
||||
readWriteBox.setEditable(true);
|
||||
readWriteBox.addItem("read write item 0");
|
||||
readWriteBox.addItem("read write item 1");
|
||||
readWriteBox.addItem("read write item 2");
|
||||
|
||||
// populate the combo boxes with data
|
||||
mapper.addMapping(&readOnlyBox, 0, "currentIndex");
|
||||
mapper.addMapping(&readWriteBox, 1, "currentText");
|
||||
mapper.toFirst();
|
||||
|
||||
// setCurrentIndex caused the value at index 0 to be displayed
|
||||
QCOMPARE(readOnlyBox.currentText(), QString("read only item 0"));
|
||||
// setCurrentText set the value in the line edit since the combobox is editable
|
||||
QCOMPARE(readWriteBox.currentText(), QString("item 0 1"));
|
||||
|
||||
// set some new values on the boxes
|
||||
readOnlyBox.setCurrentIndex(1);
|
||||
readWriteBox.setEditText("read write item y");
|
||||
|
||||
mapper.submit();
|
||||
|
||||
// make sure the new values are in the model
|
||||
QCOMPARE(model->data(model->index(0, 0)).toInt(), 1);
|
||||
QCOMPARE(model->data(model->index(0, 1)).toString(), QString("read write item y"));
|
||||
|
||||
// now test updating of the widgets
|
||||
model->setData(model->index(0, 0), 2, Qt::EditRole);
|
||||
model->setData(model->index(0, 1), QString("read write item z"), Qt::EditRole);
|
||||
|
||||
QCOMPARE(readOnlyBox.currentIndex(), 2);
|
||||
QCOMPARE(readWriteBox.currentText(), QString("read write item z"));
|
||||
}
|
||||
|
||||
void tst_QDataWidgetMapper::mappedWidgetAt()
|
||||
{
|
||||
QDataWidgetMapper mapper;
|
||||
QAbstractItemModel *model = testModel(&mapper);
|
||||
mapper.setModel(model);
|
||||
|
||||
QLineEdit lineEdit1;
|
||||
QLineEdit lineEdit2;
|
||||
|
||||
QCOMPARE(mapper.mappedWidgetAt(432312), nullptr);
|
||||
|
||||
mapper.addMapping(&lineEdit1, 1);
|
||||
mapper.addMapping(&lineEdit2, 2);
|
||||
|
||||
QCOMPARE(mapper.mappedWidgetAt(1), &lineEdit1);
|
||||
QCOMPARE(mapper.mappedWidgetAt(2), &lineEdit2);
|
||||
|
||||
mapper.addMapping(&lineEdit2, 4242);
|
||||
|
||||
QCOMPARE(mapper.mappedWidgetAt(2), nullptr);
|
||||
QCOMPARE(mapper.mappedWidgetAt(4242), &lineEdit2);
|
||||
}
|
||||
|
||||
void tst_QDataWidgetMapper::textEditDoesntChangeFocusOnTab_qtbug3305()
|
||||
{
|
||||
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
||||
QSKIP("Wayland: This fails. Figure out why.");
|
||||
|
||||
QDataWidgetMapper mapper;
|
||||
QAbstractItemModel *model = testModel(&mapper);
|
||||
mapper.setModel(model);
|
||||
|
||||
QSignalSpy closeEditorSpy(mapper.itemDelegate(),
|
||||
&QAbstractItemDelegate::closeEditor);
|
||||
QVERIFY(closeEditorSpy.isValid());
|
||||
|
||||
QWidget container;
|
||||
container.setLayout(new QVBoxLayout);
|
||||
|
||||
QLineEdit *lineEdit = new QLineEdit;
|
||||
mapper.addMapping(lineEdit, 0);
|
||||
container.layout()->addWidget(lineEdit);
|
||||
|
||||
QTextEdit *textEdit = new QTextEdit;
|
||||
mapper.addMapping(textEdit, 1);
|
||||
container.layout()->addWidget(textEdit);
|
||||
|
||||
lineEdit->setFocus();
|
||||
|
||||
container.show();
|
||||
|
||||
QApplicationPrivate::setActiveWindow(&container);
|
||||
QVERIFY(QTest::qWaitForWindowActive(&container));
|
||||
|
||||
int closeEditorSpyCount = 0;
|
||||
const QString textEditContents = textEdit->toPlainText();
|
||||
|
||||
QCOMPARE(closeEditorSpy.size(), closeEditorSpyCount);
|
||||
QVERIFY(lineEdit->hasFocus());
|
||||
QVERIFY(!textEdit->hasFocus());
|
||||
|
||||
// this will generate a closeEditor for the tab key, and another for the focus out
|
||||
QTest::keyClick(QApplication::focusWidget(), Qt::Key_Tab);
|
||||
closeEditorSpyCount += 2;
|
||||
QTRY_COMPARE(closeEditorSpy.size(), closeEditorSpyCount);
|
||||
|
||||
QTRY_VERIFY(textEdit->hasFocus());
|
||||
QVERIFY(!lineEdit->hasFocus());
|
||||
|
||||
// now that the text edit is focused, a tab keypress will insert a tab, not change focus
|
||||
QTest::keyClick(QApplication::focusWidget(), Qt::Key_Tab);
|
||||
QTRY_COMPARE(closeEditorSpy.size(), closeEditorSpyCount);
|
||||
|
||||
QVERIFY(!lineEdit->hasFocus());
|
||||
QVERIFY(textEdit->hasFocus());
|
||||
QCOMPARE(textEdit->toPlainText(), QLatin1Char('\t') + textEditContents);
|
||||
|
||||
// now give focus back to the line edit and check closeEditor gets emitted
|
||||
lineEdit->setFocus();
|
||||
QTRY_VERIFY(lineEdit->hasFocus());
|
||||
QVERIFY(!textEdit->hasFocus());
|
||||
++closeEditorSpyCount;
|
||||
QCOMPARE(closeEditorSpy.size(), closeEditorSpyCount);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QDataWidgetMapper)
|
||||
#include "tst_qdatawidgetmapper.moc"
|
Reference in New Issue
Block a user