1 /*
2 SPDX-FileCopyrightText: 2012-2013 Evan Teran <evan.teran@gmail.com>
3 SPDX-FileCopyrightText: 2006 Michel Marti <mma@objectxp.com>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include "kcalc_bitset.h"
9 #include "bitbutton.h"
10
11 #include <KLocalizedString>
12 #include <QButtonGroup>
13 #include <QGridLayout>
14 #include <QHBoxLayout>
15 #include <QLabel>
16 #include <QPainter>
17
18 // TODO: I think it would actually be appropriate to use a std::bitset<64>
19 // for the internal representation of this class perhaps
20 // the only real caveat is the conversion to/from quint64
21
22 //------------------------------------------------------------------------------
23 // Name: paintEvent
24 // Desc: draws the button
25 //------------------------------------------------------------------------------
paintEvent(QPaintEvent *)26 void BitButton::paintEvent(QPaintEvent *)
27 {
28 uint8_t alpha = 0x60;
29 QPainter painter(this);
30 painter.setRenderHint(QPainter::Antialiasing, true);
31 QPen pen(palette().text(), 1);
32 pen.setJoinStyle(Qt::MiterJoin);
33 painter.setPen(pen);
34
35 if (on_) {
36 painter.setBrush(palette().text());
37 alpha = 0xB0;
38 } else {
39 painter.setBrush(palette().base());
40 }
41
42 if (over_) {
43 painter.setBrush(QColor(palette().text().color().red(), palette().text().color().green(), palette().text().color().blue(), alpha));
44 }
45
46 painter.drawRect(rect().adjusted(1, 1, -1, -1));
47 }
48
49 //------------------------------------------------------------------------------
50 // Name: KCalcBitset
51 // Desc: constructor
52 //------------------------------------------------------------------------------
KCalcBitset(QWidget * parent)53 KCalcBitset::KCalcBitset(QWidget *parent)
54 : QFrame(parent)
55 , bit_button_group_(new QButtonGroup(this))
56 , value_(0)
57 {
58 setFrameStyle(QFrame::Panel | QFrame::Sunken);
59
60 connect(bit_button_group_, qOverload<QAbstractButton *>(&QButtonGroup::buttonClicked), this, &KCalcBitset::slotToggleBit);
61
62 // smaller label font
63 QFont fnt = font();
64 if (fnt.pointSize() > 6) {
65 fnt.setPointSize(fnt.pointSize() - 1);
66 }
67
68 // main layout
69 auto layout = new QGridLayout(this);
70 layout->setContentsMargins(2, 2, 2, 2);
71 layout->setSpacing(0);
72
73 // create bits
74 int bitCounter = 63;
75 for (int rows = 0; rows < 2; rows++) {
76 for (int cols = 0; cols < 4; cols++) {
77 // two rows of four words
78 auto const wordlayout = new QHBoxLayout();
79 wordlayout->setContentsMargins(2, 2, 2, 2);
80 wordlayout->setSpacing(2);
81 layout->addLayout(wordlayout, rows, cols);
82
83 for (int bit = 0; bit < 8; bit++) {
84 auto const tmpBitButton = new BitButton(this);
85 tmpBitButton->setToolTip(i18n("Bit %1 = %2", bitCounter, 1ULL << bitCounter));
86 wordlayout->addWidget(tmpBitButton);
87 bit_button_group_->addButton(tmpBitButton, bitCounter);
88 bitCounter--;
89 }
90
91 // label word
92 auto label = new QLabel(this);
93 label->setText(QString::number(bitCounter + 1));
94 label->setFont(fnt);
95 wordlayout->addWidget(label);
96 }
97 }
98 }
99
100 //------------------------------------------------------------------------------
101 // Name: setValue
102 // Desc: set the value of the bitset based on an unsigned 64-bit number
103 //------------------------------------------------------------------------------
setValue(quint64 value)104 void KCalcBitset::setValue(quint64 value)
105 {
106 if (value_ == value) {
107 // don't waste time if there was no change..
108 return;
109 }
110
111 value_ = value;
112
113 // set each bit button
114 for (int i = 0; i < 64; i++) {
115 if (auto bb = qobject_cast<BitButton *>(bit_button_group_->button(i))) {
116 bb->setOn(value & 1);
117 }
118 value >>= 1;
119 }
120 }
121
122 //------------------------------------------------------------------------------
123 // Name: getValue
124 // Desc: returns the bitset value as an unsigned 64-bit number
125 //------------------------------------------------------------------------------
getValue() const126 quint64 KCalcBitset::getValue() const
127 {
128 return value_;
129 }
130
131 //------------------------------------------------------------------------------
132 // Name: slotToggleBit
133 // Desc: inverts the value of a single bit
134 //------------------------------------------------------------------------------
slotToggleBit(QAbstractButton * button)135 void KCalcBitset::slotToggleBit(QAbstractButton *button)
136 {
137 if (button) {
138 const int bit = bit_button_group_->id(button);
139 const quint64 nv = getValue() ^ (1LL << bit);
140 setValue(nv);
141 Q_EMIT valueChanged(value_);
142 }
143 }
144