ArvizProfileManagerWidget.cpp
Go to the documentation of this file.
2
3#include <string>
4
5#include <QBoxLayout>
6#include <QDialogButtonBox>
7#include <QFormLayout>
8#include <QLabel>
9#include <QMessageBox>
10#include <QPushButton>
11#include <QRadioButton>
12#include <QVBoxLayout>
13
16
17namespace armarx
18{
19
20 const QString ArvizProfileManagerWidget::SETTINGS_DEFAULT_PROFILE_KEY = "defaultProfileName";
21
23 const QString& name,
24 bool additive,
25 bool addDialog,
26 bool isDefault) :
27 QDialog(parent)
28 {
29 setWindowTitle(addDialog ? "Add ArViz Profile" : "Edit ArViz Profile");
30
31 // Set up UI components
32 nameInput = new QLineEdit(this);
33 nameInput->setText(name);
34
35 additiveRadioButton = new QRadioButton("Save added layers", this);
36 additiveRadioButton->setChecked(additive);
37 substractiveRadioButton = new QRadioButton("Save removed layers", this);
38 substractiveRadioButton->setChecked(not additive);
39
40 defaultCheckBox = new QCheckBox("Mark default", this);
41 defaultCheckBox->setChecked(isDefault);
42
43 // Save/Cancel buttons
44 QDialogButtonBox* buttonBox =
45 new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel, this);
46 connect(buttonBox, &QDialogButtonBox::accepted, this, &ProfileDialog::accept);
47 connect(buttonBox, &QDialogButtonBox::rejected, this, &ProfileDialog::reject);
48 buttonBox->setCenterButtons(true);
49
50 // Delete button
51 deleteButton = new QPushButton("Delete", this);
52 connect(deleteButton, &QPushButton::clicked, this, &ProfileDialog::deleteProfile);
53
54 // Layouts
55 QFormLayout* formLayout = new QFormLayout;
56 formLayout->addRow("Profile Name:", nameInput);
57 formLayout->addRow(additiveRadioButton);
58 formLayout->addRow(substractiveRadioButton);
59 formLayout->addRow(defaultCheckBox);
60 formLayout->addRow(buttonBox);
61 formLayout->addRow(deleteButton);
62
63 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
64 setLayout(formLayout);
65 adjustSize();
66 }
67
71
72 QString
74 {
75 return nameInput->text();
76 }
77
78 bool
80 {
81 return additiveRadioButton->isChecked();
82 }
83
84 bool
86 {
87 return defaultCheckBox->isChecked();
88 }
89
90 void
91 ProfileDialog::deleteProfile()
92 {
93 // Handle the profile deletion
95 reject(); // Close the dialog after deletion
96 }
97
99 QWidget(parent),
100 settings(QString((armarx::ArmarXDataPath::GetDefaultUserConfigPath() +
101 "/ArvizProfileManager.conf")
102 .c_str()),
103 QSettings::NativeFormat),
104 currentProfile(Profile())
105 {
106 QHBoxLayout* layout = new QHBoxLayout(this);
107
108 // Setup UI elements
109 layersComboBox = new QComboBox(this);
110 connect(layersComboBox,
111 QOverload<int>::of(&QComboBox::activated),
112 this,
114
115 addButton = new QPushButton("Add", this);
116 editButton = new QPushButton("Edit", this);
117 saveButton = new QPushButton("Save", this);
118
119 layout->addWidget(new QLabel("ArViz Profile: "));
120 layout->addWidget(layersComboBox);
121 layout->addWidget(addButton);
122 layout->addWidget(editButton);
123 layout->addWidget(saveButton);
124
125 setLayout(layout);
126
127 connect(addButton, &QPushButton::clicked, this, &ArvizProfileManagerWidget::addProfile);
128 connect(editButton, &QPushButton::clicked, this, &ArvizProfileManagerWidget::editProfile);
129 connect(saveButton,
130 &QPushButton::clicked,
131 this,
132 &ArvizProfileManagerWidget::saveCurrentProfile);
133
134 loadLayerNames();
135
136 // Load default profile
137 const QString defaultProfileName = settings.value(SETTINGS_DEFAULT_PROFILE_KEY).toString();
138 if (int i = layersComboBox->findText(defaultProfileName); i >= 0)
139 {
140 layersComboBox->setCurrentText(defaultProfileName);
142 }
143 else
144 {
145 // Not found. Load empty profile
146 layersComboBox->setCurrentIndex(-1);
147 }
148 }
149
150 void
152 {
153 if (index >= 0 and index < layersComboBox->count())
154 {
155 loadProfile(layersComboBox->itemText(index));
156 emit publishUpdate();
157 }
158 }
159
160 void
161 ArvizProfileManagerWidget::saveCurrentProfile()
162 {
163 const QString name = layersComboBox->currentText();
164 if (name.isEmpty())
165 {
166 QMessageBox::warning(this, "Warning", "Please enter a valid name.");
167 return;
168 }
169
170 if (saveProfile(name, currentProfile))
171 {
172 if (layersComboBox->findText(name) == -1)
173 {
174 layersComboBox->addItem(name);
175 }
176 layersComboBox->setCurrentText(name);
177 }
178 }
179
180 void
181 ArvizProfileManagerWidget::deleteCurrentProfileSave()
182 {
183 const QString name = layersComboBox->currentText();
184 settings.remove(name);
185
186 const int index = layersComboBox->currentIndex();
187 layersComboBox->removeItem(index);
188 settings.remove(name);
189
190 if (layersComboBox->count() == 0)
191 {
192 editButton->setDisabled(true);
193 saveButton->setDisabled(true);
194 }
195
196 emit publishUpdate();
197 }
198
199 void
200 ArvizProfileManagerWidget::addProfile()
201 {
202 if (dialog == nullptr || !dialog->isVisible())
203 {
204 const QString defaultName = "Profile";
205 const bool defaultAdditive = false;
206 QString name = defaultName;
207 unsigned int counter = 2;
208 while (layersComboBox->count() > 0 and layersComboBox->findText(name) >= 0)
209 {
210 name = defaultName + QString::fromStdString(std::to_string(counter++));
211 }
212 dialog = new ProfileDialog(this,
213 name,
214 defaultAdditive,
215 true,
216 settings.value(SETTINGS_DEFAULT_PROFILE_KEY) == name);
217 const int result = dialog->exec();
218
219 if (result == QDialog::Accepted)
220 {
221 if (dialog->getName().isEmpty())
222 {
223 ARMARX_WARNING << "Empty name for profile set.";
224 return;
225 }
226 if (layersComboBox->findText(dialog->getName()) >= 0)
227 {
228 ARMARX_WARNING << "Profile with name " << dialog->getName().toStdString()
229 << " already exists!";
230 return;
231 }
232
233 if (dialog->isDefaultProfile())
234 {
235 settings.setValue(SETTINGS_DEFAULT_PROFILE_KEY, dialog->getName());
236 }
237
238 currentProfile.layers = {};
239 currentProfile.additive = dialog->isAdditive();
240 emit fetchUpdate();
241
242 saveProfile(dialog->getName(), currentProfile);
243 loadLayerNames();
244 layersComboBox->setCurrentText(dialog->getName());
245 }
246 else
247 {
248 // do nothing
249 }
250 }
251 else
252 {
253 QMessageBox::information(this, "Dialog Already Open", "The dialog is already open.");
254 }
255 }
256
257 void
258 ArvizProfileManagerWidget::editProfile()
259 {
260 if (layersComboBox->count() > 0)
261 {
262 if (dialog == nullptr || !dialog->isVisible())
263 {
264 const auto name = layersComboBox->currentText();
265 dialog = new ProfileDialog(this,
266 name,
267 currentProfile.additive,
268 false,
269 settings.value(SETTINGS_DEFAULT_PROFILE_KEY) == name);
270 connect(dialog,
272 this,
273 &ArvizProfileManagerWidget::deleteCurrentProfileSave);
274 const int result = dialog->exec();
275
276 if (result == QDialog::Accepted)
277 {
278 const auto newName = dialog->getName();
279
280 if (newName.isEmpty())
281 {
282 ARMARX_WARNING << "Empty name for profile set.";
283 return;
284 }
285
286 if (newName != name)
287 {
288 // Rename
289 if (layersComboBox->findText(newName) >= 0)
290 {
291 ARMARX_WARNING << "Profile with name " << newName.toStdString()
292 << " already exists!";
293 return;
294 }
295 settings.remove(layersComboBox->currentText());
296 }
297
298 if (dialog->isAdditive() != currentProfile.additive)
299 {
300 currentProfile.layers.clear();
301 currentProfile.additive = dialog->isAdditive();
302 emit fetchUpdate();
303 }
304
305 if (dialog->isDefaultProfile())
306 {
307 settings.setValue(SETTINGS_DEFAULT_PROFILE_KEY, newName);
308 }
309 else if (settings.value(SETTINGS_DEFAULT_PROFILE_KEY) == name)
310 {
311 settings.setValue(SETTINGS_DEFAULT_PROFILE_KEY, "");
312 }
313
314 saveProfile(dialog->getName(), currentProfile);
315 loadLayerNames();
316 layersComboBox->setCurrentText(newName);
317 }
318 else
319 {
320 // do nothing
321 }
322 }
323 else
324 {
325 QMessageBox::information(
326 this, "Dialog Already Open", "The dialog is already open.");
327 }
328 }
329 }
330
331 void
332 ArvizProfileManagerWidget::loadLayerNames()
333 {
334 layersComboBox->clear();
335 for (const QString& groups : settings.childGroups())
336 {
337 layersComboBox->addItem(groups);
338 }
339 if (layersComboBox->count() == 0)
340 {
341 editButton->setDisabled(true);
342 saveButton->setDisabled(true);
343 }
344 else
345 {
346 editButton->setEnabled(true);
347 saveButton->setEnabled(true);
348 }
349 }
350
351 void
352 ArvizProfileManagerWidget::loadProfile(const QString& name)
353 {
354 ARMARX_INFO << "Loading ArViz profile " << name.toStdString();
355
356 std::scoped_lock lock(mtx);
357 currentProfile.layers.clear();
358
359 settings.beginGroup(name);
360 currentProfile.additive = settings.value("additive").toBool();
361 const int size = settings.beginReadArray("layers");
362 for (int i = 0; i < size; ++i)
363 {
364 settings.setArrayIndex(i);
365 QString first = settings.value("component").toString();
366 QString second = settings.value("layer").toString();
367 currentProfile.layers.insert({first.toStdString(), second.toStdString()});
368 }
369 settings.endArray();
370 settings.endGroup();
371 editButton->setEnabled(true);
372 }
373
374 bool
375 ArvizProfileManagerWidget::saveProfile(const QString& name, const Profile& profile)
376 {
377 settings.beginGroup(name);
378 settings.setValue("additive", profile.additive);
379 settings.remove("layers");
380 settings.beginWriteArray("layers", profile.layers.size());
381 int i = 0;
382 for (const auto& pair : profile.layers)
383 {
384 settings.setArrayIndex(i++);
385 settings.setValue("component", QString::fromStdString(pair.first));
386 settings.setValue("layer", QString::fromStdString(pair.second));
387 }
388 settings.endArray();
389 settings.endGroup();
390 return true;
391 }
392
393} // namespace armarx
uint8_t index
The ArmarXDataPath class provides static methods to handle ArmarX data directories.
ProfileDialog(QWidget *parent=nullptr, const QString &name="", bool additive=false, bool addDialog=true, bool isDefault=false)
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
This file offers overloads of toIce() and fromIce() functions for STL container types.