HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
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  if (mItemType==ModulePinsTreeItem::Group)
30  return (QString("[%1] %2").arg(getChildCount()).arg(mIndex ? QChar(0x2193) : QChar(0x2191)));
31  return mIndex;
32  case 2:
33  return QString::fromStdString(enum_to_string(mPinDirection));
34  case 3:
35  return QString::fromStdString(enum_to_string(mPinType));
36  case 4:
37  return mNetName;
38  }
39  return QVariant();
40  }
41 
43  {
44  Q_ASSERT(data.size() >= 5);
45  mPinName = data[0].toString();
46  mIndex = data[1].toInt();
47  mPinDirection = enum_from_string<PinDirection>(data[2].toString().toStdString());
48  mPinType = enum_from_string<PinType>(data[3].toString().toStdString());
49  mNetName = data[4].toString();
50  }
51 
53  {
54  switch (column)
55  {
56  case 0:
57  mPinName = data.toString();
58  break;
59  case 1:
60  mIndex = data.toInt();
61  break;
62  case 2:
63  mPinDirection = enum_from_string<PinDirection>(data.toString().toStdString());
64  break;
65  case 3:
66  mPinType = enum_from_string<PinType>(data.toString().toStdString());
67  break;
68  case 4:
69  mNetName = data.toString();
70  break;
71  }
72  }
73 
75  {
76  Q_UNUSED(data)
77  }
78 
80  {
81  return 5;
82  }
83 
85  {
86  setHeaderLabels(QStringList() << "Name "
87  << "Size/Index"
88  << "Direction"
89  << "Type"
90  << "Connected Net");
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 
132  QModelIndex ModulePinsTreeModel::getIndexFromPinsItem(ModulePinsTreeItem *item) const
133  {
134  if (mOrphanedItem.contains(item)) return QModelIndex();
135  return getIndexFromItem(item);
136  }
137 
138 
140  {
141  QStringList types;
142  types << "pintreemodel/item";
143  return types;
144  }
145 
146  QMimeData* ModulePinsTreeModel::mimeData(const QModelIndexList& indexes) const
147  {
148  if (indexes.size() != 5) //columncount, only 1 item is allowed
149  return new QMimeData();
150 
151  QMimeData* data = new QMimeData();
152  ModulePinsTreeItem* item = static_cast<ModulePinsTreeItem*>(getItemFromIndex(indexes.at(0)));
153  QByteArray encodedData;
154  QDataStream stream(&encodedData, QIODevice::WriteOnly);
155  QString type = item->itemType() == ModulePinsTreeItem::Pin ? "pin" : "group";
156  stream << type << item->id();
157  data->setText(item->itemType() == ModulePinsTreeItem::Pin
158  ? PyCodeProvider::pyCodeModulePinById(mModule->get_id(),item->id())
159  : PyCodeProvider::pyCodeModulePinGroup(mModule->get_id(),item->id()));
160  data->setData("pintreemodel/item", encodedData);
161  return data;
162  }
163 
164  bool ModulePinsTreeModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
165  {
166  Q_UNUSED(action)
167  Q_UNUSED(column)
168 
169  QString type;
170  int id;
171  QByteArray encItem = data->data("pintreemodel/item");
172  QDataStream dataStream(&encItem, QIODevice::ReadOnly);
173 // debug pingroup qDebug() << "dropMimeData" << encItem << row << column;
174  dataStream >> type >> id;
175 
176  auto droppedItem = (type == "group") ? static_cast<ModulePinsTreeItem*>(mIdToGroupItem.value(id)) : static_cast<ModulePinsTreeItem*>(mIdToPinItem.value(id));
177  //auto droppedParentItem = droppedItem->getParent();
178  auto dropPositionItem = getItemFromIndex(parent);
179 
180  // perhaps helper functions?
181  // 1. group on group (between group)
182  // 2. pin on group
183  // 3. pin between groups
184  // 4. pin between pins
185 
186  // put ignore flags here? perhaps needed specifically in other places in functions..
187  if(type == "group")
188  {
189  if(!dropPositionItem)
190  {
191 // debug pingroup qDebug() << "group was dropped between groups... with row: " << row; //check in canDropMine if its not an adjacent row?
192  dndGroupBetweenGroup(droppedItem, row);
193  }
194  else
195  {
196  ModulePinsTreeItem* pitem = dynamic_cast<ModulePinsTreeItem*>(dropPositionItem);
197  if (pitem && pitem->itemType() == ModulePinsTreeItem::Pin)
198  {
199  // debug pingroup qDebug() << "group was dropped on a pin...";
200  ModulePinsTreeItem* parentGroupItem = static_cast<ModulePinsTreeItem*>(pitem->getParent());
201  row = getIndexFromPinsItem(pitem).row();
202  dndGroupOnGroup(droppedItem, parentGroupItem, row);
203  }
204  else
205  // debug pingroup qDebug() << "group was dropped on a group?";
206  dndGroupOnGroup(droppedItem, dropPositionItem);
207  }
208  }
209  else
210  {
211  if(!dropPositionItem)
212  {
213 // debug pingroup qDebug() << "pin was dropped between groups on row " << row;
214  dndPinBetweenGroup(droppedItem, row);
215  }
216  else if(row != -1)
217  {
218 // debug pingroup qDebug() << "pin was dropped between pins";
219  dndPinBetweenPin(droppedItem, dropPositionItem, row);
220  }
221  else
222  {
223  ModulePinsTreeItem* pitem = dynamic_cast<ModulePinsTreeItem*>(dropPositionItem);
224  if (pitem && pitem->itemType() == ModulePinsTreeItem::Pin)
225  {
226 // debug pingroup qDebug() << "pin was dropped on a pin...";
227  ModulePinsTreeItem* parentGroupItem = static_cast<ModulePinsTreeItem*>(pitem->getParent());
228  row = getIndexFromPinsItem(pitem).row();
229  dndPinBetweenPin(droppedItem, parentGroupItem, row);
230  }
231  else
232 // debug pingroup qDebug() << "pin was dropped on a group...";
233  dndPinOnGroup(droppedItem, dropPositionItem);
234  }
235  }
236 
237  return true;
238  }
239 
240 
241  bool ModulePinsTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
242  {
243  Q_UNUSED(column)
244  Q_UNUSED(action)
245  if(!data->formats().contains("pintreemodel/item")) return false;
246 
247  QString type; int id;
248  auto encItem = data->data("pintreemodel/item");
249  QDataStream dataStream(&encItem, QIODevice::ReadOnly);
250  dataStream >> type >> id;
251  auto parentItem = static_cast<ModulePinsTreeItem*>(getItemFromIndex(parent));
252  // qDebug() << "type: " << type << ", id" << id << ", row: " << row;
253 
254  // construct a "drop-matrix" here, but only 4(5) things are NOT allowed (so check for these):
255  // 1: drop a pin on its OWN parent
256  // 3: drop a pingroup on/between pins
257  // 4: drop an item on itself
258  // 5: drop adjecent index to itself, must be at least 1 item apart
259  if(type == "group")
260  {
261  auto item = static_cast<ModulePinsTreeItem*>(mIdToGroupItem[id]);
262  if(parentItem)
263  {
264  if(item->itemType() == ModulePinsTreeItem::Pin || (item->itemType() == ModulePinsTreeItem::Group && row != -1) || item == parentItem)
265  return false;
266  }
267  else // here, only check for adjacent rows
268  {
269  auto itRow = item->getOwnRow();
270  if(itRow == row || ((itRow+1) == row))
271  return false;
272  }
273  }
274  if(type == "pin")
275  {
276  // perhaps check here that a pin can only be dropped between groups if its own group has size > 1?
277  // otherwise it does not make much sense...perhaps change this check
278  auto item = mIdToPinItem[id];
279  if((!parentItem && item->getParent()->getChildCount() == 1)
280  || (item->getParent() == parentItem && row == -1)
281  || item == parentItem )
282  // || (parentItem && (parentItem->itemType() == PortTreeItem::Pin)))
283  return false;
284  // case if one wants to drop between pins in same group, check if its not adjacent row (other cases are handled on case above
285  if(item->getParent() == parentItem)
286  {
287  auto itRow = item->getOwnRow();
288  if(itRow == row || ((itRow+1) == row))
289  return false;
290  }
291  }
292  return true;
293  }
294 
296  {
298  mModule = nullptr;
299  mNameToTreeItem.clear();
300  mIdToGroupItem.clear();
301  mIdToPinItem.clear();
302  }
303 
305  {
306  mModule = m;
307  beginResetModel();
308 
309  for(PinGroup<ModulePin>* pinGroup : m->get_pin_groups())
310  {
311  if(pinGroup->empty())
312  continue;
313 
314  auto pinGroupName = QString::fromStdString(pinGroup->get_name());
315  ModulePinsTreeItem* pinGroupItem = new ModulePinsTreeItem(ModulePinsTreeItem::Group, pinGroup->get_id(), pinGroupName, pinGroup->get_direction(),
316  pinGroup->get_type(), pinGroup->is_ascending() ? 0 : 1);
317  mIdToGroupItem.insert(pinGroup->get_id(), pinGroupItem);
318  for(ModulePin* pin : pinGroup->get_pins())
319  {
321  pin->get_id(),
322  QString::fromStdString(pin->get_name()),
323  pin->get_direction(),
324  pin->get_type(),
325  pin->get_group().second,
326  QString::fromStdString(pin->get_net()->get_name()));
327  pinGroupItem->appendChild(pinItem);
328  mNameToTreeItem.insert(QString::fromStdString(pin->get_name()), pinItem);
329  mIdToPinItem.insert(pin->get_id(), pinItem);
330  }
331  mNameToTreeItem.insert(pinGroupName, pinGroupItem);
332  mRootItem->appendChild(pinGroupItem);
333  }
334 
335 // Keep old code for the time being to review whether all cases are covered
336 //
337 // for (PinGroup<ModulePin>* pinGroup : m->get_pin_groups())
338 // {
339 // //ignore empty pingroups
340 // if (pinGroup->empty())
341 // continue;
342 
343 
344 // ModulePin* firstPin = pinGroup->get_pins().front();
345 // QString pinGroupName;
346 // QString pinGroupDirection = QString::fromStdString(enum_to_string(firstPin->get_direction()));
347 // QString pinGroupType = QString::fromStdString(enum_to_string(firstPin->get_type()));
348 // if (pinGroup->size() == 1)
349 // {
350 // pinGroupName = QString::fromStdString(firstPin->get_name());
351 // }
352 // else
353 // {
354 // pinGroupName = QString::fromStdString(pinGroup->get_name());
355 // }
356 
357 // TreeItem* pinGroupItem = new TreeItem(QList<QVariant>() << pinGroupName << pinGroupDirection << pinGroupType << "");
358 
359 // if (pinGroup->size() == 1)
360 // {
361 // pinGroupItem->setDataAtColumn(sNetColumn, QString::fromStdString(firstPin->get_net()->get_name()));
362 // pinGroupItem->setAdditionalData(keyType, QVariant::fromValue(itemType::pin));
363 // //since a single-pin pingroup represents the pin itself, take the pinid
364 // pinGroupItem->setAdditionalData(keyId, firstPin->get_id());
365 // mIdToPinItem.insert(firstPin->get_id(), pinGroupItem);
366 // }
367 // else
368 // {
369 // pinGroupItem->setAdditionalData(keyType, QVariant::fromValue(itemType::portMultiBit));
370 // pinGroupItem->setAdditionalData(keyId, pinGroup->get_id());
371 // mIdToGroupItem.insert(pinGroup->get_id(), pinGroupItem);
372 // for (ModulePin* pin : pinGroup->get_pins())
373 // {
374 // TreeItem* pinItem =
375 // new TreeItem(QList<QVariant>() << QString::fromStdString(pin->get_name()) << pinGroupDirection << pinGroupType << QString::fromStdString(pin->get_net()->get_name()));
376 // pinItem->setAdditionalData(keyType, QVariant::fromValue(itemType::pin));
377 // pinItem->setAdditionalData(keyId, pin->get_id());
378 // pinGroupItem->appendChild(pinItem);
379 // mNameToTreeItem.insert(QString::fromStdString(pin->get_name()), pinItem);
380 // mIdToPinItem.insert(pin->get_id(), pinItem);
381 // }
382 // }
383 // mRootItem->appendChild(pinGroupItem);
384 // mNameToTreeItem.insert(pinGroupName, pinGroupItem);
385 // }
386  endResetModel();
387 
388  Q_EMIT numberOfPortsChanged(m->get_pins().size());
389  }
390 
392  {
393  Module* m = mModule;
394  if (!m)
395  return;
396 
398  clear(); // sets mModule to nullptr
399  setModule(m);
401  }
402 
404  {
405  if (!mModule) //no current module = no represented net
406  return nullptr;
407 
408  if (item->itemType() == ModulePinsTreeItem::Group && item->getChildCount() > 1)
409  return nullptr;
410 
411  Module* m = gNetlist->get_module_by_id(mModule->get_id());
412  if (!m)
413  return nullptr;
414 
415  //std::string name = item->getData(sNameColumn).toString().toStdString();
416  if (auto* pin = m->get_pin_by_id(item->id()); pin != nullptr)
417  {
418  return pin->get_net();
419  }
420 
421  return nullptr;
422  }
423 
425  {
426  if (!mModule) return -1;
427  return mModule->get_id();
428  }
429 
431  {
432  static const QSet<PinEvent> groupEvents = { PinEvent::GroupCreate,
438  Q_UNUSED(pev);
439  Q_UNUSED(pgid);
440  if (m != mModule) return;
441 
442  if (pev == PinEvent::PinsReload)
443  {
444  // a bulk operation replaced the pins of this module, the individual events have been coalesced
445  reload();
446  return;
447  }
448 
449  // debug pingroups log_info("gui", "Handle pin_changed event {} ID={}", enum_to_string<PinEvent>(pev), pgid);
450  ModulePinsTreeItem* ptiPin = nullptr;
451  ModulePinsTreeItem* ptiGroup = nullptr;
452  const PinGroup<ModulePin>* pgroup = nullptr;
453  const ModulePin* pin = nullptr;
454  int pinRow = -1;
455 
456 
457  if (pev == PinEvent::PinDelete)
458  {
459  ptiPin = mIdToPinItem.value(pgid);
460  }
461 
462  if (groupEvents.contains(pev))
463  {
464  // group event
465  ptiGroup = mIdToGroupItem.value(pgid);
466  if (pev != PinEvent::GroupCreate && !ptiGroup)
467  {
468  log_warning("gui", "Cannot handle event for pin group ID={}, tree item does not exist.", pgid);
469  return;
470  }
471  if (pev != PinEvent::GroupDelete)
472  {
473  pgroup = m->get_pin_group_by_id(pgid);
474  if (!pgroup)
475  {
476  log_warning("gui", "Cannot handle event for pin group ID={}, no such group.", pgid);
477  return;
478  }
479  }
480  }
481  else
482  {
483  // pin event
484  ptiPin = mIdToPinItem.value(pgid);
485  if (pev != PinEvent::PinCreate && !ptiPin)
486  {
487  log_warning("gui", "Cannot handle event for pin ID={}, tree item does not exist.", pgid);
488  return;
489  }
490  if (pev != PinEvent::PinDelete)
491  {
492  pin = m->get_pin_by_id(pgid);
493  if (!pin)
494  {
495  log_warning("gui", "Cannot handle event for pin ID={}, no such pid.", pgid);
496  return;
497  }
498  auto pgPair = pin->get_group();
499  pgroup = pgPair.first;
500  pinRow = ActionPingroup::pinIndex2Row(pin,pgPair.second);
501  if (pgroup)
502  ptiGroup = mIdToGroupItem.value(pgroup->get_id());
503  }
504  }
505 
506  QModelIndex dataChangedIndex;
507 
508  switch (pev)
509  {
511  {
513  pgroup->get_id(),
514  QString::fromStdString(pgroup->get_name()),
515  pgroup->get_direction(),
516  pgroup->get_type(),
517  pgroup->is_ascending()?0:1);
518  mIdToGroupItem.insert(ptiGroup->id(), ptiGroup);
519  int inx = ActionPingroup::pinGroupIndex(m,pgroup);
520  insertItem(ptiGroup, mRootItem, inx);
521  break;
522  }
524  {
525  int inx = ActionPingroup::pinGroupIndex(m,pgroup);
526  removeItem(ptiGroup);
527  insertItem(ptiGroup, mRootItem, inx);
528  break;
529  }
531  ptiGroup->setName(QString::fromStdString(pgroup->get_name()));
532  dataChangedIndex = getIndexFromPinsItem(ptiGroup);
533  break;
535  ptiGroup->setPinType(pgroup->get_type());
536  dataChangedIndex = getIndexFromPinsItem(ptiGroup);
537  break;
539  ptiGroup->setPinDirection(pgroup->get_direction());
540  dataChangedIndex = getIndexFromPinsItem(ptiGroup);
541  break;
543  removeItem(ptiGroup);
544  delete ptiGroup;
545  break;
546  case PinEvent::PinCreate:
547  {
548  if (!pgroup || !ptiGroup)
549  {
550  log_warning("gui", "Cannot handle pin create event for pin ID={}, pin is not assigned to any group.", pgid);
551  return;
552  }
553  QString netName;
554  if (pin->get_net())
555  netName = QString::fromStdString(pin->get_net()->get_name());
557  pin->get_id(),
559  pin->get_direction(),
560  pin->get_type(),
561  pin->get_group().second,
562  netName);
563  mIdToPinItem.insert(ptiPin->id(), ptiPin);
564  insertItem(ptiPin, ptiGroup, pinRow);
565  updateGroupIndex(ptiGroup);
566  break;
567  }
569  {
570  if (!pgroup || !ptiGroup)
571  {
572  log_warning("gui", "Cannot handle pin reorder event for pin ID={}, pin is not assigned to any group.", pgid);
573  return;
574  }
575  removeItem(ptiPin);
576  insertItem(ptiPin, ptiGroup, pinRow);
577  updateGroupIndex(ptiGroup);
578  break;
579  }
581  {
582  if (!pgroup || !ptiGroup)
583  {
584  log_warning("gui", "Cannot handle pin assign event for pin ID={}, pin is not assigned to any group.", pgid);
585  return;
586  }
587  removeItem(ptiPin);
588  insertItem(ptiPin, ptiGroup, pinRow);
589 
590  // Unfortunately the event does not tell us where the pin was assigned previously. We have to update all group indices.
591  for (BaseTreeItem* bti : mRootItem->getChildren())
592  {
593  ModulePinsTreeItem* grpItem = static_cast<ModulePinsTreeItem*>(bti);
594  // check whether group still exists (might have been deleted when moving last pin)
595  if (mModule->get_pin_group_by_id(grpItem->id()))
596  updateGroupIndex(static_cast<ModulePinsTreeItem*>(grpItem));
597  }
598  break;
599  }
600  case PinEvent::PinRename:
601  ptiPin->setName(QString::fromStdString(pin->get_name()));
602  dataChangedIndex = getIndexFromPinsItem(ptiPin);
603  break;
605  ptiPin->setPinType(pin->get_type());
606  dataChangedIndex = getIndexFromPinsItem(ptiPin);
607  break;
609  ptiPin->setPinDirection(pin->get_direction());
610  dataChangedIndex = getIndexFromPinsItem(ptiPin);
611  break;
612  case PinEvent::PinDelete:
613  removeItem(ptiPin);
614  delete ptiPin;
615  break;
616  default:
617  break;
618  }
619 
620  if (dataChangedIndex.isValid())
621  {
622  QModelIndex inxLastCol = createIndex(dataChangedIndex.row(),columnCount()-1,dataChangedIndex.internalPointer());
623  Q_EMIT dataChanged(dataChangedIndex,inxLastCol);
624  }
625  }
626 
627  void ModulePinsTreeModel::dndGroupOnGroup(BaseTreeItem *droppedGroup, BaseTreeItem *onDroppedGroup, int row)
628  {
629  // SPECIFY: 1) create completely new group, all pins in that, delete old 2 groups
630  // 2) just add all pins from dropped group to "ondroppedgroup", then rename?
631 // InputDialog ipd("Name of new group", "Name of new group:", onDroppedGroup->getData(sNameColumn).toString());
632 // if(ipd.exec() == QDialog::Rejected) return false;
634  auto srcgroup = mModule->get_pin_group_by_id(static_cast<ModulePinsTreeItem*>(droppedGroup)->id());
635  for(const auto &pin : srcgroup->get_pins())
636  pins.append(pin->get_id());
637  if (pins.isEmpty()) return; // no pins to move
638 
639  auto tgtgroup = mModule->get_pin_group_by_id(static_cast<ModulePinsTreeItem*>(onDroppedGroup)->id());
640 
641  ActionPingroup* act = ActionPingroup::addPinsToExistingGroup(mModule,tgtgroup->get_id(),pins,row);
642  if (act) act->exec();
643 
644  // too keep the order, ActionAddItemsToObject cannot be executed with all pins, but a ComAction must be created
645  // with many ActionAddItemsToObject that contain a single pin each -> set destroys order of pins in source pingroup
646  }
647 
648  void ModulePinsTreeModel::dndGroupBetweenGroup(ModulePinsTreeItem *droppedGroup, int row)
649  {
650  int ownRow = droppedGroup->getOwnRow();
651  bool bottomEdge = row == mRootItem->getChildCount();
652  auto desiredIdx = bottomEdge ? row-1 : row;
653  if(ownRow < row && !bottomEdge) desiredIdx--;
654  ActionPingroup* act = new ActionPingroup(PinActionType::GroupMoveToRow,droppedGroup->id(),"",desiredIdx);
655  act->setObject(UserActionObject(mModule->get_id(),UserActionObjectType::Module));
656  act->exec();
657  }
658 
659  void ModulePinsTreeModel::dndPinOnGroup(ModulePinsTreeItem *droppedPin, BaseTreeItem *onDroppedGroup)
660  {
661  ActionPingroup* act = new ActionPingroup(PinActionType::PinAsignToGroup,droppedPin->id(),"",static_cast<ModulePinsTreeItem*>(onDroppedGroup)->id());
662  act->setObject(UserActionObject(mModule->get_id(),UserActionObjectType::Module));
663  act->exec();
664  }
665 
666  void ModulePinsTreeModel::dndPinBetweenPin(ModulePinsTreeItem *droppedPin, BaseTreeItem *onDroppedParent, int row)
667  {
668  int desiredIdx = row;
669  ActionPingroup* act = nullptr;
670  if(droppedPin->getParent() == onDroppedParent) // same group
671  {
672  int ownRow = droppedPin->getOwnRow();
673  bool bottomEdge = row == onDroppedParent->getChildCount();
674  desiredIdx = bottomEdge ? row-1 : row;
675  if(ownRow < row && !bottomEdge) desiredIdx--; // insert item here
676  act = new ActionPingroup(PinActionType::PinMoveToRow,droppedPin->id(),"",desiredIdx); // TODO : start_index, descending
677  }
678  else
679  {
680  act = ActionPingroup::addPinToExistingGroup(mModule,static_cast<ModulePinsTreeItem*>(onDroppedParent)->id(),droppedPin->id(),desiredIdx);
681  if (!act) return;
682  }
683  act->setObject(UserActionObject(mModule->get_id(),UserActionObjectType::Module));
684  act->exec();
685  }
686 
687  void ModulePinsTreeModel::dndPinBetweenGroup(ModulePinsTreeItem *droppedPin, int row)
688  {
689  // row is needed for when groups can change its order within the module
690  Q_UNUSED(row)
691 
692  auto pinToMove = mModule->get_pin_by_id(droppedPin->id());
693  if (!pinToMove) return;
694 
695  QString groupName = ActionPingroup::generateGroupName(mModule,pinToMove);
696 
697  ActionPingroup* act = ActionPingroup::addPinToNewGroup(mModule, groupName, droppedPin->id(),row);
698  act->exec();
699  }
700 
701  void ModulePinsTreeModel::updateGroupIndex(ModulePinsTreeItem* groupItem)
702  {
703  PinGroup<ModulePin>* pg = mModule->get_pin_group_by_id(groupItem->id());
704  Q_ASSERT(pg);
705  for (ModulePin* pin : pg->get_pins())
706  {
707  int inx = pg->get_index(pin).get();
708  ModulePinsTreeItem* pinItem = mIdToPinItem.value(pin->get_id());
709  Q_ASSERT(pinItem);
710  pinItem->setIndex(inx);
711  }
712  QModelIndex pi = getIndexFromPinsItem(groupItem);
713  QModelIndex i0 = index(0,0,pi);
714  QModelIndex i1 = index(groupItem->getChildCount()-1,4,pi);
715  Q_EMIT dataChanged(i0,i1);
716  }
717 
718  void ModulePinsTreeModel::insertItem(ModulePinsTreeItem* item, BaseTreeItem* parent, int index)
719  {
720  // fun fact: if an item is inserted above an item that is expanded, the tree collapses all indeces
722  parent->insertChild(index, item);
723  endInsertRows();
724  //mNameToTreeItem.insert(item->getData(sNameColumn).toString(), item);
725  item->itemType() == ModulePinsTreeItem::Pin ? mIdToPinItem.insert(item->id(), item) : mIdToGroupItem.insert(item->id(), item);
726  //mIdToPinItem.insert(getIdOfItem(item), item);
727  }
728 
729  void ModulePinsTreeModel::removeItem(ModulePinsTreeItem* item)
730  {
731  auto itOrphan = mOrphanedItem.find(item);
732  if (itOrphan != mOrphanedItem.end())
733  {
734  // already orphaned and not part of the tree
735  mOrphanedItem.erase(itOrphan);
736  }
737  else
738  {
739  beginRemoveRows(parent(getIndexFromPinsItem(item)), item->getOwnRow(), item->getOwnRow());
740  item->getParent()->removeChild(item);
741  endRemoveRows();
742  }
743  //mNameToTreeItem.remove(item->getData(sNameColumn).toString());
744  //for now, only ids of pin-items (since these functions are only relevant for dnd)
745  if (item->itemType() == ModulePinsTreeItem::Pin)
746  mIdToPinItem.remove(item->id());
747  else
748  {
749  for (BaseTreeItem* bti : item->getChildren())
750  {
751  mOrphanedItem.insert(static_cast<ModulePinsTreeItem*>(bti));
752  item->removeChild(bti);
753  }
754  mIdToGroupItem.remove(item->id());
755  }
756  //mIdToPinItem.remove(getIdOfItem(item));
757  //delete item;
758  }
759 
760  void ModulePinsTreeModel::dumpModel(const char* msg) const
761  {
762  std::cerr << msg << " \t Pins:";
763  for (int i : mIdToPinItem.keys()) std::cerr << " " << i;
764  std::cerr << " \t Grps:";
765  for (int i : mIdToGroupItem.keys()) std::cerr << " " << i;
766  std::cerr << std::endl;
767  for (const BaseTreeItem* bti : mRootItem->getChildren())
768  {
769  const ModulePinsTreeItem* mpti = static_cast<const ModulePinsTreeItem*>(bti);
770  std::cerr << mpti->id() << " <" << mpti->name().toStdString() << ">\n";
771  for (const BaseTreeItem* cti : mpti->getChildren())
772  {
773  const ModulePinsTreeItem* mptpin = static_cast<const ModulePinsTreeItem*>(cti);
774  std::cerr << " " << mptpin->id() << " <" << mptpin->name().toStdString() << "> \t" << mptpin->getData(2).toString().toStdString() << " \t " <<
775  mptpin->getData(4).toString().toStdString() << "\n";
776  }
777  }
778  std::cerr << "-------------" << std::endl;
779  }
780 
781 } // 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:110
u32 get_id() const
Definition: base_pin.h:90
PinType get_type() const
Definition: base_pin.h:150
const std::pair< PinGroup< T > *, i32 > & get_group() const
Definition: base_pin.h:160
PinDirection get_direction() const
Definition: base_pin.h:130
(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:133
const std::string & get_name() const
Definition: pin_group.h:153
bool is_ascending() const
Definition: pin_group.h:276
PinDirection get_direction() const
Definition: pin_group.h:193
PinType get_type() const
Definition: pin_group.h:173
static QString pyCodeModulePinGroup(u32 moduleId, u32 groupId)
static QString pyCodeModulePinById(u32 moduleId, u32 pinId)
uint32_t u32
Definition: defines.h:41
#define log_warning(channel,...)
Definition: log.h:76
Definition: defines.h:45
PinDirection
Definition: pin_direction.h:36
PinEvent
Definition: pin_event.h:42
@ PinsReload
group deleted
@ 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: gui_globals.h:69
NetlistRelay * gNetlistRelay
Definition: gui_globals.h:74
PinType
Definition: pin_type.h:36
std::string enum_to_string(T e)
Definition: enums.h:53
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