4#include "moc_DynExpManager.cpp"
5#include "ui_DynExpManager.h"
9 : QMainWindow(parent), DynExpCore(DynExpCore),
10 ui(std::make_unique<
Ui::DynExpManagerClass>()),
11 UpdateUITimer(new QTimer(this)),
13 ModuleWindowsActionGroup(new QActionGroup(this)),
14 UIThemeActionGroup(new QActionGroup(this)), UIBrightThemeAction(nullptr), UIDarkThemeAction(nullptr),
15 LogContextMenu(new QMenu(this)),
16 ItemTreeContextMenu(new QMenu(this)), ClearWarningAction(nullptr),
17 ItemTreeHardwareAdapters(nullptr), ItemTreeInstruments(nullptr), ItemTreeModules(nullptr),
18 StatusBar(this), IsResetting(false), ShouldRedrawCircuitDiagram(true), ShouldUpdateCircuitDiagram(false)
20 qApp->setStyle(QStyleFactory::create(
"Fusion"));
46 ui->tableLog->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
47 ui->tableLog->verticalHeader()->setMinimumSectionSize(18);
48 ui->tableLog->verticalHeader()->setDefaultSectionSize(
ui->tableLog->verticalHeader()->minimumSectionSize());
49 ui->tableLog->setColumnWidth(0, 140);
73 ui->treeItems->header()->resizeSection(0, 120);
74 ui->treeItems->header()->resizeSection(1, 180);
75 ui->treeItems->header()->resizeSection(2, 100);
76 ui->splitterInstrListMain->setStretchFactor(0, 16);
77 ui->splitterInstrListMain->setStretchFactor(1, 5);
102 : NumItemsInWarningState(0), NumItemsInErrorState(0),
103 State(new QPushButton(Owner)),
104 NumRunningInstrGroup(new QWidget(Owner)), NumRunningInstrLayout(new QHBoxLayout),
105 NumRunningInstrImage(new QLabel(Owner)), NumRunningInstr(new QLabel(Owner)),
106 NumRunningModuleGroup(new QWidget(Owner)), NumRunningModuleLayout(new QHBoxLayout),
107 NumRunningModuleImage(new QLabel(Owner)), NumRunningModule(new QLabel(Owner))
109 constexpr int Height = 16;
111 State->setFlat(
true);
112 State->setMinimumHeight(24);
113 State->setFocusPolicy(Qt::FocusPolicy::NoFocus);
117 NumRunningInstrImage->setSizePolicy({ QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum });
120 NumRunningInstr->setSizePolicy({ QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding });
124 NumRunningModuleImage->setSizePolicy({ QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum });
127 NumRunningModule->setSizePolicy({ QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding });
141 std::string ObjectName =
"< Unknown >";
151 ObjectName =
"< Error while fetching name >";
163 std::string ErrorMessage =
"";
171 ErrorMessage = e.what();
173 catch (
const std::exception& e)
175 ErrorMessage = e.what();
179 ErrorMessage =
"Unknown Error";
182 if (!ErrorMessage.empty())
184 QMessageBox::warning(
this,
"DynExp - Error",
185 QString::fromStdString(
186 "Starting up the item " +
GetObjectNameSafe(Object) +
", the following error occurred:\n\n"
197 std::string ErrorMessage =
"";
205 ErrorMessage = e.what();
207 catch (
const std::exception& e)
209 ErrorMessage = e.what();
213 ErrorMessage =
"Unknown Error";
216 if (!ErrorMessage.empty())
220 QMessageBox::warning(
this,
"DynExp - Error",
221 QString::fromStdString(
222 "Resetting the item " + ObjectName +
", the following error occurred:\n\n"
231 if (EventLogSize >= std::numeric_limits<int>::max())
234 if (
ui->tableLog->rowCount() <
static_cast<int>(EventLogSize))
237 for (
const auto& LogEntry : Log)
239 const auto Row =
ui->tableLog->rowCount();
241 ui->tableLog->setRowCount(Row + 1);
242 ui->tableLog->setItem(Row, 0,
new QTableWidgetItem(QString::fromStdString(
Util::ToStr(LogEntry.TimePoint))));
244 ui->tableLog->setItem(Row, 2,
new QTableWidgetItem(QString::fromStdString(LogEntry.Message)));
246 for (
int i = 0; i < 3; ++i)
249 ui->tableLog->resizeColumnToContents(2);
250 ui->tableLog->scrollToBottom();
257 for (
auto i =
ui->tableLog->rowCount() - 1; i >= 0; --i)
258 for (
int j = 0; j < 3; ++j)
266 for (
auto ModuleIter = ModuleManager.cbegin(); ModuleIter != ModuleManager.cend(); ++ModuleIter)
270 auto Module = ModuleIter->second.ResourcePointer.get();
273 if (!Module->HasUI())
279 if (!QModule.IsRunning())
281 else if (QModule.IsPaused())
299 catch (
const std::exception& e)
316 setWindowTitle(QString::fromStdString(std::string(
"DynExp Manager - ") + ProjectFilename.string()));
319 setWindowTitle(
"DynExp Manager");
351 if (NumRunningInstr + NumRunningModule > 0)
411 ItemToSelect = LastAdded;
414 ItemToSelect = LastAdded;
418 ui->treeItems->clearSelection();
419 ItemToSelect->setSelected(
true);
433 std::string ObjectName;
434 if (ExceptionPtr || Warning)
457 else if (!IsConnected)
461 "This hardware adapter is not connected yet, and thus it cannot be used now.");
470 constexpr auto Msg =
"This hardware adapter does not respond.";
488 std::string ObjectName;
489 if (ExceptionPtr || Warning)
521 "This instrument is ready to be run.",
"Stopped");
526 constexpr auto Msg =
"This instrument does not respond.";
539 static constexpr auto PausedString =
"This module is paused because one or more linked instruments have been terminated. Restart these instruments in order to continue.";
540 static bool DisplayWarning =
false;
541 static auto DisplayWarningLastSwitchTime = std::chrono::system_clock::now();
543 if (DisplayWarningLastSwitchTime <= std::chrono::system_clock::now() - std::chrono::seconds(2))
545 DisplayWarning = !DisplayWarning;
546 DisplayWarningLastSwitchTime = std::chrono::system_clock::now();
554 std::string ObjectName;
578 ErrorEntries.emplace_back(QString::fromStdString(ObjectName),
579 QString(PausedString) +
"\n\n" + QString::fromStdString(Resource.
ResourcePointer->GetReasonWhyPaused().Description),
583 if ((Warning && !Resource.
ResourcePointer->IsPaused()) || (Warning && DisplayWarning))
603 "This module is ready to be run.",
"Stopped");
608 constexpr auto Msg =
"This module does not respond.";
620 bool FetchingObjectNameFailed =
false;
624 ObjectName = QString::fromStdString(Object->
GetObjectName());
628 ObjectName =
"< Error >";
629 FetchingObjectNameFailed =
true;
632 Item->setText(0, ObjectName);
633 Item->setToolTip(0, ObjectName);
634 Item->setData(0, Qt::ItemDataRole::UserRole, QVariant::fromValue(FetchingObjectNameFailed));
642 for (
int i = 0; i <
ui->treeItems->topLevelItemCount(); ++i)
644 QTreeWidgetItem* ParentItem =
ui->treeItems->topLevelItem(i);
645 for (
int j = 0; j < ParentItem->childCount(); ++j)
647 QTreeWidgetItem* ChildItem = ParentItem->child(j);
648 if (ChildItem->data(1, Qt::ItemDataRole::UserRole).value<
decltype(SelectedEntry)>() == SelectedEntry)
652 ui->treeItems->clearSelection();
653 ui->treeItems->setFocus();
654 ChildItem->setSelected(
true);
663 const QString& Description,
const QString& StateTitle,
const char* IconPath)
665 ItemTreeItem.setData(2, Qt::ItemDataRole::UserRole,
667 ItemTreeItem.setIcon(2, QIcon(IconPath));
668 ItemTreeItem.setText(2, StateTitle);
669 ItemTreeItem.setForeground(2, QApplication::palette().text().color());
670 ItemTreeItem.setToolTip(2, Description);
679 const QString& Description)
681 ItemTreeItem.setData(2, Qt::ItemDataRole::UserRole,
684 ItemTreeItem.setText(2,
"Running");
686 ItemTreeItem.setToolTip(2, Description);
695 const QString& Description)
697 ItemTreeItem.setData(2, Qt::ItemDataRole::UserRole,
700 ItemTreeItem.setText(2,
"Paused");
702 ItemTreeItem.setToolTip(2, Description);
711 const QString& Description)
713 ItemTreeItem.setData(2, Qt::ItemDataRole::UserRole,
716 ItemTreeItem.setText(2,
"Warning");
718 ItemTreeItem.setToolTip(2, Description);
727 const std::exception_ptr& ExceptionPtr)
729 ItemTreeItem.setData(2, Qt::ItemDataRole::UserRole,
732 ItemTreeItem.setText(2,
"Error");
743 const QString& Description)
745 ItemTreeItem.setData(2, Qt::ItemDataRole::UserRole,
748 ItemTreeItem.setText(2,
"Connecting...");
749 ItemTreeItem.setForeground(2, QApplication::palette().text().color());
750 ItemTreeItem.setToolTip(2, Description);
756 const QString& Description)
758 ItemTreeItem.setData(2, Qt::ItemDataRole::UserRole,
761 ItemTreeItem.setText(2,
"Not responding");
763 ItemTreeItem.setToolTip(2, Description);
773 QString HTMLColorQ = QString::fromStdString(HTMLColor);
777 if (HTMLColorQ.toLower() ==
"blue")
779 if (HTMLColorQ.toLower() ==
"green")
783 return QColor(HTMLColorQ);
791 return QColor(
"blue");
795 if (Color == QColor(
"blue"))
824 if (QMessageBox::question(
this,
"DynExp - Close project?",
825 "Really close the current project? All running items will be stopped and unsaved changes will be lost.",
826 QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::No)
827 != QMessageBox::StandardButton::Yes)
830 std::string ErrorMessage =
"";
838 ErrorMessage = e.what();
840 catch (
const std::exception& e)
842 ErrorMessage = e.what();
846 ErrorMessage =
"Unknown Error";
849 if (!ErrorMessage.empty())
851 auto Result = QMessageBox::critical(
this,
"DynExp - Critical error",
852 QString::fromStdString(
853 "Closing a project and stopping all running items, the following error occurred:\n\n"
854 + ErrorMessage +
"\n\n- Click 'Retry' to try again to close the project."
855 +
"\n- Click 'Ignore' to force the project to be closed. This may cause DynExp to be terminated without properly shutting down."
856 +
"\n- Click 'Cancel' to return to the project without closing it."
857 ), QMessageBox::StandardButton::Cancel | QMessageBox::StandardButton::Retry | QMessageBox::StandardButton::Ignore,
858 QMessageBox::StandardButton::Cancel);
862 case QMessageBox::StandardButton::Cancel:
return false;
863 case QMessageBox::StandardButton::Ignore:
return true;
875 std::string ErrorMessage =
"";
883 ErrorMessage = e.what();
885 catch (
const std::exception& e)
887 ErrorMessage = e.what();
891 ErrorMessage =
"Unknown Error";
894 if (!ErrorMessage.empty())
896 auto Result = QMessageBox::critical(
this,
"DynExp - Critical error",
897 QString::fromStdString(
898 "Stopping a worker thread, the following error occurred:\n\n"
899 + ErrorMessage +
"\n\n- Click 'Retry' to try again to stop the thread."
900 +
"\n- Click 'Ignore' to force DynExp to be terminated without properly shutting down."
901 +
"\n- Click 'Cancel' to return to DynExp without closing it."
902 ), QMessageBox::StandardButton::Cancel | QMessageBox::StandardButton::Retry | QMessageBox::StandardButton::Ignore,
903 QMessageBox::StandardButton::Cancel);
907 case QMessageBox::StandardButton::Cancel:
return false;
908 case QMessageBox::StandardButton::Ignore: std::terminate();
918 std::string ErrorMessage =
"";
926 ErrorMessage = e.what();
928 catch (
const std::exception& e)
930 ErrorMessage = e.what();
934 ErrorMessage =
"Unknown Error";
937 if (!ErrorMessage.empty())
939 QMessageBox::warning(
this,
"DynExp - Error",
940 QString::fromStdString(
941 std::string(
"Saving the project to file ").append(Filename)
942 +
", the following error occurred:\n\n" + ErrorMessage
949 ui->action_Run_Item->setEnabled(
false);
950 ui->action_Stop_Item->setEnabled(
false);
951 ui->action_Force_Stop_Item->setEnabled(
false);
952 ui->action_Reset_Item->setEnabled(
false);
953 ui->action_Configure_Item->setEnabled(
false);
954 ui->action_Delete_Item->setEnabled(
false);
964 for (std::remove_const_t<
decltype(NumModules)> i = 0; i < NumModules; ++i)
977 for (
auto ModuleIter = ModuleManager.cbegin(); ModuleIter != ModuleManager.cend(); ++ModuleIter)
981 auto Module = ModuleIter->second.ResourcePointer.get();
984 if (!Module->IsRunning() || !Module->HasUI())
996 catch (
const std::exception& e)
1012 for (
auto ModuleIter = ModuleManager.cbegin(); ModuleIter != ModuleManager.cend(); ++ModuleIter)
1016 auto Module = ModuleIter->second.ResourcePointer.get();
1019 if (!Module->IsRunning() || !Module->HasUI())
1024 if (QModule.IsActiveWindow())
1032 catch (
const std::exception& e)
1073 if (!Module->IsRunning())
1078 auto const Action = &Module->InitUI(*
this,
ui->mdiMain);
1081 ui->menu_Window->addAction(Action);
1097 std::string ErrorMessage =
"";
1098 std::string ObjectName =
"< Unknown >";
1102 Object->Terminate(Force);
1110 if (QMessageBox::warning(
this,
"DynExp - Force-terminate item?",
1111 QString(
"This runnable is currently being used by at least another item. Force-terminate the item?\n\n")
1113 QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::No)
1114 == QMessageBox::StandardButton::Yes)
1122 ErrorMessage = e.what();
1124 catch (
const std::exception& e)
1126 ErrorMessage = e.what();
1130 ErrorMessage =
"Unknown Error";
1133 if (!ErrorMessage.empty())
1135 QMessageBox::warning(
this,
"DynExp - Error",
1136 QString::fromStdString(
1137 "Stopping the item " + ObjectName +
", the following error occurred:\n\n"
1156 QCoreApplication::postEvent(
this, Event->clone());
1162 if (std::uncaught_exceptions())
1186 catch (
const std::exception& e)
1209 qApp->setPalette(QPalette());
1210 qApp->setStyleSheet(
"");
1237 auto Filename =
Util::PromptOpenFilePath(
this,
"Open project",
".dynp",
"DynExp project files (*.dynp)").toStdString();
1238 if (Filename.empty())
1241 std::string ErrorMessage =
"";
1249 ErrorMessage = e.what();
1251 catch (
const std::exception& e)
1253 ErrorMessage = e.what();
1257 ErrorMessage =
"Unknown Error";
1260 if (!ErrorMessage.empty())
1262 QMessageBox::warning(
this,
"DynExp - Error",
1263 QString::fromStdString(
1264 "Opening a project from file " + Filename +
", the following error occurred:\n\n"
1275 Util::EventLog().
Log(
"Error occurred while resetting project. Execution cannot continue.",
1310 auto Filename =
Util::PromptSaveFilePath(
this,
"Save project as",
".dynp",
"DynExp project files (*.dynp)").toStdString();
1311 if (Filename.empty())
1321 std::string ErrorMessage =
"";
1327 auto BusyDlg = std::make_unique<BusyDialog>(
this);
1328 BusyDlg->SetDescriptionText(
"Connecting hardware adapters...");
1332 auto Result = BusyDlg->exec();
1333 ConnectingHardwareAdaptersFuture.wait();
1335 if (Result == QDialog::Accepted)
1337 BusyDlg->SetDescriptionText(
"Starting instruments...");
1341 Result = BusyDlg->exec();
1343 if (Result == QDialog::Accepted)
1345 else if (BusyDlg->GetException())
1346 std::rethrow_exception(BusyDlg->GetException());
1348 else if (BusyDlg->GetException())
1349 std::rethrow_exception(BusyDlg->GetException());
1354 ErrorMessage = e.what();
1356 catch (
const std::exception& e)
1358 ErrorMessage = e.what();
1362 ErrorMessage =
"Unknown Error";
1365 if (!ErrorMessage.empty())
1367 QMessageBox::warning(
this,
"DynExp - Error",
1368 QString::fromStdString(
1369 "Starting up the project, the following error occurred:\n\n"
1379 std::string ErrorMessage =
"";
1387 ErrorMessage = e.what();
1389 catch (
const std::exception& e)
1391 ErrorMessage = e.what();
1395 ErrorMessage =
"Unknown Error";
1398 if (!ErrorMessage.empty())
1400 QMessageBox::warning(
this,
"DynExp - Error",
1401 QString::fromStdString(
1402 "Shutting down the project, the following error occurred:\n\n"
1412 std::string ErrorMessage =
"";
1420 ErrorMessage = e.what();
1422 catch (
const std::exception& e)
1424 ErrorMessage = e.what();
1428 ErrorMessage =
"Unknown Error";
1431 if (!ErrorMessage.empty())
1433 QMessageBox::warning(
this,
"DynExp - Error",
1434 QString::fromStdString(
1435 "Resetting the project's failed items, the following error occurred:\n\n"
1445 std::string ErrorMessage =
"";
1453 ErrorMessage = e.what();
1455 catch (
const std::exception& e)
1457 ErrorMessage = e.what();
1461 ErrorMessage =
"Unknown Error";
1464 if (!ErrorMessage.empty())
1466 QMessageBox::warning(
this,
"DynExp - Error",
1467 QString::fromStdString(
1468 "Restoring the main and module windows' geometries and states from the project file, the following error occurred:\n\n"
1476 std::string ErrorMessage =
"";
1484 ErrorMessage = e.what();
1486 catch (
const std::exception& e)
1488 ErrorMessage = e.what();
1492 ErrorMessage =
"Unknown Error";
1495 if (!ErrorMessage.empty())
1497 QMessageBox::warning(
this,
"DynExp - Error",
1498 QString::fromStdString(
1499 "Editing the project settings, the following error occurred:\n\n"
1507 if (
ui->treeItems->selectedItems().length() != 1)
1510 auto Item =
ui->treeItems->selectedItems()[0];
1513 std::string ErrorMessage =
"";
1514 std::string ObjectName =
"< Unknown >";
1535 ErrorMessage = e.what();
1537 catch (
const std::exception& e)
1539 ErrorMessage = e.what();
1543 ErrorMessage =
"Unknown Error";
1546 if (!ErrorMessage.empty())
1548 QMessageBox::warning(
this,
"DynExp - Error",
1549 QString::fromStdString(
1550 "Starting the item " + ObjectName +
", the following error occurred:\n\n"
1560 if (
ui->treeItems->selectedItems().length() != 1)
1563 auto Item =
ui->treeItems->selectedItems()[0];
1567 std::string ErrorMessage =
"";
1578 ErrorMessage = e.what();
1580 catch (
const std::exception& e)
1582 ErrorMessage = e.what();
1586 ErrorMessage =
"Unknown Error";
1589 if (!ErrorMessage.empty())
1591 QMessageBox::warning(
this,
"DynExp - Error",
1592 QString::fromStdString(
1593 "Determining the object to be stopped, the following error occurred:\n\n"
1608 if (
ui->treeItems->selectedItems().length() != 1)
1611 auto Item =
ui->treeItems->selectedItems()[0];
1615 std::string ErrorMessage =
"";
1628 ErrorMessage = e.what();
1630 catch (
const std::exception& e)
1632 ErrorMessage = e.what();
1636 ErrorMessage =
"Unknown Error";
1639 if (!ErrorMessage.empty())
1643 QMessageBox::warning(
this,
"DynExp - Error",
1644 QString::fromStdString(
1645 "Resetting the item " + ObjectName +
", the following error occurred:\n\n"
1657 if (
ui->treeItems->selectedItems().length() != 1)
1660 auto Item =
ui->treeItems->selectedItems()[0];
1664 bool ResetRequired =
false;
1666 std::string ErrorMessage =
"";
1674 Object = RunnableObject;
1679 Object = RunnableObject;
1695 ErrorMessage = e.what();
1697 catch (
const std::exception& e)
1699 ErrorMessage = e.what();
1703 ErrorMessage =
"Unknown Error";
1708 if (!ErrorMessage.empty())
1709 QMessageBox::warning(
this,
"DynExp - Error",
1710 QString::fromStdString(
1711 "Configuring the item " + ObjectName +
", the following error occurred:\n\n"
1719 if ((Object && !RunnableObject) || (RunnableObject && RunnableObject->
IsRunning()) )
1721 if (QMessageBox::question(
this,
"DynExp - Reset item?",
1722 QString::fromStdString(
"The item " + ObjectName +
" needs to be reset in order to apply the changes. Should it be reset now?"),
1723 QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::No)
1724 == QMessageBox::StandardButton::Yes)
1737 if (
ui->treeItems->selectedItems().length() != 1)
1740 auto Item =
ui->treeItems->selectedItems()[0];
1743 std::string ErrorMessage =
"";
1744 std::string ObjectName =
"< Unknown >";
1772 if (QMessageBox::question(
this,
"DynExp - Stop item?",
1773 QString::fromStdString(
"The item " + ObjectName +
" is currently running. Should it be stopped in order to be deleted?"),
1774 QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::No)
1775 != QMessageBox::StandardButton::Yes)
1795 ErrorMessage = e.what();
1797 catch (
const std::exception& e)
1799 ErrorMessage = e.what();
1803 ErrorMessage =
"Unknown Error";
1808 if (!ErrorMessage.empty())
1810 QMessageBox::warning(
this,
"DynExp - Error",
1811 QString::fromStdString(
1812 "Deleting the item " + ObjectName +
", the following error occurred:\n\n"
1830 ui->action_Dock_Undock_Window->setEnabled(
true);
1838 QModule->DockUndockWindow();
1878 std::string ErrorMessage =
"";
1882 ui->tableLog->setRowCount(0);
1887 ErrorMessage = e.what();
1889 catch (
const std::exception& e)
1891 ErrorMessage = e.what();
1895 ErrorMessage =
"Unknown Error";
1898 if (!ErrorMessage.empty())
1900 QMessageBox::warning(
this,
"DynExp - Error",
1901 QString::fromStdString(
1902 "Clearing the event log, the following error occurred:\n\n"
1910 if (
ui->treeItems->selectedItems().length() != 1)
1913 auto Item =
ui->treeItems->selectedItems()[0];
1929 Object->ClearWarning();
1957 if (
ui->treeItems->selectedItems().length() != 1)
1963 auto Item =
ui->treeItems->selectedItems()[0];
1968 ui->action_Reset_Item->setEnabled(
true);
1969 ui->action_Configure_Item->setEnabled(
true);
1970 ui->action_Delete_Item->setEnabled(
true);
1977 ui->action_Run_Item->setEnabled(
false);
1978 ui->action_Stop_Item->setEnabled(
false);
1979 ui->action_Force_Stop_Item->setEnabled(
false);
1988 bool IsRunning =
false;
2001 ui->action_Run_Item->setEnabled(!IsRunning);
2002 ui->action_Stop_Item->setEnabled(IsRunning);
2003 ui->action_Force_Stop_Item->setEnabled(IsRunning);
2025 ui->treeItems->clearSelection();
Implements DynExp's main UI window called DynExpManager.
Implements DynExp's main window as a Qt-based user interface (UI).
void SelectItemTreeItem(QTreeWidgetItem *SelectedEntry)
Selects the given QTreeWidgetItem instance and brings this DynExpManager window to the front.
DynExpAbout * AboutDialog
Dialog showing license and copyright information.
void ChangeItemTreeItemToRunningState(QTreeWidgetItem &ItemTreeItem, const ItemTreeItemDataType &ItemTreeItemData, const QString &Description)
void OnProjectSettingsClicked()
QColor HTMLColorStringToThemeColor(const std::string &HTMLColor) const
Constructs a QColor instance from an HTML color string depending on the currently active UI theme.
void Reset(bool Force=false)
Resets the currently loaded project removing all resources from the resource managers....
void UpdateCircuitDiagram()
void OnAddHardwareAdapter()
void OnStatusBarStateClicked()
void OnWindowMenuClosed()
void OnItemDoubleClicked(QTreeWidgetItem *Item, int Column)
QMenu * ItemTreeContextMenu
Context menu appearing when right-clicking on the main tree widget showing DynExp::Object instances.
ErrorListDialog * ErrorListDlg
Dialog showing the list of currently active warnings and errors (ErrorEntries)
void MakeItem(QAction *SenderAction, LibraryVectorT &Lib, ManagerT &ResourceManager)
Creates a DynExp::Object instance according to a QAction instance SenderAction, which contains the in...
DynExp::DynExpCore & DynExpCore
Handle to DynExp's internal data.
QTreeWidgetItem * ItemTreeHardwareAdapters
Item for the hardware adapters section within the main tree widget showing DynExp::Object instances.
QColor AdjustColorToThemeColor(const QColor &Color) const
Transforms a QColor instance depending on the currently active UI theme.
void OnResetFailedItems()
void OnItemSelectionChanged()
bool Shutdown() noexcept
Terminates DynExpCore::WorkerThread and waits until the thread has ended.
static std::string GetObjectNameSafe(DynExp::Object *Object)
Retrieves the name of a DynExp::Object instance from its parameter class instance.
void OnWindowMenuOpened()
void OnStopItem(bool Force=false)
void ChangeItemTreeItemToNotRespondingState(QTreeWidgetItem &ItemTreeItem, const ItemTreeItemDataType &ItemTreeItemData, const QString &Description)
void OnDockUndockWindow()
void ResetItem(DynExp::Object *Object)
Calls DynExp::Object::Reset() on a DynExp::Object instance.
void OnRestoreWindowStatesFromParams()
void RegisterItemsFromLibrary(const LibraryVectorT &Lib, QMenu *const MenuBase, const QString IconPath, void(DynExpManager::*Slot)())
Adds the library entries from Lib to submenus below MenuBase and assigns actions to them invoking Slo...
void UpdateModuleWindowsActionShortcuts() noexcept
Establishes shortcuts to switch between module windows. Refer to ModuleWindowsActionGroup.
QTreeWidgetItem * ItemTreeModules
Item for the modules section within the main tree widget showing DynExp::Object instances.
virtual void closeEvent(QCloseEvent *event) override
bool UpdateItemConfig(DynExp::Object *Object, LibraryVectorT &Lib, ManagerT &ResourceManager)
Invokes a configuration dialog to let the user adjust the parameters of a DynExp::Object instance.
void OnLogContextMenuRequested(const QPoint &Position)
void ChangeItemTreeItemToNotConnectedState(QTreeWidgetItem &ItemTreeItem, const ItemTreeItemDataType &ItemTreeItemData, const QString &Description)
void OnModuleWindowActivated(QMdiSubWindow *Window)
void PostKeyPressEvent(QKeyEvent *Event) noexcept
Delegates a Qt key press event (e.g. the key sequences Ctrl+1 - Ctrl+9) from module widgets to the ma...
void FocusMainWindow() noexcept
Focuses/activates DynExp's main window and moves it on top of other windows if possible.
void DisableAllActions() noexcept
Disables all user interface actions such that item-specific ones can be reenabled upon a selection ch...
void OnShowCircuitDiagram()
struct DynExpManager::StatusBarType StatusBar
DynExp::QModuleBase * GetModuleByActiveUIWindow() noexcept
Determines the DynExp::QModuleBase instance of the current project whose UI window is active (has the...
void UpdateItemTreeItemObjectName(QTreeWidgetItem *Item, const DynExp::Object *Object)
Updates the text of a QTreeWidgetItem instance to match it to the related DynExp::Object instance.
QMenu * LogContextMenu
Context menu appearing when right-clicking on the message log widget.
std::unique_ptr< Ui::DynExpManagerClass > ui
Qt widgets belonging to the main window's user interface.
void UpdateModuleWindowsActionIcons() noexcept
Invokes DynExp::QModuleBase::UpdateModuleWindowFocusAction() on each module.
QActionGroup * UIThemeActionGroup
Actions to switch in between different UI themes.
std::unique_ptr< CircuitDiagram > CircuitDiagramDlg
Dialog showing the circuit diagram of the current project. It has no parent to not stay on top of the...
bool IsResetting
Indicates whether DynExpManager is currently deleting all resources to empty the project.
QActionGroup * ModuleWindowsActionGroup
Actions to switch between module windows with CTRL + < number key > shortcuts.
QAction * UIBrightThemeAction
Action for a bright UI theme.
void ChangeItemTreeItemToPausedState(QTreeWidgetItem &ItemTreeItem, const ItemTreeItemDataType &ItemTreeItemData, const QString &Description)
QTreeWidgetItem * ItemTreeInstruments
Item for the instruments section within the main tree widget showing DynExp::Object instances.
void UpdateModulesUI() noexcept
void OnUIThemeChanged(QAction *ThemeAction)
void UpdateItemTreeItem(const DynExp::HardwareAdapterManager::ResourceType &Resource)
void RegisterModuleUI(DynExp::Object *const Object)
Initializes the UI of the module Object (expecting that Object is a DynExp::QModuleBase instance....
void SaveProject(std::string_view Filename) noexcept
Saves the current DynExp project to an XML project file.
QAction * ClearWarningAction
Action to clear the warning of an item within the main tree widget showing DynExp::Object instances.
QTreeWidgetItem * UpdateItemTreeSection(QTreeWidgetItem *Section, ManagerT &ResourceManager)
Loops through resources managed by ResourceManager and adds respective QTreeWidgetItem instances as c...
void ChangeItemTreeItemToErrorState(QTreeWidgetItem &ItemTreeItem, const ItemTreeItemDataType &ItemTreeItemData, const std::exception_ptr &ExceptionPtr)
bool StopItem(DynExp::RunnableObject *Object, bool Force=false) noexcept
Calls DynExp::RunnableObject::Terminate() on a DynExp::RunnableObject instance.
void ChangeItemTreeItemToNormalState(QTreeWidgetItem &ItemTreeItem, const ItemTreeItemDataType &ItemTreeItemData, const QString &Description, const QString &StateTitle, const char *IconPath=DynExpUI::Icons::Stopped)
bool ShouldRedrawCircuitDiagram
Indicates whether the circuit diagram has to be rebuilt. Particularly, this must be set to true direc...
void EnsureItemReadyState(DynExp::Object *Object)
Calls DynExp::Object::EnsureReadyState() on a DynExp::Object instance.
void OnItemTreeContextMenuRequested(const QPoint &Position)
void ChangeItemTreeItemToWarningState(QTreeWidgetItem &ItemTreeItem, const ItemTreeItemDataType &ItemTreeItemData, const QString &Description)
ErrorListDialog::ErrorEntriesType ErrorEntries
List of all currently active warnings and errors.
bool CloseProject() noexcept
Closes the current project and opens a new, empty one.
DynExpManager(DynExp::DynExpCore &DynExpCore, QWidget *parent=Q_NULLPTR)
Constructs a DynExpManager instance.
bool ShouldUpdateCircuitDiagram
Indicates whether any item state has changed. Set to true to update the circuit diagram....
QAction * UIDarkThemeAction
Action for a dark UI theme.
QTimer * UpdateUITimer
Timer for periodically updating the user interface.
DynExp's core class acts as the interface between the user interface and DynExp's internal data like ...
void SaveProject(std::string_view Filename, const QMainWindow &MainWindow, const QDialog &CircuitDiagramDlg, QSplitter &HSplitter, QSplitter &VSplitter)
Saves the current DynExp project to an XML project file.
auto & GetHardwareAdapterLib() const noexcept
Getter for the hardware adapter library.
auto ConnectHardwareAdapters(CommonResourceManagerBase::FunctionToCallWhenObjectStartedType FunctionToCallWhenHardwareAdapterConnecting=nullptr)
Connects all hardware adapters contained in HardwareAdapterMgr asynchronously calling ResourceManager...
void ShutdownProject()
Terminates all running instruments and modules.
bool AllInstrumentsInitialized() const
Checks whether all instruments contained in InstrumentMgr have been initialized successfully.
auto & GetInstrumentLib() const noexcept
Getter for the instrument library.
void OpenProject(std::string_view Filename)
Loads a DynExp project from an XML project file.
auto & GetInstrumentManager() noexcept
Getter for the instrument manager.
bool IsProjectOpened(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const noexcept
Locks Params and determines whether a project has been openend from a project file.
auto & GetModuleManager() noexcept
Getter for the module manager.
void EditProjectSettings(QWidget *const DialogParent)
Opens a settings dialog (ParamsConfigDialog) to let the user configure the parameter values of the cu...
void RestoreWindowStatesFromParams(QMainWindow &MainWindow, QDialog &CircuitDiagramDlg, QSplitter &HSplitter, QSplitter &VSplitter, bool OnlyMainWindow=false)
Sets module and main windows' positions, sizes and styles according to parameters stored in the curre...
void Reset(bool Force=false)
Resets the currently loaded project removing all resources from the resource managers....
bool HasLoadedProjectFromCommandlineParams() noexcept
Indicates whether a DynExp project has been loaded from a path specified as a command line argument w...
auto & GetHardwareAdapterManager() noexcept
Getter for the hardware adapter manager.
auto GetProjectFilename(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Locks Params and returns the current DynExp project's filename.
void RunModules(CommonResourceManagerBase::FunctionToCallWhenObjectStartedType FunctionToCallWhenModuleStarted=nullptr)
Runs all modules contained in ModuleMgr with RunnableObjectParams::StartupType::OnCreation startup se...
void RunInstruments(CommonResourceManagerBase::FunctionToCallWhenObjectStartedType FunctionToCallWhenInstrumentStarted=nullptr)
Runs all instruments contained in InstrumentMgr with RunnableObjectParams::StartupType::OnCreation st...
bool AllHardwareAdaptersConnected() const
Checks whether all hardware adapters contained in HardwareAdapterMgr have been connected successfully...
void ResetFailedItems(QWidget &ParentWindow)
Calls Object::Reset() and Object::ClearWarning() on all owned DynExp::Object instances which are in a...
void Shutdown()
Terminates DynExpCore::WorkerThread and waits until the thread has ended.
auto & GetModuleLib() const noexcept
Getter for the module library.
Base class for all DynExp Objects like hardware adapters (DynExp::HardwareAdapterBase),...
void Reset()
Resets this Object instance (including all its derived classes) by calling ResetImpl()....
void EnsureReadyState(bool IsAutomaticStartup)
Ensures that this Object instance is ready by possibly starting its worker thread or by opening conne...
auto GetObjectName(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Returns the name of this Object instance.
@ ApplyStoredWindowStates
Base class for modules with a Qt-based user interface. Derive from this class to implement modules wi...
void HideUI()
Removes MdiSubWindow, DockWidget, and ModuleWindowFocusAction setting them to nullptr.
void UpdateModuleWindowFocusAction()
Updates the icon assigned to ModuleWindowFocusAction depending on whether Widget is docked to or undo...
Exception type thrown by TerminateImpl() if the RunnableObject cannot be terminated for being used by...
std::string_view GetUserNames() const
Getter for UserNames.
std::string GetErrorMessage() const
Genereates a user-readable error message containing the content of UserNames.
Defines an Object which possesses a thread it runs in. The RunnableObject can be started and stopped ...
bool Run(QWidget *ParentWidget=nullptr)
Starts the RunnableObject instance's thread and ensures that all Object instances linked to this inst...
bool IsRunning() const noexcept
Returns Running.
void Terminate(bool Force=false, const std::chrono::milliseconds Timeout=TerminateTimeoutDefault)
Notifies the RunnableObject instance's thread to terminate and waits until it has ended....
QTreeWidgetItem * GetSelectedEntry()
void SetErrorEntries(const ErrorEntriesType &ErrorEntries)
void ResetClosedByClickingOpenWidget() noexcept
bool HasBeenClosedByClickingOpenWidget() const noexcept
void Log(const std::string &Message, const ErrorType Type=ErrorType::Info, const size_t Line=0, const std::string &Function="", const std::string &File="", const int ErrorCode=0, const std::stacktrace &Trace={}) noexcept
Logs an event from information specified manually.
auto GetLogSize() const
Determines the number of entries in the internal event log.
void ClearLog()
Clears the internal event log.
std::vector< LogEntry > GetLog(size_t FirstElement=0) const
Returns the internal event log starting from the n-th stored element.
DynExp exceptions are derived from this class. It contains basic information about the cause of the e...
constexpr const char * GetErrorLabelColor() const
const ErrorType Type
DynExp error type from Util::ErrorType
constexpr const char * GetErrorLabel() const
An invalid argument like a null pointer has been passed to a function.
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
const QColor green("lime")
constexpr auto GetStyleSheet()
const QColor blue(42, 130, 218)
constexpr auto Instrument
constexpr auto HardwareAdapter
constexpr auto NotResponding
static const auto PushButtonReadyStyleSheetBright
static const auto PushButtonRunningStyleSheet
static const auto PushButtonErrorStyleSheet
static const auto PushButtonReadyStyleSheetDark
static const auto PushButtonWarningStyleSheet
std::string ToStr(const T &Value, int Precision=-1)
Converts a (numeric) value of type T to a std::string using operator<< of std::stringstream.
std::string ExceptionToStr(const std::exception_ptr ExceptionPtr)
Returns the what() information of an exception derived from std::exception and stored in an exception...
EventLogger & EventLog()
This function holds a static EventLogger instance and returns a reference to it. DynExp uses only one...
QString PromptOpenFilePath(QWidget *Parent, const QString &Title, const QString &DefaultSuffix, const QString &NameFilter, const QString &InitialDirectory)
Opens a file dialog to ask the user to select a single existing file.
void ActivateWindow(QWidget &Widget)
Renders a window active and brings it to the front.
QString PromptSaveFilePath(QWidget *Parent, const QString &Title, const QString &DefaultSuffix, const QString &NameFilter, const QString &InitialDirectory)
Works as PromptOpenFilePath() but asks the user to select a single file which does not need to exist.
Accumulates include statements to provide a precompiled header.
Bundles data which is assigned to items of the main QTreeWidget. Each item refers to a DynExp::Object...
const DynExp::ItemIDType ID
ID of the DynExp::Object instance assigned to this item.
QLabel * NumRunningModule
QWidget * NumRunningInstrGroup
StatusBarType(DynExpManager *Owner)
Constructs a StatusBarType instance.
QHBoxLayout * NumRunningInstrLayout
QHBoxLayout * NumRunningModuleLayout
QLabel * NumRunningInstrImage
size_t NumItemsInErrorState
QWidget * NumRunningModuleGroup
QLabel * NumRunningModuleImage
size_t NumItemsInWarningState
Defines a DynExp resource, which mainly owns a DynExp::Object instance wrapping a pointer to it.
std::unique_ptr< QTreeWidgetItem > TreeWidgetItem
For visualization of the resource and its state in DynExp's main window (DynExpManager)....
PointerType ResourcePointer
Pointer to the DynExp::Object instance owned by this resource.