[med-svn] [Git][med-team/edfbrowser][upstream] New upstream version 1.97+dfsg
Étienne Mollier (@emollier)
gitlab at salsa.debian.org
Tue Nov 29 19:46:07 GMT 2022
Étienne Mollier pushed to branch upstream at Debian Med / edfbrowser
Commits:
59fae14f by Étienne Mollier at 2022-11-29T20:38:00+01:00
New upstream version 1.97+dfsg
- - - - -
22 changed files:
- annotations_dock.cpp
- check_for_updates.cpp
- cnvs/mit2edf.cpp
- doc/manual.html
- global.h
- hypnogram_dialog.cpp
- hypnogram_dialog.h
- hypnogram_dock.cpp
- hypnogram_dock.h
- import_annotations.cpp
- load_session.cpp
- mainwindow.cpp
- mainwindow.h
- mainwindow_constr.cpp
- read_write_settings.cpp
- special_button.cpp
- special_button.h
- third_party/fidlib/fidrf_cmdlist.h
- utils.c
- utils.h
- version.txt
- videoplayer.cpp
Changes:
=====================================
annotations_dock.cpp
=====================================
@@ -216,8 +216,7 @@ void UI_Annotationswindow::delete_annots()
return;
}
- annot_list = &(edf_hdr->annot_list);
- if(annot_list == NULL)
+ if(edf_hdr == NULL)
{
snprintf(str, 4096, "Nullpointer returned: file: %s line %i", __FILE__, __LINE__);
QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
@@ -225,6 +224,8 @@ void UI_Annotationswindow::delete_annots()
return;
}
+ annot_list = &(edf_hdr->annot_list);
+
annot = edfplus_annotation_get_item_visible_only(annot_list, list->currentRow());
if(annot == NULL)
{
@@ -265,7 +266,7 @@ void UI_Annotationswindow::delete_all_annots()
return;
}
- if(&edf_hdr->annot_list == NULL)
+ if(edf_hdr == NULL)
{
snprintf(str, 4096, "Nullpointer returned: file: %s line %i", __FILE__, __LINE__);
QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
@@ -329,8 +330,7 @@ void UI_Annotationswindow::rename_all()
return;
}
- annot_list = &(edf_hdr->annot_list);
- if(annot_list == NULL)
+ if(edf_hdr == NULL)
{
snprintf(str, 4096, "Nullpointer returned: file: %s line %i", __FILE__, __LINE__);
QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
@@ -338,6 +338,8 @@ void UI_Annotationswindow::rename_all()
return;
}
+ annot_list = &(edf_hdr->annot_list);
+
annot = edfplus_annotation_get_item_visible_only(annot_list, list->currentRow());
if(annot == NULL)
{
@@ -384,8 +386,7 @@ void UI_Annotationswindow::show_heart_rate(bool)
return;
}
- annot_list = &(edf_hdr->annot_list);
- if(annot_list == NULL)
+ if(edf_hdr == NULL)
{
snprintf(str, 4096, "Nullpointer returned: file: %s line %i", __FILE__, __LINE__);
QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
@@ -393,6 +394,8 @@ void UI_Annotationswindow::show_heart_rate(bool)
return;
}
+ annot_list = &(edf_hdr->annot_list);
+
annot = edfplus_annotation_get_item_visible_only(annot_list, row);
if(annot == NULL)
{
@@ -466,8 +469,7 @@ void UI_Annotationswindow::show_stats(bool)
return;
}
- annot_list = &(edf_hdr->annot_list);
- if(annot_list == NULL)
+ if(edf_hdr == NULL)
{
snprintf(str, 4096, "Nullpointer returned: file: %s line %i", __FILE__, __LINE__);
QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
@@ -475,6 +477,8 @@ void UI_Annotationswindow::show_stats(bool)
return;
}
+ annot_list = &(edf_hdr->annot_list);
+
annot = edfplus_annotation_get_item_visible_only(annot_list, list->currentRow());
if(annot == NULL)
{
@@ -512,6 +516,14 @@ void UI_Annotationswindow::filt_ival_time(bool)
return;
}
+ if(edf_hdr == NULL)
+ {
+ snprintf(str, 4096, "Nullpointer returned: file: %s line %i", __FILE__, __LINE__);
+ QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
+ messagewindow.exec();
+ return;
+ }
+
annot_list = &(edf_hdr->annot_list);
annot = edfplus_annotation_get_item_visible_only(annot_list, list->currentRow());
@@ -1072,8 +1084,7 @@ void UI_Annotationswindow::average_annot(bool)
return;
}
- annot_list = &(edf_hdr->annot_list);
- if(annot_list == NULL)
+ if(edf_hdr == NULL)
{
snprintf(str, 4096, "Nullpointer returned: file: %s line %i", __FILE__, __LINE__);
QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
@@ -1081,6 +1092,8 @@ void UI_Annotationswindow::average_annot(bool)
return;
}
+ annot_list = &(edf_hdr->annot_list);
+
annot = edfplus_annotation_get_item_visible_only(annot_list, list->currentRow());
if(annot == NULL)
{
=====================================
check_for_updates.cpp
=====================================
@@ -46,8 +46,8 @@ Check_for_updates::Check_for_updates(UI_Mainwindow *mw)
request.setRawHeader("User-Agent", PROGRAM_NAME " " PROGRAM_VERSION " OS_UNKNOWN " THIS_APP_BITS_W);
#ifdef Q_OS_LINUX
request.setRawHeader("User-Agent", PROGRAM_NAME " " PROGRAM_VERSION " Q_OS_LINUX " THIS_APP_BITS_W);
-#elif defined (Q_OS_MAC)
- request.setRawHeader("User-Agent", PROGRAM_NAME " " PROGRAM_VERSION " Q_OS_MAC " THIS_APP_BITS_W);
+#elif defined (Q_OS_MACOS)
+ request.setRawHeader("User-Agent", PROGRAM_NAME " " PROGRAM_VERSION " Q_OS_MACOS " THIS_APP_BITS_W);
#elif defined (Q_OS_WIN32)
request.setRawHeader("User-Agent", PROGRAM_NAME " " PROGRAM_VERSION " Q_OS_WIN32 " THIS_APP_BITS_W);
#else
=====================================
cnvs/mit2edf.cpp
=====================================
@@ -30,94 +30,129 @@
#include "mit2edf.h"
-#define NOTQRS 0 /* not-QRS (not a getann/putann code) */
-#define NORMAL 1 /* normal beat */
-#define LBBB 2 /* left bundle branch block beat */
-#define RBBB 3 /* right bundle branch block beat */
-#define ABERR 4 /* aberrated atrial premature beat */
-#define PVC 5 /* premature ventricular contraction */
-#define FUSION 6 /* fusion of ventricular and normal beat */
-#define NPC 7 /* nodal (junctional) premature beat */
-#define APC 8 /* atrial premature contraction */
-#define SVPB 9 /* premature or ectopic supraventricular beat */
-#define VESC 10 /* ventricular escape beat */
-#define NESC 11 /* nodal (junctional) escape beat */
-#define PACE 12 /* paced beat */
-#define UNKNOWN 13 /* unclassifiable beat */
-#define NOISE 14 /* signal quality change */
-#define ARFCT 16 /* isolated QRS-like artifact */
-#define STCH 18 /* ST change */
-#define TCH 19 /* T-wave change */
-#define SYSTOLE 20 /* systole */
-#define DIASTOLE 21 /* diastole */
-#define NOTE 22 /* comment annotation */
-#define MEASURE 23 /* measurement annotation */
-#define PWAVE 24 /* P-wave peak */
-#define BBB 25 /* left or right bundle branch block */
-#define PACESP 26 /* non-conducted pacer spike */
-#define TWAVE 27 /* T-wave peak */
-#define RHYTHM 28 /* rhythm change */
-#define UWAVE 29 /* U-wave peak */
-#define LEARN 30 /* learning */
-#define FLWAV 31 /* ventricular flutter wave */
-#define VFON 32 /* start of ventricular flutter/fibrillation */
-#define VFOFF 33 /* end of ventricular flutter/fibrillation */
-#define AESC 34 /* atrial escape beat */
-#define SVESC 35 /* supraventricular escape beat */
-#define LINK 36 /* link to external data (aux contains URL) */
-#define NAPC 37 /* non-conducted P-wave (blocked APB) */
-#define PFUS 38 /* fusion of paced and normal beat */
-#define WFON 39 /* waveform onset */
-#define PQ WFON /* PQ junction (beginning of QRS) */
-#define WFOFF 40 /* waveform end */
-#define JPT WFOFF /* J point (end of QRS) */
-#define RONT 41 /* R-on-T premature ventricular contraction */
+#define NOTQRS (0) /* not-QRS (not a getann/putann code) */
+#define NORMAL (1) /* normal beat */
+#define LBBB (2) /* left bundle branch block beat */
+#define RBBB (3) /* right bundle branch block beat */
+#define ABERR (4) /* aberrated atrial premature beat */
+#define PVC (5) /* premature ventricular contraction */
+#define FUSION (6) /* fusion of ventricular and normal beat */
+#define NPC (7) /* nodal (junctional) premature beat */
+#define APC (8) /* atrial premature contraction */
+#define SVPB (9) /* premature or ectopic supraventricular beat */
+#define VESC (10) /* ventricular escape beat */
+#define NESC (11) /* nodal (junctional) escape beat */
+#define PACE (12) /* paced beat */
+#define UNKNOWN (13) /* unclassifiable beat */
+#define NOISE (14) /* signal quality change */
+#define ARFCT (16) /* isolated QRS-like artifact */
+#define STCH (18) /* ST change */
+#define TCH (19) /* T-wave change */
+#define SYSTOLE (20) /* systole */
+#define DIASTOLE (21) /* diastole */
+#define NOTE (22) /* comment annotation */
+#define MEASURE (23) /* measurement annotation */
+#define PWAVE (24) /* P-wave peak */
+#define BBB (25) /* left or right bundle branch block */
+#define PACESP (26) /* non-conducted pacer spike */
+#define TWAVE (27) /* T-wave peak */
+#define RHYTHM (28) /* rhythm change */
+#define UWAVE (29) /* U-wave peak */
+#define LEARN (30) /* learning */
+#define FLWAV (31) /* ventricular flutter wave */
+#define VFON (32) /* start of ventricular flutter/fibrillation */
+#define VFOFF (33) /* end of ventricular flutter/fibrillation */
+#define AESC (34) /* atrial escape beat */
+#define SVESC (35) /* supraventricular escape beat */
+#define LINK (36) /* link to external data (aux contains URL) */
+#define NAPC (37) /* non-conducted P-wave (blocked APB) */
+#define PFUS (38) /* fusion of paced and normal beat */
+#define WFON (39) /* waveform onset */
+#define PQ WFON /* PQ junction (beginning of QRS) */
+#define WFOFF (40) /* waveform end */
+#define JPT WFOFF /* J point (end of QRS) */
+#define RONT (41) /* R-on-T premature ventricular contraction */
/* ... annotation codes between RONT+1 and ACMAX inclusive are user-defined */
-#define ACMAX 49 /* value of largest valid annot code (must be < 50) */
-
-
-static char annotdescrlist[42][48]=
- {"not-QRS","normal beat",
- "left bundle branch block beat", "right bundle branch block beat",
- "aberrated atrial premature beat", "premature ventricular contraction",
- "fusion of ventricular and normal beat", "nodal (junctional) premature beat",
- "atrial premature contraction", "premature or ectopic supraventricular beat",
- "ventricular escape beat", "nodal (junctional) escape beat",
- "paced beat", "unclassifiable beat",
- "signal quality change", "isolated QRS-like artifact",
- "ST change", "T-wave change",
- "systole", "diastole",
- "comment annotation", "measurement annotation",
- "P-wave peak", "left or right bundle branch block",
- "non-conducted pacer spike", "T-wave peak",
- "rhythm change", "U-wave peak",
- "learning", "ventricular flutter wave",
- "start of ventricular flutter/fibrillation", "end of ventricular flutter/fibrillation",
- "atrial escape beat", "supraventricular escape beat",
- "link to external data (aux contains URL)", "non-conducted P-wave (blocked APB)",
- "fusion of paced and normal beat", "waveform onset",
- "waveform end", "R-on-T premature ventricular contraction"};
-
+#define ACMAX (49) /* value of largest valid annot code (must be < 50) */
+static char annotdescrlist[52][64]=
+{
+ "not-QRS", /* 0 */
+ "normal beat", /* 1 */
+ "left bundle branch block beat", /* 2 */
+ "right bundle branch block beat", /* 3 */
+ "aberrated atrial premature beat", /* 4 */
+ "premature ventricular contraction", /* 5 */
+ "fusion of ventricular and normal beat", /* 6 */
+ "nodal (junctional) premature beat", /* 7 */
+ "atrial premature contraction", /* 8 */
+ "premature or ectopic supraventricular beat", /* 9 */
+ "ventricular escape beat", /* 10 */
+ "nodal (junctional) escape beat", /* 11 */
+ "paced beat", /* 12 */
+ "unclassifiable beat", /* 13 */
+ "signal quality change", /* 14 */
+ "<empty description>", /* 15 */
+ "isolated QRS-like artifact", /* 16 */
+ "<empty description>", /* 17 */
+ "ST change", /* 18 */
+ "T-wave change", /* 19 */
+ "systole", /* 20 */
+ "diastole", /* 21 */
+ "comment annotation", /* 22 */
+ "measurement annotation", /* 23 */
+ "P-wave peak", /* 24 */
+ "left or right bundle branch block", /* 25 */
+ "non-conducted pacer spike", /* 26 */
+ "T-wave peak", /* 27 */
+ "rhythm change", /* 28 */
+ "U-wave peak", /* 29 */
+ "learning", /* 30 */
+ "ventricular flutter wave", /* 31 */
+ "start of ventricular flutter/fibrillation", /* 32 */
+ "end of ventricular flutter/fibrillation", /* 33 */
+ "atrial escape beat", /* 34 */
+ "supraventricular escape beat", /* 35 */
+ "link to external data (aux contains URL)", /* 36 */
+ "non-conducted P-wave (blocked APB)", /* 37 */
+ "fusion of paced and normal beat", /* 38 */
+ "waveform onset", /* 39 */
+ "waveform end", /* 40 */
+ "R-on-T premature ventricular contraction", /* 41 */
+ "<empty description>", /* 42 */
+ "<empty description>", /* 43 */
+ "<empty description>", /* 44 */
+ "<empty description>", /* 45 */
+ "<empty description>", /* 46 */
+ "<empty description>", /* 47 */
+ "<empty description>", /* 48 */
+ "<empty description>", /* 49 */
+ "<empty description>", /* 50 */
+ "<empty description>" /* 51 */
+};
+
+
+
+#define ANNOT_EXT_NUM (10)
#define ANNOT_EXT_STR_LEN (16)
-static char annotextlist[][ANNOT_EXT_STR_LEN]=
- {
- ".ari",
- ".ecg",
- ".trigger",
- ".qrs",
- ".atr",
- ".apn",
- ".st",
- ".pwave",
- ".marker",
- };
+static char annotextlist[ANNOT_EXT_NUM][ANNOT_EXT_STR_LEN]=
+{
+ ".ari",
+ ".ecg",
+ ".trigger",
+ ".qrs",
+ ".atr",
+ ".apn",
+ ".st",
+ ".pwave",
+ ".marker",
+ ".seizures",
+};
-#define ANNOT_EXT_CNT ((int)(sizeof(annotextlist) / sizeof(char[ANNOT_EXT_STR_LEN])))
UI_MIT2EDFwindow::UI_MIT2EDFwindow(QWidget *w_parent, char *recent_dir, char *save_dir)
@@ -1190,7 +1225,7 @@ OUT1:
get_filename_from_path(filename_x, annot_filename, MAX_PATH_LENGTH);
- for(k=0; k<ANNOT_EXT_CNT; k++)
+ for(k=0; k<ANNOT_EXT_NUM; k++)
{
tc = 0LL;
=====================================
doc/manual.html
=====================================
@@ -21,7 +21,7 @@
</style>
</head><body>
-<h1>EDFbrowser 1.96 manual</h1>
+<h1>EDFbrowser 1.97 manual</h1>
<p><br></p>
@@ -643,8 +643,16 @@
When using the <a href="#Annotation_editor">Annotation editor</a>, the hypnogram will be updated realtime when adding, moving or deleting annotations.<br>
<br>
You can select whether you want the hypnogram draws from onset to the next onset or according to the duration of the annotation.<br>
+ (check or uncheck "Use annotations' duration for epoch length")<br>
When you select the latter, any gaps / overlaps between consegutive annotations greater than 0.1 second will be highlighted red in order<br>
- to assist you with scoring the file.
+ to assist you with scoring the file.<br>
+ <br>
+ In addition, there's the possibility to create colored overlays using user defined annotations.<br>
+ Simply check the option "Add overlays" and insert the annotation(s). Click on the colored buttons in order to modify<br>
+ the color. The transparency of the overlay color is set using the alpha channel: 0 = completely transparent, 255 is completely opaque.<br>
+ The default value for the alpha channel is 32.<br>
+ <br>
+ Right-click on the hypnogram and select "close" in order to close it.
</p>
<p><br></p>
=====================================
global.h
=====================================
@@ -67,7 +67,7 @@
#endif
#define PROGRAM_NAME "EDFbrowser"
-#define PROGRAM_VERSION "1.96"
+#define PROGRAM_VERSION "1.97"
#define PROGRAM_BETA_SUFFIX ""
#define MINIMUM_QT4_VERSION (0x040701)
#define MINIMUM_QT5_VERSION (0x050901)
=====================================
hypnogram_dialog.cpp
=====================================
@@ -44,7 +44,14 @@ UI_hypnogram_window::UI_hypnogram_window(QWidget *w_parent, struct edfhdrblock *
QHBoxLayout *hlayout_tmp=NULL;
- myobjectDialog->setMinimumSize(400 * mainwindow->w_scaling, 400 * mainwindow->h_scaling);
+ if(mainwindow->hypnogram_use_overlays)
+ {
+ myobjectDialog->setMinimumSize(400 * mainwindow->w_scaling, 700 * mainwindow->h_scaling);
+ }
+ else
+ {
+ myobjectDialog->setMinimumSize(400 * mainwindow->w_scaling, 400 * mainwindow->h_scaling);
+ }
myobjectDialog->setWindowTitle("Hypnogram");
myobjectDialog->setModal(true);
myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true);
@@ -84,6 +91,38 @@ UI_hypnogram_window::UI_hypnogram_window(QWidget *w_parent, struct edfhdrblock *
annot6_edit = new QLineEdit;
annot6_edit->setToolTip("The annotation that will be mapped to the label in the left column");
+ annot1_ov_edit = new QLineEdit;
+ annot1_ov_edit->setToolTip("The annotation that will be used for the overlay");
+ annot2_ov_edit = new QLineEdit;
+ annot2_ov_edit->setToolTip("The annotation that will be used for the overlay");
+ annot3_ov_edit = new QLineEdit;
+ annot3_ov_edit->setToolTip("The annotation that will be used for the overlay");
+ annot4_ov_edit = new QLineEdit;
+ annot4_ov_edit->setToolTip("The annotation that will be used for the overlay");
+ annot5_ov_edit = new QLineEdit;
+ annot5_ov_edit->setToolTip("The annotation that will be used for the overlay");
+ annot6_ov_edit = new QLineEdit;
+ annot6_ov_edit->setToolTip("The annotation that will be used for the overlay");
+
+ ov_color_button1 = new SpecialButton;
+ ov_color_button1->setColor(mainwindow->hypnogram_annot_ov_color[0]);
+ ov_color_button1->setToolTip("Click to change the overlay color");
+ ov_color_button2 = new SpecialButton;
+ ov_color_button2->setColor(mainwindow->hypnogram_annot_ov_color[1]);
+ ov_color_button2->setToolTip("Click to change the overlay color");
+ ov_color_button3 = new SpecialButton;
+ ov_color_button3->setColor(mainwindow->hypnogram_annot_ov_color[2]);
+ ov_color_button3->setToolTip("Click to change the overlay color");
+ ov_color_button4 = new SpecialButton;
+ ov_color_button4->setColor(mainwindow->hypnogram_annot_ov_color[3]);
+ ov_color_button4->setToolTip("Click to change the overlay color");
+ ov_color_button5 = new SpecialButton;
+ ov_color_button5->setColor(mainwindow->hypnogram_annot_ov_color[4]);
+ ov_color_button5->setToolTip("Click to change the overlay color");
+ ov_color_button6 = new SpecialButton;
+ ov_color_button6->setColor(mainwindow->hypnogram_annot_ov_color[5]);
+ ov_color_button6->setToolTip("Click to change the overlay color");
+
close_button = new QPushButton;
close_button->setText("Close");
@@ -107,6 +146,13 @@ UI_hypnogram_window::UI_hypnogram_window(QWidget *w_parent, struct edfhdrblock *
annot5_edit->setText(mainwindow->hypnogram_annot_name[4]);
annot6_edit->setText(mainwindow->hypnogram_annot_name[5]);
+ annot1_ov_edit->setText(mainwindow->hypnogram_annot_ov_name[0]);
+ annot2_ov_edit->setText(mainwindow->hypnogram_annot_ov_name[1]);
+ annot3_ov_edit->setText(mainwindow->hypnogram_annot_ov_name[2]);
+ annot4_ov_edit->setText(mainwindow->hypnogram_annot_ov_name[3]);
+ annot5_ov_edit->setText(mainwindow->hypnogram_annot_ov_name[4]);
+ annot6_ov_edit->setText(mainwindow->hypnogram_annot_ov_name[5]);
+
QVBoxLayout *vlayout2 = new QVBoxLayout;
vlayout2->addWidget(stage_label);
vlayout2->addWidget(stage1_edit);
@@ -157,6 +203,87 @@ UI_hypnogram_window::UI_hypnogram_window(QWidget *w_parent, struct edfhdrblock *
"If disabled, it will draw from onset to the next onset.");
QObject::connect(use_epoch_len_checkbox, SIGNAL(stateChanged(int)), this, SLOT(use_epoch_len_checkbox_changed(int)));
+ use_overlays_checkbox = new QCheckBox;
+ use_overlays_checkbox->setTristate(false);
+ if(mainwindow->hypnogram_use_overlays)
+ {
+ use_overlays_checkbox->setCheckState(Qt::Checked);
+ }
+ else
+ {
+ use_overlays_checkbox->setCheckState(Qt::Unchecked);
+ }
+ hlayout_tmp = new QHBoxLayout;
+ hlayout_tmp->setAlignment(Qt::AlignCenter);
+ hlayout_tmp->addWidget(use_overlays_checkbox);
+ hlayout_tmp->addStretch(1000);
+ flayout1->addRow("Add overlays", hlayout_tmp);
+ QObject::connect(use_overlays_checkbox, SIGNAL(stateChanged(int)), this, SLOT(use_overlays_checkbox_changed(int)));
+
+ QFormLayout *flayout2 = new QFormLayout;
+ flayout2->setSpacing(20);
+
+ flayout2->addRow(" ", (QWidget *)NULL);
+
+ hlayout_tmp = new QHBoxLayout;
+ hlayout_tmp->setAlignment(Qt::AlignCenter);
+ hlayout_tmp->addWidget(annot1_ov_edit);
+ hlayout_tmp->addStretch(100);
+ hlayout_tmp->addWidget(ov_color_button1);
+ hlayout_tmp->addStretch(1000);
+ flayout2->addRow("Overlay", hlayout_tmp);
+
+ hlayout_tmp = new QHBoxLayout;
+ hlayout_tmp->setAlignment(Qt::AlignCenter);
+ hlayout_tmp->addWidget(annot2_ov_edit);
+ hlayout_tmp->addStretch(100);
+ hlayout_tmp->addWidget(ov_color_button2);
+ hlayout_tmp->addStretch(1000);
+ flayout2->addRow("Overlay", hlayout_tmp);
+
+ hlayout_tmp = new QHBoxLayout;
+ hlayout_tmp->setAlignment(Qt::AlignCenter);
+ hlayout_tmp->addWidget(annot3_ov_edit);
+ hlayout_tmp->addStretch(100);
+ hlayout_tmp->addWidget(ov_color_button3);
+ hlayout_tmp->addStretch(1000);
+ flayout2->addRow("Overlay", hlayout_tmp);
+
+ hlayout_tmp = new QHBoxLayout;
+ hlayout_tmp->setAlignment(Qt::AlignCenter);
+ hlayout_tmp->addWidget(annot4_ov_edit);
+ hlayout_tmp->addStretch(100);
+ hlayout_tmp->addWidget(ov_color_button4);
+ hlayout_tmp->addStretch(1000);
+ flayout2->addRow("Overlay", hlayout_tmp);
+
+ hlayout_tmp = new QHBoxLayout;
+ hlayout_tmp->setAlignment(Qt::AlignCenter);
+ hlayout_tmp->addWidget(annot5_ov_edit);
+ hlayout_tmp->addStretch(100);
+ hlayout_tmp->addWidget(ov_color_button5);
+ hlayout_tmp->addStretch(1000);
+ flayout2->addRow("Overlay", hlayout_tmp);
+
+ hlayout_tmp = new QHBoxLayout;
+ hlayout_tmp->setAlignment(Qt::AlignCenter);
+ hlayout_tmp->addWidget(annot6_ov_edit);
+ hlayout_tmp->addStretch(100);
+ hlayout_tmp->addWidget(ov_color_button6);
+ hlayout_tmp->addStretch(1000);
+ flayout2->addRow("Overlay", hlayout_tmp);
+
+ flayout2widget = new QWidget;
+ flayout2widget->setLayout(flayout2);
+ if(mainwindow->hypnogram_use_overlays)
+ {
+ flayout2widget->setVisible(true);
+ }
+ else
+ {
+ flayout2widget->setVisible(false);
+ }
+
QHBoxLayout *hlayout1 = new QHBoxLayout;
hlayout1->addWidget(close_button);
hlayout1->addStretch(1000);
@@ -167,20 +294,50 @@ UI_hypnogram_window::UI_hypnogram_window(QWidget *w_parent, struct edfhdrblock *
QVBoxLayout *vlayout1 = new QVBoxLayout;
vlayout1->addLayout(hlayout2);
vlayout1->addLayout(flayout1);
+ vlayout1->addWidget(flayout2widget);
vlayout1->addStretch(1000);
- vlayout1->addSpacing(20);
+ vlayout1->addSpacing(30);
vlayout1->addLayout(hlayout1);
myobjectDialog->setLayout(vlayout1);
- QObject::connect(close_button, SIGNAL(clicked()), myobjectDialog, SLOT(close()));
- QObject::connect(default_button, SIGNAL(clicked()), this, SLOT(default_button_clicked()));
- QObject::connect(start_button, SIGNAL(clicked()), this, SLOT(start_button_clicked()));
+ QObject::connect(close_button, SIGNAL(clicked()), myobjectDialog, SLOT(close()));
+ QObject::connect(default_button, SIGNAL(clicked()), this, SLOT(default_button_clicked()));
+ QObject::connect(start_button, SIGNAL(clicked()), this, SLOT(start_button_clicked()));
+ QObject::connect(ov_color_button1, SIGNAL(clicked(SpecialButton *)), this, SLOT(ov_color_button1_clicked(SpecialButton *)));
+ QObject::connect(ov_color_button2, SIGNAL(clicked(SpecialButton *)), this, SLOT(ov_color_button2_clicked(SpecialButton *)));
+ QObject::connect(ov_color_button3, SIGNAL(clicked(SpecialButton *)), this, SLOT(ov_color_button3_clicked(SpecialButton *)));
+ QObject::connect(ov_color_button4, SIGNAL(clicked(SpecialButton *)), this, SLOT(ov_color_button4_clicked(SpecialButton *)));
+ QObject::connect(ov_color_button5, SIGNAL(clicked(SpecialButton *)), this, SLOT(ov_color_button5_clicked(SpecialButton *)));
+ QObject::connect(ov_color_button6, SIGNAL(clicked(SpecialButton *)), this, SLOT(ov_color_button6_clicked(SpecialButton *)));
myobjectDialog->exec();
}
+void UI_hypnogram_window::use_overlays_checkbox_changed(int state)
+{
+ if(state==Qt::Checked)
+ {
+ mainwindow->hypnogram_use_overlays = 1;
+
+ flayout2widget->setVisible(true);
+
+ myobjectDialog->setMinimumSize(400 * mainwindow->w_scaling, 700 * mainwindow->h_scaling);
+ }
+ else
+ {
+ mainwindow->hypnogram_use_overlays = 0;
+
+ flayout2widget->setVisible(false);
+
+ myobjectDialog->setMinimumSize(400 * mainwindow->w_scaling, 400 * mainwindow->h_scaling);
+ }
+
+ myobjectDialog->adjustSize();
+}
+
+
void UI_hypnogram_window::use_epoch_len_checkbox_changed(int state)
{
if(state==Qt::Checked)
@@ -209,6 +366,22 @@ void UI_hypnogram_window::default_button_clicked()
annot4_edit->setText("N2");
annot5_edit->setText("N3");
annot6_edit->setText("N4");
+
+ annot1_ov_edit->clear();
+ annot2_ov_edit->clear();
+ annot3_ov_edit->clear();
+ annot4_ov_edit->clear();
+ annot5_ov_edit->clear();
+ annot6_ov_edit->clear();
+
+ ov_color_button1->setColor(QColor(0, 128, 0, 32));
+ ov_color_button2->setColor(QColor(0, 0, 128, 32));
+ ov_color_button3->setColor(QColor(128, 128, 0, 32));
+ ov_color_button4->setColor(QColor(128, 0, 128, 32));
+ ov_color_button5->setColor(QColor(0, 64, 192, 32));
+ ov_color_button6->setColor(QColor(128, 192, 64, 32));
+
+ use_overlays_checkbox->setCheckState(Qt::Unchecked);
}
@@ -226,12 +399,12 @@ void UI_hypnogram_window::start_button_clicked()
dock_param.mainwindow = mainwindow;
- strlcpy(dock_param.stage_name[0], stage1_edit->text().toLatin1().data(), 32);
- strlcpy(dock_param.stage_name[1], stage2_edit->text().toLatin1().data(), 32);
- strlcpy(dock_param.stage_name[2], stage3_edit->text().toLatin1().data(), 32);
- strlcpy(dock_param.stage_name[3], stage4_edit->text().toLatin1().data(), 32);
- strlcpy(dock_param.stage_name[4], stage5_edit->text().toLatin1().data(), 32);
- strlcpy(dock_param.stage_name[5], stage6_edit->text().toLatin1().data(), 32);
+ strlcpy(dock_param.stage_name[0], stage1_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.stage_name[1], stage2_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.stage_name[2], stage3_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.stage_name[3], stage4_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.stage_name[4], stage5_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.stage_name[5], stage6_edit->text().toUtf8().data(), 32);
for(i=0; i<HYPNOGRAM_STAGENUM; i++)
{
@@ -240,12 +413,12 @@ void UI_hypnogram_window::start_button_clicked()
strlcpy(mainwindow->hypnogram_stage_name[i], dock_param.stage_name[i], 32);
}
- strlcpy(dock_param.annot_name[0], annot1_edit->text().toLatin1().data(), 32);
- strlcpy(dock_param.annot_name[1], annot2_edit->text().toLatin1().data(), 32);
- strlcpy(dock_param.annot_name[2], annot3_edit->text().toLatin1().data(), 32);
- strlcpy(dock_param.annot_name[3], annot4_edit->text().toLatin1().data(), 32);
- strlcpy(dock_param.annot_name[4], annot5_edit->text().toLatin1().data(), 32);
- strlcpy(dock_param.annot_name[5], annot6_edit->text().toLatin1().data(), 32);
+ strlcpy(dock_param.annot_name[0], annot1_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.annot_name[1], annot2_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.annot_name[2], annot3_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.annot_name[3], annot4_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.annot_name[4], annot5_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.annot_name[5], annot6_edit->text().toUtf8().data(), 32);
for(i=0; i<HYPNOGRAM_STAGENUM; i++)
{
@@ -254,6 +427,26 @@ void UI_hypnogram_window::start_button_clicked()
strlcpy(mainwindow->hypnogram_annot_name[i], dock_param.annot_name[i], 32);
}
+ strlcpy(dock_param.annot_ov_name[0], annot1_ov_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.annot_ov_name[1], annot2_ov_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.annot_ov_name[2], annot3_ov_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.annot_ov_name[3], annot4_ov_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.annot_ov_name[4], annot5_ov_edit->text().toUtf8().data(), 32);
+ strlcpy(dock_param.annot_ov_name[5], annot6_ov_edit->text().toUtf8().data(), 32);
+
+ for(i=0; i<HYPNOGRAM_OVNUM; i++)
+ {
+ trim_spaces(dock_param.annot_ov_name[i]);
+
+ strlcpy(mainwindow->hypnogram_annot_ov_name[i], dock_param.annot_ov_name[i], 32);
+
+ dock_param.annot_ov_color[i] = mainwindow->hypnogram_annot_ov_color[i];
+ }
+
+ dock_param.use_epoch_len = mainwindow->hypnogram_use_epoch_len;
+
+ dock_param.use_overlays = mainwindow->hypnogram_use_overlays;
+
mainwindow->hypnogram_dock[instance_num] = new UI_hypnogram_dock(mainwindow, dock_param);
mainwindow->addToolBar(Qt::BottomToolBarArea, mainwindow->hypnogram_dock[instance_num]->hypnogram_dock);
@@ -268,7 +461,82 @@ void UI_hypnogram_window::start_button_clicked()
}
+void UI_hypnogram_window::ov_color_button1_clicked(SpecialButton *b)
+{
+ QColor temp = QColorDialog::getColor(mainwindow->hypnogram_annot_ov_color[0], myobjectDialog, "Select Color", QColorDialog::ShowAlphaChannel);
+
+ if(temp.isValid())
+ {
+ mainwindow->hypnogram_annot_ov_color[0] = temp;
+
+ b->setColor(temp);
+ }
+}
+
+
+void UI_hypnogram_window::ov_color_button2_clicked(SpecialButton *b)
+{
+ QColor temp = QColorDialog::getColor(mainwindow->hypnogram_annot_ov_color[1], myobjectDialog, "Select Color", QColorDialog::ShowAlphaChannel);
+
+ if(temp.isValid())
+ {
+ mainwindow->hypnogram_annot_ov_color[1] = temp;
+
+ b->setColor(temp);
+ }
+}
+
+
+void UI_hypnogram_window::ov_color_button3_clicked(SpecialButton *b)
+{
+ QColor temp = QColorDialog::getColor(mainwindow->hypnogram_annot_ov_color[2], myobjectDialog, "Select Color", QColorDialog::ShowAlphaChannel);
+
+ if(temp.isValid())
+ {
+ mainwindow->hypnogram_annot_ov_color[2] = temp;
+
+ b->setColor(temp);
+ }
+}
+
+
+void UI_hypnogram_window::ov_color_button4_clicked(SpecialButton *b)
+{
+ QColor temp = QColorDialog::getColor(mainwindow->hypnogram_annot_ov_color[3], myobjectDialog, "Select Color", QColorDialog::ShowAlphaChannel);
+
+ if(temp.isValid())
+ {
+ mainwindow->hypnogram_annot_ov_color[3] = temp;
+
+ b->setColor(temp);
+ }
+}
+
+void UI_hypnogram_window::ov_color_button5_clicked(SpecialButton *b)
+{
+ QColor temp = QColorDialog::getColor(mainwindow->hypnogram_annot_ov_color[4], myobjectDialog, "Select Color", QColorDialog::ShowAlphaChannel);
+
+ if(temp.isValid())
+ {
+ mainwindow->hypnogram_annot_ov_color[4] = temp;
+
+ b->setColor(temp);
+ }
+}
+
+
+void UI_hypnogram_window::ov_color_button6_clicked(SpecialButton *b)
+{
+ QColor temp = QColorDialog::getColor(mainwindow->hypnogram_annot_ov_color[5], myobjectDialog, "Select Color", QColorDialog::ShowAlphaChannel);
+
+ if(temp.isValid())
+ {
+ mainwindow->hypnogram_annot_ov_color[5] = temp;
+
+ b->setColor(temp);
+ }
+}
=====================================
hypnogram_dialog.h
=====================================
@@ -38,6 +38,7 @@
#include "mainwindow.h"
#include "utils.h"
#include "hypnogram_dock.h"
+#include "special_button.h"
@@ -75,19 +76,42 @@ private:
*annot3_edit,
*annot4_edit,
*annot5_edit,
- *annot6_edit;
+ *annot6_edit,
+ *annot1_ov_edit,
+ *annot2_ov_edit,
+ *annot3_ov_edit,
+ *annot4_ov_edit,
+ *annot5_ov_edit,
+ *annot6_ov_edit;
QPushButton *close_button,
*start_button,
*default_button;
- QCheckBox *use_epoch_len_checkbox;
+ QCheckBox *use_epoch_len_checkbox,
+ *use_overlays_checkbox;
+
+ SpecialButton *ov_color_button1,
+ *ov_color_button2,
+ *ov_color_button3,
+ *ov_color_button4,
+ *ov_color_button5,
+ *ov_color_button6;
+
+ QWidget *flayout2widget;
private slots:
void start_button_clicked();
void default_button_clicked();
void use_epoch_len_checkbox_changed(int);
+ void use_overlays_checkbox_changed(int);
+ void ov_color_button1_clicked(SpecialButton *);
+ void ov_color_button2_clicked(SpecialButton *);
+ void ov_color_button3_clicked(SpecialButton *);
+ void ov_color_button4_clicked(SpecialButton *);
+ void ov_color_button5_clicked(SpecialButton *);
+ void ov_color_button6_clicked(SpecialButton *);
};
=====================================
hypnogram_dock.cpp
=====================================
@@ -84,14 +84,52 @@ UI_hypnogram_dock::UI_hypnogram_dock(QWidget *w_parent, struct hypnogram_dock_pa
hypnogram_dock = new QToolBar("Hypnogram", mainwindow);
hypnogram_dock->setOrientation(Qt::Horizontal);
hypnogram_dock->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
+ hypnogram_dock->setMinimumWidth(800);
hypnogram_dock->addWidget(frame);
hypnogram_dock->setAttribute(Qt::WA_DeleteOnClose, true);
+ hypnogram_dock->setContextMenuPolicy(Qt::CustomContextMenu);
- QObject::connect(mainwindow, SIGNAL(file_position_changed(long long)), this, SLOT(file_pos_changed(long long)));
- QObject::connect(mainwindow, SIGNAL(file_position_changed(long long)), this, SLOT(file_pos_changed(long long)));
- QObject::connect(hypnogram_dock, SIGNAL(destroyed(QObject *)), this, SLOT(hypnogram_dock_destroyed(QObject *)));
+ context_menu = new QMenu(hypnogram_dock);
+// QAction *settings_act = new QAction("Settings", this);
+ QAction *close_act = new QAction("Close", this);
+// context_menu->addAction(settings_act);
+ context_menu->addAction(close_act);
+
+ QObject::connect(mainwindow, SIGNAL(file_position_changed(long long)), this, SLOT(file_pos_changed(long long)));
+ QObject::connect(mainwindow, SIGNAL(file_position_changed(long long)), this, SLOT(file_pos_changed(long long)));
+ QObject::connect(hypnogram_dock, SIGNAL(destroyed(QObject *)), this, SLOT(hypnogram_dock_destroyed(QObject *)));
+ QObject::connect(hypnogram_dock, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(show_context_menu(QPoint)));
+ QObject::connect(close_act, SIGNAL(triggered(bool)), this, SLOT(close_dock(bool)));
file_pos_changed(0);
+
+// printf("mainwindow: %p\n"
+// "instance_num: %i\n"
+// "use_epoch_len: %i\n"
+// "use_overlay: %i\n"
+// "stage_name[0]: %s\n"
+// "stage_name[1]: %s\n"
+// "stage_name[2]: %s\n"
+// "annot_name[0]: %s\n"
+// "annot_name[1]: %s\n"
+// "annot_name[2]: %s\n"
+// "annot_ov_name[0]: %s\n"
+// "annot_ov_name[1]: %s\n"
+// "annot_ov_name[2]: %s\n",
+// mainwindow,
+// param.instance_num,
+// param.use_epoch_len,
+// param.use_overlays,
+// param.stage_name[0],
+// param.stage_name[1],
+// param.stage_name[2],
+// param.annot_name[0],
+// param.annot_name[1],
+// param.annot_name[2],
+// param.annot_ov_name[0],
+// param.annot_ov_name[1],
+// param.annot_ov_name[2]
+// );
}
@@ -110,6 +148,12 @@ UI_hypnogram_dock::~UI_hypnogram_dock()
}
+void UI_hypnogram_dock::close_dock(bool)
+{
+ delete this;
+}
+
+
void UI_hypnogram_dock::update_curve(void)
{
hypnogram_curve->update();
@@ -131,6 +175,12 @@ void UI_hypnogram_dock::hypnogram_dock_destroyed(QObject *)
}
+void UI_hypnogram_dock::show_context_menu(QPoint)
+{
+ context_menu->exec(QCursor::pos());
+}
+
+
void UI_hypnogram_dock::file_pos_changed(long long)
{
trck_indic->set_position((int)((param.edfhdr->viewtime + (mainwindow->pagetime / 2)) / 10000000LL));
@@ -310,18 +360,17 @@ void hypnogram_curve_widget::set_params(struct hypnogram_dock_param_struct *parm
void hypnogram_curve_widget::paintEvent(QPaintEvent *)
{
- int w, h, i, j, n, pos_x1=0, pos_x2=0, stage=0, tmp1, tmp2;
+ int w, h, i, j, k, n, pos_x1=0, pos_x2=0, stage=0, tmp1, tmp2;
double pixel_per_unit,
pixel_per_sec,
offset;
- long long annot_duration=-1LL,
- annot_end=0LL,
+ long long annot_end=0LL,
prev_annot_end=0x7fffffffffffffffLL,
tdiff=0LL;
- char str[64];
+ char str[64]={""};
struct annotation_list *annot_list;
@@ -359,7 +408,60 @@ void hypnogram_curve_widget::paintEvent(QPaintEvent *)
n = edfplus_annotation_size(annot_list);
- for(i=0; i<n; i++)
+ if(param.use_overlays)
+ {
+ for(i=0, k=0; i<n; i++)
+ {
+ annot = edfplus_annotation_get_item(annot_list, i);
+
+ strlcpy(str, annot->description, 48);
+ trim_spaces(str);
+
+ for(j=0; j<HYPNOGRAM_OVNUM; j++)
+ {
+ if(!strcmp(str, param.annot_ov_name[j]))
+ {
+ pos_x2 = ((double)(annot->onset) * pixel_per_sec) / TIME_DIMENSION;
+
+ if(param.use_epoch_len)
+ {
+ pos_x1 = ((double)(annot->long_duration) * pixel_per_sec) / TIME_DIMENSION;
+
+ painter.fillRect(pos_x2, 0, pos_x1, h, param.annot_ov_color[j]);
+ }
+ else
+ {
+ if(k)
+ {
+ painter.fillRect(pos_x1, 0, pos_x2 - pos_x1, h, param.annot_ov_color[stage]);
+ }
+
+ pos_x1 = pos_x2;
+ }
+
+ stage = j;
+
+ k++;
+
+ break;
+ }
+ }
+ }
+
+ if(!param.use_epoch_len)
+ {
+ if(k)
+ {
+ painter.fillRect(pos_x1, 0, w - pos_x1, h, param.annot_ov_color[stage]);
+ }
+ }
+ }
+
+ pos_x1=0;
+ pos_x2=0;
+ stage=0;
+
+ for(i=0, k=0; i<n; i++)
{
annot = edfplus_annotation_get_item(annot_list, i);
@@ -372,9 +474,7 @@ void hypnogram_curve_widget::paintEvent(QPaintEvent *)
{
pos_x2 = ((double)(annot->onset) * pixel_per_sec) / TIME_DIMENSION;
- annot_duration = annot->long_duration;
-
- if(mainwindow->hypnogram_use_epoch_len)
+ if(param.use_epoch_len)
{
annot_end = annot->onset + annot->long_duration;
@@ -383,21 +483,24 @@ void hypnogram_curve_widget::paintEvent(QPaintEvent *)
painter.drawLine(pos_x1, offset + (j * pixel_per_unit) + 0.5,
pos_x2, offset + (j * pixel_per_unit) + 0.5);
}
- else if(i && (!mainwindow->hypnogram_use_epoch_len))
+ else
+ {
+ if(k)
{
painter.drawLine(pos_x1, offset + (stage * pixel_per_unit) + 0.5,
pos_x2, offset + (stage * pixel_per_unit) + 0.5);
-
- pos_x1 = pos_x2;
}
- if(i)
+ pos_x1 = pos_x2;
+ }
+
+ if(k)
{
painter.drawLine(pos_x2, offset + (stage * pixel_per_unit) + 0.5,
pos_x2, offset + (j * pixel_per_unit) + 0.5);
}
- if(mainwindow->hypnogram_use_epoch_len)
+ if(param.use_epoch_len)
{
if(prev_annot_end != 0x7fffffffffffffff)
{
@@ -426,27 +529,19 @@ void hypnogram_curve_widget::paintEvent(QPaintEvent *)
stage = j;
+ k++;
+
break;
}
}
}
- if(!mainwindow->hypnogram_use_epoch_len)
+ if(!param.use_epoch_len)
{
- if(pos_x1)
+ if(k)
{
- if(annot_duration > 0)
- {
- pos_x2 = (((double)annot_duration * pixel_per_sec) / TIME_DIMENSION) + pos_x1;
-
- painter.drawLine(pos_x1, offset + (stage * pixel_per_unit) + 0.5,
- pos_x2, offset + (stage * pixel_per_unit) + 0.5);
- }
- else
- {
- painter.drawLine(pos_x1, offset + (stage * pixel_per_unit) + 0.5,
- w, offset + (stage * pixel_per_unit) + 0.5);
- }
+ painter.drawLine(pos_x1, offset + (stage * pixel_per_unit) + 0.5,
+ w, offset + (stage * pixel_per_unit) + 0.5);
}
}
}
=====================================
hypnogram_dock.h
=====================================
@@ -41,6 +41,7 @@
#define HYPNOGRAM_STAGENUM (6)
+#define HYPNOGRAM_OVNUM (6)
class UI_Mainwindow;
@@ -52,8 +53,12 @@ class hypnogram_curve_widget;
struct hypnogram_dock_param_struct
{
int instance_num;
+ int use_epoch_len;
+ int use_overlays;
char stage_name[HYPNOGRAM_STAGENUM][32];
char annot_name[HYPNOGRAM_STAGENUM][32];
+ char annot_ov_name[HYPNOGRAM_OVNUM][32];
+ QColor annot_ov_color[HYPNOGRAM_OVNUM];
struct edfhdrblock *edfhdr;
UI_Mainwindow *mainwindow;
};
@@ -81,6 +86,8 @@ public slots:
private:
+ QMenu *context_menu;
+
simple_tracking_indicator2 *trck_indic;
simple_ruler_indicator2 *srl_indic;
@@ -93,6 +100,8 @@ private slots:
void file_pos_changed(long long);
void hypnogram_dock_destroyed(QObject *);
+ void close_dock(bool);
+ void show_context_menu(QPoint);
};
=====================================
import_annotations.cpp
=====================================
@@ -37,78 +37,111 @@
#define TAB_CNT (5)
-#define NOTQRS 0 /* not-QRS (not a getann/putann code) */
-#define NORMAL 1 /* normal beat */
-#define LBBB 2 /* left bundle branch block beat */
-#define RBBB 3 /* right bundle branch block beat */
-#define ABERR 4 /* aberrated atrial premature beat */
-#define PVC 5 /* premature ventricular contraction */
-#define FUSION 6 /* fusion of ventricular and normal beat */
-#define NPC 7 /* nodal (junctional) premature beat */
-#define APC 8 /* atrial premature contraction */
-#define SVPB 9 /* premature or ectopic supraventricular beat */
-#define VESC 10 /* ventricular escape beat */
-#define NESC 11 /* nodal (junctional) escape beat */
-#define PACE 12 /* paced beat */
-#define UNKNOWN 13 /* unclassifiable beat */
-#define NOISE 14 /* signal quality change */
-#define ARFCT 16 /* isolated QRS-like artifact */
-#define STCH 18 /* ST change */
-#define TCH 19 /* T-wave change */
-#define SYSTOLE 20 /* systole */
-#define DIASTOLE 21 /* diastole */
-#define NOTE 22 /* comment annotation */
-#define MEASURE 23 /* measurement annotation */
-#define PWAVE 24 /* P-wave peak */
-#define BBB 25 /* left or right bundle branch block */
-#define PACESP 26 /* non-conducted pacer spike */
-#define TWAVE 27 /* T-wave peak */
-#define RHYTHM 28 /* rhythm change */
-#define UWAVE 29 /* U-wave peak */
-#define LEARN 30 /* learning */
-#define FLWAV 31 /* ventricular flutter wave */
-#define VFON 32 /* start of ventricular flutter/fibrillation */
-#define VFOFF 33 /* end of ventricular flutter/fibrillation */
-#define AESC 34 /* atrial escape beat */
-#define SVESC 35 /* supraventricular escape beat */
-#define LINK 36 /* link to external data (aux contains URL) */
-#define NAPC 37 /* non-conducted P-wave (blocked APB) */
-#define PFUS 38 /* fusion of paced and normal beat */
-#define WFON 39 /* waveform onset */
-#define PQ WFON /* PQ junction (beginning of QRS) */
-#define WFOFF 40 /* waveform end */
-#define JPT WFOFF /* J point (end of QRS) */
-#define RONT 41 /* R-on-T premature ventricular contraction */
+#define NOTQRS (0) /* not-QRS (not a getann/putann code) */
+#define NORMAL (1) /* normal beat */
+#define LBBB (2) /* left bundle branch block beat */
+#define RBBB (3) /* right bundle branch block beat */
+#define ABERR (4) /* aberrated atrial premature beat */
+#define PVC (5) /* premature ventricular contraction */
+#define FUSION (6) /* fusion of ventricular and normal beat */
+#define NPC (7) /* nodal (junctional) premature beat */
+#define APC (8) /* atrial premature contraction */
+#define SVPB (9) /* premature or ectopic supraventricular beat */
+#define VESC (10) /* ventricular escape beat */
+#define NESC (11) /* nodal (junctional) escape beat */
+#define PACE (12) /* paced beat */
+#define UNKNOWN (13) /* unclassifiable beat */
+#define NOISE (14) /* signal quality change */
+#define ARFCT (16) /* isolated QRS-like artifact */
+#define STCH (18) /* ST change */
+#define TCH (19) /* T-wave change */
+#define SYSTOLE (20) /* systole */
+#define DIASTOLE (21) /* diastole */
+#define NOTE (22) /* comment annotation */
+#define MEASURE (23) /* measurement annotation */
+#define PWAVE (24) /* P-wave peak */
+#define BBB (25) /* left or right bundle branch block */
+#define PACESP (26) /* non-conducted pacer spike */
+#define TWAVE (27) /* T-wave peak */
+#define RHYTHM (28) /* rhythm change */
+#define UWAVE (29) /* U-wave peak */
+#define LEARN (30) /* learning */
+#define FLWAV (31) /* ventricular flutter wave */
+#define VFON (32) /* start of ventricular flutter/fibrillation */
+#define VFOFF (33) /* end of ventricular flutter/fibrillation */
+#define AESC (34) /* atrial escape beat */
+#define SVESC (35) /* supraventricular escape beat */
+#define LINK (36) /* link to external data (aux contains URL) */
+#define NAPC (37) /* non-conducted P-wave (blocked APB) */
+#define PFUS (38) /* fusion of paced and normal beat */
+#define WFON (39) /* waveform onset */
+#define PQ WFON /* PQ junction (beginning of QRS) */
+#define WFOFF (40) /* waveform end */
+#define JPT WFOFF /* J point (end of QRS) */
+#define RONT (41) /* R-on-T premature ventricular contraction */
/* ... annotation codes between RONT+1 and ACMAX inclusive are user-defined */
-#define ACMAX 49 /* value of largest valid annot code (must be < 50) */
-
-
-static char annotdescrlist[42][64]=
- {"not-QRS","normal beat",
- "left bundle branch block beat", "right bundle branch block beat",
- "aberrated atrial premature beat", "premature ventricular contraction",
- "fusion of ventricular and normal beat", "nodal (junctional) premature beat",
- "atrial premature contraction", "premature or ectopic supraventricular beat",
- "ventricular escape beat", "nodal (junctional) escape beat",
- "paced beat", "unclassifiable beat",
- "signal quality change", "isolated QRS-like artifact",
- "ST change", "T-wave change",
- "systole", "diastole",
- "comment annotation", "measurement annotation",
- "P-wave peak", "left or right bundle branch block",
- "non-conducted pacer spike", "T-wave peak",
- "rhythm change", "U-wave peak",
- "learning", "ventricular flutter wave",
- "start of ventricular flutter/fibrillation", "end of ventricular flutter/fibrillation",
- "atrial escape beat", "supraventricular escape beat",
- "link to external data (aux contains URL)", "non-conducted P-wave (blocked APB)",
- "fusion of paced and normal beat", "waveform onset",
- "waveform end", "R-on-T premature ventricular contraction"};
-
-
-#define ANNOT_EXT_CNT 8
+#define ACMAX (49) /* value of largest valid annot code (must be < 50) */
+
+
+static char annotdescrlist[52][64]=
+{
+ "not-QRS", /* 0 */
+ "normal beat", /* 1 */
+ "left bundle branch block beat", /* 2 */
+ "right bundle branch block beat", /* 3 */
+ "aberrated atrial premature beat", /* 4 */
+ "premature ventricular contraction", /* 5 */
+ "fusion of ventricular and normal beat", /* 6 */
+ "nodal (junctional) premature beat", /* 7 */
+ "atrial premature contraction", /* 8 */
+ "premature or ectopic supraventricular beat", /* 9 */
+ "ventricular escape beat", /* 10 */
+ "nodal (junctional) escape beat", /* 11 */
+ "paced beat", /* 12 */
+ "unclassifiable beat", /* 13 */
+ "signal quality change", /* 14 */
+ "<empty description>", /* 15 */
+ "isolated QRS-like artifact", /* 16 */
+ "<empty description>", /* 17 */
+ "ST change", /* 18 */
+ "T-wave change", /* 19 */
+ "systole", /* 20 */
+ "diastole", /* 21 */
+ "comment annotation", /* 22 */
+ "measurement annotation", /* 23 */
+ "P-wave peak", /* 24 */
+ "left or right bundle branch block", /* 25 */
+ "non-conducted pacer spike", /* 26 */
+ "T-wave peak", /* 27 */
+ "rhythm change", /* 28 */
+ "U-wave peak", /* 29 */
+ "learning", /* 30 */
+ "ventricular flutter wave", /* 31 */
+ "start of ventricular flutter/fibrillation", /* 32 */
+ "end of ventricular flutter/fibrillation", /* 33 */
+ "atrial escape beat", /* 34 */
+ "supraventricular escape beat", /* 35 */
+ "link to external data (aux contains URL)", /* 36 */
+ "non-conducted P-wave (blocked APB)", /* 37 */
+ "fusion of paced and normal beat", /* 38 */
+ "waveform onset", /* 39 */
+ "waveform end", /* 40 */
+ "R-on-T premature ventricular contraction", /* 41 */
+ "<empty description>", /* 42 */
+ "<empty description>", /* 43 */
+ "<empty description>", /* 44 */
+ "<empty description>", /* 45 */
+ "<empty description>", /* 46 */
+ "<empty description>", /* 47 */
+ "<empty description>", /* 48 */
+ "<empty description>", /* 49 */
+ "<empty description>", /* 50 */
+ "<empty description>" /* 51 */
+};
+
+
//#define IMPORT_ANNOTS_DEBUG
@@ -776,7 +809,8 @@ int UI_ImportAnnotationswindow::import_from_mitwfdb(void)
sampletime = TIME_DIMENSION / SampleTimeSpinbox->value();
- strlcpy(path, QFileDialog::getOpenFileName(0, "Open MIT WFDB annotation file", QString::fromLocal8Bit(mainwindow->recent_opendir), "MIT annotation files (*.ari *.ecg *.trigger *.qrs *.atr *.apn *.st *.pwave);;All files (*)").toLocal8Bit().data(), MAX_PATH_LENGTH);
+ strlcpy(path, QFileDialog::getOpenFileName(0, "Open MIT WFDB annotation file", QString::fromLocal8Bit(mainwindow->recent_opendir),
+ "MIT annotation files (*.ari *.ecg *.trigger *.qrs *.atr *.apn *.st *.pwave *.marker *.seizures);;All files (*)").toLocal8Bit().data(), MAX_PATH_LENGTH);
if(!strcmp(path, ""))
{
=====================================
load_session.cpp
=====================================
@@ -2143,6 +2143,42 @@ int UI_Mainwindow::read_session_file(const char *path_session)
xml_go_up(xml_hdl);
}
+ if(!xml_goto_nth_element_inside(xml_hdl, "hypnogram_use_epoch_len", 0))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ return session_format_error(__FILE__, __LINE__, NULL, xml_hdl);
+ }
+
+ hypnogram_param.use_epoch_len = atoi(result);
+ if(hypnogram_param.use_epoch_len != 1)
+ {
+ hypnogram_param.use_epoch_len = 0;
+ }
+
+ hypnogram_use_epoch_len = hypnogram_param.use_epoch_len;
+
+ xml_go_up(xml_hdl);
+ }
+
+ if(!xml_goto_nth_element_inside(xml_hdl, "use_overlays", 0))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ return session_format_error(__FILE__, __LINE__, NULL, xml_hdl);
+ }
+
+ hypnogram_param.use_overlays = atoi(result);
+ if(hypnogram_param.use_overlays != 1)
+ {
+ hypnogram_param.use_overlays = 0;
+ }
+
+ hypnogram_use_overlays = hypnogram_param.use_overlays;
+
+ xml_go_up(xml_hdl);
+ }
+
for(j=0; j<HYPNOGRAM_STAGENUM; j++)
{
if(xml_goto_nth_element_inside(xml_hdl, "stage_name", j))
@@ -2157,6 +2193,8 @@ int UI_Mainwindow::read_session_file(const char *path_session)
strlcpy(hypnogram_param.stage_name[j], result, 32);
+ strlcpy(hypnogram_stage_name[j], hypnogram_param.stage_name[j], 32);
+
xml_go_up(xml_hdl);
}
@@ -2174,9 +2212,37 @@ int UI_Mainwindow::read_session_file(const char *path_session)
strlcpy(hypnogram_param.annot_name[j], result, 32);
+ strlcpy(hypnogram_annot_name[j], hypnogram_param.annot_name[j], 32);
+
xml_go_up(xml_hdl);
}
+ for(j=0; j<HYPNOGRAM_OVNUM; j++)
+ {
+ if(!xml_goto_nth_element_inside(xml_hdl, "annot_ov_name", j))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ return session_format_error(__FILE__, __LINE__, NULL, xml_hdl);
+ }
+
+ strlcpy(hypnogram_param.annot_ov_name[j], result, 32);
+
+ strlcpy(hypnogram_annot_ov_name[j], hypnogram_param.annot_ov_name[j], 32);
+
+ xml_go_up(xml_hdl);
+ }
+ }
+
+ for(j=0; j<HYPNOGRAM_OVNUM; j++)
+ {
+ get_rgbcolor_settings(xml_hdl, "annot_ov_color", j, &hypnogram_param.annot_ov_color[j]);
+
+ hypnogram_annot_ov_color[j] = hypnogram_param.annot_ov_color[j] ;
+ }
+
+ hypnogram_param.mainwindow = this;
+
hypnogram_dock[hypnogram_param.instance_num] = new UI_hypnogram_dock(this, hypnogram_param);
addToolBar(Qt::BottomToolBarArea, hypnogram_dock[hypnogram_param.instance_num]->hypnogram_dock);
=====================================
mainwindow.cpp
=====================================
@@ -833,6 +833,31 @@ void UI_Mainwindow::save_session()
fprintf(pro_file, "</annot_name>\n");
}
+ for(j=0; j<HYPNOGRAM_OVNUM; j++)
+ {
+ fprintf(pro_file, " <annot_ov_name>");
+ xml_fwrite_encode_entity(pro_file, hypnogram_dock[i]->param.annot_ov_name[j]);
+ fprintf(pro_file, "</annot_ov_name>\n");
+ }
+
+ for(j=0; j<HYPNOGRAM_OVNUM; j++)
+ {
+ fprintf(pro_file, " <annot_ov_color>\n"
+ " <red>%i</red>\n"
+ " <green>%i</green>\n"
+ " <blue>%i</blue>\n"
+ " <alpha>%i</alpha>\n"
+ " </annot_ov_color>\n",
+ hypnogram_dock[i]->param.annot_ov_color[j].red(),
+ hypnogram_dock[i]->param.annot_ov_color[j].green(),
+ hypnogram_dock[i]->param.annot_ov_color[j].blue(),
+ hypnogram_dock[i]->param.annot_ov_color[j].alpha());
+ }
+
+ fprintf(pro_file, " <hypnogram_use_epoch_len>%i</hypnogram_use_epoch_len>\n", hypnogram_dock[i]->param.use_epoch_len);
+
+ fprintf(pro_file, " <use_overlays>%i</use_overlays>\n", hypnogram_dock[i]->param.use_overlays);
+
fprintf(pro_file, " <hdr_idx>%i</hdr_idx>\n", hdr_idx);
fprintf(pro_file, " </hypnogram>\n");
=====================================
mainwindow.h
=====================================
@@ -265,6 +265,7 @@ public:
annot_editor_user_button_stay_on_epoch_boundary,
channel_linked_annotations,
hypnogram_use_epoch_len,
+ hypnogram_use_overlays,
dig_min_max_overflow,
dig_min_max_overflow_warning_showed,
options_dialog_idx,
@@ -302,7 +303,8 @@ long long annot_editor_user_button_epoch_len,
last_check_for_updates_time;
QColor hrvdock_trace_color,
- annot_list_edited_txt_color;
+ annot_list_edited_txt_color,
+ hypnogram_annot_ov_color[6];
unsigned long long pagetime,
maxfilesize_to_readin_annotations,
@@ -325,6 +327,7 @@ long long annot_editor_user_button_epoch_len,
drop_path[MAX_PATH_LENGTH],
hypnogram_stage_name[6][32],
hypnogram_annot_name[6][32],
+ hypnogram_annot_ov_name[6][32],
ecg_qrs_rpeak_descr[32],
annot_edit_user_button_name[8][64],
annot_by_rect_draw_description[MAX_ANNOTEDIT_SIDE_MENU_ANNOTS][32];
=====================================
mainwindow_constr.cpp
=====================================
@@ -154,6 +154,8 @@ UI_Mainwindow::UI_Mainwindow()
hypnogram_use_epoch_len = 0;
+ hypnogram_use_overlays = 0;
+
channel_linked_annotations = 1;
use_diverse_signal_colors = 1;
@@ -402,6 +404,18 @@ UI_Mainwindow::UI_Mainwindow()
strlcpy(hypnogram_annot_name[4], "N3", 32);
strlcpy(hypnogram_annot_name[5], "N4", 32);
+ for(i=0; i<6; i++)
+ {
+ hypnogram_annot_ov_name[i][0] = 0;
+ }
+
+ hypnogram_annot_ov_color[0] = QColor(0, 128, 0, 32);
+ hypnogram_annot_ov_color[1] = QColor(0, 0, 128, 32);
+ hypnogram_annot_ov_color[2] = QColor(128, 128, 0, 32);
+ hypnogram_annot_ov_color[3] = QColor(128, 0, 128, 32);
+ hypnogram_annot_ov_color[4] = QColor(0, 64, 192, 32);
+ hypnogram_annot_ov_color[5] = QColor(128, 192, 64, 32);
+
strlcpy(ecg_qrs_rpeak_descr, "R-peak", 32);
use_signallabel_in_annot_descr = 1;
=====================================
read_write_settings.cpp
=====================================
@@ -2001,6 +2001,27 @@ void UI_Mainwindow::read_general_settings()
}
}
+ for(i=0; i<6; i++)
+ {
+ if(!(xml_goto_nth_element_inside(xml_hdl, "annot_ov_name", i)))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ xml_close(xml_hdl);
+ return;
+ }
+
+ strlcpy(hypnogram_annot_ov_name[i], result, 32);
+
+ xml_go_up(xml_hdl);
+ }
+ }
+
+ for(i=0; i<6; i++)
+ {
+ get_rgbcolor_settings(xml_hdl, "annot_ov_color", i, &hypnogram_annot_ov_color[i]);
+ }
+
if(!(xml_goto_nth_element_inside(xml_hdl, "hypnogram_use_epoch_len", 0)))
{
if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
@@ -2018,6 +2039,23 @@ void UI_Mainwindow::read_general_settings()
xml_go_up(xml_hdl);
}
+ if(!(xml_goto_nth_element_inside(xml_hdl, "use_overlays", 0)))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ xml_close(xml_hdl);
+ return;
+ }
+
+ hypnogram_use_overlays = atoi(result);
+ if(hypnogram_use_overlays != 1)
+ {
+ hypnogram_use_overlays = 0;
+ }
+
+ xml_go_up(xml_hdl);
+ }
+
xml_go_up(xml_hdl);
}
@@ -3467,7 +3505,27 @@ void UI_Mainwindow::write_settings()
fprintf(cfgfile, " <annot_name>%s</annot_name>\n", str);
}
+ for(i=0; i<6; i++)
+ {
+ xml_strlcpy_encode_entity(str, hypnogram_annot_ov_name[i], 1024);
+
+ fprintf(cfgfile, " <annot_ov_name>%s</annot_ov_name>\n", str);
+ }
+ for(i=0; i<6; i++)
+ {
+ fprintf(cfgfile, " <annot_ov_color>\n"
+ " <red>%i</red>\n"
+ " <green>%i</green>\n"
+ " <blue>%i</blue>\n"
+ " <alpha>%i</alpha>\n"
+ " </annot_ov_color>\n",
+ hypnogram_annot_ov_color[i].red(),
+ hypnogram_annot_ov_color[i].green(),
+ hypnogram_annot_ov_color[i].blue(),
+ hypnogram_annot_ov_color[i].alpha());
+ }
fprintf(cfgfile, " <hypnogram_use_epoch_len>%i</hypnogram_use_epoch_len>\n", hypnogram_use_epoch_len);
+ fprintf(cfgfile, " <use_overlays>%i</use_overlays>\n", hypnogram_use_overlays);
fprintf(cfgfile, " </hypnogram>\n");
fprintf(cfgfile, " <ecg_qrs>\n");
=====================================
special_button.cpp
=====================================
@@ -76,7 +76,7 @@ void SpecialButton::paintEvent(QPaintEvent *)
}
-int SpecialButton::heightForWidth(int w)
+int SpecialButton::heightForWidth(int w) const
{
return w;
}
=====================================
special_button.h
=====================================
@@ -49,6 +49,7 @@ public:
QSize sizeHint() const {return minimumSizeHint(); }
QSize minimumSizeHint() const;
+ int heightForWidth(int) const;
public slots:
void setColor(QColor);
@@ -56,7 +57,6 @@ public slots:
void setGlobalColor(int);
int globalColor();
void setText(const char *);
- int heightForWidth(int);
protected:
void paintEvent(QPaintEvent *);
=====================================
third_party/fidlib/fidrf_cmdlist.h
=====================================
@@ -261,7 +261,11 @@ fid_run_new(FidFilter *filt, double (**funcpp)(void *,double)) {
filt= FFNEXT(filt);
}
} else
+ {
error("Internal error: fid_run_new can only handle IIR + FIR types");
+ n_iir = 0;
+ n_fir = 0;
+ }
// Okay, we now have an IIR/FIR pair to process, possibly with
// n_iir or n_fir == 0 if one half is missing
=====================================
utils.c
=====================================
@@ -2292,6 +2292,53 @@ int strlcat(char *dst, const char *src, int sz)
#endif
+void remove_leading_chars(char *str, int n)
+{
+ int i, len;
+
+ if(str == NULL) return;
+
+ if(n < 1) return;
+
+ len = strlen(str);
+
+ if(n >= len)
+ {
+ str[0] = 0;
+
+ return;
+ }
+
+ for(i=0; i<(len-n); i++)
+ {
+ str[i] = str[i + n];
+ }
+
+ str[i] = 0;
+}
+
+
+void remove_trailing_chars(char *str, int n)
+{
+ int len;
+
+ if(str == NULL) return;
+
+ if(n < 1) return;
+
+ len = strlen(str);
+
+ if(n >= len)
+ {
+ str[0] = 0;
+
+ return;
+ }
+
+ str[len - n] = 0;
+}
+
+
void str_insert_substr(char *str, int pos, int len, const char *substr, int subpos, int sublen)
{
int i, slen;
=====================================
utils.h
=====================================
@@ -48,6 +48,8 @@ void trim_spaces(char *);
/* removes trailing zero's from one or more occurrences of a decimal fraction in a string */
void remove_trailing_zeros(char *);
void convert_trailing_zeros_to_spaces(char *);
+void remove_leading_chars(char *, int);
+void remove_trailing_chars(char *, int);
/* Inserts a copy of substr into str. The substring is the portion of substr that begins at */
/* the character position subpos and spans sublen characters (or until the end of substr */
=====================================
version.txt
=====================================
@@ -1,4 +1,20 @@
+ version 1.97 November 19, 2022
+ --------------
+
+ - Mit to EDF+ converter: fixed a bug in the annotation description list..
+
+ - Import annotations tool: MIT/WFDB: fixed a bug in the annotation description list.
+
+ - Fixed compiler warnings on MacOS.
+
+ - Hypnogram: fixed a bug that caused the hypnogram to be empty when it was loaded from
+ a session file.
+
+ - Hypnogram: added the possibility to show user defined annotations using colored
+ overlays in the hypnogram.
+
+
version 1.96 October 15, 2022
--------------
=====================================
videoplayer.cpp
=====================================
@@ -211,7 +211,7 @@ void UI_Mainwindow::start_stop_video()
#else
arguments << "-I" << "rc" << "--rc-host" << str << "--video-on-top" << "--width" << "150" << "--height" << "150" << "--ignore-config";
-#ifdef Q_OS_MAC
+#ifdef Q_OS_MACOS
video_process->start("/Applications/VLC.app/Contents/MacOS/VLC", arguments);
#else
video_process->start("vlc", arguments);
@@ -329,7 +329,7 @@ void UI_Mainwindow::start_stop_video()
" or\n "
" \n C:\\Program Files (x86)\\VideoLAN\\VLC\\\n ");
#else
-#ifdef Q_OS_MAC
+#ifdef Q_OS_MACOS
msgbox.setText(" \n Cannot start the video player. \n "
" \n Check if VLC is installed in /Applications/. \n ");
#else
View it on GitLab: https://salsa.debian.org/med-team/edfbrowser/-/commit/59fae14f18536b05ce8aa63466184bb1fdefb71f
--
View it on GitLab: https://salsa.debian.org/med-team/edfbrowser/-/commit/59fae14f18536b05ce8aa63466184bb1fdefb71f
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20221129/d223b440/attachment-0001.htm>
More information about the debian-med-commit
mailing list