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