RTXI  2.4
The Real-Time eXperiment Interface Documentation
default_gui_model.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 <default_gui_model.h>
21 #include <main_window.h>
22 #include <iostream>
23 
24 namespace
25 {
26 class SyncEvent: public RT::Event
27 {
28 public:
29  int callback(void)
30  {
31  return 0;
32  };
33 };
34 };
35 
36 DefaultGUILineEdit::DefaultGUILineEdit(QWidget *parent):QLineEdit(parent)
37 {
38  QObject::connect(this,SIGNAL(textChanged(const QString &)),this,SLOT(redden(void)));
39 }
40 
42 {
43 }
44 
46 {
47  palette.setBrush(this->foregroundRole(), QApplication::palette().color(QPalette::WindowText));
48  this->setPalette(palette);
49  setModified(false);
50 }
51 
53 {
54  if(isModified())
55  {
56  palette.setBrush(this->foregroundRole(), Qt::red);
57  this->setPalette(palette);
58  }
59 }
60 
62  QWidget(MainWindow::getInstance()->centralWidget()), Workspace::Instance(name, var, size), myname(name)
63 {
64  setWindowTitle(QString::number(getID()) + " " + QString::fromStdString(name));
65 
66  QTimer *timer = new QTimer(this);
67  timer->setTimerType(Qt::PreciseTimer);
68  timer->start(1000);
69  QObject::connect(timer,SIGNAL(timeout(void)),this,SLOT(refresh(void)));
70 }
71 
73 {
74  // Ensure that the realtime thread isn't in the middle of executing DefaultGUIModel::execute()
75  setActive( false );
76  SyncEvent event;
78 
79  for (std::map<QString, param_t>::iterator i = parameter.begin(); i
80  != parameter.end(); ++i)
81  if (i->second.type & PARAMETER)
82  delete i->second.str_value;
83 }
84 
86 {
87 
88  // Make Mdi
89  subWindow = new QMdiSubWindow;
90  subWindow->setAttribute(Qt::WA_DeleteOnClose);
91  subWindow->setWindowIcon(QIcon("/usr/local/share/rtxi/RTXI-widget-icon.png"));
92  subWindow->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint);
93  subWindow->setOption(QMdiSubWindow::RubberBandResize, true);
94  subWindow->setOption(QMdiSubWindow::RubberBandMove, true);
95  MainWindow::getInstance()->createMdi(subWindow);
96 
97  // Create main layout
98  layout = new QGridLayout;
99 
100  // Create child widget and gridLayout
101  QScrollArea *gridArea = new QScrollArea;
102  gridBox = new QWidget;
103  gridArea->setWidget(gridBox);
104  gridArea->ensureWidgetVisible(gridBox, 0, 0);
105  gridArea->setWidgetResizable(true);
106  QGridLayout *gridLayout = new QGridLayout;
107 
108  size_t nstate = 0, nparam = 0, nevent = 0, ncomment = 0;
109  for (int i = 0; i < size; i++)
110  {
111  if (var[i].flags & (PARAMETER | STATE | EVENT | COMMENT))
112  {
113  param_t param;
114 
115  param.label = new QLabel(QString::fromStdString(var[i].name), gridBox);
116  gridLayout->addWidget(param.label, parameter.size(), 0);
117  param.edit = new DefaultGUILineEdit(gridBox);
118  gridLayout->addWidget(param.edit, parameter.size(), 1);
119 
120  param.label->setToolTip(QString::fromStdString(var[i].description));
121  param.edit->setToolTip(QString::fromStdString(var[i].description));
122 
123  if (var[i].flags & PARAMETER)
124  {
125  if (var[i].flags & DOUBLE)
126  {
127  param.edit->setValidator(new QDoubleValidator(param.edit));
128  param.type = PARAMETER | DOUBLE;
129  }
130  else if (var[i].flags & UINTEGER)
131  {
132  QIntValidator *validator = new QIntValidator(param.edit);
133  param.edit->setValidator(validator);
134  validator->setBottom(0);
135  param.type = PARAMETER | UINTEGER;
136  }
137  else if (var[i].flags & INTEGER)
138  {
139  param.edit->setValidator(new QIntValidator(param.edit));
140  param.type = PARAMETER | INTEGER;
141  }
142  else
143  param.type = PARAMETER;
144  param.index = nparam++;
145  param.str_value = new QString;
146  }
147  else if (var[i].flags & STATE)
148  {
149  param.edit->setReadOnly(true);
150  palette.setBrush(param.edit->foregroundRole(), Qt::darkGray);
151  param.edit->setPalette(palette);
152  param.type = STATE;
153  param.index = nstate++;
154  }
155  else if (var[i].flags & EVENT)
156  {
157  param.edit->setReadOnly(true);
158  param.type = EVENT;
159  param.index = nevent++;
160  }
161  else if (var[i].flags & COMMENT)
162  {
163  param.type = COMMENT;
164  param.index = ncomment++;
165  }
166  parameter[QString::fromStdString(var[i].name)] = param;
167  }
168  }
169 
170  // Create child widget
171  buttonGroup = new QGroupBox;
172  QHBoxLayout *buttonLayout = new QHBoxLayout;
173 
174  // Create elements
175  pauseButton = new QPushButton("Pause", this);
176  pauseButton->setCheckable(true);
177  QObject::connect(pauseButton,SIGNAL(toggled(bool)),this,SLOT(pause(bool)));
178  buttonLayout->addWidget(pauseButton);
179 
180  modifyButton = new QPushButton("Modify", this);
181  QObject::connect(modifyButton,SIGNAL(clicked(void)),this,SLOT(modify(void)));
182  buttonLayout->addWidget(modifyButton);
183 
184  unloadButton = new QPushButton("Unload", this);
185  QObject::connect(unloadButton,SIGNAL(clicked(void)),this,SLOT(exit(void)));
186  buttonLayout->addWidget(unloadButton);
187 
188  // Add layout to box
189  gridBox->setLayout(gridLayout);
190  buttonGroup->setLayout(buttonLayout);
191 
192  // Keep one row of space above for users to place in grid
193  layout->addWidget(gridArea, 1, 0);
194 
195  // Attempt to put these at the bottom at all times
196  layout->addWidget(buttonGroup, 10, 0);
197 
198  // Set layout to Mdi and show
199  setLayout(layout);
200  subWindow->setWidget(this);
201  subWindow->show();
202 }
203 
205 {
206 }
207 
209 {
210  subWindow->adjustSize();
211 }
212 
214 {
215  // Ensure that the realtime thread isn't in the middle of executing DefaultGUIModel::execute()
216  setActive(false);
217  SyncEvent event;
219 
220  update(EXIT);
222  subWindow->close();
223 }
224 
226 {
227  for (std::map<QString, param_t>::iterator i = parameter.begin(); i!= parameter.end(); ++i)
228  {
229  if (i->second.type & (STATE | EVENT))
230  {
231  i->second.edit->setText(QString::number(getValue(i->second.type, i->second.index)));
232  palette.setBrush(i->second.edit->foregroundRole(), Qt::darkGray);
233  i->second.edit->setPalette(palette);
234  }
235  else if ((i->second.type & PARAMETER) && !i->second.edit->isModified()
236  && i->second.edit->text() != *i->second.str_value)
237  {
238  i->second.edit->setText(*i->second.str_value);
239  }
240  else if ((i->second.type & COMMENT) && !i->second.edit->isModified()
241  && i->second.edit->text() != QString::fromStdString(getValueString(COMMENT, i->second.index)))
242  {
243  i->second.edit->setText(QString::fromStdString(getValueString(COMMENT, i->second.index)));
244  }
245  }
246  pauseButton->setChecked(!getActive());
247 }
248 
250 {
251  bool active = getActive();
252  setActive(false);
253  // Ensure that the realtime thread isn't in the middle of executing DefaultGUIModel::execute()
254  SyncEvent event;
256 
257  for (std::map<QString, param_t>::iterator i = parameter.begin(); i != parameter.end(); ++i)
258  if (i->second.type & COMMENT)
259  {
260  QByteArray textData = i->second.edit->text().toLatin1();
261  const char *text = textData.constData();
262  Workspace::Instance::setComment(i->second.index, text);
263  }
264 
265  update(MODIFY);
266  setActive(active);
267 
268  for (std::map<QString, param_t>::iterator i = parameter.begin(); i != parameter.end(); ++i)
269  i->second.edit->blacken();
270 }
271 
272 QString DefaultGUIModel::getComment(const QString &name)
273 {
274  std::map<QString, param_t>::iterator n = parameter.find(name);
275  if (n != parameter.end() && (n->second.type & COMMENT))
276  return QString::fromStdString(getValueString(COMMENT, n->second.index));
277  return "";
278 }
279 
280 void DefaultGUIModel::setComment(const QString &name, QString comment)
281 {
282  std::map<QString, param_t>::iterator n = parameter.find(name);
283  if (n != parameter.end() && (n->second.type & COMMENT))
284  {
285  n->second.edit->setText(comment);
286  QByteArray textData = comment.toLatin1();
287  const char *text = textData.constData();
288  Workspace::Instance::setComment(n->second.index, text);
289  }
290 }
291 
292 QString DefaultGUIModel::getParameter(const QString &name)
293 {
294  std::map<QString, param_t>::iterator n = parameter.find(name);
295  if ((n != parameter.end()) && (n->second.type & PARAMETER))
296  {
297  *n->second.str_value = n->second.edit->text();
298  setValue(n->second.index, n->second.edit->text().toDouble());
299  return n->second.edit->text();
300  }
301  return "";
302 }
303 
304 void DefaultGUIModel::setParameter(const QString &name, double value)
305 {
306  std::map<QString, param_t>::iterator n = parameter.find(name);
307  if ((n != parameter.end()) && (n->second.type & PARAMETER))
308  {
309  n->second.edit->setText(QString::number(value));
310  *n->second.str_value = n->second.edit->text();
311  setValue(n->second.index, n->second.edit->text().toDouble());
312  }
313 }
314 
315 void DefaultGUIModel::setParameter(const QString &name, const QString value)
316 {
317  std::map<QString, param_t>::iterator n = parameter.find(name);
318  if ((n != parameter.end()) && (n->second.type & PARAMETER))
319  {
320  n->second.edit->setText(value);
321  *n->second.str_value = n->second.edit->text();
322  setValue(n->second.index, n->second.edit->text().toDouble());
323  }
324 }
325 
326 void DefaultGUIModel::setState(const QString &name, double &ref)
327 {
328  std::map<QString, param_t>::iterator n = parameter.find(name);
329  if ((n != parameter.end()) && (n->second.type & STATE))
330  {
331  setData(Workspace::STATE, n->second.index, &ref);
332  n->second.edit->setText(QString::number(ref));
333  }
334 }
335 
336 void DefaultGUIModel::setEvent(const QString &name, double &ref)
337 {
338  std::map<QString, param_t>::iterator n = parameter.find(name);
339  if ((n != parameter.end()) && (n->second.type & EVENT))
340  {
341  setData(Workspace::EVENT, n->second.index, &ref);
342  n->second.edit->setText(QString::number(ref));
343  }
344 }
345 
347 {
348  if (pauseButton->isChecked() != p)
349  pauseButton->setDown(p);
350 
351  setActive(!p);
352  if (p)
353  update(PAUSE);
354  else
355  update(UNPAUSE);
356 }
357 
358 void DefaultGUIModel::doDeferred(const Settings::Object::State &)
359 {
360  setWindowTitle(QString::number(getID()) + " " + QString::fromStdString(myname));
361 }
362 
363 void DefaultGUIModel::doLoad(const Settings::Object::State &s)
364 {
365  for (std::map<QString, param_t>::iterator i = parameter.begin(); i
366  != parameter.end(); ++i)
367  i->second.edit->setText(QString::fromStdString(s.loadString((i->first).toStdString())));
368  if (s.loadInteger("Maximized"))
369  showMaximized();
370  else if (s.loadInteger("Minimized"))
371  showMinimized();
372  // this only exists in RTXI versions >1.3
373  if (s.loadInteger("W") != 0)
374  {
375  resize(s.loadInteger("W"), s.loadInteger("H"));
376  parentWidget()->move(s.loadInteger("X"), s.loadInteger("Y"));
377  }
378 
379  pauseButton->setChecked(s.loadInteger("paused"));
380  modify();
381 }
382 
383 void DefaultGUIModel::doSave(Settings::Object::State &s) const
384 {
385  s.saveInteger("paused", pauseButton->isChecked());
386  if (isMaximized())
387  s.saveInteger("Maximized", 1);
388  else if (isMinimized())
389  s.saveInteger("Minimized", 1);
390 
391  QPoint pos = parentWidget()->pos();
392  s.saveInteger("X", pos.x());
393  s.saveInteger("Y", pos.y());
394  s.saveInteger("W", width());
395  s.saveInteger("H", height());
396 
397  for (std::map<QString, param_t>::const_iterator i = parameter.begin(); i
398  != parameter.end(); ++i)
399  s.saveString((i->first).toStdString(), (i->second.edit->text()).toStdString());
400 }
401 
402 void DefaultGUIModel::receiveEvent(const Event::Object *event)
403 {
404  if (event->getName() == Event::RT_PREPERIOD_EVENT)
405  {
406  periodEventPaused = getActive();
407  setActive(false);
408  }
409  else if (event->getName() == Event::RT_POSTPERIOD_EVENT)
410  {
411 #ifdef DEBUG
412  if (getActive())
413  ERROR_MSG("DefaultGUIModel::receiveEvent : model unpaused during a period update\n");
414 #endif
415  update(PERIOD);
416  setActive(periodEventPaused);
417  }
418 }
Plugin::Manager::unload
void unload(Object *object)
Definition: plugin.cpp:100
DefaultGUIModel::param_t::type
IO::flags_t type
Definition: default_gui_model.h:179
DefaultGUILineEdit::blacken
void blacken(void)
Definition: default_gui_model.cpp:45
RT::Event
Definition: rt.h:82
DefaultGUIModel::modifyButton
QPushButton * modifyButton
Definition: default_gui_model.h:172
DefaultGUIModel::update
virtual void update(update_flags_t flag)
Definition: default_gui_model.cpp:204
Event::RT_POSTPERIOD_EVENT
const char * RT_POSTPERIOD_EVENT
Definition: event.cpp:26
ERROR_MSG
void ERROR_MSG(const std::string &errmsg,...)
Definition: debug.cpp:27
default_gui_model.h
DefaultGUIModel::UINTEGER
static const IO::flags_t UINTEGER
Definition: default_gui_model.h:116
DefaultGUIModel::param_t::index
size_t index
Definition: default_gui_model.h:180
DefaultGUIModel::EVENT
static const IO::flags_t EVENT
Definition: default_gui_model.h:98
DefaultGUIModel::setParameter
void setParameter(const QString &name, double value)
Definition: default_gui_model.cpp:304
DefaultGUIModel::COMMENT
static const IO::flags_t COMMENT
Definition: default_gui_model.h:104
Event::Object::getName
const char * getName(void) const
Definition: event.h:141
DefaultGUIModel::pauseButton
QPushButton * pauseButton
Definition: default_gui_model.h:171
MainWindow::createMdi
void createMdi(QMdiSubWindow *)
Definition: main_window.cpp:230
DefaultGUIModel::refresh
virtual void refresh(void)
Definition: default_gui_model.cpp:225
DefaultGUIModel::resizeMe
void resizeMe()
Definition: default_gui_model.cpp:208
DefaultGUIModel::PERIOD
@ PERIOD
Definition: default_gui_model.h:135
RT::System::postEvent
int postEvent(Event *event, bool blocking=true)
Definition: rt.cpp:218
DefaultGUIModel::update_flags_t
update_flags_t
Definition: default_gui_model.h:131
RT::Thread::setActive
void setActive(bool)
Definition: rt.cpp:152
DefaultGUIModel::param_t::edit
DefaultGUILineEdit * edit
Definition: default_gui_model.h:178
DefaultGUIModel::palette
QPalette palette
Definition: default_gui_model.h:184
DefaultGUIModel::getParameter
QString getParameter(const QString &name)
Definition: default_gui_model.cpp:292
DefaultGUIModel::EXIT
@ EXIT
Definition: default_gui_model.h:138
Workspace::Instance::getValueString
std::string getValueString(IO::flags_t type, size_t index) const
Definition: workspace.cpp:204
RT::Event::callback
virtual int callback(void)=0
Workspace::Instance::getValue
double getValue(IO::flags_t type, size_t index) const
Definition: workspace.cpp:182
DefaultGUILineEdit::DefaultGUILineEdit
DefaultGUILineEdit(QWidget *)
Definition: default_gui_model.cpp:36
Settings::Object::State::loadString
std::string loadString(const std::string &name) const
Definition: settings.cpp:93
RT::System::getInstance
static System * getInstance(void)
Definition: rt.cpp:361
DefaultGUILineEdit::redden
void redden(void)
Definition: default_gui_model.cpp:52
DefaultGUIModel::DefaultGUIModel
DefaultGUIModel(std::string name, variable_t *variables, size_t size)
Definition: default_gui_model.cpp:61
DefaultGUIModel::pause
virtual void pause(bool)
Definition: default_gui_model.cpp:346
Settings::Object::State::saveString
void saveString(const std::string &name, const std::string &value)
Definition: settings.cpp:119
DefaultGUIModel::setState
void setState(const QString &name, double &ref)
Definition: default_gui_model.cpp:326
DefaultGUIModel::~DefaultGUIModel
virtual ~DefaultGUIModel(void)
Definition: default_gui_model.cpp:72
IO::channel_t
Definition: io.h:56
Settings::Object::State::loadInteger
int loadInteger(const std::string &name) const
Definition: settings.cpp:77
DefaultGUIModel::modify
virtual void modify(void)
Definition: default_gui_model.cpp:249
DefaultGUIModel::createGUI
void createGUI(DefaultGUIModel::variable_t *var, int size)
Definition: default_gui_model.cpp:85
Workspace
Internal Control Oriented Classes.
Definition: workspace.h:30
DefaultGUIModel::setComment
void setComment(const QString &name, const QString comment)
Definition: default_gui_model.cpp:280
DefaultGUIModel::INTEGER
static const IO::flags_t INTEGER
Definition: default_gui_model.h:112
DefaultGUIModel::param_t::str_value
QString * str_value
Definition: default_gui_model.h:181
Settings::Object::State
Definition: settings.h:62
Workspace::Instance::setValue
void setValue(size_t index, double value)
Definition: workspace.cpp:231
Plugin::Manager::getInstance
static Manager * getInstance(void)
Definition: plugin.cpp:188
Settings::Object::State::saveInteger
void saveInteger(const std::string &name, int)
Definition: settings.cpp:112
DefaultGUIModel::PAUSE
@ PAUSE
Definition: default_gui_model.h:136
DefaultGUIModel::layout
QGridLayout * layout
Definition: default_gui_model.h:215
DefaultGUILineEdit::~DefaultGUILineEdit
~DefaultGUILineEdit(void)
Definition: default_gui_model.cpp:41
DefaultGUIModel::param_t::label
QLabel * label
Definition: default_gui_model.h:177
Workspace::Instance::setData
void setData(IO::flags_t type, size_t index, double *value)
Definition: workspace.cpp:272
DefaultGUIModel::PARAMETER
static const IO::flags_t PARAMETER
Definition: default_gui_model.h:86
MainWindow::getInstance
static MainWindow * getInstance(void)
Definition: main_window.cpp:454
DefaultGUIModel::STATE
static const IO::flags_t STATE
Definition: default_gui_model.h:92
DefaultGUIModel::setEvent
void setEvent(const QString &name, double &ref)
Definition: default_gui_model.cpp:336
RT::Thread::getActive
bool getActive(void) const
Definition: rt.h:600
Event::RT_PREPERIOD_EVENT
const char * RT_PREPERIOD_EVENT
Definition: event.cpp:25
DefaultGUIModel::exit
virtual void exit(void)
Definition: default_gui_model.cpp:213
Workspace::Instance::setComment
void setComment(size_t index, std::string comment)
Definition: workspace.cpp:253
DefaultGUIModel::unloadButton
QPushButton * unloadButton
Definition: default_gui_model.h:173
Event::Object
Definition: event.h:128
MainWindow
Definition: main_window.h:35
DefaultGUIModel::MODIFY
@ MODIFY
Definition: default_gui_model.h:134
Settings::Object::getID
ID getID(void) const
Definition: settings.h:131
DefaultGUIModel::parameter
std::map< QString, param_t > parameter
Definition: default_gui_model.h:183
DefaultGUIModel::getComment
QString getComment(const QString &name)
Definition: default_gui_model.cpp:272
DefaultGUILineEdit::palette
QPalette palette
Definition: default_gui_model.h:43
DefaultGUIModel::param_t
Definition: default_gui_model.h:175
DefaultGUIModel::DOUBLE
static const IO::flags_t DOUBLE
Definition: default_gui_model.h:108
DefaultGUILineEdit
Definition: default_gui_model.h:34
DefaultGUIModel::UNPAUSE
@ UNPAUSE
Definition: default_gui_model.h:137
main_window.h