HAL
main_window.cpp
Go to the documentation of this file.
2 
3 #include "gui/action/action.h"
12 #include "gui/gui_def.h"
13 #include "gui/gui_globals.h"
26 #include "hal_core/defines.h"
28 #include "hal_core/netlist/gate.h"
31 #include "hal_core/netlist/net.h"
39 #include "hal_core/utilities/log.h"
41 
42 #include <QApplication>
43 #include <QCloseEvent>
44 #include <QDesktopWidget>
45 #include <QDir>
46 #include <QFileDialog>
47 #include <QInputDialog>
48 #include <QMessageBox>
49 #include <QPushButton>
50 #include <QRegExp>
51 #include <QShortcut>
52 #include <QStringList>
53 #include <QtConcurrent>
54 
55 
56 namespace hal
57 {
58  const char* MSG_PROJECT_ALREADY_OPEN = "You are already working on a HAL project. Close current project first.";
59 
61 
62  MainWindow::MainWindow(QWidget* parent) : QWidget(parent)
63  {
64  mFileActions = new FileActions(this);
65  ensurePolished(); // ADD REPOLISH METHOD
68 
69  mLayout = new QVBoxLayout(this);
70  mLayout->setContentsMargins(0, 0, 0, 0);
71  mLayout->setSpacing(0);
72 
73  mMenuBar = new QMenuBar();
74  mMenuBar->setNativeMenuBar(true);
75  mMenuBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
76  mLayout->addWidget(mMenuBar);
77 
78  mToolBarLayout = new QHBoxLayout();
79  mToolBarLayout->setContentsMargins(0, 0, 0, 0);
80  mToolBarLayout->setSpacing(0);
81  mLayout->addLayout(mToolBarLayout);
82 
83  mLeftToolBar = new QToolBar();
84  mLeftToolBar->setObjectName("Toolbar");
85  mLeftToolBar->setMovable(false);
86  mLeftToolBar->setFloatable(false);
87  mLeftToolBar->setIconSize(QSize(18, 18));
88  mLeftToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
89  mToolBarLayout->addWidget(mLeftToolBar);
90 
91  mRightToolBar = new QToolBar();
92  mRightToolBar->setObjectName("Toolbar");
93  mRightToolBar->setMovable(false);
94  mRightToolBar->setFloatable(false);
95  mRightToolBar->setIconSize(QSize(18, 18));
96  mRightToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
97  mRightToolBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
98  mToolBarLayout->addWidget(mRightToolBar);
99 
100  mStackedWidget = new QStackedWidget();
101  mLayout->addWidget(mStackedWidget);
102 
103  mSettings = new MainSettingsWidget;
104  mStackedWidget->addWidget(mSettings);
105 
106  mPluginManager = new GuiPluginManager(this);
108  mStackedWidget->addWidget(mPluginManager);
109 
110  mLayoutArea = new ContentLayoutArea();
111  mStackedWidget->addWidget(mLayoutArea);
112 
113  // mContainer = new QWidget();
114  // mStackedWidget->addWidget(mContainer);
115 
116  // mContainerLayout = new QVBoxLayout(mContainer);
117 
118  // mContainerLayout->setContentsMargins(0, 0, 0, 0);
119  // mContainerLayout->setSpacing(0);
120 
121  // m_tool_bar = new QToolBar();
122  // m_tool_bar->setMovable(false);
123  // m_tool_bar->setFloatable(false);
124  // m_tool_bar->setIconSize(QSize(18, 18));
125  // m_tool_bar->setToolButtonStyle(Qt::ToolButtonIconOnly);
126  // mContainerLayout->addWidget(m_tool_bar);
127 
128  // mLayoutArea = new hal_content_layout_area();
129  // mContainerLayout->addWidget(mLayoutArea);
130 
131  //welcome screen + other screens (?)
132 
133  mWelcomeScreen = new WelcomeScreen();
134  mStackedWidget->addWidget(mWelcomeScreen);
135  mGateLibraryManager = new GateLibraryManager(this);
136  mStackedWidget->addWidget(mGateLibraryManager);
137 
138  mStackedWidget->setCurrentWidget(mWelcomeScreen);
139 
141 
142  mActionImportNetlist = new Action(this);
143  mActionExportProject = new Action(this);
144  mActionImportProject = new Action(this);
145  mActionGateLibraryManager = new Action(this);
146  mActionAbout = new Action(this);
147 
148  mActionStartRecording = new Action(this);
149  mActionStopRecording = new Action(this);
150  mActionPlayMacro = new Action(this);
151  mActionUndo = new Action(this);
152 
153  mActionSettings = new Action(this);
154  mActionPluginManager = new Action(this);
155  mActionQuit = new Action(this);
156 
157  // //mOpenIconStyle = "all->#fcfcb0";
158  // //mOpenIconStyle = "all->#f2e4a4";
159  // mOpenIconStyle = "all->#3192C5";
160  // mOpenIconPath = ":/icons/folder";
161 
162  // mSaveIconStyle = "all->#3192C5";
163  // mSaveIconPath = ":/icons/folder-down";
164 
165  // //mScheduleIconStyle = "all->#08d320";
166  // //mScheduleIconStyle = "all->#05c61c";
167  // mScheduleIconStyle = "all->#2BAD4A";
168  // mScheduleIconPath = ":/icons/list";
169 
170  // //mRunIconStyle = "all->#05c61c";
171  // mRunIconStyle = "all->#2BAD4A";
172  // mRunIconPath = ":/icons/run";
173 
174  // mContentIconStyle = "all->#AFB1B3";
175  // mContentIconPath = ":/icons/content";
176 
177  // mSettingsIconStyle = "all->#AFB1B3";
178  // mSettingsIconPath = ":/icons/settings";
179 
180  setWindowIcon(gui_utility::getStyledSvgIcon(mHalIconStyle, mHalIconPath));
181 
182  mActionImportNetlist->setIcon(gui_utility::getStyledSvgIcon(mOpenFileIconStyle, mOpenFileIconPath));
183  mActionQuit->setIcon(gui_utility::getStyledSvgIcon(mQuitIconStyle, mQuitIconPath));
184  mActionGateLibraryManager->setIcon(gui_utility::getStyledSvgIcon(mNeGateIconStyle, mNeGateIconPath));
185  mActionUndo->setIcon(gui_utility::getStyledSvgIcon(mUndoIconStyle, mUndoIconPath));
186  mActionSettings->setIcon(gui_utility::getStyledSvgIcon(mSettingsIconStyle, mSettingsIconPath));
187  mActionPluginManager->setIcon(gui_utility::getStyledSvgIcon(mPluginsIconStyle, mPluginsIconPath));
188 
189  mMenuFile = new QMenu(mMenuBar);
190  mMenuEdit = new QMenu(mMenuBar);
191  mMenuMacro = new QMenu(mMenuBar);
192  mMenuUtilities = new QMenu(mMenuBar);
193  mMenuPlugins = new QMenu(mMenuBar);
194  mMenuHelp = new QMenu(mMenuBar);
195 
196  mMenuBar->addAction(mMenuFile->menuAction());
197  mMenuBar->addAction(mMenuEdit->menuAction());
198  mMenuBar->addAction(mMenuMacro->menuAction());
199  mMenuBar->addAction(mMenuUtilities->menuAction());
200  mMenuBar->addAction(mMenuPlugins->menuAction());
201  mMenuBar->addAction(mMenuHelp->menuAction());
202  mMenuFile->addAction(mFileActions->create());
203  mMenuFile->addAction(mFileActions->open());
204  mMenuFile->addAction(mFileActions->close());
205  mMenuFile->addAction(mFileActions->save());
206  mMenuFile->addAction(mFileActions->saveAs());
207 
208  QMenu* menuImport = new QMenu("Import …", this);
209  menuImport->addAction(mActionImportNetlist);
210  menuImport->addAction(mActionImportProject);
211 
212  QMenu* menuExport = new QMenu("Export …", this);
213  bool hasExporter = false;
215  {
216  if (it.second.empty()) continue; // no extensions registered
217 
218  QString label = QString::fromStdString(it.first);
219  QRegExp re("Default (.*) Writer", Qt::CaseInsensitive);
220  QString txt = (re.indexIn(label) < 0)
221  ? label.remove(QChar(':'))
222  : QString("Export as ") + re.cap(1);
223 
224  QStringList extensions;
225  extensions.append(txt);
226  for (std::string ex : it.second)
227  extensions.append(QString::fromStdString(ex));
228 
229  hasExporter = true;
230  Action* action = new Action(txt, this);
231  action->setData(extensions);
233  menuExport->addAction(action);
234  }
235  if (hasExporter) mMenuFile->addSeparator();
236  mActionExportProject->setDisabled(true);
237  menuExport->addAction(mActionExportProject);
238 
239  mMenuFile->addMenu(menuImport);
240  mMenuFile->addMenu(menuExport);
241  mMenuFile->addSeparator();
242  mMenuFile->addAction(mActionQuit);
243 
244  SettingsItemCheckbox* evlogSetting = new SettingsItemCheckbox(
245  "Netlist event log",
246  "debug/event_log",
247  false,
248  "eXpert Settings:Debug",
249  "Specifies whether each netlist event gets dumped to event log. Might generate a lot of output thus slowing down hal system."
250  );
251  event_log::enable_event_log(evlogSetting->value().toBool());
252  connect(evlogSetting,&SettingsItemCheckbox::boolChanged,this,&MainWindow::handleEventLogEnabled);
253 
254  mMenuEdit->addAction(mActionUndo);
255  mMenuEdit->addSeparator();
256  mMenuEdit->addAction(mActionSettings);
257  mMenuMacro->addAction(mActionStartRecording);
258  mMenuMacro->addAction(mActionStopRecording);
259  mMenuMacro->addSeparator();
260  mMenuMacro->addAction(mActionPlayMacro);
261  mMenuPlugins->setDisabled(true); // enable when project open
262  mMenuUtilities->addAction(mActionPluginManager);
263  mMenuUtilities->addAction(mActionGateLibraryManager);
264  mMenuHelp->addAction(mActionAbout);
265  mLeftToolBar->addAction(mFileActions->create());
266  mLeftToolBar->addAction(mFileActions->open());
267  mLeftToolBar->addAction(mFileActions->save());
268  mLeftToolBar->addAction(mFileActions->saveAs());
269  mLeftToolBar->addAction(mActionUndo);
270  mRightToolBar->addAction(mActionPluginManager);
271  mRightToolBar->addAction(mActionGateLibraryManager);
272  mRightToolBar->addAction(mActionSettings);
273 
274  mActionStartRecording->setText("Start recording");
275  mActionStopRecording->setText("Stop recording");
276  mActionPlayMacro->setText("Play macro");
277 
278  mActionStartRecording->setEnabled(true);
279  mActionStopRecording->setEnabled(false);
280  mActionPlayMacro->setEnabled(true);
281 
282  setWindowTitle("HAL");
283  mActionImportNetlist->setText("Import Netlist");
284  mActionImportProject->setText("Import Project");
285  mActionExportProject->setText("Export Project");
286  mActionGateLibraryManager->setText("Gate Library Manager");
287  mActionUndo->setText("Undo");
288  mActionAbout->setText("About");
289  mActionSettings->setText("Settings");
290  mActionPluginManager->setText("Plugin Manager");
291  mActionQuit->setText("Quit");
292  mMenuFile->setTitle("File");
293  mMenuEdit->setTitle("Edit");
294  mMenuMacro->setTitle("Macro");
295  mMenuUtilities->setTitle("Utilities");
296  mMenuPlugins->setTitle("Plugins");
297  mMenuHelp->setTitle("Help");
298 
299  gPythonContext = new PythonContext(this);
300 
301  gContentManager = new ContentManager(this);
302  gCommentManager = new CommentManager(this);
303 
304  mSettingUndoLast = new SettingsItemKeybind("Undo Last Action", "keybinds/action_undo", QKeySequence("Ctrl+Z"), "Keybindings:Global", "Keybind for having last user interaction undone.");
305 
306  QShortcut* shortCutUndoLast = new QShortcut(mSettingUndoLast->value().toString(), this);
307 
308  connect(mSettingUndoLast, &SettingsItemKeybind::keySequenceChanged, shortCutUndoLast, &QShortcut::setKey);
309 
310  connect(shortCutUndoLast, &QShortcut::activated, mActionUndo, &QAction::trigger);
311 
312  connect(mActionImportNetlist, &Action::triggered, this, &MainWindow::handleActionImportNetlist);
313  connect(mActionAbout, &Action::triggered, this, &MainWindow::handleActionAbout);
314  connect(mActionSettings, &Action::triggered, this, &MainWindow::openSettings);
315  connect(mActionPluginManager, &Action::triggered, this, &MainWindow::openPluginManager);
316  connect(mSettings, &MainSettingsWidget::close, this, &MainWindow::closeSettings);
317  connect(mGateLibraryManager, &GateLibraryManager::close, this, &MainWindow::closeGateLibraryManager);
318  connect(mActionExportProject, &Action::triggered, this, &MainWindow::handleExportProjectTriggered);
319  connect(mActionImportProject, &Action::triggered, this, &MainWindow::handleImportProjectTriggered);
320  connect(mActionGateLibraryManager, &Action::triggered, this, &MainWindow::handleActionGatelibraryManager);
321  connect(mActionQuit, &Action::triggered, this, &MainWindow::onActionQuitTriggered);
322 
323  connect(mActionStartRecording, &Action::triggered, this, &MainWindow::handleActionStartRecording);
324  connect(mActionStopRecording, &Action::triggered, this, &MainWindow::handleActionStopRecording);
325  connect(mActionPlayMacro, &Action::triggered, this, &MainWindow::handleActionPlayMacro);
326  connect(mActionUndo, &Action::triggered, this, &MainWindow::handleActionUndo);
327 
329  connect(sSettingStyle, &SettingsItemDropdown::intChanged, this, &MainWindow::reloadStylsheet);
330  enableUndo(false);
331 
332  restoreState();
333  }
334 
335  void MainWindow::reloadStylsheet(int istyle)
336  {
337  QString styleSheetToOpen;
338 
339  switch (istyle)
340  {
341  case StyleSheetOption::Dark:
342  styleSheetToOpen = ":/style/dark";
343  break;
344  case StyleSheetOption::Light:
345  styleSheetToOpen = ":/style/light";
346  break;
347  default:
348  return;
349  }
350  QFile stylesheet(styleSheetToOpen);
351  stylesheet.open(QFile::ReadOnly);
352  qApp->setStyleSheet(QString(stylesheet.readAll()));
353  }
354 
355  QString MainWindow::halIconPath() const
356  {
357  return mHalIconPath;
358  }
359 
360  QString MainWindow::halIconStyle() const
361  {
362  return mHalIconStyle;
363  }
364 
365  QString MainWindow::openFileIconPath() const
366  {
367  return mOpenFileIconPath;
368  }
369 
370  QString MainWindow::openFileIconStyle() const
371  {
372  return mOpenFileIconStyle;
373  }
374 
375  QString MainWindow::quitIconPath() const
376  {
377  return mQuitIconPath;
378  }
379 
380  QString MainWindow::quitIconStyle() const
381  {
382  return mQuitIconStyle;
383  }
384 
385  QString MainWindow::settingsIconPath() const
386  {
387  return mSettingsIconPath;
388  }
389 
390  QString MainWindow::settingsIconStyle() const
391  {
392  return mSettingsIconStyle;
393  }
394 
395  QString MainWindow::pluginsIconPath() const
396  {
397  return mPluginsIconPath;
398  }
399 
400  QString MainWindow::pluginsIconStyle() const
401  {
402  return mPluginsIconStyle;
403  }
404 
405  QString MainWindow::undoIconPath() const
406  {
407  return mUndoIconPath;
408  }
409 
410  QString MainWindow::undoIconStyle() const
411  {
412  return mUndoIconStyle;
413  }
414 
415  QString MainWindow::neGateIconPath() const
416  {
417  return mNeGateIconPath;
418  }
419  QString MainWindow::neGateIconStyle() const
420  {
421  return mNeGateIconStyle;
422  }
423 
424  QString MainWindow::disabledIconStyle() const
425  {
426  return mDisabledIconStyle;
427  }
428 
429  void MainWindow::setHalIconPath(const QString& path)
430  {
431  mHalIconPath = path;
432  }
433 
434  void MainWindow::setHalIconStyle(const QString& style)
435  {
436  mHalIconStyle = style;
437  }
438 
439  void MainWindow::setOpenFileIconPath(const QString& path)
440  {
441  mOpenFileIconPath = path;
442  }
443 
444  void MainWindow::setOpenFileIconStyle(const QString& style)
445  {
446  mOpenFileIconStyle = style;
447  }
448 
449  void MainWindow::setQuitIconPath(const QString& path)
450  {
451  mQuitIconPath = path;
452  }
453 
454  void MainWindow::setQuitIconStyle(const QString& style)
455  {
456  mQuitIconStyle = style;
457  }
458 
459  void MainWindow::setSettingsIconPath(const QString& path)
460  {
461  mSettingsIconPath = path;
462  }
463 
464  void MainWindow::setSettingsIconStyle(const QString& style)
465  {
466  mSettingsIconStyle = style;
467  }
468 
469  void MainWindow::setPluginsIconPath(const QString& path)
470  {
471  mPluginsIconPath = path;
472  }
473 
474  void MainWindow::setPluginsIconStyle(const QString& style)
475  {
476  mPluginsIconStyle = style;
477  }
478 
479  void MainWindow::setUndoIconPath(const QString& path)
480  {
481  mUndoIconPath = path;
482  }
483 
484  void MainWindow::setUndoIconStyle(const QString& style)
485  {
486  mUndoIconStyle = style;
487  }
488 
489  void MainWindow::setNeGateIconPath(const QString& path)
490  {
491  mNeGateIconPath = path;
492  }
493  void MainWindow::setNeGateIconStyle(const QString& style)
494  {
495  mNeGateIconStyle = style;
496  }
497 
498  void MainWindow::setDisabledIconStyle(const QString& style)
499  {
500  mDisabledIconStyle = style;
501  }
502 
503  void MainWindow::addContent(ContentWidget* widget, int index, content_anchor anchor)
504  {
505  mLayoutArea->addContent(widget, index, anchor);
506  }
507 
508  void MainWindow::removeContent(ContentWidget* widget)
509  {
510  Q_UNUSED(widget)
511  // IMPLEMENT
512  }
513 
515  {
516  mLayoutArea->clear();
517  }
518 
519  void MainWindow::handleEventLogEnabled(bool enable)
520  {
522  }
523 
524  extern void runMain(const QString fileName, const QList<QString> plugins);
525 
526  void MainWindow::onActionCloseDocumentTriggered()
527  {
528  //mLayoutArea->removeContent();
529  }
530 
531  void MainWindow::openSettings()
532  {
534  {
535  if(!mGateLibraryManager->callUnsavedChangesWindow()) return;
536  }
537  if (mStackedWidget->currentWidget() == mSettings)
538  return; //nothing todo, already fetchGateLibrary
539 
540  mSettings->activate();
541  mStackedWidget->setCurrentWidget(mSettings);
542  }
543 
544  void MainWindow::closeSettings()
545  {
546  if (!mSettings->handleAboutToClose())
547  return;
548  if (FileManager::get_instance()->fileOpen())
549  mStackedWidget->setCurrentWidget(mLayoutArea);
550  else
551  mStackedWidget->setCurrentWidget(mWelcomeScreen);
552  }
553 
554  void MainWindow::closeGateLibraryManager()
555  {
556  bool isFileOpen = FileManager::get_instance()->fileOpen();
557  if(isFileOpen)
558  mStackedWidget->setCurrentWidget(mLayoutArea);
559  else
560  mStackedWidget->setCurrentWidget(mWelcomeScreen);
561  mFileActions->setup();
562  }
563 
564  void MainWindow::openPluginManager()
565  {
567  {
568  if(!mGateLibraryManager->callUnsavedChangesWindow()) return;
569  }
570 
571  mPluginManager->repolish();
572  if (mStackedWidget->currentWidget() == mPluginManager)
573  return; //nothing todo, already fetchGateLibrary
574 
575  if (mStackedWidget->currentWidget() == mSettings)
576  {
577  if (!mSettings->handleAboutToClose())
578  return;
579  }
580  mStackedWidget->setCurrentWidget(mPluginManager);
581  mFileActions->setup(nullptr, mPluginManager);
582  }
583 
584  void MainWindow::closePluginManager()
585  {
586  if (FileManager::get_instance()->fileOpen())
587  mStackedWidget->setCurrentWidget(mLayoutArea);
588  else
589  mStackedWidget->setCurrentWidget(mWelcomeScreen);
590 
591  mMenuPlugins->clear();
592  if (FileManager::get_instance()->fileOpen())
593  mPluginManager->addPluginActions(mMenuPlugins);
594  else
595  mMenuPlugins->setDisabled(true);
596  mFileActions->setup();
597  }
598 
599  void MainWindow::handleActionNew()
600  {
601  if (gNetlist != nullptr)
602  {
603  QMessageBox msgBox;
604  msgBox.setText("Error: New Project");
606  msgBox.setStyleSheet("QLabel{min-width: 600px;}");
609  msgBox.exec();
610  return;
611  }
612 
613  ActionOpenNetlistFile* act = new ActionOpenNetlistFile(ActionOpenNetlistFile::CreateNew);
614  act->exec();
615  }
616 
617  void MainWindow::handleActionOpenProject()
618  {
619  if (gNetlist != nullptr)
620  {
621  QMessageBox msgBox;
622  msgBox.setText("Error: Open Project");
624  msgBox.setStyleSheet("QLabel{min-width: 600px;}");
627  msgBox.exec();
628  return;
629  }
630 
631  ProjectDirDialog pdd("Open HAL project", QDir::currentPath(), this);
632  if (pdd.exec() != QDialog::Accepted) return;
633  QStringList projects = pdd.selectedFiles();
634  for (int inx = 0; inx < projects.size(); ++inx)
635  {
636  if (!QFileInfo(projects.at(inx)).suffix().isEmpty())
637  {
638  QMessageBox::warning(this,"Bad project directory", "HAL project directories must not have suffix (." +
639  QFileInfo(projects.at(inx)).suffix() + ") in name");
640  continue;
641  }
642  ActionOpenNetlistFile* act = new ActionOpenNetlistFile(ActionOpenNetlistFile::OpenProject, pdd.selectedFiles().at(inx));
643  act->exec();
644  break;
645  }
646  }
647 
648  void MainWindow::handleActionImportNetlist()
649  {
650  if (gNetlist != nullptr)
651  {
652  QMessageBox msgBox;
653  msgBox.setText("Error: Import Netlist");
655  msgBox.setStyleSheet("QLabel{min-width: 600px;}");
658  msgBox.exec();
659  return;
660  }
661 
662  QString title = "Import Netlist";
663  SupportedFileFormats sff = gPluginRelay->mGuiPluginTable->listFacFeature(FacExtensionInterface::FacNetlistParser);
664  QString text = sff.toFileDialog(true);
665 
666  // Non native dialogs does not work on macOS. Therefore do net set DontUseNativeDialog!
667  QString path = QDir::currentPath();
668 
669  if (gGuiState->contains("FileDialog/Path/MainWindow"))
670  path = gGuiState->value("FileDialog/Path/MainWindow").toString();
671 
672  QString fileName = QFileDialog::getOpenFileName(nullptr, title, path, text, nullptr);
673 
674  if (!fileName.isNull())
675  {
676  QString ext = QFileInfo(fileName).suffix();
677  if (!ext.isEmpty())
678  gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacNetlistParser,ext);
679 
680  gGuiState->setValue("FileDialog/Path/MainWindow", fileName);
681 
682  ActionOpenNetlistFile* actOpenfile = new ActionOpenNetlistFile(ActionOpenNetlistFile::ImportFile, fileName);
683  actOpenfile->exec();
684  }
685  }
686 
687  void MainWindow::handleProjectOpened(const QString& projDir, const QString& fileName)
688  {
689  Q_UNUSED(projDir);
690  mActionExportProject->setEnabled(true);
691  mActionImportProject->setDisabled(true);
692  handleFileOpened(fileName);
693  }
694 
695  void MainWindow::handleFileOpened(const QString& fileName)
696  {
697  Q_UNUSED(fileName)
698  if (mStackedWidget->currentWidget() == mWelcomeScreen)
699  {
700  mStackedWidget->setCurrentWidget(mLayoutArea);
701  mWelcomeScreen->close();
702  }
703  gPythonContext->updateNetlist();
704 
705  mMenuPlugins->clear();
706  mPluginManager->addPluginActions(mMenuPlugins);
707  }
708 
709  void MainWindow::handleActionExport()
710  {
711  if (!gNetlist) return;
712  QAction* act = static_cast<QAction*>(sender());
713  if (!act || act->data().isNull()) return;
714 
716  if (erf.queryFilename())
717  erf.exportNetlist();
718 
719  }
720 
721  void MainWindow::handleActionGatelibraryManager()
722  {
723  if(!gNetlist)
724  {
725  QMessageBox optBox;
726  QPushButton* newBtn = optBox.addButton("New", QMessageBox::AcceptRole);
727  newBtn->setToolTip("Create new gate library");
728  QPushButton* openBtn = optBox.addButton(QMessageBox::Open);
729  openBtn->setToolTip("Open existing gate library");
730  QPushButton* cancelBtn = optBox.addButton(QMessageBox::Cancel);
731  optBox.setWindowTitle("Please select …");
732  cancelBtn->setToolTip("Cancel");
733 
734  optBox.setText("Gate Library Manager");
735 
736  auto btn = optBox.exec();
737 
738  if(optBox.clickedButton() == newBtn)
739  {
740  mGateLibraryManager->handleCreateAction();
741  mStackedWidget->setCurrentWidget(mGateLibraryManager);
742  mFileActions->setup(mGateLibraryManager);
743  return;
744  }
745  else if (optBox.clickedButton() == cancelBtn)
746  return;
747  }
749  {
750  if(!mGateLibraryManager->callUnsavedChangesWindow()) return;
751  }
752  if(mGateLibraryManager->initialize())
753  {
754  mStackedWidget->setCurrentWidget(mGateLibraryManager);
755  mFileActions->setup(mGateLibraryManager);
756  }
757  }
758 
759  void MainWindow::handleImportProjectTriggered()
760  {
761  ImportProjectDialog ipd(this);
762  if (ipd.exec() == QDialog::Accepted)
763  {
764  if (ipd.importProject())
765  {
766  ActionOpenNetlistFile* act = new ActionOpenNetlistFile(ActionOpenNetlistFile::OpenProject,
767  ipd.extractedProjectAbsolutePath());
768  act->exec();
769  }
770  else
772  "Import Project Failed",
773  "Failed to extract a HAL project from selected archive file.\n"
774  "You might want to uncompress the archive manually and try to fetchGateLibrary the project.");
775  }
776  }
777 
778  void MainWindow::handleExportProjectTriggered()
779  {
780  ExportProjectDialog epd(this);
781  if (epd.exec() == QDialog::Accepted)
782  {
783  epd.exportProject();
784  }
785  }
786 
787  void MainWindow::handleSaveAsTriggered()
788  {
789  QString filename = saveHandler();
790  if (!filename.isEmpty())
791  gContentManager->setWindowTitle(filename);
792  }
793 
794  void MainWindow::handleSaveTriggered()
795  {
796  ProjectManager* pm = ProjectManager::instance();
797  if (pm->get_project_status() == ProjectManager::ProjectStatus::NONE) return;
798  QString projectDir = QString::fromStdString(pm->get_project_directory().string());
799  saveHandler(projectDir);
800  gContentManager->setWindowTitle(projectDir);
801  }
802 
803  QString MainWindow::saveHandler(const QString &projectDir)
804  {
805  if (!gNetlist) return QString();
806 
807  QString saveProjectDir(projectDir);
808 
809  ProjectManager* pm = ProjectManager::instance();
810 
811  if (saveProjectDir.isEmpty())
812  {
813  QString title = "Save Project";
814  QString filter = "HAL Directory Folder (*)";
815 
816  // Non native dialogs does not work on macOS. Therefore do net set DontUseNativeDialog!
817  saveProjectDir = QFileDialog::getSaveFileName(nullptr, title, QDir::currentPath(), filter, nullptr);
818  if (saveProjectDir.isEmpty()) return QString();
819 
820  QFileInfo finfo(saveProjectDir);
821 
822  if (!finfo.suffix().isEmpty())
823  {
824  QMessageBox::warning(this,"Save Error", "selected project directory name must not have suffix ." + finfo.suffix());
825  return QString();
826  }
827  if (finfo.exists())
828  {
829  QMessageBox::warning(this,"Save Error", "folder " + saveProjectDir + " already exists");
830  return QString();
831  }
832 
833  if (!pm->create_project_directory(saveProjectDir.toStdString()))
834  {
835  QMessageBox::warning(this,"Save Error", "cannot create folder " + saveProjectDir);
836  return QString();
837  }
838  }
839 
841 
842  if (!pm->serialize_project(gNetlist))
843  {
844  log_warning("gui", "error saving netlist to <" + qNetlistPath.toStdString() + ">");
845  return QString();
846  }
847 
849 
850  FileManager* fm = FileManager::get_instance();
851  fm->watchFile(qNetlistPath);
852  fm->emitProjectSaved(saveProjectDir, qNetlistPath);
853 
854  return QString::fromStdString(pm->get_project_directory().string());
855  }
856 
857  void MainWindow::handleActionStartRecording()
858  {
859  mActionStartRecording->setEnabled(false);
860  mActionStopRecording->setEnabled(true);
861  mActionPlayMacro->setEnabled(false);
862  UserActionManager::instance()->setStartRecording();
863  }
864 
865  void MainWindow::handleActionStopRecording()
866  {
867  UserActionManager* uam = UserActionManager::instance();
868  QString macroFile;
869  bool trySaveMacro = true;
870  while (trySaveMacro) {
871  if (uam->hasRecorded())
872  {
873  macroFile = QFileDialog::getSaveFileName(this, "Save macro to file", ".");
874  if (!macroFile.isEmpty() && !macroFile.contains(QChar('.')))
875  macroFile += ".xml";
876  }
877  switch (uam->setStopRecording(macroFile))
878  {
879  case QMessageBox::Retry:
880  break;
881  case QMessageBox::Cancel:
882  return;
883  default:
884  // Ok or Discard
885  trySaveMacro = false;
886  break;
887  }
888  }
889  mActionStartRecording->setEnabled(true);
890  mActionStopRecording->setEnabled(false);
891  mActionPlayMacro->setEnabled(true);
892  }
893 
894  void MainWindow::handleActionPlayMacro()
895  {
896  QString macroFile = QFileDialog::getOpenFileName(this, "Load macro file", ".", "Macro files (*.xml);;All files(*)");
897  if (!macroFile.isEmpty())
898  UserActionManager::instance()->playMacro(macroFile);
899  }
900 
901  void MainWindow::handleActionAbout()
902  {
903  AboutDialog ad;
904  ad.exec();
905  }
906 
907  void MainWindow::handleActionUndo()
908  {
909  UserActionManager::instance()->undoLastAction();
910  }
911 
912  void MainWindow::enableUndo(bool enable)
913  {
914  QString iconStyle = enable ? mUndoIconStyle : mDisabledIconStyle;
915  mActionUndo->setEnabled(enable);
916  mActionUndo->setIcon(gui_utility::getStyledSvgIcon(iconStyle, mUndoIconPath));
917  }
918 
919  void MainWindow::handleActionCloseFile()
920  {
921  if (FileManager::get_instance()->fileOpen())
922  tryToCloseFile();
923  }
924 
925  void MainWindow::onActionQuitTriggered()
926  {
927  close();
928  }
929 
930  void MainWindow::closeEvent(QCloseEvent* event)
931  {
932  if (gFileStatusManager->isGatelibModified() || FileManager::get_instance()->fileOpen())
933  {
934  if (tryToCloseFile())
935  event->accept();
936  else
937  {
938  event->ignore();
939  return;
940  }
941  }
942 
943  saveState();
944  qApp->quit();
945  }
946 
947  bool MainWindow::tryToCloseFile()
948  {
950  {
951  QMessageBox msgBox(this);
952  msgBox.setStyleSheet("QLabel{min-width: 600px;}");
953  auto cancelButton = msgBox.addButton("Cancel", QMessageBox::RejectRole);
954  msgBox.addButton("Close Anyway", QMessageBox::ApplyRole);
955  msgBox.setDefaultButton(cancelButton);
956  msgBox.setInformativeText("Are you sure you want to close the application ?");
957 
958  msgBox.setText("There are unsaved modifications.");
959  QString detailed_text = "The following modifications have not been saved yet:\n";
961  detailed_text.append(" -> modified Gate Library\n");
962  for (const auto& s : gFileStatusManager->getUnsavedChangeDescriptors())
963  detailed_text.append(" -> " + s + "\n");
964 
965  msgBox.setDetailedText(detailed_text);
966 
967  for (const auto& button : msgBox.buttons())
968  {
969  // if (button->text() == "Show Details...")
970  if (msgBox.buttonRole(button) == QMessageBox::ActionRole)
971  {
972  button->click();
973  break;
974  }
975  }
976 
977  msgBox.exec();
978 
979  if (msgBox.clickedButton() == cancelButton)
980  return false;
981  }
982 
983  // going to close
984 
985  for (GuiExtensionInterface* geif : GuiPluginManager::getGuiExtensions().values())
986  geif->netlist_about_to_close(gNetlist);
987 
988  mActionExportProject->setDisabled(true);
989  mActionImportProject->setEnabled(true);
990 
991  gPythonContext->abortThreadAndWait();
992 
994 
995  clear();
996 
998  // PYTHON ???
1001 
1002  FileManager::get_instance()->closeFile();
1003  setWindowTitle("HAL");
1004  gFileStatusManager->netlistClosed(); // disable save actions
1005 
1006  mStackedWidget->setCurrentWidget(mWelcomeScreen);
1007 
1008  gNetlistRelay->reset();
1009 
1010  mMenuPlugins->clear();
1011  mMenuPlugins->setDisabled(true);
1012 // mActionGateLibraryManager->setVisible(true);
1013 
1014  return true;
1015  }
1016 
1017  void MainWindow::restoreState()
1018  {
1019  QPoint pos = SettingsManager::instance()->mainWindowPosition();
1020  move(pos);
1021  QSize size = SettingsManager::instance()->mainWindowSize();
1022  resize(size);
1023  //restore state of all subwindows
1024  mLayoutArea->initSplitterSize(size);
1025  }
1026 
1027  void MainWindow::saveState()
1028  {
1029  SettingsManager::instance()->mainWindowSaveGeometry(pos(), size());
1030  }
1031 
1032 
1033 } // namespace hal
A dialog that displays the Qt version and our open source license.
Definition: about_dialog.h:43
Provides an interface for triggerable functionality that can be inserted into widgets and also connec...
Definition: action.h:42
Manages the layout of all ContentWidgets.
Manages all ContentWidgets.
void setWindowTitle(const QString &filename)
Abstract class for Widgets within HAL's ContentArea.
Utility class to export (save) different hal files.
static FileManager * get_instance()
void projectOpened(QString projectDir, QString fileName)
void fileOpened(const QString &fileName)
QList< QString > getUnsavedChangeDescriptors() const
SupportedFileFormats listFacFeature(FacExtensionInterface::Feature ft) const
void loadFeature(FacExtensionInterface::Feature ft, const QString &extension=QString())
The top-level widget that displays all settings.
void closeGateLibraryManager()
void openPluginManager()
void handleActionImportNetlist()
void handleActionAbout()
void handleActionGatelibraryManager()
void handleActionUndo()
void closePluginManager()
void reloadStylsheet(int istyle)
void handleActionStopRecording()
void handleActionStartRecording()
void enableUndo(bool enable=true)
void handleProjectOpened(const QString &projDir, const QString &fileName)
void handleActionPlayMacro()
void onActionQuitTriggered()
void handleFileOpened(const QString &fileName)
void handleActionExport()
static SettingsItemDropdown * sSettingStyle
Definition: main_window.h:302
GuiPluginTable * mGuiPluginTable
Definition: plugin_relay.h:68
std::filesystem::path get_default_filename(const std::string &extension=std::string()) const
bool create_project_directory(const std::string &path)
bool serialize_project(Netlist *netlist, bool shadow=false)
ProjectStatus get_project_status() const
const ProjectDirectory & get_project_directory() const
A SettingsItem representing a Checkbox.
virtual QVariant value() const override
A SettingsItem that represents a dropdown menu.
void intChanged(int value)
A SettingsItem to modify keybinds.
void keySequenceChanged(QKeySequence value)
QString toFileDialog(bool addHalFormat) const
Handles and manages user actions related proccesses.
void canUndoLastAction(bool yesWeCan)
static UserActionManager * instance()
QMessageBox::StandardButton setStopRecording(const QString &macroFilename)
Hal's welcome screen.
#define log_warning(channel,...)
Definition: log.h:76
action
Definition: control.py:16
void enable_event_log(bool enable)
Definition: event_log.cpp:20
QIcon getStyledSvgIcon(const QString &from_to_colors_enabled, const QString &svg_path, QString from_to_colors_disabled=QString())
Definition: graphics.cpp:60
const std::unordered_map< std::string, std::vector< std::string > > & get_writer_extensions()
Retrieve the extensions for which extensions have been registered.
const char * MSG_PROJECT_ALREADY_OPEN
Definition: main_window.cpp:58
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
void runMain(const QString fileName, const QList< QString > plugins)
GraphContextManager * gGraphContextManager
Definition: plugin_gui.cpp:85
SelectionRelay * gSelectionRelay
Definition: plugin_gui.cpp:83
CommentManager * gCommentManager
Definition: plugin_gui.cpp:87
Netlist * gNetlist
Definition: plugin_gui.cpp:80
NetlistRelay * gNetlistRelay
Definition: plugin_gui.cpp:81
This file contains various functions to create and load netlists.
QVariant data() const const
void setDisabled(bool b)
void trigger()
void triggered(bool checked)
virtual int exec()
QString currentPath()
virtual bool open(QIODevice::OpenMode mode) override
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QStringList selectedFiles() const const
QString suffix() const const
QByteArray readAll()
void append(const T &value)
const T & at(int i) const const
int size() const const
QAction * addAction(const QString &text)
void addButton(QAbstractButton *button, QMessageBox::ButtonRole role)
QAbstractButton * clickedButton() const const
virtual int exec() override
void setInformativeText(const QString &text)
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)
QString cap(int nth) const const
int indexIn(const QString &str, int offset, QRegExp::CaretMode caretMode) const const
bool contains(const QString &key) const const
void setValue(const QString &key, const QVariant &value)
QVariant value(const QString &key, const QVariant &defaultValue) const const
void activated()
void setKey(const QKeySequence &key)
QString & append(QChar ch)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
bool isNull() const const
QString & remove(int position, int n)
std::string toStdString() const const
CaseInsensitive
ToolButtonIconOnly
bool isNull() const const
bool toBool() const const
QString toString() const const
QStringList toStringList() const const
void setStyleSheet(const QString &styleSheet)
void setToolTip(const QString &)