From b92db8a4adf985fe842ec0693e17c81d9e816b93 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 15 May 2018 15:05:29 +0200 Subject: Show the display role inside the editor for the relation in a QComboBox When a QComboBox is used as the editor for a relation inside a view then it could end up showing the contents of the EditRole. This would be the field which is used to represent the entry as opposed to the DisplayRole which is what the user would expect to see is. Therefore, setEditorData() is overridden to ensure that it is showing the right data to the user. When the model gets updated, it will take the corresponding EditRole value as before to ensure it is updated correctly. Task-number: QTBUG-59632 Change-Id: Ibbccc3e9477de1cdefb654051b97dd111df36382 Reviewed-by: Jesus Fernandez --- src/sql/models/qsqlrelationaldelegate.h | 23 ++- .../qsqlrelationaldelegate.pro | 5 + .../tst_qsqlrelationaldelegate.cpp | 170 +++++++++++++++++++++ 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 tests/auto/sql/models/qsqlrelationaldelegate/qsqlrelationaldelegate.pro create mode 100644 tests/auto/sql/models/qsqlrelationaldelegate/tst_qsqlrelationaldelegate.cpp diff --git a/src/sql/models/qsqlrelationaldelegate.h b/src/sql/models/qsqlrelationaldelegate.h index 0af87f64ae..e8ae5a229d 100644 --- a/src/sql/models/qsqlrelationaldelegate.h +++ b/src/sql/models/qsqlrelationaldelegate.h @@ -55,7 +55,7 @@ QT_REQUIRE_CONFIG(sqlmodel); #endif #include #include - +#include QT_BEGIN_NAMESPACE @@ -99,6 +99,27 @@ QWidget *createEditor(QWidget *aParent, return combo; } + void setEditorData(QWidget *editor, const QModelIndex &index) const override + { + if (!index.isValid()) + return; + + if (qobject_cast(editor)) { + // Taken from QItemDelegate::setEditorData() as we need + // to present the DisplayRole and not the EditRole which + // is the id reference to the related model + QVariant v = index.data(Qt::DisplayRole); + QByteArray n = editor->metaObject()->userProperty().name(); + if (!n.isEmpty()) { + if (!v.isValid()) + v = QVariant(editor->property(n).userType(), nullptr); + editor->setProperty(n, v); + return; + } + } + QItemDelegate::setEditorData(editor, index); + } + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override { if (!index.isValid()) diff --git a/tests/auto/sql/models/qsqlrelationaldelegate/qsqlrelationaldelegate.pro b/tests/auto/sql/models/qsqlrelationaldelegate/qsqlrelationaldelegate.pro new file mode 100644 index 0000000000..d911a46259 --- /dev/null +++ b/tests/auto/sql/models/qsqlrelationaldelegate/qsqlrelationaldelegate.pro @@ -0,0 +1,5 @@ +CONFIG += testcase +TARGET = tst_qsqlrelationaldelegate +SOURCES += tst_qsqlrelationaldelegate.cpp + +QT = core sql testlib core-private sql-private widgets diff --git a/tests/auto/sql/models/qsqlrelationaldelegate/tst_qsqlrelationaldelegate.cpp b/tests/auto/sql/models/qsqlrelationaldelegate/tst_qsqlrelationaldelegate.cpp new file mode 100644 index 0000000000..36f592395e --- /dev/null +++ b/tests/auto/sql/models/qsqlrelationaldelegate/tst_qsqlrelationaldelegate.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include +#include + +#include "../../kernel/qsqldatabase/tst_databases.h" + +const QString reltest1(qTableName("reltest1", __FILE__, QSqlDatabase())), + reltest2(qTableName("reltest2", __FILE__, QSqlDatabase())); + +class tst_QSqlRelationalDelegate : public QObject +{ + Q_OBJECT + +public: + void recreateTestTables(QSqlDatabase); + + tst_Databases dbs; + +public slots: + void initTestCase_data(); + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void comboBoxEditor(); +private: + void dropTestTables(QSqlDatabase db); +}; + + +void tst_QSqlRelationalDelegate::initTestCase_data() +{ + QVERIFY(dbs.open()); + if (dbs.fillTestTable() == 0) + QSKIP("No database drivers are available in this Qt configuration"); +} + +void tst_QSqlRelationalDelegate::recreateTestTables(QSqlDatabase db) +{ + dropTestTables(db); + + QSqlQuery q(db); + QVERIFY_SQL(q, exec("create table " + reltest1 + + " (id int not null primary key, name varchar(20), title_key int, another_title_key int)")); + QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(1, 'harry', 1, 2)")); + QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(2, 'trond', 2, 1)")); + QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(3, 'vohi', 1, 2)")); + QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(4, 'boris', 2, 2)")); + QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(5, 'nat', NULL, NULL)")); + QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(6, 'ale', NULL, 2)")); + + QVERIFY_SQL(q, exec("create table " + reltest2 + " (id int not null primary key, title varchar(20))")); + QVERIFY_SQL(q, exec("insert into " + reltest2 + " values(1, 'herr')")); + QVERIFY_SQL(q, exec("insert into " + reltest2 + " values(2, 'mister')")); +} + +void tst_QSqlRelationalDelegate::initTestCase() +{ + foreach (const QString &dbname, dbs.dbNames) { + QSqlDatabase db=QSqlDatabase::database(dbname); + QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); + if (dbType == QSqlDriver::Interbase) { + db.exec("SET DIALECT 3"); + } else if (dbType == QSqlDriver::MSSqlServer) { + db.exec("SET ANSI_DEFAULTS ON"); + db.exec("SET IMPLICIT_TRANSACTIONS OFF"); + } else if (dbType == QSqlDriver::PostgreSQL) { + db.exec("set client_min_messages='warning'"); + } + recreateTestTables(db); + } +} + +void tst_QSqlRelationalDelegate::cleanupTestCase() +{ + foreach (const QString &dbName, dbs.dbNames) { + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + dropTestTables(QSqlDatabase::database(dbName)); + } + dbs.close(); +} + +void tst_QSqlRelationalDelegate::dropTestTables(QSqlDatabase db) +{ + QStringList tableNames = { reltest1, reltest2 }; + tst_Databases::safeDropTables(db, tableNames); +} + +void tst_QSqlRelationalDelegate::init() +{ +} + +void tst_QSqlRelationalDelegate::cleanup() +{ +} + +void tst_QSqlRelationalDelegate::comboBoxEditor() +{ + QFETCH_GLOBAL(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QTableView tv; + QSqlRelationalTableModel model(0, db); + model.setEditStrategy(QSqlTableModel::OnManualSubmit); + model.setTable(reltest1); + model.setRelation(2, QSqlRelation(reltest2, "id", "title")); + model.setRelation(3, QSqlRelation(reltest2, "id", "title")); + tv.setModel(&model); + QVERIFY_SQL(model, select()); + + QSqlRelationalDelegate delegate; + tv.setItemDelegate(&delegate); + tv.show(); + QVERIFY(QTest::qWaitForWindowActive(&tv)); + + QModelIndex index = model.index(0, 2); + tv.setCurrentIndex(index); + tv.edit(index); + QList comboBoxes = tv.viewport()->findChildren(); + QCOMPARE(comboBoxes.count(), 1); + + QComboBox *editor = comboBoxes.at(0); + QCOMPARE(editor->currentText(), "herr"); + QTest::keyClick(editor, Qt::Key_Down); + QTest::keyClick(editor, Qt::Key_Enter); + QCOMPARE(editor->currentText(), "mister"); + QVERIFY_SQL(model, submitAll()); + + QSqlQuery qry(db); + QVERIFY_SQL(qry, exec("SELECT title_key FROM " + reltest1 + " WHERE id=1")); + QVERIFY(qry.next()); + QCOMPARE(qry.value(0).toString(), "mister"); +} + +QTEST_MAIN(tst_QSqlRelationalDelegate) +#include "tst_qsqlrelationaldelegate.moc" -- cgit v1.2.3