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  }
323  if (pm->serialize_project(gNetlist))
325  projectSuccessfullyLoaded(projdir,netlistFilename);
326  log_info("gui", "Created empty project '{}' with gate library '{}'.", projdir.toStdString(), gatelib.toStdString());
327  }
328 
329  void FileManager::importFile(QString filename)
330  {
331  // check whether there is already a project with the same name as file-to-be-imported
332  QString testProjectExists(filename);
333  testProjectExists.remove(QRegularExpression("\\.\\w*$"));
334  if (directoryStatus(testProjectExists) == FileManager::ProjectDirectory)
335  {
336  QMessageBox msgBox;
338  msgBox.setWindowTitle("Resume previous work");
339  msgBox.setText("A hal project exists for the selected netlist.");
340  auto butLoadProject = msgBox.addButton("Load hal project", QMessageBox::ActionRole);
341  auto butImportNetlist = msgBox.addButton("Parse " + QFileInfo(filename).suffix() + " file", QMessageBox::ActionRole);
342  msgBox.addButton("Abort", QMessageBox::RejectRole);
343 
344  QSpacerItem* horizontalSpacer = new QSpacerItem(500, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
345  QGridLayout* layout = (QGridLayout*)msgBox.layout();
346  layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
347 
348  msgBox.exec();
349 
350  if (msgBox.clickedButton() == (QAbstractButton*)butLoadProject)
351  {
352  openProject(testProjectExists);
353  return;
354  }
355  else if (msgBox.clickedButton() != (QAbstractButton*)butImportNetlist)
356  {
357  return;
358  }
359  }
360 
361  for (;;) // loop upon wrong suffix or upon error creating project directory
362  {
363  ImportNetlistDialog ind(filename, qApp->activeWindow());
364  if (ind.exec() != QDialog::Accepted) return;
365  QString projdir = ind.projectDirectory();
366  if (projdir.isEmpty()) return;
367 
368  if (!QFileInfo(projdir).suffix().isEmpty())
369  {
370  QMessageBox::warning(qApp->activeWindow(),"Aborted", "selected project directory name must not have suffix ." + QFileInfo(projdir).suffix());
371  continue;
372  }
373 
374  ProjectManager* pm = ProjectManager::instance();
375  if (!pm->create_project_directory(projdir.toStdString()))
376  {
377  QMessageBox::warning(qApp->activeWindow(),"Aborted", "Error creating project directory <" + projdir +
378  ">\nYou might want to try a different name or location");
379  continue;
380  }
381 
382  QDir projectDir(projdir);
383  QString netlistFilename = filename;
384  if (ind.isMoveNetlistChecked())
385  {
386  netlistFilename = projectDir.absoluteFilePath(QFileInfo(filename).fileName());
387  QDir().rename(filename,netlistFilename);
388  }
389 
390  QString gatelib = ind.gateLibraryPath();
391  if (ind.isCopyGatelibChecked() && !gatelib.isEmpty())
392  {
393  QFileInfo glInfo(gatelib);
394  QString targetGateLib = projectDir.absoluteFilePath(glInfo.fileName());
395  if (QFile::copy(gatelib,targetGateLib))
396  gatelib = targetGateLib;
397  }
398 
399  std::filesystem::path lpath = pm->get_project_directory().get_default_filename(".log");
400  LogManager::get_instance()->set_file_name(lpath);
401 
402  if (deprecatedOpenFile(netlistFilename, gatelib))
403  {
405  if (gNetlist)
406  if (pm->serialize_project(gNetlist))
408  Q_EMIT projectOpened(projectDir.absolutePath(),QString::fromStdString(pm->get_netlist_filename()));
409  }
410  else
411  {
412  // failed to create project: if netlist was moved move back before deleting directory
413  if (ind.isMoveNetlistChecked())
414  QDir().rename(netlistFilename,filename);
415  if (pm->remove_project_directory())
416  log_info("gui", "Project directory removed since import failed.");
417  else
418  log_warning("gui", "Failed to remove project directory after failed import attempt");
419  }
420 
421  return; // break loop
422  }
423  }
424 
425  void FileManager::moveShadowToProject(const QDir& shDir) const
426  {
427  QString replaceToken = "/" + QString::fromStdString(ProjectDirectory::s_shadow_dir) + "/";
429  {
430  QString targetPath(finfo.absoluteFilePath());
431  targetPath.replace(replaceToken,"/");
432 
433  if (finfo.isDir())
434  {
435  QDir().mkpath(targetPath);
436  moveShadowToProject(QDir(finfo.absoluteFilePath()));
437  }
438  else if (finfo.isFile())
439  {
440  if (QFileInfo(targetPath).exists()) QFile::remove(targetPath);
441  QFile::copy(finfo.absoluteFilePath(),targetPath);
442  log_info("gui", "File restored from autosave: {}.", targetPath.toStdString());
443  }
444  else
445  {
446  log_info("gui","Cannot move {} from autosave to project directory.", finfo.absoluteFilePath().toStdString());
447  }
448  }
449  }
450 
451  void FileManager::openProject(QString projPath)
452  {
453  ProjectManager* pm = ProjectManager::instance();
454  pm->set_project_directory(projPath.toStdString());
455 
457  QFileInfo shInfo(shDir.absoluteFilePath(QString::fromStdString(ProjectManager::s_project_file)));
458  if (shInfo.exists() && shInfo.isFile())
459  {
460  QString message =
461  "It seems that HAL crashed during your last session. Last autosave was on " +
462  shInfo.lastModified().toString("dd.MM.yyyy hh:mm") + ". Restore that state?";
463  if (QMessageBox::question(nullptr, "HAL did not exit cleanly", message, QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
464  {
465  moveShadowToProject(shDir);
467  }
468  }
469 
470  ProjectJson projFile(QDir(projPath).absoluteFilePath(".project.json"));
471  QString glExtension = QFileInfo(projFile.gateLibraryFilename()).suffix();
472  if (!glExtension.isEmpty() && gPluginRelay->mGuiPluginTable)
473  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser,"." +glExtension);
474 
475 
476  if (!pm->open_project())
477  {
478  QString errorMsg = QString("Error opening project <%1>").arg(projPath);
479  log_error("gui", "{}", errorMsg.toStdString());
480  displayErrorMessage(errorMsg);
481  return;
482  }
483 
484  gNetlistOwner = std::move(pm->get_netlist());
485  gNetlist = gNetlistOwner.get();
487  projectSuccessfullyLoaded(projPath, filename);
490 
491  std::filesystem::path lpath = pm->get_project_directory().get_default_filename(".log");
492  LogManager::get_instance()->set_file_name(lpath);
493  }
494 
495  bool FileManager::deprecatedOpenFile(QString filename, QString gatelibraryPath)
496  {
497  QString logical_file_name = filename;
498 
499  QString glSuffix = QFileInfo(gatelibraryPath).suffix();
500  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser,"."+glSuffix);
501 
502  if (gNetlist)
503  {
504  // ADD ERROR MESSAGE
505  return false;
506  }
507 
508  if (filename.isEmpty())
509  {
510  QString errorMsg("Unable to open file. File name is empty");
511  log_error("gui", "{}", errorMsg.toStdString());
512  displayErrorMessage(errorMsg);
513  return false;
514  }
515 
516  QFile file(filename);
517 
518  if (!file.open(QFile::ReadOnly))
519  {
520  std::string error_message("Unable to open file" + filename.toStdString());
521  log_error("gui", "Unable to open file '{}'", error_message);
522  displayErrorMessage(QString::fromStdString(error_message));
523  return false;
524  }
525 
526  QFileInfo nlInfo(filename);
527  if (nlInfo.suffix()=="hal")
528  {
529  QHash<int,int> errorCount;
530  for (;;) // try loading hal file until exit by return
531  {
532  // event_controls::enable_all(false); won't get events until callbacks are registered
533  auto netlist = netlist_factory::load_netlist(filename.toStdString(),gatelibraryPath.toStdString());
534  // event_controls::enable_all(true);
535  if (netlist)
536  {
537  gNetlistOwner = std::move(netlist);
538  gNetlist = gNetlistOwner.get();
540  fileSuccessfullyLoaded(logical_file_name);
542  return true;
543  }
544  else
545  {
546  std::string error_message("Failed to create netlist from .hal file");
547  log_error("gui", "{}", error_message);
548  displayErrorMessage(QString::fromStdString(error_message));
549  return false;
550  }
551  }
552  }
553  else
554  {
556  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacNetlistParser,"."+nlInfo.suffix());
557  }
558 
559  if (!gatelibraryPath.isEmpty())
560  {
561  log_info("gui", "Trying to use gate library {}.", gatelibraryPath.toStdString());
562  QFileInfo glInfo(gatelibraryPath);
564  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser,"."+glInfo.suffix());
565 
566  auto netlist = netlist_factory::load_netlist(filename.toStdString(), gatelibraryPath.toStdString());
567 
568  if (netlist)
569  {
570  gNetlistOwner = std::move(netlist);
571  gNetlist = gNetlistOwner.get();
573  fileSuccessfullyLoaded(logical_file_name);
575  return true;
576  }
577  else
578  {
579  log_error("gui", "Failed using gate library {}.", gatelibraryPath.toStdString());
580  displayErrorMessage("Failed to open netlist\nwith user selected gate library\n"+gatelibraryPath);
581  return false;
582  }
583  }
584 
585  QString lib_file_name = filename.left(filename.lastIndexOf('.')) + ".lib";
586  if (QFileInfo::exists(lib_file_name) && QFileInfo(lib_file_name).isFile())
587  {
588  log_info("gui", "Trying to use gate library {}.", lib_file_name.toStdString());
590  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser,".lib");
591 
592  // event_controls::enable_all(false);
593  auto netlist = netlist_factory::load_netlist(filename.toStdString(), lib_file_name.toStdString());
594  // event_controls::enable_all(true);
595 
596  if (netlist)
597  {
598  gNetlistOwner = std::move(netlist);
599  gNetlist = gNetlistOwner.get();
601  fileSuccessfullyLoaded(logical_file_name);
603  return true;
604  }
605  else
606  {
607  log_error("gui", "Failed using gate library {}.", lib_file_name.toStdString());
608  }
609  }
610 
611  log_info("gui", "Searching for (other) compatible netlists.");
613  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser);
614 
615  // event_controls::enable_all(false);
616  std::vector<std::unique_ptr<Netlist>> netlists = netlist_factory::load_netlists(filename.toStdString());
617  // event_controls::enable_all(true);
618 
619  if (netlists.empty())
620  {
621  std::string error_message("Unable to find a compatible gate library. Deserialization failed!");
622  log_error("gui", "{}", error_message);
623  displayErrorMessage(QString::fromStdString(error_message));
624  return false;
625  }
626  else if (netlists.size() == 1)
627  {
628  log_info("gui", "One compatible gate library found.");
629  gNetlistOwner = std::move(netlists.at(0));
630  gNetlist = gNetlistOwner.get();
633  }
634  else
635  {
636  log_info("gui", "{} compatible gate libraries found. User has to select one.", netlists.size());
637 
638  QInputDialog dialog;
639  QStringList libs;
640 
641  for (auto& n : netlists)
642  {
643  libs.append(QString::fromStdString(n->get_gate_library()->get_name()));
644  }
645 
646  dialog.setComboBoxItems(libs);
647  dialog.setWindowTitle("Select gate library");
648  dialog.setLabelText("The specified file can be processed with more than one gate library. Please select which library should be used:");
649 
650  if (dialog.exec())
651  {
652  std::string selection = dialog.textValue().toStdString();
653 
654  for (auto& n : netlists)
655  {
656  if (n->get_gate_library()->get_name() == selection)
657  {
658  gNetlistOwner = std::move(n);
659  gNetlist = gNetlistOwner.get();
662  }
663  }
664  }
665  else
666  {
667  return false;
668  }
669  }
670 
671  fileSuccessfullyLoaded(logical_file_name);
672  return true;
673  }
674 
675  void FileManager::closeFile()
676  {
677  if (!mFileOpen)
678  return;
679 
680  mTimer->stop();
681  Q_EMIT fileAboutToClose(mFileName);
682 
683  // CHECK DIRTY AND TRIGGER SAVE ROUTINE
684 
686  mFileWatcher->removePath(mFileName);
687  mFileName = "";
688  mFileOpen = false;
689 
690  removeShadowDirectory();
691 
692  gNetlistOwner.reset();
693  gNetlist = nullptr;
694 
696  ProjectManager::instance()->set_project_status(ProjectManager::ProjectStatus::NONE);
697 
698  Q_EMIT fileClosed();
699  }
700 
701  void FileManager::handleFileChanged(const QString& path)
702  {
703  Q_EMIT fileChanged(path);
704  }
705 
706  void FileManager::handleDirectoryChanged(const QString& path)
707  {
708  Q_EMIT fileDirectoryChanged(path);
709  }
710 
711  void FileManager::updateRecentFiles(const QString& file) const
712  {
713  QStringList list;
714 
715  gGuiState->beginReadArray("recent_files");
716  for (int i = 0; i < 14; ++i)
717  {
719  QString state_file = gGuiState->value("file").toString();
720 
721  if (state_file.isEmpty())
722  continue;
723 
724  list.append(gGuiState->value("file").toString());
725  }
726  gGuiState->endArray();
727 
728  int index = list.indexOf(file);
729  if (index == -1)
730  list.prepend(file);
731  else
732  list.move(index, 0);
733 
734  gGuiState->beginGroup("recent_files");
735  gGuiState->remove("");
736  gGuiState->endGroup();
737 
738  gGuiState->beginWriteArray("recent_files");
739  int i = 0;
740  std::vector<std::filesystem::path> files;
741  for (QString& string : list)
742  {
743  std::filesystem::path file_path(string.toStdString());
744  bool skip = false;
745  for (const auto& other : files)
746  {
747  if (std::filesystem::equivalent(file_path, other))
748  {
749  skip = true;
750  break;
751  }
752  }
753  if (!skip)
754  {
756  gGuiState->setValue("file", string);
757  ++i;
758  if (i == 14)
759  break;
760  }
761  }
762  gGuiState->endArray();
763  }
764 
765  void FileManager::displayErrorMessage(QString error_message)
766  {
767  QMessageBox msgBox;
768  msgBox.setText("Error");
769  msgBox.setInformativeText(error_message);
770  msgBox.setStyleSheet("QLabel{min-width: 600px;}");
773  msgBox.exec();
774  }
775 } // 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 &)