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