void DivePercentageItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { int sec = 0; // We don't have enougth data to calculate things, quit. if (!shouldCalculateStuff(topLeft, bottomRight)) return; // Ignore empty values. a heart rate of 0 would be a bad sign. QPolygonF poly; for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++) { sec = dataModel->index(i, hDataColumn).data().toInt(); QPointF point(hAxis->posAtValue(sec), vAxis->posAtValue(64 - 4 * tissueIndex)); poly.append(point); } setPolygon(poly); if (texts.count()) texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom); }
void DiveMeanDepthItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { double meandepthvalue = 0.0; // We don't have enougth data to calculate things, quit. if (!shouldCalculateStuff(topLeft, bottomRight)) return; QPolygonF poly; plot_data *entry = dataModel->data().entry; for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++, entry++) { // Ignore empty values if (entry->running_sum == 0 || entry->sec == 0) continue; meandepthvalue = entry->running_sum / entry->sec; QPointF point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(meandepthvalue)); poly.append(point); } lastRunningSum = meandepthvalue; setPolygon(poly); createTextItem(); }
void PartialPressureGasItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { //AbstractProfilePolygonItem::modelDataChanged(); if (!shouldCalculateStuff(topLeft, bottomRight)) return; plot_data *entry = dataModel->data().entry; QPolygonF poly; QPolygonF alertpoly; alertPolygons.clear(); QSettings s; s.beginGroup("TecDetails"); double threshould = s.value(threshouldKey).toDouble(); bool inAlertFragment = false; for (int i = 0; i < dataModel->rowCount(); i++, entry++) { double value = dataModel->index(i, vDataColumn).data().toDouble(); int time = dataModel->index(i, hDataColumn).data().toInt(); QPointF point(hAxis->posAtValue(time), vAxis->posAtValue(value)); poly.push_back(point); if (value >= threshould) { if (inAlertFragment) { alertPolygons.back().push_back(point); } else { alertpoly.clear(); alertpoly.push_back(point); alertPolygons.append(alertpoly); inAlertFragment = true; } } else { inAlertFragment = false; } } setPolygon(poly); /* createPPLegend(trUtf8("pN" UTF8_SUBSCRIPT_2),getColor(PN2), legendPos); */ }
void DiveProfileItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { bool eventAdded = false; if (!shouldCalculateStuff(topLeft, bottomRight)) return; AbstractProfilePolygonItem::modelDataChanged(topLeft, bottomRight); if (polygon().isEmpty()) return; show_reported_ceiling = prefs.dcceiling; reported_ceiling_in_red = prefs.redceiling; profileColor = getColor(DEPTH_BOTTOM); int currState = qobject_cast<ProfileWidget2 *>(scene()->views().first())->currentState; if (currState == ProfileWidget2::PLAN) { plot_data *entry = dataModel->data().entry; for (int i = 0; i < dataModel->rowCount(); i++, entry++) { int max = maxCeiling(i); // Don't scream if we violate the ceiling by a few cm if (entry->depth < max - 100) { profileColor = QColor(Qt::red); if (!eventAdded) { add_event(&displayed_dive.dc, entry->sec, SAMPLE_EVENT_CEILING, -1, max / 1000, "planned waypoint above ceiling"); eventAdded = true; } } } } /* Show any ceiling we may have encountered */ if (prefs.dcceiling && !prefs.redceiling) { QPolygonF p = polygon(); plot_data *entry = dataModel->data().entry + dataModel->rowCount() - 1; for (int i = dataModel->rowCount() - 1; i >= 0; i--, entry--) { if (!entry->in_deco) { /* not in deco implies this is a safety stop, no ceiling */ p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(0))); } else { p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(qMin(entry->stopdepth, entry->depth)))); } } setPolygon(p); } // This is the blueish gradient that the Depth Profile should have. // It's a simple QLinearGradient with 2 stops, starting from top to bottom. QLinearGradient pat(0, polygon().boundingRect().top(), 0, polygon().boundingRect().bottom()); pat.setColorAt(1, profileColor); pat.setColorAt(0, getColor(DEPTH_TOP)); setBrush(QBrush(pat)); int last = -1; for (int i = 0, count = dataModel->rowCount(); i < count; i++) { struct plot_data *entry = dataModel->data().entry + i; if (entry->depth < 2000) continue; if ((entry == entry->max[2]) && entry->depth / 100 != last) { plot_depth_sample(entry, Qt::AlignHCenter | Qt::AlignBottom, getColor(SAMPLE_DEEP)); last = entry->depth / 100; } if ((entry == entry->min[2]) && entry->depth / 100 != last) { plot_depth_sample(entry, Qt::AlignHCenter | Qt::AlignTop, getColor(SAMPLE_SHALLOW)); last = entry->depth / 100; } if (entry->depth != last) last = -1; } }
void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { // We don't have enougth data to calculate things, quit. if (!shouldCalculateStuff(topLeft, bottomRight)) return; int last_index = -1; int o2mbar; QPolygonF boundingPoly, o2Poly; // This is the "Whole Item", but a pressure can be divided in N Polygons. polygons.clear(); if (displayed_dive.dc.divemode == CCR) polygons.append(o2Poly); for (int i = 0, count = dataModel->rowCount(); i < count; i++) { o2mbar = 0; plot_data *entry = dataModel->data().entry + i; int mbar = GET_PRESSURE(entry); if (displayed_dive.dc.divemode == CCR) o2mbar = GET_O2CYLINDER_PRESSURE(entry); if (entry->cylinderindex != last_index) { polygons.append(QPolygonF()); // this is the polygon that will be actually drawn on screen. last_index = entry->cylinderindex; } if (!mbar) { continue; } if (o2mbar) { QPointF o2point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(o2mbar)); boundingPoly.push_back(o2point); polygons.first().push_back(o2point); } QPointF point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(mbar)); boundingPoly.push_back(point); // The BoundingRect polygons.last().push_back(point); // The polygon thta will be plotted. } setPolygon(boundingPoly); qDeleteAll(texts); texts.clear(); int mbar, cyl; int seen_cyl[MAX_CYLINDERS] = { false, }; int last_pressure[MAX_CYLINDERS] = { 0, }; int last_time[MAX_CYLINDERS] = { 0, }; struct plot_data *entry; cyl = -1; o2mbar = 0; double print_y_offset[8][2] = { { 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 } ,{ 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 } }; // CCR dives: These are offset values used to print the gas lables and pressures on a CCR dive profile at // appropriate Y-coordinates: One doublet of values for each of 8 cylinders. // Order of offsets within a doublet: gas lable offset; gas pressure offset. // The array is initialised with default values that apply to non-CCR dives. bool offsets_initialised = false; int o2cyl = -1, dilcyl = -1; QFlags<Qt::AlignmentFlag> alignVar= Qt::AlignTop, align_dil = Qt::AlignBottom, align_o2 = Qt::AlignTop; double axisRange = (vAxis->maximum() - vAxis->minimum())/1000; // Convert axis pressure range to bar double axisLog = log10(log10(axisRange)); for (int i = 0, count = dataModel->rowCount(); i < count; i++) { entry = dataModel->data().entry + i; mbar = GET_PRESSURE(entry); if (displayed_dive.dc.divemode == CCR && displayed_dive.oxygen_cylinder_index >= 0) o2mbar = GET_O2CYLINDER_PRESSURE(entry); if (o2mbar) { // If there is an o2mbar value then this is a CCR dive. Then do: // The first time an o2 value is detected, see if the oxygen cyl pressure graph starts above or below the dil graph if (!offsets_initialised) { // Initialise the parameters for placing the text correctly near the graph line: o2cyl = displayed_dive.oxygen_cylinder_index; dilcyl = displayed_dive.diluent_cylinder_index; if ((o2mbar > mbar)) { // If above, write o2 start cyl pressure above graph and diluent pressure below graph: print_y_offset[o2cyl][0] = -7 * axisLog; // y offset for oxygen gas lable (above); pressure offsets=-0.5, already initialised print_y_offset[dilcyl][0] = 5 * axisLog; // y offset for diluent gas lable (below) } else { // ... else write o2 start cyl pressure below graph: print_y_offset[o2cyl][0] = 5 * axisLog; // o2 lable & pressure below graph; pressure offsets=-0.5, already initialised print_y_offset[dilcyl][0] = -7.8 * axisLog; // and diluent lable above graph. align_dil = Qt::AlignTop; align_o2 = Qt::AlignBottom; } offsets_initialised = true; } if (!seen_cyl[displayed_dive.oxygen_cylinder_index]) { //For o2, on the left of profile, write lable and pressure plotPressureValue(o2mbar, entry->sec, align_o2, print_y_offset[o2cyl][1]); plotGasValue(o2mbar, entry->sec, displayed_dive.cylinder[displayed_dive.oxygen_cylinder_index].gasmix, align_o2, print_y_offset[o2cyl][0]); seen_cyl[displayed_dive.oxygen_cylinder_index] = true; } last_pressure[displayed_dive.oxygen_cylinder_index] = o2mbar; last_time[displayed_dive.oxygen_cylinder_index] = entry->sec; alignVar = align_dil; } if (!mbar) continue; if (cyl != entry->cylinderindex) { // Pressure value near the left hand edge of the profile - other cylinders: cyl = entry->cylinderindex; // For each other cylinder, write the gas lable and pressure if (!seen_cyl[cyl]) { plotPressureValue(mbar, entry->sec, alignVar, print_y_offset[cyl][1]); plotGasValue(mbar, entry->sec, displayed_dive.cylinder[cyl].gasmix, align_dil, print_y_offset[cyl][0]); seen_cyl[cyl] = true; } } last_pressure[cyl] = mbar; last_time[cyl] = entry->sec; } for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { // For each cylinder, on right hand side of profile, write cylinder pressure alignVar = ((o2cyl >= 0) && (cyl == displayed_dive.oxygen_cylinder_index)) ? align_o2 : align_dil; if (last_time[cyl]) { plotPressureValue(last_pressure[cyl], last_time[cyl], (alignVar | Qt::AlignLeft), print_y_offset[cyl][1]); } } }
void DiveGasPressureItem::modelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) { // We don't have enougth data to calculate things, quit. if (!shouldCalculateStuff(topLeft, bottomRight)) return; int last_index = -1; QPolygonF boundingPoly; // This is the "Whole Item", but a pressure can be divided in N Polygons. polygons.clear(); for (int i = 0, count = dataModel->rowCount(); i < count; i++) { plot_data* entry = dataModel->data().entry + i; int mbar = GET_PRESSURE(entry); if (entry->cylinderindex != last_index) { polygons.append(QPolygonF()); // this is the polygon that will be actually drawned on screen. last_index = entry->cylinderindex; } if (!mbar) { continue; } QPointF point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(mbar)); boundingPoly.push_back(point); // The BoundingRect polygons.last().push_back(point); // The polygon thta will be plotted. } setPolygon(boundingPoly); qDeleteAll(texts); texts.clear(); int mbar, cyl; int seen_cyl[MAX_CYLINDERS] = { false, }; int last_pressure[MAX_CYLINDERS] = { 0, }; int last_time[MAX_CYLINDERS] = { 0, }; struct plot_data *entry; struct dive *dive = getDiveById(dataModel->id()); Q_ASSERT(dive != NULL); cyl = -1; for (int i = 0, count = dataModel->rowCount(); i < count; i++) { entry = dataModel->data().entry + i; mbar = GET_PRESSURE(entry); if (!mbar) continue; if (cyl != entry->cylinderindex) { cyl = entry->cylinderindex; if (!seen_cyl[cyl]) { plot_pressure_value(mbar, entry->sec, Qt::AlignRight | Qt::AlignTop); plot_gas_value(mbar, entry->sec, Qt::AlignRight | Qt::AlignBottom, get_o2(&dive->cylinder[cyl].gasmix), get_he(&dive->cylinder[cyl].gasmix)); seen_cyl[cyl] = true; } } last_pressure[cyl] = mbar; last_time[cyl] = entry->sec; } for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { if (last_time[cyl]) { plot_pressure_value(last_pressure[cyl], last_time[cyl], Qt::AlignLeft | Qt::AlignTop); } } }
void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { // We don't have enougth data to calculate things, quit. if (!shouldCalculateStuff(topLeft, bottomRight)) return; int last_index = -1; int o2mbar; QPolygonF boundingPoly, o2Poly; // This is the "Whole Item", but a pressure can be divided in N Polygons. polygons.clear(); if (displayed_dive.dc.dctype == CCR) polygons.append(o2Poly); for (int i = 0, count = dataModel->rowCount(); i < count; i++) { o2mbar = 0; plot_data *entry = dataModel->data().entry + i; int mbar = GET_PRESSURE(entry); if (displayed_dive.dc.dctype == CCR) o2mbar = GET_O2CYLINDER_PRESSURE(entry); if (entry->cylinderindex != last_index) { polygons.append(QPolygonF()); // this is the polygon that will be actually drawned on screen. last_index = entry->cylinderindex; } if (!mbar) { continue; } if (o2mbar) { QPointF o2point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(o2mbar)); boundingPoly.push_back(o2point); polygons.first().push_back(o2point); } QPointF point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(mbar)); boundingPoly.push_back(point); // The BoundingRect polygons.last().push_back(point); // The polygon thta will be plotted. } setPolygon(boundingPoly); qDeleteAll(texts); texts.clear(); int mbar, cyl; int seen_cyl[MAX_CYLINDERS] = { false, }; int last_pressure[MAX_CYLINDERS] = { 0, }; int last_time[MAX_CYLINDERS] = { 0, }; struct plot_data *entry; cyl = -1; o2mbar = 0; for (int i = 0, count = dataModel->rowCount(); i < count; i++) { entry = dataModel->data().entry + i; mbar = GET_PRESSURE(entry); if (displayed_dive.dc.dctype == CCR && displayed_dive.oxygen_cylinder_index >= 0) o2mbar = GET_O2CYLINDER_PRESSURE(entry); if (o2mbar) { if (!seen_cyl[displayed_dive.oxygen_cylinder_index]) { plotPressureValue(o2mbar, entry->sec, Qt::AlignRight | Qt::AlignBottom); plotGasValue(o2mbar, entry->sec, Qt::AlignRight | Qt::AlignBottom, displayed_dive.cylinder[displayed_dive.oxygen_cylinder_index].gasmix); seen_cyl[displayed_dive.oxygen_cylinder_index] = true; } last_pressure[displayed_dive.oxygen_cylinder_index] = o2mbar; last_time[displayed_dive.oxygen_cylinder_index] = entry->sec; } if (!mbar) continue; if (cyl != entry->cylinderindex) { cyl = entry->cylinderindex; if (!seen_cyl[cyl]) { plotPressureValue(mbar, entry->sec, Qt::AlignRight | Qt::AlignTop); plotGasValue(mbar, entry->sec, Qt::AlignRight | Qt::AlignBottom, displayed_dive.cylinder[cyl].gasmix); seen_cyl[cyl] = true; } } last_pressure[cyl] = mbar; last_time[cyl] = entry->sec; } for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { if (last_time[cyl]) { plotPressureValue(last_pressure[cyl], last_time[cyl], Qt::AlignLeft | Qt::AlignTop); } } }
void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { // We don't have enougth data to calculate things, quit. if (!shouldCalculateStuff(topLeft, bottomRight)) return; int plotted_cyl[MAX_CYLINDERS] = { false, }; int last_plotted[MAX_CYLINDERS] = { 0, }; QPolygonF poly[MAX_CYLINDERS]; QPolygonF boundingPoly; polygons.clear(); for (int i = 0, count = dataModel->rowCount(); i < count; i++) { struct plot_data *entry = dataModel->data().entry + i; for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++) { int mbar = GET_PRESSURE(entry, cyl); int time = entry->sec; if (!mbar) continue; QPointF point(hAxis->posAtValue(time), vAxis->posAtValue(mbar)); boundingPoly.push_back(point); if (plotted_cyl[cyl]) { /* Have we used this culinder in the last two minutes? Continue */ if (time - last_plotted[cyl] <= 2*60) { poly[cyl].push_back(point); last_plotted[cyl] = time; continue; } /* Finish the previous one, start a new one */ polygons.append(poly[cyl]); poly[cyl] = QPolygonF(); } plotted_cyl[cyl] = true; last_plotted[cyl] = time; poly[cyl].push_back(point); } } for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++) { if (!plotted_cyl[cyl]) continue; polygons.append(poly[cyl]); } setPolygon(boundingPoly); qDeleteAll(texts); texts.clear(); int seen_cyl[MAX_CYLINDERS] = { false, }; int last_pressure[MAX_CYLINDERS] = { 0, }; int last_time[MAX_CYLINDERS] = { 0, }; // These are offset values used to print the gas lables and pressures on a // dive profile at appropriate Y-coordinates. We alternate aligning the // label and the gas pressure above and under the pressure line. // The values are historical, and we could try to pick the over/under // depending on whether this pressure is higher or lower than the average. // Right now it's just strictly alternating when you have multiple gas // pressures. QFlags<Qt::AlignmentFlag> alignVar = Qt::AlignTop; QFlags<Qt::AlignmentFlag> align[MAX_CYLINDERS]; double axisRange = (vAxis->maximum() - vAxis->minimum())/1000; // Convert axis pressure range to bar double axisLog = log10(log10(axisRange)); for (int i = 0, count = dataModel->rowCount(); i < count; i++) { struct plot_data *entry = dataModel->data().entry + i; for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++) { int mbar = GET_PRESSURE(entry, cyl); if (!mbar) continue; if (!seen_cyl[cyl]) { double value_y_offset, label_y_offset; // Magic Y offset depending on whether we're aliging // the top of the text or the bottom of the text to // the pressure line. value_y_offset = -0.5; if (alignVar & Qt::AlignTop) { label_y_offset = 5 * axisLog; } else { label_y_offset = -7 * axisLog; } plotPressureValue(mbar, entry->sec, alignVar, value_y_offset); plotGasValue(mbar, entry->sec, displayed_dive.cylinder[cyl].gasmix, alignVar, label_y_offset); seen_cyl[cyl] = true; /* Alternate alignment as we see cylinder use.. */ align[cyl] = alignVar; alignVar ^= Qt::AlignTop | Qt::AlignBottom; } last_pressure[cyl] = mbar; last_time[cyl] = entry->sec; } } // For each cylinder, on right hand side of profile, write cylinder pressure for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++) { if (last_time[cyl]) { double value_y_offset = -0.5; plotPressureValue(last_pressure[cyl], last_time[cyl], align[cyl] | Qt::AlignLeft, value_y_offset); } } }