gqtbuttonswidget
Loading...
Searching...
No Matches
gQtButtonsWidget.cc
Go to the documentation of this file.
1#include "gQtButtonsWidget.h"
2#include <QFileInfo>
3#include <QBoxLayout>
4#include <QListView>
5
6/* --- ButtonInfo Implementation ---
7 *
8 * This implementation provides:
9 * - construction of a QListWidgetItem configured as selectable/enabled
10 * - icon lookup using the "<base>_<state>.svg" filename convention
11 */
12
13ButtonInfo::ButtonInfo(const std::string& icon)
14 : buttonName(icon) {
15 thisButton = new QListWidgetItem();
16
17 // Initialize the item in the "normal" state.
18 thisButton->setIcon(iconForState(1));
19
20 // The list item must be enabled/selectable to behave as a clickable icon entry.
21 thisButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
22}
23
24QIcon ButtonInfo::iconForState(int state) const {
25 // Build the expected resource/file name for the requested state.
26 std::string filename = buttonName + "_" + std::to_string(state) + ".svg";
27
28 // QFileInfo is used as an existence check; if missing, return an empty icon.
29 QFileInfo fileInfo(QString::fromStdString(filename));
30 if (fileInfo.exists() && fileInfo.isFile()) {
31 return QIcon(QString::fromStdString(filename));
32 }
33 return QIcon();
34}
35
36/* --- GQTButtonsWidget Implementation ---
37 *
38 * This widget:
39 * - builds one ButtonInfo per base icon name
40 * - displays them in a QListWidget configured for icon mode
41 * - updates icons on press to reflect "normal" vs "pressed" state
42 */
43
45 const std::vector<std::string>& bicons,
46 bool vertical, QWidget* parent)
47 : QWidget(parent) {
48 constexpr int distanceToMargin = 12;
49
50 // Convert icon base names into internal ButtonInfo entries.
51 for (const auto& b : bicons) {
52 buttons.push_back(new ButtonInfo(b));
53 }
54
55 // Create and configure the QListWidget backend (icon mode, fixed icon size).
56 buttonsWidget = new QListWidget(this);
57 buttonsWidget->setViewMode(QListView::IconMode);
58 buttonsWidget->setIconSize(QSize(static_cast<int>(h), static_cast<int>(v)));
59
60 // Remove selection highlight to keep the visual "button" look consistent.
61 buttonsWidget->setStyleSheet(
62 "background-color: transparent; "
63 "QListWidget::item:selected { background: transparent; border: none; }");
64
65 // Insert each QListWidgetItem into the list widget.
66 for (auto& b : buttons) {
67 buttonsWidget->addItem(b->thisButton);
68 }
69
70 // When an item is pressed, update all icons so only the pressed one shows state 2.
71 connect(buttonsWidget, &QListWidget::itemPressed,
72 this, &GQTButtonsWidget::buttonWasPressed);
73
74 // Choose layout based on the requested orientation.
75 QBoxLayout* layout = vertical
76 ? static_cast<QBoxLayout*>(new QVBoxLayout(this))
77 : static_cast<QBoxLayout*>(new QHBoxLayout(this));
78 layout->setContentsMargins(0, 0, 0, 0);
79 layout->addWidget(buttonsWidget);
80 setLayout(layout);
81
82 // Size the widget so the icon strip fits exactly (plus a margin factor).
83 double hsize = (h + distanceToMargin) * (buttons.size());
84 double vsize = v + distanceToMargin;
85 if (vertical) {
86 hsize = h + distanceToMargin;
87 vsize = (v + distanceToMargin) * (buttons.size());
88 }
89 buttonsWidget->setFixedSize(static_cast<int>(hsize), static_cast<int>(vsize));
90
91 // Final style: remove focus rectangles and keep a transparent background.
92 buttonsWidget->setFocusPolicy(Qt::NoFocus);
93 buttonsWidget->setStyleSheet(
94 "QListWidget { background-color: transparent; }"
95 "QListWidget::item { background: transparent; border: none; }"
96 "QListWidget::item:selected { background: transparent; border: none; outline: none; }"
97 );
98}
99
101 // Select the requested row and switch its icon to the "pressed" state.
102 buttonsWidget->setCurrentRow(i);
103 if (i >= 0 && i < static_cast<int>(buttons.size()))
104 buttonsWidget->item(i)->setIcon(buttons[i]->iconForState(2));
105}
106
107void GQTButtonsWidget::buttonWasPressed(QListWidgetItem* item) {
108 // Reset all items to normal state.
109 for (int i = 0; i < buttonsWidget->count(); i++) {
110 buttonsWidget->item(i)->setIcon(buttons[i]->iconForState(1));
111 }
112
113 // Set the icon for the pressed item.
114 int index = buttonsWidget->row(item);
115 item->setIcon(buttons[index]->iconForState(2));
116}
117
119 // Restore every button icon to the "normal" state (state 1).
120 for (auto& b : buttons) {
121 b->thisButton->setIcon(b->iconForState(1));
122 }
123}
124
125/* --- GQTToggleButtonWidget Implementation ---
126 *
127 * This widget:
128 * - creates one checkable QPushButton per title
129 * - arranges them vertically/horizontally
130 * - tracks the last clicked button index and emits a signal on changes
131 */
132
133GQTToggleButtonWidget::GQTToggleButtonWidget(int buttonWidth, int buttonHeight, int borderRadius,
134 const std::vector<std::string>& titles,
135 bool vertical, QWidget* parent)
136 : QWidget(parent),
137 buttonPressedIndex(-1) {
138 QBoxLayout* layout = vertical
139 ? static_cast<QBoxLayout*>(new QVBoxLayout(this))
140 : static_cast<QBoxLayout*>(new QHBoxLayout(this));
141
142 // Convert std::string titles to QString for QPushButton labels.
143 QStringList buttonStrings;
144 for (const auto& title : titles) {
145 buttonStrings.append(QString::fromStdString(title));
146 }
147
148 // Create a toggleable button for each title.
149 for (int i = 0; i < buttonStrings.size(); ++i) {
150 QPushButton* button = new QPushButton(buttonStrings[i], this);
151 button->setCheckable(true);
152 button->setFixedSize(buttonWidth, buttonHeight);
153
154 // Style: rounded corners, bold text, and different background when checked.
155 button->setStyleSheet(QString(
156 "QPushButton {"
157 " border-radius: %1px;"
158 " border: 2px solid black;"
159 " background-color: rgba(255, 0, 0, 150);"
160 " font-weight: bold;"
161 "}"
162 "QPushButton:checked {"
163 " background-color: rgba(0, 255, 0, 150);"
164 "}"
165 ).arg(borderRadius));
166
167 layout->addWidget(button);
168 buttons.push_back(button);
169
170 // Use a lambda to bind each button click to its index.
171 connect(button, &QPushButton::clicked, this, [this, i]() {
172 this->setButtonPressed(i);
173 });
174 }
175 setLayout(layout);
176}
177
179 // A missing or invalid index is treated as "not checked".
180 if (buttonPressedIndex >= 0 && buttonPressedIndex < buttons.size())
181 return buttons[buttonPressedIndex]->isChecked();
182 return false;
183}
184
186 // Toggle changes checked->unchecked or unchecked->checked.
187 if (index >= 0 && index < buttons.size())
188 buttons[index]->toggle();
189}
190
192 // Query individual button state; invalid index returns false.
193 if (index >= 0 && index < buttons.size())
194 return buttons[index]->isChecked();
195 return false;
196}
197
198void GQTToggleButtonWidget::setButtonPressed(int index) {
199 // Track the last pressed index and notify listeners.
200 buttonPressedIndex = index;
201 emit buttonPressedIndexChanged(buttonPressedIndex);
202}
203
205 // Uncheck all buttons; does not change the stored pressed index.
206 for (auto& b : buttons) {
207 b->setChecked(false);
208 }
209}
void reset_buttons()
Reset all buttons to the "normal" icon state.
QListWidget * buttonsWidget
Underlying QListWidget used to render the icons.
void press_button(int i)
Programmatically press a button.
GQTButtonsWidget(double h, double v, const std::vector< std::string > &bicons, bool vertical=true, QWidget *parent=nullptr)
Constructs a GQTButtonsWidget.
void toggleButton(int index)
Toggle the checked state of a button.
GQTToggleButtonWidget(int buttonWidth, int buttonHeight, int borderRadius, const std::vector< std::string > &titles, bool vertical=true, QWidget *parent=nullptr)
Constructs a GQTToggleButtonWidget.
void reset_buttons()
Uncheck all buttons.
void buttonPressedIndexChanged(int index)
Emitted whenever the last pressed button index changes.
bool buttonStatus(int index) const
Returns the checked state for a specific button.
bool lastButtonState() const
Returns the checked state of the last pressed button.
Logical description of one icon-button entry used by GQTButtonsWidget.
QListWidgetItem * thisButton
The UI item representing this logical button.
ButtonInfo(const std::string &icon)
Constructs a ButtonInfo for a given base icon name.
QIcon iconForState(int state) const
Returns the icon for a given interaction state.