EditStatechartGroupDialog.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::
17 * @author Mirko Waechter ( mirko.waechter at kit dot edu)
18 * @date 2014
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22 
24 #include <ArmarXGui/gui-plugins/StatechartEditorPlugin/view/dialogs/ui_EditStatechartGroupDialog.h>
26 #include <QFileDialog>
27 #include <QTimer>
28 #include <QtGui>
29 #include <QToolTip>
30 
31 #include <filesystem>
32 
34 
36 
38 
40 
41 
42 
43 namespace armarx
44 {
45 
47  VariantInfoPtr variantInfo, QList<QString> selectedProxies, bool generateContext,
48  const StatechartProfilesPtr& statechartProfiles, const QMap<QString, QString>& statechartGroupConfigurations,
49  const QString& description, StatechartGroupPtr group, QWidget* parent) :
50  QDialog(parent),
52  packageTool(packageTool),
53  editMode(editMode),
54  statechartProfiles(statechartProfiles),
55  configurations(statechartGroupConfigurations),
56  variantInfo(variantInfo),
57  group(group)
58  {
59  ui->setupUi(this);
60  ui->btnShowPackageError->setVisible(false);
61 
62  ui->checkBoxGenerateContext->setChecked(generateContext);
63  updateProxyListEnabled(ui->checkBoxGenerateContext->checkState());
64  connect(ui->checkBoxGenerateContext, SIGNAL(stateChanged(int)), this, SLOT(updateProxyListEnabled(int)));
65 
66  if (editMode == NewGroup)
67  {
68  setWindowTitle("Create new Statechart Group");
69  QRegExp rx("([a-zA-Z][a-zA-Z0-9]*)");
70  ui->editStatechartGroup->setValidator(new QRegExpValidator(rx, this));
71 
72  connect(ui->btnSelectPackageFolder, SIGNAL(clicked()), this, SLOT(selectPackagePath()));
73  connect(ui->editPackagePath, SIGNAL(textChanged(QString)), this, SLOT(requestCheckPackagePath(QString)));
74  connect(ui->editStatechartGroup, SIGNAL(textChanged(QString)), this, SLOT(requestCheckPackagePath(QString)));
75 
76  timer = new QTimer(this);
77  connect(timer, SIGNAL(timeout()), this, SLOT(checkPackagePath()));
78  timer->setSingleShot(true);
79 
80  // disable ok button until everything is valid
81  ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
82  ui->tabWidget->setCurrentIndex(0);
83  }
84  else if (editMode == EditGroup)
85  {
86  setWindowTitle(groupName + " - Properties");
87  ui->editStatechartGroup->setText(groupName);
88  ui->textEditGroupDescription->setPlainText(description);
89  ui->editPackagePath->setEnabled(false);
90  ui->editStatechartGroup->setEnabled(false);
91  ui->btnSelectPackageFolder->setEnabled(false);
92 
93  ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
94  }
95  else
96  {
97  throw LocalException("Not supported enum value.");
98  }
99 
100  QStringList properties;
101  QStandardItemModel* model = new QStandardItemModel(ui->listProxies);
102  // Populate proxy/topic list
103  for (VariantInfo::LibEntryPtr lib : variantInfo->getLibs())
104  {
105  QString libName = QString::fromUtf8(lib->getName().c_str());
106 
107  for (VariantInfo::ProxyEntryPtr proxy : lib->getProxies())
108  {
109  //QString proxyType = QString::fromUtf8(proxy->getProxyTypeAsString().c_str());
110  QString proxyHumanName = QString::fromUtf8(proxy->getHumanName().c_str());
111  QString proxyMemberName = QString::fromUtf8(proxy->getMemberName().c_str());
112  QString display = QString("[%1] %3").arg(libName, proxyHumanName);
113  QStandardItem* listItem = new QStandardItem(display);
114  QString proxyId = QString("%1.%2").arg(libName, proxyMemberName);
115  listItem->setData(proxyId, Qt::UserRole);
116  listItem->setCheckable(true);
117  listItem->setEditable(false);
118  listItem->setCheckState(selectedProxies.contains(proxyId) ? Qt::Checked : Qt::Unchecked);
119  model->appendRow(listItem);
120  }
121  }
122  InfixFilterModel* filterModel = new InfixFilterModel(ui->listProxies);
123  filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
124  filterModel->setSourceModel(model);
125  ui->listProxies->setModel(filterModel);
126  connect(ui->lineEditProxyFilter, SIGNAL(textChanged(QString)), filterModel, SLOT(setFilterFixedString(QString)));
127 
128 
129  std::list<StatechartProfilePtr> profileQueue;
130  profileQueue.push_back(statechartProfiles->getRootProfile());
131  connect(ui->comboBoxStatechartProfiles, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateConfigurationTextField(QString)));
132  connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateConfigurationContent(int)));
133  while (!profileQueue.empty())
134  {
135  StatechartProfilePtr currentProfile = profileQueue.front();
136  profileQueue.pop_front();
137  ui->comboBoxStatechartProfiles->addItem(QString(currentProfile->getNesting(), '-') + " " + QString::fromStdString(currentProfile->getName()),
138  QString::fromStdString(currentProfile->getName()));
139  for (auto it = currentProfile->getChildren().rbegin(); it != currentProfile->getChildren().rend(); it++)
140  {
141  profileQueue.push_front(*it);
142  }
143  if (profileQueue.size() == 0)
144  {
145  break;
146  }
147  if (configurations[QString::fromStdString(currentProfile->getName())].isEmpty())
148  {
149  configurations[QString::fromStdString(currentProfile->getName())] = properties.join("\n");
150  }
151  }
152  connect(ui->textEditParameters, SIGNAL(textChanged()), this, SLOT(storeConfigurationText()));
153  connect(ui->listProxies->model(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(updateDependencies(QModelIndex, QModelIndex)));
154 
156 
157  }
158 
160  {
161  delete ui;
162  }
163 
165  {
166  return packageTool;
167  }
168 
170  {
171  return ui->editStatechartGroup->text();
172  }
173 
175  {
176  // new behavior
177  {
178  CMakePackageFinder finder(getPackageName().toStdString());
179 
180  std::filesystem::path path = finder.getStatechartsDir();
181 
182  if(not path.empty())
183  {
184  path /= getGroupName().toUtf8().data();
185  return QString::fromStdString(path.string());
186  }
187  }
188 
189  // legacy behavior
190 
191  ARMARX_WARNING << "The package `" << getPackageName() << "` does not provide the STATECHARTS_DIR cmake variable!"
192  << "Using legacy path for now.";
193 
194  std::filesystem::path path = ui->editPackagePath->text().toUtf8().data();
195  path /= "source";
196  path /= getPackageName().toUtf8().data();
197  path /= "statecharts";
198  path /= getGroupName().toUtf8().data();
199 
200  return QString::fromUtf8(path.c_str());
201  }
202 
204  {
205  return ui->textEditGroupDescription->toPlainText();
206  }
207 
209  {
210  const std::filesystem::path packagePath = getPackagePath().toStdString();
211 
212  std::vector<std::string> packages = CMakePackageFinder::FindAllArmarXSourcePackages();
213  ARMARX_IMPORTANT << VAROUT(packages);
214  for (const std::string& package : packages)
215  {
216  CMakePackageFinder finder(package);
217  if (finder.getPackageDir() == packagePath)
218  {
219  return QString::fromStdString(package);
220  }
221  }
222  std::stringstream ss;
223  ss << "No CMake package found for path " << packagePath << ".";
224  throw LocalException(ss.str());
225 
226  // std::filesystem::path path = getPackagePath().toUtf8().data();
227  // return QString::fromUtf8(path.filename().c_str());
228  }
229 
231  {
232  std::filesystem::path path = ui->editPackagePath->text().toUtf8().data();
233  std::filesystem::path cleanPath = path;
234 
235  try
236  {
237  cleanPath = std::filesystem::canonical(path);
238  }
239  catch (...)
240  {
241  cleanPath = ArmarXDataPath::cleanPath(path.string());
242 
243  if (*cleanPath.string().rbegin() == '/' || *cleanPath.string().rbegin() == '\\')
244  {
245  cleanPath = cleanPath.remove_filename();
246  }
247  }
248 
249  return QString::fromUtf8(cleanPath.c_str());
250  }
251 
253  {
254  QList<QString> proxies;
255  QSortFilterProxyModel* proxy = qobject_cast<QSortFilterProxyModel*>(ui->listProxies->model());
256  QStandardItemModel* model = qobject_cast<QStandardItemModel*>(proxy->sourceModel());
257  for (int row = 0; row < model->rowCount(); row++)
258  {
259  auto item = model->item(row);
260  if (item && item->checkState() == Qt::Checked)
261  {
262  proxies.append(item->data(Qt::UserRole).toString());
263  }
264  }
265 
266  return proxies;
267  }
268 
270  {
271  return ui->checkBoxGenerateContext->isChecked();
272  }
273 
274  QMap<QString, QString> EditStatechartGroupDialog::getConfigurations() const
275  {
276  return configurations;
277  }
278 
280  {
281  timer->start(250);
282 
283  }
284 
286  {
287  QFileDialog selectFolder(this, "Select ArmarX Package Root Folder");
288  QList<QUrl> urls;
289  urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation))
290  << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation));
291 
293  {
294  urls << QUrl::fromLocalFile(QString::fromStdString(ArmarXDataPath::getHomePath()));
295  }
296 
297  selectFolder.setSidebarUrls(urls);
298  // selectFolder.setOption(QFileDialog::ShowDirsOnly, true);
299  selectFolder.setOption(QFileDialog::ReadOnly, true);
300  selectFolder.setOption(QFileDialog::HideNameFilterDetails, false);
301  selectFolder.setFileMode(QFileDialog::Directory);
302 
303  if (selectFolder.exec() == QDialog::Accepted)
304  {
305  ui->editPackagePath->setText(*selectFolder.selectedFiles().begin());
306 
307  }
308  }
309 
310 
312  {
313  std::string cmdOutput;
314  if (packageTool->checkPackagePath(ui->editPackagePath->text().toStdString(), cmdOutput))
315  {
316  ui->labelPackageError->setText("Package path is valid.");
317  QPalette p(ui->labelPackageError->palette());
318  p.setColor(ui->labelPackageError->backgroundRole(), QColor::fromRgb(120, 255, 120));
319  // p.setBrush(ui->labelPackageError->backgroundRole(), p.light());
320  ui->labelPackageError->setPalette(p);
321 
322  if (!ui->editStatechartGroup->text().isEmpty())
323  {
324  ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
325  }
326  else
327  {
328  ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
329  }
330  ui->labelPackageError->setToolTip("");
331  ui->btnShowPackageError->setVisible(false);
332  }
333  else
334  {
335  ui->labelPackageError->setText("Package path is not valid!");
336  ui->labelPackageError->setToolTip(QString::fromStdString(cmdOutput));
337  QPalette p(ui->labelPackageError->palette());
338  p.setColor(ui->labelPackageError->backgroundRole(), QColor::fromRgb(255, 120, 120));
339  ui->labelPackageError->setPalette(p);
340  ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
341  ui->btnShowPackageError->setVisible(true);
342 
343  }
344  }
345 
347  {
348  ui->listProxies->setEnabled(ui->checkBoxGenerateContext->isChecked());
349  }
350 
352  {
353  int i = ui->comboBoxStatechartProfiles->findText(profileText);
354  if (i < 0)
355  {
356  return;
357  }
358  auto profile = ui->comboBoxStatechartProfiles->itemData(i).toString();
359  ui->textEditParameters->setPlainText(configurations[profile]);
360  }
361 
363  {
364  int i = ui->comboBoxStatechartProfiles->currentIndex();
365  auto profile = ui->comboBoxStatechartProfiles->itemData(i).toString();
366  configurations[profile] = ui->textEditParameters->toPlainText();
367 
368  }
369 
371  {
372 
373 
374  }
375 
376  void EditStatechartGroupDialog::updateDependencies(QModelIndex index1, QModelIndex index2)
377  {
378  auto selectedProxies = getProxies();
379  QStringList libs;
380  for (VariantInfo::LibEntryPtr lib : variantInfo->getLibs())
381  {
382  QString libName = QString::fromUtf8(lib->getName().c_str());
383  for (VariantInfo::ProxyEntryPtr proxy : lib->getProxies())
384  {
385  QString proxyMemberName = QString::fromUtf8(proxy->getMemberName().c_str());
386  QString proxyId = QString("%1.%2").arg(libName, proxyMemberName);
387  if (selectedProxies.contains(proxyId))
388  {
389  if (!libs.contains(libName))
390  {
391  libs << (libName);
392  }
393 
394  }
395  }
396  }
397  if (group)
398  {
399  QSet<QString> vars;
400  Ice::StringSeq types;
401  for (statechartmodel::StatePtr state : group->getAllStates(true))
402  {
403  for (auto& param : state->getInputParameters())
404  {
405  vars.insert(param->type);
406  }
407  for (auto& param : state->getLocalParameters())
408  {
409  vars.insert(param->type);
410  }
411  for (auto& param : state->getOutputParameters())
412  {
413  vars.insert(param->type);
414  }
415  }
416  for (auto& var : vars)
417  {
418  auto type = VariantContainerType::GetInnerType(var.toStdString());
419  if (!type.empty())
420  {
421  types.push_back(type);
422  }
423  }
424  for (std::string& lib : variantInfo->findLibNames(types))
425  {
426  auto libName = QString::fromStdString(lib);
427  if (!libs.contains(libName))
428  {
429  libs << libName;
430  }
431  }
432 
433  }
434  ui->editDependencies->setText(libs.join(" "));
435 
436  }
437 }
438 
439 void armarx::EditStatechartGroupDialog::on_pushButton_clicked()
440 {
441  auto selectedProxies = getProxies();
442  auto groupName = getGroupName();
443  int i = ui->comboBoxStatechartProfiles->currentIndex();
444  if (i < 0)
445  {
446  return;
447  }
448  auto profileName = ui->comboBoxStatechartProfiles->itemData(i).toString();
449  for (VariantInfo::LibEntryPtr lib : variantInfo->getLibs())
450  {
451  QString libName = QString::fromUtf8(lib->getName().c_str());
452 
453  for (VariantInfo::ProxyEntryPtr proxy : lib->getProxies())
454  {
455  QString proxyMemberName = QString::fromUtf8(proxy->getMemberName().c_str());
456  QString proxyId = QString("%1.%2").arg(libName, proxyMemberName);
457  if (selectedProxies.contains(proxyId))
458  {
459  QString propName = QString("ArmarX.") + groupName + "RemoteStateOfferer." + QString::fromUtf8(proxy->getPropertyName().c_str());
460 
461  if (!configurations[profileName].contains(propName))
462  {
463  QString newProp;
464  if (!proxy->getPropertyIsOptional())
465  {
466  newProp += "# Required Property\n";
467  newProp += "#" + propName + " = <set value and uncomment!>\n";
468  }
469  else
470  {
471  newProp += "#" + propName + " = " + QString::fromUtf8(proxy->getPropertyDefaultValue().c_str()) + "\n";
472  }
473 
474  configurations[profileName] += "\n" + newProp;
475  }
476  }
477  }
478  }
479  updateConfigurationTextField(ui->comboBoxStatechartProfiles->currentText());
480 }
481 
482 void armarx::EditStatechartGroupDialog::on_btnShowPackageError_clicked()
483 {
484  QToolTip::showText(ui->btnShowPackageError->mapToGlobal(QPoint(10, 10)), ui->labelPackageError->toolTip());
485 }
armarx::EditStatechartGroupDialog::requestCheckPackagePath
void requestCheckPackagePath(QString path)
Definition: EditStatechartGroupDialog.cpp:279
armarx::EditStatechartGroupDialog::selectPackagePath
void selectPackagePath()
Definition: EditStatechartGroupDialog.cpp:285
armarx::EditStatechartGroupDialog::EditGroup
@ EditGroup
Definition: EditStatechartGroupDialog.h:49
armarx::EditStatechartGroupDialog::getProxies
QList< QString > getProxies() const
Definition: EditStatechartGroupDialog.cpp:252
armarx::EditStatechartGroupDialog::storeConfigurationText
void storeConfigurationText()
Definition: EditStatechartGroupDialog.cpp:362
armarx::EditStatechartGroupDialog::getPackagePath
QString getPackagePath() const
Definition: EditStatechartGroupDialog.cpp:230
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::ArmarXPackageToolInterfacePtr
std::shared_ptr< ArmarXPackageToolInterface > ArmarXPackageToolInterfacePtr
Definition: ArmarXPackageToolInterface.h:55
armarx::VariantContainerType::GetInnerType
static std::string GetInnerType(const std::string &typeStr)
Definition: VariantContainer.cpp:281
index
uint8_t index
Definition: EtherCATFrame.h:59
armarx::ArmarXDataPath::cleanPath
static std::string cleanPath(const std::string &filepathStr)
Definition: ArmarXDataPath.cpp:331
VariantContainer.h
armarx::CMakePackageFinder::FindAllArmarXSourcePackages
static std::vector< std::string > FindAllArmarXSourcePackages()
Definition: CMakePackageFinder.cpp:438
armarx::ArmarXDataPath::getHomePath
static std::string getHomePath()
Definition: ArmarXDataPath.cpp:583
armarx::EditStatechartGroupDialog::updateDependencies
void updateDependencies(QModelIndex index1=QModelIndex(), QModelIndex index2=QModelIndex())
Definition: EditStatechartGroupDialog.cpp:376
armarx::CMakePackageFinder
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
Definition: CMakePackageFinder.h:53
display
Use of this software is granted under one of the following two to be chosen freely by the user Boost Software License Version Marcin Kalicinski Permission is hereby free of to any person or organization obtaining a copy of the software and accompanying documentation covered by this display
Definition: license.txt:11
armarx::StatechartProfilePtr
std::shared_ptr< class StatechartProfile > StatechartProfilePtr
Definition: StatechartContext.h:52
InfixFilterModel.h
EditStatechartGroupDialog.h
armarx::armem::contains
bool contains(const MemoryID &general, const MemoryID &specific)
Indicates whether general is "less specific" than, or equal to, specific, i.e.
Definition: MemoryID.cpp:558
cxxopts::empty
bool empty(const std::string &s)
Definition: cxxopts.hpp:255
armarx::StatechartProfilesPtr
std::shared_ptr< StatechartProfiles > StatechartProfilesPtr
Definition: StatechartProfiles.h:35
Ui
ArmarX Headers.
Definition: ArmarXMainWindow.h:58
armarx::CMakePackageFinder::getPackageDir
std::string getPackageDir() const
Returns the top level path of a source package.
Definition: CMakePackageFinder.h:144
armarx::EditStatechartGroupDialog
Definition: EditStatechartGroupDialog.h:44
StatechartGroup.h
armarx::EditStatechartGroupDialog::~EditStatechartGroupDialog
~EditStatechartGroupDialog() override
Definition: EditStatechartGroupDialog.cpp:159
armarx::VariantInfo::ProxyEntryPtr
std::shared_ptr< ProxyEntry > ProxyEntryPtr
Definition: VariantInfo.h:71
armarx::CMakePackageFinder::getStatechartsDir
std::string getStatechartsDir() const
Definition: CMakePackageFinder.h:115
armarx::EditStatechartGroupDialog::updateProxyListEnabled
void updateProxyListEnabled(int state)
Definition: EditStatechartGroupDialog.cpp:346
armarx::EditStatechartGroupDialog::checkPackagePath
void checkPackagePath()
Definition: EditStatechartGroupDialog.cpp:311
armarx::EditStatechartGroupDialog::getConfigurations
QMap< QString, QString > getConfigurations() const
Definition: EditStatechartGroupDialog.cpp:274
armarx::EditStatechartGroupDialog::EditMode
EditMode
Definition: EditStatechartGroupDialog.h:49
armarx::EditStatechartGroupDialog::getGroupDescription
QString getGroupDescription() const
Definition: EditStatechartGroupDialog.cpp:203
armarx::StatechartGroupPtr
std::shared_ptr< StatechartGroup > StatechartGroupPtr
Definition: StatechartGroupDefs.h:34
armarx::EditStatechartGroupDialog::getGroupPath
QString getGroupPath() const
Definition: EditStatechartGroupDialog.cpp:174
armarx::EditStatechartGroupDialog::contextGenerationEnabled
bool contextGenerationEnabled() const
Definition: EditStatechartGroupDialog.cpp:269
armarx::EditStatechartGroupDialog::EditStatechartGroupDialog
EditStatechartGroupDialog(EditMode editMode, QString groupName, ArmarXPackageToolInterfacePtr packageTool, VariantInfoPtr variantInfo, QList< QString > selectedProxies, bool generateContext, const StatechartProfilesPtr &statechartProfiles, const QMap< QString, QString > &statechartGroupConfigurations=QMap< QString, QString >(), const QString &description="", StatechartGroupPtr group=StatechartGroupPtr(), QWidget *parent=0)
Definition: EditStatechartGroupDialog.cpp:46
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
armarx::EditStatechartGroupDialog::NewGroup
@ NewGroup
Definition: EditStatechartGroupDialog.h:49
armarx::EditStatechartGroupDialog::updateConfigurationTextField
void updateConfigurationTextField(QString profileText)
Definition: EditStatechartGroupDialog.cpp:351
armarx::EditStatechartGroupDialog::getGroupName
QString getGroupName() const
Definition: EditStatechartGroupDialog.cpp:169
armarx::VariantInfoPtr
std::shared_ptr< VariantInfo > VariantInfoPtr
Definition: VariantInfo.h:39
armarx::EditStatechartGroupDialog::getPackageName
QString getPackageName() const
Definition: EditStatechartGroupDialog.cpp:208
armarx::statechartmodel::StatePtr
std::shared_ptr< State > StatePtr
Definition: State.h:46
armarx::InfixFilterModel
This proxy model reimplements the filterAcceptsRow function with a new behavior: All elements that fi...
Definition: InfixFilterModel.h:41
Logging.h
armarx::EditStatechartGroupDialog::updateConfigurationContent
void updateConfigurationContent(int index)
Definition: EditStatechartGroupDialog.cpp:370
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
ArmarXDataPath.h
armarx::EditStatechartGroupDialog::getPackageTool
ArmarXPackageToolInterfacePtr getPackageTool() const
Definition: EditStatechartGroupDialog.cpp:164
armarx::VariantInfo::LibEntryPtr
std::shared_ptr< LibEntry > LibEntryPtr
Definition: VariantInfo.h:172
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28