HAL
port_tree_model.cpp
Go to the documentation of this file.
2 
4 #include "gui/gui_globals.h"
10 #include "hal_core/netlist/net.h"
12 
13 #include <QDebug>
14 #include <QMimeData>
15 
16 namespace hal
17 {
18  PortTreeItem::PortTreeItem(Type itype, u32 id_, QString pinName, PinDirection dir, PinType ptype, int inx, QString netName)
19  : mItemType(itype), mId(id_), mPinName(pinName), mPinDirection(dir), mPinType(ptype), mNetName(netName), mIndex(inx)
20  {;}
21 
23  {
24  switch (index)
25  {
26  case 0:
27  return mPinName;
28  case 1:
29  return QString::fromStdString(enum_to_string(mPinDirection));
30  case 2:
31  return QString::fromStdString(enum_to_string(mPinType));
32  case 3:
33  return mNetName;
34  case 4:
35  if (mItemType==PortTreeItem::Group)
36  return ( mIndex ? "descending" : "ascending");
37  return mIndex;
38  }
39  return QVariant();
40  }
41 
43  {
44  Q_ASSERT(data.size() >= 5);
45  mPinName = data[0].toString();
46  mPinDirection = enum_from_string<PinDirection>(data[1].toString().toStdString());
47  mPinType = enum_from_string<PinType>(data[2].toString().toStdString());
48  mNetName = data[3].toString();
49  mIndex = data[4].toInt();
50  }
51 
52  void PortTreeItem::setDataAtIndex(int index, QVariant &data)
53  {
54  switch (index)
55  {
56  case 0:
57  mPinName = data.toString();
58  break;
59  case 1:
60  mPinDirection = enum_from_string<PinDirection>(data.toString().toStdString());
61  break;
62  case 2:
63  mPinType = enum_from_string<PinType>(data.toString().toStdString());
64  break;
65  case 3:
66  mNetName = data.toString();
67  break;
68  case 4:
69  mIndex = data.toInt();
70  break;
71  }
72  }
73 
75  {
76  Q_UNUSED(data)
77  }
78 
80  {
81  return 5;
82  }
83 
85  {
86  setHeaderLabels(QStringList() << "Name"
87  << "Direction"
88  << "Type"
89  << "Connected Net"
90  << "Index");
92 
93  //connections
95  }
96 
98  {
99  delete mRootItem;
100  }
101 
103  {
104 // Qt::ItemFlags defaultFlags = BaseTreeModel::flags(index);
105 // TreeItem* item = index.isValid() ? getItemFromIndex(index) : nullptr;
106 // if (item)
107 // {
108 // //get parent, must be a pingroup item and not the root (not allowed to drag from external group, but maybe later)
109 // TreeItem* parentItem = item->getParent();
110 // itemType type = getTypeOfItem(item);
111 // if (type == itemType::portMultiBit)
112 // return defaultFlags | Qt::ItemIsDropEnabled;
113 // else if (type == itemType::pin) // && parentItem != mRootItem)//only case that should be possible
114 // return defaultFlags | Qt::ItemIsDragEnabled; // | Qt::ItemIsDropEnabled;
115 // if (parentItem == mRootItem && type == itemType::pin)
116 // return defaultFlags;
117 // }
118  // valid-check must be ommitted when a drop between pingroups is desired, all checks are performed in canDropMimeData
120 // if(item)
121 // {
122 // // everything can be dragged, but wether it can be dropped on or not depends on the situation
123 // // -> a pin cannot be dropped onto its parent-group (but it can be dropped within its group),
124 // // and a pingroup cannot be dropped onto (or between) a pin. -> what is currently dragged can only
125 // // be checked in the "canDropMimeData" function, ItemIsDropEnabled cannot be set since its conditional on the dragged item
126 // return defaultFlags | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
127 
128 // }
129 // return defaultFlags;
130  }
131 
133  {
134  QStringList types;
135  types << "pintreemodel/item";
136  return types;
137  }
138 
139  QMimeData* ModulePinsTreeModel::mimeData(const QModelIndexList& indexes) const
140  {
141  if (indexes.size() != 5) //columncount, only 1 item is allowed
142  return new QMimeData();
143 
144  QMimeData* data = new QMimeData();
145  PortTreeItem* item = static_cast<PortTreeItem*>(getItemFromIndex(indexes.at(0)));
146  QByteArray encodedData;
147  QDataStream stream(&encodedData, QIODevice::WriteOnly);
148  QString type = item->itemType() == PortTreeItem::Pin ? "pin" : "group";
149  stream << type << item->id();
150  data->setText(item->itemType() == PortTreeItem::Pin
151  ? PyCodeProvider::pyCodeModulePinById(mModule->get_id(),item->id())
152  : PyCodeProvider::pyCodeModulePinGroup(mModule->get_id(),item->id()));
153  data->setData("pintreemodel/item", encodedData);
154  return data;
155  }
156 
157  bool ModulePinsTreeModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
158  {
159  Q_UNUSED(action)
160  Q_UNUSED(column)
161 
162  QString type;
163  int id;
164  QByteArray encItem = data->data("pintreemodel/item");
165  QDataStream dataStream(&encItem, QIODevice::ReadOnly);
166 // debug pingroup qDebug() << "dropMimeData" << encItem << row << column;
167  dataStream >> type >> id;
168 
169  auto droppedItem = (type == "group") ? static_cast<PortTreeItem*>(mIdToGroupItem.value(id)) : static_cast<PortTreeItem*>(mIdToPinItem.value(id));
170  //auto droppedParentItem = droppedItem->getParent();
171  auto dropPositionItem = getItemFromIndex(parent);
172 
173  // perhaps helper functions?
174  // 1. group on group (between group)
175  // 2. pin on group
176  // 3. pin between groups
177  // 4. pin between pins
178 
179  // put ignore flags here? perhaps needed specifically in other places in functions..
180 
181  if(type == "group")
182  {
183  if(!dropPositionItem)
184  {
185 // debug pingroup qDebug() << "group was dropped between groups... with row: " << row; //check in canDropMine if its not an adjacent row?
186  dndGroupBetweenGroup(droppedItem, row);
187  }
188  else
189  {
190  PortTreeItem* pitem = dynamic_cast<PortTreeItem*>(dropPositionItem);
191  if (pitem && pitem->itemType() == PortTreeItem::Pin)
192  {
193  // debug pingroup qDebug() << "group was dropped on a pin...";
194  PortTreeItem* parentGroupItem = static_cast<PortTreeItem*>(pitem->getParent());
195  row = getIndexFromItem(pitem).row();
196  dndGroupOnGroup(droppedItem, parentGroupItem, row);
197  }
198  else
199  // debug pingroup qDebug() << "group was dropped on a group?";
200  dndGroupOnGroup(droppedItem, dropPositionItem);
201  }
202  }
203  else
204  {
205  if(!dropPositionItem)
206  {
207 // debug pingroup qDebug() << "pin was dropped between groups on row " << row;
208  dndPinBetweenGroup(droppedItem, row);
209  }
210  else if(row != -1)
211  {
212 // debug pingroup qDebug() << "pin was dropped between pins";
213  dndPinBetweenPin(droppedItem, dropPositionItem, row);
214  }
215  else
216  {
217  PortTreeItem* pitem = dynamic_cast<PortTreeItem*>(dropPositionItem);
218  if (pitem && pitem->itemType() == PortTreeItem::Pin)
219  {
220 // debug pingroup qDebug() << "pin was dropped on a pin...";
221  PortTreeItem* parentGroupItem = static_cast<PortTreeItem*>(pitem->getParent());
222  row = getIndexFromItem(pitem).row();
223  dndPinBetweenPin(droppedItem, parentGroupItem, row);
224  }
225  else
226 // debug pingroup qDebug() << "pin was dropped on a group...";
227  dndPinOnGroup(droppedItem, dropPositionItem);
228  }
229  }
230 
231  return true;
232  }
233 
234 
235  bool ModulePinsTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
236  {
237  Q_UNUSED(column)
238  Q_UNUSED(action)
239  if(!data->formats().contains("pintreemodel/item")) return false;
240 
241  QString type; int id;
242  auto encItem = data->data("pintreemodel/item");
243  QDataStream dataStream(&encItem, QIODevice::ReadOnly);
244  dataStream >> type >> id;
245  auto parentItem = static_cast<PortTreeItem*>(getItemFromIndex(parent));
246  // qDebug() << "type: " << type << ", id" << id << ", row: " << row;
247 
248  // construct a "drop-matrix" here, but only 4(5) things are NOT allowed (so check for these):
249  // 1: drop a pin on its OWN parent
250  // 3: drop a pingroup on/between pins
251  // 4: drop an item on itself
252  // 5: drop adjecent index to itself, must be at least 1 item apart
253  if(type == "group")
254  {
255  auto item = static_cast<PortTreeItem*>(mIdToGroupItem[id]);
256  if(parentItem)
257  {
258  if(item->itemType() == PortTreeItem::Pin || (item->itemType() == PortTreeItem::Group && row != -1) || item == parentItem)
259  return false;
260  }
261  else // here, only check for adjacent rows
262  {
263  auto itRow = item->getOwnRow();
264  if(itRow == row || ((itRow+1) == row))
265  return false;
266  }
267  }
268  if(type == "pin")
269  {
270  // perhaps check here that a pin can only be dropped between groups if its own group has size > 1?
271  // otherwise it does not make much sense...perhaps change this check
272  auto item = mIdToPinItem[id];
273  if((!parentItem && item->getParent()->getChildCount() == 1)
274  || (item->getParent() == parentItem && row == -1)
275  || item == parentItem )
276  // || (parentItem && (parentItem->itemType() == PortTreeItem::Pin)))
277  return false;
278  // case if one wants to drop between pins in same group, check if its not adjacent row (other cases are handled on case above
279  if(item->getParent() == parentItem)
280  {
281  auto itRow = item->getOwnRow();
282  if(itRow == row || ((itRow+1) == row))
283  return false;
284  }
285  }
286  return true;
287  }
288 
290  {
292  mModule = nullptr;
293  mNameToTreeItem.clear();
294  mIdToGroupItem.clear();
295  mIdToPinItem.clear();
296  }
297 
299  {
300  mModule = m;
301  beginResetModel();
302 
303  for(PinGroup<ModulePin>* pinGroup : m->get_pin_groups())
304  {
305  if(pinGroup->empty())
306  continue;
307 
308  auto pinGroupName = QString::fromStdString(pinGroup->get_name());
309  PortTreeItem* pinGroupItem = new PortTreeItem(PortTreeItem::Group, pinGroup->get_id(), pinGroupName, pinGroup->get_direction(),
310  pinGroup->get_type(), pinGroup->is_ascending() ? 0 : 1);
311  mIdToGroupItem.insert(pinGroup->get_id(), pinGroupItem);
312  for(ModulePin* pin : pinGroup->get_pins())
313  {
315  pin->get_id(),
316  QString::fromStdString(pin->get_name()),
317  pin->get_direction(),
318  pin->get_type(),
319  pin->get_group().second,
320  QString::fromStdString(pin->get_net()->get_name()));
321  pinGroupItem->appendChild(pinItem);
322  mNameToTreeItem.insert(QString::fromStdString(pin->get_name()), pinItem);
323  mIdToPinItem.insert(pin->get_id(), pinItem);
324  }
325  mNameToTreeItem.insert(pinGroupName, pinGroupItem);
326  mRootItem->appendChild(pinGroupItem);
327  }
328 
329 // for (PinGroup<ModulePin>* pinGroup : m->get_pin_groups())
330 // {
331 // //ignore empty pingroups
332 // if (pinGroup->empty())
333 // continue;
334 
335 
336 // ModulePin* firstPin = pinGroup->get_pins().front();
337 // QString pinGroupName;
338 // QString pinGroupDirection = QString::fromStdString(enum_to_string(firstPin->get_direction()));
339 // QString pinGroupType = QString::fromStdString(enum_to_string(firstPin->get_type()));
340 // if (pinGroup->size() == 1)
341 // {
342 // pinGroupName = QString::fromStdString(firstPin->get_name());
343 // }
344 // else
345 // {
346 // pinGroupName = QString::fromStdString(pinGroup->get_name());
347 // }
348 
349 // TreeItem* pinGroupItem = new TreeItem(QList<QVariant>() << pinGroupName << pinGroupDirection << pinGroupType << "");
350 
351 // if (pinGroup->size() == 1)
352 // {
353 // pinGroupItem->setDataAtIndex(sNetColumn, QString::fromStdString(firstPin->get_net()->get_name()));
354 // pinGroupItem->setAdditionalData(keyType, QVariant::fromValue(itemType::pin));
355 // //since a single-pin pingroup represents the pin itself, take the pinid
356 // pinGroupItem->setAdditionalData(keyId, firstPin->get_id());
357 // mIdToPinItem.insert(firstPin->get_id(), pinGroupItem);
358 // }
359 // else
360 // {
361 // pinGroupItem->setAdditionalData(keyType, QVariant::fromValue(itemType::portMultiBit));
362 // pinGroupItem->setAdditionalData(keyId, pinGroup->get_id());
363 // mIdToGroupItem.insert(pinGroup->get_id(), pinGroupItem);
364 // for (ModulePin* pin : pinGroup->get_pins())
365 // {
366 // TreeItem* pinItem =
367 // new TreeItem(QList<QVariant>() << QString::fromStdString(pin->get_name()) << pinGroupDirection << pinGroupType << QString::fromStdString(pin->get_net()->get_name()));
368 // pinItem->setAdditionalData(keyType, QVariant::fromValue(itemType::pin));
369 // pinItem->setAdditionalData(keyId, pin->get_id());
370 // pinGroupItem->appendChild(pinItem);
371 // mNameToTreeItem.insert(QString::fromStdString(pin->get_name()), pinItem);
372 // mIdToPinItem.insert(pin->get_id(), pinItem);
373 // }
374 // }
375 // mRootItem->appendChild(pinGroupItem);
376 // mNameToTreeItem.insert(pinGroupName, pinGroupItem);
377 // }
378  endResetModel();
379 
380  Q_EMIT numberOfPortsChanged(m->get_pins().size());
381  }
382 
384  {
385  if (!mModule) //no current module = no represented net
386  return nullptr;
387 
388  if (item->itemType() == PortTreeItem::Group && item->getChildCount() > 1)
389  return nullptr;
390 
391  Module* m = gNetlist->get_module_by_id(mModule->get_id());
392  if (!m)
393  return nullptr;
394 
395  //std::string name = item->getData(sNameColumn).toString().toStdString();
396  if (auto* pin = m->get_pin_by_id(item->id()); pin != nullptr)
397  {
398  return pin->get_net();
399  }
400 
401  return nullptr;
402  }
403 
405  {
406  if (!mModule) return -1;
407  return mModule->get_id();
408  }
409 
411  {
412  static const QSet<PinEvent> groupEvents = { PinEvent::GroupCreate,
418  Q_UNUSED(pev);
419  Q_UNUSED(pgid);
420  if (m != mModule) return;
421 
422  // debug pingroups log_info("gui", "Handle pin_changed event {} ID={}", enum_to_string<PinEvent>(pev), pgid);
423  PortTreeItem* ptiPin = nullptr;
424  PortTreeItem* ptiGroup = nullptr;
425  const PinGroup<ModulePin>* pgroup = nullptr;
426  const ModulePin* pin = nullptr;
427  int pinRow = -1;
428 
429 
430  if (groupEvents.contains(pev))
431  {
432  // group event
433  ptiGroup = mIdToGroupItem.value(pgid);
434  if (pev != PinEvent::GroupCreate && !ptiGroup)
435  {
436  log_warning("gui", "Cannot handle event for pin group ID={}, tree item does not exist.", pgid);
437  return;
438  }
439  if (pev != PinEvent::GroupDelete)
440  {
441  pgroup = m->get_pin_group_by_id(pgid);
442  if (!pgroup)
443  {
444  log_warning("gui", "Cannot handle event for pin group ID={}, no such group.", pgid);
445  return;
446  }
447  }
448  }
449  else
450  {
451  // pin event
452  ptiPin = mIdToPinItem.value(pgid);
453  if (pev != PinEvent::PinCreate && !ptiPin)
454  {
455  log_warning("gui", "Cannot handle event for pin ID={}, tree item does not exist.", pgid);
456  return;
457  }
458  if (pev != PinEvent::PinDelete)
459  {
460  pin = m->get_pin_by_id(pgid);
461  if (!pin)
462  {
463  log_warning("gui", "Cannot handle event for pin ID={}, no such pid.", pgid);
464  return;
465  }
466  auto pgPair = pin->get_group();
467  pgroup = pgPair.first;
468  pinRow = pinIndex2Row(pin,pgPair.second);
469  if (pgroup)
470  ptiGroup = mIdToGroupItem.value(pgroup->get_id());
471  }
472  }
473 
474  QModelIndex dataChangedIndex;
475 
476  switch (pev)
477  {
479  {
480  ptiGroup = new PortTreeItem(PortTreeItem::Group,
481  pgroup->get_id(),
482  QString::fromStdString(pgroup->get_name()),
483  pgroup->get_direction(),
484  pgroup->get_type(),
485  pgroup->is_ascending()?0:1);
486  mIdToGroupItem.insert(ptiGroup->id(), ptiGroup);
487  int inx = pinGroupIndex(m,pgroup);
488  insertItem(ptiGroup, mRootItem, inx);
489  break;
490  }
492  {
493  int inx = pinGroupIndex(m,pgroup);
494  removeItem(ptiGroup);
495  insertItem(ptiGroup, mRootItem, inx);
496  break;
497  }
499  ptiGroup->setName(QString::fromStdString(pgroup->get_name()));
500  dataChangedIndex = getIndexFromItem(ptiGroup);
501  break;
503  ptiGroup->setPinType(pgroup->get_type());
504  dataChangedIndex = getIndexFromItem(ptiGroup);
505  break;
507  ptiGroup->setPinDirection(pgroup->get_direction());
508  dataChangedIndex = getIndexFromItem(ptiGroup);
509  break;
511  removeItem(ptiGroup);
512  delete ptiGroup;
513  break;
514  case PinEvent::PinCreate:
515  {
516  if (!pgroup || !ptiGroup)
517  {
518  log_warning("gui", "Cannot handle pin create event for pin ID={}, pin is not assigned to any group.", pgid);
519  return;
520  }
521  QString netName;
522  if (pin->get_net())
523  netName = QString::fromStdString(pin->get_net()->get_name());
524  ptiPin = new PortTreeItem(PortTreeItem::Pin,
525  pin->get_id(),
527  pin->get_direction(),
528  pin->get_type(),
529  pin->get_group().second,
530  netName);
531  mIdToPinItem.insert(ptiPin->id(), ptiPin);
532  insertItem(ptiPin, ptiGroup, pinRow);
533  updateGroupIndex(ptiGroup);
534  break;
535  }
537  {
538  if (!pgroup || !ptiGroup)
539  {
540  log_warning("gui", "Cannot handle pin reorder event for pin ID={}, pin is not assigned to any group.", pgid);
541  return;
542  }
543  removeItem(ptiPin);
544  insertItem(ptiPin, ptiGroup, pinRow);
545  updateGroupIndex(ptiGroup);
546  break;
547  }
549  {
550  if (!pgroup || !ptiGroup)
551  {
552  log_warning("gui", "Cannot handle pin assign event for pin ID={}, pin is not assigned to any group.", pgid);
553  return;
554  }
555  removeItem(ptiPin);
556  insertItem(ptiPin, ptiGroup, pinRow);
557  updateGroupIndex(ptiGroup);
558  break;
559  }
560  case PinEvent::PinRename:
561  ptiPin->setName(QString::fromStdString(pin->get_name()));
562  dataChangedIndex = getIndexFromItem(ptiPin);
563  break;
565  ptiPin->setPinType(pin->get_type());
566  dataChangedIndex = getIndexFromItem(ptiPin);
567  break;
569  ptiPin->setPinDirection(pin->get_direction());
570  dataChangedIndex = getIndexFromItem(ptiPin);
571  break;
572  case PinEvent::PinDelete:
573  removeItem(ptiPin);
574  delete ptiPin;
575  break;
576  default:
577  break;
578  }
579 
580  if (dataChangedIndex.isValid())
581  {
582  QModelIndex inxLastCol = createIndex(dataChangedIndex.row(),columnCount()-1,dataChangedIndex.internalPointer());
583  Q_EMIT dataChanged(dataChangedIndex,inxLastCol);
584  }
585  }
586 
587  void ModulePinsTreeModel::dndGroupOnGroup(BaseTreeItem *droppedGroup, BaseTreeItem *onDroppedGroup, int row)
588  {
589  // SPECIFY: 1) create completely new group, all pins in that, delete old 2 groups
590  // 2) just add all pins from dropped group to "ondroppedgroup", then rename?
591 // InputDialog ipd("Name of new group", "Name of new group:", onDroppedGroup->getData(sNameColumn).toString());
592 // if(ipd.exec() == QDialog::Rejected) return false;
594  auto srcgroup = mModule->get_pin_group_by_id(static_cast<PortTreeItem*>(droppedGroup)->id());
595  for(const auto &pin : srcgroup->get_pins())
596  pins.append(pin->get_id());
597  if (pins.isEmpty()) return; // no pins to move
598 
599  auto tgtgroup = mModule->get_pin_group_by_id(static_cast<PortTreeItem*>(onDroppedGroup)->id());
600 
601  ActionPingroup* act = ActionPingroup::addPinsToExistingGroup(mModule,tgtgroup->get_id(),pins,row);
602  if (act) act->exec();
603 
604  // too keep the order, ActionAddItemsToObject cannot be executed with all pins, but a ComAction must be created
605  // with many ActionAddItemsToObject that contain a single pin each -> set destroys order of pins in source pingroup
606  }
607 
608  void ModulePinsTreeModel::dndGroupBetweenGroup(PortTreeItem *droppedGroup, int row)
609  {
610  int ownRow = droppedGroup->getOwnRow();
611  bool bottomEdge = row == mRootItem->getChildCount();
612  auto desiredIdx = bottomEdge ? row-1 : row;
613  if(ownRow < row && !bottomEdge) desiredIdx--;
614  ActionPingroup* act = new ActionPingroup(PinActionType::GroupMoveToRow,droppedGroup->id(),"",desiredIdx);
615  act->setObject(UserActionObject(mModule->get_id(),UserActionObjectType::Module));
616  act->exec();
617  }
618 
619  void ModulePinsTreeModel::dndPinOnGroup(PortTreeItem *droppedPin, BaseTreeItem *onDroppedGroup)
620  {
621  ActionPingroup* act = new ActionPingroup(PinActionType::PinAsignToGroup,droppedPin->id(),"",static_cast<PortTreeItem*>(onDroppedGroup)->id());
622  act->setObject(UserActionObject(mModule->get_id(),UserActionObjectType::Module));
623  act->exec();
624  }
625 
626  void ModulePinsTreeModel::dndPinBetweenPin(PortTreeItem *droppedPin, BaseTreeItem *onDroppedParent, int row)
627  {
628  int desiredIdx = row;
629  ActionPingroup* act = nullptr;
630  if(droppedPin->getParent() == onDroppedParent) // same group
631  {
632  int ownRow = droppedPin->getOwnRow();
633  bool bottomEdge = row == onDroppedParent->getChildCount();
634  desiredIdx = bottomEdge ? row-1 : row;
635  if(ownRow < row && !bottomEdge) desiredIdx--; // insert item here
636  act = new ActionPingroup(PinActionType::PinMoveToRow,droppedPin->id(),"",desiredIdx); // TODO : start_index, descending
637  }
638  else
639  {
640  act = ActionPingroup::addPinToExistingGroup(mModule,static_cast<PortTreeItem*>(onDroppedParent)->id(),droppedPin->id(),desiredIdx);
641  if (!act) return;
642  }
643  act->setObject(UserActionObject(mModule->get_id(),UserActionObjectType::Module));
644  act->exec();
645  }
646 
647  void ModulePinsTreeModel::dndPinBetweenGroup(PortTreeItem *droppedPin, int row)
648  {
649  // row is needed for when groups can change its order within the module
650  Q_UNUSED(row)
651 
652  auto pinToMove = mModule->get_pin_by_id(droppedPin->id());
653  if (!pinToMove) return;
654 
655  QString groupName = generateGroupName(mModule,pinToMove);
656 
657  ActionPingroup* act = ActionPingroup::addPinToNewGroup(mModule, groupName, droppedPin->id(),row);
658  act->exec();
659  }
660 
661  void ModulePinsTreeModel::updateGroupIndex(PortTreeItem* groupItem)
662  {
663  PinGroup<ModulePin>* pg = mModule->get_pin_group_by_id(groupItem->id());
664  Q_ASSERT(pg);
665  for (ModulePin* pin : pg->get_pins())
666  {
667  int inx = pg->get_index(pin).get();
668  PortTreeItem* pinItem = mIdToPinItem.value(pin->get_id());
669  Q_ASSERT(pinItem);
670  pinItem->setIndex(inx);
671  }
672  QModelIndex pi = getIndexFromItem(groupItem);
673  QModelIndex i0 = index(0,0,pi);
674  QModelIndex i1 = index(groupItem->getChildCount()-1,4,pi);
675  Q_EMIT dataChanged(i0,i1);
676  }
677 
678  void ModulePinsTreeModel::insertItem(PortTreeItem* item, BaseTreeItem* parent, int index)
679  {
680  // fun fact: if an item is inserted above an item that is expanded, the tree collapses all indeces
682  parent->insertChild(index, item);
683  endInsertRows();
684  //mNameToTreeItem.insert(item->getData(sNameColumn).toString(), item);
685  item->itemType() == PortTreeItem::Pin ? mIdToPinItem.insert(item->id(), item) : mIdToGroupItem.insert(item->id(), item);
686  //mIdToPinItem.insert(getIdOfItem(item), item);
687  }
688 
689  void ModulePinsTreeModel::removeItem(PortTreeItem* item)
690  {
691  beginRemoveRows(parent(getIndexFromItem(item)), item->getOwnRow(), item->getOwnRow());
692  item->getParent()->removeChild(item);
693  endRemoveRows();
694  //mNameToTreeItem.remove(item->getData(sNameColumn).toString());
695  //for now, only ids of pin-items (since these functions are only relevant for dnd)
696  item->itemType() == PortTreeItem::Pin ? mIdToPinItem.remove(item->id()) : mIdToGroupItem.remove(item->id());
697  //mIdToPinItem.remove(getIdOfItem(item));
698  //delete item;
699  }
700 
701 
702 
703 } // namespace hal
Pingroup user actions.
static ActionPingroup * addPinToNewGroup(const Module *m, const QString &name, u32 pinId, int grpRow=-1)
static ActionPingroup * addPinToExistingGroup(const Module *m, u32 grpId, u32 pinId, int pinRow=-1)
static ActionPingroup * addPinsToExistingGroup(const Module *m, u32 grpId, QList< u32 > pinIds, int pinRow=-1)
bool exec() override
const std::string & get_name() const
Definition: base_pin.h:108
u32 get_id() const
Definition: base_pin.h:88
PinType get_type() const
Definition: base_pin.h:148
const std::pair< PinGroup< T > *, i32 > & get_group() const
Definition: base_pin.h:158
PinDirection get_direction() const
Definition: base_pin.h:128
(Future) Base class for all tree models related to the details widget.
virtual BaseTreeItem * getParent() const
virtual int getChildCount() const
virtual void appendChild(BaseTreeItem *child)
virtual int getOwnRow()
The BaseTreeModel implements generic standard functions of a tree model.
QModelIndex getIndexFromItem(BaseTreeItem *item) const
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const override
RootTreeItem * mRootItem
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
virtual void clear()
virtual Qt::ItemFlags flags(const QModelIndex &index) const override
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
void setHeaderLabels(const QStringList &label)
BaseTreeItem * getItemFromIndex(QModelIndex index) const
std::vector< ModulePin * > get_pins(const std::function< bool(ModulePin *)> &filter=nullptr) const
Definition: module.cpp:873
ModulePin * get_pin_by_id(const u32 id) const
Definition: module.cpp:985
std::vector< PinGroup< ModulePin > * > get_pin_groups(const std::function< bool(PinGroup< ModulePin > *)> &filter=nullptr) const
Definition: module.cpp:964
PinGroup< ModulePin > * get_pin_group_by_id(const u32 id) const
Definition: module.cpp:1036
u32 get_id() const
Definition: module.cpp:82
Net * get_net() const
Definition: module_pin.cpp:19
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override
ModulePinsTreeModel(QObject *parent=nullptr)
QStringList mimeTypes() const override
Net * getNetFromItem(PortTreeItem *item)
QMimeData * mimeData(const QModelIndexList &indexes) const override
void handleModulePortsChanged(Module *m, PinEvent pev, u32 pgid)
Qt::ItemFlags flags(const QModelIndex &index) const override
void numberOfPortsChanged(const int newNumber)
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
Definition: net.h:58
const std::string & get_name() const
Definition: net.cpp:98
Module * get_module_by_id(u32 module_id) const
Definition: netlist.cpp:613
void modulePortsChanged(Module *m, PinEvent pev, u32 pgid) const
u32 get_id() const
Definition: pin_group.h:130
const std::string & get_name() const
Definition: pin_group.h:150
bool is_ascending() const
Definition: pin_group.h:273
PinDirection get_direction() const
Definition: pin_group.h:190
PinType get_type() const
Definition: pin_group.h:170
void setPinDirection(PinDirection dir)
void setPinType(PinType ptype)
void appendData(QVariant data) override
void setDataAtIndex(int index, QVariant &data) override
void setData(QList< QVariant > data) override
int getColumnCount() const override
void setName(const QString &nam)
Type itemType() const
QVariant getData(int column) const override
static QString pyCodeModulePinGroup(u32 moduleId, u32 groupId)
static QString pyCodeModulePinById(u32 moduleId, u32 pinId)
#define log_warning(channel,...)
Definition: log.h:76
action
Definition: control.py:16
PinDirection
Definition: pin_direction.h:36
int pinGroupIndex(const Module *mod, const PinGroup< ModulePin > *pgrp)
PinEvent
Definition: pin_event.h:42
@ PinTypeChange
pin renamed
@ GroupReorder
changed PinDirection attribute of group (like input)
@ PinDirChange
changed PinType attribute of pin (like data)
@ PinCreate
moved group to a new position within containing module
@ GroupTypeChange
pin group renamed
@ PinRename
pin assigned to new group
@ PinAssignToGroup
new pin created
@ PinDelete
moved pin to a new position within containing group
@ GroupRename
new pin group created
@ GroupDelete
pin deleted
@ GroupDirChange
changed PinType attribute of group (like data)
@ PinReorder
changed PinDirection attribute of pin (like input)
int pinIndex2Row(const ModulePin *pin, int index)
Netlist * gNetlist
Definition: plugin_gui.cpp:80
NetlistRelay * gNetlistRelay
Definition: plugin_gui.cpp:81
PinType
Definition: pin_type.h:36
QString generateGroupName(const Module *mod, const ModulePin *pin)
std::string enum_to_string(T e)
Definition: enums.h:52
quint32 u32
PinType type
std::vector< PinInformation > pins
i32 id
void beginInsertRows(const QModelIndex &parent, int first, int last)
void beginRemoveRows(const QModelIndex &parent, int first, int last)
QModelIndex createIndex(int row, int column, void *ptr) const const
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles)
void * internalPointer() const const
bool isValid() const const
int row() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
bool contains(const T &value) const const
QString fromStdString(const std::string &str)
DropAction
typedef ItemFlags