collision_matrix_model.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2016, CITEC, Bielefeld University
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Robert Haschke */
36 
37 #include "collision_matrix_model.h"
38 #include <boost/unordered_map.hpp>
39 #include <boost/assign.hpp>
40 #include <QVector>
41 #include <QBrush>
42 #include <QColor>
43 #include <QPalette>
44 #include <QApplication>
45 #include <QItemSelection>
46 
47 using namespace moveit_setup_assistant;
48 
50 static const boost::unordered_map<moveit_setup_assistant::DisabledReason, const char*> longReasonsToString =
51  boost::assign::map_list_of // clang-format off
52  ( moveit_setup_assistant::NEVER, "Never in Collision" )
53  ( moveit_setup_assistant::DEFAULT, "Collision by Default" )
54  ( moveit_setup_assistant::ADJACENT, "Adjacent Links" )
55  ( moveit_setup_assistant::ALWAYS, "Always in Collision" )
56  ( moveit_setup_assistant::USER, "User Disabled" )
57  ( moveit_setup_assistant::NOT_DISABLED, ""); // clang-format on
58 
60 static const boost::unordered_map<moveit_setup_assistant::DisabledReason, QVariant> longReasonsToBrush =
61  boost::assign::map_list_of // clang-format off
62  ( moveit_setup_assistant::NEVER, QBrush(QColor("lightgreen")) )
63  ( moveit_setup_assistant::DEFAULT, QBrush(QColor("lightpink")) )
64  ( moveit_setup_assistant::ADJACENT, QBrush(QColor("powderblue")) )
65  ( moveit_setup_assistant::ALWAYS, QBrush(QColor("tomato")) )
66  ( moveit_setup_assistant::USER, QBrush(QColor("yellow")) )
67  ( moveit_setup_assistant::NOT_DISABLED, QBrush()); // clang-format on
68 
70  const std::vector<std::string>& names, QObject* parent)
71  : QAbstractTableModel(parent), pairs(pairs), std_names(names)
72 {
73  int idx = 0;
74  for (std::vector<std::string>::const_iterator it = names.begin(), end = names.end(); it != end; ++it, ++idx)
75  {
76  visual_to_index << idx;
77  q_names << QString::fromStdString(*it);
78  }
79 }
80 
81 // return item in pairs map given a normalized index, use item(normalized(index))
82 moveit_setup_assistant::LinkPairMap::iterator CollisionMatrixModel::item(const QModelIndex& index)
83 {
84  int r = visual_to_index[index.row()], c = visual_to_index[index.column()];
85  if (r == c)
86  return pairs.end();
87 
88  // setLinkPair() actually inserts the pair (A,B) where A < B
89  if (std_names[r] >= std_names[c])
90  std::swap(r, c);
91 
92  return pairs.find(std::make_pair(std_names[r], std_names[c]));
93 }
94 
95 int CollisionMatrixModel::rowCount(const QModelIndex& /*parent*/) const
96 {
97  return visual_to_index.size();
98 }
99 
100 int CollisionMatrixModel::columnCount(const QModelIndex& /*parent*/) const
101 {
102  return visual_to_index.size();
103 }
104 
105 QVariant CollisionMatrixModel::data(const QModelIndex& index, int role) const
106 {
107  if (index.isValid() && index.row() == index.column() && role == Qt::BackgroundRole)
108  return QApplication::palette().window();
109 
110  moveit_setup_assistant::LinkPairMap::const_iterator item = this->item(index);
111  if (item == pairs.end())
112  return QVariant();
113 
114  switch (role)
115  {
116  case Qt::CheckStateRole:
117  return item->second.disable_check ? Qt::Checked : Qt::Unchecked;
118  case Qt::ToolTipRole:
119  return longReasonsToString.at(item->second.reason);
120  case Qt::BackgroundRole:
121  return longReasonsToBrush.at(item->second.reason);
122  }
123  return QVariant();
124 }
125 
127 {
128  moveit_setup_assistant::LinkPairMap::const_iterator item = this->item(index);
129  if (item == pairs.end())
131  return item->second.reason;
132 }
133 
134 bool CollisionMatrixModel::setData(const QModelIndex& index, const QVariant& value, int role)
135 {
136  if (role == Qt::CheckStateRole)
137  {
138  moveit_setup_assistant::LinkPairMap::iterator item = this->item(index);
139  if (item == pairs.end())
140  return false;
141 
142  bool new_value = (value.toInt() == Qt::Checked);
143  if (item->second.disable_check == new_value)
144  return true;
145 
146  item->second.disable_check = new_value;
147 
148  // Handle USER Reasons: 1) pair is disabled by user
149  if (item->second.disable_check == true && item->second.reason == moveit_setup_assistant::NOT_DISABLED)
150  item->second.reason = moveit_setup_assistant::USER;
151 
152  // Handle USER Reasons: 2) pair was disabled by user and now is enabled (not checked)
153  else if (item->second.disable_check == false && item->second.reason == moveit_setup_assistant::USER)
154  item->second.reason = moveit_setup_assistant::NOT_DISABLED;
155 
156  QModelIndex mirror = this->index(index.column(), index.row());
157  Q_EMIT dataChanged(index, index);
158  Q_EMIT dataChanged(mirror, mirror);
159  return true;
160  }
161  return false; // reject all other changes
162 }
163 
164 void CollisionMatrixModel::setEnabled(const QItemSelection& selection, bool value)
165 {
166  // perform changes without signalling
167  QItemSelection changes;
168  blockSignals(true);
169  for (const auto range : selection)
170  {
171  setEnabled(range.indexes(), value);
172 
173  const QModelIndex& top_left = range.topLeft();
174  const QModelIndex& bottom_right = range.bottomRight();
175  changes.select(top_left, bottom_right);
176  changes.select(createIndex(top_left.column(), top_left.row()),
177  createIndex(bottom_right.column(), bottom_right.row()));
178  }
179  blockSignals(false);
180 
181  // emit changes
182  for (const auto range : changes)
183  Q_EMIT dataChanged(range.topLeft(), range.bottomRight());
184 }
185 
186 void CollisionMatrixModel::setEnabled(const QModelIndexList& indexes, bool value)
187 {
188  for (const auto idx : indexes)
189  setData(idx, value ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
190 }
191 
192 void CollisionMatrixModel::setFilterRegExp(const QString& filter)
193 {
194  beginResetModel();
195  QRegExp regexp(filter);
196  visual_to_index.clear();
197  for (int idx = 0, end = q_names.size(); idx != end; ++idx)
198  {
199  if (q_names[idx].contains(regexp))
200  visual_to_index << idx;
201  }
202  endResetModel();
203 }
204 
205 QVariant CollisionMatrixModel::headerData(int section, Qt::Orientation, int role) const
206 {
207  if (role == Qt::DisplayRole)
208  return q_names[visual_to_index[section]];
209  return QVariant();
210 }
211 
212 Qt::ItemFlags CollisionMatrixModel::flags(const QModelIndex& index) const
213 {
214  if (!index.isValid())
215  return 0;
216 
217  Qt::ItemFlags f = QAbstractTableModel::flags(index);
218  if (index.row() != index.column())
219  f |= Qt::ItemIsUserCheckable;
220  return f;
221 }
moveit_setup_assistant::LinkPairMap & pairs
static const boost::unordered_map< moveit_setup_assistant::DisabledReason, QVariant > longReasonsToBrush
Boost mapping of reasons to a background color.
CollisionMatrixModel(moveit_setup_assistant::LinkPairMap &pairs, const std::vector< std::string > &names, QObject *parent=NULL)
f
bool setData(const QModelIndex &, const QVariant &value, int role)
Qt::ItemFlags flags(const QModelIndex &index) const
int rowCount(const QModelIndex &parent=QModelIndex()) const
QVariant headerData(int section, Qt::Orientation orientation, int role) const
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
r
DisabledReason
Reasons for disabling link pairs. Append "in collision" for understanding. NOT_DISABLED means the lin...
const std::vector< std::string > std_names
static const boost::unordered_map< moveit_setup_assistant::DisabledReason, const char * > longReasonsToString
Boost mapping of reasons for disabling a link pair to strings.
int columnCount(const QModelIndex &parent=QModelIndex()) const
void setFilterRegExp(const QString &filter)
moveit_setup_assistant::LinkPairMap::iterator item(const QModelIndex &index)
void setEnabled(const QItemSelection &selection, bool value)
std::map< std::pair< std::string, std::string >, LinkPairData > LinkPairMap
LinkPairMap is an adjacency list structure containing links in string-based form. Used for disabled l...
moveit_setup_assistant::DisabledReason reason(const QModelIndex &index) const


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Sun Oct 18 2020 13:19:28