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 
46  : mMaxContextId(0)
47  {
48  mContextTreeModel = new ContextTreeModel(this);
49  mSettingDebugGrid = new SettingsItemCheckbox("GUI Debug Grid",
50  "debug/grid",
51  false,
52  "eXpert Settings:Debug",
53  "Specifies whether the debug grid is displayed in the Graph View. The gird represents the scene as the layouter interprets it.");
54 
55  mSettingDumpJunction = new SettingsItemCheckbox("Dump Junction Data",
56  "debug/junction",
57  false,
58  "eXpert Settings:Debug",
59  "Dump input data from junction router to file 'junction_data.txt' for external debugging.");
60 
61  mSettingParseLayout = new SettingsItemCheckbox("Apply Parsed Position", "graph_view/layout_parse", true, "Graph View", "Use parsed verilog coordinates if available.");
62 
63  mSettingLayoutBoxes = new SettingsItemCheckbox("Optimize Box Layout", "graph_view/layout_boxes", true, "Graph View", "If disabled faster randomized placement.");
64  }
65 
67  {
68  ContextDirectory* contextDir = mContextTreeModel->addDirectory(name, mContextTreeModel->getDirectory(parentId), ++mMaxContextId);
69  return contextDir;
70  }
71 
72 
73  bool GraphContextManager::moveItem(u32 itemId, bool isDirectory, u32 parentId, int row)
74  {
75  ContextTreeItem* itemToMove = nullptr;
76  if (isDirectory)
77  itemToMove = dynamic_cast<ContextTreeItem*>(mContextTreeModel->getDirectory(itemId));
78  else
79  itemToMove = dynamic_cast<ContextTreeItem*>(mContextTreeModel->getContext(itemId));
80 
81  BaseTreeItem* parentItem = parentId
82  ? mContextTreeModel->getDirectory(parentId)
83  : mContextTreeModel->getRootItem();
84  if (!parentItem || !itemToMove) return false;
85 
86  return mContextTreeModel->moveItem(itemToMove, parentItem, row);
87  }
88 
89 
90 
91  u32 GraphContextManager::getParentId(u32 childId, bool isDirectory) const
92  {
93  if (isDirectory)
94  {
95  BaseTreeItem* bti = mContextTreeModel->getDirectory(childId);
96  ContextTreeItem* parentItem = dynamic_cast<ContextTreeItem*>(bti->getParent());
97  if (parentItem) return parentItem->getId();
98  return 0;
99  }
100  GraphContext* context = getContextById(childId);
101  if (!context) return 0;
102  QModelIndex inx = mContextTreeModel->getIndexFromContext(context);
103  if (!inx.isValid()) return 0;
104  BaseTreeItem* bti =mContextTreeModel->getItemFromIndex(inx);
105  if (!bti) return 0;
106  ContextTreeItem* parentItem = dynamic_cast<ContextTreeItem*>(bti->getParent());
107  if (parentItem) return parentItem->getId();
108  return 0;
109  }
110 
112  {
113  GraphContext* context = new GraphContext(++mMaxContextId, name);
114  context->setLayouter(getDefaultLayouter(context));
115  context->setShader(getDefaultShader(context));
116 
117  context->scene()->setDebugGridEnabled(mSettingDebugGrid->value().toBool());
118  connect(mSettingDebugGrid, &SettingsItemCheckbox::boolChanged, context->scene(), &GraphicsScene::setDebugGridEnabled);
119 
120  mContextTreeModel->addContext(context, mContextTreeModel->getDirectory(parentId));
121 
122  Q_EMIT contextCreated(context);
123 
124  return context;
125  }
126 
128  {
129  if (!ctx || ctx->id() == ctxId)
130  return; // nothing to do
131  if (getContextById(ctxId))
132  return; // id is in use
133  ctx->mId = ctxId;
134  if (ctxId > mMaxContextId)
135  mMaxContextId = ctxId;
136  }
137 
138  void GraphContextManager::openModuleInView(u32 moduleId, bool unfold)
139  {
140  const Module* module = gNetlist->get_module_by_id(moduleId);
141 
142  if (!module)
143  return;
144 
145  GraphContext* moduleContext =
147  if (moduleContext)
148  {
149  // open existing view
152  }
153  else
154  {
156  act->setUseCreatedObject();
157  QString name = QString::fromStdString(module->get_name()) + " (ID: " + QString::number(moduleId) + ")";
159  act->addAction(new ActionAddItemsToObject({module->get_id()}, {}));
160  if (unfold) act->addAction(new ActionUnfoldModule(module->get_id()));
161  act->exec();
162  moduleContext = gGraphContextManager->getContextById(act->object().id());
163  moduleContext->setDirty(false);
164  moduleContext->setExclusiveModuleId(module->get_id());
165  }
166  }
167 
169  {
170  QString name = gGraphContextManager->nextViewName("Isolated View");
171 
173  act->setUseCreatedObject();
175  act->addAction(new ActionAddItemsToObject({}, {gateId}));
176  act->exec();
177  }
178 
180  QSet<u32> allGates;
181 
182  Net* net = gNetlist->get_net_by_id(netId);
183 
184  PlacementHint plc(PlacementHint::PlacementModeType::GridPosition);
185  int currentY = -(int)(net->get_num_of_sources()/2);
186  for(auto endpoint : net->get_sources()) {
187  u32 id = endpoint->get_gate()->get_id();
188  allGates.insert(id);
189  plc.addGridPosition(Node(id, Node::NodeType::Gate), {0, currentY++});
190  }
191  currentY = -(int)(net->get_num_of_destinations()/2);
192  for(auto endpoint : net->get_destinations()) {
193  u32 id = endpoint->get_gate()->get_id();
194  allGates.insert(id);
195  plc.addGridPosition(Node(id, Node::NodeType::Gate), {1, currentY++});
196  }
197 
198  QString name = gGraphContextManager->nextViewName("Isolated View");
199 
201  act->setUseCreatedObject();
203  auto actionAITO = new ActionAddItemsToObject({}, allGates);
204  actionAITO->setPlacementHint(plc);
205  act->addAction(actionAITO);
206  act->exec();
207  }
208 
210  {
211  ctx->mName = newName;
212 
213  Q_EMIT contextRenamed(ctx);
214  }
215 
217  {
218  ctxDir->setName(newName);
219 
220  Q_EMIT directoryRenamed(ctxDir);
221  }
222 
224  {
225  Q_EMIT deletingContext(ctx);
226 
227  mContextTreeModel->removeContext(ctx);
228 
229  delete ctx;
230  }
231 
233  {
234  Q_EMIT deletingDirectory(ctxDir);
235 
236  mContextTreeModel->removeDirectory(ctxDir);
237 
238  delete ctxDir;
239  }
240 
242  {
243  return mContextTreeModel->list();
244  }
245 
247  {
248  for (GraphContext* ctx : mContextTreeModel->list())
249  {
250  if (ctx->id() == id)
251  return ctx;
252  }
253  return nullptr;
254  }
255 
257  {
258  BaseTreeItem* bti = mContextTreeModel->getDirectory(id);
259  if (bti)
260  {
261  ContextDirectory* directory = static_cast<ContextTreeItem*>(bti)->directory();
262  if (directory) return directory;
263  }
264 
265  return nullptr;
266  }
267 
269  {
270  for (GraphContext* ctx : mContextTreeModel->list())
271  {
272  if (ctx->name() == name && !ctx->isDirty())
273  return ctx;
274  }
275  return nullptr;
276  }
277 
279  {
280  for (GraphContext* ctx : mContextTreeModel->list())
281  {
282  if (ctx->getExclusiveModuleId() == module_id)
283  return ctx;
284  }
285  return nullptr;
286  }
287 
289  {
290  int cnt = 0;
291 
292  for (;;)
293  {
294  QString name = QString("%1 %2").arg(prefix).arg(++cnt);
295  if (!contextWithNameExists(name)) return name;
296  }
297  }
298 
300  {
301  for (GraphContext* ctx : mContextTreeModel->list())
302  {
303  if (ctx->name() == name)
304  {
305  return true;
306  }
307  }
308  return false;
309  }
310 
312  {
313  for (GraphContext* context : mContextTreeModel->list())
314  if (context->getSpecialUpdate())
315  {
316  context->add({m->get_id()}, {});
317  context->setSpecialUpdate(false);
318  }
319  }
320 
322  {
323  for (GraphContext* context : mContextTreeModel->list())
324  {
325  if (context->getExclusiveModuleId() == m->get_id())
326  {
327  context->setExclusiveModuleId(0, false);
328  deleteGraphContext(context);
329  }
330  else if (context->modules().contains(m->get_id()))
331  {
332  context->remove({m->get_id()}, {});
333 
334  if (context->empty() || context->willBeEmptied())
335  deleteGraphContext(context);
336  }
337  }
338  }
339 
341  {
342  for (GraphContext* context : mContextTreeModel->list())
343  if (context->modules().contains(m->get_id()))
344  context->scheduleSceneUpdate();
345  }
346 
348  {
349  for (GraphContext* context : mContextTreeModel->list())
350  if (context->modules().contains(m->get_id()))
351  context->scheduleSceneUpdate();
352  }
353 
355  {
356  auto gates = m->get_gates();
357  QSet<u32> gateIDs;
358  for (auto g : gates)
359  gateIDs.insert(g->get_id());
360  for (GraphContext* context : mContextTreeModel->list())
361  if (context->modules().contains(m->get_id()) // contains module
362  || context->gates().intersects(gateIDs)) // contains gate from module
363  context->scheduleSceneUpdate();
364  // a context can contain a gate from a module if it is showing the module
365  // or if it's showing a parent and the module is unfolded
366  }
367 
368  void GraphContextManager::handleModuleSubmoduleAdded(Module* m, const u32 added_module) const
369  {
370  // dump("ModuleSubmoduleAdded", m->get_id(), added_module);
371 
372  QList<u32> module_ids = {};
373  Module* current_module = m;
374 
375  do
376  {
377  module_ids.append(current_module->get_id());
378  current_module = current_module->get_parent_module();
379  } while (current_module);
380 
381  for (GraphContext* context : mContextTreeModel->list())
382  {
383  if (context->isShowingFoldedTopModule()) continue;
384  if (context->isShowingModule(m->get_id(), {added_module}, {}, {}, {}) && !context->isShowingModule(added_module, {}, {}, {}, {}))
385  context->add({added_module}, {});
386  else
387  context->testIfAffected(m->get_id(), &added_module, nullptr);
388 
389  // When the module is unfolded and was moved to another folded module visible in view,
390  // remove all gates and submodules of added_module from view
391  if (context->isShowingModule(added_module, {}, {}, {}, {}))
392  {
393  QSet<u32> modules = context->modules();
394  modules.remove(added_module);
395 
396  // modules : all modules visible in graph context view except recently added
397  // module_ids : all anchestors of recently added module
398  // algorithm : remove 'recently added' module from view if it was moved to
399  // (child or grandchild of) another module visible in view
400  for (u32 id : module_ids)
401  if (modules.contains(id))
402  {
403  context->removeModuleContents(added_module);
404  return;
405  }
406  }
407  }
408  }
409 
411  {
412  // FIXME this also triggers on module deletion (not only moving)
413  // and collides with handleModuleRemoved
414  // dump("ModuleSubmoduleRemoved", m->get_id(), removed_module);
415 
416  for (GraphContext* context : mContextTreeModel->list())
417  {
418  if (context->isShowingFoldedTopModule()) continue;
419  if (context->isScheduledRemove(Node(removed_module,Node::Module)) ||
420  context->isShowingModule(m->get_id(), {}, {}, {removed_module}, {}))
421  context->remove({removed_module}, {});
422  else
423  context->testIfAffected(m->get_id(), &removed_module, nullptr);
424 
425  if (context->empty() || context->willBeEmptied())
426  deleteGraphContext(context);
427  }
428  }
429 
430  void GraphContextManager::handleModuleGateAssigned(Module* m, const u32 inserted_gate) const
431  {
432  // dump("ModuleGateAssigned", m->get_id(), inserted_gate);
433 
434  QList<u32> module_ids = {};
435  Module* current_module = m;
436 
437  do
438  {
439  module_ids.append(current_module->get_id());
440  current_module = current_module->get_parent_module();
441  } while (current_module);
442 
443  for (GraphContext* context : mContextTreeModel->list())
444  {
445  if (context->isShowingFoldedTopModule()) continue;
446  if (context->isShowingModule(m->get_id(), {}, {inserted_gate}, {}, {}))
447  context->add({}, {inserted_gate});
448  else
449  context->testIfAffected(m->get_id(), nullptr, &inserted_gate);
450 
451  if (context->gates().contains(inserted_gate))
452  {
453  QSet<u32> modules = context->modules();
454 
455  for (u32 id : module_ids)
456  if (modules.contains(id))
457  {
458  context->remove({}, {inserted_gate});
459  break;
460  }
461  }
462  }
463  }
464 
466  {
467  // dump("ModuleGateRemoved", m->get_id(), removed_gate);
468  for (GraphContext* context : mContextTreeModel->list())
469  {
470  if (context->isShowingFoldedTopModule()) continue;
471  if (context->isScheduledRemove(Node(removed_gate,Node::Gate)) ||
472  context->isShowingModule(m->get_id(), {}, {}, {}, {removed_gate}))
473  {
474  context->remove({}, {removed_gate});
475  if (context->empty() || context->willBeEmptied())
476  {
477  deleteGraphContext(context);
478  }
479  // when the module is empty, add the empty folded module to the view
480  else if (m->get_gates().empty() && m->get_submodules().empty())
481  {
482  context->add({m->get_id()}, {});
483  }
484  }
485  // if a module is unfolded, then the gate is not deleted from the view
486  // but the color of the gate changes to its new parent's color
487 
488  else
489  context->testIfAffected(m->get_id(), nullptr, &removed_gate);
490 
494  }
495  }
496 
497  void GraphContextManager::dump(const QString& title, u32 mid, u32 xid) const
498  {
499  QTextStream xout(stdout, QIODevice::WriteOnly);
500  xout << "===" << title << "===" << mid << "===" << xid << "===\n";
501  for (Module* m : gNetlist->get_modules())
502  {
503  xout << "M" << m->get_id() << " SM:";
504  for (Module* sm : m->get_submodules())
505  xout << " " << sm->get_id();
506  xout << " G:";
507  for (Gate* g : m->get_gates())
508  xout << " " << g->get_id();
509  xout << "\n";
510  }
511  xout << "gats:";
512  for (Gate* g : gNetlist->get_gates())
513  xout << " " << g->get_id();
514  xout << "\n";
515 
516  for (GraphContext* ctx : mContextTreeModel->list())
517  {
518  xout << "ctx " << ctx->id() << ":";
519  for (hal::Node nd : ctx->getLayouter()->positionToNodeMap().values())
520  {
521  xout << " " << (nd.type() == Node::Module ? 'm' : 'g') << nd.id();
522  }
523  xout << "\n";
524  }
525  xout << "-------\n";
526  }
527 
529  {
530  Q_UNUSED(pev);
531  Q_UNUSED(pgid);
532  for (GraphContext* context : mContextTreeModel->list())
533  if (context->modules().contains(m->get_id()))
534  {
535  context->updateNets();
536  context->scheduleSceneUpdate();
537  }
538  }
539 
541  {
542  for (GraphContext* context : mContextTreeModel->list())
543  if (context->gates().contains(g->get_id()))
544  context->remove({}, {g->get_id()});
545  }
546 
548  {
549  for (GraphContext* context : mContextTreeModel->list())
550  if (context->gates().contains(g->get_id()))
551  context->scheduleSceneUpdate();
552  }
553 
555  {
556  Q_UNUSED(n)
557 
558  // CAN NETS BE CREATED WITH SRC AND DST INFORMATION ?
559  // IF NOT THIS EVENT DOESNT NEED TO BE HANDLED
560  }
561 
563  {
564  for (GraphContext* context : mContextTreeModel->list())
565  if (context->nets().contains(n->get_id()))
566  context->scheduleSceneUpdate();
567  }
568 
570  {
571  for (GraphContext* context : mContextTreeModel->list())
572  if (context->nets().contains(n->get_id()))
573  context->scheduleSceneUpdate();
574  }
575 
576  void GraphContextManager::handleNetSourceAdded(Net* n, const u32 src_gate_id) const
577  {
578  for (GraphContext* context : mContextTreeModel->list())
579  {
580  if (context->nets().contains(n->get_id()) || context->gates().contains(src_gate_id))
581  {
582  // forcibly apply changes since nets need to be recalculated
583  context->applyChanges();
584  context->scheduleSceneUpdate();
585  }
586  }
587  }
588 
589  void GraphContextManager::handleNetSourceRemoved(Net* n, const u32 src_gate_id) const
590  {
591  UNUSED(src_gate_id);
592 
593  for (GraphContext* context : mContextTreeModel->list())
594  {
595  if (context->nets().contains(n->get_id()))
596  {
597  // forcibly apply changes since nets need to be recalculated
598  context->applyChanges();
599  context->scheduleSceneUpdate();
600  }
601  }
602  }
603 
604  void GraphContextManager::handleNetDestinationAdded(Net* n, const u32 dst_gate_id) const
605  {
606  for (GraphContext* context : mContextTreeModel->list())
607  {
608  if (context->nets().contains(n->get_id()) || context->gates().contains(dst_gate_id))
609  {
610  // forcibly apply changes since nets need to be recalculated
611  context->applyChanges();
612  context->scheduleSceneUpdate();
613  }
614  }
615  }
616 
618  {
619  UNUSED(dst_gate_id);
620 
621  for (GraphContext* context : mContextTreeModel->list())
622  {
623  if (context->nets().contains(n->get_id()))
624  {
625  // forcibly apply changes since nets need to be recalculated
626  context->applyChanges();
627  context->scheduleSceneUpdate();
628  }
629  }
630  }
631 
633  {
634  for (GraphContext* context : mContextTreeModel->list())
635  {
636  if (context->nets().contains(mNetId) || context->isShowingNetDestination(mNetId))
637  {
638  context->applyChanges();
639  context->scheduleSceneUpdate();
640  }
641  }
642  }
643 
645  {
646  for (GraphContext* context : mContextTreeModel->list())
647  {
648  if (context->nets().contains(mNetId) || context->isShowingNetSource(mNetId))
649  {
650  context->applyChanges();
651  context->scheduleSceneUpdate();
652  }
653  }
654  }
655 
657  {
658  for (GraphContext* context : mContextTreeModel->list())
659  if (context->nets().contains(mNetId))
660  {
661  context->applyChanges();
662  context->scheduleSceneUpdate();
663  }
664  }
665 
667  {
668  for (GraphContext* context : mContextTreeModel->list())
669  if (context->nets().contains(mNetId))
670  {
671  context->applyChanges();
672  context->scheduleSceneUpdate();
673  }
674  }
675 
677  {
678  StandardGraphLayouter* layouter = new StandardGraphLayouter(context);
679  layouter->setDumpJunctionEnabled(mSettingDumpJunction->value().toBool());
680  layouter->setParseLayoutEnabled(mSettingParseLayout->value().toBool());
681  layouter->setLayoutBoxesEnabled(mSettingLayoutBoxes->value().toBool());
682 
686 
687  return layouter;
688  }
689 
691  {
692  return new ModuleShader(context);
693  }
694 
696  {
697  return mContextTreeModel;
698  }
699 
701  {
702  for (GraphContext* context : mContextTreeModel->list())
703  delete context;
704 
705  mContextTreeModel->clear();
706  }
707 
709  {
710  QFile jsFile(filename);
711  if (!jsFile.open(QIODevice::ReadOnly))
712  return nullptr;
713  QJsonDocument jsonDoc = QJsonDocument::fromJson(jsFile.readAll());
714  const QJsonObject& json = jsonDoc.object();
715  GraphContext* firstContext = nullptr;
716  GraphContext* selectedContext = nullptr;
717 
718  if (json.contains("directories") && json["directories"].isArray())
719  {
720  QJsonArray jsonDirectories = json["directories"].toArray();
721  int ndir = jsonDirectories.size();
722  for (int idir = 0; idir < ndir; idir++)
723  {
724  QJsonObject jsondir = jsonDirectories.at(idir).toObject();
725  if (!jsondir.contains("id") || !jsondir["id"].isDouble())
726  continue;
727  u32 dirId = jsondir["id"].toInt();
728  if (!jsondir.contains("name") || !jsondir["name"].isString())
729  continue;
730  QString dirName = jsondir["name"].toString();
731  if (!jsondir.contains("parentId"))
732  continue;
733  u32 dirParentId = jsondir["parentId"].toInt();
734 
735  BaseTreeItem* dirParent = mContextTreeModel->getRootItem();
736 
737  if (dirParentId != 0)
738  dirParent = mContextTreeModel->getDirectory(dirParentId);
739 
740  if (dirId < 0 || dirId > 0x7FFFFFFF)
741  dirId = ++mMaxContextId;
742 
743  mContextTreeModel->addDirectory(dirName, dirParent, dirId);
744  }
745  }
746  if (json.contains("views") && json["views"].isArray())
747  {
748  QJsonArray jsonViews = json["views"].toArray();
749  int nviews = jsonViews.size();
750  for (int iview = 0; iview < nviews; iview++)
751  {
752  QJsonObject jsonView = jsonViews.at(iview).toObject();
753  if (!jsonView.contains("id") || !jsonView["id"].isDouble())
754  continue;
755  u32 viewId = jsonView["id"].toInt();
756  if (!jsonView.contains("name") || !jsonView["name"].isString())
757  continue;
758  QString viewName = jsonView["name"].toString();
759  if (viewId > mMaxContextId)
760  mMaxContextId = viewId;
761  int visibleFlag = 1; // default to visible before flag was invented
762  if (jsonView.contains("visible"))
763  visibleFlag = jsonView["visible"].toInt();
764 
765  u32 viewParentId = 0;
766  if (!jsonView.contains("parentId"))
767  viewParentId = jsonView["parentId"].toInt();
768 
769  BaseTreeItem* viewParent = mContextTreeModel->getRootItem();
770 
771  if (viewParentId != 0) {
772  viewParent = mContextTreeModel->getDirectory(viewParentId);
773  }
774 
775 
777  if (context)
778  {
779  // load view in existing context
780  context->clear();
781  if (viewName != context->mName)
782  renameGraphContextAction(context,viewName);
783  if (!context->readFromFile(jsonView))
784  {
785  log_warning("gui", "failed to set up existing context ID={} from view file {}.", context->id(), filename.toStdString());
786  continue;
787  }
788  }
789  else
790  {
791  // create new context
792  context = new GraphContext(viewId, viewName);
793  context->setLayouter(getDefaultLayouter(context));
794  context->setShader(getDefaultShader(context));
795  // context->setExclusiveModuleId(exclusiveModuleId); TODO exclusive module ID
796  context->scene()->setDebugGridEnabled(mSettingDebugGrid->value().toBool());
797  connect(mSettingDebugGrid, &SettingsItemCheckbox::boolChanged, context->scene(), &GraphicsScene::setDebugGridEnabled);
798 
799  if (!context->readFromFile(jsonView))
800  {
801  log_warning("gui", "failed to create context context ID={} view file {}.", context->id(), filename.toStdString());
802  deleteGraphContext(context);
803  continue;
804  }
805 
806  mContextTreeModel->addContext(context, viewParent);
807  if (visibleFlag)
808  Q_EMIT contextCreated(context);
809  }
810 
811  if (jsonView.contains("exclusiveModuleId"))
812  context->setExclusiveModuleId(jsonView["exclusiveModuleId"].toInt(),false);
813  if (jsonView.contains("selected"))
814  selectedContext = context;
815  if (visibleFlag==2)
816  selectedContext = context;
817  if (!firstContext)
818  firstContext = context;
819  context->setDirty(false);
820  }
821  }
822  if (selectedContext) return selectedContext;
823  return firstContext;
824  }
825 
827  {
828  QFile jsFile(filename);
829  if (!jsFile.open(QIODevice::WriteOnly))
830  return false;
831 
832  QJsonObject json;
833  QJsonArray jsonViews;
834  for (GraphContext* context : mContextTreeModel->list())
835  {
836  BaseTreeItem* parent = mContextTreeModel->getItemFromIndex(mContextTreeModel->getIndexFromContext(context))->getParent();
837  int parentId = 0;
838  if (parent != mContextTreeModel->getRootItem())
839  parentId = static_cast<ContextTreeItem*>(parent)->directory()->id();
840 
841  QJsonObject jsonView;
842  context->writeToFile(jsonView, parentId);
843  jsonViews.append(jsonView);
844  }
845  json["views"] = jsonViews;
846 
847  QJsonArray jsonDirectories;
848  for (ContextDirectory* directory : mContextTreeModel->directoryList())
849  {
850  QJsonObject jsonDirectory;
851  directory->writeToFile(jsonDirectory);
852  jsonDirectories.append(jsonDirectory);
853  }
854  json["directories"] = jsonDirectories;
855  return (jsFile.write(QJsonDocument(json).toJson(QJsonDocument::Compact)) >= 0); // neg return value indicates error
856  }
857 } // 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
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:196
void addGridPosition(const Node &nd, const QPoint &p)
Definition: gui_def.h:263
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