1 /*
2 This file is part of the Okteta Kasten module, made within the KDE community.
3
4 SPDX-FileCopyrightText: 2009, 2011 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 "bytearraycombobox_p.hpp"
10 #include "bytearraycombobox.hpp"
11
12 // KF
13 #include <KLocalizedString>
14 // Qt
15 #include <QLayout>
16 #include <QLineEdit>
17 #include <QAbstractItemView>
18
19 namespace Okteta {
20
formatNames()21 const QStringList& formatNames()
22 {
23 static QStringList list = QStringList {
24 // i18nc("@item:inlistbox guessing the coding of the bytes by the input", "Auto"),
25 i18nc("@item:inlistbox coding of the bytes as values in the hexadecimal format", "Hex"),
26 i18nc("@item:inlistbox coding of the bytes as values in the decimal format", "Dec"),
27 i18nc("@item:inlistbox coding of the bytes as values in the octal format", "Oct"),
28 i18nc("@item:inlistbox coding of the bytes as values in the binary format", "Bin"),
29 i18nc("@item:inlistbox coding of the bytes as characters with the values", "Char"),
30 i18nc("@item:inlistbox coding of the bytes as UTF-8 characters with the values", "UTF-8"),
31 };
32 return list;
33 }
34
init()35 void ByteArrayComboBoxPrivate::init()
36 {
37 Q_Q(ByteArrayComboBox);
38
39 auto* baseLayout = new QHBoxLayout(q);
40 baseLayout->setContentsMargins(0, 0, 0, 0);
41 baseLayout->setSpacing(0);
42
43 mFormatComboBox = new KComboBox(q);
44 mFormatComboBox->addItems(formatNames());
45 QObject::connect(mFormatComboBox, QOverload<int>::of(&QComboBox::activated),
46 q, [&](int index) { onFormatChanged(index); });
47
48 mValueComboBox = new KComboBox(q);
49 mValueComboBox->setEditable(true);
50 mValueComboBox->setMaxCount(10);
51 mValueComboBox->setInsertPolicy(QComboBox::NoInsert);
52 mValueComboBox->setDuplicatesEnabled(false);
53 q->setFocusProxy(mValueComboBox);
54 QObject::connect(mValueComboBox->lineEdit(), &QLineEdit::textEdited,
55 q, [&](const QString& text) { onValueEdited(text); });
56 QAbstractItemView* formatComboBoxListView = mFormatComboBox->view();
57 QObject::connect(formatComboBoxListView, &QAbstractItemView::activated,
58 mValueComboBox, QOverload<>::of(&KComboBox::setFocus));
59 // TODO: is a workaround for Qt 4.5.1 which doesn't emit activated() for mouse clicks
60 QObject::connect(formatComboBoxListView, &QAbstractItemView::pressed,
61 mValueComboBox, QOverload<>::of(&KComboBox::setFocus));
62 mValidator = new ByteArrayValidator(mValueComboBox);
63 const ByteArrayValidator::Coding coding =
64 static_cast<ByteArrayValidator::Coding>(mFormatComboBox->currentIndex());
65 mValidator->setCodec(coding);
66
67 mValueComboBox->setValidator(mValidator);
68 QObject::connect(mValueComboBox, QOverload<int>::of(&QComboBox::activated),
69 q, [&](int index) { onValueActivated(index); });
70
71 baseLayout->addWidget(mFormatComboBox);
72 baseLayout->addWidget(mValueComboBox, 1);
73 QWidget::setTabOrder(mFormatComboBox, mValueComboBox);
74 }
75
setByteArray(const QByteArray & byteArray)76 void ByteArrayComboBoxPrivate::setByteArray(const QByteArray& byteArray)
77 {
78 mValueComboBox->setEditText(mValidator->toString(byteArray));
79 }
80
setCharCodec(const QString & charCodecName)81 void ByteArrayComboBoxPrivate::setCharCodec(const QString& charCodecName)
82 {
83 const bool isChar8Visible = (mFormatComboBox->currentIndex() == ByteArrayValidator::CharCoding);
84
85 // update the char string if shown
86 QByteArray currentByteArray;
87 if (isChar8Visible) {
88 const QString currentChar8String = mValueComboBox->currentText();
89 currentByteArray = mValidator->toByteArray(currentChar8String);
90 }
91
92 mValidator->setCharCodec(charCodecName);
93
94 if (isChar8Visible) {
95 const QString char8String = mValidator->toString(currentByteArray);
96 mValueComboBox->setEditText(char8String);
97 }
98 }
99
setMaxLength(int maxLength)100 void ByteArrayComboBoxPrivate::setMaxLength(int maxLength)
101 {
102 const int oldMaxLength = mValidator->maxLength();
103 if (oldMaxLength == maxLength) {
104 return;
105 }
106
107 mValidator->setMaxLength(maxLength);
108
109 if (oldMaxLength > maxLength) {
110 QString currentText = mValueComboBox->currentText();
111 int dummyPos;
112 mValidator->validate(currentText, dummyPos);
113 mValueComboBox->setEditText(currentText);
114 }
115 }
116
setMinLength(int minLength)117 void ByteArrayComboBoxPrivate::setMinLength(int minLength)
118 {
119 const int oldMinLength = mValidator->minLength();
120 if (oldMinLength == minLength) {
121 return;
122 }
123
124 mValidator->setMinLength(minLength);
125
126 if (oldMinLength < minLength) {
127 QString currentText = mValueComboBox->currentText();
128 int dummyPos;
129 mValidator->validate(currentText, dummyPos);
130 mValueComboBox->setEditText(currentText);
131 }
132 }
133
rememberCurrentByteArray()134 void ByteArrayComboBoxPrivate::rememberCurrentByteArray()
135 {
136 mValueComboBox->insertItem(-1, mValueComboBox->currentText(), mFormatComboBox->currentIndex());
137 }
138
maxLength() const139 int ByteArrayComboBoxPrivate::maxLength() const
140 {
141 return mValidator->maxLength();
142 }
143
minLength() const144 int ByteArrayComboBoxPrivate::minLength() const
145 {
146 return mValidator->minLength();
147 }
148
onFormatChanged(int index)149 void ByteArrayComboBoxPrivate::onFormatChanged(int index)
150 {
151 Q_Q(ByteArrayComboBox);
152
153 const QString currentValueText = mValueComboBox->currentText();
154 const bool isCurrentValueTextEmpty = currentValueText.isEmpty();
155 const QByteArray byteArray = isCurrentValueTextEmpty ? QByteArray() : mValidator->toByteArray(currentValueText);
156
157 mValidator->setCodec(static_cast<ByteArrayValidator::Coding>(index));
158
159 if (!isCurrentValueTextEmpty) {
160 const QString convertedValueText = mValidator->toString(byteArray);
161 mValueComboBox->setEditText(convertedValueText);
162 }
163
164 emit q->formatChanged(index);
165 }
166
onValueEdited(const QString & value)167 void ByteArrayComboBoxPrivate::onValueEdited(const QString& value)
168 {
169 Q_Q(ByteArrayComboBox);
170
171 const QByteArray byteArray = mValidator->toByteArray(value);
172
173 emit q->byteArrayChanged(byteArray);
174 }
175
onValueActivated(int index)176 void ByteArrayComboBoxPrivate::onValueActivated(int index)
177 {
178 Q_Q(ByteArrayComboBox);
179
180 if (index != -1) {
181 const int oldFormatIndex = mFormatComboBox->currentIndex();
182 const int itemFormatIndex = mValueComboBox->itemData(index).toInt();
183 const bool isOtherFormat = (oldFormatIndex != itemFormatIndex);
184
185 if (isOtherFormat) {
186 mFormatComboBox->setCurrentIndex(itemFormatIndex);
187 mValidator->setCodec(static_cast<ByteArrayValidator::Coding>(itemFormatIndex));
188
189 }
190 const QString currentValueText = mValueComboBox->currentText();
191 const QByteArray byteArray = mValidator->toByteArray(currentValueText);
192
193 emit q->byteArrayChanged(byteArray);
194 if (isOtherFormat) {
195 emit q->formatChanged(itemFormatIndex);
196 }
197 }
198 }
199
200 }
201