1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtSql module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QSQLRELATIONALDELEGATE_H
41#define QSQLRELATIONALDELEGATE_H
42
43#include <QtSql/qtsqlglobal.h>
44
45QT_REQUIRE_CONFIG(sqlmodel);
46
47#ifdef QT_WIDGETS_LIB
48
49#include <QtWidgets/qitemdelegate.h>
50#if QT_CONFIG(listview)
51#include <QtWidgets/qlistview.h>
52#endif
53#if QT_CONFIG(combobox)
54#include <QtWidgets/qcombobox.h>
55#endif
56#include <QtSql/qsqldriver.h>
57#include <QtSql/qsqlrelationaltablemodel.h>
58#include <QtCore/qmetaobject.h>
59QT_BEGIN_NAMESPACE
60
61// ### Qt6: QStyledItemDelegate
62class QSqlRelationalDelegate: public QItemDelegate
63{
64 static int fieldIndex(const QSqlTableModel *const model,
65 const QSqlDriver *const driver,
66 const QString &fieldName)
67 {
68 const QString stripped = driver->isIdentifierEscaped(identifier: fieldName, type: QSqlDriver::FieldName)
69 ? driver->stripDelimiters(identifier: fieldName, type: QSqlDriver::FieldName)
70 : fieldName;
71 return model->fieldIndex(fieldName: stripped);
72 }
73
74public:
75
76explicit QSqlRelationalDelegate(QObject *aParent = nullptr)
77 : QItemDelegate(aParent)
78{}
79
80~QSqlRelationalDelegate()
81{}
82
83QWidget *createEditor(QWidget *aParent,
84 const QStyleOptionViewItem &option,
85 const QModelIndex &index) const override
86{
87 const QSqlRelationalTableModel *sqlModel = qobject_cast<const QSqlRelationalTableModel *>(object: index.model());
88 QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(column: index.column()) : nullptr;
89 if (!childModel)
90 return QItemDelegate::createEditor(parent: aParent, option, index);
91 const QSqlDriver *const driver = childModel->database().driver();
92
93 QComboBox *combo = new QComboBox(aParent);
94 combo->setModel(childModel);
95 combo->setModelColumn(fieldIndex(model: childModel, driver,
96 fieldName: sqlModel->relation(column: index.column()).displayColumn()));
97 combo->installEventFilter(filterObj: const_cast<QSqlRelationalDelegate *>(this));
98
99 return combo;
100}
101
102 void setEditorData(QWidget *editor, const QModelIndex &index) const override
103 {
104 if (!index.isValid())
105 return;
106
107 if (qobject_cast<QComboBox *>(object: editor)) {
108 // Taken from QItemDelegate::setEditorData() as we need
109 // to present the DisplayRole and not the EditRole which
110 // is the id reference to the related model
111 QVariant v = index.data(arole: Qt::DisplayRole);
112 const QByteArray n = editor->metaObject()->userProperty().name();
113 if (!n.isEmpty()) {
114 if (!v.isValid())
115 v = QVariant(editor->property(name: n.data()).userType(), nullptr);
116 editor->setProperty(name: n.data(), value: v);
117 return;
118 }
119 }
120 QItemDelegate::setEditorData(editor, index);
121 }
122
123void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
124{
125 if (!index.isValid())
126 return;
127
128 QSqlRelationalTableModel *sqlModel = qobject_cast<QSqlRelationalTableModel *>(object: model);
129 QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(column: index.column()) : nullptr;
130 QComboBox *combo = qobject_cast<QComboBox *>(object: editor);
131 if (!sqlModel || !childModel || !combo) {
132 QItemDelegate::setModelData(editor, model, index);
133 return;
134 }
135 const QSqlDriver *const driver = childModel->database().driver();
136
137 int currentItem = combo->currentIndex();
138 int childColIndex = fieldIndex(model: childModel, driver,
139 fieldName: sqlModel->relation(column: index.column()).displayColumn());
140 int childEditIndex = fieldIndex(model: childModel, driver,
141 fieldName: sqlModel->relation(column: index.column()).indexColumn());
142 sqlModel->setData(item: index,
143 value: childModel->data(idx: childModel->index(row: currentItem, column: childColIndex), role: Qt::DisplayRole),
144 role: Qt::DisplayRole);
145 sqlModel->setData(item: index,
146 value: childModel->data(idx: childModel->index(row: currentItem, column: childEditIndex), role: Qt::EditRole),
147 role: Qt::EditRole);
148}
149
150};
151
152QT_END_NAMESPACE
153
154#endif // QT_WIDGETS_LIB
155
156#endif // QSQLRELATIONALDELEGATE_H
157

source code of qtbase/src/sql/models/qsqlrelationaldelegate.h