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
45 QT_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>
59 QT_BEGIN_NAMESPACE
60
61 // ### Qt6: QStyledItemDelegate
62 class QSqlRelationalDelegate: public QItemDelegate
63 {
fieldIndex(const QSqlTableModel * const model,const QSqlDriver * const driver,const QString & fieldName)64 static int fieldIndex(const QSqlTableModel *const model,
65 const QSqlDriver *const driver,
66 const QString &fieldName)
67 {
68 const QString stripped = driver->isIdentifierEscaped(fieldName, QSqlDriver::FieldName)
69 ? driver->stripDelimiters(fieldName, QSqlDriver::FieldName)
70 : fieldName;
71 return model->fieldIndex(stripped);
72 }
73
74 public:
75
76 explicit QSqlRelationalDelegate(QObject *aParent = nullptr)
QItemDelegate(aParent)77 : QItemDelegate(aParent)
78 {}
79
~QSqlRelationalDelegate()80 ~QSqlRelationalDelegate()
81 {}
82
createEditor(QWidget * aParent,const QStyleOptionViewItem & option,const QModelIndex & index)83 QWidget *createEditor(QWidget *aParent,
84 const QStyleOptionViewItem &option,
85 const QModelIndex &index) const override
86 {
87 const QSqlRelationalTableModel *sqlModel = qobject_cast<const QSqlRelationalTableModel *>(index.model());
88 QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : nullptr;
89 if (!childModel)
90 return QItemDelegate::createEditor(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(childModel, driver,
96 sqlModel->relation(index.column()).displayColumn()));
97 combo->installEventFilter(const_cast<QSqlRelationalDelegate *>(this));
98
99 return combo;
100 }
101
setEditorData(QWidget * editor,const QModelIndex & index)102 void setEditorData(QWidget *editor, const QModelIndex &index) const override
103 {
104 if (!index.isValid())
105 return;
106
107 if (qobject_cast<QComboBox *>(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(Qt::DisplayRole);
112 const QByteArray n = editor->metaObject()->userProperty().name();
113 if (!n.isEmpty()) {
114 if (!v.isValid())
115 v = QVariant(editor->property(n.data()).userType(), nullptr);
116 editor->setProperty(n.data(), v);
117 return;
118 }
119 }
120 QItemDelegate::setEditorData(editor, index);
121 }
122
setModelData(QWidget * editor,QAbstractItemModel * model,const QModelIndex & index)123 void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
124 {
125 if (!index.isValid())
126 return;
127
128 QSqlRelationalTableModel *sqlModel = qobject_cast<QSqlRelationalTableModel *>(model);
129 QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : nullptr;
130 QComboBox *combo = qobject_cast<QComboBox *>(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(childModel, driver,
139 sqlModel->relation(index.column()).displayColumn());
140 int childEditIndex = fieldIndex(childModel, driver,
141 sqlModel->relation(index.column()).indexColumn());
142 sqlModel->setData(index,
143 childModel->data(childModel->index(currentItem, childColIndex), Qt::DisplayRole),
144 Qt::DisplayRole);
145 sqlModel->setData(index,
146 childModel->data(childModel->index(currentItem, childEditIndex), Qt::EditRole),
147 Qt::EditRole);
148 }
149
150 };
151
152 QT_END_NAMESPACE
153
154 #endif // QT_WIDGETS_LIB
155
156 #endif // QSQLRELATIONALDELEGATE_H
157