RenameStateDialog.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 Valerij Wittenbeck (valerij.wittenbeck at student dot kit dot edu
18 * @date 2015
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22 
23 #include "RenameStateDialog.h"
24 #include <ArmarXGui/gui-plugins/StatechartEditorPlugin/view/dialogs/ui_RenameStateDialog.h>
25 
27 #include <QFileDialog>
28 #include <QTimer>
29 
32 #include <numeric>
33 
34 #include <QtGui>
35 
36 namespace armarx
37 {
38 
39  RenameStateDialog::RenameStateDialog(const StateTreeModelPtr& treeModel, const StatechartGroupPtr& sourceGroup, const statechartmodel::StatePtr& sourceState, QWidget* parent) :
40  QDialog(parent),
41  ui(new Ui::RenameStateDialog),
42  sourceGroup(sourceGroup),
43  sourceState(sourceState),
44  validStateNameRegExp("[a-zA-Z][a-zA-Z0-9]*"),
45  validInstanceNameRegExp("[a-zA-Z][a-zA-Z0-9_]*"),
46  validNewName(false),
47  validInstanceNames(true),
48  colorGreen(QColor::fromRgb(120, 255, 120)),
49  colorRed(QColor::fromRgb(255, 120, 120)),
50  colorYellow(QColor::fromRgb(255, 200, 0)),
51  saveAll(false),
52  alreadyChecking(false)
53  {
54  ui->setupUi(this);
55  setOkButtonsEnabled(false);
56  ui->editOldName->setText(sourceState->getStateName());
57  ui->editOldName->setReadOnly(true);
58  // ui->editOldName->setEnabled(false);
59 
60  ui->editNewName->setValidator(new QRegExpValidator(validStateNameRegExp, this));
61 
62  connect(ui->btnCancel, SIGNAL(clicked()), this, SLOT(reject()));
63  connect(ui->btnSaveAndProceed, SIGNAL(clicked()), this, SLOT(saveAllProceedButtonClicked()));
64  connect(ui->btnDontSaveAndProceed, SIGNAL(clicked()), this, SLOT(accept()));
65  connect(ui->editNewName, SIGNAL(textChanged(QString)), this, SLOT(verifyNewName(QString)));
66  connect(ui->statesWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(verifyInstanceName(QTableWidgetItem*)));
67 
68  localStates = sourceGroup->getAllStates(true);
69 
70  for (const StatechartGroupPtr& group : treeModel->getGroups())
71  {
72  if (group->getWriteAccess() == StatechartGroup::eReadOnly)
73  {
74  continue;
75  }
76  for (const StateTreeNodePtr& node : group->getAllNodes())
77  {
78  if (!node->isState() || !node->getState())
79  {
80  continue;
81  }
82 
83  auto state = node->getState();
84 
85  for (const statechartmodel::StateInstancePtr& instance : state->getSubstates())
86  {
87  if (!instance->getStateClass())
88  {
89  continue;
90  }
91 
92  if (instance->getStateClass()->getUUID() == sourceState->getUUID())
93  {
94  instanceRenameInfos.push_back({group, node, instance->getInstanceName(), instance->getInstanceName()});
95  }
96  }
97  }
98  }
99 
100  std::sort(instanceRenameInfos.begin(), instanceRenameInfos.end(), [](const StateRenamer::InstanceRenameInfo & info1, const StateRenamer::InstanceRenameInfo & info2)
101  {
102  if (info1.group->getName() == info2.group->getName())
103  {
104  if (info1.parentState->getState()->getStateName() == info2.parentState->getState()->getStateName())
105  {
106  return info1.fromName.compare(info2.toName);
107  }
108 
109  return info1.parentState->getState()->getStateName().compare(info2.parentState->getState()->getStateName());
110  }
111 
112  return info1.group->getName().compare(info2.group->getName());
113  });
114 
115  ui->statesWidget->clear();
116  ui->statesWidget->setRowCount(instanceRenameInfos.size());
117  ui->statesWidget->setColumnCount(3);
118  ui->statesWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
119  ui->statesWidget->setHorizontalHeaderLabels({"Statechart Group", "Parent State", "Instance Name"});
120 
121  int i = 0;
122 
123  for (const auto& info : instanceRenameInfos)
124  {
125  QTableWidgetItem* groupItem = new QTableWidgetItem(info.group->getName());
126  groupItem->setFlags(groupItem->flags() ^ Qt::ItemIsEditable);
127  ui->statesWidget->setItem(i, 0, groupItem);
128 
129  QTableWidgetItem* stateItem = new QTableWidgetItem(info.parentState->getState()->getStateName());
130  stateItem->setFlags(stateItem->flags() ^ Qt::ItemIsEditable);
131  ui->statesWidget->setItem(i, 1, stateItem);
132 
133  QTableWidgetItem* newInstanceItem = new QTableWidgetItem(info.toName);
134  newInstanceItem->setBackgroundColor(colorGreen);
135  ui->statesWidget->setItem(i, 2, newInstanceItem);
136 
137  ++i;
138  }
139  }
140 
141  RenameStateDialog::~RenameStateDialog()
142  {
143  delete ui;
144  }
145 
146  void RenameStateDialog::setOkButtonsEnabled(bool enabled)
147  {
148  ui->btnDontSaveAndProceed->setEnabled(enabled);
149  ui->btnSaveAndProceed->setEnabled(enabled);
150  }
151 
152  StatechartGroupPtr RenameStateDialog::getGroup() const
153  {
154  return sourceGroup;
155  }
156 
157  statechartmodel::StatePtr RenameStateDialog::getState() const
158  {
159  return sourceState;
160  }
161 
162  QVector<StateRenamer::InstanceRenameInfo> RenameStateDialog::getInstanceRenameInfos() const
163  {
164  return instanceRenameInfos;
165  }
166 
167  bool RenameStateDialog::isSaveAllRequested() const
168  {
169  return saveAll;
170  }
171 
172  QString RenameStateDialog::getNewStateName() const
173  {
174  return ui->editNewName->text();
175  }
176 
177  void RenameStateDialog::saveAllProceedButtonClicked()
178  {
179  saveAll = true;
180  accept();
181  }
182 
183  void RenameStateDialog::verifyInstanceName(QTableWidgetItem* item)
184  {
185  const int r = item->row();
186  const int c = item->column();
187 
188  //setting the background color triggers the "itemchanged" signal, which is what called this method in the first place
189  //this elegant solution ensures that no recursive calling is taking place
190  if (c != 2 || ui->statesWidget->columnCount() < 3 || ui->statesWidget->rowCount() == 0 || alreadyChecking)
191  {
192  return;
193  }
194 
195  alreadyChecking = true;
196 
197  StateRenamer::InstanceRenameInfo& info = instanceRenameInfos[r];
198 
199  bool hasNameCollisions = false;
200 
201  for (int i = 0; i < ui->statesWidget->rowCount(); ++i)
202  {
203  const auto& itemCheck = ui->statesWidget->item(i, 2);
204 
205  if (!itemCheck)
206  {
207  continue;
208  }
209 
210  const StateRenamer::InstanceRenameInfo& infoCheck = instanceRenameInfos[i];
211 
212  bool collision = false;
213 
214  for (int j = 0; j < ui->statesWidget->rowCount() && !collision; ++j)
215  {
216  const auto& itemOther = ui->statesWidget->item(j, 2);
217 
218  if (i == j || !itemOther)
219  {
220  continue;
221  }
222 
223  const StateRenamer::InstanceRenameInfo& infoR = instanceRenameInfos[j];
224 
225  if (infoCheck.parentState->getState()->getUUID() == infoR.parentState->getState()->getUUID())
226  {
227  ARMARX_INFO_S << " checking: " << itemCheck->text() << " " << itemOther->text();
228  collision = itemCheck->text() == itemOther->text();
229  }
230  }
231 
232  hasNameCollisions |= collision;
233  itemCheck->setBackgroundColor(collision ? colorRed : colorGreen);
234  }
235 
236  bool validName = validInstanceNameRegExp.exactMatch(item->text());
237 
238  if (validName)
239  {
240  info.toName = item->text();
241  }
242 
243  item->setBackgroundColor(!validName ? colorRed : item->backgroundColor());
244  validInstanceNames = validName && !hasNameCollisions;
245  setOkButtonsEnabled(validInstanceNames && validNewName);
246  alreadyChecking = false;
247  }
248 
249  void RenameStateDialog::verifyNewName(QString newName)
250  {
251  bool inUse = false;
252 
253  for (const auto& s : localStates)
254  {
255  if (newName == s->getStateName())
256  {
257  inUse = true;
258  break;
259  }
260  }
261 
262  QColor colorToUse;
263 
264  if (inUse)
265  {
266  ui->labelNewNameError->setText("Name already in use");
267  colorToUse = colorRed;
268  }
269  else
270  {
271  ui->labelNewNameError->setText("Valid name");
272  colorToUse = colorGreen;
273  }
274 
275  validNewName = (!inUse && newName.size() != 0);
276  setOkButtonsEnabled(validNewName && validInstanceNames);
277 
278  QPalette p(ui->labelNewNameError->palette());
279  p.setColor(ui->labelNewNameError->backgroundRole(), colorToUse);
280  ui->labelNewNameError->setPalette(p);
281  }
282 
283 } // namespace armarx
armarx::StateTreeModelPtr
std::shared_ptr< StateTreeModel > StateTreeModelPtr
Definition: StateTreeModel.h:44
armarx::RenameStateDialog::RenameStateDialog
RenameStateDialog(const StateTreeModelPtr &treeModel, const StatechartGroupPtr &sourceGroup, const statechartmodel::StatePtr &sourceState, QWidget *parent=0)
Definition: RenameStateDialog.cpp:39
armarx::StateRenamer::InstanceRenameInfo
Definition: StateRenamer.h:44
armarx::StateTreeNodePtr
std::shared_ptr< StateTreeNode > StateTreeNodePtr
Definition: StatechartGroupDefs.h:31
armarx::StateRenamer::InstanceRenameInfo::group
StatechartGroupPtr group
Definition: StateRenamer.h:46
armarx::StateRenamer::InstanceRenameInfo::parentState
StateTreeNodePtr parentState
Definition: StateRenamer.h:47
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
RenameStateDialog.h
armarx::RenameStateDialog
Definition: RenameStateDialog.h:41
armarx::StatechartGroup::eReadOnly
@ eReadOnly
Definition: StatechartGroup.h:40
armarx::statechartmodel::StateInstancePtr
std::shared_ptr< StateInstance > StateInstancePtr
Definition: StateInstance.h:138
armarx::RenameStateDialog::verifyInstanceName
void verifyInstanceName(QTableWidgetItem *item)
Definition: RenameStateDialog.cpp:183
armarx::RenameStateDialog::saveAllProceedButtonClicked
void saveAllProceedButtonClicked()
Definition: RenameStateDialog.cpp:177
Ui
ArmarX Headers.
Definition: ArmarXMainWindow.h:58
enabled
std::atomic< bool > * enabled
Definition: RemoteGuiWidgetController.cpp:75
armarx::RenameStateDialog::verifyNewName
void verifyNewName(QString newName)
Definition: RenameStateDialog.cpp:249
armarx::StatechartGroupPtr
std::shared_ptr< StatechartGroup > StatechartGroupPtr
Definition: StatechartGroupDefs.h:34
GroupCloner.h
armarx::statechartmodel::StatePtr
std::shared_ptr< State > StatePtr
Definition: State.h:46
armarx::StateRenamer::InstanceRenameInfo::toName
QString toName
Definition: StateRenamer.h:49
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:195
Logging.h
ArmarXDataPath.h
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28