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 "addresscombobox_p.hpp"
10 #include "addresscombobox.hpp"
11
12 // KF
13 #include <KLocalizedString>
14 // Qt
15 #include <QLayout>
16 #include <QLineEdit>
17 #include <QAbstractItemView>
18
19 /*
20 Problem: what to do if the format is changed for which the current string is not valid?
21 Solution: we always convert the string to the new format, so there is never such a situation
22 */
23
24 namespace Okteta {
25
formatStrings()26 static const QStringList& formatStrings()
27 {
28 static QStringList list = QStringList {
29 // i18nc("@item:inlistbox guessing the format of the address by the input", "Auto"),
30 i18nc("@item:inlistbox coding of offset in the hexadecimal format", "Hex"),
31 i18nc("@item:inlistbox coding of offset in the decimal format", "Dec"),
32 i18nc("@item:inlistbox coding of offset in the expression format", "Expr"),
33 };
34 return list;
35 }
36
init()37 void AddressComboBoxPrivate::init()
38 {
39 Q_Q(AddressComboBox);
40
41 auto* baseLayout = new QHBoxLayout(q);
42 baseLayout->setContentsMargins(0, 0, 0, 0);
43 baseLayout->setSpacing(0);
44
45 mFormatComboBox = new KComboBox(q);
46 mFormatComboBox->addItems(formatStrings());
47 QObject::connect(mFormatComboBox, QOverload<int>::of(&QComboBox::activated),
48 q, [&](int index) { onFormatChanged(index); });
49
50 mValueComboBox = new KComboBox(q);
51 mValueComboBox->setEditable(true);
52 mValueComboBox->setMaxCount(10);
53 mValueComboBox->setInsertPolicy(QComboBox::NoInsert);
54 mValueComboBox->setDuplicatesEnabled(false);
55 q->setFocusProxy(mValueComboBox);
56 QObject::connect(mValueComboBox->lineEdit(), &QLineEdit::textEdited,
57 q, [&](const QString& text) { onValueEdited(text); });
58 QAbstractItemView* formatComboBoxListView = mFormatComboBox->view();
59 QObject::connect(formatComboBoxListView, &QAbstractItemView::activated,
60 mValueComboBox, QOverload<>::of(&KComboBox::setFocus));
61 // TODO: is a workaround for Qt 4.5.1 which doesn't emit activated() for mouse clicks
62 QObject::connect(formatComboBoxListView, &QAbstractItemView::pressed,
63 mValueComboBox, QOverload<>::of(&KComboBox::setFocus));
64 mValidator = new AddressValidator(mValueComboBox, AddressValidator::HexadecimalCoding);
65 const AddressValidator::Coding coding =
66 static_cast<AddressValidator::Coding>(mFormatComboBox->currentIndex());
67 mValidator->setCodec(coding);
68 mValueComboBox->setValidator(mValidator);
69 QObject::connect(mValueComboBox, QOverload<int>::of(&QComboBox::activated),
70 q, [&](int index) { onValueActivated(index); });
71 baseLayout->addWidget(mFormatComboBox);
72 baseLayout->addWidget(mValueComboBox, 1);
73 QWidget::setTabOrder(mFormatComboBox, mValueComboBox);
74 }
75
rememberCurrentAddress()76 void AddressComboBoxPrivate::rememberCurrentAddress()
77 {
78 // don't insert same value multiple times in a row
79 if (mValueComboBox->itemText(0) != mValueComboBox->currentText()) {
80 mValueComboBox->insertItem(-1, mValueComboBox->currentText(), mFormatComboBox->currentIndex());
81 }
82 }
83
onFormatChanged(int formatIndex)84 void AddressComboBoxPrivate::onFormatChanged(int formatIndex)
85 {
86 Q_Q(AddressComboBox);
87
88 const QString currentValueText = mValueComboBox->currentText();
89 const bool isCurrentValueTextEmpty = currentValueText.isEmpty();
90
91 AddressValidator::AddressType addressType;
92 Address address;
93 if (isCurrentValueTextEmpty) {
94 address = -1;
95 addressType = mAddressType;
96 } else {
97 address = mValidator->toAddress(currentValueText, &addressType);
98 }
99
100 mValidator->setCodec(static_cast<AddressValidator::Coding>(formatIndex));
101
102 if (!isCurrentValueTextEmpty) {
103 const QString convertedValueText = mValidator->toString(address, addressType);
104 mValueComboBox->setEditText(convertedValueText);
105 }
106
107 if (mAddressType != addressType) {
108 mAddressType = addressType;
109 emit q->addressTypeChanged(mAddressType);
110 }
111 emit q->formatChanged(formatIndex);
112 }
113
onValueEdited(const QString & value)114 void AddressComboBoxPrivate::onValueEdited(const QString& value)
115 {
116 Q_Q(AddressComboBox);
117
118 AddressValidator::AddressType addressType;
119 const Address address = mValidator->toAddress(value, &addressType);
120
121 if (mAddressType != addressType) {
122 mAddressType = addressType;
123 emit q->addressTypeChanged(mAddressType);
124 }
125 emit q->addressChanged(address);
126 }
127
onValueActivated(int index)128 void AddressComboBoxPrivate::onValueActivated(int index)
129 {
130 Q_Q(AddressComboBox);
131
132 if (index != -1) {
133 const int oldFormatIndex = mFormatComboBox->currentIndex();
134 const int itemFormatIndex = mValueComboBox->itemData(index).toInt();
135
136 const bool isOtherFormat = (oldFormatIndex != itemFormatIndex);
137 if (isOtherFormat) {
138 mFormatComboBox->setCurrentIndex(itemFormatIndex);
139 mValidator->setCodec(static_cast<AddressValidator::Coding>(itemFormatIndex));
140
141 }
142 const QString currentValueText = mValueComboBox->currentText();
143
144 AddressValidator::AddressType addressType;
145 const Address address = mValidator->toAddress(currentValueText, &addressType);
146
147 if (mAddressType != addressType) {
148 mAddressType = addressType;
149 emit q->addressTypeChanged(mAddressType);
150 }
151 emit q->addressChanged(address);
152 if (isOtherFormat) {
153 emit q->formatChanged(itemFormatIndex);
154 }
155 }
156 }
157
158 }
159