HAL
module_pins_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  ModulePinsTreeItem::ModulePinsTreeItem(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==ModulePinsTreeItem::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 
53  {
54  switch (column)
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  ModulePinsTreeItem* item = static_cast<ModulePinsTreeItem*>(getItemFromIndex(indexes.at(0)));
146  QByteArray encodedData;
147  QDataStream stream(&encodedData, QIODevice::WriteOnly);
148  QString type = item->itemType() == ModulePinsTreeItem::Pin ? "pin" : "group";
149  stream << type << item->id();
150  data->setText(item->itemType() == ModulePinsTreeItem::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<ModulePinsTreeItem*>(mIdToGroupItem.value(id)) : static_cast<ModulePinsTreeItem*>(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  ModulePinsTreeItem* pitem = dynamic_cast<ModulePinsTreeItem*>(dropPositionItem);
191  if (pitem && pitem->itemType() == ModulePinsTreeItem::Pin)
192  {
193  // debug pingroup qDebug() << "group was dropped on a pin...";
194  ModulePinsTreeItem* parentGroupItem = static_cast<ModulePinsTreeItem*>(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  ModulePinsTreeItem* pitem = dynamic_cast<ModulePinsTreeItem*>(dropPositionItem);
218  if (pitem && pitem->itemType() == ModulePinsTreeItem::Pin)
219  {
220 // debug pingroup qDebug() << "pin was dropped on a pin...";
221  ModulePinsTreeItem* parentGroupItem = static_cast<ModulePinsTreeItem*>(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<ModulePinsTreeItem*>(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<ModulePinsTreeItem*>(mIdToGroupItem[id]);
256  if(parentItem)
257  {
258  if(item->itemType() == ModulePinsTreeItem::Pin || (item->itemType() == ModulePinsTreeItem::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  ModulePinsTreeItem* pinGroupItem = new ModulePinsTreeItem(ModulePinsTreeItem::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 // Keep old code for the time being to review whether all cases are covered
330 //
331 // for (PinGroup<ModulePin>* pinGroup : m->get_pin_groups())
332 // {
333 // //ignore empty pingroups
334 // if (pinGroup->empty())
335 // continue;
336 
337 
338 // ModulePin* firstPin = pinGroup->get_pins().front();
339 // QString pinGroupName;
340 // QString pinGroupDirection = QString::fromStdString(enum_to_string(firstPin->get_direction()));
341 // QString pinGroupType = QString::fromStdString(enum_to_string(firstPin->get_type()));
342 // if (pinGroup->size() == 1)
343 // {
344 // pinGroupName = QString::fromStdString(firstPin->get_name());
345 // }
346 // else
347 // {
348 // pinGroupName = QString::fromStdString(pinGroup->get_name());
349 // }
350 
351 // TreeItem* pinGroupItem = new TreeItem(QList<QVariant>() << pinGroupName << pinGroupDirection << pinGroupType << "");
352 
353 // if (pinGroup->size() == 1)
354 // {
355 // pinGroupItem->setDataAtColumn(sNetColumn, QString::fromStdString(firstPin->get_net()->get_name()));
356 // pinGroupItem->setAdditionalData(keyType, QVariant::fromValue(itemType::pin));
357 // //since a single-pin pingroup represents the pin itself, take the pinid
358 // pinGroupItem->setAdditionalData(keyId, firstPin->get_id());
359 // mIdToPinItem.insert(firstPin->get_id(), pinGroupItem);
360 // }
361 // else
362 // {
363 // pinGroupItem->setAdditionalData(keyType, QVariant::fromValue(itemType::portMultiBit));
364 // pinGroupItem->setAdditionalData(keyId, pinGroup->get_id());
365 // mIdToGroupItem.insert(pinGroup->get_id(), pinGroupItem);
366 // for (ModulePin* pin : pinGroup->get_pins())
367 // {
368 // TreeItem* pinItem =
369 // new TreeItem(QList<QVariant>() << QString::fromStdString(pin->get_name()) << pinGroupDirection << pinGroupType << QString::fromStdString(pin->get_net()->get_name()));
370 // pinItem->setAdditionalData(keyType, QVariant::fromValue(itemType::pin));
371 // pinItem->setAdditionalData(keyId, pin->get_id());
372 // pinGroupItem->appendChild(pinItem);
373 // mNameToTreeItem.insert(QString::fromStdString(pin->get_name()), pinItem);
374 // mIdToPinItem.insert(pin->get_id(), pinItem);
375 // }
376 // }
377 // mRootItem->appendChild(pinGroupItem);
378 // mNameToTreeItem.insert(pinGroupName, pinGroupItem);
379 // }
380  endResetModel();
381 
382  Q_EMIT numberOfPortsChanged(m->get_pins().size());
383  }
384 
386  {
387  if (!mModule) //no current module = no represented net
388  return nullptr;
389 
390  if (item->itemType() == ModulePinsTreeItem::Group && item->getChildCount() > 1)
391  return nullptr;
392 
393  Module* m = gNetlist->get_module_by_id(mModule->get_id());
394  if (!m)
395  return nullptr;
396 
397  //std::string name = item->getData(sNameColumn).toString().toStdString();
398  if (auto* pin = m->get_pin_by_id(item->id()); pin != nullptr)
399  {
400  return pin->get_net();
401  }
402 
403  return nullptr;
404  }
405 
407  {
408  if (!mModule) return -1;
409  return mModule->get_id();
410  }
411 
413  {
414  static const QSet<PinEvent> groupEvents = { PinEvent::GroupCreate,
420  Q_UNUSED(pev);
421  Q_UNUSED(pgid);
422  if (m != mModule) return;
423 
424  // debug pingroups log_info("gui", "Handle pin_changed event {} ID={}", enum_to_string<PinEvent>(pev), pgid);
425  ModulePinsTreeItem* ptiPin = nullptr;
426  ModulePinsTreeItem* ptiGroup = nullptr;
427  const PinGroup<ModulePin>* pgroup = nullptr;
428  const ModulePin* pin = nullptr;
429  int pinRow = -1;
430 
431 
432  if (groupEvents.contains(pev))
433  {
434  // group event
435  ptiGroup = mIdToGroupItem.value(pgid);
436  if (pev != PinEvent::GroupCreate && !ptiGroup)
437  {
438  log_warning("gui", "Cannot handle event for pin group ID={}, tree item does not exist.", pgid);
439  return;
440  }
441  if (pev != PinEvent::GroupDelete)
442  {
443  pgroup = m->get_pin_group_by_id(pgid);
444  if (!pgroup)
445  {
446  log_warning("gui", "Cannot handle event for pin group ID={}, no such group.", pgid);
447  return;
448  }
449  }
450  }
451  else
452  {
453  // pin event
454  ptiPin = mIdToPinItem.value(pgid);
455  if (pev != PinEvent::PinCreate && !ptiPin)
456  {
457  log_warning("gui", "Cannot handle event for pin ID={}, tree item does not exist.", pgid);
458  return;
459  }
460  if (pev != PinEvent::PinDelete)
461  {
462  pin = m->get_pin_by_id(pgid);
463  if (!pin)
464  {
465  log_warning("gui", "Cannot handle event for pin ID={}, no such pid.", pgid);
466  return;
467  }
468  auto pgPair = pin->get_group();
469  pgroup = pgPair.first;
470  pinRow = ActionPingroup::pinIndex2Row(pin,pgPair.second);
471  if (pgroup)
472  ptiGroup = mIdToGroupItem.value(pgroup->get_id());
473  }
474  }
475 
476  QModelIndex dataChangedIndex;
477 
478  switch (pev)
479  {
481  {
483  pgroup->get_id(),
484  QString::fromStdString(pgroup->get_name()),
485  pgroup->get_direction(),
486  pgroup->get_type(),
487  pgroup->is_ascending()?0:1);
488  mIdToGroupItem.insert(ptiGroup->id(), ptiGroup);
489  int inx = ActionPingroup::pinGroupIndex(m,pgroup);
490  insertItem(ptiGroup, mRootItem, inx);
491  break;
492  }
494  {
495  int inx = ActionPingroup::pinGroupIndex(m,pgroup);
496  removeItem(ptiGroup);
497  insertItem(ptiGroup, mRootItem, inx);
498  break;
499  }
501  ptiGroup->setName(QString::fromStdString(pgroup->get_name()));
502  dataChangedIndex = getIndexFromItem(ptiGroup);
503  break;
505  ptiGroup->setPinType(pgroup->get_type());
506  dataChangedIndex = getIndexFromItem(ptiGroup);
507  break;
509  ptiGroup->setPinDirection(pgroup->get_direction());
510  dataChangedIndex = getIndexFromItem(ptiGroup);
511  break;
513  removeItem(ptiGroup);
514  delete ptiGroup;
515  break;
516  case PinEvent::PinCreate:
517  {
518  if (!pgroup || !ptiGroup)
519  {
520  log_warning("gui", "Cannot handle pin create event for pin ID={}, pin is not assigned to any group.", pgid);
521  return;
522  }
523  QString netName;
524  if (pin->get_net())
525  netName = QString::fromStdString(pin->get_net()->get_name());
527  pin->get_id(),
529  pin->get_direction(),
530  pin->get_type(),
531  pin->get_group().second,
532  netName);
533  mIdToPinItem.insert(ptiPin->id(), ptiPin);
534  insertItem(ptiPin, ptiGroup, pinRow);
535  updateGroupIndex(ptiGroup);
536  break;
537  }
539  {
540  if (!pgroup || !ptiGroup)
541  {
542  log_warning("gui", "Cannot handle pin reorder event for pin ID={}, pin is not assigned to any group.", pgid);
543  return;
544  }
545  removeItem(ptiPin);
546  insertItem(ptiPin, ptiGroup, pinRow);
547  updateGroupIndex(ptiGroup);
548  break;
549  }
551  {
552  if (!pgroup || !ptiGroup)
553  {
554  log_warning("gui", "Cannot handle pin assign event for pin ID={}, pin is not assigned to any group.", pgid);
555  return;
556  }
557  removeItem(ptiPin);
558  insertItem(ptiPin, ptiGroup, pinRow);
559 
560  // Unfortunately the event does not tell us where the pin was assigned previously. We have to update all group indices.
561  for (BaseTreeItem* bti : mRootItem->getChildren())
562  {
563  ModulePinsTreeItem* grpItem = static_cast<ModulePinsTreeItem*>(bti);
564  // check whether group still exists (might have been deleted when moving last pin)
565  if (mModule->get_pin_group_by_id(grpItem->id()))
566  updateGroupIndex(static_cast<ModulePinsTreeItem*>(grpItem));
567  }
568  break;
569  }
570  case PinEvent::PinRename:
571  ptiPin->setName(QString::fromStdString(pin->get_name()));
572  dataChangedIndex = getIndexFromItem(ptiPin);
573  break;
575  ptiPin->setPinType(pin->get_type());
576  dataChangedIndex = getIndexFromItem(ptiPin);
577  break;
579  ptiPin->setPinDirection(pin->get_direction());
580  dataChangedIndex = getIndexFromItem(ptiPin);
581  break;
582  case PinEvent::PinDelete:
583  removeItem(ptiPin);
584  delete ptiPin;
585  break;
586  default:
587  break;
588  }
589 
590  if (dataChangedIndex.isValid())
591  {
592  QModelIndex inxLastCol = createIndex(dataChangedIndex.row(),columnCount()-1,dataChangedIndex.internalPointer());
593  Q_EMIT dataChanged(dataChangedIndex,inxLastCol);
594  }
595  }
596 
597  void ModulePinsTreeModel::dndGroupOnGroup(BaseTreeItem *droppedGroup, BaseTreeItem *onDroppedGroup, int row)
598  {
599  // SPECIFY: 1) create completely new group, all pins in that, delete old 2 groups
600  // 2) just add all pins from dropped group to "ondroppedgroup", then rename?
601 // InputDialog ipd("Name of new group", "Name of new group:", onDroppedGroup->getData(sNameColumn).toString());
602 // if(ipd.exec() == QDialog::Rejected) return false;
604  auto srcgroup = mModule->get_pin_group_by_id(static_cast<ModulePinsTreeItem*>(droppedGroup)->id());
605  for(const auto &pin : srcgroup->get_pins())
606  pins.append(pin->get_id());
607  if (pins.isEmpty()) return; // no pins to move
608 
609  auto tgtgroup = mModule->get_pin_group_by_id(static_cast<ModulePinsTreeItem*>(onDroppedGroup)->id());
610 
611  ActionPingroup* act = ActionPingroup::addPinsToExistingGroup(mModule,tgtgroup->get_id(),pins,row);
612  if (act) act->exec();
613 
614  // too keep the order, ActionAddItemsToObject cannot be executed with all pins, but a ComAction must be created
615  // with many ActionAddItemsToObject that contain a single pin each -> set destroys order of pins in source pingroup
616  }
617 
618  void ModulePinsTreeModel::dndGroupBetweenGroup(ModulePinsTreeItem *droppedGroup, int row)
619  {
620  int ownRow = droppedGroup->getOwnRow();
621  bool bottomEdge = row == mRootItem->getChildCount();
622  auto desiredIdx = bottomEdge ? row-1 : row;
623  if(ownRow < row && !bottomEdge) desiredIdx--;
624  ActionPingroup* act = new ActionPingroup(PinActionType::GroupMoveToRow,droppedGroup->id(),"",desiredIdx);
625  act->setObject(UserActionObject(mModule->get_id(),UserActionObjectType::Module));
626  act->exec();
627  }
628 
629  void ModulePinsTreeModel::dndPinOnGroup(ModulePinsTreeItem *droppedPin, BaseTreeItem *onDroppedGroup)
630  {
631  ActionPingroup* act = new ActionPingroup(PinActionType::PinAsignToGroup,droppedPin->id(),"",static_cast<ModulePinsTreeItem*>(onDroppedGroup)->id());
632  act->setObject(UserActionObject(mModule->get_id(),UserActionObjectType::Module));
633  act->exec();
634  }
635 
636  void ModulePinsTreeModel::dndPinBetweenPin(ModulePinsTreeItem *droppedPin, BaseTreeItem *onDroppedParent, int row)
637  {
638  int desiredIdx = row;
639  ActionPingroup* act = nullptr;
640  if(droppedPin->getParent() == onDroppedParent) // same group
641  {
642  int ownRow = droppedPin->getOwnRow();
643  bool bottomEdge = row == onDroppedParent->getChildCount();
644  desiredIdx = bottomEdge ? row-1 : row;
645  if(ownRow < row && !bottomEdge) desiredIdx--; // insert item here
646  act = new ActionPingroup(PinActionType::PinMoveToRow,droppedPin->id(),"",desiredIdx); // TODO : start_index, descending
647  }
648  else
649  {
650  act = ActionPingroup::addPinToExistingGroup(mModule,static_cast<ModulePinsTreeItem*>(onDroppedParent)->id(),droppedPin->id(),desiredIdx);
651  if (!act) return;
652  }
653  act->setObject(UserActionObject(mModule->get_id(),UserActionObjectType::Module));
654  act->exec();
655  }
656 
657  void ModulePinsTreeModel::dndPinBetweenGroup(ModulePinsTreeItem *droppedPin, int row)
658  {
659  // row is needed for when groups can change its order within the module
660  Q_UNUSED(row)
661 
662  auto pinToMove = mModule->get_pin_by_id(droppedPin->id());
663  if (!pinToMove) return;
664 
665  QString groupName = ActionPingroup::generateGroupName(mModule,pinToMove);
666 
667  ActionPingroup* act = ActionPingroup::addPinToNewGroup(mModule, groupName, droppedPin->id(),row);
668  act->exec();
669  }
670 
671  void ModulePinsTreeModel::updateGroupIndex(ModulePinsTreeItem* groupItem)
672  {
673  PinGroup<ModulePin>* pg = mModule->get_pin_group_by_id(groupItem->id());
674  Q_ASSERT(pg);
675  for (ModulePin* pin : pg->get_pins())
676  {
677  int inx = pg->get_index(pin).get();
678  ModulePinsTreeItem* pinItem = mIdToPinItem.value(pin->get_id());
679  Q_ASSERT(pinItem);
680  pinItem->setIndex(inx);
681  }
682  QModelIndex pi = getIndexFromItem(groupItem);
683  QModelIndex i0 = index(0,0,pi);
684  QModelIndex i1 = index(groupItem->getChildCount()-1,4,pi);
685  Q_EMIT dataChanged(i0,i1);
686  }
687 
688  void ModulePinsTreeModel::insertItem(ModulePinsTreeItem* item, BaseTreeItem* parent, int index)
689  {
690  // fun fact: if an item is inserted above an item that is expanded, the tree collapses all indeces
692  parent->insertChild(index, item);
693  endInsertRows();
694  //mNameToTreeItem.insert(item->getData(sNameColumn).toString(), item);
695  item->itemType() == ModulePinsTreeItem::Pin ? mIdToPinItem.insert(item->id(), item) : mIdToGroupItem.insert(item->id(), item);
696  //mIdToPinItem.insert(getIdOfItem(item), item);
697  }
698 
699  void ModulePinsTreeModel::removeItem(ModulePinsTreeItem* item)
700  {
701  beginRemoveRows(parent(getIndexFromItem(item)), item->getOwnRow(), item->getOwnRow());
702  item->getParent()->removeChild(item);
703  endRemoveRows();
704  //mNameToTreeItem.remove(item->getData(sNameColumn).toString());
705  //for now, only ids of pin-items (since these functions are only relevant for dnd)
706  item->itemType() == ModulePinsTreeItem::Pin ? mIdToPinItem.remove(item->id()) : mIdToGroupItem.remove(item->id());
707  //mIdToPinItem.remove(getIdOfItem(item));
708  //delete item;
709  }
710 
711 
712 
713 } // namespace hal
Pingroup user actions.
static ActionPingroup * addPinToNewGroup(const Module *m, const QString &name, u32 pinId, int grpRow=-1)
static QString generateGroupName(const Module *mod, const ModulePin *pin)
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)
static int pinGroupIndex(const Module *mod, const PinGroup< ModulePin > *pgrp)
static int pinIndex2Row(const ModulePin *pin, int index)
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 QList< BaseTreeItem * > getChildren() const
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
void setPinType(PinType ptype)
void setName(const QString &nam)
QVariant getData(int column) const override
void setPinDirection(PinDirection dir)
int getColumnCount() const override
void setData(QList< QVariant > data) override
void setDataAtColumn(int column, QVariant &data) override
void appendData(QVariant data) override
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
QMimeData * mimeData(const QModelIndexList &indexes) const override
void handleModulePortsChanged(Module *m, PinEvent pev, u32 pgid)
Qt::ItemFlags flags(const QModelIndex &index) const override
Net * getNetFromItem(ModulePinsTreeItem *item)
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
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
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)
Netlist * gNetlist
Definition: plugin_gui.cpp:80
NetlistRelay * gNetlistRelay
Definition: plugin_gui.cpp:81
PinType
Definition: pin_type.h:36
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