StateDialog.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package
19 * @author
20 * @date
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24#include "StateDialog.h"
25
26#include <iterator>
27
28#include <QDesktopWidget>
29#include <QFileDialog>
30#include <QInputDialog>
31#include <QMessageBox>
32#include <QtGui>
33
36
37#include <ArmarXGui/gui-plugins/StatechartEditorPlugin/view/dialogs/ui_StateDialog.h>
40
42
43namespace armarx
44{
45
46 QMap<QString, DynamicLibraryPtr> StateDialog::Libraries = QMap<QString, DynamicLibraryPtr>();
47
49 Ice::CommunicatorPtr communicator,
50 VariantInfoPtr variantInfo,
51 StatechartProfilePtr currentProfile,
52 bool locked,
53 bool readOnly,
54 QPointer<TipDialog> tipDialog,
55 QWidget* parent) :
56 QDialog(parent),
57 ui(new Ui::StateDialog),
58 stateInstance(stateInstance),
59 communicator(communicator),
60 variantInfo(variantInfo),
61 currentProfile(currentProfile),
62 tipDialog(tipDialog),
63 readOnly(readOnly)
64 {
65 ui->setupUi(this);
66 setWindowTitle("State " + stateInstance->getInstanceName() + " Dialog");
67 ui->tableInput->setCommunicator(communicator);
68 ui->tableLocal->setCommunicator(communicator);
69 ui->tableOutput->setCommunicator(communicator);
70 ui->tableInput->setCurrentProfile(currentProfile);
71 ui->tableLocal->setCurrentProfile(currentProfile);
72 ui->tableOutput->setCurrentProfile(currentProfile);
73 ui->tableLocal->hideColumn(StatechartEditorParameterEditor::eOptional);
74 ui->tableLocal->hideValueColumns();
75 ui->tableOutput->hideValueColumns();
76 // ui->tableLocal->hideColumn(StatechartEditorParameterEditor::eProvideDefaultValue);
77 // ui->tableLocal->hideColumn(StatechartEditorParameterEditor::eEditableValue);
78 // ui->tableOutput->hideColumn(StatechartEditorParameterEditor::eProvideDefaultValue);
79 // ui->tableOutput->hideColumn(StatechartEditorParameterEditor::eEditableValue);
80 ui->tableInput->setVariantInfo(variantInfo);
81 ui->tableLocal->setVariantInfo(variantInfo);
82 ui->tableOutput->setVariantInfo(variantInfo);
83
84 if (stateInstance)
85 {
86 statechartmodel::StatePtr state = stateInstance->getStateClass();
87
88 if (!stateInstance->getParent())
89 {
90 // toplevel state-> instance name is not real anyway
91 ui->editInstanceName->setEnabled(false);
92 }
93
94 ui->editInstanceName->setText(stateInstance->getInstanceName());
95 ui->editInstanceName->setValidator(
96 new QRegExpValidator(QRegExp("([a-zA-Z][a-zA-Z0-9_]*)"), this));
97
98 if (state)
99 {
100 ui->editStateName->setText(state->getStateName());
101 ui->stateDocuEditor->setPlainText(state->getDescription());
102 statechartmodel::EventList outgoingEvents = state->getOutgoingEvents();
103 foreach (statechartmodel::EventPtr e, outgoingEvents)
104 {
105 ui->cbOutgoingEvents->addItem(e->name);
106 eventDescriptionMap[e->name] = e->description;
107 }
108
109 if (!outgoingEvents.isEmpty())
110 {
111 eventNameComboboxChanged(ui->cbOutgoingEvents->currentText());
112 }
113
114 ui->tableInput->setStateInstance(stateInstance);
115 ui->tableInput->buildFromMap(state->getInputParameters());
116 ui->tableLocal->setStateInstance(stateInstance);
117 ui->tableLocal->buildFromMap(state->getLocalParameters());
118 ui->tableOutput->setStateInstance(stateInstance);
119 ui->tableOutput->buildFromMap(state->getOutputParameters());
120
121 connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(setBlackLists()));
122 setBlackLists();
123 }
124 else
125 {
126 ui->editStateName->setEnabled(false);
127 ui->stateDocuEditor->setEnabled(false);
128 ui->cbOutgoingEvents->setEnabled(false);
129 ui->btnAddEvent->setEnabled(false);
130 ui->tabWidget->setTabEnabled(1, false);
131 ui->tabWidget->setTabEnabled(2, false);
132 ui->tabWidget->setTabEnabled(3, false);
133 }
134
136 std::dynamic_pointer_cast<statechartmodel::RemoteState>(stateInstance);
137
138 if (remoteState)
139 {
140 ui->editProxyName->setText(remoteState->proxyName);
141 }
142 else
143 {
144 ui->editProxyName->setEnabled(false);
145 }
146
148 std::dynamic_pointer_cast<statechartmodel::EndState>(stateInstance);
149
150 if (endstate)
151 {
152 ui->labelInstanceName->setText("State/Event name");
153 }
154 else
155 {
156 ui->labelInstanceName->setText("State Instance name");
157 }
158 }
159
160 fileDialog = new QFileDialog(this);
161 fileDialog->setModal(true);
162 fileDialog->setFileMode(QFileDialog::ExistingFiles);
163 fileDialog->setOption(QFileDialog::HideNameFilterDetails, false);
164 QList<QUrl> urls;
165 urls << QUrl::fromLocalFile(
166 QDesktopServices::storageLocation(QDesktopServices::HomeLocation))
167 << QUrl::fromLocalFile(
168 QDesktopServices::storageLocation(QDesktopServices::DesktopLocation));
169
170 if (!ArmarXDataPath::getHomePath().empty())
171 {
172 urls << QUrl::fromLocalFile(QString::fromStdString(ArmarXDataPath::getHomePath()));
173 }
174
175 fileDialog->setSidebarUrls(urls);
176 QStringList fileTypes;
177 fileTypes << tr("Libraries (*.so)") << tr("All Files (*.*)");
178 fileDialog->setNameFilters(fileTypes);
179 // connect(ui->btnLoadLib, SIGNAL(clicked()), fileDialog, SLOT(show()));
180 connect(fileDialog, SIGNAL(accepted()), this, SLOT(loadLibrary()));
181
182 connect(ui->cbOutgoingEvents,
183 SIGNAL(currentIndexChanged(const QString&)),
184 this,
185 SLOT(eventNameComboboxChanged(const QString&)));
186 connect(ui->btnAddEvent, SIGNAL(clicked()), this, SLOT(eventButtonAdd()));
187 connect(ui->btnDeleteEvent, SIGNAL(clicked()), this, SLOT(eventButtonDelete()));
188 connect(
189 ui->editEventDescription, SIGNAL(textChanged()), this, SLOT(eventDescriptionChanged()));
190 connect(ui->btnLock, SIGNAL(toggled(bool)), this, SLOT(setLockStatus(bool)));
191 connect(ui->tableInput,
192 SIGNAL(typeChanged(int, QString)),
193 this,
194 SLOT(updateLinkHint(int, QString)));
195 connect(ui->tableLocal,
196 SIGNAL(typeChanged(int, QString)),
197 this,
198 SLOT(updateLinkHint(int, QString)));
199 connect(ui->tableOutput,
200 SIGNAL(typeChanged(int, QString)),
201 this,
202 SLOT(updateLinkHint(int, QString)));
203
204 ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!readOnly);
205
206
207 if (locked)
208 {
209 setLockStatus(false);
210 }
211
212 if (readOnly || !locked)
213 {
214 ui->btnLock->hide();
215 }
216
217 QRect rec = QApplication::desktop()->screenGeometry();
218 this->resize(rec.width() * 0.9, this->height());
219
220 updateLinkHint(0, 0);
221 }
222
224 {
225 delete ui;
226 }
227
230 {
232
233 if (stateInstance && (state = stateInstance->getStateClass()))
234 {
235 return getUpdatedParameters(state->getInputParameters(), *ui->tableInput);
236 }
237
238 throw new LocalException("Could not get state parameters; invalid state?");
240 }
241
244 {
246
247 if (stateInstance && (state = stateInstance->getStateClass()))
248 {
249 return getUpdatedParameters(state->getLocalParameters(), *ui->tableLocal);
250 }
251
252 throw new LocalException("Could not get state parameters; invalid state?");
254 }
255
258 {
260
261 if (stateInstance && (state = stateInstance->getStateClass()))
262 {
263 return getUpdatedParameters(state->getOutputParameters(), *ui->tableOutput);
264 }
265
266 throw new LocalException("Could not get state parameters; invalid state?");
268 }
269
270 QString
272 {
273 return ui->editInstanceName->text();
274 }
275
276 QString
278 {
279 return ui->editStateName->text();
280 }
281
282 QString
284 {
285 return ui->editProxyName->text();
286 }
287
288 QString
290 {
291 return ui->stateDocuEditor->toPlainText();
292 }
293
296 {
298
299 for (int i = 0; i < ui->cbOutgoingEvents->count(); ++i)
300 {
302 event->name = ui->cbOutgoingEvents->itemText(i);
303 event->description = eventDescriptionMap[event->name];
304 eventList.append(event);
305 }
306
307 return eventList;
308 }
309
310 void
311 StateDialog::eventNameComboboxChanged(const QString& eventName)
312 {
313 ui->editEventDescription->setEnabled(true);
314 ui->editEventDescription->setPlainText(eventDescriptionMap[eventName]);
315 ui->btnDeleteEvent->setEnabled(true);
316 }
317
318 void
319 StateDialog::eventButtonAdd()
320 {
321 RegExpValidatedInputDialog d(
322 "New Event Name", "Event name", QRegExp("^([a-zA-Z_]{1})([a-zA-Z_0-9]+)$"), this);
323
324 if (d.exec() == QDialog::Accepted)
325 {
326 auto eventName = d.getTextValue();
327 if (!eventName.isEmpty())
328 {
329 ui->cbOutgoingEvents->addItem(eventName);
330 }
331 // No need to create entry in event description map (automatically done by operator[] on access)
332 }
333 }
334
335 void
336 StateDialog::eventButtonDelete()
337 {
338 if (ui->cbOutgoingEvents->currentText() != "Failure")
339 {
340 ui->cbOutgoingEvents->removeItem(ui->cbOutgoingEvents->currentIndex());
341 }
342 else
343 {
344 QMessageBox::warning(0,
345 "Deletion failed",
346 "You cannot delete the failure event. This event is needed to "
347 "handle internal statechart failures.");
348 }
349 }
350
351 void
352 StateDialog::eventDescriptionChanged()
353 {
354 eventDescriptionMap[ui->cbOutgoingEvents->currentText()] =
355 ui->editEventDescription->toPlainText();
356 }
357
358 void
359 StateDialog::loadLibrary()
360 {
361 ARMARX_INFO_S << "loading libs";
362 QStringList files = fileDialog->selectedFiles();
363 foreach (QString file, files)
364 {
365 ARMARX_INFO_S << "loading " << file.toStdString();
366
367 if (Libraries.find(file) != Libraries.end())
368 {
369 continue;
370 }
371
372 DynamicLibraryPtr lib(new DynamicLibrary());
373 lib->load(file.toStdString());
374 Libraries[file] = lib;
375 }
377 ui->tableInput->refreshVariantTypes();
378 ui->tableLocal->refreshVariantTypes();
379 ui->tableOutput->refreshVariantTypes();
380 }
381
382 void
383 StateDialog::setBlackLists()
384 {
385 ui->tableInput->setKeyBlackList(ui->tableLocal->getKeys());
386 ui->tableLocal->setKeyBlackList(ui->tableInput->getKeys());
387 }
388
389 void
390 StateDialog::setLockStatus(bool unlock)
391 {
392 if (unlock && tipDialog)
393 {
394 tipDialog->setModal(true);
395 tipDialog->showMessage(
396 "You are unlocking the editing of the state class. Editing a state class will "
397 "change all occurrences of this state and not only this instance. To use custom "
398 "parameters for this instance use the transition mapping.",
399 "State class unlocking");
400 tipDialog->resize(500, 150);
401 tipDialog->activateWindow();
402 tipDialog->raise();
403 }
404
405 ui->tableInput->setEnabled(unlock);
406 ui->tableOutput->setEnabled(unlock);
407 ui->tableLocal->setEnabled(unlock);
408 ui->cbOutgoingEvents->setEnabled(unlock);
409 ui->stateDocuEditor->setEnabled(unlock);
410 ui->editEventDescription->setEnabled(unlock);
411 }
412
413 void
414 StateDialog::updateLinkHint(int, QString)
415 {
416 if (!variantInfo)
417 {
418 return;
419 }
420
421 QSet<QString> vars;
422 vars.unite(ui->tableInput->getTypes())
423 .unite(ui->tableLocal->getTypes())
424 .unite(ui->tableOutput->getTypes());
425 Ice::StringSeq types;
426 for (auto& var : vars)
427 {
428 auto type = VariantContainerType::GetInnerType(var.toStdString());
429 if (!type.empty())
430 {
431 types.push_back(type);
432 }
433 }
434 QStringList libs;
435 for (std::string& lib : variantInfo->findLibNames(types))
436 {
437 libs << QString::fromStdString(lib);
438 }
439 ui->editDependencies->setText(libs.join(" "));
440 }
441
443 StateDialog::getUpdatedParameters(const statechartmodel::StateParameterMap& source,
444 const StatechartEditorParameterEditor& parameterEditor) const
445 {
446 statechartmodel::StateParameterMap newValues = parameterEditor.getStateParameters();
447
448 QSet<QString> profiles;
449 StatechartProfilePtr p = currentProfile;
450
451 while (p)
452 {
453 profiles.insert(QString::fromUtf8(p->getName().data()));
454 p = p->getParent();
455 }
456
457 for (const auto& oldParamEntry : source.toStdMap())
458 {
459 QString key = oldParamEntry.first;
460
461 // copy default values for other profiles if the parameter still exists && the type is unchanged:
462 if (newValues.contains(key) && newValues[key]->type == oldParamEntry.second->type)
463 {
464 for (const auto& pdvEntry : oldParamEntry.second->profileDefaultValues.toStdMap())
465 {
466 if (!profiles.contains(pdvEntry.first))
467 {
468 newValues[key]->profileDefaultValues.insert(pdvEntry.first,
469 pdvEntry.second);
470 }
471 }
472 }
473 }
474
475 return newValues;
476 }
477
478 void
480 {
481 if (readOnly && tipDialog)
482 {
483
484 tipDialog->showMessage("This state is read-only. Thus, changes cannot be saved.",
485 "Read-only state");
486 tipDialog->raise();
487 tipDialog->activateWindow();
488 tipDialog->exec();
489 }
490 }
491} // namespace armarx
static std::string getHomePath()
static void RegisterKnownObjectFactoriesWithIce(const Ice::CommunicatorPtr &ic)
Registers all object factories that are known with Ice.
QString getProxyName() const
statechartmodel::StateParameterMap getLocalParams() const
QString getStateInstanceName() const
QString getStateName() const
statechartmodel::StateParameterMap getOutputParams() const
StateDialog(statechartmodel::StateInstancePtr stateInstance, Ice::CommunicatorPtr communicator, VariantInfoPtr variantInfo, StatechartProfilePtr currentProfile, bool locked, bool readOnly, QPointer< TipDialog > tipDialog, QWidget *parent=0)
void showEvent(QShowEvent *) override
QString getDescription() const
statechartmodel::EventList getOutgoingEvents() const
statechartmodel::StateParameterMap getInputParams() const
static std::string GetInnerType(const std::string &typeStr)
#define ARMARX_INFO_S
Definition Logging.h:202
::IceInternal::Handle<::Ice::Communicator > CommunicatorPtr
Definition IceManager.h:49
ArmarX Headers.
std::shared_ptr< State > StatePtr
Definition State.h:48
QMap< QString, StateParameterPtr > StateParameterMap
std::shared_ptr< StateInstance > StateInstancePtr
std::shared_ptr< Event > EventPtr
Definition XmlWriter.h:46
QList< EventPtr > EventList
Definition XmlWriter.h:47
std::shared_ptr< RemoteState > RemoteStatePtr
Definition RemoteState.h:47
std::shared_ptr< EndState > EndStatePtr
Definition EndState.h:45
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::shared_ptr< VariantInfo > VariantInfoPtr
Definition VariantInfo.h:39
std::shared_ptr< class StatechartProfile > StatechartProfilePtr
std::shared_ptr< DynamicLibrary > DynamicLibraryPtr
Vertex source(const detail::edge_base< Directed, Vertex > &e, const PCG &)