EventSenderConfig.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* ArmarX is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License version 2 as
6* published by the Free Software Foundation.
7*
8* ArmarX is distributed in the hope that it will be useful, but
9* WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>.
15*
16* @package ArmarX::GuiComponent::EventSender
17* @author Mirko Waechter
18* @copyright 2012 Mirko Waechter
19* @license http://www.gnu.org/licenses/gpl-2.0.txt
20* GNU General Public License
21*/
22
23#include "EventSenderConfig.h"
24
25#include <ArmarXGui/gui-plugins/StatechartEventSenderPlugin/ui_EventSenderConfig.h>
26
28
29
30// ArmarX
37
39
40//Ice
41#include <IceUtil/IceUtil.h>
42
43// Qt headers
44#include <QComboBox>
45#include <QFile>
46#include <QFileDialog>
47#include <QMessageBox>
48#include <QPushButton>
49#include <QScrollArea>
50#include <QTableWidget>
51#include <QTableWidgetItem>
52#include <QTreeView>
53#include <QValidator>
54#include <Qt>
55#include <QtGlobal>
56
57// System
58#include <cmath>
59#include <cstdio>
60#include <cstdlib>
61#include <cstring>
62#include <iostream>
63#include <string>
64
65
66using namespace armarx;
67
69{
70 event = new Event(EVENTTOALL, "dummyEvent");
71}
72
73void
75{
76 settings->setValue("eventSenderName", eventSenderName);
77 settings->setValue("description", description);
78 settings->setValue("componentName", componentName);
79 settings->setValue("globalStateIdentifier", globalStateIdentifier.c_str());
80
81 if (event)
82 {
83 settings->setValue("eventName", event->eventName.c_str());
84 settings->setValue("eventReceiverName", event->eventReceiverName.c_str());
85 settings->beginWriteArray("parameters");
86 StringVariantContainerBaseMap::const_iterator it = event->properties.begin();
87 int i = 0;
88
89 for (; it != event->properties.end(); ++it, i++)
90 {
91 SingleVariantPtr sVar = SingleVariantPtr::dynamicCast(it->second);
92 settings->setArrayIndex(i);
93 settings->setValue("key", it->first.c_str());
94 settings->setValue("VariantTypeId", sVar->get()->getType());
95 settings->setValue("value", sVar->get()->getOutputValueOnly().c_str());
96 }
97
98 settings->endArray();
99 }
100}
101
102void
104{
105 eventSenderName = settings->value("eventSenderName").toString();
106 description = settings->value("description").toString();
107 componentName = settings->value("componentName").toString();
108 event = new Event(settings->value("eventReceiverName").toString().toStdString(),
109 settings->value("eventName").toString().toStdString());
110 globalStateIdentifier = settings->value("globalStateIdentifier").toString().toStdString();
111 int size = settings->beginReadArray("parameters");
112
113 for (int i = 0; i < size; ++i)
114 {
115 settings->setArrayIndex(i);
116 SingleVariantPtr sVar = new SingleVariant();
117 VariantPtr var = new Variant();
118 var->setType(settings->value("VariantTypeId").toInt());
119 QVariant data = settings->value("value");
120 VariantTypeId type = var->getType();
121
122 if (type == VariantType::String)
123 {
124 var->setString(data.toString().toStdString());
125 }
126 else if (type == VariantType::Int)
127 {
128 var->setInt(data.toInt());
129 }
130 else if (type == VariantType::Long)
131 {
132 var->setLong(data.toLongLong());
133 }
134 else if (type == VariantType::Float)
135 {
136 var->setFloat(data.toFloat());
137 }
138 else if (type == VariantType::Double)
139 {
140 var->setDouble(data.toDouble());
141 }
142 else if (type == VariantType::Bool)
143 {
144 var->setBool(data.toBool());
145 }
146 else
147 {
149 }
150
151 sVar->setVariant(var);
152 std::string key = settings->value("key").toString().toStdString();
153 event->properties[key] = sVar;
154 ARMARX_VERBOSE_S << "Reading parameter " << key << ": " << *sVar->get() << flush;
155 }
156
157 settings->endArray();
158}
159
162{
163 ui->setupUi(this);
164 setupUi();
165}
166
168{
169 delete ui;
170 // ARMARX_INFO << "~EventSenderConfigDialog" << flush;
171}
172
173void
175{
176 switch (index)
177 {
178 default:
179 //cases not defined yet
180 break;
181 }
182}
183
184void
186{
187 throw NotImplementedYetException("Sending event");
188 // QModelIndex index = treeBox->view()->currentIndex();
189 // if(treeBox->model()->itemData(index)[STATE_ITEM_TYPE] != StateItemModel::eInstanceStateItem){
190 // ARMARX_INFO << "You cannot send an event to this type of state! You can only send events to 'Requested Instances'." << flush;
191 // return;
192 // }
193
194 // QVariant varStateId =getSelectedState();
195 // QVariant varComponentName =getSelectedComponentName();
196 // ARMARX_INFO << "event receiver: " << varComponentName.toString().toStdString() << ":" << varStateId.toString().toStdString() << flush;
197 // RemoteStateOffererInterfacePrx statePrx;
198 // EventPtr event = getSelectedEvent();
199 // if(!event)
200 // return;
201 // statePrx = getProxy<RemoteStateOffererInterfacePrx>(varComponentName.toString().toStdString());
202 // if(!statePrx){
203 // ARMARX_WARNING << "Proxy is NULL" << flush;
204 // return;
205 // }
206
207 // statePrx->begin_issueEventWithGlobalIdStr(varStateId.toString().toStdString(), event);
208 // ARMARX_INFO << "sent event " << event->eventName << " to " << varComponentName.toString().toStdString() << flush;
209 // ARMARX_INFO << "event parameter count: " << event->properties.size() << flush;
210}
211
214{
215 QString currentEventString = ui->CBEvent->currentText();
216 EventPtr event = new Event(EVENTTOALL, currentEventString.toStdString());
217 event->properties = ui->paramEditor->getStringValueMap();
218 // for(int row=0; row < ui->paramEditor->rowCount(); ++row)
219 // {
220
221
222 // if(!ui->paramEditor->item(row,0)){
223 // ArmarXWidgetController::showMessageBox("Please enter a key for the parameter with id #" + QString::number(row+1));
224 // return NULL;
225 // }
226 // std::string key = ui->paramEditor->item(row,0)->text().toStdString();
227 // QComboBox* CBvalueType = qobject_cast<QComboBox*>(ui->paramEditor->cellWidget(row,1));
228
229 // if(!CBvalueType){
230 // ARMARX_WARNING << "CBvalueType pointer is NULL" << flush;
231 // continue;
232 // }
233 // int type = CBvalueType->itemData(CBvalueType->currentIndex()).toInt();
234 // QLineEdit* valueEdit = qobject_cast<QLineEdit*>(ui->paramEditor->cellWidget(row,2));
235
236 // if( type == VariantType::Int)
237 // event->add(key, valueEdit->text().toInt());
238
239 // else if( type == VariantType::Bool)
240 // if(valueEdit->text() == "true" || valueEdit->text() == "1")
241 // event->add(key, Variant(true));
242 // else
243 // event->add(key, Variant(false));
244
245 // else if( type == VariantType::Float)
246 // event->add(key, valueEdit->text().toFloat());
247
248 // else if( type == VariantType::String)
249 // event->add(key, valueEdit->text().toStdString());
250
251 //// else if( type == VariantType::DataFieldIdentifier)
252 //// {
253 //// DataFieldIdentifierBasePtr id = new DataFieldIdentifier(valueEdit->text().toStdString());
254 //// event->add(key, id);
255
256 //// }
257 //// else if( eLinkedPosition:
258 //// {
259 //// LinkedPosition pos(valueEdit->text().toStdString());
260 //// event->add(key, id);
261 //// break;
262 //// }
263 // else
264 // ARMARX_WARNING << "Datatype not implemented yet!" << flush;
265
266 // }
267
268
269 return event;
270}
271
272void
274{
275 // EventSenderConfig config;
276 // // set test data
277 // config.componentName = "RobotStatechart";
278 // config.globalStateIdentifier = "RobotStatechart->RobotControl->Functional";
279 // config.event = new Event(EVENTTOALL, "EvLoadScenario");
280 // config.event->add("test", std::string("Visual"));
281
282 ui->edtEventSenderName->setText(config.eventSenderName);
283 ui->edtDescription->setText(config.description);
284
285 if (iceManager)
286 {
288 }
289
290 ui->edtSelectedState->setText(config.globalStateIdentifier.c_str());
291 QModelIndex index =
292 getRowOfItem(model, "", STATE_GLOBALSTATEID, QString(config.globalStateIdentifier.c_str()));
293
294 if (index.isValid())
295 {
296 // we need to set the current index this way because QComboBox does
297 // not work well with hierarchical states
298 QModelIndex oldIndex = treeBox->rootModelIndex();
299 treeBox->setRootModelIndex(index.parent());
300 treeBox->setCurrentIndex(index.row());
301 treeBox->setRootModelIndex(oldIndex);
302 treeBox->view()->setCurrentIndex(index);
303
304 stateSelected(-1); // update event list
305 }
306
307 ui->CBEvent->setCurrentIndex(
308 ui->CBEvent->findText(config.event->eventName.c_str())); // set correct event as selected
309
310 // set parameters
311
312 ui->paramEditor->setRowCount(0);
313 StringVariantContainerBaseMap::const_iterator it = config.event->properties.begin();
314
315 for (; it != config.event->properties.end(); ++it)
316 {
317 SingleVariantPtr sVar = SingleVariantPtr::dynamicCast(it->second);
318 ui->paramEditor->addParameterRow(
319 it->first.c_str(),
320 QString::fromStdString(
321 VariantContainerType::allTypesToString(sVar->getContainerType())),
322 sVar->get()->getOutputValueOnly().c_str());
323 }
324}
325
326const QModelIndex
328 QString searchString,
329 int userDataRole,
330 QVariant userData) const
331{
332 QStandardItem* item = model->invisibleRootItem();
333 return getRowOfItem(item, searchString, userDataRole, userData);
334}
335
336const QModelIndex
338 QString searchString,
339 int userDataRole,
340 QVariant userData) const
341{
342 if (userDataRole == 0 && searchString.length() == 0)
343 {
344 throw LocalException("Either searchString or userDataRole must be given!");
345 }
346
347 int i = -1;
348 QStandardItem* child;
349
350 while (i++, child = item->child(i), child != NULL)
351 {
352 if (child->text() ==
353 ARMARXGUI_BASEINSTANCE_STR) // base instances are no valid event receivers
354 {
355 continue;
356 }
357
358 if ((searchString.length() == 0 || child->text() == searchString) &&
359 (userDataRole == 0 || child->data(userDataRole) == userData))
360 {
361 return child->index();
362 }
363
364 QModelIndex result = getRowOfItem(child, searchString, userDataRole, userData);
365
366 if (result.isValid())
367 {
368 return result;
369 }
370 }
371
372 return QModelIndex();
373}
374
375void
377{
378 this->iceManager = iceManager;
379
380 if (iceManager)
381 {
382 ui->paramEditor->setCommunicator(iceManager->getCommunicator());
383 }
384}
385
386QStringList
388{
389 QStringList events;
390
391 for (unsigned int i = 0; i < state->transitions.size(); i++)
392 {
393 TransitionIceBase& t = state->transitions[i];
394
395 if (!events.contains(QString(t.evt->eventName.c_str())))
396 {
397 events.push_back(QString(t.evt->eventName.c_str()));
398 }
399 }
400
401 return events;
402}
403
404void
405EventSenderConfigDialog::setEventSender(QString first, QString second)
406{
407 QSettings settings(first, second);
408 //ui->eventString->setText(settings.value("LineEdit").toString());
409 // for(int i = 0; i < settings.beginReadArray("ComboBox"); i++)
410 // {
411 // ui->eventComboBox->setItemText(i,settings.value("Event").toString());
412 // }
413 settings.endArray();
414 int rows = settings.beginReadArray("TableWidget");
415 ui->paramEditor->setRowCount(rows);
416
417 for (int i = 0; i < rows; i++)
418 {
419 settings.setArrayIndex(i);
420 int columns = settings.beginReadArray("Column");
421 ui->paramEditor->setColumnCount(columns);
422
423 for (int j = 0; j < columns; j++)
424 {
425 settings.setArrayIndex(j);
426
427 if (j == 0)
428 {
429 ui->paramEditor->item(i, j)->setText(settings.value("Cell").toString());
430 }
431
432 if (j == 1)
433 {
434 QComboBox* tempBox = new QComboBox;
435 int comboLength = settings.beginReadArray("ComboBox");
436
437 for (int index = 0; index < comboLength; index++)
438 {
439 QString cell;
440 cell.setNum(index);
441 tempBox->insertItem(index, settings.value(cell).toString());
442 }
443
444 ui->paramEditor->setCellWidget(i, j, tempBox);
445 // if(valueboxes.contains(tempBox->objectName()))
446 // {
447 // valueboxes.removeOne(tempBox->objectName);
448 // valueboxes.append(tempBox);
449 // }
450 settings.endArray();
451 }
452
453 if (j == 2)
454 {
455 QLineEdit* tempEdit = new QLineEdit;
456 tempEdit->setText(settings.value("Cell").toString());
457 ui->paramEditor->setCellWidget(i, j, tempEdit);
458 }
459 }
460
461 settings.endArray();
462 }
463
464 settings.endArray();
465}
466
467void
469{
470 QSettings settings("armarx", "eventSender");
471 //settings.setValue("LineEdit", ui->eventString->text());
472 settings.beginWriteArray("ComboBox");
473 // for(int i = 0; i < ui->eventComboBox->count(); i++)
474 // {
475 // settings.setValue("Event", ui->eventComboBox->itemText(i));
476 // }
477 settings.endArray();
478 settings.beginWriteArray("TableWidget");
479
480 for (int i = 0; i < ui->paramEditor->rowCount(); i++)
481 {
482 settings.setArrayIndex(i);
483 settings.beginWriteArray("Column");
484
485 for (int j = 0; j < ui->paramEditor->columnCount(); j++)
486 {
487 settings.setArrayIndex(j);
488
489 if (j == 0)
490 {
491 settings.setValue("Cell", ui->paramEditor->item(i, j)->text());
492 }
493
494 if (j == 1)
495 {
496 QComboBox* tempBox = qobject_cast<QComboBox*>(ui->paramEditor->cellWidget(i, j));
497 settings.beginWriteArray("ComboBox");
498
499 for (int index = 0; index < tempBox->count(); index++)
500 {
501 settings.setArrayIndex(index);
502 QString cell;
503 cell.setNum(index);
504 settings.setValue(cell, tempBox->itemText(index));
505 }
506
507 settings.endArray();
508 }
509
510 if (j == 2)
511 {
512 QLineEdit* tempEdit = qobject_cast<QLineEdit*>(ui->paramEditor->cellWidget(i, j));
513 settings.setValue("Cell", tempEdit->text());
514 }
515 }
516
517 settings.endArray();
518 }
519
520 settings.endArray();
521}
522
523void
525{
526 ARMARX_VERBOSE << "Updating State tree" << flush;
527 std::vector<StateIceBasePtr> baseStateList;
528 std::vector<StateIceBasePtr> instanceStateList;
529 std::string stateSearchMask = ui->edtStateSearchMask->text().toStdString();
530 std::vector<std::string> remoteStateOffererList =
531 iceManager->getIceGridSession()->getRegisteredObjectNames<RemoteStateOffererInterfacePrx>(
532 stateSearchMask);
533 // RemoteStateOffererInterface::ice_staticId()
534 QStringList componentNames; // = ui->EDTComponentName->text().split(';');
535
536 for (unsigned int i = 0; i < remoteStateOffererList.size(); ++i)
537 {
538 componentNames << QString::fromStdString(remoteStateOffererList.at(i));
539 }
540
541 if (componentNames.size() == 0)
542 {
543 ARMARX_INFO << "No RemoteStateOfferer found.";
544 return;
545 }
546
547 foreach (QString componentNameQStr, componentNames)
548 {
549 std::string componentName = componentNameQStr.trimmed().toStdString();
550
551 try
552 {
553 getTopLevelStates(componentName, baseStateList, instanceStateList);
554 model->updateModel(componentName, baseStateList, instanceStateList);
555 }
556 catch (Ice::NotRegisteredException& e)
557 {
558 ARMARX_WARNING << "The entered component with name '" << componentName
559 << "' was not found - maybe you forgot to start it?" << flush;
560 }
561 catch (IceUtil::NullHandleException& e)
562 {
563 ARMARX_ERROR << "IceUtil::NullHandleException: " << e.what()
564 << "\nFile: " << e.ice_file() << e.ice_line() << "\nBacktrace:\n"
565 << e.ice_stackTrace() << flush;
566 }
567 catch (armarx::UserException& e)
568 {
569 ARMARX_WARNING << "Found component but cannot communicate with component - probably it "
570 "is a component of another type\nreason: "
571 << e.reason << flush;
572 }
573 }
574}
575
576void
578 std::vector<StateIceBasePtr>& baseStateList,
579 std::vector<StateIceBasePtr>& instanceStateList)
580{
581 RemoteStateOffererInterfacePrx statePrx;
582 statePrx = iceManager->getProxy<armarx::RemoteStateOffererInterfacePrx>(componentName);
583
584 if (!statePrx)
585 {
586 ARMARX_WARNING << "Proxy is NULL" << flush;
587 return;
588 }
589
590 Ice::StringSeq availableStates = statePrx->getAvailableStates();
591 baseStateList.clear();
592
593 for (unsigned int i = 0; i < availableStates.size(); ++i)
594 {
595 baseStateList.push_back(statePrx->getStatechart(availableStates[i]));
596 }
597
598 StateIdNameMap availableStateInstances = statePrx->getAvailableStateInstances();
599 instanceStateList.clear();
600 StateIdNameMap::iterator it = availableStateInstances.begin();
601
602 for (; it != availableStateInstances.end(); ++it)
603 {
604 instanceStateList.push_back(statePrx->getStatechartInstance(it->first));
605 }
606}
607
608void
610{
611 //send event
612 QModelIndex modelIndex = treeBox->view()->currentIndex();
613 // ARMARX_LOG << "row : " << modelIndex.row() << flush;
614 std::string globalStateId =
615 treeBox->model()->itemData(modelIndex)[STATE_GLOBALSTATEID].toString().toStdString();
616 std::string componentName =
617 treeBox->model()->itemData(modelIndex)[STATE_COMPONENT_NAME].toString().toStdString();
618
619 // ARMARX_WARNING<< "State selection changed to "<< globalStateId << flush;
620 if (treeBox->model()->itemData(modelIndex)[STATE_ITEM_TYPE] !=
622 {
623 ui->CBEvent->clear();
624 ui->edtSelectedState->setText("");
625 return;
626 }
627
628 StateIceBasePtr statePtr = model->getState(componentName, globalStateId);
629
630 if (!statePtr)
631 {
632 ARMARX_WARNING << "Could not find state with id " << globalStateId << " of component '"
633 << componentName << "'" << flush;
634 return;
635 }
636
637 ui->edtSelectedState->setText(globalStateId.c_str());
638 ui->CBEvent->clear();
639 QStringList eventList = getPossibleEvents(statePtr);
640 ui->CBEvent->addItems(eventList);
641}
642
643void
645{
646 QObject::connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
647 QObject::connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
648
649 model = new StateItemModel();
650 treeBox = new TreeBox(model, true, this);
651 ui->gridLayout->addWidget(treeBox, 3, 4, 1, 1);
652 ui->paramEditor->setColumnHidden(StateParameterEditor::eOptional, true);
653 ui->paramEditor->setColumnHidden(StateParameterEditor::eProvideDefaultValue, true);
654 ui->paramEditor->setDefaultValueState(Qt::Checked);
655 // ui->paramEditor = new StateParameterEditor(ui->groupBox);
656 // ui->verticalLayout->addWidget(ui->paramEditor);
657
658 // addParameterRow();
659 // addParameterRow();
660 // if(ui->paramEditor->rowCount() < 2)
661 // return;
662 // if(!ui->paramEditor->item(0,0))
663 // return;
664 // ui->paramEditor->item(0,0)->setText("proxyName");
665 // ui->paramEditor->item(1,0)->setText("stateName");
666 // qobject_cast<QLineEdit*>(ui->paramEditor->cellWidget(0,2))->setText("VisualServoingExample");
667 // qobject_cast<QLineEdit*>(ui->paramEditor->cellWidget(1,2))->setText("VisualServoingExample");
668
669 // QComboBox* cbox = qobject_cast<QComboBox*>(ui->paramEditor->cellWidget(0, 1));
670 // cbox->setCurrentIndex(8);
671 // cbox = qobject_cast<QComboBox*>(ui->paramEditor->cellWidget(1, 1));
672 // cbox->setCurrentIndex(8);
673
674
675 // setup eventsender slots
676 connect(ui->addRowButton, SIGNAL(clicked()), ui->paramEditor, SLOT(addParameterRow()));
677 connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(send()));
678
679 connect(ui->actionSaveAs, SIGNAL(triggered()), this, SLOT(saveEventSender()));
680 connect(ui->BTNUpdateTreeView, SIGNAL(clicked()), this, SLOT(populateStateTreeList()));
681 connect(treeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(stateSelected(int)));
682 ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
684}
685
686QString
688{
689 QModelIndex index = treeBox->view()->currentIndex();
690 return treeBox->model()->itemData(index)[STATE_COMPONENT_NAME].toString();
691}
692
693QString
695{
696 QModelIndex index = treeBox->view()->currentIndex();
697 return treeBox->model()->itemData(index)[STATE_GLOBALSTATEID].toString();
698}
uint8_t index
#define EVENTTOALL
Definition StateBase.h:42
#define ARMARXGUI_BASEINSTANCE_STR
#define STATE_GLOBALSTATEID
#define STATE_COMPONENT_NAME
#define STATE_ITEM_TYPE
void setIceManager(IceManagerPtr iceManager)
Ui::EventSenderConfigDialog * ui
QStringList getPossibleEvents(StateIceBasePtr state)
void getTopLevelStates(std::string componentName, std::vector< StateIceBasePtr > &baseStateList, std::vector< StateIceBasePtr > &instanceStateList)
const QModelIndex getRowOfItem(QStandardItemModel *model, QString searchString, int userDataRole=0, QVariant userData=QVariant()) const
void setEventSender(QString first, QString second)
void setConfig(const EventSenderConfig &config)
An Event is used to communicate between e.g.
Definition Event.h:51
The SingleVariant class is required to store single Variant instances in VariantContainer subclasses.
static std::string allTypesToString(const ContainerTypePtr &type)
The Variant class is described here: Variants.
Definition Variant.h:224
Throw this exception to indicate missing functionality.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_VERBOSE_S
Definition Logging.h:207
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
ArmarX Headers.
const VariantTypeId String
Definition Variant.h:921
const VariantTypeId Int
Definition Variant.h:917
const VariantTypeId Long
Definition Variant.h:918
const VariantTypeId Bool
Definition Variant.h:916
const VariantTypeId Double
Definition Variant.h:920
const VariantTypeId Float
Definition Variant.h:919
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< SingleVariant > SingleVariantPtr
IceInternal::Handle< Variant > VariantPtr
Definition Variant.h:41
Ice::Int VariantTypeId
Definition Variant.h:43
const LogSender::manipulator flush
Definition LogSender.h:251
IceUtil::Handle< IceManager > IceManagerPtr
IceManager smart pointer.
Definition ArmarXFwd.h:39
IceInternal::Handle< Event > EventPtr
Typedef of EventPtr as IceInternal::Handle<Event> for convenience.
Definition Event.h:40
void saveSettings(QSettings *settings)
void loadSettings(QSettings *settings)