HAL
graph_context_manager.cpp
Go to the documentation of this file.
2 
11 #include "gui/gui_globals.h"
17 #include "hal_core/netlist/gate.h"
20 #include "hal_core/utilities/log.h"
21 
22 #include <QDateTime>
23 #include <QFile>
24 #include <QJsonArray>
25 #include <QJsonDocument>
26 #include <QJsonObject>
27 #include <QTextStream>
28 #include <QDir>
29 
30 namespace hal
31 {
32  SettingsItemCheckbox* GraphContextManager::sSettingNetGroupingToPins = new SettingsItemCheckbox("Net Grouping Color to Gate Pins",
33  "graph_view/net_grp_pin",
34  true,
35  "Appearance:Graph View",
36  "If set net grouping colors are also applied to input and output pins of gates");
37 
38  SettingsItemCheckbox* GraphContextManager::sSettingPanOnMiddleButton = new SettingsItemCheckbox("Pan with Middle Mouse Button",
39  "graph_view/pan_middle_button",
40  false,
41  "Graph View",
42  "If enabled middle mouse button will pan the graphics.\n"
43  "If disabled middle mouse button can be used for rubber band selection.");
44 
45  SettingsItemCheckbox* GraphContextManager::sSettingLayoutOnEveryChange = new SettingsItemCheckbox("Invoke Layout on Every Change",
46  "graph_view/layout_on_chage",
47  false,
48  "Graph View",
49  "If enabled every change will invoke layout() routine,\n"
50  "which will not happen upon rename and recolor otherwise.");
51 
53  : mMaxContextId(0)
54  {
55  mContextTreeModel = new ContextTreeModel(this);
56  mSettingDebugGrid = new SettingsItemCheckbox("GUI Debug Grid",
57  "debug/grid",
58  false,
59  "eXpert Settings:Debug",
60  "Specifies whether the debug grid is displayed in the Graph View. The gird represents the scene as the layouter interprets it.");
61 
62  mSettingDumpJunction = new SettingsItemCheckbox("Dump Junction Data",
63  "debug/junction",
64  false,
65  "eXpert Settings:Debug",
66  "Dump input data from junction router to file 'junction_data.txt' for external debugging.");
67 
68  mSettingParseLayout = new SettingsItemCheckbox("Apply Parsed Position", "graph_view/layout_parse", true, "Graph View", "Use parsed verilog coordinates if available.");
69 
70  mSettingLayoutBoxes = new SettingsItemCheckbox("Optimize Box Layout", "graph_view/layout_boxes", true, "Graph View", "If disabled faster randomized placement.");
71  }
72 
74  {
75  ContextDirectory* contextDir = mContextTreeModel->addDirectory(name, mContextTreeModel->getDirectory(parentId), ++mMaxContextId);
76  return contextDir;
77  }
78 
79 
80  bool GraphContextManager::moveItem(u32 itemId, bool isDirectory, u32 parentId, int row)
81  {
82  ContextTreeItem* itemToMove = nullptr;
83  if (isDirectory)
84  itemToMove = dynamic_cast<ContextTreeItem*>(mContextTreeModel->getDirectory(itemId));
85  else
86  itemToMove = dynamic_cast<ContextTreeItem*>(mContextTreeModel->getContext(itemId));
87 
88  BaseTreeItem* parentItem = parentId
89  ? mContextTreeModel->getDirectory(parentId)
90  : mContextTreeModel->getRootItem();
91  if (!parentItem || !itemToMove) return false;
92 
93  return mContextTreeModel->moveItem(itemToMove, parentItem, row);
94  }
95 
96 
97 
98  u32 GraphContextManager::getParentId(u32 childId, bool isDirectory) const
99  {
100  if (isDirectory)
101  {
102  BaseTreeItem* bti = mContextTreeModel->getDirectory(childId);
103  ContextTreeItem* parentItem = dynamic_cast<ContextTreeItem*>(bti->getParent());
104  if (parentItem) return parentItem->getId();
105  return 0;
106  }
107  GraphContext* context = getContextById(childId);
108  if (!context) return 0;
109  QModelIndex inx = mContextTreeModel->getIndexFromContext(context);
110  if (!inx.isValid()) return 0;
111  BaseTreeItem* bti =mContextTreeModel->getItemFromIndex(inx);
112  if (!bti) return 0;
113  ContextTreeItem* parentItem = dynamic_cast<ContextTreeItem*>(bti->getParent());
114  if (parentItem) return parentItem->getId();
115  return 0;
116  }
117 
119  {
120  GraphContext* context = new GraphContext(++mMaxContextId, name);
121  context->setLayouter(getDefaultLayouter(context));
122  context->setShader(getDefaultShader(context));
123 
124  context->scene()->setDebugGridEnabled(mSettingDebugGrid->value().toBool());
125  connect(mSettingDebugGrid, &SettingsItemCheckbox::boolChanged, context->scene(), &GraphicsScene::setDebugGridEnabled);
126 
127  mContextTreeModel->addContext(context, mContextTreeModel->getDirectory(parentId));
128 
129  Q_EMIT contextCreated(context);
130 
131  return context;
132  }
133 
135  {
136  if (!ctx || ctx->id() == ctxId)
137  return; // nothing to do
138  if (getContextById(ctxId))
139  return; // id is in use
140  ctx->mId = ctxId;
141  if (ctxId > mMaxContextId)
142  mMaxContextId = ctxId;
143  }
144 
145  void GraphContextManager::openModuleInView(u32 moduleId, bool unfold)
146  {
147  const Module* module = gNetlist->get_module_by_id(moduleId);
148 
149  if (!module)
150  return;
151 
152  GraphContext* moduleContext =
154  if (moduleContext)
155  {
156  // open existing view
159  }
160  else
161  {
163  act->setUseCreatedObject();
164  QString name = QString::fromStdString(module->get_name()) + " (ID: " + QString::number(moduleId) + ")";
166  act->addAction(new ActionAddItemsToObject({module->get_id()}, {}));
167  if (unfold) act->addAction(new ActionUnfoldModule(module->get_id()));
168  act->exec();
169  moduleContext = gGraphContextManager->getContextById(act->object().id());
170  moduleContext->setDirty(false);
171  moduleContext->setExclusiveModuleId(module->get_id());
172  }
173  }
174 
176  {
177  QString name = gGraphContextManager->nextViewName("Isolated View");
178 
180  act->setUseCreatedObject();
182  act->addAction(new ActionAddItemsToObject({}, {gateId}));
183  act->exec();
184  }
185 
187  QSet<u32> allGates;
188 
189  Net* net = gNetlist->get_net_by_id(netId);
190 
191  PlacementHint plc(PlacementHint::PlacementModeType::GridPosition);
192  int currentY = -(int)(net->get_num_of_sources()/2);
193  for(auto endpoint : net->get_sources()) {
194  u32 id = endpoint->get_gate()->get_id();
195  allGates.insert(id);
196  plc.addGridPosition(Node(id, Node::NodeType::Gate), {0, currentY++});
197  }
198  currentY = -(int)(net->get_num_of_destinations()/2);
199  for(auto endpoint : net->get_destinations()) {
200  u32 id = endpoint->get_gate()->get_id();
201  allGates.insert(id);
202  plc.addGridPosition(Node(id, Node::NodeType::Gate), {1, currentY++});
203  }
204 
205  QString name = gGraphContextManager->nextViewName("Isolated View");
206 
208  act->setUseCreatedObject();
210  auto actionAITO = new ActionAddItemsToObject({}, allGates);
211  actionAITO->setPlacementHint(plc);
212  act->addAction(actionAITO);
213  act->exec();
214  }
215 
217  {
218  ctx->mName = newName;
219 
220  Q_EMIT contextRenamed(ctx);
221  }
222 
224  {
225  ctxDir->setName(newName);
226 
227  Q_EMIT directoryRenamed(ctxDir);
228  }
229 
231  {
232  Q_EMIT deletingContext(ctx);
233 
234  mContextTreeModel->removeContext(ctx);
235 
236  delete ctx;
237  }
238 
240  {
241  Q_EMIT deletingDirectory(ctxDir);
242 
243  mContextTreeModel->removeDirectory(ctxDir);
244 
245  delete ctxDir;
246  }
247 
249  {
250  return mContextTreeModel->list();
251  }
252 
254  {
255  for (GraphContext* ctx : mContextTreeModel->list())
256  {
257  if (ctx->id() == id)
258  return ctx;
259  }
260  return nullptr;
261  }
262 
264  {
265  BaseTreeItem* bti = mContextTreeModel->getDirectory(id);
266  if (bti)
267  {
268  ContextDirectory* directory = static_cast<ContextTreeItem*>(bti)->directory();
269  if (directory) return directory;
270  }
271 
272  return nullptr;
273  }
274 
276  {
277  for (GraphContext* ctx : mContextTreeModel->list())
278  {
279  if (ctx->name() == name && !ctx->isDirty())
280  return ctx;
281  }
282  return nullptr;
283  }
284 
286  {
287  for (GraphContext* ctx : mContextTreeModel->list())
288  {
289  if (ctx->getExclusiveModuleId() == module_id)
290  return ctx;
291  }
292  return nullptr;
293  }
294 
296  {
297  int cnt = 0;
298 
299  for (;;)
300  {
301  QString name = QString("%1 %2").arg(prefix).arg(++cnt);
302  if (!contextWithNameExists(name)) return name;
303  }
304  }
305 
307  {
308  for (GraphContext* ctx : mContextTreeModel->list())
309  {
310  if (ctx->name() == name)
311  {
312  return true;
313  }
314  }
315  return false;
316  }
317 
319  {
320  for (GraphContext* context : mContextTreeModel->list())
321  if (context->getSpecialUpdate())
322  {
323  context->add({m->get_id()}, {});
324  context->setSpecialUpdate(false);
325  }
326  }
327 
329  {
330  for (GraphContext* context : mContextTreeModel->list())
331  {
332  if (context->getExclusiveModuleId() == m->get_id())
333  {
334  context->setExclusiveModuleId(0, false);
335  deleteGraphContext(context);
336  }
337  else if (context->modules().contains(m->get_id()))
338  {
339  context->remove({m->get_id()}, {});
340 
341  if (context->empty() || context->willBeEmptied())
342  deleteGraphContext(context);
343  }
344  }
345  }
346 
348  {
349  for (GraphContext* context : mContextTreeModel->list())
350  if (context->modules().contains(m->get_id()))
352  context->scheduleSceneUpdate();
353  else
354  context->refreshModule(m->get_id());
355  }
356 
358  {
359  for (GraphContext* context : mContextTreeModel->list())
360  if (context->modules().contains(m->get_id()))
362  context->scheduleSceneUpdate();
363  else
364  context->refreshModule(m->get_id());
365  }
366 
368  {
369  auto gates = m->get_gates();
370  QSet<u32> gateIDs;
371  for (auto g : gates)
372  gateIDs.insert(g->get_id());
373  for (GraphContext* context : mContextTreeModel->list())
374  if (context->modules().contains(m->get_id()) // contains module
375  || context->gates().intersects(gateIDs)) // contains gate from module
377  context->scheduleSceneUpdate();
378  else
379  {
380  context->handleLayouterFinished();
381  context->refreshModule(m->get_id());
382  }
383  // a context can contain a gate from a module if it is showing the module
384  // or if it's showing a parent and the module is unfolded
385  }
386 
387  void GraphContextManager::handleModuleSubmoduleAdded(Module* m, const u32 added_module) const
388  {
389  // dump("ModuleSubmoduleAdded", m->get_id(), added_module);
390 
391  QList<u32> module_ids = {};
392  Module* current_module = m;
393 
394  do
395  {
396  module_ids.append(current_module->get_id());
397  current_module = current_module->get_parent_module();
398  } while (current_module);
399 
400  for (GraphContext* context : mContextTreeModel->list())
401  {
402  if (context->isShowingFoldedTopModule()) continue;
403  if (context->isShowingModule(m->get_id(), {added_module}, {}, {}, {}) && !context->isShowingModule(added_module, {}, {}, {}, {}))
404  context->add({added_module}, {});
405  else
406  context->testIfAffected(m->get_id(), &added_module, nullptr);
407 
408  // When the module is unfolded and was moved to another folded module visible in view,
409  // remove all gates and submodules of added_module from view
410  if (context->isShowingModule(added_module, {}, {}, {}, {}))
411  {
412  QSet<u32> modules = context->modules();
413  modules.remove(added_module);
414 
415  // modules : all modules visible in graph context view except recently added
416  // module_ids : all anchestors of recently added module
417  // algorithm : remove 'recently added' module from view if it was moved to
418  // (child or grandchild of) another module visible in view
419  for (u32 id : module_ids)
420  if (modules.contains(id))
421  {
422  context->removeModuleContents(added_module);
423  return;
424  }
425  }
426  }
427  }
428 
430  {
431  // FIXME this also triggers on module deletion (not only moving)
432  // and collides with handleModuleRemoved
433  // dump("ModuleSubmoduleRemoved", m->get_id(), removed_module);
434 
435  for (GraphContext* context : mContextTreeModel->list())
436  {
437  if (context->isShowingFoldedTopModule()) continue;
438  if (context->isScheduledRemove(Node(removed_module,Node::Module)) ||
439  context->isShowingModule(m->get_id(), {}, {}, {removed_module}, {}))
440  context->remove({removed_module}, {});
441  else
442  context->testIfAffected(m->get_id(), &removed_module, nullptr);
443 
444  if (context->empty() || context->willBeEmptied())
445  deleteGraphContext(context);
446  }
447  }
448 
449  void GraphContextManager::handleModuleGateAssigned(Module* m, const u32 inserted_gate) const
450  {
451  // dump("ModuleGateAssigned", m->get_id(), inserted_gate);
452 
453  QList<u32> module_ids = {};
454  Module* current_module = m;
455 
456  do
457  {
458  module_ids.append(current_module->get_id());
459  current_module = current_module->get_parent_module();
460  } while (current_module);
461 
462  for (GraphContext* context : mContextTreeModel->list())
463  {
464  if (context->isShowingFoldedTopModule()) continue;
465  if (context->isShowingModule(m->get_id(), {}, {inserted_gate}, {}, {}))
466  context->add({}, {inserted_gate});
467  else
468  context->testIfAffected(m->get_id(), nullptr, &inserted_gate);
469 
470  if (context->gates().contains(inserted_gate))
471  {
472  QSet<u32> modules = context->modules();
473 
474  for (u32 id : module_ids)
475  if (modules.contains(id))
476  {
477  context->remove({}, {inserted_gate});
478  break;
479  }
480  }
481  }
482  }
483 
485  {
486  // dump("ModuleGateRemoved", m->get_id(), removed_gate);
487  for (GraphContext* context : mContextTreeModel->list())
488  {
489  if (context->isShowingFoldedTopModule()) continue;
490  if (context->isScheduledRemove(Node(removed_gate,Node::Gate)) ||
491  context->isShowingModule(m->get_id(), {}, {}, {}, {removed_gate}))
492  {
493  context->remove({}, {removed_gate});
494  if (context->empty() || context->willBeEmptied())
495  {
496  deleteGraphContext(context);
497  }
498  // when the module is empty, add the empty folded module to the view
499  else if (m->get_gates().empty() && m->get_submodules().empty())
500  {
501  context->add({m->get_id()}, {});
502  }
503  }
504  // if a module is unfolded, then the gate is not deleted from the view
505  // but the color of the gate changes to its new parent's color
506 
507  else
508  context->testIfAffected(m->get_id(), nullptr, &removed_gate);
509 
513  }
514  }
515 
516  void GraphContextManager::dump(const QString& title, u32 mid, u32 xid) const
517  {
518  QTextStream xout(stdout, QIODevice::WriteOnly);
519  xout << "===" << title << "===" << mid << "===" << xid << "===\n";
520  for (Module* m : gNetlist->get_modules())
521  {
522  xout << "M" << m->get_id() << " SM:";
523  for (Module* sm : m->get_submodules())
524  xout << " " << sm->get_id();
525  xout << " G:";
526  for (Gate* g : m->get_gates())
527  xout << " " << g->get_id();
528  xout << "\n";
529  }
530  xout << "gats:";
531  for (Gate* g : gNetlist->get_gates())
532  xout << " " << g->get_id();
533  xout << "\n";
534 
535  for (GraphContext* ctx : mContextTreeModel->list())
536  {
537  xout << "ctx " << ctx->id() << ":";
538  for (hal::Node nd : ctx->getLayouter()->positionToNodeMap().values())
539  {
540  xout << " " << (nd.type() == Node::Module ? 'm' : 'g') << nd.id();
541  }
542  xout << "\n";
543  }
544  xout << "-------\n";
545  }
546 
548  {
549  Q_UNUSED(pev);
550  Q_UNUSED(pgid);
551  for (GraphContext* context : mContextTreeModel->list())
552  if (context->modules().contains(m->get_id()))
553  {
554  context->updateNets();
555  context->scheduleSceneUpdate();
556  }
557  }
558 
560  {
561  for (GraphContext* context : mContextTreeModel->list())
562  if (context->gates().contains(g->get_id()))
563  context->remove({}, {g->get_id()});
564  }
565 
567  {
568  for (GraphContext* context : mContextTreeModel->list())
569  if (context->gates().contains(g->get_id()))
570  context->scheduleSceneUpdate();
571  }
572 
574  {
575  Q_UNUSED(n)
576 
577  // CAN NETS BE CREATED WITH SRC AND DST INFORMATION ?
578  // IF NOT THIS EVENT DOESNT NEED TO BE HANDLED
579  }
580 
582  {
583  for (GraphContext* context : mContextTreeModel->list())
584  if (context->nets().contains(n->get_id()))
585  context->scheduleSceneUpdate();
586  }
587 
589  {
590  for (GraphContext* context : mContextTreeModel->list())
591  if (context->nets().contains(n->get_id()))
592  context->scheduleSceneUpdate();
593  }
594 
595  void GraphContextManager::handleNetSourceAdded(Net* n, const u32 src_gate_id) const
596  {
597  for (GraphContext* context : mContextTreeModel->list())
598  {
599  if (context->nets().contains(n->get_id()) || context->gates().contains(src_gate_id))
600  {
601  // forcibly apply changes since nets need to be recalculated
602  context->applyChanges();
603  context->scheduleSceneUpdate();
604  }
605  }
606  }
607 
608  void GraphContextManager::handleNetSourceRemoved(Net* n, const u32 src_gate_id) const
609  {
610  UNUSED(src_gate_id);
611 
612  for (GraphContext* context : mContextTreeModel->list())
613  {
614  if (context->nets().contains(n->get_id()))
615  {
616  // forcibly apply changes since nets need to be recalculated
617  context->applyChanges();
618  context->scheduleSceneUpdate();
619  }
620  }
621  }
622 
623  void GraphContextManager::handleNetDestinationAdded(Net* n, const u32 dst_gate_id) const
624  {
625  for (GraphContext* context : mContextTreeModel->list())
626  {
627  if (context->nets().contains(n->get_id()) || context->gates().contains(dst_gate_id))
628  {
629  // forcibly apply changes since nets need to be recalculated
630  context->applyChanges();
631  context->scheduleSceneUpdate();
632  }
633  }
634  }
635 
637  {
638  UNUSED(dst_gate_id);
639 
640  for (GraphContext* context : mContextTreeModel->list())
641  {
642  if (context->nets().contains(n->get_id()))
643  {
644  // forcibly apply changes since nets need to be recalculated
645  context->applyChanges();
646  context->scheduleSceneUpdate();
647  }
648  }
649  }
650 
652  {
653  for (GraphContext* context : mContextTreeModel->list())
654  {
655  if (context->nets().contains(mNetId) || context->isShowingNetDestination(mNetId))
656  {
657  context->applyChanges();
658  context->scheduleSceneUpdate();
659  }
660  }
661  }
662 
664  {
665  for (GraphContext* context : mContextTreeModel->list())
666  {
667  if (context->nets().contains(mNetId) || context->isShowingNetSource(mNetId))
668  {
669  context->applyChanges();
670  context->scheduleSceneUpdate();
671  }
672  }
673  }
674 
676  {
677  for (GraphContext* context : mContextTreeModel->list())
678  if (context->nets().contains(mNetId))
679  {
680  context->applyChanges();
681  context->scheduleSceneUpdate();
682  }
683  }
684 
686  {
687  for (GraphContext* context : mContextTreeModel->list())
688  if (context->nets().contains(mNetId))
689  {
690  context->applyChanges();
691  context->scheduleSceneUpdate();
692  }
693  }
694 
696  {
697  StandardGraphLayouter* layouter = new StandardGraphLayouter(context);
698  layouter->setDumpJunctionEnabled(mSettingDumpJunction->value().toBool());
699  layouter->setParseLayoutEnabled(mSettingParseLayout->value().toBool());
700  layouter->setLayoutBoxesEnabled(mSettingLayoutBoxes->value().toBool());
701 
705 
706  return layouter;
707  }
708 
710  {
711  return new ModuleShader(context);
712  }
713 
715  {
716  return mContextTreeModel;
717  }
718 
720  {
721  for (GraphContext* context : mContextTreeModel->list())
722  delete context;
723 
724  mContextTreeModel->clear();
725  }
726 
728  {
729  QFile jsFile(filename);
730  if (!jsFile.open(QIODevice::ReadOnly))
731  return nullptr;
732  QJsonDocument jsonDoc = QJsonDocument::fromJson(jsFile.readAll());
733  const QJsonObject& json = jsonDoc.object();
734  GraphContext* firstContext = nullptr;
735  GraphContext* selectedContext = nullptr;
736 
737  if (json.contains("directories") && json["directories"].isArray())
738  {
739  QJsonArray jsonDirectories = json["directories"].toArray();
740  int ndir = jsonDirectories.size();
741  for (int idir = 0; idir < ndir; idir++)
742  {
743  QJsonObject jsondir = jsonDirectories.at(idir).toObject();
744  if (!jsondir.contains("id") || !jsondir["id"].isDouble())
745  continue;
746  u32 dirId = jsondir["id"].toInt();
747  if (!jsondir.contains("name") || !jsondir["name"].isString())
748  continue;
749  QString dirName = jsondir["name"].toString();
750  if (!jsondir.contains("parentId"))
751  continue;
752  u32 dirParentId = jsondir["parentId"].toInt();
753 
754  BaseTreeItem* dirParent = mContextTreeModel->getRootItem();
755 
756  if (dirParentId != 0)
757  dirParent = mContextTreeModel->getDirectory(dirParentId);
758 
759  if (dirId < 0 || dirId > 0x7FFFFFFF)
760  dirId = ++mMaxContextId;
761 
762  mContextTreeModel->addDirectory(dirName, dirParent, dirId);
763  }
764  }
765  if (json.contains("views") && json["views"].isArray())
766  {
767  QJsonArray jsonViews = json["views"].toArray();
768  int nviews = jsonViews.size();
769  for (int iview = 0; iview < nviews; iview++)
770  {
771  QJsonObject jsonView = jsonViews.at(iview).toObject();
772  if (!jsonView.contains("id") || !jsonView["id"].isDouble())
773  continue;
774  u32 viewId = jsonView["id"].toInt();
775  if (!jsonView.contains("name") || !jsonView["name"].isString())
776  continue;
777  QString viewName = jsonView["name"].toString();
778  if (viewId > mMaxContextId)
779  mMaxContextId = viewId;
780  int visibleFlag = 1; // default to visible before flag was invented
781  if (jsonView.contains("visible"))
782  visibleFlag = jsonView["visible"].toInt();
783 
784  u32 viewParentId = 0;
785  if (!jsonView.contains("parentId"))
786  viewParentId = jsonView["parentId"].toInt();
787 
788  BaseTreeItem* viewParent = mContextTreeModel->getRootItem();
789 
790  if (viewParentId != 0) {
791  viewParent = mContextTreeModel->getDirectory(viewParentId);
792  }
793 
794 
796  if (context)
797  {
798  // load view in existing context
799  context->clear();
800  if (viewName != context->mName)
801  renameGraphContextAction(context,viewName);
802  if (!context->readFromFile(jsonView))
803  {
804  log_warning("gui", "failed to set up existing context ID={} from view file {}.", context->id(), filename.toStdString());
805  continue;
806  }
807  }
808  else
809  {
810  // create new context
811  context = new GraphContext(viewId, viewName);
812  context->setLayouter(getDefaultLayouter(context));
813  context->setShader(getDefaultShader(context));
814  // context->setExclusiveModuleId(exclusiveModuleId); TODO exclusive module ID
815  context->scene()->setDebugGridEnabled(mSettingDebugGrid->value().toBool());
816  connect(mSettingDebugGrid, &SettingsItemCheckbox::boolChanged, context->scene(), &GraphicsScene::setDebugGridEnabled);
817 
818  if (!context->readFromFile(jsonView))
819  {
820  log_warning("gui", "failed to create context context ID={} view file {}.", context->id(), filename.toStdString());
821  deleteGraphContext(context);
822  continue;
823  }
824 
825  mContextTreeModel->addContext(context, viewParent);
826  if (visibleFlag)
827  Q_EMIT contextCreated(context);
828  }
829 
830  if (jsonView.contains("exclusiveModuleId"))
831  context->setExclusiveModuleId(jsonView["exclusiveModuleId"].toInt(),false);
832  if (jsonView.contains("selected"))
833  selectedContext = context;
834  if (visibleFlag==2)
835  selectedContext = context;
836  if (!firstContext)
837  firstContext = context;
838  context->setDirty(false);
839  }
840  }
841  if (selectedContext) return selectedContext;
842  return firstContext;
843  }
844 
846  {
847  QFile jsFile(filename);
848  if (!jsFile.open(QIODevice::WriteOnly))
849  return false;
850 
851  QJsonObject json;
852  QJsonArray jsonViews;
853  for (GraphContext* context : mContextTreeModel->list())
854  {
855  BaseTreeItem* parent = mContextTreeModel->getItemFromIndex(mContextTreeModel->getIndexFromContext(context))->getParent();
856  int parentId = 0;
857  if (parent != mContextTreeModel->getRootItem())
858  parentId = static_cast<ContextTreeItem*>(parent)->directory()->id();
859 
860  QJsonObject jsonView;
861  context->writeToFile(jsonView, parentId);
862  jsonViews.append(jsonView);
863  }
864  json["views"] = jsonViews;
865 
866  QJsonArray jsonDirectories;
867  for (ContextDirectory* directory : mContextTreeModel->directoryList())
868  {
869  QJsonObject jsonDirectory;
870  directory->writeToFile(jsonDirectory);
871  jsonDirectories.append(jsonDirectory);
872  }
873  json["directories"] = jsonDirectories;
874  return (jsFile.write(QJsonDocument(json).toJson(QJsonDocument::Compact)) >= 0); // neg return value indicates error
875  }
876 } // namespace hal
Adds an item to a module or grouping.
void setPlacementHint(PlacementHint hint)
(Future) Base class for all tree models related to the details widget.
virtual BaseTreeItem * getParent() const
BaseTreeItem * getRootItem() const
BaseTreeItem * getItemFromIndex(QModelIndex index) const
ContextManagerWidget * getContextManagerWidget()
void setName(QString name_)
void selectViewContext(GraphContext *context)
Base model for the ContextManagerWidget to manage GraphContexts.
bool moveItem(ContextTreeItem *itemToMove, BaseTreeItem *newParent, int row=-1)
void removeDirectory(ContextDirectory *directory)
const QVector< GraphContext * > & list()
QModelIndex getIndexFromContext(GraphContext *context) const
BaseTreeItem * getDirectory(u32 directoryId) const
void removeContext(GraphContext *context)
ContextDirectory * addDirectory(QString name, BaseTreeItem *parentItem, u32 id)
void addContext(GraphContext *context, BaseTreeItem *parent=nullptr)
const QVector< ContextDirectory * > & directoryList()
BaseTreeItem * getContext(u32 contextId) const
Definition: gate.h:58
Logical container for modules, gates, and nets.
Definition: graph_context.h:55
GraphicsScene * scene()
bool readFromFile(const QJsonObject &json)
void setDirty(bool dty)
void setExclusiveModuleId(u32 id, bool emitSignal=true)
void setShader(GraphShader *shader)
void setLayouter(GraphLayouter *layouter)
void contextRenamed(GraphContext *context)
void handleModuleNameChanged(Module *m) const
static SettingsItemCheckbox * sSettingLayoutOnEveryChange
void renameContextDirectoryAction(ContextDirectory *ctxDir, const QString &newName)
QString nextViewName(const QString &prefix) const
GraphContext * createNewContext(const QString &name, u32 parentId=0)
void handleMarkedGlobalOutput(u32 mNetId)
void renameGraphContextAction(GraphContext *ctx, const QString &newName)
void deleteContextDirectory(ContextDirectory *ctxDir)
void setContextId(GraphContext *ctx, u32 ctxId)
void handleNetNameChanged(Net *n) const
void handleModuleTypeChanged(Module *m) const
GraphContext * getContextById(u32 id) const
bool handleSaveTriggered(const QString &filename)
ContextTreeModel * getContextTreeModel() const
GraphContext * getContextByExclusiveModuleId(u32 module_id) const
void handleMarkedGlobalInput(u32 mNetId)
u32 getParentId(u32 childId, bool isDirectory) const
void handleNetDestinationRemoved(Net *n, const u32 dst_gate_id) const
GraphContext * getCleanContext(const QString &name) const
void handleGateRemoved(Gate *g) const
void handleModuleGateAssigned(Module *m, const u32 inserted_gate) const
bool contextWithNameExists(const QString &name) const
void handleNetSourceRemoved(Net *n, const u32 src_gate_id) const
void handleUnmarkedGlobalOutput(u32 mNetId)
GraphLayouter * getDefaultLayouter(GraphContext *const context) const
void handleUnmarkedGlobalInput(u32 mNetId)
void handleNetDestinationAdded(Net *n, const u32 dst_gate_id) const
void contextCreated(GraphContext *context)
void deleteGraphContext(GraphContext *ctx)
static SettingsItemCheckbox * sSettingPanOnMiddleButton
static SettingsItemCheckbox * sSettingNetGroupingToPins
ContextDirectory * createNewDirectory(const QString &name, u32 parentId=0)
void handleModuleCreated(Module *m) const
void handleModuleSubmoduleAdded(Module *m, const u32 added_module) const
void handleModulePortsChanged(Module *m, PinEvent pev, u32 pgid)
void handleModuleGateRemoved(Module *m, const u32 removed_gate)
bool moveItem(u32 itemId, bool isDirectory, u32 parentId, int row=-1)
void handleModuleColorChanged(Module *m) const
GraphShader * getDefaultShader(GraphContext *const context) const
void directoryRenamed(ContextDirectory *directory)
GraphContext * restoreFromFile(const QString &filename)
void openModuleInView(u32 moduleId, bool unfold)
void handleModuleSubmoduleRemoved(Module *m, const u32 removed_module)
void deletingDirectory(ContextDirectory *directory)
void handleNetSourceAdded(Net *n, const u32 src_gate_id) const
ContextDirectory * getDirectoryById(u32 id) const
void handleGateNameChanged(Gate *g) const
QVector< GraphContext * > getContexts() const
void deletingContext(GraphContext *context)
Base class for all specific layouters.
void setDumpJunctionEnabled(bool enabled)
Base class to store and update visual information about the graph.
Definition: graph_shader.h:47
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
std::vector< Module * > get_submodules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=false) const
Definition: module.cpp:259
u32 get_id() const
Definition: module.cpp:82
Specifically stores/updates visual information about a module and its items.
Definition: module_shader.h:37
Definition: net.h:58
const std::vector< Gate * > & get_gates() const
Definition: netlist.cpp:204
const std::vector< Module * > & get_modules() const
Definition: netlist.cpp:624
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
The Node class object represents a module or a gate.
Definition: gui_def.h:61
@ Module
Definition: gui_def.h:63
@ Gate
Definition: gui_def.h:63
The PlacementHint class object provides hints for the layouter how new box objects are placed on a vi...
Definition: gui_def.h:211
void addGridPosition(const Node &nd, const QPoint &p)
Definition: gui_def.h:278
A SettingsItem representing a Checkbox.
virtual QVariant value() const override
The standard layouter used to layout netlists.
void addAction(UserAction *act)
virtual UserActionObject object() const
Definition: user_action.h:102
#define UNUSED(expr)
Definition: defines.h:49
#define log_warning(channel,...)
Definition: log.h:76
const Module * module(const Gate *g, const NodeBoxes &boxes)
ContentManager * gContentManager
Definition: plugin_gui.cpp:78
PinEvent
Definition: pin_event.h:42
GraphContextManager * gGraphContextManager
Definition: plugin_gui.cpp:85
Netlist * gNetlist
Definition: plugin_gui.cpp:80
n
Definition: test.py:6
quint32 u32
Net * net
std::string name
virtual bool open(QIODevice::OpenMode mode) override
QByteArray readAll()
qint64 write(const char *data, qint64 maxSize)
void append(const QJsonValue &value)
QJsonValue at(int i) const const
int size() const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QJsonObject object() const const
bool contains(const QString &key) const const
QJsonObject toObject() const const
void append(const T &value)
bool isValid() 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)
bool remove(const T &value)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromStdString(const std::string &str)
QString number(int n, int base)
std::string toStdString() const const
bool toBool() const const