Tissue saturation plot a la Sherwater Pretel

This adds a toolbox icon to turn on a tissue plot inspired by the bar
graph of the Sherwater Petrel,

It shows the inert gas partial pressures for individual compartments. If
they are below the ambient pressure (grey line) they are shown in units of
the ambient pressure, if they are above, the excess is shown as a
percentage of the allowed overpressure for plain Buehlmann. So it has the
same units as a gradient factor. Thus also the a gradient factor line (for
the current depth) is shown.

The different tissues get different colors, greener for the faster ones and bluer
for the slower ones.

Positioning and on/off icon action still need some tender loving care.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Robert C. Helling 2014-09-15 14:09:00 +02:00 committed by Dirk Hohndel
parent 7cdf55ffcc
commit 3fc9c1e005
21 changed files with 319 additions and 8 deletions

4
deco.c
View file

@ -85,12 +85,12 @@ double gf_low_pressure_this_dive;
#define TISSUE_ARRAY_SZ sizeof(tissue_n2_sat) #define TISSUE_ARRAY_SZ sizeof(tissue_n2_sat)
double tolerated_by_tissue[16]; double tolerated_by_tissue[16];
double tissue_inertgas_saturation[16];
double buehlmann_inertgas_a[16], buehlmann_inertgas_b[16];
static double tissue_tolerance_calc(const struct dive *dive) static double tissue_tolerance_calc(const struct dive *dive)
{ {
int ci = -1; int ci = -1;
double tissue_inertgas_saturation[16], buehlmann_inertgas_a[16], buehlmann_inertgas_b[16];
double ret_tolerance_limit_ambient_pressure = 0.0; double ret_tolerance_limit_ambient_pressure = 0.0;
double gf_high = buehlmann_config.gf_high; double gf_high = buehlmann_config.gf_high;
double gf_low = buehlmann_config.gf_low; double gf_low = buehlmann_config.gf_low;

4
deco.h
View file

@ -7,6 +7,10 @@ extern "C" {
extern double tolerated_by_tissue[]; extern double tolerated_by_tissue[];
extern double buehlmann_N2_t_halflife[]; extern double buehlmann_N2_t_halflife[];
extern double tissue_inertgas_saturation[16];
extern double buehlmann_inertgas_a[16], buehlmann_inertgas_b[16];
extern double gf_low_pressure_this_dive;
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -66,6 +66,8 @@ extern const char *default_dive_computer_vendor;
extern const char *default_dive_computer_product; extern const char *default_dive_computer_product;
extern const char *default_dive_computer_device; extern const char *default_dive_computer_device;
#define AMB_PERCENTAGE 50.0
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

BIN
icons/petrel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

1
pref.h
View file

@ -45,6 +45,7 @@ struct preferences {
short show_average_depth; short show_average_depth;
short zoomed_plot; short zoomed_plot;
short hrgraph; short hrgraph;
short percentagegraph;
short rulergraph; short rulergraph;
short tankbar; short tankbar;
short save_userid_local; short save_userid_local;

View file

@ -759,6 +759,10 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
struct plot_data *entry = pi->entry + i; struct plot_data *entry = pi->entry + i;
int j, t0 = (entry - 1)->sec, t1 = entry->sec; int j, t0 = (entry - 1)->sec, t1 = entry->sec;
int time_stepsize = 20; int time_stepsize = 20;
entry->ambpressure = (double) depth_to_mbar(entry->depth, dive) / 1000.0;
entry->gfline = MAX((double) prefs.gflow, (entry->ambpressure - surface_pressure) / (gf_low_pressure_this_dive - surface_pressure) *
(prefs.gflow - prefs.gfhigh) + prefs.gfhigh) * (100.0 - AMB_PERCENTAGE) / 100.0 + AMB_PERCENTAGE;
if (t0 != t1 && t1 - t0 < time_stepsize) if (t0 != t1 && t1 - t0 < time_stepsize)
time_stepsize = t1 - t0; time_stepsize = t1 - t0;
for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) { for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
@ -773,8 +777,13 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
entry->ceiling = (entry - 1)->ceiling; entry->ceiling = (entry - 1)->ceiling;
else else
entry->ceiling = deco_allowed_depth(tissue_tolerance, surface_pressure, dive, !prefs.calcceiling3m); entry->ceiling = deco_allowed_depth(tissue_tolerance, surface_pressure, dive, !prefs.calcceiling3m);
for (j = 0; j < 16; j++) for (j = 0; j < 16; j++) {
double m_value = buehlmann_inertgas_a[j] + entry->ambpressure / buehlmann_inertgas_b[j];
entry->ceilings[j] = deco_allowed_depth(tolerated_by_tissue[j], surface_pressure, dive, 1); entry->ceilings[j] = deco_allowed_depth(tolerated_by_tissue[j], surface_pressure, dive, 1);
entry->percentages[j] = tissue_inertgas_saturation[j] < entry->ambpressure ?
tissue_inertgas_saturation[j] / entry->ambpressure * AMB_PERCENTAGE:
AMB_PERCENTAGE + (tissue_inertgas_saturation[j] - entry->ambpressure) / (m_value - entry->ambpressure) * (100.0 - AMB_PERCENTAGE);
}
/* should we do more calculations? /* should we do more calculations?
* We don't for print-mode because this info doesn't show up there */ * We don't for print-mode because this info doesn't show up there */

View file

@ -31,6 +31,7 @@ struct plot_data {
int depth; int depth;
int ceiling; int ceiling;
int ceilings[16]; int ceilings[16];
int percentages[16];
int ndl; int ndl;
int tts; int tts;
int stoptime; int stoptime;
@ -55,6 +56,8 @@ struct plot_data {
int pressure_time; int pressure_time;
int heartbeat; int heartbeat;
int bearing; int bearing;
double ambpressure;
double gfline;
}; };
struct ev_select { struct ev_select {

View file

@ -57,6 +57,9 @@ void fill_profile_color()
profile_color[CEILING_DEEP] = COLOR(RED1_MED_TRANS, BLACK1_HIGH_TRANS, RED1_MED_TRANS); profile_color[CEILING_DEEP] = COLOR(RED1_MED_TRANS, BLACK1_HIGH_TRANS, RED1_MED_TRANS);
profile_color[CALC_CEILING_SHALLOW] = COLOR(FUNGREEN1_HIGH_TRANS, BLACK1_HIGH_TRANS, FUNGREEN1_HIGH_TRANS); profile_color[CALC_CEILING_SHALLOW] = COLOR(FUNGREEN1_HIGH_TRANS, BLACK1_HIGH_TRANS, FUNGREEN1_HIGH_TRANS);
profile_color[CALC_CEILING_DEEP] = COLOR(APPLE1_HIGH_TRANS, BLACK1_HIGH_TRANS, APPLE1_HIGH_TRANS); profile_color[CALC_CEILING_DEEP] = COLOR(APPLE1_HIGH_TRANS, BLACK1_HIGH_TRANS, APPLE1_HIGH_TRANS);
profile_color[TISSUE_PERCENTAGE] = COLOR(GOVERNORBAY2, BLACK1_LOW_TRANS, GOVERNORBAY2);
profile_color[GF_LINE] = COLOR(BLACK1, BLACK1_LOW_TRANS, BLACK1);
profile_color[AMB_PRESSURE_LINE] = COLOR(TUNDORA1_MED_TRANS, BLACK1_LOW_TRANS, ATLANTIS1);
#undef COLOR #undef COLOR
} }

View file

@ -67,7 +67,10 @@ typedef enum {
CEILING_SHALLOW, CEILING_SHALLOW,
CEILING_DEEP, CEILING_DEEP,
CALC_CEILING_SHALLOW, CALC_CEILING_SHALLOW,
CALC_CEILING_DEEP CALC_CEILING_DEEP,
TISSUE_PERCENTAGE,
GF_LINE,
AMB_PRESSURE_LINE
} color_indice_t; } color_indice_t;

View file

@ -73,7 +73,7 @@ MainWindow::MainWindow() : QMainWindow(),
profileToolbarActions << ui.profCalcAllTissues << ui.profCalcCeiling << ui.profDcCeiling << ui.profEad << profileToolbarActions << ui.profCalcAllTissues << ui.profCalcCeiling << ui.profDcCeiling << ui.profEad <<
ui.profHR << ui.profIncrement3m << ui.profMod << ui.profNdl_tts << ui.profNdl_tts << ui.profHR << ui.profIncrement3m << ui.profMod << ui.profNdl_tts << ui.profNdl_tts <<
ui.profPhe << ui.profPn2 << ui.profPO2 << ui.profRuler << ui.profSAC << ui.profScaled << ui.profPhe << ui.profPn2 << ui.profPO2 << ui.profRuler << ui.profSAC << ui.profScaled <<
ui.profTogglePicture << ui.profTankbar; ui.profTogglePicture << ui.profTankbar << ui.profTissues;
setWindowIcon(QIcon(":subsurface-icon")); setWindowIcon(QIcon(":subsurface-icon"));
if (!QIcon::hasThemeIcon("window-close")) { if (!QIcon::hasThemeIcon("window-close")) {
QIcon::setThemeName("subsurface"); QIcon::setThemeName("subsurface");
@ -815,6 +815,7 @@ void MainWindow::readSettings()
TOOLBOX_PREF_BUTTON(show_sac, show_sac, profSAC); TOOLBOX_PREF_BUTTON(show_sac, show_sac, profSAC);
TOOLBOX_PREF_BUTTON(show_pictures_in_profile, show_pictures_in_profile, profTogglePicture); TOOLBOX_PREF_BUTTON(show_pictures_in_profile, show_pictures_in_profile, profTogglePicture);
TOOLBOX_PREF_BUTTON(tankbar, tankbar, profTankbar); TOOLBOX_PREF_BUTTON(tankbar, tankbar, profTankbar);
TOOLBOX_PREF_BUTTON(percentagegraph, precentagegraph, profTissues);
s.endGroup(); s.endGroup();
s.beginGroup("DiveComputer"); s.beginGroup("DiveComputer");
default_dive_computer_vendor = getSetting(s, "dive_computer_vendor"); default_dive_computer_vendor = getSetting(s, "dive_computer_vendor");
@ -1286,6 +1287,7 @@ TOOLBOX_PREF_PROFILE(profSAC, show_sac, show_sac);
TOOLBOX_PREF_PROFILE(profScaled, zoomed_plot, zoomed_plot); TOOLBOX_PREF_PROFILE(profScaled, zoomed_plot, zoomed_plot);
TOOLBOX_PREF_PROFILE(profTogglePicture, show_pictures_in_profile, show_pictures_in_profile); TOOLBOX_PREF_PROFILE(profTogglePicture, show_pictures_in_profile, show_pictures_in_profile);
TOOLBOX_PREF_PROFILE(profTankbar, tankbar, tankbar); TOOLBOX_PREF_PROFILE(profTankbar, tankbar, tankbar);
TOOLBOX_PREF_PROFILE(profTissues, percentagegraph, percentagegraph);
void MainWindow::turnOffNdlTts() void MainWindow::turnOffNdlTts()
{ {

View file

@ -143,6 +143,7 @@ slots:
void on_profScaled_triggered(bool triggered); void on_profScaled_triggered(bool triggered);
void on_profTogglePicture_triggered(bool triggered); void on_profTogglePicture_triggered(bool triggered);
void on_profTankbar_triggered(bool triggered); void on_profTankbar_triggered(bool triggered);
void on_profTissues_triggered(bool triggered);
void on_actionExport_triggered(); void on_actionExport_triggered();
void on_copy_triggered(); void on_copy_triggered();
void on_paste_triggered(); void on_paste_triggered();

View file

@ -256,7 +256,7 @@ p, li { white-space: pre-wrap; }
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1682</width> <width>1682</width>
<height>25</height> <height>22</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">
@ -844,6 +844,21 @@ p, li { white-space: pre-wrap; }
<string>Filter by Tags</string> <string>Filter by Tags</string>
</property> </property>
</action> </action>
<action name="profTissues">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../subsurface.qrc">
<normaloff>:/icon_tissue</normaloff>:/icon_tissue</iconset>
</property>
<property name="text">
<string>Toggle Tissue Graph</string>
</property>
<property name="toolTip">
<string>Toggle Tissue Graph</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View file

@ -330,6 +330,7 @@ void PreferencesDialog::loadSettings()
GET_BOOL("calcalltissues", calcalltissues); GET_BOOL("calcalltissues", calcalltissues);
GET_BOOL("hrgraph", hrgraph); GET_BOOL("hrgraph", hrgraph);
GET_BOOL("tankbar", tankbar); GET_BOOL("tankbar", tankbar);
GET_BOOL("percentagegraph", percentagegraph);
GET_INT("gflow", gflow); GET_INT("gflow", gflow);
GET_INT("gfhigh", gfhigh); GET_INT("gfhigh", gfhigh);
GET_BOOL("gf_low_at_maxdepth", gf_low_at_maxdepth); GET_BOOL("gf_low_at_maxdepth", gf_low_at_maxdepth);

View file

@ -54,6 +54,10 @@ QVariant DivePlotDataModel::data(const QModelIndex &index, int role) const
return item.pressures.o2; return item.pressures.o2;
case HEARTBEAT: case HEARTBEAT:
return item.heartbeat; return item.heartbeat;
case AMBPRESSURE:
return AMB_PERCENTAGE;
case GFLINE:
return item.gfline;
} }
} }
@ -61,6 +65,10 @@ QVariant DivePlotDataModel::data(const QModelIndex &index, int role) const
return item.ceilings[index.column() - TISSUE_1]; return item.ceilings[index.column() - TISSUE_1];
} }
if (role == Qt::DisplayRole && index.column() >= PERCENTAGE_1 && index.column() <= PERCENTAGE_16) {
return item.percentages[index.column() - PERCENTAGE_1];
}
if (role == Qt::BackgroundRole) { if (role == Qt::BackgroundRole) {
switch (index.column()) { switch (index.column()) {
case COLOR: case COLOR:
@ -117,10 +125,15 @@ QVariant DivePlotDataModel::headerData(int section, Qt::Orientation orientation,
return tr("pHe"); return tr("pHe");
case PO2: case PO2:
return tr("pO₂"); return tr("pO₂");
case AMBPRESSURE:
return tr("Ambient pressure");
} }
if (role == Qt::DisplayRole && section >= TISSUE_1 && section <= TISSUE_16) { if (role == Qt::DisplayRole && section >= TISSUE_1 && section <= TISSUE_16) {
return QString("Ceiling: %1").arg(section - TISSUE_1); return QString("Ceiling: %1").arg(section - TISSUE_1);
} }
if (role == Qt::DisplayRole && section >= PERCENTAGE_1 && section <= PERCENTAGE_16) {
return QString("Tissue: %1").arg(section - PERCENTAGE_1);
}
return QVariant(); return QVariant();
} }

View file

@ -40,10 +40,28 @@ public:
TISSUE_14, TISSUE_14,
TISSUE_15, TISSUE_15,
TISSUE_16, TISSUE_16,
PERCENTAGE_1,
PERCENTAGE_2,
PERCENTAGE_3,
PERCENTAGE_4,
PERCENTAGE_5,
PERCENTAGE_6,
PERCENTAGE_7,
PERCENTAGE_8,
PERCENTAGE_9,
PERCENTAGE_10,
PERCENTAGE_11,
PERCENTAGE_12,
PERCENTAGE_13,
PERCENTAGE_14,
PERCENTAGE_15,
PERCENTAGE_16,
PN2, PN2,
PHE, PHE,
PO2, PO2,
HEARTBEAT, HEARTBEAT,
AMBPRESSURE,
GFLINE,
COLUMNS COLUMNS
}; };
explicit DivePlotDataModel(QObject *parent = 0); explicit DivePlotDataModel(QObject *parent = 0);

View file

@ -338,6 +338,155 @@ void DiveHeartrateItem::settingsChanged()
setVisible(prefs.hrgraph); setVisible(prefs.hrgraph);
} }
DivePercentageItem::DivePercentageItem(int i)
{
QPen pen;
QColor color;
color.setHsl(100 + 10 * i, 200, 100);
pen.setBrush(QBrush(color));
pen.setCosmetic(true);
pen.setWidth(1);
setPen(pen);
settingsChanged();
}
void DivePercentageItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
int last = -300, last_printed_hr = 0, sec = 0;
// We don't have enougth data to calculate things, quit.
if (!shouldCalculateStuff(topLeft, bottomRight))
return;
// Ignore empty values. a heartrate of 0 would be a bad sign.
QPolygonF poly;
for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++) {
int hr = dataModel->index(i, vDataColumn).data().toInt();
if (!hr)
continue;
sec = dataModel->index(i, hDataColumn).data().toInt();
QPointF point(hAxis->posAtValue(sec), vAxis->posAtValue(hr));
poly.append(point);
}
setPolygon(poly);
if (texts.count())
texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
}
void DivePercentageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
if (polygon().isEmpty())
return;
painter->save();
painter->setPen(pen());
painter->drawPolyline(polygon());
painter->restore();
}
void DivePercentageItem::settingsChanged()
{
setVisible(prefs.percentagegraph);
}
DiveAmbPressureItem::DiveAmbPressureItem()
{
QPen pen;
pen.setBrush(QBrush(getColor(::AMB_PRESSURE_LINE)));
pen.setCosmetic(true);
pen.setWidth(2);
setPen(pen);
settingsChanged();
}
void DiveAmbPressureItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
int last = -300, last_printed_hr = 0, sec = 0;
// We don't have enougth data to calculate things, quit.
if (!shouldCalculateStuff(topLeft, bottomRight))
return;
// Ignore empty values. a heartrate of 0 would be a bad sign.
QPolygonF poly;
for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++) {
int hr = dataModel->index(i, vDataColumn).data().toInt();
if (!hr)
continue;
sec = dataModel->index(i, hDataColumn).data().toInt();
QPointF point(hAxis->posAtValue(sec), vAxis->posAtValue(hr));
poly.append(point);
}
setPolygon(poly);
if (texts.count())
texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
}
void DiveAmbPressureItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
if (polygon().isEmpty())
return;
painter->save();
painter->setPen(pen());
painter->drawPolyline(polygon());
painter->restore();
}
void DiveAmbPressureItem::settingsChanged()
{
setVisible(prefs.percentagegraph);
}
DiveGFLineItem::DiveGFLineItem()
{
QPen pen;
pen.setBrush(QBrush(getColor(::GF_LINE)));
pen.setCosmetic(true);
pen.setWidth(2);
setPen(pen);
settingsChanged();
}
void DiveGFLineItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
int last = -300, last_printed_hr = 0, sec = 0;
// We don't have enougth data to calculate things, quit.
if (!shouldCalculateStuff(topLeft, bottomRight))
return;
// Ignore empty values. a heartrate of 0 would be a bad sign.
QPolygonF poly;
for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++) {
int hr = dataModel->index(i, vDataColumn).data().toInt();
if (!hr)
continue;
sec = dataModel->index(i, hDataColumn).data().toInt();
QPointF point(hAxis->posAtValue(sec), vAxis->posAtValue(hr));
poly.append(point);
}
setPolygon(poly);
if (texts.count())
texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
}
void DiveGFLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
if (polygon().isEmpty())
return;
painter->save();
painter->setPen(pen());
painter->drawPolyline(polygon());
painter->restore();
}
void DiveGFLineItem::settingsChanged()
{
setVisible(prefs.percentagegraph);
}
DiveTemperatureItem::DiveTemperatureItem() DiveTemperatureItem::DiveTemperatureItem()
{ {
QPen pen; QPen pen;

View file

@ -107,6 +107,39 @@ private:
QString visibilityKey; QString visibilityKey;
}; };
class DivePercentageItem : public AbstractProfilePolygonItem {
Q_OBJECT
public:
DivePercentageItem(int i);
virtual void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual void settingsChanged();
private:
QString visibilityKey;
};
class DiveAmbPressureItem : public AbstractProfilePolygonItem {
Q_OBJECT
public:
DiveAmbPressureItem();
virtual void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual void settingsChanged();
private:
QString visibilityKey;
};
class DiveGFLineItem : public AbstractProfilePolygonItem {
Q_OBJECT
public:
DiveGFLineItem();
virtual void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual void settingsChanged();
private:
QString visibilityKey;
};
class DiveGasPressureItem : public AbstractProfilePolygonItem { class DiveGasPressureItem : public AbstractProfilePolygonItem {
Q_OBJECT Q_OBJECT

View file

@ -57,6 +57,7 @@ static struct _ItemPos {
_Axis depth; _Axis depth;
_Axis partialPressure; _Axis partialPressure;
_Axis partialPressureWithTankBar; _Axis partialPressureWithTankBar;
_Axis percentage;
_Axis time; _Axis time;
_Axis cylinder; _Axis cylinder;
_Axis temperature; _Axis temperature;
@ -89,6 +90,9 @@ ProfileWidget2::ProfileWidget2(QWidget *parent) : QGraphicsView(parent),
po2GasItem(new PartialPressureGasItem()), po2GasItem(new PartialPressureGasItem()),
heartBeatAxis(new DiveCartesianAxis()), heartBeatAxis(new DiveCartesianAxis()),
heartBeatItem(new DiveHeartrateItem()), heartBeatItem(new DiveHeartrateItem()),
percentageAxis(new DiveCartesianAxis()),
ambPressureItem(new DiveAmbPressureItem()),
gflineItem(new DiveGFLineItem()),
mouseFollowerVertical(new DiveLineItem()), mouseFollowerVertical(new DiveLineItem()),
mouseFollowerHorizontal(new DiveLineItem()), mouseFollowerHorizontal(new DiveLineItem()),
rulerItem(new RulerItem2()), rulerItem(new RulerItem2()),
@ -159,6 +163,7 @@ void ProfileWidget2::addItemsToScene()
scene()->addItem(pn2GasItem); scene()->addItem(pn2GasItem);
scene()->addItem(pheGasItem); scene()->addItem(pheGasItem);
scene()->addItem(po2GasItem); scene()->addItem(po2GasItem);
scene()->addItem(percentageAxis);
scene()->addItem(heartBeatAxis); scene()->addItem(heartBeatAxis);
scene()->addItem(heartBeatItem); scene()->addItem(heartBeatItem);
scene()->addItem(rulerItem); scene()->addItem(rulerItem);
@ -174,6 +179,11 @@ void ProfileWidget2::addItemsToScene()
Q_FOREACH (DiveCalculatedTissue *tissue, allTissues) { Q_FOREACH (DiveCalculatedTissue *tissue, allTissues) {
scene()->addItem(tissue); scene()->addItem(tissue);
} }
Q_FOREACH (DivePercentageItem *percentage, allPercentages) {
scene()->addItem(percentage);
}
scene()->addItem(ambPressureItem);
scene()->addItem(gflineItem);
} }
void ProfileWidget2::setupItemOnScene() void ProfileWidget2::setupItemOnScene()
@ -207,6 +217,12 @@ void ProfileWidget2::setupItemOnScene()
heartBeatAxis->setFontLabelScale(0.7); heartBeatAxis->setFontLabelScale(0.7);
heartBeatAxis->setLineSize(96); heartBeatAxis->setLineSize(96);
percentageAxis->setOrientation(DiveCartesianAxis::BottomToTop);
percentageAxis->setTickSize(0.2);
percentageAxis->setTickInterval(10);
percentageAxis->setFontLabelScale(0.7);
percentageAxis->setLineSize(96);
temperatureAxis->setOrientation(DiveCartesianAxis::BottomToTop); temperatureAxis->setOrientation(DiveCartesianAxis::BottomToTop);
temperatureAxis->setTickSize(2); temperatureAxis->setTickSize(2);
temperatureAxis->setTickInterval(300); temperatureAxis->setTickInterval(300);
@ -233,10 +249,15 @@ void ProfileWidget2::setupItemOnScene()
DiveCalculatedTissue *tissueItem = new DiveCalculatedTissue(); DiveCalculatedTissue *tissueItem = new DiveCalculatedTissue();
setupItem(tissueItem, timeAxis, profileYAxis, dataModel, DivePlotDataModel::TISSUE_1 + i, DivePlotDataModel::TIME, 1 + i); setupItem(tissueItem, timeAxis, profileYAxis, dataModel, DivePlotDataModel::TISSUE_1 + i, DivePlotDataModel::TIME, 1 + i);
allTissues.append(tissueItem); allTissues.append(tissueItem);
DivePercentageItem *percentageItem = new DivePercentageItem(i);
setupItem(percentageItem, timeAxis, percentageAxis, dataModel, DivePlotDataModel::PERCENTAGE_1 + i, DivePlotDataModel::TIME, 1 + i);
allPercentages.append(percentageItem);
} }
setupItem(gasPressureItem, timeAxis, cylinderPressureAxis, dataModel, DivePlotDataModel::TEMPERATURE, DivePlotDataModel::TIME, 1); setupItem(gasPressureItem, timeAxis, cylinderPressureAxis, dataModel, DivePlotDataModel::TEMPERATURE, DivePlotDataModel::TIME, 1);
setupItem(temperatureItem, timeAxis, temperatureAxis, dataModel, DivePlotDataModel::TEMPERATURE, DivePlotDataModel::TIME, 1); setupItem(temperatureItem, timeAxis, temperatureAxis, dataModel, DivePlotDataModel::TEMPERATURE, DivePlotDataModel::TIME, 1);
setupItem(heartBeatItem, timeAxis, heartBeatAxis, dataModel, DivePlotDataModel::HEARTBEAT, DivePlotDataModel::TIME, 1); setupItem(heartBeatItem, timeAxis, heartBeatAxis, dataModel, DivePlotDataModel::HEARTBEAT, DivePlotDataModel::TIME, 1);
setupItem(ambPressureItem, timeAxis, percentageAxis, dataModel, DivePlotDataModel::AMBPRESSURE, DivePlotDataModel::TIME, 1);
setupItem(gflineItem, timeAxis, percentageAxis, dataModel, DivePlotDataModel::GFLINE, DivePlotDataModel::TIME, 1);
setupItem(diveProfileItem, timeAxis, profileYAxis, dataModel, DivePlotDataModel::DEPTH, DivePlotDataModel::TIME, 0); setupItem(diveProfileItem, timeAxis, profileYAxis, dataModel, DivePlotDataModel::DEPTH, DivePlotDataModel::TIME, 0);
#define CREATE_PP_GAS(ITEM, VERTICAL_COLUMN, COLOR, COLOR_ALERT, THRESHOULD_SETTINGS, VISIBILITY_SETTINGS) \ #define CREATE_PP_GAS(ITEM, VERTICAL_COLUMN, COLOR, COLOR_ALERT, THRESHOULD_SETTINGS, VISIBILITY_SETTINGS) \
@ -261,6 +282,8 @@ void ProfileWidget2::setupItemOnScene()
gasYAxis->setZValue(timeAxis->zValue() + 1); gasYAxis->setZValue(timeAxis->zValue() + 1);
heartBeatAxis->setTextVisible(true); heartBeatAxis->setTextVisible(true);
heartBeatAxis->setLinesVisible(true); heartBeatAxis->setLinesVisible(true);
percentageAxis->setTextVisible(true);
percentageAxis->setLinesVisible(true);
} }
void ProfileWidget2::replot() void ProfileWidget2::replot()
@ -307,7 +330,7 @@ void ProfileWidget2::setupItemSizes()
itemPos.partialPressure.pos.off.setX(110); itemPos.partialPressure.pos.off.setX(110);
itemPos.partialPressure.pos.off.setY(63); itemPos.partialPressure.pos.off.setY(63);
itemPos.partialPressure.expanded.setP1(QPointF(0, 0)); itemPos.partialPressure.expanded.setP1(QPointF(0, 0));
itemPos.partialPressure.expanded.setP2(QPointF(0, 30)); itemPos.partialPressure.expanded.setP2(QPointF(0, 20));
itemPos.partialPressureWithTankBar = itemPos.partialPressure; itemPos.partialPressureWithTankBar = itemPos.partialPressure;
itemPos.partialPressureWithTankBar.expanded.setP2(QPointF(0, 27)); itemPos.partialPressureWithTankBar.expanded.setP2(QPointF(0, 27));
@ -334,7 +357,12 @@ void ProfileWidget2::setupItemSizes()
itemPos.heartBeat.pos.on.setX(3); itemPos.heartBeat.pos.on.setX(3);
itemPos.heartBeat.pos.on.setY(60); itemPos.heartBeat.pos.on.setY(60);
itemPos.heartBeat.expanded.setP1(QPointF(0, 0)); itemPos.heartBeat.expanded.setP1(QPointF(0, 0));
itemPos.heartBeat.expanded.setP2(QPointF(0, 20)); itemPos.heartBeat.expanded.setP2(QPointF(0, 15));
itemPos.percentage.pos.on.setX(3);
itemPos.percentage.pos.on.setY(85); // was 80
itemPos.percentage.expanded.setP1(QPointF(0, 0));
itemPos.percentage.expanded.setP2(QPointF(0, 15)); // was 20
itemPos.dcLabel.on.setX(3); itemPos.dcLabel.on.setX(3);
itemPos.dcLabel.on.setY(100); itemPos.dcLabel.on.setY(100);
@ -485,6 +513,11 @@ void ProfileWidget2::plotDive(struct dive *d, bool force)
} }
heartBeatAxis->setVisible(prefs.hrgraph && pInfo.maxhr); heartBeatAxis->setVisible(prefs.hrgraph && pInfo.maxhr);
percentageAxis->setMinimum(0);
percentageAxis->setMaximum(100);
percentageAxis->setVisible(false);
percentageAxis->updateTicks(HR_AXIS);
timeAxis->setMaximum(maxtime); timeAxis->setMaximum(maxtime);
int i, incr; int i, incr;
static int increments[8] = { 10, 20, 30, 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60 }; static int increments[8] = { 10, 20, 30, 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60 };
@ -760,12 +793,15 @@ void ProfileWidget2::setEmptyState()
pn2GasItem->setVisible(false); pn2GasItem->setVisible(false);
po2GasItem->setVisible(false); po2GasItem->setVisible(false);
pheGasItem->setVisible(false); pheGasItem->setVisible(false);
ambPressureItem->setVisible(false);
gflineItem->setVisible(false);
mouseFollowerHorizontal->setVisible(false); mouseFollowerHorizontal->setVisible(false);
mouseFollowerVertical->setVisible(false); mouseFollowerVertical->setVisible(false);
#define HIDE_ALL(TYPE, CONTAINER) \ #define HIDE_ALL(TYPE, CONTAINER) \
Q_FOREACH (TYPE *item, CONTAINER) item->setVisible(false); Q_FOREACH (TYPE *item, CONTAINER) item->setVisible(false);
HIDE_ALL(DiveCalculatedTissue, allTissues); HIDE_ALL(DiveCalculatedTissue, allTissues);
HIDE_ALL(DivePercentageItem, allPercentages);
HIDE_ALL(DiveEventItem, eventItems); HIDE_ALL(DiveEventItem, eventItems);
HIDE_ALL(DiveHandler, handles); HIDE_ALL(DiveHandler, handles);
HIDE_ALL(QGraphicsSimpleTextItem, gases); HIDE_ALL(QGraphicsSimpleTextItem, gases);
@ -842,6 +878,16 @@ void ProfileWidget2::setProfileState()
tissue->setVisible(true); tissue->setVisible(true);
} }
} }
percentageAxis->setPos(itemPos.percentage.pos.on);
percentageAxis->setLine(itemPos.percentage.expanded);
if (prefs.percentagegraph) {
Q_FOREACH (DivePercentageItem *percentage, allPercentages) {
percentage->setVisible(true);
}
ambPressureItem->setVisible(true);
} gflineItem->setVisible(true);
rulerItem->setVisible(prefs.rulergraph); rulerItem->setVisible(prefs.rulergraph);
tankItem->setVisible(prefs.tankbar); tankItem->setVisible(prefs.tankbar);
tankItem->setPos(itemPos.tankBar.on); tankItem->setPos(itemPos.tankBar.on);

View file

@ -15,6 +15,7 @@
// */ // */
#include "graphicsview-common.h" #include "graphicsview-common.h"
#include "divelineitem.h" #include "divelineitem.h"
#include "diveprofileitem.h"
class RulerItem2; class RulerItem2;
struct dive; struct dive;
@ -34,6 +35,7 @@ class DiveProfileItem;
class TimeAxis; class TimeAxis;
class DiveTemperatureItem; class DiveTemperatureItem;
class DiveHeartrateItem; class DiveHeartrateItem;
class PercentageItem;
class DiveGasPressureItem; class DiveGasPressureItem;
class DiveCalculatedCeiling; class DiveCalculatedCeiling;
class DiveCalculatedTissue; class DiveCalculatedTissue;
@ -163,6 +165,10 @@ private:
PartialPressureGasItem *po2GasItem; PartialPressureGasItem *po2GasItem;
DiveCartesianAxis *heartBeatAxis; DiveCartesianAxis *heartBeatAxis;
DiveHeartrateItem *heartBeatItem; DiveHeartrateItem *heartBeatItem;
DiveCartesianAxis *percentageAxis;
QList<DivePercentageItem *> allPercentages;
DiveAmbPressureItem *ambPressureItem;
DiveGFLineItem *gflineItem;
DiveLineItem *mouseFollowerVertical; DiveLineItem *mouseFollowerVertical;
DiveLineItem *mouseFollowerHorizontal; DiveLineItem *mouseFollowerHorizontal;
RulerItem2 *rulerItem; RulerItem2 *rulerItem;

View file

@ -58,6 +58,7 @@
<file alias="icon_ceiling_dc">icons/pc.png</file> <file alias="icon_ceiling_dc">icons/pc.png</file>
<file alias="icon_ead">icons/ead.png</file> <file alias="icon_ead">icons/ead.png</file>
<file alias="icon_HR">icons/icon-HR.png</file> <file alias="icon_HR">icons/icon-HR.png</file>
<file alias="icon_tissue">icons/petrel.png</file>
<file alias="calendar">icons/calendarbg.png</file> <file alias="calendar">icons/calendarbg.png</file>
<file alias="pictures">icons/pictures.png</file> <file alias="pictures">icons/pictures.png</file>
<file>icons/subsurface/index.theme</file> <file>icons/subsurface/index.theme</file>

View file

@ -19,6 +19,7 @@ struct preferences default_prefs = {
.modpO2 = 1.6, .modpO2 = 1.6,
.ead = false, .ead = false,
.hrgraph = true, .hrgraph = true,
.percentagegraph = true,
.dcceiling = true, .dcceiling = true,
.redceiling = false, .redceiling = false,
.calcceiling = false, .calcceiling = false,