30#include "stationtreeeventmonitor.h"
35#include <QTreeWidgetItem>
45StationTreeEventMonitor::StationTreeEventMonitor(
IRoboDK* rdk, QObject* parent)
52 const auto items = _rdk->getItemList();
53 for (
const auto& item : items)
55 auto treeItem =
dynamic_cast<QTreeWidgetItem*
>(item);
56 if (treeItem && treeItem->treeWidget())
58 _tree = treeItem->treeWidget();
66 auto model = _tree->model();
68 using ModelClass = QAbstractItemModel;
69 using ThisClass = StationTreeEventMonitor;
70 connect(model, &ModelClass::modelReset,
this, &ThisClass::refresh);
71 connect(model, &ModelClass::dataChanged,
this, &ThisClass::onModelDataChanged);
72 connect(model, &ModelClass::rowsInserted,
this, &ThisClass::onModelRowsInserted);
73 connect(model, &ModelClass::rowsRemoved,
this, &ThisClass::onModelRowsRemoved);
78void StationTreeEventMonitor::refresh()
80 _addedIndices.clear();
84 if (!_tree || !_tree->model())
87 iterateOverTree(QModelIndex(), [
this] (
const QModelIndex& index)
89 auto item = itemFromIndex(index);
93 const QString name = index.data().toString();
94 _nameTable.insert({name, item});
95 _nameCache[item] = name;
99void StationTreeEventMonitor::submit()
103 auto addItem = [
this, &child] (
const QModelIndex& index)
105 auto item = itemFromIndex(index);
109 const QString name = index.data().toString();
110 _nameTable.insert({name, item});
111 _nameCache[item] = name;
113 if (_filter & IgnoreAdd)
116 if ((_filter & IgnoreChildren) && child)
119 if ((_filter & IgnoreInactiveStations) && !isActiveStationItem(index))
122 emit itemAdded(item);
125 for (
const auto& index : _addedIndices)
131 iterateOverTree(index, addItem);
134 _addedIndices.clear();
137void StationTreeEventMonitor::onModelDataChanged(
138 const QModelIndex& topLeft,
139 const QModelIndex& bottomRight,
140 const QVector<int>& roles)
142 if (!topLeft.isValid() || !bottomRight.isValid() || topLeft.parent() != bottomRight.parent())
145 bool nameChanged =
false;
146 bool iconChanged =
false;
148 for (
int role : roles)
152 case Qt::DisplayRole:
156 case Qt::DecorationRole:
164 bool isActive = (_filter & IgnoreInactiveStations) == 0 || isActiveStationItem(topLeft);
165 const auto parent = topLeft.parent();
167 auto updateItem = [
this, nameChanged, iconChanged, isActive, parent] (
const QModelIndex& index)
169 auto item = itemFromIndex(index);
173 const auto cache = _nameCache.find(item);
174 if (cache == _nameCache.end())
177 const auto range = _nameTable.equal_range(cache->second);
178 for (
auto it = range.first; it != range.second; ++it)
180 if (it->second == item)
182 _nameTable.erase(it);
187 const QString name = index.data().toString();
188 _nameTable.insert({name, item});
189 _nameCache[item] = name;
194 if ((_filter & IgnoreChildren) && parent != index.parent())
197 if (nameChanged && (_filter & IgnoreNameChange) == 0)
198 emit itemNameChanged(item, name);
200 if (iconChanged && (_filter & IgnoreIconChange) == 0)
201 emit itemIconChanged(item, qvariant_cast<QIcon>(index.data(Qt::DecorationRole)));
204 for (
int row = topLeft.row(); row <= bottomRight.row(); ++row)
206 auto index = _tree->model()->index(row, 0, topLeft.parent());
207 if (!index.isValid())
211 iterateOverTree(index, updateItem);
215void StationTreeEventMonitor::onModelRowsInserted(
const QModelIndex& parent,
int first,
int last)
217 if (_filter & IgnoreAdd)
220 for (
int row = first; row <= last; ++row)
222 auto index = _tree->model()->index(row, 0, parent);
225 auto it = std::find(_addedIndices.begin(), _addedIndices.end(), index);
226 if (it == _addedIndices.end())
227 _addedIndices.push_back(index);
231 if (_policy == AutoSubmit)
232 QTimer::singleShot(0,
this, &StationTreeEventMonitor::submit);
235void StationTreeEventMonitor::onModelRowsRemoved(
const QModelIndex& parent,
int first,
int last)
237 auto removeItem = [
this, &parent] (
const QModelIndex& index)
239 auto item = itemFromIndex(index);
243 const auto cache = _nameCache.find(item);
244 if (cache == _nameCache.end())
247 const auto range = _nameTable.equal_range(cache->second);
248 for (
auto it = range.first; it != range.second; ++it)
250 if (it->second == item)
252 _nameTable.erase(it);
257 _nameCache.erase(cache);
259 if (_filter & IgnoreRemove)
262 if ((_filter & IgnoreChildren) && parent != index.parent())
265 if ((_filter & IgnoreInactiveStations) && !isActiveStationItem(index))
268 emit itemRemoved(item);
271 for (
int row = last; row >= first; --row)
273 auto index = _tree->model()->index(row, 0, parent);
274 if (!index.isValid())
277 iterateOverTree(index, removeItem,
true);
282void StationTreeEventMonitor::iterateOverTree(
283 const QModelIndex& parent,
284 const TreeCallback& callback,
287 auto model = _tree->model();
289 using StackEntry = std::pair<int, QModelIndex>;
290 std::stack<StackEntry> stack;
291 stack.push({0, parent});
293 while (!stack.empty())
295 auto& entry = stack.top();
296 const auto& parent = entry.second;
297 const int start = entry.first;
298 const int count = model->rowCount(parent);
302 if (reverse && start > 0)
304 auto index = model->index(count - start, 0, parent);
308 for (
int i = start; i < count; ++i)
310 int row = reverse ? (count - i - 1) : i;
312 auto index = model->index(row, 0, parent);
313 if (!index.isValid())
319 if (model->hasChildren(index))
322 stack.push({0, index});
337IItem* StationTreeEventMonitor::itemFromIndex(
const QModelIndex& index)
const
339 auto treeItem =
static_cast<QTreeWidgetItem*
>(index.internalPointer());
340 return dynamic_cast<IItem*
>(treeItem);
343bool StationTreeEventMonitor::isActiveStationItem(
const QModelIndex& index)
const
345 QModelIndex parent = index;
346 while (parent.parent().isValid())
347 parent = parent.parent();
349 if (!parent.isValid())
352 auto item = itemFromIndex(parent);
353 return item && _rdk && item == _rdk->getActiveStation();
The Item class represents an item in RoboDK station. An item can be a robot, a frame,...
This class is the iterface to the RoboDK API. With the RoboDK API you can automate certain tasks and ...