HAL
file_manager.cpp
Go to the documentation of this file.
2 
3 #include "gui/gui_globals.h"
18 
19 #include <QDateTime>
20 #include <QFile>
21 #include <QFileInfo>
22 #include <QFileSystemWatcher>
23 #include <QGridLayout>
24 #include <QInputDialog>
25 #include <QMessageBox>
26 #include <QPushButton>
27 #include <QSpacerItem>
28 #include <QTextStream>
29 #include <QApplication>
30 #include <QDir>
31 #include <QRegularExpression>
32 #include <QDebug>
33 #include <QJsonDocument>
34 #include <QJsonObject>
35 
36 namespace hal
37 {
38  FileManager::FileManager(QObject* parent) : QObject(parent), mFileWatcher(new QFileSystemWatcher(this)), mFileOpen(false)
39  {
40  mSettingAutosave = new SettingsItemCheckbox(
41  "Autosave",
42  "advanced/autosave",
43  true,
44  "eXpert Settings:Autosave",
45  "Specifies wheather HAL should autosave."
46  );
47 
48  mSettingAutosaveInterval = new SettingsItemSpinbox(
49  "Autosave Interval",
50  "advanced/autosave_interval",
51  30,
52  "eXpert Settings:Autosave",
53  "Sets after how much time in seconds an autosave will occur."
54  );
55 
56  mAutosaveEnabled = mSettingAutosave->value().toBool();
57  mAutosaveInterval = mSettingAutosaveInterval->value().toInt();
58 
59  if (mAutosaveInterval < 30) // failsafe in case somebody sets "0" in the .ini
60  mAutosaveInterval = 30;
61 
62  connect(mSettingAutosave, &SettingsItemCheckbox::boolChanged, this, [this](bool value){
63  mAutosaveEnabled = value;
64  if (mTimer->isActive())
65  mTimer->start(mAutosaveInterval * 1000);
66  });
67 
68  connect(mSettingAutosaveInterval, &SettingsItemSpinbox::intChanged, this, [this](int value){
69  mAutosaveInterval = value;
70  if (mTimer->isActive())
71  mTimer->start(mAutosaveInterval * 1000);
72  });
73 
74  connect(mFileWatcher, &QFileSystemWatcher::fileChanged, this, &FileManager::handleFileChanged);
75  connect(mFileWatcher, &QFileSystemWatcher::directoryChanged, this, &FileManager::handleDirectoryChanged);
76  mTimer = new QTimer(this);
77  connect(mTimer, &QTimer::timeout, this, &FileManager::autosave);
78  }
79 
80  FileManager* FileManager::get_instance()
81  {
82  static FileManager manager;
83  return &manager;
84  }
85 
86  bool FileManager::fileOpen() const
87  {
88  return mFileOpen;
89  }
90 
91  void FileManager::autosave()
92  {
93  ProjectManager* pm = ProjectManager::instance();
94  if (pm->get_project_status() != ProjectManager::ProjectStatus::NONE && mAutosaveEnabled)
95  {
96  if (gPythonContext->pythonThread())
97  {
98  log_info("gui", "Autosave deferred while python script is running...");
99  return;
100  }
101  log_info("gui", "saving a backup in case something goes wrong...");
102  if (!ProjectManager::instance()->serialize_project(gNetlist, true))
103  log_warning("gui", "Autosave failed to create project backup to directory '{}'.", pm->get_project_directory().get_shadow_dir().string());
104  }
105  }
106 
107  QString FileManager::fileName() const
108  {
109  if (mFileOpen)
110  return mFileName;
111 
112  return QString();
113  }
114 
115  void FileManager::watchFile(const QString& fileName)
116  {
117  if (fileName == mFileName)
118  {
119  return;
120  }
121 
122  if (!mFileName.isEmpty())
123  {
124  mFileWatcher->removePath(mFileName);
125  removeShadowDirectory();
126  }
127 
128  mTimer->stop();
129 
130  if (!fileName.isEmpty())
131  {
132  log_info("gui", "watching current file '{}'", fileName.toStdString());
133 
134  // autosave periodically
135  // (we also start the timer if autosave is disabled since it's way
136  // easier to just do nothing when the timer fires instead of messing
137  // with complicated start/stop conditions)
138  mTimer->start(mAutosaveInterval * 1000);
139 
140  mFileName = fileName;
141  mFileWatcher->addPath(mFileName);
142  mFileOpen = true;
143  updateRecentFiles(mFileName);
144  }
145  }
146 
147  void FileManager::emitProjectSaved(QString& projectDir, QString& file)
148  {
149  Q_EMIT projectSaved(projectDir, file);
150  }
151 
152  void FileManager::projectSuccessfullyLoaded(QString& projectDir, QString& file)
153  {
154  watchFile(file);
155  Q_EMIT projectOpened(projectDir, file);
158  ProjectManager::instance()->set_project_status(ProjectManager::ProjectStatus::OPENED);
159  }
160 
161 
162  FileManager::DirectoryStatus FileManager::directoryStatus(const QString& pathname)
163  {
164  QFileInfo info(pathname);
165  if (!info.exists()) return NotExisting;
166 
167  if (info.isFile())
168  {
170  return IsFile;
171  else
172  return InvalidExtension;
173  }
174 
175  if (info.isDir())
176  {
177  if (!info.suffix().isEmpty()) return InvalidExtension;
178  QFile ff(QDir(pathname).absoluteFilePath(QString::fromStdString(ProjectManager::s_project_file)));
179  if (ff.exists())
180  {
181  if (!ff.open(QIODevice::ReadOnly))
182  return ParseError;
183  QJsonParseError err;
184  QJsonDocument doc = QJsonDocument::fromJson(ff.readAll(),&err);
185  if (err.error != QJsonParseError::NoError)
186  return ParseError;
187  if (!doc.isObject())
188  return ParseError;
189  if (!doc.object().contains("netlist"))
190  return NetlistError;
191  QString nl = doc.object()["netlist"].toString();
192  if (nl.isEmpty()) return NetlistError;
193  if (QFileInfo(nl).isAbsolute())
194  {
195  if (!QFileInfo(nl).exists())
196  return NetlistError;
197  }
198  else
199  {
200  if (!QFileInfo(QDir(pathname).absoluteFilePath(nl)).exists())
201  return NetlistError;
202  }
203  QString gl = doc.object()["gate_library"].toString();
204  if (gl.isEmpty()) return GatelibError;
205  if (QFileInfo(gl).isAbsolute())
206  {
207  if (!QFileInfo(gl).exists())
208  return GatelibError;
209  }
210  else
211  {
212  if (!QFileInfo(QDir(pathname).absoluteFilePath(gl)).exists())
213  return GatelibError;
214  }
215  return ProjectDirectory;
216  }
217  else
218  return OtherDirectory;
219  }
220 
221  return UnknownDirectoryEntry;
222  }
223 
224  QString FileManager::directoryStatusText(DirectoryStatus stat)
225  {
226  switch (stat)
227  {
228  case ProjectDirectory:
229  return QString("seems to be a HAL project");
230  case OtherDirectory:
231  return QString("no HAL project file found in current directory");
232  case IsFile:
233  return QString("entry is not a directory but a file");
234  case NotExisting:
235  return QString("directory does not exist");
236  case InvalidExtension:
237  return QString("HAL project directory must not have an extension");
238  case ParseError:
239  return QString("HAL project file parse error");
240  case NetlistError:
241  return QString("cannot find HAL netlist");
242  case GatelibError:
243  return QString("cannot find HAL gate library");
244  case UnknownDirectoryEntry:
245  return QString("entry is neither directory nor file");
246  }
247 
248  return QString();
249  }
250 
251  void FileManager::fileSuccessfullyLoaded(QString file)
252  {
253  watchFile(file);
254  Q_EMIT fileOpened(file);
255  ProjectManager::instance()->set_project_status(ProjectManager::ProjectStatus::OPENED);
256  }
257 
258  void FileManager::removeShadowDirectory()
259  {
260  ProjectManager* pm = ProjectManager::instance();
261  if (pm->get_project_status() == ProjectManager::ProjectStatus::NONE) return;
262  QDir shDir(QString::fromStdString(pm->get_project_directory().get_shadow_dir()));
263  if (shDir.exists())
264  {
265  shDir.removeRecursively();
266  QDir().mkpath(shDir.absolutePath());
267  }
268 
269  }
270 
271  void FileManager::newProject()
272  {
273  NewProjectDialog npr(qApp->activeWindow());
274  if (npr.exec() != QDialog::Accepted) return;
275 
276  QString projdir = npr.projectDirectory();
277  if (projdir.isEmpty()) return;
278 
279  QString gatelib = npr.gateLibraryPath();
280  if (gatelib.isEmpty())
281  {
282  QMessageBox::warning(qApp->activeWindow(),"Aborted", "Cannot create project <" + projdir + ">, no gate library selected");
283  return;
284  }
286  if (!glib)
287  {
288  QMessageBox::warning(qApp->activeWindow(),"Aborted", "Cannot create project <" + projdir + ">, cannot load gate library <" + gatelib + ">");
289  return;
290  }
291 
292  ProjectManager* pm = ProjectManager::instance();
293  if (!pm->create_project_directory(projdir.toStdString()))
294  {
295  QMessageBox::warning(qApp->activeWindow(),"Aborted", "Error creating project directory <" + projdir + ">");
296  return;
297  }
298 
299  QDir projectDir(projdir);
300  QString netlistFilename = QString::fromStdString(pm->get_netlist_filename());
301  if (npr.isCopyGatelibChecked())
302  {
303  QFileInfo glInfo(gatelib);
304  QString targetGateLib = projectDir.absoluteFilePath(glInfo.fileName());
305  if (QFile::copy(gatelib,targetGateLib))
306  gatelib = targetGateLib;
307  }
308 
309  std::filesystem::path lpath = pm->get_project_directory().get_default_filename(".log");
310  LogManager::get_instance()->set_file_name(lpath);
311 
313  gNetlist = gNetlistOwner.get();
314 
315  if (!gNetlist)
316  {
317  QMessageBox::warning(qApp->activeWindow(),"Aborted", "Failed to create <" + projdir + "> with gate library <" + gatelib + ">");
318  return;
319  }
322  if (pm->serialize_project(gNetlist))
324  projectSuccessfullyLoaded(projdir,netlistFilename);
325  log_info("gui", "Created empty project '{}' with gate library '{}'.", projdir.toStdString(), gatelib.toStdString());
326  }
327 
328  void FileManager::importFile(QString filename)
329  {
330  // check whether there is already a project with the same name as file-to-be-imported
331  QString testProjectExists(filename);
332  testProjectExists.remove(QRegularExpression("\\.\\w*$"));
333  if (directoryStatus(testProjectExists) == FileManager::ProjectDirectory)
334  {
335  QMessageBox msgBox;
337  msgBox.setWindowTitle("Resume previous work");
338  msgBox.setText("A hal project exists for the selected netlist.");
339  auto butLoadProject = msgBox.addButton("Load hal project", QMessageBox::ActionRole);
340  auto butImportNetlist = msgBox.addButton("Parse " + QFileInfo(filename).suffix() + " file", QMessageBox::ActionRole);
341  msgBox.addButton("Abort", QMessageBox::RejectRole);
342 
343  QSpacerItem* horizontalSpacer = new QSpacerItem(500, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
344  QGridLayout* layout = (QGridLayout*)msgBox.layout();
345  layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
346 
347  msgBox.exec();
348 
349  if (msgBox.clickedButton() == (QAbstractButton*)butLoadProject)
350  {
351  openProject(testProjectExists);
352  return;
353  }
354  else if (msgBox.clickedButton() != (QAbstractButton*)butImportNetlist)
355  {
356  return;
357  }
358  }
359 
360  for (;;) // loop upon wrong suffix or upon error creating project directory
361  {
362  ImportNetlistDialog ind(filename, qApp->activeWindow());
363  if (ind.exec() != QDialog::Accepted) return;
364  QString projdir = ind.projectDirectory();
365  if (projdir.isEmpty()) return;
366 
367  if (!QFileInfo(projdir).suffix().isEmpty())
368  {
369  QMessageBox::warning(qApp->activeWindow(),"Aborted", "selected project directory name must not have suffix ." + QFileInfo(projdir).suffix());
370  continue;
371  }
372 
373  ProjectManager* pm = ProjectManager::instance();
374  if (!pm->create_project_directory(projdir.toStdString()))
375  {
376  QMessageBox::warning(qApp->activeWindow(),"Aborted", "Error creating project directory <" + projdir +
377  ">\nYou might want to try a different name or location");
378  continue;
379  }
380 
381  QDir projectDir(projdir);
382  QString netlistFilename = filename;
383  if (ind.isMoveNetlistChecked())
384  {
385  netlistFilename = projectDir.absoluteFilePath(QFileInfo(filename).fileName());
386  QDir().rename(filename,netlistFilename);
387  }
388 
389  QString gatelib = ind.gateLibraryPath();
390  if (ind.isCopyGatelibChecked() && !gatelib.isEmpty())
391  {
392  QFileInfo glInfo(gatelib);
393  QString targetGateLib = projectDir.absoluteFilePath(glInfo.fileName());
394  if (QFile::copy(gatelib,targetGateLib))
395  gatelib = targetGateLib;
396  }
397 
398  std::filesystem::path lpath = pm->get_project_directory().get_default_filename(".log");
399  LogManager::get_instance()->set_file_name(lpath);
400 
401  if (deprecatedOpenFile(netlistFilename, gatelib))
402  {
404  if (gNetlist)
405  if (pm->serialize_project(gNetlist))
407  Q_EMIT projectOpened(projectDir.absolutePath(),QString::fromStdString(pm->get_netlist_filename()));
408  }
409  else
410  {
411  // failed to create project: if netlist was moved move back before deleting directory
412  if (ind.isMoveNetlistChecked())
413  QDir().rename(netlistFilename,filename);
414  if (pm->remove_project_directory())
415  log_info("gui", "Project directory removed since import failed.");
416  else
417  log_warning("gui", "Failed to remove project directory after failed import attempt");
418  }
419 
420  return; // break loop
421  }
422  }
423 
424  void FileManager::moveShadowToProject(const QDir& shDir) const
425  {
426  QString replaceToken = "/" + QString::fromStdString(ProjectDirectory::s_shadow_dir) + "/";
428  {
429  QString targetPath(finfo.absoluteFilePath());
430  targetPath.replace(replaceToken,"/");
431 
432  if (finfo.isDir())
433  {
434  QDir().mkpath(targetPath);
435  moveShadowToProject(QDir(finfo.absoluteFilePath()));
436  }
437  else if (finfo.isFile())
438  {
439  if (QFileInfo(targetPath).exists()) QFile::remove(targetPath);
440  QFile::copy(finfo.absoluteFilePath(),targetPath);
441  log_info("gui", "File restored from autosave: {}.", targetPath.toStdString());
442  }
443  else
444  {
445  log_info("gui","Cannot move {} from autosave to project directory.", finfo.absoluteFilePath().toStdString());
446  }
447  }
448  }
449 
450  void FileManager::openProject(QString projPath)
451  {
452  ProjectManager* pm = ProjectManager::instance();
453  pm->set_project_directory(projPath.toStdString());
454 
456  QFileInfo shInfo(shDir.absoluteFilePath(QString::fromStdString(ProjectManager::s_project_file)));
457  if (shInfo.exists() && shInfo.isFile())
458  {
459  QString message =
460  "It seems that HAL crashed during your last session. Last autosave was on " +
461  shInfo.lastModified().toString("dd.MM.yyyy hh:mm") + ". Restore that state?";
462  if (QMessageBox::question(nullptr, "HAL did not exit cleanly", message, QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
463  {
464  moveShadowToProject(shDir);
466  }
467  }
468 
469  ProjectJson projFile(QDir(projPath).absoluteFilePath(".project.json"));
470  QString glExtension = QFileInfo(projFile.gateLibraryFilename()).suffix();
471  if (!glExtension.isEmpty() && gPluginRelay->mGuiPluginTable)
472  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser,"." +glExtension);
473 
474 
475  if (!pm->open_project())
476  {
477  QString errorMsg = QString("Error opening project <%1>").arg(projPath);
478  log_error("gui", "{}", errorMsg.toStdString());
479  displayErrorMessage(errorMsg);
480  return;
481  }
482 
483  gNetlistOwner = std::move(pm->get_netlist());
484  gNetlist = gNetlistOwner.get();
486  projectSuccessfullyLoaded(projPath, filename);
488 
489  std::filesystem::path lpath = pm->get_project_directory().get_default_filename(".log");
490  LogManager::get_instance()->set_file_name(lpath);
491  }
492 
493  bool FileManager::deprecatedOpenFile(QString filename, QString gatelibraryPath)
494  {
495  QString logical_file_name = filename;
496 
497  QString glSuffix = QFileInfo(gatelibraryPath).suffix();
498  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser,"."+glSuffix);
499 
500  if (gNetlist)
501  {
502  // ADD ERROR MESSAGE
503  return false;
504  }
505 
506  if (filename.isEmpty())
507  {
508  QString errorMsg("Unable to open file. File name is empty");
509  log_error("gui", "{}", errorMsg.toStdString());
510  displayErrorMessage(errorMsg);
511  return false;
512  }
513 
514  QFile file(filename);
515 
516  if (!file.open(QFile::ReadOnly))
517  {
518  std::string error_message("Unable to open file" + filename.toStdString());
519  log_error("gui", "Unable to open file '{}'", error_message);
520  displayErrorMessage(QString::fromStdString(error_message));
521  return false;
522  }
523 
524  QFileInfo nlInfo(filename);
525  if (nlInfo.suffix()=="hal")
526  {
527  QHash<int,int> errorCount;
528  for (;;) // try loading hal file until exit by return
529  {
530  // event_controls::enable_all(false); won't get events until callbacks are registered
531  auto netlist = netlist_factory::load_netlist(filename.toStdString(),gatelibraryPath.toStdString());
532  // event_controls::enable_all(true);
533  if (netlist)
534  {
535  gNetlistOwner = std::move(netlist);
536  gNetlist = gNetlistOwner.get();
538  fileSuccessfullyLoaded(logical_file_name);
539  return true;
540  }
541  else
542  {
543  std::string error_message("Failed to create netlist from .hal file");
544  log_error("gui", "{}", error_message);
545  displayErrorMessage(QString::fromStdString(error_message));
546  return false;
547  }
548  }
549  }
550  else
551  {
553  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacNetlistParser,"."+nlInfo.suffix());
554  }
555 
556  if (!gatelibraryPath.isEmpty())
557  {
558  log_info("gui", "Trying to use gate library {}.", gatelibraryPath.toStdString());
559  QFileInfo glInfo(gatelibraryPath);
561  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser,"."+glInfo.suffix());
562 
563  auto netlist = netlist_factory::load_netlist(filename.toStdString(), gatelibraryPath.toStdString());
564 
565  if (netlist)
566  {
567  gNetlistOwner = std::move(netlist);
568  gNetlist = gNetlistOwner.get();
570  fileSuccessfullyLoaded(logical_file_name);
571  return true;
572  }
573  else
574  {
575  log_error("gui", "Failed using gate library {}.", gatelibraryPath.toStdString());
576  displayErrorMessage("Failed to open netlist\nwith user selected gate library\n"+gatelibraryPath);
577  return false;
578  }
579  }
580 
581  QString lib_file_name = filename.left(filename.lastIndexOf('.')) + ".lib";
582  if (QFileInfo::exists(lib_file_name) && QFileInfo(lib_file_name).isFile())
583  {
584  log_info("gui", "Trying to use gate library {}.", lib_file_name.toStdString());
586  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser,".lib");
587 
588  // event_controls::enable_all(false);
589  auto netlist = netlist_factory::load_netlist(filename.toStdString(), lib_file_name.toStdString());
590  // event_controls::enable_all(true);
591 
592  if (netlist)
593  {
594  gNetlistOwner = std::move(netlist);
595  gNetlist = gNetlistOwner.get();
597  fileSuccessfullyLoaded(logical_file_name);
598  return true;
599  }
600  else
601  {
602  log_error("gui", "Failed using gate library {}.", lib_file_name.toStdString());
603  }
604  }
605 
606  log_info("gui", "Searching for (other) compatible netlists.");
608  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser);
609 
610  // event_controls::enable_all(false);
611  std::vector<std::unique_ptr<Netlist>> netlists = netlist_factory::load_netlists(filename.toStdString());
612  // event_controls::enable_all(true);
613 
614  if (netlists.empty())
615  {
616  std::string error_message("Unable to find a compatible gate library. Deserialization failed!");
617  log_error("gui", "{}", error_message);
618  displayErrorMessage(QString::fromStdString(error_message));
619  return false;
620  }
621  else if (netlists.size() == 1)
622  {
623  log_info("gui", "One compatible gate library found.");
624  gNetlistOwner = std::move(netlists.at(0));
625  gNetlist = gNetlistOwner.get();
627  }
628  else
629  {
630  log_info("gui", "{} compatible gate libraries found. User has to select one.", netlists.size());
631 
632  QInputDialog dialog;
633  QStringList libs;
634 
635  for (auto& n : netlists)
636  {
637  libs.append(QString::fromStdString(n->get_gate_library()->get_name()));
638  }
639 
640  dialog.setComboBoxItems(libs);
641  dialog.setWindowTitle("Select gate library");
642  dialog.setLabelText("The specified file can be processed with more than one gate library. Please select which library should be used:");
643 
644  if (dialog.exec())
645  {
646  std::string selection = dialog.textValue().toStdString();
647 
648  for (auto& n : netlists)
649  {
650  if (n->get_gate_library()->get_name() == selection)
651  {
652  gNetlistOwner = std::move(n);
653  gNetlist = gNetlistOwner.get();
655  }
656  }
657  }
658  else
659  {
660  return false;
661  }
662  }
663 
664  fileSuccessfullyLoaded(logical_file_name);
665  return true;
666  }
667 
668  void FileManager::closeFile()
669  {
670  if (!mFileOpen)
671  return;
672 
673  mTimer->stop();
674  Q_EMIT fileAboutToClose(mFileName);
675 
676  // CHECK DIRTY AND TRIGGER SAVE ROUTINE
677 
679  mFileWatcher->removePath(mFileName);
680  mFileName = "";
681  mFileOpen = false;
682 
683  removeShadowDirectory();
684 
685  gNetlistOwner.reset();
686  gNetlist = nullptr;
687 
689  ProjectManager::instance()->set_project_status(ProjectManager::ProjectStatus::NONE);
690 
691  Q_EMIT fileClosed();
692  }
693 
694  void FileManager::handleFileChanged(const QString& path)
695  {
696  Q_EMIT fileChanged(path);
697  }
698 
699  void FileManager::handleDirectoryChanged(const QString& path)
700  {
701  Q_EMIT fileDirectoryChanged(path);
702  }
703 
704  void FileManager::updateRecentFiles(const QString& file) const
705  {
706  QStringList list;
707 
708  gGuiState->beginReadArray("recent_files");
709  for (int i = 0; i < 14; ++i)
710  {
712  QString state_file = gGuiState->value("file").toString();
713 
714  if (state_file.isEmpty())
715  continue;
716 
717  list.append(gGuiState->value("file").toString());
718  }
719  gGuiState->endArray();
720 
721  int index = list.indexOf(file);
722  if (index == -1)
723  list.prepend(file);
724  else
725  list.move(index, 0);
726 
727  gGuiState->beginGroup("recent_files");
728  gGuiState->remove("");
729  gGuiState->endGroup();
730 
731  gGuiState->beginWriteArray("recent_files");
732  int i = 0;
733  std::vector<std::filesystem::path> files;
734  for (QString& string : list)
735  {
736  std::filesystem::path file_path(string.toStdString());
737  bool skip = false;
738  for (const auto& other : files)
739  {
740  if (std::filesystem::equivalent(file_path, other))
741  {
742  skip = true;
743  break;
744  }
745  }
746  if (!skip)
747  {
749  gGuiState->setValue("file", string);
750  ++i;
751  if (i == 14)
752  break;
753  }
754  }
755  gGuiState->endArray();
756  }
757 
758  void FileManager::displayErrorMessage(QString error_message)
759  {
760  QMessageBox msgBox;
761  msgBox.setText("Error");
762  msgBox.setInformativeText(error_message);
763  msgBox.setStyleSheet("QLabel{min-width: 600px;}");
766  msgBox.exec();
767  }
768 } // namespace hal
then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file
Copyright The Montserrat Project in Original or Modified may be sold by itself Original or Modified Versions of the Font Software may be redistributed and or sold with any provided that each copy contains the above copyright notice and this license These can be included either as stand alone text files
Definition: OFL.txt:59
void handleOpenDocument(const QString &fileName)
Stores information about the currently opened netlist.
Definition: file_manager.h:48
void loadFeature(FacExtensionInterface::Feature ft, const QString &extension=QString())
void registerNetlistCallbacks()
void unregisterNetlistCallbacks()
QString projectDirectory() const
QString gateLibraryPath() const
GuiPluginTable * mGuiPluginTable
Definition: plugin_relay.h:68
std::filesystem::path get_default_filename(const std::string &extension=std::string()) const
std::filesystem::path get_shadow_dir() const
QString gateLibraryFilename() const
Definition: project_json.h:48
bool create_project_directory(const std::string &path)
bool serialize_project(Netlist *netlist, bool shadow=false)
std::unique_ptr< Netlist > & get_netlist()
ProjectStatus get_project_status() const
void restore_project_file_from_autosave()
std::string get_netlist_filename() const
bool open_project(const std::string &path="")
const ProjectDirectory & get_project_directory() const
void set_project_directory(const std::string &path)
#define log_error(channel,...)
Definition: log.h:78
#define log_info(channel,...)
Definition: log.h:70
#define log_warning(channel,...)
Definition: log.h:76
GateLibrary * load(std::filesystem::path file_path, bool reload)
std::unique_ptr< Netlist > create_netlist(const GateLibrary *gate_library)
Create a new empty netlist using the specified gate library.
std::unique_ptr< Netlist > load_netlist(const std::filesystem::path &netlist_file, const std::filesystem::path &gate_library_file)
Create a netlist from the given file.
std::vector< std::unique_ptr< Netlist > > load_netlists(const std::filesystem::path &netlist_file)
Create a netlist from a given file for each matching pre-loaded gate library.
bool can_parse(const std::filesystem::path &file_name)
PythonContext * gPythonContext
Definition: plugin_gui.cpp:88
QSettings * gGuiState
Definition: plugin_gui.cpp:77
ContentManager * gContentManager
Definition: plugin_gui.cpp:78
PluginRelay * gPluginRelay
Definition: plugin_gui.cpp:82
FileStatusManager * gFileStatusManager
Definition: plugin_gui.cpp:84
Netlist * gNetlist
Definition: plugin_gui.cpp:80
NetlistRelay * gNetlistRelay
Definition: plugin_gui.cpp:81
std::shared_ptr< Netlist > gNetlistOwner
Definition: plugin_gui.cpp:79
n
Definition: test.py:6
This file contains various functions to create and load netlists.
message(VERBOSE "Qt5Widgets_LIBRARIES: ${Qt5Widgets_LIBRARIES}") elseif(NOT Qt5Widgets_FOUND) set(Missing_package "TRUE") if(APPLE AND CMAKE_HOST_APPLE) message(STATUS "To install qt5 on MacOS using homebrew run following command
Definition: CMakeLists.txt:15
QString toString(Qt::DateFormat format) const const
virtual int exec()
QString absoluteFilePath(const QString &fileName) const const
QString absolutePath() const const
QFileInfoList entryInfoList(QDir::Filters filters, QDir::SortFlags sort) const const
bool mkpath(const QString &dirPath) const const
bool rename(const QString &oldName, const QString &newName)
bool copy(const QString &newName)
bool remove()
bool exists() const const
QString fileName() const const
bool isDir() const const
bool isFile() const const
QDateTime lastModified() const const
QString suffix() const const
void directoryChanged(const QString &path)
void fileChanged(const QString &path)
void addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
int columnCount() const const
int rowCount() const const
void setComboBoxItems(const QStringList &items)
void setLabelText(const QString &text)
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
bool isObject() const const
QJsonObject object() const const
bool contains(const QString &key) const const
void append(const T &value)
void move(int from, int to)
void prepend(const T &value)
void addButton(QAbstractButton *button, QMessageBox::ButtonRole role)
QAbstractButton * clickedButton() const const
virtual int exec() override
void setIcon(QMessageBox::Icon)
void setInformativeText(const QString &text)
QMessageBox::StandardButton question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
void setDefaultButton(QPushButton *button)
void setWindowTitle(const QString &title)
void setStandardButtons(QMessageBox::StandardButtons buttons)
void setText(const QString &text)
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
void beginGroup(const QString &prefix)
int beginReadArray(const QString &prefix)
void beginWriteArray(const QString &prefix, int size)
void endArray()
void endGroup()
void remove(const QString &key)
void setArrayIndex(int i)
void setValue(const QString &key, const QVariant &value)
QVariant value(const QString &key, const QVariant &defaultValue) const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString left(int n) const const
QString & remove(int position, int n)
std::string toStdString() const const
int indexOf(QStringView str, int from) const const
void timeout()
QString toString() const const
QLayout * layout() const const
void setStyleSheet(const QString &styleSheet)
void setWindowTitle(const QString &)