21 #include <QApplication>  22 #include <QDesktopServices>  24 #include <QFileDialog>  26 #include <QMessageBox>  44 #include "rtxiConfig.h"  51  : QMainWindow(nullptr, Qt::Window)
  52  , event_manager(ev_manager)
  53  , mdiArea(new QMdiArea)
  56  setCentralWidget(mdiArea);
  59  setWindowTitle(
"RTXI - Real-time eXperimental Interface");
  60  setWindowIcon(QIcon(
"/usr/share/rtxi/RTXI-icon.png"));
  63  QApplication::setOrganizationName(
"RTXI");
  64  QApplication::setOrganizationDomain(
"rtxi.org");
  65  QApplication::setApplicationName(
"RTXI");
  78  createSystemActions();
  91  return moduleMenu->addSeparator();
  96  return fileMenu->addAction(label);
  103  fileMenu->addAction(load);
  104  fileMenu->addAction(save);
  105  fileMenu->addAction(reset);
  106  fileMenu->addSeparator();
  107  fileMenu->addAction(quit);
  108  fileMenu->addSeparator();
  113  return moduleMenu->addAction(text);
  117  const QObject* receiver,
  120  return moduleMenu->addAction(text, receiver, member);
  125  action->setData(parameter);
  135  action->setText(text);
  140  const QList<QAction*> actionList = moduleMenu->actions();
  141  if (!actionList.empty()) {
  142  moduleMenu->removeAction(action);
  147  const QObject* handler,
  150  return utilMenu->addAction(label, handler, slot);
  153 void MainWindow::createFileMenu()
  155  fileMenu = menuBar()->addMenu(tr(
"&File"));
  156  fileMenu->addAction(load);
  157  fileMenu->addAction(save);
  158  fileMenu->addAction(reset);
  159  fileMenu->addSeparator();
  160  fileMenu->addAction(quit);
  161  fileMenu->addSeparator();
  163  SIGNAL(triggered(QAction*)),
  165  SLOT(fileMenuActivated(QAction*)));
  168 void MainWindow::createWidgetMenu()
  170  moduleMenu = menuBar()->addMenu(tr(
"&Widgets"));
  171  this->loadDynamicWidget = 
new QAction(
"Load Plugin", 
this);
  172  moduleMenu->addAction(this->loadDynamicWidget);
  174  SIGNAL(triggered(QAction*)),
  176  SLOT(modulesMenuActivated(QAction*)));
  179 void MainWindow::createUtilMenu()
  181  utilMenu = menuBar()->addMenu(tr(
"&Utilities"));
  182  filtersSubMenu = utilMenu->addMenu(tr(
"&Filters"));
  183  signalsSubMenu = utilMenu->addMenu(tr(
"&Signals"));
  184  utilitiesSubMenu = utilMenu->addMenu(tr(
"&Utilities"));
  186  SIGNAL(triggered(QAction*)),
  188  SLOT(utilitiesMenuActivated(QAction*)));
  190  QDir libsDir = QCoreApplication::applicationDirPath() + QDir::separator()
  191  + QString(
"rtxi_modules");
  192  if (!libsDir.exists()) {
  195  libsDir.setNameFilters(QStringList(
"*.so"));
  196  for (
const auto& entryItem : libsDir.entryList()) {
  197  utilItem = 
new QAction(entryItem, 
this);
  198  if (entryItem.contains(
"analysis") || entryItem.contains(
"sync")
  199  || entryItem.contains(
"mimic"))
  201  utilitiesSubMenu->addAction(utilItem);
  202  } 
else if (entryItem.contains(
"iir") || entryItem.contains(
"fir")) {
  203  filtersSubMenu->addAction(utilItem);
  204  } 
else if (entryItem.contains(
"signal") || entryItem.contains(
"noise")
  205  || entryItem.contains(
"ttl") || entryItem.contains(
"maker"))
  207  signalsSubMenu->addAction(utilItem);
  214 void MainWindow::createSystemMenu()
  216  this->systemMenu = menuBar()->addMenu(tr(
"&System"));
  217  this->systemMenu->addAction(this->openRTBenchmarks);
  218  this->systemMenu->addAction(this->openUserPrefs);
  219  this->systemMenu->addAction(this->openControlPanel);
  220  this->systemMenu->addAction(this->openConnector);
  221  this->systemMenu->addAction(this->openOscilloscope);
  222  this->systemMenu->addAction(this->openDataRecorder);
  223  this->systemMenu->addAction(this->openRTXIWizard);
  225  SIGNAL(triggered(QAction*)),
  227  SLOT(systemMenuActivated(QAction*)));
  230 void MainWindow::createWindowsMenu()
  232  windowsMenu = menuBar()->addMenu(tr(
"&Windows"));
  234  windowsMenu, SIGNAL(aboutToShow()), 
this, SLOT(windowsMenuAboutToShow()));
  237 void MainWindow::createHelpMenu()
  239  this->helpMenu = menuBar()->addMenu(tr(
"&Help"));
  240  this->helpMenu->addSeparator();
  241  this->helpMenu->addAction(artxi);
  242  this->helpMenu->addAction(axeno);
  243  this->helpMenu->addAction(aqt);
  244  this->helpMenu->addSeparator();
  245  this->helpMenu->addAction(adocs);
  246  this->helpMenu->addAction(sub_issue);
  249 void MainWindow::createFileActions()
  251  this->load = 
new QAction(tr(
"&Load Workspace"), 
this);
  252  this->load->setShortcuts(QKeySequence::Open);
  253  this->load->setStatusTip(tr(
"Load a saved workspace"));
  254  connect(load, SIGNAL(triggered()), 
this, SLOT(loadSettings()));
  256  this->save = 
new QAction(tr(
"&Save Workspace"), 
this);
  257  this->save->setShortcuts(QKeySequence::Save);
  258  this->save->setStatusTip(tr(
"Save current workspace"));
  259  connect(save, SIGNAL(triggered()), 
this, SLOT(saveSettings()));
  261  this->reset = 
new QAction(tr(
"&Reset Workspace"), 
this);
  262  this->reset->setStatusTip(tr(
"Reset to default RTXI workspace"));
  263  connect(reset, SIGNAL(triggered()), 
this, SLOT(resetSettings()));
  265  this->quit = 
new QAction(tr(
"&Quit"), 
this);
  266  this->quit->setShortcut(tr(
"Ctrl+Q"));
  267  this->quit->setStatusTip(tr(
"Quit RTXI"));
  268  connect(QCoreApplication::instance(),
  269  SIGNAL(aboutToQuit()),
  271  SLOT(closeAllSubWindows()));
  272  connect(quit, SIGNAL(triggered()), 
this, SLOT(close()));
  280 void MainWindow::createHelpActions()
  282  artxi = 
new QAction(tr(
"About &RTXI"), 
this);
  283  connect(artxi, SIGNAL(triggered()), 
this, SLOT(about()));
  285  axeno = 
new QAction(tr(
"About &Xenomai"), 
this);
  286  connect(axeno, SIGNAL(triggered()), 
this, SLOT(aboutXeno()));
  288  aqt = 
new QAction(tr(
"About &Qt"), 
this);
  289  connect(aqt, SIGNAL(triggered()), 
this, SLOT(aboutQt()));
  291  adocs = 
new QAction(tr(
"&Documentation"), 
this);
  292  connect(adocs, SIGNAL(triggered()), 
this, SLOT(openDocs()));
  294  sub_issue = 
new QAction(tr(
"&Submit Issue"), 
this);
  295  connect(sub_issue, SIGNAL(triggered()), 
this, SLOT(openSubIssue()));
  298 void MainWindow::createSystemActions()
  300  this->openRTBenchmarks = 
new QAction(
  302  this->openUserPrefs =
  304  this->openControlPanel =
  306  this->openConnector =
  308  this->openOscilloscope =
  310  this->openDataRecorder =
  312  this->openRTXIWizard =
  316 void MainWindow::about()
  318  const std::string version_str = fmt::format(
  319  "{}.{}.{}", RTXI_VERSION_MAJOR, RTXI_VERSION_MINOR, RTXI_VERSION_PATCH);
  323  QString(
"RTXI Version ") + QString(version_str.c_str())
  325  "\n\nReleased under the GPLv3.\nSee www.rtxi.org for details."));
  328 void MainWindow::aboutQt()
  330  QMessageBox::aboutQt(
this);
  333 void MainWindow::aboutXeno()
  336  this, 
"About Xenomai", 
"Running POSIX (non-RT) real-time core");
  339 void MainWindow::openDocs()
  341  QDesktopServices::openUrl(QUrl(
"http://rtxi.org/docs/", QUrl::TolerantMode));
  344 void MainWindow::openSubIssue()
  346  QDesktopServices::openUrl(
  347  QUrl(
"https://github.com/rtxi/rtxi/issues", QUrl::TolerantMode));
  356  userprefs.beginGroup(
"MainWindow");
  357  restoreGeometry(userprefs.value(
"geometry", saveGeometry()).toByteArray());
  358  move(userprefs.value(
"pos", pos()).toPoint());
  359  resize(userprefs.value(
"size", size()).toSize());
  360  if (userprefs.value(
"maximized", isMaximized()).toBool()) {
  363  userprefs.endGroup();
  367 void MainWindow::loadSettings()
  369  const QSettings userprefs;
  370  const QString env_var = QString::fromLocal8Bit(qgetenv(
"HOME"));
  372  const QString filename = QFileDialog::getOpenFileName(
  374  tr(
"Load saved workspace"),
  375  userprefs.value(
"/dirs/setfiles", env_var).toString(),
  376  tr(
"Settings (*.set)"));
  378  if (QFile(filename).exists()) {
  380  mdiArea->closeAllSubWindows();
  384 void MainWindow::saveSettings()
  387  userprefs.beginGroup(
"Workspaces");
  388  auto* save_settings_dialog = 
new QInputDialog(
this);
  389  save_settings_dialog->setInputMode(QInputDialog::TextInput);
  390  save_settings_dialog->setComboBoxEditable(
true);
  391  save_settings_dialog->setComboBoxItems(userprefs.childGroups());
  392  save_settings_dialog->setLabelText(
"Profile");
  393  save_settings_dialog->setOkButtonText(
"Save");
  394  userprefs.endGroup();
  395  save_settings_dialog->exec();
  398 void MainWindow::resetSettings()
  405 void MainWindow::utilitiesMenuActivated(QAction* 
id)
  407  this->loadWidget(QCoreApplication::applicationDirPath() + QDir::separator()
  408  + QString(
"rtxi_modules") + QDir::separator() + id->text());
  411 void MainWindow::loadWidget(
const QString& module_name)
  414  event.setParam(
"pluginName", std::any(module_name.toStdString()));
  418  auto status = std::any_cast<std::string>(event.getParam(
"status"));
  419  if (status == 
"failure") {
  423  auto create_rtxi_panel_func =
  424  std::any_cast<Widgets::Panel* (*)(QMainWindow*, Event::Manager*)>(
  425  event.getParam(
"createRTXIPanel"));
  426  auto* rtxi_plugin_pointer =
  427  std::any_cast<Widgets::Plugin*>(event.getParam(
"pluginPointer"));
  428  auto* rtxi_panel_pointer = create_rtxi_panel_func(
this, this->event_manager);
  429  rtxi_plugin_pointer->attachPanel(rtxi_panel_pointer);
  434  rtxi_panel_pointer->show();
  437 void MainWindow::systemMenuActivated(QAction* 
id)
  439  this->loadWidget(id->text());
  442 void MainWindow::windowsMenuAboutToShow()
  445  windowsMenu->clear();
  448  windowsMenu->addAction(tr(
"Cascade"), mdiArea, SLOT(cascadeSubWindows()));
  449  windowsMenu->addAction(tr(
"Tile"), mdiArea, SLOT(tileSubWindows()));
  450  windowsMenu->addSeparator();
  453  subWindows = mdiArea->subWindowList();
  456  if (subWindows.isEmpty()) {
  460  for (
auto* subwin : subWindows) {
  462  windowsMenu->addAction(
new QAction(subwin->widget()->windowTitle(), 
this));
  465  SIGNAL(triggered(QAction*)),
  467  SLOT(windowsMenuActivated(QAction*)));
  470 void MainWindow::windowsMenuActivated(QAction* 
id)
  473  subWindows = mdiArea->subWindowList();
  476  if (subWindows.isEmpty()) {
  479  for (QMdiSubWindow* subwindow : this->subWindows) {
  480  if (subwindow->widget()->windowTitle() == id->text()) {
  481  mdiArea->setActiveSubWindow(subwindow);
  486 void MainWindow::modulesMenuActivated(QAction* )
  488  const QString filename = QFileDialog::getOpenFileName(
  491  QCoreApplication::applicationDirPath() + QDir::separator()
  492  + QString(
"rtxi_modules"),
  493  tr(
"Plugins (*.so);;All (*.*)"));
  494  if (!filename.isNull()) {
  495  this->loadWidget(filename);
  499 void MainWindow::fileMenuActivated(QAction* 
id)
  503  if (id->text().contains(
"Load Workspace")
  504  || id->text().contains(
"Save Workspace")
  505  || id->text().contains(
"Reset Workspace") || id->text().contains(
"Quit"))
  513  mdiArea->closeAllSubWindows();
  518 void MainWindow::closeEvent(QCloseEvent* )
  524  userprefs.beginGroup(
"MainWindow");
  525  userprefs.setValue(
"geometry", saveGeometry());
  526  userprefs.setValue(
"maximized", isMaximized());
  527  if (!isMaximized()) {
  528  userprefs.setValue(
"pos", pos());
  529  userprefs.setValue(
"size", size());
  531  userprefs.endGroup();
 void registerHandler(Handler *handler)
void postEvent(Object *event)
static void changeWidgetMenuItem(QAction *action, const QString &text)
QAction * insertWidgetMenuSeparator()
void removeWidgetMenuItem(QAction *action)
QAction * createFileMenuItem(const QString &label)
MainWindow(Event::Manager *ev_manager)
static void setWidgetMenuItemParameter(QAction *action, int parameter)
QAction * createUtilMenuItem(const QString &label, const QObject *handler, const char *slot)
QAction * createWidgetMenuItem(const QString &text)
constexpr std::string_view MODULE_NAME
constexpr std::string_view MODULE_NAME
constexpr std::string_view MODULE_NAME
constexpr std::string_view MODULE_NAME
constexpr std::string_view MODULE_NAME
constexpr std::string_view MODULE_NAME