HAL
graph_context.cpp
Go to the documentation of this file.
3 
11 #include "gui/gui_globals.h"
12 #include "gui/gui_def.h"
16 #include <QVector>
17 #include <QJsonArray>
20 
21 namespace hal
22 {
23  static const bool sLazyUpdates = false;
24 
26  : QObject(parent),
27  mId(id_),
28  mName(name),
29  mParentWidget(nullptr),
30  mDirty(false),
31  mLayouter(nullptr),
32  mShader(nullptr),
33  mUserUpdateCount(0),
34  mUnappliedChanges(false),
35  mSceneUpdateRequired(false),
36  mSceneUpdateInProgress(false),
37  mSpecialUpdate(false),
38  mExclusiveModuleId(0)
39  {
40  mTimestamp = QDateTime::currentDateTime();
41  connect(MainWindow::sSettingStyle,&SettingsItemDropdown::intChanged,this,&GraphContext::handleStyleChanged);
42  connect(gNetlistRelay, &NetlistRelay::moduleNameChanged, this, &GraphContext::handleModuleNameChanged);
43  connect(this, &GraphContext::exclusiveModuleLost, this, &GraphContext::handleExclusiveModuleLost);
44  }
45 
47  {
49  if (mParentWidget) mParentWidget->handleContextAboutToBeDeleted();
50  delete mLayouter;
51  delete mShader;
52  }
53 
55  {
56  assert(layouter);
57 
58  if (mLayouter)
59  delete mLayouter;
60 
61  mLayouter = layouter;
62  }
63 
65  {
66  assert(shader);
67 
68  if (mShader)
69  delete mShader;
70 
71  mShader = shader;
72  }
73 
75  {
76  ++mUserUpdateCount;
77  }
78 
80  {
81  --mUserUpdateCount;
82  if (mUserUpdateCount == 0)
83  {
84  evaluateChanges();
85  update();
86  }
87  }
88 
89  void GraphContext::add(const QSet<u32>& modules, const QSet<u32>& gates, PlacementHint placement)
90  {
91  QSet<u32> new_modules = modules - mModules;
92  QSet<u32> new_gates = gates - mGates;
93 
94  QSet<u32> old_modules = mRemovedModules & modules;
95  QSet<u32> old_gates = mRemovedGates & gates;
96 
97  // if we have a placement hint for the added nodes, we ignore it and leave
98  // the nodes where they are (i.e. we just deschedule their removal and not
99  // re-run the placement algo on them)
100  mRemovedModules -= old_modules;
101  mRemovedGates -= old_gates;
102 
103  mAddedModules += new_modules;
104  mAddedGates += new_gates;
105 
106  mPlacementList[placement.mode()].append(
107  PlacementEntry(placement,new_modules,new_gates));
108 
109  if (mUserUpdateCount == 0)
110  {
111  evaluateChanges();
112  update();
113  }
114  if (!new_modules.isEmpty() || !new_gates.isEmpty()) setDirty(true);
115  }
116 
117  void GraphContext::remove(const QSet<u32>& modules, const QSet<u32>& gates)
118  {
119  QSet<u32> old_modules = modules & mModules;
120  QSet<u32> old_gates = gates & mGates;
121 
122  mRemovedModules += old_modules;
123  mRemovedGates += old_gates;
124 
125  mAddedModules -= modules;
126  mAddedGates -= gates;
127 
128  // We don't update mPlacementList here. Keeping elements
129  // in memory is less of an issue than finding the modules/gates _by value_
130  // in the maps and removing them. At the end of applyChanges() the lists are
131  // cleared anyway.
132 
133  if (mUserUpdateCount == 0)
134  {
135  evaluateChanges();
136  update();
137  }
138  if (!old_modules.isEmpty() || !old_gates.isEmpty()) setDirty(true);
139  }
140 
142  {
143  mRemovedModules = mModules;
144  mRemovedGates = mGates;
145 
146  mAddedModules.clear();
147  mAddedGates.clear();
148 
149  for (int i=0; i<4; i++)
150  mPlacementList[i].clear();
151 
152  if (mUserUpdateCount == 0)
153  {
154  evaluateChanges();
155  update();
156  }
157  }
158 
160  {
161  QSet<u32> containedGates = mGates + mAddedGates - mRemovedGates;
162  return containedGates.contains(gateId);
163  }
164 
165  bool GraphContext::isModuleUnfolded(const u32 moduleId) const
166  {
167  QSet<u32> containedGates = mGates + mAddedGates - mRemovedGates;
168  QSet<u32> containedModules = mModules + mAddedModules - mRemovedModules;
169 
170  auto m = gNetlist->get_module_by_id(moduleId);
171 
172  for (const Gate* g : m->get_gates())
173  {
174  if (!containedGates.contains(g->get_id())) return false;
175  }
176  for (const Module* sm : m->get_submodules())
177  {
178  if (!isModuleUnfolded(sm->get_id()) && !containedModules.contains(sm->get_id()))
179  return false;
180  }
181  return true;
182  }
183 
184  void GraphContext::unfoldModule(const u32 id, const PlacementHint& plc)
185  {
186  auto contained_modules = mModules + mAddedModules - mRemovedModules;
187 
188  if (contained_modules.find(id) != contained_modules.end())
189  {
190  auto m = gNetlist->get_module_by_id(id);
193 
194  Node singleContentNode;
195  PlacementHint childPlc;
196 
197  for (const Gate* g : m->get_gates())
198  {
199  singleContentNode = Node(g->get_id(),Node::Gate);
200  gates.insert(g->get_id());
201  }
202  for (const Module* sm : m->get_submodules())
203  {
204  singleContentNode = Node(sm->get_id(),Node::Module);
205  modules.insert(sm->get_id());
206  }
207 
208  if (plc.mode() == PlacementHint::GridPosition)
209  {
210  // placement determined by caller
211  childPlc = plc;
212  }
213  else if (gates.size() + modules.size() == 1)
214  {
215  // There is only a single child in this module, keep the grid position
217  NetLayoutPoint childPos = mLayouter->positonForNode(Node(id,Node::Module));
218  if (!childPos.isUndefined())
219  childPlc.addGridPosition(singleContentNode,childPos);
220  }
221 
222  // That would unfold the empty module into nothing, meaning there would
223  // be no way back
224  assert(!gates.empty() || !modules.empty());
225 
226  beginChange();
227  mLayouter->prepareRollback();
228  remove({id}, {});
229  add(modules, gates, childPlc);
230  endChange();
231  }
232  }
233 
234  bool GraphContext::empty() const
235  {
236  return mGates.empty() && mModules.empty();
237  }
238 
240  {
241  QSet<u32> tempMod = mModules + mAddedModules - mRemovedModules;
242  QSet<u32> tempGat = mGates + mAddedGates - mRemovedGates;
243  return tempMod.isEmpty() && tempGat.isEmpty();
244  }
245 
246  void GraphContext::testIfAffected(const u32 id, const u32* moduleId, const u32* gateId)
247  {
248  if (testIfAffectedInternal(id, moduleId, gateId))
250  }
251 
252  bool GraphContext::testIfAffectedInternal(const u32 id, const u32* moduleId, const u32* gateId)
253  {
254  Node nd(id,Node::Module);
255  if (getLayouter()->boxes().boxForNode(nd))
256  return true;
257 
258  std::vector<Gate*> modifiedGates;
259  if (moduleId)
260  {
261  Module* m = gNetlist->get_module_by_id(*moduleId);
262  if (m) modifiedGates = m->get_gates(nullptr,true);
263  }
264  if (gateId)
265  {
266  Gate* g = gNetlist->get_gate_by_id(*gateId);
267  if (g) modifiedGates.push_back(g);
268  }
269  for (Gate* mg : modifiedGates)
270  if (getLayouter()->boxes().boxForGate(mg))
271  return true;
272 
273  return false;
274  }
275 
276  void GraphContext::removeModuleContents(const u32 moduleId)
277  {
278  QSet<u32> childGates;
279  QSet<u32> childModules;
280 
281  for (const Gate* g : gNetlist->get_module_by_id(moduleId)->get_gates(nullptr, true))
282  {
283  childGates.insert(g->get_id());
284  }
285  for (const Module* sm : gNetlist->get_module_by_id(moduleId)->get_submodules(nullptr, true))
286  {
287  childModules.insert(sm->get_id());
288  }
289  remove(childModules, childGates);
290  }
291 
292  bool GraphContext::isShowingModule(const u32 id) const
293  {
294  return isShowingModule(id, {}, {}, {}, {});
295  }
296 
297  bool GraphContext::isShowingModule(const u32 id, const QSet<u32>& minus_modules, const QSet<u32>& minus_gates, const QSet<u32>& plus_modules, const QSet<u32>& plus_gates) const
298  {
299  // There are all sorts of problems when we allow this, since now any empty
300  // module thinks that it is every other empty module. Blocking this,
301  // however, essentially means that we must destroy all empty contexts:
302  // With the block in place, a context won't recognize it's module anymore
303  // once the last gate has removed, so adding a new gate won't update the
304  // context.
305  if (empty())
306  {
307  return false;
308  }
309 
310  // TODO deduplicate
313 
315 
316  auto contextGates = (mGates - mRemovedGates) + mAddedGates;
317  auto contextModules = (mModules - mRemovedModules) + mAddedModules;
318  auto moduleGates = (gates - minus_gates) + plus_gates;
319  auto moduleModules = (modules - minus_modules) + plus_modules;
320 
321  return contextGates == moduleGates && contextModules == moduleModules;
322  }
323 
324 
326  {
327  auto contextGates = (mGates - mRemovedGates) + mAddedGates;
328  if (!contextGates.isEmpty()) return false;
329  auto contextModules = (mModules - mRemovedModules) + mAddedModules;
330  if (contextModules.size() != 1) return false;
331  return (*mModules.constBegin() == 1); // top_module has ID=1
332  }
333 
334  void GraphContext::getModuleChildrenRecursively(const u32 id, QSet<u32>* gates, QSet<u32>* modules) const
335  {
336 
337  auto containedModules = mModules + mAddedModules - mRemovedModules;
338 
339  Module* m = gNetlist->get_module_by_id(id);
340  if (!m) return;
341 
342  for (const Gate* g : m->get_gates())
343  {
344  gates->insert(g->get_id());
345  }
346  for (const Module* sm : m->get_submodules())
347  {
348  if (!containedModules.contains(sm->get_id()) && isModuleUnfolded(sm->get_id()))
350  else
351  modules->insert(sm->get_id());
352  }
353  }
354 
356  {
357  // Module Context connection is lost when a unfolded submodule (visible in view) is deleted
358  // The connection is lost, because the deletion of an unfolded module does not add its submodules/gates
359  // to the view
360 
361  if (!mExclusiveModuleId) return false;
362 
363  auto containedModules = mModules + mAddedModules - mRemovedModules;
364  auto containedGates = mGates + mAddedGates - mRemovedGates;
365 
366  // folded module
367  if (containedGates.empty() && containedModules.size() == 1 && *containedModules.begin() == mExclusiveModuleId)
368  return true;
369  // unfolded module
370  if (isShowingModule(mExclusiveModuleId, {}, {}, {}, {}))
371  return true;
372  return false;
373  }
374 
375  bool GraphContext::isShowingNetSource(const u32 mNetId) const
376  {
377  auto net = gNetlist->get_net_by_id(mNetId);
378  auto src_pins = net->get_sources();
379 
380  for(auto pin : src_pins)
381  {
382  if(pin->get_gate() != nullptr)
383  {
384  if(mGates.contains(pin->get_gate()->get_id()))
385  return true;
386  }
387  }
388 
389  return false;
390  }
391 
393  {
394  auto net = gNetlist->get_net_by_id(mNetId);
395  auto dst_pins = net->get_destinations();
396 
397  for(auto pin : dst_pins)
398  {
399  if(pin->get_gate() != nullptr)
400  {
401  if(mGates.contains(pin->get_gate()->get_id()))
402  return true;
403  }
404  }
405 
406  return false;
407  }
408 
410  {
411  for (Endpoint* ep : n->get_sources())
412  {
413  Gate* g = ep->get_gate();
414  NodeBox* box = mLayouter->boxes().boxForGate(g);
415  if (box) return box->getNode();
416  }
417  return Node();
418  }
419 
421  {
422  for (Endpoint* ep : n->get_destinations())
423  {
424  Gate* g = ep->get_gate();
425  NodeBox* box = mLayouter->boxes().boxForGate(g);
426  if (box) return box->getNode();
427  }
428  return Node();
429  }
430 
432  {
433  return mModules;
434  }
435 
437  {
438  return mGates;
439  }
440 
442  {
443  return mNets;
444  }
445 
447  {
448  return mLayouter->scene();
449  }
450 
452  {
453  return mId;
454  }
455 
457  {
458  return mName;
459  }
460 
462  {
463  if (mDirty) return mName + "*";
464  return mName;
465  }
466 
468  {
469  return mSceneUpdateInProgress;
470  }
471 
473  {
474  mSceneUpdateRequired = true;
475 
476  if (sLazyUpdates)
477  if (!mParentWidget)
478  return;
479 
480  if(mUserUpdateCount == 0)
481  update();
482  }
483 
485  {
486  if (mGates.contains(id))
487  return Node(id, Node::Gate);
488 
489  Gate* g = gNetlist->get_gate_by_id(id);
490 
491  if (!g)
492  return Node();
493 
494  Module* m = g->get_module();
495 
496  while (m)
497  {
498  if (mModules.contains(m->get_id()))
499  return Node(m->get_id(), Node::Module);
500  m = m->get_parent_module();
501  }
502 
503  return Node();
504  }
505 
506  /*GraphLayouter* GraphContext::debugGetLayouter() const
507  {
508  return mLayouter;
509  }*/
510 
511  void GraphContext::layoutProgress(int percent) const
512  {
513  QString text;
514  if (!percent) text = QString("Layout %1[%2]").arg(mName).arg(mId);
515  if (mParentWidget) mParentWidget->showProgress(percent,text);
516  }
517 
519  {
520  if (mParentWidget) mParentWidget->storeViewport();
521  }
522 
524  {
525  const QMap<QPoint,Node> nodeMap = mLayouter->positionToNodeMap();
526  auto it = nodeMap.find(from);
527  if (it==nodeMap.constEnd()) return;
528  mLayouter->setNodePosition(it.value(),to);
530  }
531 
532  void GraphContext::handleLayouterFinished()
533  {
534  if (mUnappliedChanges)
535  applyChanges();
536 
537  if (mSceneUpdateRequired)
538  {
539  requireSceneUpdate();
540  }
541  else
542  {
543  mShader->update();
544  mLayouter->scene()->updateVisuals(mShader->getShading());
545 
546  mSceneUpdateInProgress = false;
547 
548  mLayouter->scene()->connectAll();
549 
550  if (mParentWidget) mParentWidget->handleSceneAvailable();
551  }
552  }
553 
554  void GraphContext::evaluateChanges()
555  {
556  if (!mAddedGates.isEmpty() || !mRemovedGates.isEmpty() || !mAddedModules.isEmpty() || !mRemovedModules.isEmpty())
557  mUnappliedChanges = true;
558  }
559 
560  void GraphContext::update()
561  {
562  if (mSceneUpdateInProgress)
563  return;
564 
565  storeViewport();
566 
567  if (mUnappliedChanges)
568  applyChanges();
569 
570  if (mSceneUpdateRequired)
571  requireSceneUpdate();
572  }
573 
574  void GraphContext::applyChanges()
575  {
576  // since changes are only applied once in a while added module might not exist any more
577  auto it = mAddedModules.begin();
578  while (it != mAddedModules.end())
579  {
580  if (gNetlist->get_module_by_id(*it))
581  ++it;
582  else
583  it = mAddedModules.erase(it);
584  }
585 
586  mModules -= mRemovedModules;
587  mGates -= mRemovedGates;
588 
589  mModules += mAddedModules;
590  mGates += mAddedGates;
591 
592  mLayouter->remove(mRemovedModules, mRemovedGates, mNets);
593  mShader->remove(mRemovedModules, mRemovedGates, mNets);
594 
595  updateNets();
596 
597  int placementOrder[4] = { PlacementHint::GridPosition,
601 
602  for (int iplc = 0; iplc<4; iplc++)
603  {
604  for (const PlacementEntry& plcEntry : mPlacementList[placementOrder[iplc]])
605  {
606  QSet<u32> modsForHint = plcEntry.mModules;
607  modsForHint &= mAddedModules; // may contain obsolete entries that we must filter out
608  QSet<u32> gatsForHint = plcEntry.mGates;
609  gatsForHint &= mAddedGates;
610  mLayouter->add(modsForHint, gatsForHint, mNets, plcEntry.mPlacementHint);
611  }
612  }
613 
614  mShader->add(mAddedModules, mAddedGates, mNets);
615 
616  mAddedModules.clear();
617  mAddedGates.clear();
618 
619  mRemovedModules.clear();
620  mRemovedGates.clear();
621 
622  for (int i=0; i<4; i++)
623  mPlacementList[i].clear();
624 
625  mUnappliedChanges = false;
626  mSceneUpdateRequired = true;
627  }
628 
630  {
631  mNets.clear();
632  for (const auto& id : mGates)
633  {
634  if (mRemovedGates.contains(id)) continue;
635  auto g = gNetlist->get_gate_by_id(id);
636  if (!g) continue;
637  for (auto net : g->get_fan_in_nets())
638  {
639  //if(!net->is_unrouted() || net->is_global_input_net() || net->is_global_output_net())
640  mNets.insert(net->get_id());
641  }
642  for (auto net : g->get_fan_out_nets())
643  {
644  //if(!net->is_unrouted() || net->is_global_input_net() || net->is_global_output_net())
645  mNets.insert(net->get_id());
646  }
647  }
648  for (const auto& id : mModules)
649  {
650  if (mRemovedModules.contains(id)) continue;
651  auto m = gNetlist->get_module_by_id(id);
652  if (!m) continue;
653  for (auto net : m->get_input_nets())
654  {
655  mNets.insert(net->get_id());
656  }
657  for (auto net : m->get_output_nets())
658  {
659  mNets.insert(net->get_id());
660  }
661  }
662  }
663 
664  void GraphContext::requireSceneUpdate()
665  {
666  if (LayoutLockerManager::instance()->canUpdate(this))
667  startSceneUpdate();
668  }
669 
670  void GraphContext::startSceneUpdate()
671  {
672  mSceneUpdateRequired = false;
673  mSceneUpdateInProgress = true;
674 
675  if (mParentWidget) mParentWidget->handleSceneUnavailable();
676  mLayouter->scene()->disconnectAll();
677 
678  // LayouterTask* task = new LayouterTask(mLayouter);
679  // connect(task, &LayouterTask::finished, this, &GraphContext::handleLayouterFinished, Qt::ConnectionType::QueuedConnection);
680  // gThreadPool->queueTask(task);
681 
683 
684  mLayouter->layout();
685  handleLayouterFinished();
686  }
687 
689  {
690  if (!mSceneUpdateInProgress) return;
691  if (!mLayouter->rollback()) return;
692  mGates.clear();
693  mModules.clear();
694  for (const Node& nd : mLayouter->nodeToPositionMap().keys())
695  {
696  switch (nd.type())
697  {
698  case Node::Module: mModules.insert(nd.id()); break;
699  case Node::Gate: mGates.insert(nd.id()); break;
700  default: break;
701  }
702  }
703  mLayouter->layout();
704  handleLayouterFinished();
705  }
706 
707  void GraphContext::handleStyleChanged(int istyle)
708  {
709  Q_UNUSED(istyle);
710  handleLayouterFinished();
711  }
712 
714  {
717  }
718 
719  void GraphContext::handleModuleNameChanged(Module* m)
720  {
721  if (mExclusiveModuleId == m->get_id())
722  {
723  QString name = QString::fromStdString(m->get_name()) + " (ID: " + QString::number(m->get_id()) + ")";
726  act->exec();
727  }
728  Q_EMIT(dataChanged());
729  }
730 
732  {
733  return mTimestamp;
734  }
735 
737  {
738  if (json.contains("timestamp") && json["timestamp"].isString())
739  mTimestamp = QDateTime::fromString(json["timestamp"].toString());
740 
741  QList<QPair<Node,QPoint>> nodesToPlace;
742 
743  if (json.contains("modules") && json["modules"].isArray())
744  {
745  QJsonArray jsonMods = json["modules"].toArray();
746  int nmods = jsonMods.size();
747  for (int imod=0; imod<nmods; imod++)
748  {
749  QJsonObject jsonMod = jsonMods.at(imod).toObject();
750  if (!jsonMod.contains("id") || !jsonMod["id"].isDouble()) continue;
751  u32 id = jsonMod["id"].toInt();
752  if (!gNetlist->get_module_by_id(id))
753  {
754  log_warning("gui", "Module id={} not found in netlist, view id={} not restored.", id, mId);
755  return false;
756  }
757  if (!jsonMod.contains("x") || !jsonMod["x"].isDouble()) continue;
758  int x = jsonMod["x"].toInt();
759  if (!jsonMod.contains("y") || !jsonMod["y"].isDouble()) continue;
760  int y = jsonMod["y"].toInt();
761  Node nd(id,Node::Module);
762  nodesToPlace.append(QPair<Node,QPoint>(nd,QPoint(x,y)));
763  }
764  }
765 
766  if (json.contains("gates") && json["gates"].isArray())
767  {
768  QJsonArray jsonGats = json["gates"].toArray();
769  int ngats = jsonGats.size();
770  for (int igat=0; igat<ngats; igat++)
771  {
772  QJsonObject jsonGat = jsonGats.at(igat).toObject();
773  if (!jsonGat.contains("id") || !jsonGat["id"].isDouble()) continue;
774  u32 id = jsonGat["id"].toInt();
775  if (!gNetlist->get_gate_by_id(id))
776  {
777  log_warning("gui", "Gate id={} not found in netlist, view id={} not restored.", id, mId);
778  return false;
779  }
780  if (!jsonGat.contains("x") || !jsonGat["x"].isDouble()) continue;
781  int x = jsonGat["x"].toInt();
782  if (!jsonGat.contains("y") || !jsonGat["y"].isDouble()) continue;
783  int y = jsonGat["y"].toInt();
784  Node nd(id,Node::Gate);
785  nodesToPlace.append(QPair<Node,QPoint>(nd,QPoint(x,y)));
786  }
787  }
788 
789  if (nodesToPlace.isEmpty())
790  {
791  log_warning("gui", "Cannot restore view id={}, there are no nodes to place.", mId);
792  return false;
793  }
794 
795  mModules.clear();
796  mGates.clear();
797  for (const QPair<Node,QPoint>& box : nodesToPlace)
798  {
799  if (box.first.type() == Node::Module)
800  mModules.insert(box.first.id());
801  else
802  mGates.insert(box.first.id());
803  mLayouter->setNodePosition(box.first,box.second);
804  }
805  if (mModules.size()==1 && mGates.isEmpty())
806  setExclusiveModuleId(*(mModules.begin()),false);
807 
808  if (json.contains("nets") && json["nets"].isArray())
809  {
810  QJsonArray jsonNets = json["nets"].toArray();
811  int nnets = jsonNets.size();
812  for (int inet=0; inet<nnets; inet++)
813  {
814  QJsonObject jsonNet = jsonNets.at(inet).toObject();
815  if (!jsonNet.contains("id") || !jsonNet["id"].isDouble()) continue;
816  u32 id = jsonNet["id"].toInt();
817  if (!gNetlist->get_net_by_id(id)) return false;
818  mNets.insert(id);
819  }
820  }
821 
822  //scheduleSceneUpdate();
823  setDirty(false);
824  return true;
825  }
826 
827  void GraphContext::writeToFile(QJsonObject& json, int parentId)
828  {
829  json["id"] = (int) mId;
830  json["name"] = mName;
831  json["timestamp"] = mTimestamp.toString();
832  json["exclusiveModuleId"] = (int) mExclusiveModuleId;
833  json["visible"] = gContentManager->getGraphTabWidget()->visibleStatus(this);
834  json["parentId"] = (int) parentId;
836  QJsonArray jsonMods;
837  for (u32 id : mModules)
838  {
840  Q_ASSERT(!pos.isUndefined());
841  QJsonObject jsonMod;
842  jsonMod["id"] = (int) id;
843  jsonMod["x"] = (int) pos.x();
844  jsonMod["y"] = (int) pos.y();
845  jsonMods.append(jsonMod);
846  }
847  json["modules"] = jsonMods;
848 
850  QJsonArray jsonGats;
851  for (u32 id : mGates)
852  {
854  Q_ASSERT(!pos.isUndefined());
855  QJsonObject jsonGat;
856  jsonGat["id"] = (int) id;
857  jsonGat["x"] = (int) pos.x();
858  jsonGat["y"] = (int) pos.y();
859  jsonGats.append(jsonGat);
860  }
861  json["gates"] = jsonGats;
862 
864  QJsonArray jsonNets;
865  for (u32 id : mNets)
866  {
867  QJsonObject jsonNet;
868  jsonNet["id"] = (int) id;
869  jsonNets.append(jsonNet);
870  }
871  json["nets"] = jsonNets;
872  setDirty(false);
873  }
874 
875  void GraphContext::setDirty(bool dty)
876  {
877  if (mDirty==dty) return;
878  mDirty = dty;
879  Q_EMIT(dataChanged());
880  }
881 
882  void GraphContext::setScheduleRemove(const QSet<u32>& mods, const QSet<u32>& gats)
883  {
884  mScheduleRemoveModules = mods;
885  mScheduleRemoveGates = gats;
886  }
887 
889  {
890  switch (nd.type()) {
891  case Node::Module:
892  {
893  auto it = mScheduleRemoveModules.find(nd.id());
894  if (it != mScheduleRemoveModules.end())
895  {
896  mScheduleRemoveModules.erase(it);
897  return true;
898  }
899  break;
900  }
901  case Node::Gate:
902  {
903  auto it = mScheduleRemoveGates.find(nd.id());
904  if (it != mScheduleRemoveGates.end())
905  {
906  mScheduleRemoveGates.erase(it);
907  return true;
908  }
909  break;
910  }
911  default:
912  break;
913  }
914  return false;
915  }
916 
918  {
919  mSpecialUpdate = state;
920  }
921 
923  {
924  if (mParentWidget)
925  mParentWidget->showComments(nd);
926  }
927 
928  void GraphContext::setExclusiveModuleId(u32 id, bool emitSignal)
929  {
930  u32 old_id = mExclusiveModuleId;
931  mExclusiveModuleId = id;
932 
933  // Emit signal if context is not showing an exclusive module anymore
934  if ((id == 0 && old_id != 0) && emitSignal)
935  Q_EMIT(exclusiveModuleLost(old_id));
936  }
937 
938  void GraphContext::handleExclusiveModuleLost(u32 old_id)
939  {
940  Module* m = gNetlist->get_module_by_id(old_id);
941  assert(m);
942 
943  u32 cnt = 0;
944  while (true)
945  {
946  ++cnt;
947  QString new_name = QString::fromStdString(m->get_name()) + " modified";
948  if (cnt > 1)
949  {
950  new_name += " (" + QString::number(cnt) + ")";
951  }
952  bool found = false;
953  for (const auto& ctx : gGraphContextManager->getContexts())
954  {
955  if (ctx->name() == new_name)
956  {
957  found = true;
958  break;
959  }
960  }
961  if (!found)
962  {
963  ActionRenameObject* act = new ActionRenameObject(new_name);
964  act->setObject(UserActionObject(this->id(),UserActionObjectType::ContextView));
965  act->exec();
966  break;
967  }
968  }
969  Q_EMIT(dataChanged());
970  }
971 }
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable from
GraphTabWidget * getGraphTabWidget()
Get hal's graph tab widget.
Definition: gate.h:58
bool isModuleUnfolded(const u32 moduleId) const
bool isGateUnfolded(u32 gateId) const
void remove(const QSet< u32 > &modules, const QSet< u32 > &gates)
void setSpecialUpdate(bool state)
void writeToFile(QJsonObject &json, int parentId)
void unfoldModule(const u32 id, const PlacementHint &plc)
void showComments(const Node &nd)
GraphicsScene * scene()
bool readFromFile(const QJsonObject &json)
Node getNetSource(const Net *n) const
bool isShowingModuleExclusively()
void moveNodeAction(const QPoint &from, const QPoint &to)
bool isShowingFoldedTopModule() const
void setDirty(bool dty)
bool isShowingModule(const u32 id) const
void setExclusiveModuleId(u32 id, bool emitSignal=true)
void add(const QSet< u32 > &modules, const QSet< u32 > &gates, PlacementHint placement=PlacementHint())
bool empty() const
void layoutProgress(int percent) const
Node getNetDestination(const Net *n) const
const QSet< u32 > & gates() const
const QSet< u32 > & modules() const
void testIfAffected(const u32 id, const u32 *moduleId, const u32 *gateId)
Node nodeForGate(const u32 id) const
void exclusiveModuleLost(u32 old_id)
void setScheduleRemove(const QSet< u32 > &mods, const QSet< u32 > &gats)
void setShader(GraphShader *shader)
bool isScheduledRemove(const Node &nd)
QDateTime getTimestamp() const
GraphLayouter * getLayouter() const
GraphContext(u32 id_, const QString &name, QObject *parent=nullptr)
bool willBeEmptied() const
QString getNameWithDirtyState() const
void setLayouter(GraphLayouter *layouter)
QString name() const
const QSet< u32 > & nets() const
bool isShowingNetSource(const u32 mNetId) const
bool sceneUpdateInProgress() const
bool isShowingNetDestination(const u32 mNetId) const
void getModuleChildrenRecursively(const u32 moduleId, QSet< u32 > *gates, QSet< u32 > *modules) const
QVector< GraphContext * > getContexts() const
Base class for all specific layouters.
virtual void remove(const QSet< u32 > modules, const QSet< u32 > gates, const QSet< u32 > nets)=0
void setNodePosition(const Node &n, const QPoint &p)
virtual void add(const QSet< u32 > modules, const QSet< u32 > gates, const QSet< u32 > nets, PlacementHint placement=PlacementHint())=0
const QMap< QPoint, Node > positionToNodeMap() const
NetLayoutPoint positonForNode(const Node &nd) const
const QMap< Node, QPoint > nodeToPositionMap() const
GraphicsScene * scene() const
const NodeBoxes & boxes() const
Base class to store and update visual information about the graph.
Definition: graph_shader.h:47
virtual void add(const QSet< u32 > modules, const QSet< u32 > gates, const QSet< u32 > nets)=0
virtual void update()=0
virtual void remove(const QSet< u32 > modules, const QSet< u32 > gates, const QSet< u32 > nets)=0
const Shading & getShading()
int visibleStatus(const GraphContext *ctx) const
void handleSceneUnavailable()
void showProgress(int percent, const QString &text=QString())
void handleSceneAvailable()
void showComments(const Node &nd)
void handleContextAboutToBeDeleted()
Container for a GraphGraphicsView containing gates, nets, and modules.
void updateVisuals(const GraphShader::Shading &s)
static LayoutLockerManager * instance()
void removeWaitingContext(GraphContext *ctx)
static SettingsItemDropdown * sSettingStyle
Definition: main_window.h:302
Module * get_parent_module() const
Definition: module.cpp:125
const std::vector< Gate * > & get_gates() const
Definition: module.cpp:391
std::string get_name() const
Definition: module.cpp:87
const std::unordered_set< Net * > & get_input_nets() const
Definition: module.cpp:540
std::vector< Module * > get_submodules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=false) const
Definition: module.cpp:259
const std::unordered_set< Net * > & get_output_nets() const
Definition: module.cpp:545
u32 get_id() const
Definition: module.cpp:82
Definition: net.h:58
bool isUndefined() const
Gate * get_gate_by_id(const u32 gate_id) const
Definition: netlist.cpp:193
Module * get_module_by_id(u32 module_id) const
Definition: netlist.cpp:613
Net * get_net_by_id(u32 net_id) const
Definition: netlist.cpp:353
void moduleNameChanged(Module *m) const
The NodeBox class represents a node placed at a grid position within a hal view.
Definition: node_box.h:50
Node getNode() const
getNode getter for node information
Definition: node_box.h:75
NodeBox * boxForGate(const Gate *g) const
boxForGate find NodeBox by Gate pointer.
Definition: node_box.h:184
The Node class object represents a module or a gate.
Definition: gui_def.h:61
NodeType type() const
type getter for type information
Definition: gui_def.h:71
@ Module
Definition: gui_def.h:63
@ Gate
Definition: gui_def.h:63
u32 id() const
id getter for ID information
Definition: gui_def.h:77
Container class to store a PlacementHint togerther with a set of modules and gates.
Definition: gui_def.h:283
The PlacementHint class object provides hints for the layouter how new box objects are placed on a vi...
Definition: gui_def.h:196
void addGridPosition(const Node &nd, const QPoint &p)
Definition: gui_def.h:263
PlacementModeType mode() const
mode getter for placement mode type
Definition: gui_def.h:223
void intChanged(int value)
virtual void setObject(const UserActionObject &obj)
Definition: user_action.cpp:32
The UserActionObject class represents a single object used in UserAction.
#define log_warning(channel,...)
Definition: log.h:76
S to(const T &str)
ContentManager * gContentManager
Definition: plugin_gui.cpp:78
GraphContextManager * gGraphContextManager
Definition: plugin_gui.cpp:85
Netlist * gNetlist
Definition: plugin_gui.cpp:80
NetlistRelay * gNetlistRelay
Definition: plugin_gui.cpp:81
n
Definition: test.py:6
quint32 u32
Net * net
std::string name
QDateTime currentDateTime()
QDateTime fromString(const QString &string, Qt::DateFormat format)
QString toString(Qt::DateFormat format) const const
void append(const QJsonValue &value)
QJsonValue at(int i) const const
int size() const const
bool contains(const QString &key) const const
QJsonObject toObject() const const
void append(const T &value)
bool isEmpty() const const
QMap::const_iterator constEnd() const const
QMap::iterator find(const Key &key)
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int x() const const
int y() const const
QSet::iterator begin()
void clear()
QSet::const_iterator constBegin() const const
bool contains(const T &value) const const
bool empty() const const
QSet::iterator end()
QSet::iterator erase(QSet::iterator pos)
QSet::iterator find(const T &value)
QSet::iterator insert(const T &value)
bool isEmpty() const const
int size() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromStdString(const std::string &str)
QString number(int n, int base)