RTXI  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
main_window.cpp
Go to the documentation of this file.
1 /*
2  The Real-Time eXperiment Interface (RTXI)
3  Copyright (C) 2011 Georgia Institute of Technology, University of Utah, Weill Cornell Medical College
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 
20 #include <cmdline.h>
21 #include <debug.h>
22 #include <algorithm>
23 #include <settings.h>
24 #include <rtxi_config.h>
25 #include <stdlib.h>
26 #include <main_window.h>
27 #include <mutex.h>
28 #include <plugin.h>
29 
30 MainWindow::MainWindow (void) : QMainWindow(NULL, Qt::Window)
31 {
32 
33  // Make central RTXI parent widget
34  mdiArea = new QMdiArea;
35  setCentralWidget(mdiArea);
36 
37  /* Initialize Window Settings */
38  setWindowTitle("RTXI - Real-time eXperimental Interface");
39  setWindowIcon(QIcon("/usr/local/share/rtxi/RTXI-icon.png"));
40 
41  /* Set Qt Settings Information */
42  QCoreApplication::setOrganizationName("RTXI");
43  QCoreApplication::setOrganizationDomain("rtxi.org");
44  QCoreApplication::setApplicationName("RTXI");
45 
46  /* Initialize Menus */
49 
50  /* Initialize Module Menu */
52 
53  /* Initialize Utilities menu */
55 
56  /* Initialize System Menu */
58 
59  /* Initialize Windows Menu */
61 
62  /* Initialize Help Menu */
65 
66  /* Check for updates */
67  //updateCheck();
68 }
69 
71 {
72 }
73 
75 {
76  return moduleMenu->addSeparator();
77 }
78 
79 QAction* MainWindow::createFileMenuItem(const QString &text)
80 {
81  return fileMenu->addAction(text);
82 }
83 
85 {
86  // Clear but add back default actions
87  fileMenu->clear();
88  fileMenu->addAction(load);
89  fileMenu->addAction(save);
90  fileMenu->addAction(reset);
91  fileMenu->addSeparator();
92  fileMenu->addAction(quit);
93  fileMenu->addSeparator();
94 }
95 
96 QAction* MainWindow::createModuleMenuItem(const QString &text)
97 {
98  return moduleMenu->addAction(text);
99 }
100 
101 QAction* MainWindow::createModuleMenuItem(const QString &text, const QObject *receiver, const char *member)
102 {
103  return moduleMenu->addAction(text, receiver, member);
104 }
105 
106 void MainWindow::setModuleMenuItemParameter (QAction *action, int parameter)
107 {
108  action->setData(parameter);
109 }
110 
112 {
113  moduleMenu->clear();
114 }
115 
116 void MainWindow::changeModuleMenuItem (QAction *action, QString text)
117 {
118  action->setText(text);
119 }
120 
121 void MainWindow::removeModuleMenuItem (QAction *action)
122 {
123  QList<QAction *> actionList = moduleMenu->actions();
124  if(!actionList.empty())
125  moduleMenu->removeAction(action);
126 }
127 
128 QAction* MainWindow::createUtilMenuItem(const QString &text, const QObject * receiver, const char *member)
129 {
130  return utilMenu->addAction (text, receiver, member);
131 }
132 
134 {
135  fileMenu = menuBar()->addMenu(tr("&File"));
136  fileMenu->addAction(load);
137  fileMenu->addAction(save);
138  fileMenu->addAction(reset);
139  fileMenu->addSeparator();
140  fileMenu->addAction(quit);
141  fileMenu->addSeparator();
142  connect(fileMenu, SIGNAL(triggered(QAction*)), this, SLOT(fileMenuActivated(QAction*)));
143 }
144 
146 {
147  moduleMenu = menuBar()->addMenu(tr("&Modules"));
148  connect(moduleMenu, SIGNAL(triggered(QAction*)), this, SLOT(modulesMenuActivated(QAction*)));
149 }
150 
152 {
153  utilMenu = menuBar()->addMenu(tr("&Utilities"));
154  filtersSubMenu = utilMenu->addMenu(tr("&Filters"));
155  signalsSubMenu = utilMenu->addMenu(tr("&Signals"));
156  utilitiesSubMenu = utilMenu->addMenu(tr("&Utilities"));
157  connect(utilMenu, SIGNAL(triggered(QAction*)), this, SLOT(utilitiesMenuActivated(QAction*)));
158 
159  QDir libsDir("/usr/local/lib/rtxi/");
160  if(!libsDir.exists())
161  return;
162 
163  libsDir.setNameFilters(QStringList("*.so"));
164  for(size_t i = 0; i < libsDir.entryList().size(); i++)
165  {
166  utilItem = new QAction(libsDir.entryList().at(i), this);
167  if(libsDir.entryList().at(i).contains("analysis"))
168  utilitiesSubMenu->addAction(utilItem);
169  else if(libsDir.entryList().at(i).contains("sync"))
170  utilitiesSubMenu->addAction(utilItem);
171  else if(libsDir.entryList().at(i).contains("mimic"))
172  utilitiesSubMenu->addAction(utilItem);
173  else if(libsDir.entryList().at(i).contains("iir"))
174  filtersSubMenu->addAction(utilItem);
175  else if(libsDir.entryList().at(i).contains("fir"))
176  filtersSubMenu->addAction(utilItem);
177  else if(libsDir.entryList().at(i).contains("signal"))
178  signalsSubMenu->addAction(utilItem);
179  else if(libsDir.entryList().at(i).contains("noise"))
180  signalsSubMenu->addAction(utilItem);
181  else if(libsDir.entryList().at(i).contains("ttl"))
182  signalsSubMenu->addAction(utilItem);
183  else if(libsDir.entryList().at(i).contains("maker"))
184  signalsSubMenu->addAction(utilItem);
185  }
186 }
187 
189 {
190  systemMenu = menuBar()->addMenu(tr("&System"));
191 }
192 
194 {
195  windowsMenu = menuBar()->addMenu(tr("&Windows"));
196  connect(windowsMenu,SIGNAL(aboutToShow(void)),this,SLOT(windowsMenuAboutToShow(void)));
197 }
198 
200 {
201  helpMenu = menuBar()->addMenu(tr("&Help"));
202  helpMenu->addSeparator();
203  helpMenu->addAction(artxi);
204  helpMenu->addAction(axeno);
205  helpMenu->addAction(aqt);
206  helpMenu->addSeparator();
207  helpMenu->addAction(adocs);
208  helpMenu->addAction(sub_issue);
209 }
210 
212 {
213  load = new QAction(tr("&Load Workspace"), this);
214  load->setShortcuts(QKeySequence::Open);
215  load->setStatusTip(tr("Load a saved workspace"));
216  connect(load, SIGNAL(triggered()), this, SLOT(loadSettings()));
217 
218  save = new QAction(tr("&Save Workspace"), this);
219  save->setShortcuts(QKeySequence::Save);
220  save->setStatusTip(tr("Save current workspace"));
221  connect(save, SIGNAL(triggered()), this, SLOT(saveSettings()));
222 
223  reset = new QAction(tr("&Reset Workspace"), this);
224  reset->setStatusTip(tr("Reset to default RTXI workspace"));
225  connect(reset, SIGNAL(triggered()), this, SLOT(resetSettings()));
226 
227  quit = new QAction(tr("&Quit"), this);
228  quit->setShortcut(tr("Ctrl+Q"));
229  quit->setStatusTip(tr("Quit RTXI"));
230  connect(qApp, SIGNAL(aboutToQuit()), mdiArea, SLOT(closeAllSubWindows()));
231  connect(quit, SIGNAL(triggered()), this, SLOT(close()));
232 }
233 
234 void MainWindow::createMdi(QMdiSubWindow *subWindow)
235 {
236  mdiArea->addSubWindow(subWindow);
237 }
238 
240 {
241  artxi = new QAction(tr("About &RTXI"),this);
242  connect(artxi, SIGNAL(triggered()), this, SLOT(about()));
243 
244  axeno = new QAction(tr("About &Xenomai"),this);
245  connect(axeno, SIGNAL(triggered()), this, SLOT(aboutXeno()));
246 
247  aqt = new QAction(tr("About &Qt"),this);
248  connect(aqt, SIGNAL(triggered()), this, SLOT(aboutQt()));
249 
250  adocs = new QAction(tr("&Documentation"), this);
251  connect(adocs, SIGNAL(triggered()), this, SLOT(openDocs()));
252 
253  sub_issue = new QAction(tr("&Submit Issue"), this);
254  connect(sub_issue, SIGNAL(triggered()), this, SLOT(openSubIssue()));
255 }
256 
257 QAction* MainWindow::createSystemMenuItem (const QString &text, const QObject *receiver, const char *member)
258 {
259  return systemMenu->addAction(text, receiver, member);
260 }
261 
263 {
264  QMessageBox::about(this, "About RTXI", "RTXI Version " + QString(VERSION)
265  + "\n\nReleased under the GPLv3.\nSee www.rtxi.org for details.");
266 }
267 
269 {
270  QMessageBox::aboutQt(this);
271 }
272 
274 {
275 #if CONFIG_XENO_VERSION_MAJOR
276  FILE *fp;
277  char xeno_buff[8];
278  fp = fopen("/proc/xenomai/version","r");
279  fscanf(fp, "%s", xeno_buff);
280  fclose(fp);
281  QMessageBox::about(this, "About Xenomai", "Xenomai Version " + QString(xeno_buff));
282 #else
283  QMessageBox::about(this, "About Xenomai", "Running POSIX (non-RT)");
284 #endif
285 }
286 
288 {
289  QDesktopServices::openUrl(QUrl("http://rtxi.org/docs/", QUrl::TolerantMode));
290 }
291 
293 {
294  QDesktopServices::openUrl(QUrl("https://github.com/rtxi/rtxi/issues", QUrl::TolerantMode));
295 }
296 
298 {
299  FILE *pp;
300  pp = popen("/home/yapatel/Dev/rtxi-dev/rtxi/scripts/update_rtxi.sh","r");
301  if (pp != NULL)
302  {
303  while (1)
304  {
305  char *res;
306  char buf[1];
307  res = fgets(buf, sizeof buf, pp);
308  printf("%s", res);
309  }
310  pclose(pp);
311  }
312 }
313 
314 /*
315  * Load MainWindow settings
316  */
318 {
319  QSettings userprefs;
320  userprefs.setPath (QSettings::NativeFormat, QSettings::SystemScope, "/usr/local/share/rtxi/");
321  userprefs.beginGroup("MainWindow");
322  restoreGeometry(userprefs.value("geometry", saveGeometry()).toByteArray());
323  move(userprefs.value("pos", pos()).toPoint());
324  resize(userprefs.value("size", size()).toSize());
325  if(userprefs.value("maximized", isMaximized()).toBool())
326  showMaximized();
327  userprefs.endGroup();
328  show();
329 }
330 
332 {
333  QSettings userprefs;
334  userprefs.setPath (QSettings::NativeFormat, QSettings::SystemScope, "/usr/local/share/rtxi/");
335 
336  QString filename = QFileDialog::getOpenFileName(this,
337  tr("Load saved workspace"), userprefs.value("/dirs/setfiles", getenv("HOME")).toString(), tr("Settings (*.set)"));
338 
339  if (QFile(filename).exists())
340  {
341  systemMenu->clear();
342  mdiArea->closeAllSubWindows();
343  Settings::Manager::getInstance()->load(filename.toStdString());
344  }
345 }
346 
348 {
349  QSettings userprefs;
350  userprefs.setPath (QSettings::NativeFormat, QSettings::SystemScope, "/usr/local/share/rtxi/");
351 
352  QString filename = QFileDialog::getSaveFileName(this,
353  tr("Save current workspace"), userprefs.value("/dirs/setfiles", getenv("HOME")).toString(), tr("Settings (*.set)"));
354 
355  if (!filename.isEmpty())
356  {
357  if (!filename.endsWith(".set"))
358  filename = filename+".set";
359  if (QFileInfo (filename).exists() && QMessageBox::warning(this,
360  "File Exists", "Do you wish to overwrite " + filename + "?",
361  QMessageBox::Yes | QMessageBox::Default,
362  QMessageBox::No | QMessageBox::Escape) != QMessageBox::Yes)
363  {
364  DEBUG_MSG ("MainWindow::saveSettings : canceled overwrite\n");
365  return;
366  }
367  Settings::Manager::getInstance()->save(filename.toStdString());
368  }
369 }
370 
372 {
373  systemMenu->clear();
374  mdiArea->closeAllSubWindows();
375  Settings::Manager::getInstance()->load("/usr/local/share/rtxi/rtxi.conf");
376 }
377 
379 {
380  Plugin::Manager::getInstance()->load(id->text());
381 }
382 
384 {
385 
386  // Clear previous entries
387  windowsMenu->clear();
388 
389  // Add default options
390  windowsMenu->addAction(tr("Cascade"),mdiArea,SLOT(cascadeSubWindows()));
391  windowsMenu->addAction(tr("Tile"),mdiArea,SLOT(tileSubWindows()));
392  windowsMenu->addSeparator();
393 
394  // Get list of open subwindows in Mdi Area
395  subWindows = mdiArea->subWindowList();
396 
397  // Make sure it isn't empty
398  if(subWindows.isEmpty())
399  return;
400 
401  // Create windows list based off of what's open
402  for(int i = 0; i < subWindows.size(); i++)
403  {
404  QAction *item = new QAction(subWindows.at(i)->widget()->windowTitle(), this);
405  windowsMenu->addAction(item);
406  }
407  connect(windowsMenu, SIGNAL(triggered(QAction*)), this, SLOT(windowsMenuActivated(QAction*)));
408 }
409 
411 {
412 
413  // Get list of open subwindows in Mdi Area
414  subWindows = mdiArea->subWindowList();
415 
416  // Make sure it isn't empty
417  if(subWindows.isEmpty())
418  return;
419 
420  for(uint16_t i = 0; i < subWindows.size(); i++)
421  if(subWindows.at(i)->widget()->windowTitle() == id->text())
422  mdiArea->setActiveSubWindow(subWindows.at(i));
423 }
424 
426 {
427  // Annoying but the best way to do it is to tie an action to the entire menu
428  // so we have to tell it to ignore the first two modules
429  if(id->text().contains("Load Plugin"))
430  return;
431 
432  // Have to trim the first three characters before loading
433  // or else parser will include qstring formatting
434  Plugin::Manager::getInstance()->load(id->text().remove(0,3));
435 }
436 
438 {
439  // Annoying but the best way to do it is to tie an action to the entire menu
440  // so we have to tell it to ignore the first three items
441  if(id->text().contains("Load Workspace") ||
442  id->text().contains("Save Workspace") ||
443  id->text().contains("Reset Workspace") ||
444  id->text().contains("Quit"))
445  return;
446 
447  // Have to trim the first three characters before loading
448  // or else parser will include qstring formatting
449  systemMenu->clear();
450  mdiArea->closeAllSubWindows();
451  Settings::Manager::getInstance()->load(id->text().remove(0,3).toStdString());
452 }
453 
454 void MainWindow::closeEvent(QCloseEvent *event)
455 {
456  /*
457  * Save MainWindow settings
458  */
459  QSettings userprefs;
460  userprefs.setPath (QSettings::NativeFormat, QSettings::SystemScope, "/usr/local/share/rtxi/");
461  userprefs.beginGroup("MainWindow");
462  userprefs.setValue("geometry", saveGeometry());
463  userprefs.setValue("maximized", isMaximized());
464  if(!isMaximized())
465  {
466  userprefs.setValue("pos", pos());
467  userprefs.setValue("size", size());
468  }
469  userprefs.endGroup();
470 }
471 
472 static Mutex mutex;
474 
476 {
477  if (instance)
478  return instance;
479 
480  /*************************************************************************
481  * Seems like alot of hoops to jump through, but static allocation isn't *
482  * thread-safe. So effort must be taken to ensure mutual exclusion. *
483  *************************************************************************/
484 
485  Mutex::Locker lock (&::mutex);
486  if (!instance)
487  {
488  static MainWindow mainwindow;
489  instance = &mainwindow;
490  }
491  return instance;
492 }
static MainWindow * getInstance(void)
QMenu * utilitiesSubMenu
Definition: main_window.h:196
QMenu * helpMenu
Definition: main_window.h:199
void clearFileMenu(void)
Definition: main_window.cpp:84
QList< QMdiSubWindow * > subWindows
Definition: main_window.h:189
void changeModuleMenuItem(QAction *action, QString text)
QMenu * signalsSubMenu
Definition: main_window.h:195
QAction * save
Definition: main_window.h:202
void aboutXeno(void)
void createFileActions()
int load(const std::string &)
Definition: settings.cpp:230
QAction * reset
Definition: main_window.h:203
void openDocs(void)
virtual ~MainWindow(void)
Definition: main_window.cpp:70
void fileMenuActivated(QAction *)
void createHelpActions()
void loadWindow(void)
QMenu * moduleMenu
Definition: main_window.h:192
void createWindowsMenu()
void createFileMenu()
void windowsMenuActivated(QAction *)
QAction * adocs
Definition: main_window.h:208
QAction * createUtilMenuItem(const QString &label, const QObject *handler, const char *slot)
void createModuleMenu()
#define VERSION
Definition: rtxi_config.h:78
void createHelpMenu()
Definition: mutex.h:28
void about(void)
int save(const std::string &)
Definition: settings.cpp:358
void utilitiesMenuActivated(QAction *)
QAction * aqt
Definition: main_window.h:207
void closeEvent(QCloseEvent *)
static MainWindow * instance
Definition: main_window.h:185
Object * load(const QString &library)
Definition: plugin.cpp:46
void createMdi(QMdiSubWindow *)
QAction * axeno
Definition: main_window.h:206
QAction * createFileMenuItem(const QString &label)
Definition: main_window.cpp:79
void createSystemMenu()
QAction * load
Definition: main_window.h:201
QMenu * filtersSubMenu
Definition: main_window.h:194
QAction * quit
Definition: main_window.h:204
QMdiArea * mdiArea
Definition: main_window.h:188
QMenu * fileMenu
Definition: main_window.h:191
void aboutQt(void)
QMenu * windowsMenu
Definition: main_window.h:198
void windowsMenuAboutToShow(void)
MainWindow(void)
Definition: main_window.cpp:30
void saveSettings(void)
QMenu * systemMenu
Definition: main_window.h:197
void resetSettings(void)
QMenu * utilMenu
Definition: main_window.h:193
void updateCheck(void)
void modulesMenuActivated(QAction *)
void removeModuleMenuItem(QAction *action)
QAction * sub_issue
Definition: main_window.h:209
QAction * createModuleMenuItem(const QString &text)
Definition: main_window.cpp:96
void setModuleMenuItemParameter(QAction *action, int parameter)
QAction * utilItem
Definition: main_window.h:210
void loadSettings(void)
static Manager * getInstance(void)
Definition: plugin.cpp:186
void openSubIssue(void)
QAction * insertModuleMenuSeparator(void)
Definition: main_window.cpp:74
void createUtilMenu()
static Manager * getInstance(void)
Definition: settings.cpp:534
QAction * createSystemMenuItem(const QString &label, const QObject *handler, const char *slot)
void clearModuleMenu(void)
#define DEBUG_MSG(fmt, args...)
Prints debug messages to standard error.
Definition: debug.h:53
QAction * artxi
Definition: main_window.h:205