Clean up and automate Event Flags initialization, add tooltips

This commit is contained in:
Mark Watkins 2014-08-07 05:49:05 +10:00
parent 6913da8e69
commit 3dc74a3231
6 changed files with 172 additions and 68 deletions

View File

@ -57,33 +57,110 @@ qint64 gFlagsGroup::Maxx()
void gFlagsGroup::SetDay(Day *d) void gFlagsGroup::SetDay(Day *d)
{ {
LayerGroup::SetDay(d); LayerGroup::SetDay(d);
lvisible.clear();
int cnt = 0; int cnt = 0;
for (int i = 0; i < layers.size(); i++) { if (!d) {
gFlagsLine *f = dynamic_cast<gFlagsLine *>(layers[i]); m_empty = true;
return;
}
QHash<ChannelID, schema::Channel *> chans;
if (!f) { continue; } schema::channel[CPAP_CSR].setOrder(1);
schema::channel[CPAP_CSR].setOrder(1);
schema::channel[CPAP_Ramp].setOrder(2);
schema::channel[CPAP_LargeLeak].setOrder(2);
schema::channel[CPAP_ClearAirway].setOrder(3);
schema::channel[CPAP_Obstructive].setOrder(4);
schema::channel[CPAP_Apnea].setOrder(4);
schema::channel[CPAP_NRI].setOrder(3);
schema::channel[CPAP_Hypopnea].setOrder(5);
schema::channel[CPAP_FlowLimit].setOrder(6);
schema::channel[CPAP_RERA].setOrder(6);
schema::channel[CPAP_VSnore].setOrder(7);
schema::channel[CPAP_VSnore2].setOrder(8);
schema::channel[CPAP_ExP].setOrder(6);
bool e = f->isEmpty(); alwaysVisible(CPAP_LargeLeak);
alwaysVisible(CPAP_Hypopnea);
alwaysVisible(CPAP_Obstructive);
if (!e || f->isAlwaysVisible()) {
lvisible.push_back(f);
if (!e) { for (int i=0; i< m_day->size(); ++i) {
cnt++; Session * sess = m_day->sessions.at(i);
QHash<ChannelID, QVector<EventList *> >::iterator it;
for (it = sess->eventlist.begin(); it != sess->eventlist.end(); ++it) {
ChannelID code = it.key();
if (chans.contains(code)) continue;
schema::Channel * chan = &schema::channel[code];
if (chan->type() == schema::FLAG) {
chans[code] = chan;
} else if (chan->type() == schema::MINOR_FLAG) {
// chans[code] = chan;
} else if (chan->type() == schema::SPAN) {
chans[code] = chan;
} }
} }
} }
m_empty = (cnt == 0); for (int i=0; i < m_alwaysvisible.size(); ++i) {
ChannelID code = m_alwaysvisible.at(i);
if (m_empty) { if (!chans.contains(code)) {
if (d) { schema::Channel * chan = &schema::channel[code];
m_empty = !d->channelExists(CPAP_Pressure); chans[code] = chan;
} }
} }
QMultiMap<int, schema::Channel *> order;
QHash<ChannelID, schema::Channel *>::iterator cit;
for (cit = chans.begin(); cit != chans.end(); ++cit) {
int ord = schema::channel[cit.key()].order();
order.insert(ord, cit.value());
}
QMultiMap<int, schema::Channel *>::iterator it;
for (int i=0;i <lvisible.size(); i++) {
delete lvisible.at(i);
}
lvisible.clear();
for (it = order.begin(); it != order.end(); ++it) {
schema::Channel * chan = it.value();
gFlagsLine * fl = new gFlagsLine(chan->id());
fl->SetDay(d);
lvisible.push_back(fl);
}
cnt = lvisible.size();
// for (int i = 0; i < layers.size(); i++) {
// gFlagsLine *f = dynamic_cast<gFlagsLine *>(layers[i]);
// if (!f) { continue; }
// bool e = f->isEmpty();
// if (!e || f->isAlwaysVisible()) {
// lvisible.push_back(f);
// if (!e) {
// cnt++;
// }
// }
// }
m_empty = (cnt == 0);
// if (m_empty) {
// if (d) {
// m_empty = !d->channelExists(CPAP_Pressure);
// }
// }
m_barh = 0; m_barh = 0;
} }
@ -98,13 +175,21 @@ void gFlagsGroup::paint(QPainter &painter, gGraph &g, const QRegion &region)
if (!m_day) { return; } if (!m_day) { return; }
int vis = lvisible.size();
QVector<gFlagsLine *> visflags;
for (int i = 0; i < lvisible.size(); i++) {
if (schema::channel[lvisible.at(i)->code()].enabled())
visflags.push_back(lvisible.at(i));
}
int vis = visflags.size();
m_barh = float(height) / float(vis); m_barh = float(height) / float(vis);
float linetop = top; float linetop = top;
QColor barcol; QColor barcol;
for (int i = 0; i < lvisible.size(); i++) { for (int i = 0; i < visflags.size(); i++) {
// Alternating box color // Alternating box color
if (i & 1) { barcol = COLOR_ALT_BG1; } if (i & 1) { barcol = COLOR_ALT_BG1; }
else { barcol = COLOR_ALT_BG2; } else { barcol = COLOR_ALT_BG2; }
@ -113,8 +198,8 @@ void gFlagsGroup::paint(QPainter &painter, gGraph &g, const QRegion &region)
// Paint the actual flags // Paint the actual flags
QRect rect(left, linetop, width, m_barh); QRect rect(left, linetop, width, m_barh);
lvisible[i]->m_rect = rect; visflags[i]->m_rect = rect;
lvisible[i]->paint(painter, g, QRegion(rect)); visflags[i]->paint(painter, g, QRegion(rect));
linetop += m_barh; linetop += m_barh;
} }
@ -160,10 +245,8 @@ bool gFlagsGroup::mouseMoveEvent(QMouseEvent *event, gGraph *graph)
} }
gFlagsLine::gFlagsLine(ChannelID code, QColor flag_color, QString label, bool always_visible, gFlagsLine::gFlagsLine(ChannelID code)
FlagType flt) : Layer(code)
: Layer(code), m_label(label), m_always_visible(always_visible), m_flt(flt),
m_flag_color(flag_color)
{ {
} }
gFlagsLine::~gFlagsLine() gFlagsLine::~gFlagsLine()
@ -197,11 +280,12 @@ void gFlagsLine::paint(QPainter &painter, gGraph &w, const QRegion &region)
double xmult = width / xx; double xmult = width / xx;
QString label = schema::channel[m_code].label(); schema::Channel & chan = schema::channel[m_code];
GetTextExtent(label, m_lx, m_ly);
GetTextExtent(chan.label(), m_lx, m_ly);
// Draw text label // Draw text label
w.renderText(label, left - m_lx - 10, top + (height / 2) + (m_ly / 2)); w.renderText(chan.label(), left - m_lx - 10, top + (height / 2) + (m_ly / 2));
float x1, x2; float x1, x2;
@ -223,6 +307,7 @@ void gFlagsLine::paint(QPainter &painter, gGraph &w, const QRegion &region)
QColor color=schema::channel[m_code].defaultColor(); QColor color=schema::channel[m_code].defaultColor();
QBrush brush(color); QBrush brush(color);
bool hover = false;
for (QList<Session *>::iterator s = m_day->begin(); s != m_day->end(); s++) { for (QList<Session *>::iterator s = m_day->begin(); s != m_day->end(); s++) {
if (!(*s)->enabled()) { if (!(*s)->enabled()) {
continue; continue;
@ -264,7 +349,7 @@ void gFlagsLine::paint(QPainter &painter, gGraph &w, const QRegion &region)
np -= idx; np -= idx;
if (m_flt == FT_Bar) { if (chan.type() == schema::FLAG) {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Draw Event Flag Bars // Draw Event Flag Bars
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -277,9 +362,22 @@ void gFlagsLine::paint(QPainter &painter, gGraph &w, const QRegion &region)
} }
x1 = (X - minx) * xmult + left; x1 = (X - minx) * xmult + left;
if (!hover && QRect(x1-3, bartop-2, 6, bottom-bartop+4).contains(w.graphView()->currentMousePos())) {
hover = true;
painter.setPen(QPen(Qt::red,1));
painter.drawRect(x1-2, bartop-2, 4, bottom-bartop+4);
int x,y;
QString lab = QString("%1 (%2)").arg(schema::channel[m_code].fullname()).arg(*dptr);
GetTextExtent(lab, x, y);
w.ToolTip(lab, x1 - 10, bartop + (3 * w.printScaleY()), TT_AlignRight, p_profile->general->tooltipTimeout());
}
vlines.append(QLine(x1, bartop, x1, bottom)); vlines.append(QLine(x1, bartop, x1, bottom));
} }
} else if (m_flt == FT_Span) { } else if (chan.type() == schema::SPAN) {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Draw Event Flag Spans // Draw Event Flag Spans
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -297,7 +395,20 @@ void gFlagsLine::paint(QPainter &painter, gGraph &w, const QRegion &region)
x1 = double(X - minx) * xmult + left; x1 = double(X - minx) * xmult + left;
x2 = double(X2 - minx) * xmult + left; x2 = double(X2 - minx) * xmult + left;
brush = QBrush(color);
painter.fillRect(x2, bartop, x1-x2, bottom-bartop, brush); painter.fillRect(x2, bartop, x1-x2, bottom-bartop, brush);
if (!hover && QRect(x2, bartop, x1-x2, bottom-bartop).contains(w.graphView()->currentMousePos())) {
hover = true;
painter.setPen(QPen(Qt::red,1));
painter.drawRect(x2, bartop, x1-x2, bottom-bartop);
int x,y;
QString lab = QString("%1 (%2)").arg(schema::channel[m_code].fullname()).arg(*dptr);
GetTextExtent(lab, x, y);
w.ToolTip(lab, x2 - 10, bartop + (3 * w.printScaleY()), TT_AlignRight, p_profile->general->tooltipTimeout());
}
} }
} }
} }

View File

@ -49,35 +49,20 @@ class gFlagsLine: public Layer
\param always_visible Whether to always show this line, even if empty \param always_visible Whether to always show this line, even if empty
\param Type of Flag, either FT_Bar, or FT_Span \param Type of Flag, either FT_Bar, or FT_Span
*/ */
gFlagsLine(ChannelID code, QColor col = Qt::black, QString label = "", bool always_visible = false, gFlagsLine(ChannelID code);
FlagType flt = FT_Bar);
virtual ~gFlagsLine(); virtual ~gFlagsLine();
//! \brief Drawing code to add the flags and span markers to the Vertex buffers. //! \brief Drawing code to add the flags and span markers to the Vertex buffers.
virtual void paint(QPainter &painter, gGraph &w, const QRegion &region); virtual void paint(QPainter &painter, gGraph &w, const QRegion &region);
//! \brief Returns true if should always show this flag, even if it's empty
bool isAlwaysVisible() { return m_always_visible; }
//! \brief Set this to true to make a flag line always visible
void setAlwaysVisible(bool b) { m_always_visible = b; }
//! \brief Returns the label for this individual Event Flags line
QString label() { return m_label; }
//! \brief Sets the label for this individual Event Flags line
void setLabel(QString s) { m_label = s; }
void setTotalLines(int i) { total_lines = i; } void setTotalLines(int i) { total_lines = i; }
void setLineNum(int i) { line_num = i; } void setLineNum(int i) { line_num = i; }
protected: protected:
virtual bool mouseMoveEvent(QMouseEvent *event, gGraph *graph); virtual bool mouseMoveEvent(QMouseEvent *event, gGraph *graph);
QString m_label;
bool m_always_visible; bool m_always_visible;
int total_lines, line_num; int total_lines, line_num;
FlagType m_flt;
QColor m_flag_color;
int m_lx, m_ly; int m_lx, m_ly;
}; };
@ -115,9 +100,13 @@ class gFlagsGroup: public LayerGroup
//! Returns a list of Visible gFlagsLine layers to draw //! Returns a list of Visible gFlagsLine layers to draw
QVector<gFlagsLine *> &visibleLayers() { return lvisible; } QVector<gFlagsLine *> &visibleLayers() { return lvisible; }
void alwaysVisible(ChannelID code) { m_alwaysvisible.push_back(code); }
protected: protected:
virtual bool mouseMoveEvent(QMouseEvent *event, gGraph *graph); virtual bool mouseMoveEvent(QMouseEvent *event, gGraph *graph);
QList<ChannelID> m_alwaysvisible;
QVector<gFlagsLine *> lvisible; QVector<gFlagsLine *> lvisible;
float m_barh; float m_barh;
bool m_empty; bool m_empty;

View File

@ -118,7 +118,7 @@ void gSegmentChart::paint(QPainter &painter, gGraph &w, const QRegion &region)
// Pie Chart // Pie Chart
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
if (m_graph_type == GST_Pie) { if (m_graph_type == GST_Pie) {
const QColor col = schema::channel[m_codes[m % m_colors.size()]].defaultColor(); const QColor col = schema::channel[m_codes[m]].defaultColor();
// length of this segment in degrees // length of this segment in degrees
float len = 360.0 / float(m_total) * float(data); float len = 360.0 / float(m_total) * float(data);
@ -151,7 +151,7 @@ void gSegmentChart::paint(QPainter &painter, gGraph &w, const QRegion &region)
double tpx = (pierect.x() + pierect.width()/2) + (sin((180 - angle) * (M_PI / 180.0)) * (radius / 1.65)); double tpx = (pierect.x() + pierect.width()/2) + (sin((180 - angle) * (M_PI / 180.0)) * (radius / 1.65));
double tpy = (pierect.y() + pierect.height()/2) + (cos((180 - angle) * (M_PI / 180.0)) * (radius / 1.65)); double tpy = (pierect.y() + pierect.height()/2) + (cos((180 - angle) * (M_PI / 180.0)) * (radius / 1.65));
QString txt = m_names[m]; //QString::number(floor(100.0/m_total*data),'f',0)+"%"; QString txt = schema::channel[m_codes[m]].label(); //QString::number(floor(100.0/m_total*data),'f',0)+"%";
int x, y; int x, y;
GetTextExtent(txt, x, y); GetTextExtent(txt, x, y);
// antialiasing looks like crap here.. // antialiasing looks like crap here..

View File

@ -548,7 +548,8 @@ Channel::Channel(ChannelID id, ChanType type, ScopeType scope, QString code, QSt
m_lowerThreshold(0), m_lowerThreshold(0),
m_upperThresholdColor(Qt::red), m_upperThresholdColor(Qt::red),
m_lowerThresholdColor(Qt::green), m_lowerThresholdColor(Qt::green),
m_enabled(true) m_enabled(true),
m_order(255)
{ {
} }
bool Channel::isNull() bool Channel::isNull()

View File

@ -53,7 +53,7 @@ extern Channel EmptyChannel;
class Channel class Channel
{ {
public: public:
Channel() { m_id = 0; m_upperThreshold = 0; m_lowerThreshold = 0; m_enabled = true; } Channel() { m_id = 0; m_upperThreshold = 0; m_lowerThreshold = 0; m_enabled = true; m_order = 255; }
Channel(ChannelID id, ChanType type, ScopeType scope, QString code, QString fullname, Channel(ChannelID id, ChanType type, ScopeType scope, QString code, QString fullname,
QString description, QString label, QString unit, DataType datatype = DEFAULT, QColor = Qt::black, QString description, QString label, QString unit, DataType datatype = DEFAULT, QColor = Qt::black,
int link = 0); int link = 0);
@ -68,6 +68,7 @@ class Channel
const QString &description() { return m_description; } const QString &description() { return m_description; }
const QString &label() { return m_label; } const QString &label() { return m_label; }
const QString &units() { return m_unit; } const QString &units() { return m_unit; }
inline short order() const { return m_order; }
inline EventDataType upperThreshold() const { return m_upperThreshold; } inline EventDataType upperThreshold() const { return m_upperThreshold; }
inline EventDataType lowerThreshold() const { return m_lowerThreshold; } inline EventDataType lowerThreshold() const { return m_lowerThreshold; }
@ -85,6 +86,7 @@ class Channel
void setUpperThresholdColor(QColor color) { m_upperThresholdColor = color; } void setUpperThresholdColor(QColor color) { m_upperThresholdColor = color; }
void setLowerThreshold(EventDataType value) { m_lowerThreshold = value; } void setLowerThreshold(EventDataType value) { m_lowerThreshold = value; }
void setLowerThresholdColor(QColor color) { m_lowerThresholdColor = color; } void setLowerThresholdColor(QColor color) { m_lowerThresholdColor = color; }
void setOrder(short order) { m_order = order; }
QString option(int i) { QString option(int i) {
if (m_options.contains(i)) { if (m_options.contains(i)) {
@ -123,6 +125,7 @@ class Channel
QColor m_lowerThresholdColor; QColor m_lowerThresholdColor;
bool m_enabled; bool m_enabled;
short m_order;
}; };
/*! \class ChannelList /*! \class ChannelList

View File

@ -215,27 +215,27 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
gFlagsGroup *fg=new gFlagsGroup(); gFlagsGroup *fg=new gFlagsGroup();
SF->AddLayer(AddCPAP(fg)); SF->AddLayer(AddCPAP(fg));
// Spans // Spans
fg->AddLayer((new gFlagsLine(CPAP_CSR, COLOR_CSR, STR_TR_PB, false, FT_Span))); // fg->AddLayer((new gFlagsLine(CPAP_CSR, COLOR_CSR, STR_TR_PB, false, FT_Span)));
fg->AddLayer((new gFlagsLine(CPAP_LargeLeak, COLOR_LargeLeak, STR_TR_LL, false, FT_Span))); // fg->AddLayer((new gFlagsLine(CPAP_LargeLeak, COLOR_LargeLeak, STR_TR_LL, false, FT_Span)));
fg->AddLayer((new gFlagsLine(CPAP_Ramp, COLOR_Ramp, schema::channel[CPAP_Ramp].label(), false, FT_Span))); // fg->AddLayer((new gFlagsLine(CPAP_Ramp, COLOR_Ramp, schema::channel[CPAP_Ramp].label(), false, FT_Span)));
// Flags // // Flags
fg->AddLayer((new gFlagsLine(CPAP_ClearAirway, COLOR_ClearAirway, STR_TR_CA,false))); // fg->AddLayer((new gFlagsLine(CPAP_ClearAirway, COLOR_ClearAirway, STR_TR_CA,false)));
fg->AddLayer((new gFlagsLine(CPAP_Obstructive, COLOR_Obstructive, STR_TR_OA,true))); // fg->AddLayer((new gFlagsLine(CPAP_Obstructive, COLOR_Obstructive, STR_TR_OA,true)));
fg->AddLayer((new gFlagsLine(CPAP_Apnea, COLOR_Apnea, STR_TR_UA))); // fg->AddLayer((new gFlagsLine(CPAP_Apnea, COLOR_Apnea, STR_TR_UA)));
fg->AddLayer((new gFlagsLine(CPAP_Hypopnea, COLOR_Hypopnea, STR_TR_H,true))); // fg->AddLayer((new gFlagsLine(CPAP_Hypopnea, COLOR_Hypopnea, STR_TR_H,true)));
fg->AddLayer((new gFlagsLine(CPAP_ExP, COLOR_ExP, STR_TR_EP,false))); // fg->AddLayer((new gFlagsLine(CPAP_ExP, COLOR_ExP, STR_TR_EP,false)));
fg->AddLayer((new gFlagsLine(CPAP_LeakFlag, COLOR_LeakFlag, STR_TR_LE,false))); // fg->AddLayer((new gFlagsLine(CPAP_LeakFlag, COLOR_LeakFlag, STR_TR_LE,false)));
fg->AddLayer((new gFlagsLine(CPAP_NRI, COLOR_NRI, STR_TR_NRI,false))); // fg->AddLayer((new gFlagsLine(CPAP_NRI, COLOR_NRI, STR_TR_NRI,false)));
fg->AddLayer((new gFlagsLine(CPAP_FlowLimit, COLOR_FlowLimit, STR_TR_FL))); // fg->AddLayer((new gFlagsLine(CPAP_FlowLimit, COLOR_FlowLimit, STR_TR_FL)));
fg->AddLayer((new gFlagsLine(CPAP_SensAwake, COLOR_SensAwake, STR_TR_SA))); // fg->AddLayer((new gFlagsLine(CPAP_SensAwake, COLOR_SensAwake, STR_TR_SA)));
fg->AddLayer((new gFlagsLine(CPAP_RERA, COLOR_RERA, STR_TR_RE))); // fg->AddLayer((new gFlagsLine(CPAP_RERA, COLOR_RERA, STR_TR_RE)));
fg->AddLayer((new gFlagsLine(CPAP_VSnore, COLOR_VibratorySnore, STR_TR_VS))); // fg->AddLayer((new gFlagsLine(CPAP_VSnore, COLOR_VibratorySnore, STR_TR_VS)));
fg->AddLayer((new gFlagsLine(CPAP_VSnore2, COLOR_VibratorySnore, STR_TR_VS2))); // fg->AddLayer((new gFlagsLine(CPAP_VSnore2, COLOR_VibratorySnore, STR_TR_VS2)));
if (p_profile->cpap->userEventFlagging()) { // if (p_profile->cpap->userEventFlagging()) {
fg->AddLayer((new gFlagsLine(CPAP_UserFlag1, COLOR_Yellow, STR_TR_UF1))); // fg->AddLayer((new gFlagsLine(CPAP_UserFlag1, COLOR_Yellow, STR_TR_UF1)));
fg->AddLayer((new gFlagsLine(CPAP_UserFlag2, COLOR_DarkGreen, STR_TR_UF2))); // fg->AddLayer((new gFlagsLine(CPAP_UserFlag2, COLOR_DarkGreen, STR_TR_UF2)));
fg->AddLayer((new gFlagsLine(CPAP_UserFlag3, COLOR_Brown, STR_TR_UF3))); // fg->AddLayer((new gFlagsLine(CPAP_UserFlag3, COLOR_Brown, STR_TR_UF3)));
} // }
//fg->AddLayer((new gFlagsLine(PRS1_0B,COLOR_DarkGreen,tr("U0B")))); //fg->AddLayer((new gFlagsLine(PRS1_0B,COLOR_DarkGreen,tr("U0B"))));
SF->setBlockZoom(true); SF->setBlockZoom(true);
SF->AddLayer(new gShadowArea()); SF->AddLayer(new gShadowArea());