38#include <boost/assign.hpp>
43#include <QApplication>
44#include <QItemSelection>
45#include <QRegularExpression>
46#include <unordered_map>
53static const std::unordered_map<DisabledReason, const char*> LONG_REASONS_TO_STRING =
54 boost::assign::map_list_of
55 (
NEVER,
"Never in Collision" )
56 (
DEFAULT,
"Collision by Default" )
58 (
ALWAYS,
"Always in Collision" )
59 (
USER,
"User Disabled" )
63static const std::unordered_map<DisabledReason, QVariant> LONG_REASONS_TO_BRUSH =
64 boost::assign::map_list_of
65 (
NEVER, QBrush(QColor(
"lightgreen")) )
66 (
DEFAULT, QBrush(QColor(
"lightpink")) )
67 (
ADJACENT, QBrush(QColor(
"powderblue")) )
68 (
ALWAYS, QBrush(QColor(
"tomato")) )
69 (
USER, QBrush(QColor(
"yellow")) )
73 : QAbstractTableModel(parent), pairs_(pairs), std_names_(names)
76 for (std::vector<std::string>::const_iterator it = names.begin(), end = names.end(); it != end; ++it, ++idx)
78 visual_to_index_ << idx;
79 q_names_ << QString::fromStdString(*it);
84LinkPairMap::iterator CollisionMatrixModel::item(
const QModelIndex& index)
86 int r = visual_to_index_[index.row()], c = visual_to_index_[index.column()];
91 if (std_names_[r] >= std_names_[c])
94 return pairs_.find(std::make_pair(std_names_[r], std_names_[c]));
99 return visual_to_index_.size();
104 return visual_to_index_.size();
109 if (index.isValid() && index.row() == index.column() && role == Qt::BackgroundRole)
110 return QApplication::palette().window();
112 LinkPairMap::const_iterator item = this->item(index);
113 if (item == pairs_.end())
118 case Qt::CheckStateRole:
119 return item->second.disable_check ? Qt::Checked : Qt::Unchecked;
120 case Qt::ToolTipRole:
121 return LONG_REASONS_TO_STRING.at(item->second.reason);
122 case Qt::BackgroundRole:
123 return LONG_REASONS_TO_BRUSH.at(item->second.reason);
130 LinkPairMap::const_iterator item = this->item(index);
131 if (item == pairs_.end())
133 return item->second.reason;
138 if (role == Qt::CheckStateRole)
140 LinkPairMap::iterator item = this->item(index);
141 if (item == pairs_.end())
144 bool new_value = (value.toInt() == Qt::Checked);
145 if (item->second.disable_check == new_value)
148 item->second.disable_check = new_value;
151 if (item->second.disable_check && item->second.reason ==
NOT_DISABLED)
153 item->second.reason =
USER;
157 else if (!item->second.disable_check && item->second.reason ==
USER)
162 QModelIndex mirror = this->index(index.column(), index.row());
163 Q_EMIT dataChanged(index, index);
164 Q_EMIT dataChanged(mirror, mirror);
173 QItemSelection changes;
175 for (
const auto& range : selection)
179 const QModelIndex& top_left = range.topLeft();
180 const QModelIndex& bottom_right = range.bottomRight();
181 changes.select(top_left, bottom_right);
182 changes.select(createIndex(top_left.column(), top_left.row()),
183 createIndex(bottom_right.column(), bottom_right.row()));
188 for (
const auto& range : changes)
189 Q_EMIT dataChanged(range.topLeft(), range.bottomRight());
194 for (
const auto idx : indexes)
195 setData(idx, value ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
201 QRegularExpression regexp(QRegularExpression::escape(filter));
202 visual_to_index_.clear();
203 for (
int idx = 0, end = q_names_.size(); idx != end; ++idx)
205 if (q_names_[idx].contains(regexp))
206 visual_to_index_ << idx;
213 if (role == Qt::DisplayRole)
214 return q_names_[visual_to_index_[section]];
220 if (!index.isValid())
221 return Qt::NoItemFlags;
223 Qt::ItemFlags f = QAbstractTableModel::flags(index);
224 if (index.row() != index.column())
225 f |= Qt::ItemIsUserCheckable;
int columnCount(const QModelIndex &parent=QModelIndex()) const override
bool setData(const QModelIndex &, const QVariant &value, int role) override
CollisionMatrixModel(LinkPairMap &pairs, const std::vector< std::string > &names, QObject *parent=nullptr)
void setEnabled(const QItemSelection &selection, bool value)
DisabledReason reason(const QModelIndex &index) const
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void setFilterRegularExpression(const QString &filter)
Qt::ItemFlags flags(const QModelIndex &index) const override
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
DisabledReason
Reasons for disabling link pairs. Append "in collision" for understanding. NOT_DISABLED means the lin...
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...