HAL  v4.5.0-133-g64838ea8d
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
module_model.cpp
Go to the documentation of this file.
2 
3 #include "gui/gui_globals.h"
7 
9 #include "hal_core/netlist/net.h"
10 #include <QMimeData>
11 #include <QIODevice>
12 
13 namespace hal
14 {
15  ModuleModel::ModuleModel(QObject* parent) : BaseTreeModel(parent), mIsModifying(false), mResetInProgress(false)
16  {
17  // use root item to store header information
18  setHeaderLabels(QStringList() << "Name" << "ID" << "Type");
19  connect(gNetlistRelay, &NetlistRelay::moduleCreated, this, &ModuleModel::handleModuleCreated);
20  connect(gNetlistRelay, &NetlistRelay::moduleNameChanged, this, &ModuleModel::handleModuleNameChanged);
21  connect(gNetlistRelay, &NetlistRelay::moduleTypeChanged, this, &ModuleModel::handleModuleTypeChanged);
22  connect(gNetlistRelay, &NetlistRelay::moduleParentChanged, this, &ModuleModel::handleModuleParentChanged);
23  connect(gNetlistRelay, &NetlistRelay::moduleSubmoduleAdded, this, &ModuleModel::handleModuleSubmoduleAdded);
24  connect(gNetlistRelay, &NetlistRelay::moduleSubmoduleRemoved, this, &ModuleModel::handleModuleSubmoduleRemoved);
25  connect(gNetlistRelay, &NetlistRelay::moduleGateAssigned, this, &ModuleModel::handleModuleGateAssigned);
26  connect(gNetlistRelay, &NetlistRelay::moduleGatesAssignBegin, this, &ModuleModel::handleModuleGatesAssignBegin);
27  connect(gNetlistRelay, &NetlistRelay::moduleGatesAssignEnd, this, &ModuleModel::handleModuleGatesAssignEnd);
28  connect(gNetlistRelay, &NetlistRelay::moduleGateRemoved, this, &ModuleModel::handleModuleGateRemoved);
29  connect(gNetlistRelay, &NetlistRelay::moduleRemoved, this, &ModuleModel::handleModuleRemoved);
30  connect(gNetlistRelay, &NetlistRelay::gateNameChanged, this, &ModuleModel::handleGateNameChanged);
31  connect(gNetlistRelay, &NetlistRelay::netCreated, this, &ModuleModel::handleNetCreated);
32  connect(gNetlistRelay, &NetlistRelay::netRemoved, this, &ModuleModel::handleNetRemoved);
33  connect(gNetlistRelay, &NetlistRelay::netNameChanged, this, &ModuleModel::handleNetNameChanged);
34  connect(gNetlistRelay, &NetlistRelay::netSourceAdded, this, &ModuleModel::handleNetUpdated);
35  connect(gNetlistRelay, &NetlistRelay::netSourceRemoved, this, &ModuleModel::handleNetUpdated);
36  connect(gNetlistRelay, &NetlistRelay::netDestinationAdded, this, &ModuleModel::handleNetUpdated);
37  connect(gNetlistRelay, &NetlistRelay::netDestinationRemoved, this, &ModuleModel::handleNetUpdated);
38  }
39 
40  QVariant ModuleModel::data(const QModelIndex& index, int role) const
41  {
42  if (!index.isValid())
43  return QVariant();
44 
45  ModuleItem* item = static_cast<ModuleItem*>(index.internalPointer());
46 
47  if (!item)
48  return QVariant();
49 
50  switch (role)
51  {
52  case Qt::DecorationRole:
53  {
54  if (index.column() == 0)
55  {
56  switch(item->getType()){
63  }
64  }
65  break;
66  }
67  case Qt::DisplayRole:
68  {
69  return item->getData(index.column());
70  }
71  case Qt::ForegroundRole:
72  {
73  if (item->highlighted())
74  return QColor(QColor(255, 221, 0)); // USE STYLESHEETS
75  else
76  return QColor(QColor(255, 255, 255)); // USE STYLESHEETS
77  }
79  return index.column() == 1
81  : Qt::AlignLeft;
82  default:
83  return QVariant();
84  }
85  return QVariant();
86  }
87 
88  QMimeData* ModuleModel::mimeData(const QModelIndexList &indexes) const
89  {
90  QMimeData* retval = new QMimeData;
91  // only single row allowed
92  int row = -1;
93  for (const QModelIndex& inx : indexes)
94  {
95  if (row < 0)
96  row = inx.row();
97  else if (row != inx.row())
98  return retval;
99  }
100  if (row < 0)
101  return retval;
102 
103  QModelIndex firstIndex = indexes.at(0);
104  BaseTreeItem* bti = getItemFromIndex(firstIndex);
105  row = firstIndex.row();
106  BaseTreeItem* parentItem = bti->getParent();
107  ModuleItem* item = dynamic_cast<ModuleItem*>(bti);
108  if (!item)
109  {
110  qDebug() << "cannot cast" << indexes.at(0);
111  return retval;
112  }
113  QByteArray encodedData;
114  QDataStream stream(&encodedData, QIODevice::WriteOnly);
115  QString moveText;
116  int id = item->id();
117 
118  switch (item->getType())
119  {
121  moveText = PyCodeProvider::pyCodeModule(id);
122  break;
124  moveText = PyCodeProvider::pyCodeGate(id);
125  break;
127  moveText = PyCodeProvider::pyCodeNet(id);
128  break;
129  }
130 
131  stream << item->getType() << id << row << (quintptr) parentItem;
132  retval->setText(moveText);
133  retval->setData("modulemodel/item", encodedData);
134  return retval;
135 
136  }
137 
139  {
140  if (!index.isValid())
141  return Qt::NoItemFlags;
142 
144  }
145 
147  {
148  if (index.isValid())
149  return static_cast<ModuleItem*>(index.internalPointer());
150  else
151  return nullptr;
152  }
153 
155  {
156  return mModuleItemMaps[(int)type]->value(id);
157  }
158 
160  {
161  return mModuleItemMaps[(int)type]->values(id);
162  }
163 
165  {
166  beginResetModel();
167 
169  mModuleMap.clear();
170  mGateMap.clear();
171  mNetMap.clear();
172  endResetModel();
173  }
174 
175  void ModuleModel::populateFromGatelist(const std::vector<Gate *> &gates)
176  {
177  setIsModifying(true);
178  beginResetModel();
179  clear();
180 
181  QMap<Module*,ModuleItem*> parentMap;
182  for (const Gate* g : gates)
183  {
184  Module* parentModule = g->get_module();
185  ModuleItem* parentItem;
186  bool insertToRoot = true;
187  ModuleItem* childItem = new ModuleItem(g->get_id(), ModuleItem::TreeItemType::Gate, this);
188 
189  while (parentModule && insertToRoot)
190  {
191  parentItem = parentMap.value(parentModule);
192  if (!parentItem)
193  {
194  parentItem = new ModuleItem(parentModule->get_id(), ModuleItem::TreeItemType::Module, this);
195  parentMap.insert(parentModule, parentItem);
196  }
197  else
198  {
199  insertToRoot = false;
200  }
201  parentItem->appendChild(childItem);
202  parentModule = parentModule->get_parent_module();
203  childItem = parentItem;
204  }
205 
206  if (insertToRoot)
207  {
208  mRootItem->appendChild(parentItem);
209  }
210  }
211 
212  setIsModifying(false);
213  endResetModel();
214  }
215 
216  void ModuleModel::populateTree(const QVector<u32>& modIds, const QVector<u32>& gateIds, const QVector<u32>& netIds)
217  {
218  setIsModifying(true);
219  mResetInProgress = true;
220  beginResetModel();
221  // Might want to add parameter for container of moduleIds that don't get recursively inserted.
222  clear();
223 
224  QList<ModuleItem*> newRootList;
225  for(u32 id : modIds)
228 
229  for(u32 id : gateIds)
230  newRootList.append(new ModuleItem(id, ModuleItem::TreeItemType::Gate, this));
231 
232  for(u32 id : netIds)
233  newRootList.append(new ModuleItem(id, ModuleItem::TreeItemType::Net, this));
234 
235  for(auto item : newRootList)
236  mRootItem->appendChild(item);
237  mResetInProgress = false;
238  setIsModifying(false);
239  endResetModel();
240  }
241 
242  void ModuleModel::addModule(u32 id, u32 parentId)
243  {
244  Q_ASSERT(gNetlist->get_module_by_id(id));
245  Q_ASSERT(gNetlist->get_module_by_id(parentId));
246 
247  for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it)
248  {
249  ModuleItem* parentItem = it.value();
251  }
252  }
253 
254  void ModuleModel::addGate(u32 id, u32 parentId)
255  {
256  Q_ASSERT(gNetlist->get_gate_by_id(id));
257  Q_ASSERT(gNetlist->get_module_by_id(parentId));
258 
259 
260  for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it)
261  {
263  }
264  }
265 
266  void ModuleModel::addNet(u32 id, u32 parentId)
267  {
268  Q_ASSERT(gNetlist->get_net_by_id(id));
269  Q_ASSERT(gNetlist->get_module_by_id(parentId));
270 
271  for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it)
272  {
274  }
275  }
276 
278  {
279  Q_ASSERT(module);
280  ModuleItem* moduleItem = createChildItem(module->get_id(), ModuleItem::TreeItemType::Module, parentItem ? parentItem : mRootItem);
281  Q_ASSERT(moduleItem);
282  for(const Module* subModule : module->get_submodules())
283  addRecursively(subModule, moduleItem);
284 
285  for(const Gate* g : module->get_gates())
286  createChildItem(g->get_id(), ModuleItem::TreeItemType::Gate, moduleItem);
287  }
288 
290  {
291  QList<ModuleItem*> trashcan; // access items to delete without map
292 
293  for (auto it = mModuleMap.lowerBound(id); it != mModuleMap.upperBound(id); ++it)
294  trashcan.append(it.value());
295 
296  for (ModuleItem* item : trashcan)
297  {
298  BaseTreeItem* parentItem = item->getParent();
299  removeChildItem(item,parentItem);
300  }
301  }
302 
304  {
305  QList<ModuleItem*> trashcan; // access items to delete without map
306 
307  for (auto it = mGateMap.lowerBound(id); it != mGateMap.upperBound(id); ++it)
308  trashcan.append(it.value());
309 
310  for (ModuleItem* item : trashcan)
311  {
312  BaseTreeItem* parentItem = item->getParent();
313  removeChildItem(item,parentItem);
314  }
315  }
316 
318  {
319  QList<ModuleItem*> trashcan; // access items to delete without map
320 
321  for (auto it = mNetMap.lowerBound(id); it != mNetMap.upperBound(id); ++it)
322  trashcan.append(it.value());
323 
324  for (ModuleItem* item : trashcan)
325  {
326  BaseTreeItem* parentItem = item->getParent();
327  removeChildItem(item,parentItem);
328  }
329  }
330 
332  {
333  ModuleItem* retval = new ModuleItem(id, itemType, this);
334 
335  if (!parentItem) parentItem = mRootItem;
336 
337  if (mResetInProgress)
338  {
339  // the enclosing model reset already makes the views re-read everything. Emitting row signals in
340  // between is undefined behavior and would make an attached proxy re-map its rows for every item.
341  parentItem->appendChild(retval);
342  return retval;
343  }
344 
345  QModelIndex index = getIndexFromItem(parentItem);
346  int row = parentItem->getChildCount();
347  const bool wasModifying = mIsModifying;
348  mIsModifying = true;
349  beginInsertRows(index, row, row);
350  parentItem->appendChild(retval);
351  endInsertRows();
352  mIsModifying = wasModifying;
353 
354  return retval;
355  }
356 
357  void ModuleModel::removeChildItem(ModuleItem *itemToRemove, BaseTreeItem *parentItem)
358  {
359  Q_ASSERT(itemToRemove);
360  Q_ASSERT(parentItem);
361 
362  while (itemToRemove->getChildCount())
363  {
364  ModuleItem* childItem = static_cast<ModuleItem*>(itemToRemove->getChildren().at(0));
365  removeChildItem(childItem,itemToRemove);
366  }
367 
368  if (mResetInProgress)
369  {
370  // see createChildItem(), the enclosing model reset covers this removal
371  parentItem->removeChild(itemToRemove);
372  delete itemToRemove;
373  return;
374  }
375 
376  QModelIndex index = getIndexFromItem(parentItem);
377 
378  int row = itemToRemove->getOwnRow();
379 
380  const bool wasModifying = mIsModifying;
381  mIsModifying = true;
382  beginRemoveRows(index, row, row);
383  parentItem->removeChild(itemToRemove);
384  endRemoveRows();
385  mIsModifying = wasModifying;
386 
387  delete itemToRemove;
388  }
389 
390  void ModuleModel::handleModuleNameChanged(Module* mod)
391  {
392  updateModuleName(mod->get_id());
393  }
394 
395  void ModuleModel::handleModuleTypeChanged(Module* mod)
396  {
397  updateModuleType(mod->get_id());
398  }
399 
400  void ModuleModel::handleModuleRemoved(Module* mod)
401  {
402  removeModule(mod->get_id());
403  }
404 
405  void ModuleModel::handleModuleCreated(Module* mod)
406  {
407  if (mod->get_parent_module() == nullptr) return;
408  addModule(mod->get_id(), mod->get_parent_module()->get_id());
409  }
410 
411  void ModuleModel::handleModuleGateAssigned(Module* mod, u32 gateId)
412  {
413  if (mTempGateAssignment.isAccumulate())
414  mTempGateAssignment.assignGateToModule(gateId,mod);
415  else
416  {
417  moduleAssignGate(mod->get_id(), gateId);
418  moduleAssignNets({gateId});
419  }
420  }
421 
422  void ModuleModel::handleModuleGateRemoved(Module* mod, u32 gateId)
423  {
424  QList<QPair<ModuleItem*,ModuleItem*> > trashcan; // item to delete, parent
425 
426  if (mTempGateAssignment.isAccumulate())
427  mTempGateAssignment.removeGateFromModule(gateId,mod);
428  else
429  {
430  for (auto it = mGateMap.lowerBound(gateId); it != mGateMap.upperBound(gateId); ++it)
431  {
432  ModuleItem* item = it.value();
433  if (item->isToplevelItem()) continue;;
434 
435  ModuleItem* parentItem = static_cast<ModuleItem*>(item->getParent());
436  if (parentItem->id() == mod->get_id())
437  trashcan.append(QPair<ModuleItem*,ModuleItem*>(item, parentItem));
438  }
439  }
440 
441  for (const QPair<ModuleItem*,ModuleItem*>& trash : trashcan)
442  removeChildItem(trash.first, trash.second);
443  }
444 
445  void ModuleModel::handleModuleGatesAssignBegin(Module* mod, u32 numberGates)
446  {
447  Q_UNUSED(mod);
448  Q_UNUSED(numberGates);
449  mTempGateAssignment.beginAccumulate();
450  }
451 
452  void ModuleModel::handleModuleGatesAssignEnd(Module* mod, u32 numberGates)
453  {
454  Q_UNUSED(mod);
455  Q_UNUSED(numberGates);
456  mTempGateAssignment.endAccumulate();
457  if (!mTempGateAssignment.isAccumulate())
458  {
459  for (auto it = mTempGateAssignment.mGateAssign.begin(); it != mTempGateAssignment.mGateAssign.end(); ++it)
460  {
461  moduleAssignGate(it.value()->get_id(), it.key()); // moduleId, gateId
462  }
463  moduleAssignNets(mTempGateAssignment.mGateAssign.keys());
464  mTempGateAssignment.mGateAssign.clear();
465  mTempGateAssignment.mGateRemove.clear();
466  }
467  }
468 
469  void ModuleModel::handleGateRemoved(Gate* gat)
470  {
471  removeGate(gat->get_id());
472  }
473 
474  void ModuleModel::handleGateCreated(Gate* gat)
475  {
476  Module* mod = gat->get_module();
477  if (mod) moduleAssignGate(mod->get_id(), gat->get_id());
478  }
479 
480  void ModuleModel::handleGateNameChanged(Gate* gat)
481  {
482  updateGateName(gat->get_id());
483  }
484 
485  void ModuleModel::handleNetCreated(Net* net)
486  {
487  addNet(net->get_id(), gNetlist->get_top_module()->get_id());
488  }
489 
490  void ModuleModel::handleNetRemoved(Net* net)
491  {
492  removeNet(net->get_id());
493  }
494 
495  void ModuleModel::handleNetNameChanged(Net* net)
496  {
497  updateNetName(net->get_id());
498  }
499 
500  void ModuleModel::handleNetUpdated(Net* net, u32 data)
501  {
502  Q_UNUSED(data);
504  }
505 
506  void ModuleModel::handleModuleParentChanged(const Module* mod)
507  {
508  Q_ASSERT(mod);
509  updateModuleParent(mod);
510 
511  QHash<const Net*,ModuleItem*> parentAssignment;
512  std::unordered_set<Net*> assignedNets;
513  findNetParentRecursion(mRootItem, parentAssignment, assignedNets);
514 
515  for(Net* net : mod->get_nets())
516  updateNetParent(net, &parentAssignment);
517  }
518 
519  void ModuleModel::handleModuleSubmoduleAdded(Module* mod, u32 submodId)
520  {
521  Q_UNUSED(mod);
522  Q_UNUSED(submodId);
523  }
524 
525  void ModuleModel::handleModuleSubmoduleRemoved(Module* mod, u32 submodId)
526  {
527  Q_UNUSED(mod);
528  Q_UNUSED(submodId);
529  }
530 
531  void ModuleModel::findNetParentRecursion(BaseTreeItem* parent, QHash<const Net *, ModuleItem *> &parentAssignment, std::unordered_set<Net*>& assignedNets) const
532  {
533  for (BaseTreeItem* bti : parent->getChildren())
534  {
535  ModuleItem* item = dynamic_cast<ModuleItem*>(bti);
536  if (!item || item->getType() != ModuleItem::TreeItemType::Module) continue;
537  findNetParentRecursion(item, parentAssignment, assignedNets);
538  Module* m = gNetlist->get_module_by_id(item->id());
539  Q_ASSERT(m);
540  std::unordered_set<Net*> internalNets = m->get_nets();
541  if (!internalNets.empty())
542  {
543  for (Net* n : assignedNets)
544  internalNets.erase(n);
545  for (Net* n : m->get_input_nets())
546  internalNets.erase(n);
547  for (Net* n : m->get_output_nets())
548  internalNets.erase(n);
549  }
550  for (Net* n : internalNets)
551  {
552  parentAssignment[n] = item;
553  assignedNets.insert(n);
554  }
555  }
556  }
557 
558  Module* ModuleModel::findNetParent(const Net *net) const
559  {
560  QHash<Module*,int> modHash;
561  if (net->is_global_input_net() || net->is_global_output_net()) return nullptr;
562  int maxDepth = 0;
563 
564  for (const Endpoint* ep : net->get_sources())
565  {
566  Module* m = ep->get_gate()->get_module();
567  Q_ASSERT(m);
568  int depth = m->get_submodule_depth();
569  if (depth > maxDepth) maxDepth = depth;
570  modHash.insert(m,depth);
571  }
572 
573  for (const Endpoint* ep : net->get_destinations())
574  {
575  Module* m = ep->get_gate()->get_module();
576  Q_ASSERT(m);
577  int depth = m->get_submodule_depth();
578  if (depth > maxDepth) maxDepth = depth;
579  modHash.insert(m,depth);
580  }
581 
582  while (modHash.size() > 1 && maxDepth > 0)
583  {
584  auto it = modHash.begin();
585  while (it != modHash.end())
586  {
587  if (it.value() == maxDepth)
588  {
589  Module* parentMod = it.key()->get_parent_module();
590  modHash.erase(it);
591  if (parentMod) modHash.insert(parentMod,maxDepth-1);
592  break;
593  }
594  ++it;
595  }
596  if (it == modHash.end())
597  --maxDepth;
598  }
599  if (modHash.empty()) return nullptr;
600  return modHash.begin().key();
601  }
602 
603  void ModuleModel::moduleAssignGate(const u32 moduleId, const u32 gateId)
604  {
605  // Don't need new function handleModuleGateRemoved(), because the GateAssinged event always follows GateRemoved
606  // or NetlistInternalManager updates Net connections when a gate is deleted.
607 
608  QSet<ModuleItem*> parentsHandled;
609  Q_ASSERT(gNetlist->get_gate_by_id(gateId));
610 
611  QList<QPair<ModuleItem*,ModuleItem*> > trashcan; // item to delete, parent
612  for (auto itGat = mGateMap.lowerBound(gateId); itGat != mGateMap.upperBound(gateId); ++itGat)
613  {
614  ModuleItem* gatItem = itGat.value();
615  if (gatItem->isToplevelItem()) continue;
616  ModuleItem* oldParentItem = static_cast<ModuleItem*>(gatItem->getParent());
617  Q_ASSERT(oldParentItem);
618 
619  if (oldParentItem->id() != moduleId)
620  {
621  trashcan.append(QPair<ModuleItem*,ModuleItem*>(gatItem,oldParentItem));
622  }
623  else
624  {
625  parentsHandled.insert(oldParentItem);
626  }
627  }
628  for (const QPair<ModuleItem*,ModuleItem*>& trash : trashcan)
629  removeChildItem(trash.first, trash.second);
630 
631  if (!moduleId) return;
632  for (auto itMod = mModuleMap.lowerBound(moduleId); itMod != mModuleMap.upperBound(moduleId); ++itMod)
633  {
634  ModuleItem* parentItem = itMod.value();
635  if (parentsHandled.contains(parentItem)) continue;
636  createChildItem(gateId, ModuleItem::TreeItemType::Gate, parentItem);
637  }
638 
639  }
640 
642  {
643  QHash<const Net*,ModuleItem*> parentAssignment;
644  std::unordered_set<Net*> assignedNets;
645  findNetParentRecursion(mRootItem, parentAssignment, assignedNets);
646 
647  QSet<const Net*> netsToAssign;
648  if (gateIds.isEmpty())
649  {
650  netsToAssign = QtCompat::listToSet<const Net*>(parentAssignment.keys());
651  }
652  else
653  {
654  for (u32 id : gateIds)
655  {
656  Gate* gate = gNetlist->get_gate_by_id(id);
657  for(Net* in_net : gate->get_fan_in_nets())
658  netsToAssign.insert(in_net);
659  for(Net* out_net : gate->get_fan_out_nets())
660  netsToAssign.insert(out_net);
661  }
662  }
663 
664  for (const Net* n: netsToAssign)
665  updateNetParent(n, &parentAssignment);
666  }
667 
669  {
670  Q_ASSERT(net);
671  u32 netId = net->get_id();
672 
673  QSet<ModuleItem*> parentsHandled;
674  u32 newParentId = 0;
675  if (parentAssignment)
676  {
677  ModuleItem* modItem = parentAssignment->value(net);
678  if (modItem)
679  newParentId = modItem->id();
680  }
681  else
682  {
683  Module* newParentModule = findNetParent(net);
684  if (newParentModule)
685  newParentId = newParentModule->get_id();
686  }
687 
688  QList<QPair<ModuleItem*,ModuleItem*> > trashcan; // item to delete, parent
689 
690  for (auto itNet = mNetMap.lowerBound(netId); itNet != mNetMap.upperBound(netId); ++itNet)
691  {
692  if (itNet.value()->isToplevelItem()) continue;
693 
694  ModuleItem* netItem = itNet.value();
695  ModuleItem* oldParentItem = static_cast<ModuleItem*>(netItem->getParent());
696  Q_ASSERT(oldParentItem);
697 
698  if (newParentId == 0 || newParentId != oldParentItem->id())
699  {
700  trashcan.append(QPair<ModuleItem*,ModuleItem*>(netItem,oldParentItem));
701  break;
702  }
703  else
704  {
705  parentsHandled.insert(oldParentItem);
706  }
707  }
708 
709  for (const QPair<ModuleItem*,ModuleItem*>& trash : trashcan)
710  removeChildItem(trash.first, trash.second);
711 
712  if (!newParentId) return;
713  for (auto itMod = mModuleMap.lowerBound(newParentId); itMod != mModuleMap.upperBound(newParentId); ++itMod)
714  {
715  ModuleItem* parentItem = itMod.value();
716  if (parentsHandled.contains(parentItem)) continue;
717  createChildItem(net->get_id(), ModuleItem::TreeItemType::Net, parentItem);
718  }
719  }
720 
722  {
723  ModuleItem* moduleItemToBeMoved = nullptr;
724  bool moduleItemReassigned = false;
725 
726  Q_ASSERT(module);
727  u32 id = module->get_id();
728  Q_ASSERT(id != 1);
729 
730  QSet<ModuleItem*> parentsHandled;
731  u32 parentId = module->get_parent_module()->get_id();
732  Q_ASSERT(parentId > 0);
733 
734  QList<QPair<ModuleItem*,ModuleItem*> > trashcan; // item to delete, parent
735 
736  for (auto itSubm = mModuleMap.lowerBound(id); itSubm != mModuleMap.upperBound(id); ++itSubm)
737  {
738  ModuleItem* submItem = itSubm.value();
739  if (submItem->isToplevelItem()) continue;
740 
741  ModuleItem* oldParentItem = static_cast<ModuleItem*>(submItem->getParent());
742  Q_ASSERT(oldParentItem);
743 
744  if (oldParentItem->id() != parentId)
745  {
746  if (moduleItemToBeMoved)
747  {
748  // remove tree item recursively
749  trashcan.append(QPair<ModuleItem*,ModuleItem*>(submItem,oldParentItem));
750  }
751  else
752  {
753  // save tree item for reassignment
754  moduleItemToBeMoved = submItem;
755  QModelIndex index = getIndexFromItem(oldParentItem);
756 
757  int row = submItem->getOwnRow();
758 
759  mIsModifying = true;
760  beginRemoveRows(index, row, row);
761  oldParentItem->removeChild(submItem);
762  endRemoveRows();
763  mIsModifying = false;
764  }
765  }
766  else
767  {
768  parentsHandled.insert(oldParentItem);
769  }
770  }
771  for (const QPair<ModuleItem*,ModuleItem*>& trash : trashcan)
772  removeChildItem(trash.first, trash.second);
773 
774  if (!parentId) return;
775  for (auto itMod = mModuleMap.lowerBound(parentId); itMod != mModuleMap.upperBound(parentId); ++itMod)
776  {
777  ModuleItem* parentItem = itMod.value();
778  if (parentsHandled.contains(parentItem)) continue;
779  if (moduleItemToBeMoved && !moduleItemReassigned)
780  {
781  QModelIndex index = getIndexFromItem(parentItem);
782  int row = parentItem->getChildCount();
783  mIsModifying = true;
784  beginInsertRows(index, row, row);
785  parentItem->appendChild(moduleItemToBeMoved);
786  endInsertRows();
787  mIsModifying = false;
788  moduleItemReassigned = true;
789  }
790  else
791  {
792  addRecursively(module, parentItem);
793  }
794  }
795 
796  if (moduleItemToBeMoved && !moduleItemReassigned)
797  {
798  removeChildItem(moduleItemToBeMoved, moduleItemToBeMoved->getParent());
799  }
800 
801  }
802 
804  {
805  Q_ASSERT(gNetlist->get_module_by_id(id));
806 
807  for (auto it = mModuleMap.lowerBound(id); it != mModuleMap.upperBound(id); ++it)
808  {
809  ModuleItem* item = it.value();
810  Q_ASSERT(item);
811 
813 
816  }
817  }
818 
820  {
821  Q_ASSERT(gNetlist->get_module_by_id(id));
822 
823  for (auto it = mModuleMap.lowerBound(id); it != mModuleMap.upperBound(id); ++it)
824  {
825  ModuleItem* item = it.value();
826  Q_ASSERT(item);
827 
829 
832  }
833  }
834 
836  {
837  Q_ASSERT(gNetlist->get_gate_by_id(id));
838 
839  for (auto it = mGateMap.lowerBound(id); it != mGateMap.upperBound(id); ++it)
840  {
841  ModuleItem* item = it.value();
842  Q_ASSERT(item);
843 
844  item->setName(QString::fromStdString(gNetlist->get_gate_by_id(id)->get_name())); // REMOVE & ADD AGAIN
845 
848  }
849  }
850 
852  {
853  Q_ASSERT(gNetlist->get_net_by_id(id));
854 
855  // if net elment not in model loop will reject
856  for (auto it = mNetMap.lowerBound(id); it != mNetMap.upperBound(id); ++it)
857  {
858  ModuleItem* item = it.value();
859  Q_ASSERT(item);
860 
861  item->setName(QString::fromStdString(gNetlist->get_net_by_id(id)->get_name())); // REMOVE & ADD AGAIN
862 
865  }
866  }
867 
869  {
870  return mIsModifying;
871  }
872 
873  void ModuleModel::setIsModifying(bool pIsModifying)
874  {
875  mIsModifying = pIsModifying;
876  }
877 }
(Future) Base class for all tree models related to the details widget.
virtual QList< BaseTreeItem * > getChildren() const
virtual bool removeChild(BaseTreeItem *child)
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
RootTreeItem * mRootItem
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
virtual void clear()
void setHeaderLabels(const QStringList &label)
BaseTreeItem * getItemFromIndex(QModelIndex index) const
Definition: gate.h:58
const std::vector< Net * > & get_fan_in_nets() const
Definition: gate.cpp:591
const std::string & get_name() const
Definition: gate.cpp:105
const std::vector< Net * > & get_fan_out_nets() const
Definition: gate.cpp:735
Module * get_parent_module() const
Definition: module.cpp:126
const std::vector< Gate * > & get_gates() const
Definition: module.cpp:400
std::string get_name() const
Definition: module.cpp:88
std::vector< Module * > get_submodules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=false) const
Definition: module.cpp:268
std::string get_type() const
Definition: module.cpp:107
u32 get_id() const
Definition: module.cpp:83
An item in the ModuleModel.
Definition: module_item.h:48
QVariant getData(int column) const override
Definition: module_item.cpp:88
bool isToplevelItem() const
void setName(const QString &name)
u32 id() const
bool highlighted() const
TreeItemType getType() const
void setModuleType(const QString &moduleType)
Definition: module_item.cpp:79
void updateModuleParent(const Module *module)
Qt::ItemFlags flags(const QModelIndex &index) const override
void updateNetName(const u32 id)
void updateModuleType(const u32 id)
void addRecursively(const Module *module, BaseTreeItem *parentItem=nullptr)
void addNet(const u32 id, const u32 parentId)
void removeGate(const u32 id)
void moduleAssignNets(const QList< u32 > &gateIds=QList< u32 >())
void removeModule(const u32 id)
QList< ModuleItem * > getItems(const u32 id, ModuleItem::TreeItemType type=ModuleItem::TreeItemType::Module) const
void addGate(const u32 id, const u32 parentId)
ModuleItem * getItem(const QModelIndex &index) const
void populateFromGatelist(const std::vector< Gate * > &gates)
ModuleItem * createChildItem(u32 id, ModuleItem::TreeItemType itemType, BaseTreeItem *parentItem=nullptr)
void updateGateName(const u32 id)
void addModule(const u32 id, const u32 parentId)
QVariant data(const QModelIndex &index, int role) const override
void updateNetParent(const Net *net, const QHash< const Net *, ModuleItem * > *parentAssignment=nullptr)
void setIsModifying(bool pIsModifying)
ModuleModel(QObject *parent=nullptr)
void removeNet(const u32 id)
QMimeData * mimeData(const QModelIndexList &indexes) const override
void updateModuleName(const u32 id)
void clear() override
void removeChildItem(ModuleItem *itemToRemove, BaseTreeItem *parentItem)
void populateTree(const QVector< u32 > &modIds={}, const QVector< u32 > &gatIds={}, const QVector< u32 > &netIds={})
friend class ModuleItem
Definition: module_model.h:55
void moduleAssignGate(const u32 moduleId, const u32 gateId)
Definition: net.h:58
const std::string & get_name() const
Definition: net.cpp:98
Module * get_top_module() const
Definition: netlist.cpp:610
Gate * get_gate_by_id(const u32 gate_id) const
Definition: netlist.cpp:195
Module * get_module_by_id(u32 module_id) const
Definition: netlist.cpp:615
Net * get_net_by_id(u32 net_id) const
Definition: netlist.cpp:355
void netDestinationRemoved(Net *n, const u32 dst_gate_id) const
void moduleGatesAssignEnd(Module *m, u32 number_gates) const
void moduleTypeChanged(Module *m) const
void netCreated(Net *n) const
void netSourceAdded(Net *n, const u32 src_gate_id) const
void moduleGateRemoved(Module *m, const u32 removed_gate) const
void moduleGateAssigned(Module *m, const u32 assigned_gate) const
void netSourceRemoved(Net *n, const u32 src_gate_id) const
void netRemoved(Net *n) const
void netDestinationAdded(Net *n, const u32 dst_gate_id) const
void moduleSubmoduleRemoved(Module *m, const u32 removed_module) const
void moduleNameChanged(Module *m) const
void gateNameChanged(Gate *g) const
void moduleRemoved(Module *m) const
void moduleParentChanged(Module *m) const
void moduleSubmoduleAdded(Module *m, const u32 added_module) const
void moduleCreated(Module *m) const
void moduleGatesAssignBegin(Module *m, u32 number_gates) const
void netNameChanged(Net *n) const
static QString pyCodeModule(u32 moduleId)
static QString pyCodeNet(u32 netId)
static QString pyCodeGate(u32 gateId)
static SelectionDetailsIconProvider * instance()
uint32_t u32
Definition: defines.h:41
const Module * module(const Gate *g, const NodeBoxes &boxes)
Definition: defines.h:45
Netlist * gNetlist
Definition: gui_globals.h:69
NetlistRelay * gNetlistRelay
Definition: gui_globals.h:74
PinType type
Net * net
void beginInsertRows(const QModelIndex &parent, int first, int last)
void beginRemoveRows(const QModelIndex &parent, int first, int last)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles)
virtual Qt::ItemFlags flags(const QModelIndex &index) const const
const Key & key() const const
QHash::iterator begin()
bool empty() const const
QHash::iterator end()
QHash::iterator erase(QHash::iterator pos)
QHash::iterator insert(const Key &key, const T &value)
QList< Key > keys() const const
int size() const const
const T value(const Key &key) const const
void append(const T &value)
bool isEmpty() const const
QMap::iterator insert(const Key &key, const T &value)
const T value(const Key &key, const T &defaultValue) const const
void setData(const QString &mimeType, const QByteArray &data)
void setText(const QString &text)
int column() const const
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
QSet::iterator insert(const T &value)
QString fromStdString(const std::string &str)
AlignRight
DecorationRole
typedef ItemFlags