ControlDevicesWidget.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 RobotAPI::gui-plugins::RobotUnitPlugin
17  * \author Raphael Grimm ( raphael dot grimm at kit dot edu )
18  * \date 2017
19  * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 #include "ControlDevicesWidget.h"
23 
24 #include "StyleSheets.h"
25 
26 #include <QCheckBox>
27 
28 namespace armarx
29 {
31  RobotUnitWidgetTemplateBase("ControlDevicesWidget", parent)
32  {
33  ui->treeWidget->setColumnCount(8);
34  QTreeWidgetItem* head = ui->treeWidget->headerItem();
35  head->setText(idxName, "Name");
36  head->setText(idxTags, "Tags");
37  head->setText(idxMode, "Mode");
38  head->setText(idxHWMode, "HardwareMode");
39  head->setText(idxAct, "Act");
40  head->setText(idxReq, "Req");
41  head->setText(idxType, "Target Type");
42  head->setText(idxVal, "Target Value");
43 
44  head->setToolTip(idxName, "The control device's name (green: ok, red: missmatch between requested and active mode, orange: active/requested device not found in the displayed list)");
45  head->setToolTip(idxTags, "The control device's tags");
46  head->setToolTip(idxMode, "The control device's control mode");
47  head->setToolTip(idxHWMode, "The control device's hardware control mode");
48  head->setToolTip(idxAct, "Whether the control mode is active (green: ok, red: missmatch between requested and active mode)");
49  head->setToolTip(idxReq, "Whether the control mode is requested (green: ok, red: missmatch between requested and active mode)");
50  head->setToolTip(idxType, "The control mode's target type");
51  head->setToolTip(idxVal, "The control mode's target value");
52 
53  ui->treeWidget->setColumnWidth(idxName, 150);
54  ui->treeWidget->setColumnWidth(idxTags, 100);
55  ui->treeWidget->setColumnWidth(idxMode, 225);
56  ui->treeWidget->setColumnWidth(idxHWMode, 110);
57  ui->treeWidget->setColumnWidth(idxAct, 40);
58  ui->treeWidget->setColumnWidth(idxReq, 40);
59  ui->treeWidget->setColumnWidth(idxType, 350);
60  ui->treeWidget->header()->setResizeMode(idxAct, QHeaderView::Fixed);
61  ui->treeWidget->header()->setResizeMode(idxReq, QHeaderView::Fixed);
62  }
63 
65  {
66  delete ui;
67  }
68 
69  void ControlDevicesWidget::controlDeviceStatusChanged(const ControlDeviceStatusSeq& allStatus)
70  {
71  std::unique_lock<std::recursive_timed_mutex> guard {mutex, std::defer_lock};
72  if (!guard.try_lock_for(std::chrono::microseconds(100)))
73  {
74  return;
75  }
76  for (const auto& status : allStatus)
77  {
78  if (statusUpdates[status.deviceName].timestampUSec < status.timestampUSec)
79  {
80  statusUpdates[status.deviceName] = status;
81  if (doMetaCall)
82  {
83  QMetaObject::invokeMethod(this, "updateContent", Qt::QueuedConnection);
84  }
85  }
86  }
87  }
88 
90  {
91  entries.clear();
92  statusUpdates.clear();
93  resetData.clear();
94  }
95 
97  {
98  for (const auto& pair : statusUpdates)
99  {
100  update(pair.second);
101  }
102  statusUpdates.clear();
103  }
104 
106  {
107  auto temp = robotUnit->getControlDeviceDescriptions();
108  {
109  std::unique_lock<std::recursive_timed_mutex> guard {mutex};
110  resetData = std::move(temp);
111  }
112  }
113 
115  {
116  if (resetData.empty())
117  {
118  return true;
119  }
120  add(resetData.back());
121  resetData.pop_back();
122  return false;
123  }
124 
125  void ControlDevicesWidget::add(const ControlDeviceDescription& desc)
126  {
127  std::unique_lock<std::recursive_timed_mutex> guard {mutex};
128  if (entries.count(desc.deviceName))
129  {
130  return;
131  }
132  entries[desc.deviceName] = new ControlDevicesWidgetEntry(*this, *(ui->treeWidget), desc);
133  }
134 
135  void ControlDevicesWidget::update(const ControlDeviceStatus& status)
136  {
137  std::unique_lock<std::recursive_timed_mutex> guard {mutex};
138  if (!robotUnit || ! robotUnit->isRunning())
139  {
140  return;
141  }
142  if (!entries.count(status.deviceName))
143  {
144  add(robotUnit->getControlDeviceDescription(status.deviceName));
145  }
146  entries.at(status.deviceName)->update(status);
147  }
148 
149  ControlDevicesWidgetEntry::ControlDevicesWidgetEntry(ControlDevicesWidget& parent, QTreeWidget& treeWidget, const ControlDeviceDescription& desc)
150  : QObject {&parent}
151  {
152  header = new QTreeWidgetItem;
153  treeWidget.addTopLevelItem(header);
154  header->setText(ControlDevicesWidget::idxName, QString::fromStdString(desc.deviceName));
155  //tags
156  {
157  QCheckBox* boxTags = new QCheckBox{QString::number(desc.tags.size()) + " Tags"};
158  treeWidget.setItemWidget(header, ControlDevicesWidget::idxTags, boxTags);
159  boxTags->setStyleSheet(checkboxStyleSheet());
160  boxTags->setChecked(false);
161  connect(boxTags, SIGNAL(clicked(bool)), this, SLOT(hideTagList(bool)));
162  for (const auto& tag : desc.tags)
163  {
164  QTreeWidgetItem* child = new QTreeWidgetItem {{QString::fromStdString(tag)}};
165  treeWidget.addTopLevelItem(child);
166  tags.emplace_back(child);
167  }
168  }
169  for (const auto& nameToType : desc.contolModeToTargetType)
170  {
171  ControllerEntry& subEntry = subEntries[nameToType.first];
172  subEntry.child = new QTreeWidgetItem;
173  header->addChild(subEntry.child);
174  subEntry.child->setText(ControlDevicesWidget::idxMode, QString::fromStdString(nameToType.first));
175  subEntry.child->setText(ControlDevicesWidget::idxHWMode, QString::fromStdString(nameToType.second.hardwareControlMode));
176  subEntry.child->setText(ControlDevicesWidget::idxAct, " ");
177  subEntry.child->setText(ControlDevicesWidget::idxReq, " ");
178  subEntry.child->setText(ControlDevicesWidget::idxType, QString::fromStdString(nameToType.second.targetType));
179  subEntry.value = new VariantWidget;
180  treeWidget.setItemWidget(subEntry.child, ControlDevicesWidget::idxVal, subEntry.value);
181  }
182  }
183 
184  void ControlDevicesWidgetEntry::update(const ControlDeviceStatus& status)
185  {
186  auto colorNew = (status.activeControlMode == status.requestedControlMode) ? green() : red();
187  bool newDevsNotFound = false;
188  if (activeMode != status.activeControlMode)
189  {
190  if (subEntries.count(activeMode))
191  {
192  subEntries.at(activeMode).child->setText(ControlDevicesWidget::idxAct, " ");
193  subEntries.at(activeMode).child->setBackgroundColor(ControlDevicesWidget::idxAct, transparent());
194  }
195  activeMode = status.activeControlMode;
196  if (subEntries.count(activeMode))
197  {
198  newDevsNotFound = true;
199  subEntries.at(activeMode).child->setText(ControlDevicesWidget::idxAct, "X");
200  }
201  }
202  if (requestedMode != status.requestedControlMode)
203  {
204  if (subEntries.count(requestedMode))
205  {
206  subEntries.at(requestedMode).child->setText(ControlDevicesWidget::idxReq, " ");
207  subEntries.at(requestedMode).child->setBackgroundColor(ControlDevicesWidget::idxReq, transparent());
208  }
209  requestedMode = status.requestedControlMode;
210  if (subEntries.count(requestedMode))
211  {
212  newDevsNotFound = true;
213  subEntries.at(requestedMode).child->setText(ControlDevicesWidget::idxReq, "X");
214  }
215  }
216  //color
217  {
218  //set the color here, since active may change without requested changen (or the other way) -> above there is no update
219  if (subEntries.count(requestedMode))
220  {
221  subEntries.at(requestedMode).child->setBackgroundColor(ControlDevicesWidget::idxReq, colorNew);
222  }
223  if (subEntries.count(activeMode))
224  {
225  subEntries.at(activeMode).child->setBackgroundColor(ControlDevicesWidget::idxAct, colorNew);
226  }
227  header->setBackgroundColor(ControlDevicesWidget::idxName, newDevsNotFound ? orange() : colorNew);
228  }
229  for (const auto& pair : status.controlTargetValues)
230  {
231  if (subEntries.count(pair.first))
232  {
233  subEntries.at(pair.first).value->update(pair.second);
234  subEntries.at(pair.first).value->layout()->setContentsMargins(0, 0, 0, 0);
235  }
236  }
237  }
238 
239  bool ControlDevicesWidgetEntry::matchName(const QString& name)
240  {
241  return header->text(ControlDevicesWidget::idxName).contains(name, Qt::CaseInsensitive);
242  }
243 
244  bool ControlDevicesWidgetEntry::matchTag(const QString& tag)
245  {
246  for (const auto& tagit : tags)
247  {
248  if (tagit->text(ControlDevicesWidget::idxTags).contains(tag, Qt::CaseInsensitive))
249  {
250  return true;
251  }
252  }
253  return false;
254  }
255 
256  std::set<QTreeWidgetItem*> ControlDevicesWidgetEntry::matchMode(const QString& mode)
257  {
258  std::set<QTreeWidgetItem*> hits;
259  for (const auto& pair : subEntries)
260  {
261  if (pair.second.child->text(ControlDevicesWidget::idxMode).contains(mode, Qt::CaseInsensitive))
262  {
263  hits.emplace(pair.second.child);
264  }
265  }
266  return hits;
267  }
268 
269  std::set<QTreeWidgetItem*> ControlDevicesWidgetEntry::isActiveState(const QString& state)
270  {
271  std::set<QTreeWidgetItem*> hits;
272  for (const auto& pair : subEntries)
273  {
274  if (pair.second.child->text(ControlDevicesWidget::idxAct).contains(state, Qt::CaseInsensitive))
275  {
276  hits.emplace(pair.second.child);
277  }
278  }
279  return hits;
280  }
281 
282  std::set<QTreeWidgetItem*> ControlDevicesWidgetEntry::isRequestedState(const QString& state)
283  {
284  std::set<QTreeWidgetItem*> hits;
285  for (const auto& pair : subEntries)
286  {
287  if (pair.second.child->text(ControlDevicesWidget::idxReq).contains(state, Qt::CaseInsensitive))
288  {
289  hits.emplace(pair.second.child);
290  }
291  }
292  return hits;
293  }
294 
295  std::set<QTreeWidgetItem*> ControlDevicesWidgetEntry::matchTargetType(const QString& type)
296  {
297  std::set<QTreeWidgetItem*> hits;
298  for (const auto& pair : subEntries)
299  {
300  if (pair.second.child->text(ControlDevicesWidget::idxType).contains(type, Qt::CaseInsensitive))
301  {
302  hits.emplace(pair.second.child);
303  }
304  }
305  return hits;
306  }
307 
309  {
310  if (!vis)
311  {
312  hideTagList(true);
313  }
314  header->setHidden(!vis);
315  }
316 
317  void ControlDevicesWidgetEntry::setChildVis(bool vis, std::set<QTreeWidgetItem*> children)
318  {
319  for (const auto& pair : subEntries)
320  {
321  if (children.count(pair.second.child))
322  {
323  pair.second.child->setHidden(!vis);
324  }
325  else
326  {
327  pair.second.child->setHidden(vis);
328  }
329  }
330  }
331 
332  void ControlDevicesWidgetEntry::hideTagList(bool hide)
333  {
334  for (QTreeWidgetItem* tag : tags)
335  {
336  tag->setHidden(hide);
337  }
338  }
339 }
armarx::ControlDevicesWidget::idxHWMode
static constexpr int idxHWMode
Definition: ControlDevicesWidget.h:74
armarx::ControlDevicesWidget::idxType
static constexpr int idxType
Definition: ControlDevicesWidget.h:77
armarx::ControlDevicesWidgetEntry::matchName
bool matchName(const QString &name)
Definition: ControlDevicesWidget.cpp:239
armarx::checkboxStyleSheet
QString checkboxStyleSheet()
Definition: StyleSheets.h:30
armarx::ControlDevicesWidget::idxAct
static constexpr int idxAct
Definition: ControlDevicesWidget.h:75
armarx::ControlDevicesWidgetEntry::matchTargetType
std::set< QTreeWidgetItem * > matchTargetType(const QString &type)
Definition: ControlDevicesWidget.cpp:295
armarx::ControlDevicesWidget::idxTags
static constexpr int idxTags
Definition: ControlDevicesWidget.h:72
armarx::ControlDevicesWidgetEntry::matchTag
bool matchTag(const QString &tag)
Definition: ControlDevicesWidget.cpp:244
armarx::RobotUnitWidgetTemplateBase< Ui::ControlDevicesWidget >::ui
Ui::ControlDevicesWidget * ui
Definition: RobotUnitWidgetBase.h:117
armarx::ControlDevicesWidget
Definition: ControlDevicesWidget.h:50
armarx::ControlDevicesWidgetEntry::ControlDevicesWidgetEntry
ControlDevicesWidgetEntry(ControlDevicesWidget &parent, QTreeWidget &treeWidget, const ControlDeviceDescription &desc)
Definition: ControlDevicesWidget.cpp:149
armarx::ControlDevicesWidget::idxVal
static constexpr int idxVal
Definition: ControlDevicesWidget.h:78
armarx::RobotUnitWidgetBase::doMetaCall
std::atomic_bool doMetaCall
Definition: RobotUnitWidgetBase.h:87
armarx::ControlDevicesWidget::controlDeviceStatusChanged
void controlDeviceStatusChanged(const ControlDeviceStatusSeq &allStatus)
Definition: ControlDevicesWidget.cpp:69
armarx::ControlDevicesWidgetEntry::matchMode
std::set< QTreeWidgetItem * > matchMode(const QString &mode)
Definition: ControlDevicesWidget.cpp:256
armarx::status
status
Definition: FiniteStateMachine.h:259
armarx::ControlDevicesWidgetEntry::isActiveState
std::set< QTreeWidgetItem * > isActiveState(const QString &state)
Definition: ControlDevicesWidget.cpp:269
armarx::RobotUnitWidgetBase::robotUnit
RobotUnitInterfacePrx robotUnit
Definition: RobotUnitWidgetBase.h:81
armarx::ControlDevicesWidgetEntry::setVisible
void setVisible(bool vis)
Definition: ControlDevicesWidget.cpp:308
armarx::RobotUnitWidgetBase::mutex
std::recursive_timed_mutex mutex
Definition: RobotUnitWidgetBase.h:82
armarx::ControlDevicesWidgetEntry::update
void update(const ControlDeviceStatus &status)
Definition: ControlDevicesWidget.cpp:184
armarx::ControlDevicesWidget::ControlDevicesWidget
ControlDevicesWidget(QWidget *parent=0)
Definition: ControlDevicesWidget.cpp:30
armarx::ControlDevicesWidget::idxMode
static constexpr int idxMode
Definition: ControlDevicesWidget.h:73
armarx::RobotUnitWidgetTemplateBase
Definition: RobotUnitWidgetBase.h:93
armarx::ControlDevicesWidget::doContentUpdate
void doContentUpdate() override
Definition: ControlDevicesWidget.cpp:96
armarx::ControlDevicesWidget::idxName
static constexpr int idxName
Definition: ControlDevicesWidget.h:71
armarx::red
QColor red()
Definition: StyleSheets.h:76
armarx::ControlDevicesWidget::clearAll
void clearAll() override
Definition: ControlDevicesWidget.cpp:89
armarx::ControlDevicesWidget::~ControlDevicesWidget
~ControlDevicesWidget() override
Definition: ControlDevicesWidget.cpp:64
armarx::ControlDevicesWidget::addOneFromResetData
bool addOneFromResetData() override
Definition: ControlDevicesWidget.cpp:114
ControlDevicesWidget.h
armarx::ControlDevicesWidgetEntry::isRequestedState
std::set< QTreeWidgetItem * > isRequestedState(const QString &state)
Definition: ControlDevicesWidget.cpp:282
armarx::ControlDevicesWidgetEntry::setChildVis
void setChildVis(bool vis, std::set< QTreeWidgetItem * > children)
Definition: ControlDevicesWidget.cpp:317
armarx::ControlDevicesWidget::getResetData
void getResetData() override
Definition: ControlDevicesWidget.cpp:105
armarx::transparent
QColor transparent()
Definition: StyleSheets.h:84
armarx::ControlDevicesWidget::idxReq
static constexpr int idxReq
Definition: ControlDevicesWidget.h:76
armarx::orange
QColor orange()
Definition: StyleSheets.h:80
StyleSheets.h
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::green
QColor green()
Definition: StyleSheets.h:72