1 /*
2     This file is part of the Okteta Kasten module, made within the KDE community.
3 
4     SPDX-FileCopyrightText: 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8 
9 #include "poddelegate.hpp"
10 
11 // tool
12 #include "typeeditors/binary8editor.hpp"
13 #include "typeeditors/octal8editor.hpp"
14 #include "typeeditors/hexadecimal8editor.hpp"
15 #include "typeeditors/float32editor.hpp"
16 #include "typeeditors/float64editor.hpp"
17 #include "typeeditors/char8editor.hpp"
18 #include "typeeditors/utf8editor.hpp"
19 #include "typeeditors/sintspinbox.hpp"
20 #include "typeeditors/uintspinbox.hpp"
21 #include "poddecodertool.hpp"
22 #include "types/sint8.hpp"
23 #include "types/sint16.hpp"
24 #include "types/sint32.hpp"
25 #include "types/sint64.hpp"
26 #include "types/uint8.hpp"
27 #include "types/uint16.hpp"
28 #include "types/uint32.hpp"
29 #include "types/uint64.hpp"
30 
31 // TODO: Stranger that you are reading this: please help out and show how to add QVariant::Types for custom datatypes,
32 // so that instead of this unflexible maintanance mess^WWWunlooped code QItemEditorCreator can be used!
33 
34 namespace Kasten {
35 
PODDelegate(PODDecoderTool * tool,QObject * parent)36 PODDelegate::PODDelegate(PODDecoderTool* tool, QObject* parent)
37     : QStyledItemDelegate(parent)
38     , mTool(tool)
39 {
40     qRegisterMetaType<Binary8>();
41     qRegisterMetaType<Octal8>();
42     qRegisterMetaType<Hexadecimal8>();
43     qRegisterMetaType<SInt8>();
44     qRegisterMetaType<SInt16>();
45     qRegisterMetaType<SInt32>();
46     qRegisterMetaType<SInt64>();
47     qRegisterMetaType<UInt8>();
48     qRegisterMetaType<UInt16>();
49     qRegisterMetaType<UInt32>();
50     qRegisterMetaType<UInt64>();
51     qRegisterMetaType<Float32>();
52     qRegisterMetaType<Float64>();
53     qRegisterMetaType<Char8>();
54     qRegisterMetaType<Utf8>();
55 
56     connect(mTool, &PODDecoderTool::readOnlyChanged, this, &PODDelegate::onReadOnlyChanged);
57 }
58 
59 PODDelegate::~PODDelegate() = default;
60 
61 // make sure only editors are created which have a readOnly property
62 // also beware that for subclasses of QLineEdit (all float editors) the signal
63 // editingFinished() is only emitted if validator() returns QValidator::Acceptable
64 // so onEditorDone() is not reached if QValidator::Intermediate
createEditor(QWidget * parent,const QStyleOptionViewItem & option,const QModelIndex & index) const65 QWidget* PODDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
66 {
67     QWidget* result;
68 
69     QVariant data = index.data();
70     if (data.canConvert<Binary8>()) {
71         auto* editor = new Binary8Editor(parent);
72         connect(editor, &Binary8Editor::editingFinished,
73                 this, &PODDelegate::onEditorDone);
74         result = editor;
75     } else if (data.canConvert<Octal8>()) {
76         auto* editor = new Octal8Editor(parent);
77         connect(editor, &Octal8Editor::editingFinished,
78                 this, &PODDelegate::onEditorDone);
79         result = editor;
80     } else if (data.canConvert<Hexadecimal8>()) {
81         auto* editor = new Hexadecimal8Editor(parent);
82         connect(editor, &Hexadecimal8Editor::editingFinished,
83                 this, &PODDelegate::onEditorDone);
84         result = editor;
85     } else if (data.canConvert<SInt8>()) {
86         SIntSpinBox* editor = SIntSpinBox::createSInt8Spinbox(parent);
87         connect(editor, &SIntSpinBox::editingFinished,
88                 this, &PODDelegate::onEditorDone);
89         result = editor;
90     } else if (data.canConvert<SInt16>()) {
91         SIntSpinBox* editor = SIntSpinBox::createSInt16Spinbox(parent);
92         connect(editor, &SIntSpinBox::editingFinished,
93                 this, &PODDelegate::onEditorDone);
94         result = editor;
95     } else if (data.canConvert<SInt32>()) {
96         SIntSpinBox* editor = SIntSpinBox::createSInt32Spinbox(parent);
97         connect(editor, &SIntSpinBox::editingFinished,
98                 this, &PODDelegate::onEditorDone);
99         result = editor;
100     } else if (data.canConvert<SInt64>()) {
101         SIntSpinBox* editor = SIntSpinBox::createSInt64Spinbox(parent);
102         connect(editor, &SIntSpinBox::editingFinished,
103                 this, &PODDelegate::onEditorDone);
104         result = editor;
105     } else if (data.canConvert<UInt8>()) {
106         UIntSpinBox* editor = UIntSpinBox::createUInt8Spinbox(parent);
107         editor->setBase(mTool->isUnsignedAsHex() ? 16 : 10);
108         connect(editor, &UIntSpinBox::editingFinished,
109                 this, &PODDelegate::onEditorDone);
110         result = editor;
111     } else if (data.canConvert<UInt16>()) {
112         UIntSpinBox* editor = UIntSpinBox::createUInt16Spinbox(parent);
113         editor->setBase(mTool->isUnsignedAsHex() ? 16 : 10);
114         connect(editor, &UIntSpinBox::editingFinished,
115                 this, &PODDelegate::onEditorDone);
116         result = editor;
117     } else if (data.canConvert<UInt32>()) {
118         UIntSpinBox* editor = UIntSpinBox::createUInt32Spinbox(parent);
119         editor->setBase(mTool->isUnsignedAsHex() ? 16 : 10);
120         connect(editor, &UIntSpinBox::editingFinished,
121                 this, &PODDelegate::onEditorDone);
122         result = editor;
123     } else if (data.canConvert<UInt64>()) {
124         UIntSpinBox* editor = UIntSpinBox::createUInt64Spinbox(parent);
125         editor->setBase(mTool->isUnsignedAsHex() ? 16 : 10);
126         connect(editor, &UIntSpinBox::editingFinished,
127                 this, &PODDelegate::onEditorDone);
128         result = editor;
129     } else if (data.canConvert<Float32>()) {
130         auto* editor = new Float32Editor(parent);
131         connect(editor, &Float32Editor::editingFinished,
132                 this, &PODDelegate::onEditorDone);
133         result = editor;
134     } else if (data.canConvert<Float64>()) {
135         auto* editor = new Float64Editor(parent);
136         connect(editor, &Float64Editor::editingFinished,
137                 this, &PODDelegate::onEditorDone);
138         result = editor;
139     } else if (data.canConvert<Char8>()) {
140         auto* editor = new Char8Editor(mTool->charCodec(), parent);
141         connect(editor, &Char8Editor::editingFinished,
142                 this, &PODDelegate::onEditorDone);
143         result = editor;
144     } else if (data.canConvert<Utf8>()) {
145         auto* editor = new Utf8Editor(parent);
146         connect(editor, &Utf8Editor::editingFinished,
147                 this, &PODDelegate::onEditorDone);
148         result = editor;
149     } else {
150         result = QStyledItemDelegate::createEditor(parent, option, index);
151     }
152 
153     mEditor = result;
154     onReadOnlyChanged(mTool->isReadOnly());
155 
156     return result;
157 }
158 
setEditorData(QWidget * editor,const QModelIndex & index) const159 void PODDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
160 {
161     QVariant data = index.data();
162 
163     if (data.canConvert<Binary8>()) {
164         Binary8 binary8 = data.value<Binary8>();
165         auto* binary8Editor = qobject_cast<Binary8Editor*>(editor);
166         binary8Editor->setData(binary8);
167     } else if (data.canConvert<Octal8>()) {
168         Octal8 octal8 = data.value<Octal8>();
169         auto* octal8Editor = qobject_cast<Octal8Editor*>(editor);
170         octal8Editor->setData(octal8);
171     } else if (data.canConvert<Hexadecimal8>()) {
172         Hexadecimal8 hexadecimal8 = data.value<Hexadecimal8>();
173         auto* hexadecimal8Editor = qobject_cast<Hexadecimal8Editor*>(editor);
174         hexadecimal8Editor->setData(hexadecimal8);
175     } else if (data.canConvert<SInt8>()) {
176         SInt8 sInt8 = data.value<SInt8>();
177         auto* sInt8Editor = qobject_cast<SIntSpinBox*>(editor);
178         sInt8Editor->setValue(sInt8.value);
179     } else if (data.canConvert<SInt16>()) {
180         SInt16 sInt16 = data.value<SInt16>();
181         auto* sInt16Editor = qobject_cast<SIntSpinBox*>(editor);
182         sInt16Editor->setValue(sInt16.value);
183     } else if (data.canConvert<SInt32>()) {
184         SInt32 sInt32 = data.value<SInt32>();
185         auto* sInt32Editor = qobject_cast<SIntSpinBox*>(editor);
186         sInt32Editor->setValue(sInt32.value);
187     } else if (data.canConvert<SInt64>()) {
188         SInt64 sInt64 = data.value<SInt64>();
189         auto* sInt64Editor = qobject_cast<SIntSpinBox*>(editor);
190         sInt64Editor->setValue(sInt64.value);
191     } else if (data.canConvert<UInt8>()) {
192         UInt8 uInt8 = data.value<UInt8>();
193         auto* uInt8Editor = qobject_cast<UIntSpinBox*>(editor);
194         uInt8Editor->setValue(uInt8.value);
195     } else if (data.canConvert<UInt16>()) {
196         UInt16 uInt16 = data.value<UInt16>();
197         auto* uInt16Editor = qobject_cast<UIntSpinBox*>(editor);
198         uInt16Editor->setValue(uInt16.value);
199     } else if (data.canConvert<UInt32>()) {
200         UInt32 uInt32 = data.value<UInt32>();
201         auto* uInt32Editor = qobject_cast<UIntSpinBox*>(editor);
202         uInt32Editor->setValue(uInt32.value);
203     } else if (data.canConvert<UInt64>()) {
204         UInt64 uInt64 = data.value<UInt64>();
205         auto* uInt64Editor = qobject_cast<UIntSpinBox*>(editor);
206         uInt64Editor->setValue(uInt64.value);
207     } else if (data.canConvert<Float32>()) {
208         Float32 float32 = data.value<Float32>();
209         auto* float32Editor = qobject_cast<Float32Editor*>(editor);
210         float32Editor->setData(float32);
211     } else if (data.canConvert<Float64>()) {
212         Float64 float64 = data.value<Float64>();
213         auto* float64Editor = qobject_cast<Float64Editor*>(editor);
214         float64Editor->setData(float64);
215     } else if (data.canConvert<Char8>()) {
216         Char8 char8 = data.value<Char8>();
217         auto* char8Editor = qobject_cast<Char8Editor*>(editor);
218         char8Editor->setData(char8);
219     } else if (data.canConvert<Utf8>()) {
220         Utf8 utf8 = data.value<Utf8>();
221         auto* utf8Editor = qobject_cast<Utf8Editor*>(editor);
222         utf8Editor->setData(utf8);
223     } else {
224         QStyledItemDelegate::setEditorData(editor, index);
225     }
226 }
227 
setModelData(QWidget * editor,QAbstractItemModel * model,const QModelIndex & index) const228 void PODDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
229 {
230     if (mTool->isReadOnly()) {
231         return;
232     }
233 
234     QVariant data = index.data();
235 
236     if (data.canConvert<Binary8>()) {
237         auto* binary8Editor = qobject_cast<Binary8Editor*>(editor);
238         model->setData(index, QVariant::fromValue(binary8Editor->data()));
239     } else if (data.canConvert<Octal8>()) {
240         auto* octal8Editor = qobject_cast<Octal8Editor*>(editor);
241         model->setData(index, QVariant::fromValue(octal8Editor->data()));
242     } else if (data.canConvert<Hexadecimal8>()) {
243         auto* hexadecimal8Editor = qobject_cast<Hexadecimal8Editor*>(editor);
244         model->setData(index, QVariant::fromValue(hexadecimal8Editor->data()));
245     } else if (data.canConvert<SInt8>()) {
246         auto* sintEditor = qobject_cast<SIntSpinBox*>(editor);
247         model->setData(index, QVariant::fromValue(SInt8(sintEditor->value())));
248     } else if (data.canConvert<SInt16>()) {
249         auto* sintEditor = qobject_cast<SIntSpinBox*>(editor);
250         model->setData(index, QVariant::fromValue(SInt16(sintEditor->value())));
251     } else if (data.canConvert<SInt32>()) {
252         auto* sintEditor = qobject_cast<SIntSpinBox*>(editor);
253         model->setData(index, QVariant::fromValue(SInt32(sintEditor->value())));
254     } else if (data.canConvert<SInt64>()) {
255         auto* sintEditor = qobject_cast<SIntSpinBox*>(editor);
256         model->setData(index, QVariant::fromValue(SInt64(sintEditor->value())));
257     } else if (data.canConvert<UInt8>()) {
258         auto* uintEditor = qobject_cast<UIntSpinBox*>(editor);
259         model->setData(index, QVariant::fromValue(UInt8(uintEditor->value())));
260     } else if (data.canConvert<UInt16>()) {
261         auto* uintEditor = qobject_cast<UIntSpinBox*>(editor);
262         model->setData(index, QVariant::fromValue(UInt16(uintEditor->value())));
263     } else if (data.canConvert<UInt32>()) {
264         auto* uintEditor = qobject_cast<UIntSpinBox*>(editor);
265         model->setData(index, QVariant::fromValue(UInt32(uintEditor->value())));
266     } else if (data.canConvert<UInt64>()) {
267         auto* uintEditor = qobject_cast<UIntSpinBox*>(editor);
268         model->setData(index, QVariant::fromValue(UInt64(uintEditor->value())));
269     } else if (data.canConvert<Float32>()) {
270         auto* float32Editor = qobject_cast<Float32Editor*>(editor);
271         model->setData(index, QVariant::fromValue(float32Editor->data()));
272     } else if (data.canConvert<Float64>()) {
273         auto* float64Editor = qobject_cast<Float64Editor*>(editor);
274         model->setData(index, QVariant::fromValue(float64Editor->data()));
275     } else if (data.canConvert<Char8>()) {
276         auto* char8Editor = qobject_cast<Char8Editor*>(editor);
277         model->setData(index, QVariant::fromValue(char8Editor->data()));
278     } else if (data.canConvert<Utf8>()) {
279         auto* utf8Editor = qobject_cast<Utf8Editor*>(editor);
280         model->setData(index, QVariant::fromValue(utf8Editor->data()));
281     } else {
282         QStyledItemDelegate::setModelData(editor, model, index);
283     }
284 }
285 
displayText(const QVariant & data,const QLocale & locale) const286 QString PODDelegate::displayText(const QVariant& data, const QLocale& locale) const
287 {
288     QString result;
289 
290     if (data.canConvert<Binary8>()) {
291         Binary8 binary8 = data.value<Binary8>();
292         result = binary8.toString();
293     } else if (data.canConvert<Octal8>()) {
294         Octal8 octal8 = data.value<Octal8>();
295         result = octal8.toString();
296     } else if (data.canConvert<Hexadecimal8>()) {
297         Hexadecimal8 hexadecimal8 = data.value<Hexadecimal8>();
298         result = hexadecimal8.toString();
299     } else if (data.canConvert<SInt8>()) {
300         SInt8 sInt8 = data.value<SInt8>();
301         result = sInt8.toString();
302     } else if (data.canConvert<SInt16>()) {
303         SInt16 sInt16 = data.value<SInt16>();
304         result = sInt16.toString();
305     } else if (data.canConvert<SInt32>()) {
306         SInt32 sInt32 = data.value<SInt32>();
307         result = sInt32.toString();
308     } else if (data.canConvert<SInt64>()) {
309         SInt64 sInt64 = data.value<SInt64>();
310         result = sInt64.toString();
311     } else if (data.canConvert<UInt8>()) {
312         UInt8 uInt8 = data.value<UInt8>();
313         result = uInt8.toString(mTool->isUnsignedAsHex());
314     } else if (data.canConvert<UInt16>()) {
315         UInt16 uInt16 = data.value<UInt16>();
316         result = uInt16.toString(mTool->isUnsignedAsHex());
317     } else if (data.canConvert<UInt32>()) {
318         UInt32 uInt32 = data.value<UInt32>();
319         result = uInt32.toString(mTool->isUnsignedAsHex());
320     } else if (data.canConvert<UInt64>()) {
321         UInt64 uInt64 = data.value<UInt64>();
322         result = uInt64.toString(mTool->isUnsignedAsHex());
323     } else if (data.canConvert<Float32>()) {
324         Float32 float32 = data.value<Float32>();
325         result = float32.toString();
326     } else if (data.canConvert<Float64>()) {
327         Float64 float64 = data.value<Float64>();
328         result = float64.toString();
329     } else if (data.canConvert<Char8>()) {
330         Char8 char8 = data.value<Char8>();
331         result = char8.toString();
332     } else if (data.canConvert<Utf8>()) {
333         Utf8 utf8 = data.value<Utf8>();
334         result = utf8.toString();
335     } else {
336         result = QStyledItemDelegate::displayText(data, locale);
337     }
338 
339     return result;
340 }
341 
342 // QSize PODDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const
343 // {
344 //      editor->setGeometry(option.rect);
345 // }
346 
onEditorDone()347 void PODDelegate::onEditorDone()
348 {
349     QWidget* editor = qobject_cast<QWidget*>(sender());
350     mEditor = nullptr;
351     emit commitData(editor);
352     emit closeEditor(editor);
353 }
354 
onReadOnlyChanged(bool isReadOnly) const355 void PODDelegate::onReadOnlyChanged(bool isReadOnly) const
356 {
357     if (mEditor) {
358         // going by property is slower, but saves writing this call for every widget
359         mEditor->setProperty("readOnly", isReadOnly);
360     }
361 }
362 
363 }
364