MNE-CPP  beta 1.0
eventmodel.cpp
Go to the documentation of this file.
1 //=============================================================================================================
38 //*************************************************************************************************************
39 //=============================================================================================================
40 // INCLUDES
41 //=============================================================================================================
42 
43 #include "eventmodel.h"
44 
45 
46 //*************************************************************************************************************
47 //=============================================================================================================
48 // USED NAMESPACES
49 //=============================================================================================================
50 
51 using namespace MNEBrowseRawQt;
52 
53 
54 //*************************************************************************************************************
55 //=============================================================================================================
56 // DEFINE MEMBER METHODS
57 //=============================================================================================================
58 
59 EventModel::EventModel(QObject *parent)
60 : QAbstractTableModel(parent)
61 , m_iFirstSample(0)
62 , m_bFileloaded(false)
63 , m_sFilterEventType("All")
64 {
65  //Create default event type color map
66  m_eventTypeColor[1] = QColor(Qt::black);
67  m_eventTypeColor[2] = QColor(Qt::magenta);
68  m_eventTypeColor[3] = QColor(Qt::green);
69  m_eventTypeColor[4] = QColor(Qt::red);
70  m_eventTypeColor[5] = QColor(Qt::cyan);
71  m_eventTypeColor[32] = QColor(Qt::yellow);
72  m_eventTypeColor[998] = QColor(Qt::darkBlue);
73  m_eventTypeColor[999] = QColor(Qt::darkCyan);
74 
75  //m_eventTypeList<<"1"<<"2"<<"3"<<"4"<<"4"<<"5"<<"32"<<"998"<<"999";
76 }
77 
78 
79 //*************************************************************************************************************
80 
81 EventModel::EventModel(QFile &qFile, QObject *parent)
82 : QAbstractTableModel(parent)
83 , m_iFirstSample(0)
84 , m_bFileloaded(false)
85 , m_sFilterEventType("All")
86 {
87  //Create default event type color map
88  m_eventTypeColor[1] = QColor(Qt::black);
89  m_eventTypeColor[2] = QColor(Qt::magenta);
90  m_eventTypeColor[3] = QColor(Qt::green);
91  m_eventTypeColor[4] = QColor(Qt::red);
92  m_eventTypeColor[5] = QColor(Qt::cyan);
93  m_eventTypeColor[32] = QColor(Qt::yellow);
94  m_eventTypeColor[998] = QColor(Qt::darkBlue);
95  m_eventTypeColor[999] = QColor(Qt::darkCyan);
96 
97  loadEventData(qFile);
98 }
99 
100 
101 //*************************************************************************************************************
102 //virtual functions
103 int EventModel::rowCount(const QModelIndex & /*parent*/) const
104 {
105  //Always return filtered events so that the qTableView gets the correct number of rows which are to be displayed
106  if(!m_dataSamples_Filtered.size()==0)
107  return m_dataSamples_Filtered.size();
108  else
109  return 0;
110 }
111 
112 
113 //*************************************************************************************************************
114 
115 int EventModel::columnCount(const QModelIndex & /*parent*/) const
116 {
117  return 3;
118 }
119 
120 
121 //*************************************************************************************************************
122 
123 QVariant EventModel::headerData(int section, Qt::Orientation orientation, int role) const
124 {
125  if(role != Qt::DisplayRole && role != Qt::TextAlignmentRole)
126  return QVariant();
127 
128  if(role==Qt::TextAlignmentRole)
129  return Qt::AlignHCenter + Qt::AlignVCenter;
130 
131  if(orientation == Qt::Horizontal) {
132  switch(section) {
133  case 0: //sample column
134  return QVariant("Sample");
135  case 1: //time value column
136  return QVariant("Time (s)");
137  case 2: //event type column
138  return QVariant("Type");
139  }
140  }
141  else if(orientation == Qt::Vertical) {
142  return QString("Event %1").arg(section);
143  }
144 
145  return QVariant();
146 }
147 
148 
149 //*************************************************************************************************************
150 
151 QVariant EventModel::data(const QModelIndex &index, int role) const
152 {
153  if(role == Qt::TextAlignmentRole)
154  return QVariant(Qt::AlignCenter | Qt::AlignVCenter);
155 
156  if(role != Qt::DisplayRole && role != Qt::BackgroundRole)
157  return QVariant();
158 
159  if(index.row()>=m_dataSamples_Filtered.size())
160  return QVariant();
161 
162  if (index.isValid()) {
163  //******** first column (sample index) ********
164  if(index.column()==0) {
165  switch(role) {
166  case Qt::DisplayRole:
167  return QVariant(m_dataSamples_Filtered.at(index.row())-m_iFirstSample);
168 
169  case Qt::BackgroundRole:
170  //Paint different background if event was set by user
171  if(m_dataIsUserEvent_Filtered.at(index.row()) == 1) {
172  QBrush brush;
173  brush.setStyle(Qt::SolidPattern);
174  QColor colorTemp(Qt::red);
175  colorTemp.setAlpha(15);
176  brush.setColor(colorTemp);
177  return QVariant(brush);
178  }
179  }
180  }
181 
182  //******** second column (event time plot) ********
183  if(index.column()==1){
184  switch(role) {
185  case Qt::DisplayRole: {
186  int time = ((m_dataSamples_Filtered.at(index.row()) - m_iFirstSample) / m_fiffInfo.sfreq) * 100;
187 
188  return QVariant((double)time / 100);
189  }
190 
191  case Qt::BackgroundRole:
192  //Paint different background if event was set by user
193  if(m_dataIsUserEvent_Filtered.at(index.row()) == 1) {
194  QBrush brush;
195  brush.setStyle(Qt::SolidPattern);
196  QColor colorTemp(Qt::red);
197  colorTemp.setAlpha(15);
198  brush.setColor(colorTemp);
199  return QVariant(brush);
200  }
201  }
202  }
203 
204  //******** third column (event type plot) ********
205  if(index.column()==2) {
206  switch(role) {
207  case Qt::DisplayRole:
208  return QVariant(m_dataTypes_Filtered.at(index.row()));
209 
210  case Qt::BackgroundRole: {
211  QBrush brush;
212  brush.setStyle(Qt::SolidPattern);
213  brush.setColor(m_eventTypeColor.value(m_dataTypes_Filtered.at(index.row()), Qt::black));
214 
215  QColor colorTemp = brush.color();
216  colorTemp.setAlpha(EVENT_MARKER_OPACITY);
217  brush.setColor(colorTemp);
218  return QVariant(brush);
219  }
220  }
221  }
222 
223  } // end index.valid() check
224 
225  return QVariant();
226 }
227 
228 
229 //*************************************************************************************************************
230 
231 bool EventModel::insertRows(int position, int span, const QModelIndex & parent)
232 {
233  Q_UNUSED(parent);
234 
235  if(m_dataSamples.isEmpty()) {
236  m_dataSamples.insert(0, m_iCurrentMarkerPos);
237  m_dataTypes.insert(0, 1);
238  m_dataIsUserEvent.insert(0, 1);
239  }
240  else {
241  for (int i = 0; i < span; ++i) {
242  for(int t = 0; t<m_dataSamples.size(); t++) {
243  if(m_dataSamples[t] >= m_iCurrentMarkerPos) {
244  m_dataSamples.insert(t, m_iCurrentMarkerPos);
245 
246  if(m_sFilterEventType == "All")
247  m_dataTypes.insert(t, 1);
248  else
249  m_dataTypes.insert(t, m_sFilterEventType.toInt());
250 
251  m_dataIsUserEvent.insert(t, 1);
252  break;
253  }
254 
255  if(t == m_dataSamples.size()-1) {
256  m_dataSamples.append(m_iCurrentMarkerPos);
257 
258  if(m_sFilterEventType == "All")
259  m_dataTypes.append(1);
260  else
261  m_dataTypes.append(m_sFilterEventType.toInt());
262 
263  m_dataIsUserEvent.append(1);
264  }
265  }
266  }
267  }
268 
269  beginInsertRows(QModelIndex(), position, position+span-1);
270 
271  endInsertRows();
272 
273  //Update filtered event data
274  setEventFilterType(m_sFilterEventType);
275 
276  return true;
277 }
278 
279 
280 //*************************************************************************************************************
281 
282 bool EventModel::removeRows(int position, int span, const QModelIndex & parent)
283 {
284  Q_UNUSED(parent);
285 
286  for (int i = 0; i < span; ++i) {
287  //Only user events can be deleted
288  if(m_dataIsUserEvent[position] == 1) {
289  m_dataSamples.removeAt(position);
290  m_dataTypes.removeAt(position);
291  m_dataIsUserEvent.removeAt(position);
292  }
293  }
294 
295  beginRemoveRows(QModelIndex(), position, position+span-1);
296 
297  endRemoveRows();
298 
299  //Update filtered event data
300  setEventFilterType(m_sFilterEventType);
301 
302  return true;
303 }
304 
305 
306 //*************************************************************************************************************
307 
308 Qt::ItemFlags EventModel::flags(const QModelIndex & index) const
309 {
310  //Return editable mode only for user events an when event type filtering is deactivated
311  if(m_dataIsUserEvent_Filtered[index.row()] == 1 && m_sFilterEventType == "All")
312  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
313  else
314  return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
315 }
316 
317 
318 //*************************************************************************************************************
319 
320 bool EventModel::setData(const QModelIndex & index, const QVariant & value, int role)
321 {
322  if(index.row() >= m_dataSamples.size() || index.column() >= columnCount())
323  return false;
324 
325  if(role == Qt::EditRole) {
326  int column = index.column();
327  switch(column) {
328  case 0: //sample values
329  m_dataSamples[index.row()] = value.toInt() + m_iFirstSample;
330  break;
331 
332  case 1: //time values
333  m_dataSamples[index.row()] = value.toDouble() * m_fiffInfo.sfreq + m_iFirstSample;
334  break;
335 
336  case 2: //type
337  QString string = value.toString();
338  m_dataTypes[index.row()] = string.toInt();
339  break;
340  }
341  }
342 
343  //Update filtered event data
344  setEventFilterType(m_sFilterEventType);
345 
346  return true;
347 }
348 
349 
350 //*************************************************************************************************************
351 
352 bool EventModel::loadEventData(QFile& qFile)
353 {
354  beginResetModel();
355  clearModel();
356 
357  // Read events
358  MatrixXi events;
359 
360  if(!MNE::read_events(qFile, events)) {
361  qDebug() << "Error while reading events.";
362  return false;
363  }
364 
365  //std::cout << events << endl;
366 
367  qDebug() << QString("Events read from %1").arg(qFile.fileName());
368 
369  //set loaded fiff event data
370  for(int i = 0; i < events.rows(); i++) {
371  m_dataSamples.append(events(i,0));
372  m_dataTypes.append(events(i,2));
373  m_dataIsUserEvent.append(0);
374  }
375 
376  //Set filtered events to original
377  m_dataSamples_Filtered = m_dataSamples;
378  m_dataTypes_Filtered = m_dataTypes;
379  m_dataIsUserEvent_Filtered = m_dataIsUserEvent;
380 
381  //Create type string list
382  m_eventTypeList.clear();
383  for(int i = 0; i<m_dataTypes.size(); i++)
384  if(!m_eventTypeList.contains(QString().number(m_dataTypes[i])))
385  m_eventTypeList<<QString().number(m_dataTypes[i]);
386 
387  emit updateEventTypes("All");
388 
389  endResetModel();
390 
391  m_bFileloaded = true;
392 
393  return true;
394 }
395 
396 
397 //*************************************************************************************************************
398 
399 bool EventModel::saveEventData(QFile& qFile)
400 {
401  Q_UNUSED(qFile);
402 
403  beginResetModel();
404  clearModel();
405 
406  //TODO: Save events to file
407 
408  endResetModel();
409  return true;
410 }
411 
412 
413 //*************************************************************************************************************
414 
415 void EventModel::setFiffInfo(FiffInfo& fiffInfo)
416 {
417  m_fiffInfo = fiffInfo;
418 }
419 
420 
421 //*************************************************************************************************************
422 
423 void EventModel::setFirstLastSample(int firstSample, int lastSample)
424 {
425  m_iFirstSample = firstSample;
426  m_iLastSample = lastSample;
427 }
428 
429 
430 //*************************************************************************************************************
431 
432 void EventModel::setCurrentMarkerPos(int markerPos)
433 {
434  //add m_iFirstSample because m_iFirstSample gets subtracted when data is asked from this model
435  m_iCurrentMarkerPos = markerPos + m_iFirstSample;
436 }
437 
438 
439 //*************************************************************************************************************
440 
441 FiffInfo EventModel::getFiffInfo() const
442 {
443  return m_fiffInfo;
444 }
445 
446 
447 //*************************************************************************************************************
448 
449 QPair<int, int> EventModel::getFirstLastSample() const
450 {
451  QPair<int, int> pair(m_iFirstSample, m_iLastSample);
452  return pair;
453 }
454 
455 
456 //*************************************************************************************************************
457 
458 void EventModel::setEventFilterType(const QString eventType)
459 {
460  m_sFilterEventType = eventType;
461 
462  //Clear filtered event data
463  m_dataSamples_Filtered.clear();
464  m_dataTypes_Filtered.clear();
465  m_dataIsUserEvent_Filtered.clear();
466 
467  //Fill filtered event data depending on the user defined event filter type
468  if(eventType == "All") {
469  m_dataSamples_Filtered = m_dataSamples;
470  m_dataTypes_Filtered = m_dataTypes;
471  m_dataIsUserEvent_Filtered = m_dataIsUserEvent;
472  }
473  else {
474  for(int i = 0; i<m_dataSamples.size(); i++) {
475  if(m_dataTypes[i] == eventType.toInt()) {
476  m_dataSamples_Filtered.append(m_dataSamples[i]);
477  m_dataTypes_Filtered.append(m_dataTypes[i]);
478  m_dataIsUserEvent_Filtered.append(m_dataIsUserEvent[i]);
479  }
480  }
481  }
482 
483  emit dataChanged(createIndex(0,0), createIndex(m_dataSamples_Filtered.size(), 0));
484  emit headerDataChanged(Qt::Vertical, 0, m_dataSamples_Filtered.size());
485 }
486 
487 
488 //*************************************************************************************************************
489 
490 QStringList EventModel::getEventTypeList() const
491 {
492  return m_eventTypeList;
493 }
494 
495 
496 //*************************************************************************************************************
497 
498 const QMap<int, QColor> & EventModel::getEventTypeColors()
499 {
500  return m_eventTypeColor;
501 }
502 
503 
504 //*************************************************************************************************************
505 
506 void EventModel::clearModel()
507 {
508  beginResetModel();
509  //clear event data model structure
510  m_dataSamples.clear();
511  m_dataTypes.clear();
512  m_dataIsUserEvent.clear();
513 
514  m_dataSamples_Filtered.clear();
515  m_dataTypes_Filtered.clear();
516  m_dataIsUserEvent_Filtered.clear();
517 
518  m_bFileloaded = false;
519 
520  endResetModel();
521 
522  qDebug("EventModel cleared.");
523 }
524 
525 
526 //*************************************************************************************************************
527 
528 void EventModel::addNewEventType(const QString &eventType, const QColor &typeColor)
529 {
530  //Add type color
531  m_eventTypeColor[eventType.toInt()] = typeColor;
532 
533  //Add event type to event type list
534  if(!m_eventTypeList.contains(eventType))
535  m_eventTypeList<<eventType;
536 
537  emit updateEventTypes(eventType);
538 }
This class represents the event model of the model/view framework of mne_browse_raw_qt application...
static bool read_events(QIODevice &p_IODevice, MatrixXi &eventlist)
Definition: mne.cpp:68