diff options
Diffstat (limited to 'desktop-widgets/profile/profilewidget2.cpp')
-rw-r--r-- | desktop-widgets/profile/profilewidget2.cpp | 1836 |
1 files changed, 0 insertions, 1836 deletions
diff --git a/desktop-widgets/profile/profilewidget2.cpp b/desktop-widgets/profile/profilewidget2.cpp deleted file mode 100644 index 3ccd1bb6d..000000000 --- a/desktop-widgets/profile/profilewidget2.cpp +++ /dev/null @@ -1,1836 +0,0 @@ -#include "profilewidget2.h" -#include "diveplotdatamodel.h" -#include "helpers.h" -#include "profile.h" -#include "diveeventitem.h" -#include "divetextitem.h" -#include "divetooltipitem.h" -#include "planner.h" -#include "device.h" -#include "ruleritem.h" -#include "tankitem.h" -#include "pref.h" -#include "divepicturewidget.h" -#include "diveplannermodel.h" -#include "models.h" -#include "divepicturemodel.h" -#include "maintab.h" -#include "diveplanner.h" - -#include <libdivecomputer/parser.h> -#include <QScrollBar> -#include <QtCore/qmath.h> -#include <QMessageBox> -#include <QInputDialog> -#include <QDebug> -#include <QWheelEvent> - -#ifndef QT_NO_DEBUG -#include <QTableView> -#endif -#include "mainwindow.h" -#include <preferences.h> - -/* This is the global 'Item position' variable. - * it should tell you where to position things up - * on the canvas. - * - * please, please, please, use this instead of - * hard coding the item on the scene with a random - * value. - */ -static struct _ItemPos { - struct _Pos { - QPointF on; - QPointF off; - }; - struct _Axis { - _Pos pos; - QLineF shrinked; - QLineF expanded; - QLineF intermediate; - }; - _Pos background; - _Pos dcLabel; - _Pos tankBar; - _Axis depth; - _Axis partialPressure; - _Axis partialPressureTissue; - _Axis partialPressureWithTankBar; - _Axis percentage; - _Axis percentageWithTankBar; - _Axis time; - _Axis cylinder; - _Axis temperature; - _Axis temperatureAll; - _Axis heartBeat; - _Axis heartBeatWithTankBar; -} itemPos; - -ProfileWidget2::ProfileWidget2(QWidget *parent) : QGraphicsView(parent), - currentState(INVALID), - dataModel(new DivePlotDataModel(this)), - zoomLevel(0), - zoomFactor(1.15), - background(new DivePixmapItem()), - backgroundFile(":poster"), - toolTipItem(new ToolTipItem()), - isPlotZoomed(prefs.zoomed_plot),// no! bad use of prefs. 'PreferencesDialog::loadSettings' NOT CALLED yet. - profileYAxis(new DepthAxis()), - gasYAxis(new PartialGasPressureAxis()), - temperatureAxis(new TemperatureAxis()), - timeAxis(new TimeAxis()), - diveProfileItem(new DiveProfileItem()), - temperatureItem(new DiveTemperatureItem()), - meanDepthItem(new DiveMeanDepthItem()), - cylinderPressureAxis(new DiveCartesianAxis()), - gasPressureItem(new DiveGasPressureItem()), - diveComputerText(new DiveTextItem()), - diveCeiling(new DiveCalculatedCeiling()), - gradientFactor(new DiveTextItem()), - reportedCeiling(new DiveReportedCeiling()), - pn2GasItem(new PartialPressureGasItem()), - pheGasItem(new PartialPressureGasItem()), - po2GasItem(new PartialPressureGasItem()), - o2SetpointGasItem(new PartialPressureGasItem()), - ccrsensor1GasItem(new PartialPressureGasItem()), - ccrsensor2GasItem(new PartialPressureGasItem()), - ccrsensor3GasItem(new PartialPressureGasItem()), - heartBeatAxis(new DiveCartesianAxis()), - heartBeatItem(new DiveHeartrateItem()), - percentageAxis(new DiveCartesianAxis()), - ambPressureItem(new DiveAmbPressureItem()), - gflineItem(new DiveGFLineItem()), - mouseFollowerVertical(new DiveLineItem()), - mouseFollowerHorizontal(new DiveLineItem()), - rulerItem(new RulerItem2()), - tankItem(new TankItem()), - isGrayscale(false), - printMode(false), - shouldCalculateMaxTime(true), - shouldCalculateMaxDepth(true), - fontPrintScale(1.0) -{ - // would like to be able to ASSERT here that PreferencesDialog::loadSettings has been called. - isPlotZoomed = prefs.zoomed_plot; // now it seems that 'prefs' has loaded our preferences - - memset(&plotInfo, 0, sizeof(plotInfo)); - - setupSceneAndFlags(); - setupItemSizes(); - setupItemOnScene(); - addItemsToScene(); - scene()->installEventFilter(this); - connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); - QAction *action = NULL; -#define ADD_ACTION(SHORTCUT, Slot) \ - action = new QAction(this); \ - action->setShortcut(SHORTCUT); \ - action->setShortcutContext(Qt::WindowShortcut); \ - addAction(action); \ - connect(action, SIGNAL(triggered(bool)), this, SLOT(Slot)); \ - actionsForKeys[SHORTCUT] = action; - - ADD_ACTION(Qt::Key_Escape, keyEscAction()); - ADD_ACTION(Qt::Key_Delete, keyDeleteAction()); - ADD_ACTION(Qt::Key_Up, keyUpAction()); - ADD_ACTION(Qt::Key_Down, keyDownAction()); - ADD_ACTION(Qt::Key_Left, keyLeftAction()); - ADD_ACTION(Qt::Key_Right, keyRightAction()); -#undef ADD_ACTION - -#if !defined(QT_NO_DEBUG) && defined(SHOW_PLOT_INFO_TABLE) - QTableView *diveDepthTableView = new QTableView(); - diveDepthTableView->setModel(dataModel); - diveDepthTableView->show(); -#endif -} - - -ProfileWidget2::~ProfileWidget2() -{ - delete background; - delete toolTipItem; - delete profileYAxis; - delete gasYAxis; - delete temperatureAxis; - delete timeAxis; - delete diveProfileItem; - delete temperatureItem; - delete meanDepthItem; - delete cylinderPressureAxis; - delete gasPressureItem; - delete diveComputerText; - delete diveCeiling; - delete reportedCeiling; - delete pn2GasItem; - delete pheGasItem; - delete po2GasItem; - delete o2SetpointGasItem; - delete ccrsensor1GasItem; - delete ccrsensor2GasItem; - delete ccrsensor3GasItem; - delete heartBeatAxis; - delete heartBeatItem; - delete percentageAxis; - delete ambPressureItem; - delete gflineItem; - delete mouseFollowerVertical; - delete mouseFollowerHorizontal; - delete rulerItem; - delete tankItem; -} - -#define SUBSURFACE_OBJ_DATA 1 -#define SUBSURFACE_OBJ_DC_TEXT 0x42 - -void ProfileWidget2::addItemsToScene() -{ - scene()->addItem(background); - scene()->addItem(toolTipItem); - scene()->addItem(profileYAxis); - scene()->addItem(gasYAxis); - scene()->addItem(temperatureAxis); - scene()->addItem(timeAxis); - scene()->addItem(diveProfileItem); - scene()->addItem(cylinderPressureAxis); - scene()->addItem(temperatureItem); - scene()->addItem(meanDepthItem); - scene()->addItem(gasPressureItem); - // I cannot seem to figure out if an object that I find with itemAt() on the scene - // is the object I am looking for - my guess is there's a simple way in Qt to do that - // but nothing I tried worked. - // so instead this adds a special magic key/value pair to the object to mark it - diveComputerText->setData(SUBSURFACE_OBJ_DATA, SUBSURFACE_OBJ_DC_TEXT); - scene()->addItem(diveComputerText); - scene()->addItem(diveCeiling); - scene()->addItem(gradientFactor); - scene()->addItem(reportedCeiling); - scene()->addItem(pn2GasItem); - scene()->addItem(pheGasItem); - scene()->addItem(po2GasItem); - scene()->addItem(o2SetpointGasItem); - scene()->addItem(ccrsensor1GasItem); - scene()->addItem(ccrsensor2GasItem); - scene()->addItem(ccrsensor3GasItem); - scene()->addItem(percentageAxis); - scene()->addItem(heartBeatAxis); - scene()->addItem(heartBeatItem); - scene()->addItem(rulerItem); - scene()->addItem(rulerItem->sourceNode()); - scene()->addItem(rulerItem->destNode()); - scene()->addItem(tankItem); - scene()->addItem(mouseFollowerHorizontal); - scene()->addItem(mouseFollowerVertical); - QPen pen(QColor(Qt::red).lighter()); - pen.setWidth(0); - mouseFollowerHorizontal->setPen(pen); - mouseFollowerVertical->setPen(pen); - Q_FOREACH (DiveCalculatedTissue *tissue, allTissues) { - scene()->addItem(tissue); - } - Q_FOREACH (DivePercentageItem *percentage, allPercentages) { - scene()->addItem(percentage); - } - scene()->addItem(ambPressureItem); - scene()->addItem(gflineItem); -} - -void ProfileWidget2::setupItemOnScene() -{ - background->setZValue(9999); - toolTipItem->setZValue(9998); - toolTipItem->setTimeAxis(timeAxis); - rulerItem->setZValue(9997); - tankItem->setZValue(100); - - profileYAxis->setOrientation(DiveCartesianAxis::TopToBottom); - profileYAxis->setMinimum(0); - profileYAxis->setTickInterval(M_OR_FT(10, 30)); - profileYAxis->setTickSize(0.5); - profileYAxis->setLineSize(96); - - timeAxis->setLineSize(92); - timeAxis->setTickSize(-0.5); - - gasYAxis->setOrientation(DiveCartesianAxis::BottomToTop); - gasYAxis->setTickInterval(1); - gasYAxis->setTickSize(1); - gasYAxis->setMinimum(0); - gasYAxis->setModel(dataModel); - gasYAxis->setFontLabelScale(0.7); - gasYAxis->setLineSize(96); - - heartBeatAxis->setOrientation(DiveCartesianAxis::BottomToTop); - heartBeatAxis->setTickSize(0.2); - heartBeatAxis->setTickInterval(10); - heartBeatAxis->setFontLabelScale(0.7); - 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->setTickSize(2); - temperatureAxis->setTickInterval(300); - - cylinderPressureAxis->setOrientation(DiveCartesianAxis::BottomToTop); - cylinderPressureAxis->setTickSize(2); - cylinderPressureAxis->setTickInterval(30000); - - - diveComputerText->setAlignment(Qt::AlignRight | Qt::AlignTop); - diveComputerText->setBrush(getColor(TIME_TEXT, isGrayscale)); - - rulerItem->setAxis(timeAxis, profileYAxis); - tankItem->setHorizontalAxis(timeAxis); - - // show the gradient factor at the top in the center - gradientFactor->setY(0); - gradientFactor->setX(50); - gradientFactor->setBrush(getColor(PRESSURE_TEXT)); - gradientFactor->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); - - setupItem(reportedCeiling, timeAxis, profileYAxis, dataModel, DivePlotDataModel::CEILING, DivePlotDataModel::TIME, 1); - setupItem(diveCeiling, timeAxis, profileYAxis, dataModel, DivePlotDataModel::CEILING, DivePlotDataModel::TIME, 1); - for (int i = 0; i < 16; i++) { - DiveCalculatedTissue *tissueItem = new DiveCalculatedTissue(); - setupItem(tissueItem, timeAxis, profileYAxis, dataModel, DivePlotDataModel::TISSUE_1 + i, DivePlotDataModel::TIME, 1 + i); - 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(temperatureItem, timeAxis, temperatureAxis, dataModel, DivePlotDataModel::TEMPERATURE, 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(meanDepthItem, timeAxis, profileYAxis, dataModel, DivePlotDataModel::INSTANT_MEANDEPTH, DivePlotDataModel::TIME, 1); - - -#define CREATE_PP_GAS(ITEM, VERTICAL_COLUMN, COLOR, COLOR_ALERT, THRESHOULD_SETTINGS, VISIBILITY_SETTINGS) \ - setupItem(ITEM, timeAxis, gasYAxis, dataModel, DivePlotDataModel::VERTICAL_COLUMN, DivePlotDataModel::TIME, 0); \ - ITEM->setThreshouldSettingsKey(THRESHOULD_SETTINGS); \ - ITEM->setVisibilitySettingsKey(VISIBILITY_SETTINGS); \ - ITEM->setColors(getColor(COLOR, isGrayscale), getColor(COLOR_ALERT, isGrayscale)); \ - ITEM->settingsChanged(); \ - ITEM->setZValue(99); - - CREATE_PP_GAS(pn2GasItem, PN2, PN2, PN2_ALERT, &prefs.pp_graphs.pn2_threshold, "pn2graph"); - CREATE_PP_GAS(pheGasItem, PHE, PHE, PHE_ALERT, &prefs.pp_graphs.phe_threshold, "phegraph"); - CREATE_PP_GAS(po2GasItem, PO2, PO2, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "po2graph"); - CREATE_PP_GAS(o2SetpointGasItem, O2SETPOINT, PO2_ALERT, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "po2graph"); - CREATE_PP_GAS(ccrsensor1GasItem, CCRSENSOR1, CCRSENSOR1, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "ccrsensorgraph"); - CREATE_PP_GAS(ccrsensor2GasItem, CCRSENSOR2, CCRSENSOR2, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "ccrsensorgraph"); - CREATE_PP_GAS(ccrsensor3GasItem, CCRSENSOR3, CCRSENSOR3, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "ccrsensorgraph"); -#undef CREATE_PP_GAS - - temperatureAxis->setTextVisible(false); - temperatureAxis->setLinesVisible(false); - cylinderPressureAxis->setTextVisible(false); - cylinderPressureAxis->setLinesVisible(false); - timeAxis->setLinesVisible(true); - profileYAxis->setLinesVisible(true); - gasYAxis->setZValue(timeAxis->zValue() + 1); - heartBeatAxis->setTextVisible(true); - heartBeatAxis->setLinesVisible(true); - percentageAxis->setTextVisible(true); - percentageAxis->setLinesVisible(true); - - replotEnabled = true; -} - -void ProfileWidget2::replot(struct dive *d) -{ - if (!replotEnabled) - return; - dataModel->clear(); - plotDive(d, true); -} - -void ProfileWidget2::setupItemSizes() -{ - // Scene is *always* (double) 100 / 100. - // Background Config - /* Much probably a better math is needed here. - * good thing is that we only need to change the - * Axis and everything else is auto-adjusted.* - */ - - itemPos.background.on.setX(0); - itemPos.background.on.setY(0); - itemPos.background.off.setX(0); - itemPos.background.off.setY(110); - - //Depth Axis Config - itemPos.depth.pos.on.setX(3); - itemPos.depth.pos.on.setY(3); - itemPos.depth.pos.off.setX(-2); - itemPos.depth.pos.off.setY(3); - itemPos.depth.expanded.setP1(QPointF(0, 0)); - itemPos.depth.expanded.setP2(QPointF(0, 85)); - itemPos.depth.shrinked.setP1(QPointF(0, 0)); - itemPos.depth.shrinked.setP2(QPointF(0, 55)); - itemPos.depth.intermediate.setP1(QPointF(0, 0)); - itemPos.depth.intermediate.setP2(QPointF(0, 65)); - - // Time Axis Config - itemPos.time.pos.on.setX(3); - itemPos.time.pos.on.setY(95); - itemPos.time.pos.off.setX(3); - itemPos.time.pos.off.setY(110); - itemPos.time.expanded.setP1(QPointF(0, 0)); - itemPos.time.expanded.setP2(QPointF(94, 0)); - - // Partial Gas Axis Config - itemPos.partialPressure.pos.on.setX(97); - itemPos.partialPressure.pos.on.setY(75); - itemPos.partialPressure.pos.off.setX(110); - itemPos.partialPressure.pos.off.setY(63); - itemPos.partialPressure.expanded.setP1(QPointF(0, 0)); - itemPos.partialPressure.expanded.setP2(QPointF(0, 19)); - itemPos.partialPressureWithTankBar = itemPos.partialPressure; - itemPos.partialPressureWithTankBar.expanded.setP2(QPointF(0, 17)); - itemPos.partialPressureTissue = itemPos.partialPressure; - itemPos.partialPressureTissue.pos.on.setX(97); - itemPos.partialPressureTissue.pos.on.setY(65); - itemPos.partialPressureTissue.expanded.setP2(QPointF(0, 16)); - - // cylinder axis config - itemPos.cylinder.pos.on.setX(3); - itemPos.cylinder.pos.on.setY(20); - itemPos.cylinder.pos.off.setX(-10); - itemPos.cylinder.pos.off.setY(20); - itemPos.cylinder.expanded.setP1(QPointF(0, 15)); - itemPos.cylinder.expanded.setP2(QPointF(0, 50)); - itemPos.cylinder.shrinked.setP1(QPointF(0, 0)); - itemPos.cylinder.shrinked.setP2(QPointF(0, 20)); - itemPos.cylinder.intermediate.setP1(QPointF(0, 0)); - itemPos.cylinder.intermediate.setP2(QPointF(0, 20)); - - // Temperature axis config - itemPos.temperature.pos.on.setX(3); - itemPos.temperature.pos.on.setY(60); - itemPos.temperatureAll.pos.on.setY(51); - itemPos.temperature.pos.off.setX(-10); - itemPos.temperature.pos.off.setY(40); - itemPos.temperature.expanded.setP1(QPointF(0, 20)); - itemPos.temperature.expanded.setP2(QPointF(0, 33)); - itemPos.temperature.shrinked.setP1(QPointF(0, 2)); - itemPos.temperature.shrinked.setP2(QPointF(0, 12)); - itemPos.temperature.intermediate.setP1(QPointF(0, 2)); - itemPos.temperature.intermediate.setP2(QPointF(0, 12)); - - // Heartbeat axis config - itemPos.heartBeat.pos.on.setX(3); - itemPos.heartBeat.pos.on.setY(82); - itemPos.heartBeat.expanded.setP1(QPointF(0, 0)); - itemPos.heartBeat.expanded.setP2(QPointF(0, 10)); - itemPos.heartBeatWithTankBar = itemPos.heartBeat; - itemPos.heartBeatWithTankBar.expanded.setP2(QPointF(0, 7)); - - // Percentage axis config - itemPos.percentage.pos.on.setX(3); - itemPos.percentage.pos.on.setY(80); - itemPos.percentage.expanded.setP1(QPointF(0, 0)); - itemPos.percentage.expanded.setP2(QPointF(0, 15)); - itemPos.percentageWithTankBar = itemPos.percentage; - itemPos.percentageWithTankBar.expanded.setP2(QPointF(0, 12)); - - itemPos.dcLabel.on.setX(3); - itemPos.dcLabel.on.setY(100); - itemPos.dcLabel.off.setX(-10); - itemPos.dcLabel.off.setY(100); - - itemPos.tankBar.on.setX(0); - itemPos.tankBar.on.setY(91.5); -} - -void ProfileWidget2::setupItem(AbstractProfilePolygonItem *item, DiveCartesianAxis *hAxis, - DiveCartesianAxis *vAxis, DivePlotDataModel *model, - int vData, int hData, int zValue) -{ - item->setHorizontalAxis(hAxis); - item->setVerticalAxis(vAxis); - item->setModel(model); - item->setVerticalDataColumn(vData); - item->setHorizontalDataColumn(hData); - item->setZValue(zValue); -} - -void ProfileWidget2::setupSceneAndFlags() -{ - setScene(new QGraphicsScene(this)); - scene()->setSceneRect(0, 0, 100, 100); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - scene()->setItemIndexMethod(QGraphicsScene::NoIndex); - setOptimizationFlags(QGraphicsView::DontSavePainterState); - setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); - setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - setMouseTracking(true); - background->setFlag(QGraphicsItem::ItemIgnoresTransformations); -} - -void ProfileWidget2::resetZoom() -{ - if (!zoomLevel) - return; - const qreal defScale = 1.0 / qPow(zoomFactor, (qreal)zoomLevel); - scale(defScale, defScale); - zoomLevel = 0; -} - -// Currently just one dive, but the plan is to enable All of the selected dives. -void ProfileWidget2::plotDive(struct dive *d, bool force) -{ - static bool firstCall = true; - QTime measureDuration; // let's measure how long this takes us (maybe we'll turn of TTL calculation later - measureDuration.start(); - - if (currentState != ADD && currentState != PLAN) { - if (!d) { - if (selected_dive == -1) - return; - d = current_dive; // display the current dive - } - - // No need to do this again if we are already showing the same dive - // computer of the same dive, so we check the unique id of the dive - // and the selected dive computer number against the ones we are - // showing (can't compare the dive pointers as those might change). - if (d->id == displayed_dive.id && dc_number == dataModel->dcShown() && !force) - return; - - // this copies the dive and makes copies of all the relevant additional data - copy_dive(d, &displayed_dive); - gradientFactor->setText(QString("GF %1/%2").arg(prefs.gflow).arg(prefs.gfhigh)); - } else { - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - plannerModel->createTemporaryPlan(); - struct diveplan &diveplan = plannerModel->getDiveplan(); - if (!diveplan.dp) { - plannerModel->deleteTemporaryPlan(); - return; - } - gradientFactor->setText(QString("GF %1/%2").arg(diveplan.gflow).arg(diveplan.gfhigh)); - } - - // special handling for the first time we display things - int animSpeedBackup = 0; - if (firstCall && MainWindow::instance()->filesFromCommandLine()) { - animSpeedBackup = prefs.animation_speed; - prefs.animation_speed = 0; - firstCall = false; - } - - // restore default zoom level - resetZoom(); - - // reset some item visibility on printMode changes - toolTipItem->setVisible(!printMode); - rulerItem->setVisible(prefs.rulergraph && !printMode && currentState != PLAN && currentState != ADD); - - if (currentState == EMPTY) - setProfileState(); - - // next get the dive computer structure - if there are no samples - // let's create a fake profile that's somewhat reasonable for the - // data that we have - struct divecomputer *currentdc = select_dc(&displayed_dive); - Q_ASSERT(currentdc); - if (!currentdc || !currentdc->samples) { - currentdc = fake_dc(currentdc); - } - - bool setpointflag = (currentdc->divemode == CCR) && prefs.pp_graphs.po2 && current_dive; - bool sensorflag = setpointflag && prefs.show_ccr_sensors; - o2SetpointGasItem->setVisible(setpointflag && prefs.show_ccr_setpoint); - ccrsensor1GasItem->setVisible(sensorflag); - ccrsensor2GasItem->setVisible(sensorflag && (currentdc->no_o2sensors > 1)); - ccrsensor3GasItem->setVisible(sensorflag && (currentdc->no_o2sensors > 2)); - - /* This struct holds all the data that's about to be plotted. - * I'm not sure this is the best approach ( but since we are - * interpolating some points of the Dive, maybe it is... ) - * The Calculation of the points should be done per graph, - * so I'll *not* calculate everything if something is not being - * shown. - */ - plotInfo = calculate_max_limits_new(&displayed_dive, currentdc); - create_plot_info_new(&displayed_dive, currentdc, &plotInfo, !shouldCalculateMaxDepth); - if (shouldCalculateMaxTime) - maxtime = get_maxtime(&plotInfo); - - /* Only update the max depth if it's bigger than the current ones - * when we are dragging the handler to plan / add dive. - * otherwhise, update normally. - */ - int newMaxDepth = get_maxdepth(&plotInfo); - if (!shouldCalculateMaxDepth) { - if (maxdepth < newMaxDepth) { - maxdepth = newMaxDepth; - } - } else { - maxdepth = newMaxDepth; - } - - dataModel->setDive(&displayed_dive, plotInfo); - toolTipItem->setPlotInfo(plotInfo); - - // It seems that I'll have a lot of boilerplate setting the model / axis for - // each item, I'll mostly like to fix this in the future, but I'll keep at this for now. - profileYAxis->setMaximum(maxdepth); - profileYAxis->updateTicks(); - - temperatureAxis->setMinimum(plotInfo.mintemp); - temperatureAxis->setMaximum(plotInfo.maxtemp - plotInfo.mintemp > 2000 ? plotInfo.maxtemp : plotInfo.mintemp + 2000); - - if (plotInfo.maxhr) { - heartBeatAxis->setMinimum(plotInfo.minhr); - heartBeatAxis->setMaximum(plotInfo.maxhr); - heartBeatAxis->updateTicks(HR_AXIS); // this shows the ticks - } - heartBeatAxis->setVisible(prefs.hrgraph && plotInfo.maxhr); - - percentageAxis->setMinimum(0); - percentageAxis->setMaximum(100); - percentageAxis->setVisible(false); - percentageAxis->updateTicks(HR_AXIS); - - timeAxis->setMaximum(maxtime); - int i, incr; - static int increments[8] = { 10, 20, 30, 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60 }; - /* Time markers: at most every 10 seconds, but no more than 12 markers. - * We start out with 10 seconds and increment up to 30 minutes, - * depending on the dive time. - * This allows for 6h dives - enough (I hope) for even the craziest - * divers - but just in case, for those 8h depth-record-breaking dives, - * we double the interval if this still doesn't get us to 12 or fewer - * time markers */ - i = 0; - while (i < 7 && maxtime / increments[i] > 12) - i++; - incr = increments[i]; - while (maxtime / incr > 12) - incr *= 2; - timeAxis->setTickInterval(incr); - timeAxis->updateTicks(); - cylinderPressureAxis->setMinimum(plotInfo.minpressure); - cylinderPressureAxis->setMaximum(plotInfo.maxpressure); - - rulerItem->setPlotInfo(plotInfo); - tankItem->setData(dataModel, &plotInfo, &displayed_dive); - - dataModel->emitDataChanged(); - // The event items are a bit special since we don't know how many events are going to - // exist on a dive, so I cant create cache items for that. that's why they are here - // while all other items are up there on the constructor. - qDeleteAll(eventItems); - eventItems.clear(); - struct event *event = currentdc->events; - while (event) { - // if print mode is selected only draw headings, SP change, gas events or bookmark event - if (printMode) { - if (same_string(event->name, "") || - !(strcmp(event->name, "heading") == 0 || - (same_string(event->name, "SP change") && event->time.seconds == 0) || - event_is_gaschange(event) || - event->type == SAMPLE_EVENT_BOOKMARK)) { - event = event->next; - continue; - } - } - DiveEventItem *item = new DiveEventItem(); - item->setHorizontalAxis(timeAxis); - item->setVerticalAxis(profileYAxis); - item->setModel(dataModel); - item->setEvent(event); - item->setZValue(2); - scene()->addItem(item); - eventItems.push_back(item); - event = event->next; - } - // Only set visible the events that should be visible - Q_FOREACH (DiveEventItem *event, eventItems) { - event->setVisible(!event->shouldBeHidden()); - } - QString dcText = get_dc_nickname(currentdc->model, currentdc->deviceid); - int nr; - if ((nr = number_of_computers(&displayed_dive)) > 1) - dcText += tr(" (#%1 of %2)").arg(dc_number + 1).arg(nr); - if (dcText.isEmpty()) - dcText = tr("Unknown dive computer"); - diveComputerText->setText(dcText); - if (MainWindow::instance()->filesFromCommandLine() && animSpeedBackup != 0) { - prefs.animation_speed = animSpeedBackup; - } - - if (currentState == ADD || currentState == PLAN) { // TODO: figure a way to move this from here. - repositionDiveHandlers(); - DivePlannerPointsModel *model = DivePlannerPointsModel::instance(); - model->deleteTemporaryPlan(); - } - plotPictures(); - - // OK, how long did this take us? Anything above the second is way too long, - // so if we are calculation TTS / NDL then let's force that off. - if (measureDuration.elapsed() > 1000 && prefs.calcndltts) { - MainWindow::instance()->turnOffNdlTts(); - MainWindow::instance()->getNotificationWidget()->showNotification(tr("Show NDL / TTS was disabled because of excessive processing time"), KMessageWidget::Error); - } - MainWindow::instance()->getNotificationWidget()->showNotification(get_error_string(), KMessageWidget::Error); - -} - -void ProfileWidget2::recalcCeiling() -{ - diveCeiling->recalc(); -} - -void ProfileWidget2::settingsChanged() -{ - // if we are showing calculated ceilings then we have to replot() - // because the GF could have changed; otherwise we try to avoid replot() - bool needReplot = prefs.calcceiling; - if ((prefs.percentagegraph||prefs.hrgraph) && PP_GRAPHS_ENABLED) { - profileYAxis->animateChangeLine(itemPos.depth.shrinked); - temperatureAxis->setPos(itemPos.temperatureAll.pos.on); - temperatureAxis->animateChangeLine(itemPos.temperature.shrinked); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.shrinked); - - if (prefs.tankbar) { - percentageAxis->setPos(itemPos.percentageWithTankBar.pos.on); - percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded); - heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded); - }else { - percentageAxis->setPos(itemPos.percentage.pos.on); - percentageAxis->animateChangeLine(itemPos.percentage.expanded); - heartBeatAxis->setPos(itemPos.heartBeat.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded); - } - gasYAxis->setPos(itemPos.partialPressureTissue.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressureTissue.expanded); - - } else if (PP_GRAPHS_ENABLED || prefs.hrgraph || prefs.percentagegraph) { - profileYAxis->animateChangeLine(itemPos.depth.intermediate); - temperatureAxis->setPos(itemPos.temperature.pos.on); - temperatureAxis->animateChangeLine(itemPos.temperature.intermediate); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.intermediate); - if (prefs.tankbar) { - percentageAxis->setPos(itemPos.percentageWithTankBar.pos.on); - percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded); - gasYAxis->setPos(itemPos.partialPressureWithTankBar.pos.on); - gasYAxis->setLine(itemPos.partialPressureWithTankBar.expanded); - heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded); - } else { - gasYAxis->setPos(itemPos.partialPressure.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressure.expanded); - percentageAxis->setPos(itemPos.percentage.pos.on); - percentageAxis->setLine(itemPos.percentage.expanded); - heartBeatAxis->setPos(itemPos.heartBeat.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded); - } - } else { - profileYAxis->animateChangeLine(itemPos.depth.expanded); - if (prefs.tankbar) { - temperatureAxis->setPos(itemPos.temperatureAll.pos.on); - } else { - temperatureAxis->setPos(itemPos.temperature.pos.on); - } - temperatureAxis->animateChangeLine(itemPos.temperature.expanded); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.expanded); - } - - tankItem->setVisible(prefs.tankbar); - if (prefs.zoomed_plot != isPlotZoomed) { - isPlotZoomed = prefs.zoomed_plot; - needReplot = true; - } - if (needReplot) - replot(); -} - -void ProfileWidget2::resizeEvent(QResizeEvent *event) -{ - QGraphicsView::resizeEvent(event); - fitInView(sceneRect(), Qt::IgnoreAspectRatio); - fixBackgroundPos(); -} - -void ProfileWidget2::mousePressEvent(QMouseEvent *event) -{ - if (zoomLevel) - return; - QGraphicsView::mousePressEvent(event); - if (currentState == PLAN) - shouldCalculateMaxTime = false; -} - -void ProfileWidget2::divePlannerHandlerClicked() -{ - if (zoomLevel) - return; - shouldCalculateMaxDepth = false; - replot(); -} - -void ProfileWidget2::divePlannerHandlerReleased() -{ - if (zoomLevel) - return; - shouldCalculateMaxDepth = true; - replot(); -} - -void ProfileWidget2::mouseReleaseEvent(QMouseEvent *event) -{ - if (zoomLevel) - return; - QGraphicsView::mouseReleaseEvent(event); - if (currentState == PLAN) { - shouldCalculateMaxTime = true; - replot(); - } -} - -void ProfileWidget2::fixBackgroundPos() -{ - static QPixmap toBeScaled(backgroundFile); - if (currentState != EMPTY) - return; - QPixmap p = toBeScaled.scaledToHeight(viewport()->height() - 40, Qt::SmoothTransformation); - int x = viewport()->width() / 2 - p.width() / 2; - int y = viewport()->height() / 2 - p.height() / 2; - background->setPixmap(p); - background->setX(mapToScene(x, 0).x()); - background->setY(mapToScene(y, 20).y()); -} - -void ProfileWidget2::wheelEvent(QWheelEvent *event) -{ - if (currentState == EMPTY) - return; - QPoint toolTipPos = mapFromScene(toolTipItem->pos()); - if (event->buttons() == Qt::LeftButton) - return; - if (event->delta() > 0 && zoomLevel < 20) { - scale(zoomFactor, zoomFactor); - zoomLevel++; - } else if (event->delta() < 0 && zoomLevel > 0) { - // Zooming out - scale(1.0 / zoomFactor, 1.0 / zoomFactor); - zoomLevel--; - } - scrollViewTo(event->pos()); - toolTipItem->setPos(mapToScene(toolTipPos)); -} - -void ProfileWidget2::mouseDoubleClickEvent(QMouseEvent *event) -{ - if (currentState == PLAN || currentState == ADD) { - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - QPointF mappedPos = mapToScene(event->pos()); - if (isPointOutOfBoundaries(mappedPos)) - return; - - int minutes = rint(timeAxis->valueAt(mappedPos) / 60); - int milimeters = rint(profileYAxis->valueAt(mappedPos) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); - plannerModel->addStop(milimeters, minutes * 60, 0, 0, true); - } -} - -bool ProfileWidget2::isPointOutOfBoundaries(const QPointF &point) const -{ - double xpos = timeAxis->valueAt(point); - double ypos = profileYAxis->valueAt(point); - return (xpos > timeAxis->maximum() || - xpos < timeAxis->minimum() || - ypos > profileYAxis->maximum() || - ypos < profileYAxis->minimum()); -} - -void ProfileWidget2::scrollViewTo(const QPoint &pos) -{ - /* since we cannot use translate() directly on the scene we hack on - * the scroll bars (hidden) functionality */ - if (!zoomLevel || currentState == EMPTY) - return; - QScrollBar *vs = verticalScrollBar(); - QScrollBar *hs = horizontalScrollBar(); - const qreal yRat = (qreal)pos.y() / viewport()->height(); - const qreal xRat = (qreal)pos.x() / viewport()->width(); - vs->setValue(yRat * vs->maximum()); - hs->setValue(xRat * hs->maximum()); -} - -void ProfileWidget2::mouseMoveEvent(QMouseEvent *event) -{ - QPointF pos = mapToScene(event->pos()); - toolTipItem->refresh(pos); - if (zoomLevel == 0) { - QGraphicsView::mouseMoveEvent(event); - } else { - QPoint toolTipPos = mapFromScene(toolTipItem->pos()); - scrollViewTo(event->pos()); - toolTipItem->setPos(mapToScene(toolTipPos)); - } - - qreal vValue = profileYAxis->valueAt(pos); - qreal hValue = timeAxis->valueAt(pos); - if (profileYAxis->maximum() >= vValue && profileYAxis->minimum() <= vValue) { - mouseFollowerHorizontal->setPos(timeAxis->pos().x(), pos.y()); - } - if (timeAxis->maximum() >= hValue && timeAxis->minimum() <= hValue) { - mouseFollowerVertical->setPos(pos.x(), profileYAxis->line().y1()); - } -} - -bool ProfileWidget2::eventFilter(QObject *object, QEvent *event) -{ - QGraphicsScene *s = qobject_cast<QGraphicsScene *>(object); - if (s && event->type() == QEvent::GraphicsSceneHelp) { - event->ignore(); - return true; - } - return QGraphicsView::eventFilter(object, event); -} - -void ProfileWidget2::setEmptyState() -{ - // Then starting Empty State, move the background up. - if (currentState == EMPTY) - return; - - disconnectTemporaryConnections(); - setBackgroundBrush(getColor(::BACKGROUND, isGrayscale)); - dataModel->clear(); - currentState = EMPTY; - MainWindow::instance()->setEnabledToolbar(false); - - fixBackgroundPos(); - background->setVisible(true); - - profileYAxis->setVisible(false); - gasYAxis->setVisible(false); - timeAxis->setVisible(false); - temperatureAxis->setVisible(false); - cylinderPressureAxis->setVisible(false); - toolTipItem->setVisible(false); - diveComputerText->setVisible(false); - diveCeiling->setVisible(false); - gradientFactor->setVisible(false); - reportedCeiling->setVisible(false); - rulerItem->setVisible(false); - tankItem->setVisible(false); - pn2GasItem->setVisible(false); - po2GasItem->setVisible(false); - o2SetpointGasItem->setVisible(false); - ccrsensor1GasItem->setVisible(false); - ccrsensor2GasItem->setVisible(false); - ccrsensor3GasItem->setVisible(false); - pheGasItem->setVisible(false); - ambPressureItem->setVisible(false); - gflineItem->setVisible(false); - mouseFollowerHorizontal->setVisible(false); - mouseFollowerVertical->setVisible(false); - -#define HIDE_ALL(TYPE, CONTAINER) \ - Q_FOREACH (TYPE *item, CONTAINER) item->setVisible(false); - HIDE_ALL(DiveCalculatedTissue, allTissues); - HIDE_ALL(DivePercentageItem, allPercentages); - HIDE_ALL(DiveEventItem, eventItems); - HIDE_ALL(DiveHandler, handles); - HIDE_ALL(QGraphicsSimpleTextItem, gases); -#undef HIDE_ALL -} - -void ProfileWidget2::setProfileState() -{ - // Then starting Empty State, move the background up. - if (currentState == PROFILE) - return; - - disconnectTemporaryConnections(); - connect(DivePictureModel::instance(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(plotPictures())); - connect(DivePictureModel::instance(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(plotPictures())); - connect(DivePictureModel::instance(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(plotPictures())); - /* show the same stuff that the profile shows. */ - - //TODO: Move the DC handling to another method. - MainWindow::instance()->enableShortcuts(); - - currentState = PROFILE; - MainWindow::instance()->setEnabledToolbar(true); - toolTipItem->readPos(); - setBackgroundBrush(getColor(::BACKGROUND, isGrayscale)); - - background->setVisible(false); - toolTipItem->setVisible(true); - profileYAxis->setVisible(true); - gasYAxis->setVisible(true); - timeAxis->setVisible(true); - temperatureAxis->setVisible(true); - cylinderPressureAxis->setVisible(true); - - profileYAxis->setPos(itemPos.depth.pos.on); - if ((prefs.percentagegraph||prefs.hrgraph) && PP_GRAPHS_ENABLED) { - profileYAxis->animateChangeLine(itemPos.depth.shrinked); - temperatureAxis->setPos(itemPos.temperatureAll.pos.on); - temperatureAxis->animateChangeLine(itemPos.temperature.shrinked); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.shrinked); - - if (prefs.tankbar) { - percentageAxis->setPos(itemPos.percentageWithTankBar.pos.on); - percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded); - heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded); - }else { - percentageAxis->setPos(itemPos.percentage.pos.on); - percentageAxis->animateChangeLine(itemPos.percentage.expanded); - heartBeatAxis->setPos(itemPos.heartBeat.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded); - } - gasYAxis->setPos(itemPos.partialPressureTissue.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressureTissue.expanded); - - } else if (PP_GRAPHS_ENABLED || prefs.hrgraph || prefs.percentagegraph) { - profileYAxis->animateChangeLine(itemPos.depth.intermediate); - temperatureAxis->setPos(itemPos.temperature.pos.on); - temperatureAxis->animateChangeLine(itemPos.temperature.intermediate); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.intermediate); - if (prefs.tankbar) { - percentageAxis->setPos(itemPos.percentageWithTankBar.pos.on); - percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded); - gasYAxis->setPos(itemPos.partialPressureWithTankBar.pos.on); - gasYAxis->setLine(itemPos.partialPressureWithTankBar.expanded); - heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded); - } else { - gasYAxis->setPos(itemPos.partialPressure.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressure.expanded); - percentageAxis->setPos(itemPos.percentage.pos.on); - percentageAxis->setLine(itemPos.percentage.expanded); - heartBeatAxis->setPos(itemPos.heartBeat.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded); - } - } else { - profileYAxis->animateChangeLine(itemPos.depth.expanded); - if (prefs.tankbar) { - temperatureAxis->setPos(itemPos.temperatureAll.pos.on); - } else { - temperatureAxis->setPos(itemPos.temperature.pos.on); - } - temperatureAxis->animateChangeLine(itemPos.temperature.expanded); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.expanded); - } - pn2GasItem->setVisible(prefs.pp_graphs.pn2); - po2GasItem->setVisible(prefs.pp_graphs.po2); - pheGasItem->setVisible(prefs.pp_graphs.phe); - - bool setpointflag = current_dive && (current_dc->divemode == CCR) && prefs.pp_graphs.po2; - bool sensorflag = setpointflag && prefs.show_ccr_sensors; - o2SetpointGasItem->setVisible(setpointflag && prefs.show_ccr_setpoint); - ccrsensor1GasItem->setVisible(sensorflag); - ccrsensor2GasItem->setVisible(sensorflag && (current_dc->no_o2sensors > 1)); - ccrsensor3GasItem->setVisible(sensorflag && (current_dc->no_o2sensors > 2)); - - timeAxis->setPos(itemPos.time.pos.on); - timeAxis->setLine(itemPos.time.expanded); - - cylinderPressureAxis->setPos(itemPos.cylinder.pos.on); - heartBeatItem->setVisible(prefs.hrgraph); - meanDepthItem->setVisible(prefs.show_average_depth); - - diveComputerText->setVisible(true); - diveComputerText->setPos(itemPos.dcLabel.on); - - diveCeiling->setVisible(prefs.calcceiling); - gradientFactor->setVisible(prefs.calcceiling); - reportedCeiling->setVisible(prefs.dcceiling); - - if (prefs.calcalltissues) { - Q_FOREACH (DiveCalculatedTissue *tissue, allTissues) { - tissue->setVisible(true); - } - } - - if (prefs.percentagegraph) { - Q_FOREACH (DivePercentageItem *percentage, allPercentages) { - percentage->setVisible(true); - } - - ambPressureItem->setVisible(true); - gflineItem->setVisible(true); - } - - rulerItem->setVisible(prefs.rulergraph); - tankItem->setVisible(prefs.tankbar); - tankItem->setPos(itemPos.tankBar.on); - -#define HIDE_ALL(TYPE, CONTAINER) \ - Q_FOREACH (TYPE *item, CONTAINER) item->setVisible(false); - HIDE_ALL(DiveHandler, handles); - HIDE_ALL(QGraphicsSimpleTextItem, gases); -#undef HIDE_ALL - mouseFollowerHorizontal->setVisible(false); - mouseFollowerVertical->setVisible(false); -} - -void ProfileWidget2::clearHandlers() -{ - if (handles.count()) { - foreach (DiveHandler *handle, handles) { - scene()->removeItem(handle); - delete handle; - } - handles.clear(); - } -} - -void ProfileWidget2::setToolTipVisibile(bool visible) -{ - toolTipItem->setVisible(visible); -} - -void ProfileWidget2::setAddState() -{ - if (currentState == ADD) - return; - - clearHandlers(); - setProfileState(); - mouseFollowerHorizontal->setVisible(true); - mouseFollowerVertical->setVisible(true); - mouseFollowerHorizontal->setLine(timeAxis->line()); - mouseFollowerVertical->setLine(QLineF(0, profileYAxis->pos().y(), 0, timeAxis->pos().y())); - disconnectTemporaryConnections(); - //TODO: Move this method to another place, shouldn't be on mainwindow. - MainWindow::instance()->disableShortcuts(false); - actionsForKeys[Qt::Key_Left]->setShortcut(Qt::Key_Left); - actionsForKeys[Qt::Key_Right]->setShortcut(Qt::Key_Right); - actionsForKeys[Qt::Key_Up]->setShortcut(Qt::Key_Up); - actionsForKeys[Qt::Key_Down]->setShortcut(Qt::Key_Down); - actionsForKeys[Qt::Key_Escape]->setShortcut(Qt::Key_Escape); - actionsForKeys[Qt::Key_Delete]->setShortcut(Qt::Key_Delete); - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - connect(plannerModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(replot())); - connect(plannerModel, SIGNAL(cylinderModelEdited()), this, SLOT(replot())); - connect(plannerModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(pointInserted(const QModelIndex &, int, int))); - connect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(pointsRemoved(const QModelIndex &, int, int))); - /* show the same stuff that the profile shows. */ - currentState = ADD; /* enable the add state. */ - diveCeiling->setVisible(true); - gradientFactor->setVisible(true); - setBackgroundBrush(QColor("#A7DCFF")); -} - -void ProfileWidget2::setPlanState() -{ - if (currentState == PLAN) - return; - - setProfileState(); - mouseFollowerHorizontal->setVisible(true); - mouseFollowerVertical->setVisible(true); - mouseFollowerHorizontal->setLine(timeAxis->line()); - mouseFollowerVertical->setLine(QLineF(0, profileYAxis->pos().y(), 0, timeAxis->pos().y())); - disconnectTemporaryConnections(); - //TODO: Move this method to another place, shouldn't be on mainwindow. - MainWindow::instance()->disableShortcuts(); - actionsForKeys[Qt::Key_Left]->setShortcut(Qt::Key_Left); - actionsForKeys[Qt::Key_Right]->setShortcut(Qt::Key_Right); - actionsForKeys[Qt::Key_Up]->setShortcut(Qt::Key_Up); - actionsForKeys[Qt::Key_Down]->setShortcut(Qt::Key_Down); - actionsForKeys[Qt::Key_Escape]->setShortcut(Qt::Key_Escape); - actionsForKeys[Qt::Key_Delete]->setShortcut(Qt::Key_Delete); - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - connect(plannerModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(replot())); - connect(plannerModel, SIGNAL(cylinderModelEdited()), this, SLOT(replot())); - connect(plannerModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(pointInserted(const QModelIndex &, int, int))); - connect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(pointsRemoved(const QModelIndex &, int, int))); - /* show the same stuff that the profile shows. */ - currentState = PLAN; /* enable the add state. */ - diveCeiling->setVisible(true); - gradientFactor->setVisible(true); - setBackgroundBrush(QColor("#D7E3EF")); -} - -extern struct ev_select *ev_namelist; -extern int evn_allocated; -extern int evn_used; - -bool ProfileWidget2::isPlanner() -{ - return currentState == PLAN; -} - -bool ProfileWidget2::isAddOrPlanner() -{ - return currentState == PLAN || currentState == ADD; -} - -struct plot_data *ProfileWidget2::getEntryFromPos(QPointF pos) -{ - // find the time stamp corresponding to the mouse position - int seconds = timeAxis->valueAt(pos); - struct plot_data *entry = NULL; - - for (int i = 0; i < plotInfo.nr; i++) { - entry = plotInfo.entry + i; - if (entry->sec >= seconds) - break; - } - return entry; -} - -void ProfileWidget2::setReplot(bool state) -{ - replotEnabled = state; -} - -void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) -{ - if (currentState == ADD || currentState == PLAN) { - QGraphicsView::contextMenuEvent(event); - return; - } - QMenu m; - bool isDCName = false; - if (selected_dive == -1) - return; - // figure out if we are ontop of the dive computer name in the profile - QGraphicsItem *sceneItem = itemAt(mapFromGlobal(event->globalPos())); - if (sceneItem) { - QGraphicsItem *parentItem = sceneItem; - while (parentItem) { - if (parentItem->data(SUBSURFACE_OBJ_DATA) == SUBSURFACE_OBJ_DC_TEXT) { - isDCName = true; - break; - } - parentItem = parentItem->parentItem(); - } - if (isDCName) { - if (dc_number == 0 && count_divecomputers() == 1) - // nothing to do, can't delete or reorder - return; - // create menu to show when right clicking on dive computer name - if (dc_number > 0) - m.addAction(tr("Make first divecomputer"), this, SLOT(makeFirstDC())); - if (count_divecomputers() > 1) - m.addAction(tr("Delete this divecomputer"), this, SLOT(deleteCurrentDC())); - m.exec(event->globalPos()); - // don't show the regular profile context menu - return; - } - } - // create the profile context menu - QPointF scenePos = mapToScene(event->pos()); - struct plot_data *entry = getEntryFromPos(scenePos); - GasSelectionModel *model = GasSelectionModel::instance(); - model->repopulate(); - int rowCount = model->rowCount(); - if (rowCount > 1) { - // if we have more than one gas, offer to switch to another one - QMenu *gasChange = m.addMenu(tr("Add gas change")); - for (int i = 0; i < rowCount; i++) { - QAction *action = new QAction(&m); - action->setText(model->data(model->index(i, 0), Qt::DisplayRole).toString() + QString(tr(" (Tank %1)")).arg(i + 1)); - connect(action, SIGNAL(triggered(bool)), this, SLOT(changeGas())); - action->setData(event->globalPos()); - if (i == entry->cylinderindex) - action->setDisabled(true); - gasChange->addAction(action); - } - } - QAction *setpointAction = m.addAction(tr("Add set-point change"), this, SLOT(addSetpointChange())); - setpointAction->setData(event->globalPos()); - QAction *action = m.addAction(tr("Add bookmark"), this, SLOT(addBookmark())); - action->setData(event->globalPos()); - - if (same_string(current_dc->model, "manually added dive")) - QAction *editProfileAction = m.addAction(tr("Edit the profile"), MainWindow::instance(), SLOT(editCurrentDive())); - - if (DiveEventItem *item = dynamic_cast<DiveEventItem *>(sceneItem)) { - action = new QAction(&m); - action->setText(tr("Remove event")); - action->setData(QVariant::fromValue<void *>(item)); // so we know what to remove. - connect(action, SIGNAL(triggered(bool)), this, SLOT(removeEvent())); - m.addAction(action); - action = new QAction(&m); - action->setText(tr("Hide similar events")); - action->setData(QVariant::fromValue<void *>(item)); - connect(action, SIGNAL(triggered(bool)), this, SLOT(hideEvents())); - m.addAction(action); - struct event *dcEvent = item->getEvent(); - if (dcEvent->type == SAMPLE_EVENT_BOOKMARK) { - action = new QAction(&m); - action->setText(tr("Edit name")); - action->setData(QVariant::fromValue<void *>(item)); - connect(action, SIGNAL(triggered(bool)), this, SLOT(editName())); - m.addAction(action); - } -#if 0 // FIXME::: FINISH OR DISABLE - // this shows how to figure out if we should ask the user if they want adjust interpolated pressures - // at either side of a gas change - if (dcEvent->type == SAMPLE_EVENT_GASCHANGE || dcEvent->type == SAMPLE_EVENT_GASCHANGE2) { - qDebug() << "figure out if there are interpolated pressures"; - struct plot_data *gasChangeEntry = entry; - struct plot_data *newGasEntry; - while (gasChangeEntry > plotInfo.entry) { - --gasChangeEntry; - if (gasChangeEntry->sec <= dcEvent->time.seconds) - break; - } - qDebug() << "at gas change at" << gasChangeEntry->sec << ": sensor pressure" << gasChangeEntry->pressure[0] << "interpolated" << gasChangeEntry->pressure[1]; - // now gasChangeEntry points at the gas change, that entry has the final pressure of - // the old tank, the next entry has the starting pressure of the next tank - if (gasChangeEntry + 1 <= plotInfo.entry + plotInfo.nr) { - newGasEntry = gasChangeEntry + 1; - qDebug() << "after gas change at " << newGasEntry->sec << ": sensor pressure" << newGasEntry->pressure[0] << "interpolated" << newGasEntry->pressure[1]; - if (SENSOR_PRESSURE(gasChangeEntry) == 0 || displayed_dive.cylinder[gasChangeEntry->cylinderindex].sample_start.mbar == 0) { - // if we have no sensorpressure or if we have no pressure from samples we can assume that - // we only have interpolated pressure (the pressure in the entry may be stored in the sensor - // pressure field if this is the first or last entry for this tank... see details in gaspressures.c - pressure_t pressure; - pressure.mbar = INTERPOLATED_PRESSURE(gasChangeEntry) ? : SENSOR_PRESSURE(gasChangeEntry); - QAction *adjustOldPressure = m.addAction(tr("Adjust pressure of tank %1 (currently interpolated as %2)") - .arg(gasChangeEntry->cylinderindex + 1).arg(get_pressure_string(pressure))); - } - if (SENSOR_PRESSURE(newGasEntry) == 0 || displayed_dive.cylinder[newGasEntry->cylinderindex].sample_start.mbar == 0) { - // we only have interpolated press -- see commend above - pressure_t pressure; - pressure.mbar = INTERPOLATED_PRESSURE(newGasEntry) ? : SENSOR_PRESSURE(newGasEntry); - QAction *adjustOldPressure = m.addAction(tr("Adjust pressure of tank %1 (currently interpolated as %2)") - .arg(newGasEntry->cylinderindex + 1).arg(get_pressure_string(pressure))); - } - } - } -#endif - } - bool some_hidden = false; - for (int i = 0; i < evn_used; i++) { - if (ev_namelist[i].plot_ev == false) { - some_hidden = true; - break; - } - } - if (some_hidden) { - action = m.addAction(tr("Unhide all events"), this, SLOT(unhideEvents())); - action->setData(event->globalPos()); - } - m.exec(event->globalPos()); -} - -void ProfileWidget2::deleteCurrentDC() -{ - delete_current_divecomputer(); - mark_divelist_changed(true); - // we need to force it since it's likely the same dive and same dc_number - but that's a different dive computer now - MainWindow::instance()->graphics()->plotDive(0, true); - MainWindow::instance()->refreshDisplay(); -} - -void ProfileWidget2::makeFirstDC() -{ - make_first_dc(); - mark_divelist_changed(true); - // this is now the first DC, so we need to redraw the profile and refresh the dive list - // (and no, it's not just enough to rewrite the text - the first DC is special so values in the - // dive list may change). - // As a side benefit, this returns focus to the dive list. - dc_number = 0; - MainWindow::instance()->refreshDisplay(); -} - -void ProfileWidget2::hideEvents() -{ - QAction *action = qobject_cast<QAction *>(sender()); - DiveEventItem *item = static_cast<DiveEventItem *>(action->data().value<void *>()); - struct event *event = item->getEvent(); - - if (QMessageBox::question(MainWindow::instance(), - TITLE_OR_TEXT(tr("Hide events"), tr("Hide all %1 events?").arg(event->name)), - QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { - if (!same_string(event->name, "")) { - for (int i = 0; i < evn_used; i++) { - if (same_string(event->name, ev_namelist[i].ev_name)) { - ev_namelist[i].plot_ev = false; - break; - } - } - Q_FOREACH (DiveEventItem *evItem, eventItems) { - if (same_string(evItem->getEvent()->name, event->name)) - evItem->hide(); - } - } else { - item->hide(); - } - } -} - -void ProfileWidget2::unhideEvents() -{ - for (int i = 0; i < evn_used; i++) { - ev_namelist[i].plot_ev = true; - } - Q_FOREACH (DiveEventItem *item, eventItems) - item->show(); -} - -void ProfileWidget2::removeEvent() -{ - QAction *action = qobject_cast<QAction *>(sender()); - DiveEventItem *item = static_cast<DiveEventItem *>(action->data().value<void *>()); - struct event *event = item->getEvent(); - - if (QMessageBox::question(MainWindow::instance(), TITLE_OR_TEXT( - tr("Remove the selected event?"), - tr("%1 @ %2:%3").arg(event->name).arg(event->time.seconds / 60).arg(event->time.seconds % 60, 2, 10, QChar('0'))), - QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { - remove_event(event); - mark_divelist_changed(true); - replot(); - } -} - -void ProfileWidget2::addBookmark() -{ - QAction *action = qobject_cast<QAction *>(sender()); - QPointF scenePos = mapToScene(mapFromGlobal(action->data().toPoint())); - add_event(current_dc, timeAxis->valueAt(scenePos), SAMPLE_EVENT_BOOKMARK, 0, 0, "bookmark"); - mark_divelist_changed(true); - replot(); -} - -void ProfileWidget2::addSetpointChange() -{ - QAction *action = qobject_cast<QAction *>(sender()); - QPointF scenePos = mapToScene(mapFromGlobal(action->data().toPoint())); - SetpointDialog::instance()->setpointData(current_dc, timeAxis->valueAt(scenePos)); - SetpointDialog::instance()->show(); -} - -void ProfileWidget2::changeGas() -{ - QAction *action = qobject_cast<QAction *>(sender()); - QPointF scenePos = mapToScene(mapFromGlobal(action->data().toPoint())); - QString gas = action->text(); - gas.remove(QRegExp(" \\(.*\\)")); - - // backup the things on the dataModel, since we will clear that out. - struct gasmix gasmix; - qreal sec_val = timeAxis->valueAt(scenePos); - - // no gas changes before the dive starts - unsigned int seconds = (sec_val < 0.0) ? 0 : (unsigned int)sec_val; - - // if there is a gas change at this time stamp, remove it before adding the new one - struct event *gasChangeEvent = current_dc->events; - while ((gasChangeEvent = get_next_event(gasChangeEvent, "gaschange")) != NULL) { - if (gasChangeEvent->time.seconds == seconds) { - remove_event(gasChangeEvent); - gasChangeEvent = current_dc->events; - } else { - gasChangeEvent = gasChangeEvent->next; - } - } - validate_gas(gas.toUtf8().constData(), &gasmix); - QRegExp rx("\\(\\D*(\\d+)"); - int tank; - if (rx.indexIn(action->text()) > -1) { - tank = rx.cap(1).toInt() - 1; // we display the tank 1 based - } else { - qDebug() << "failed to parse tank number"; - tank = get_gasidx(&displayed_dive, &gasmix); - } - // add this both to the displayed dive and the current dive - add_gas_switch_event(current_dive, current_dc, seconds, tank); - add_gas_switch_event(&displayed_dive, get_dive_dc(&displayed_dive, dc_number), seconds, tank); - // this means we potentially have a new tank that is being used and needs to be shown - fixup_dive(&displayed_dive); - - // FIXME - this no longer gets written to the dive list - so we need to enableEdition() here - - MainWindow::instance()->information()->updateDiveInfo(); - mark_divelist_changed(true); - replot(); -} - -bool ProfileWidget2::getPrintMode() -{ - return printMode; -} - -void ProfileWidget2::setPrintMode(bool mode, bool grayscale) -{ - printMode = mode; - resetZoom(); - - // set printMode for axes - profileYAxis->setPrintMode(mode); - gasYAxis->setPrintMode(mode); - temperatureAxis->setPrintMode(mode); - timeAxis->setPrintMode(mode); - cylinderPressureAxis->setPrintMode(mode); - heartBeatAxis->setPrintMode(mode); - percentageAxis->setPrintMode(mode); - - isGrayscale = mode ? grayscale : false; - mouseFollowerHorizontal->setVisible(!mode); - mouseFollowerVertical->setVisible(!mode); -} - -void ProfileWidget2::setFontPrintScale(double scale) -{ - fontPrintScale = scale; - emit fontPrintScaleChanged(scale); -} - -double ProfileWidget2::getFontPrintScale() -{ - if (printMode) - return fontPrintScale; - else - return 1.0; -} - -void ProfileWidget2::editName() -{ - QAction *action = qobject_cast<QAction *>(sender()); - DiveEventItem *item = static_cast<DiveEventItem *>(action->data().value<void *>()); - struct event *event = item->getEvent(); - bool ok; - QString newName = QInputDialog::getText(MainWindow::instance(), tr("Edit name of bookmark"), - tr("Custom name:"), QLineEdit::Normal, - event->name, &ok); - if (ok && !newName.isEmpty()) { - if (newName.length() > 22) { //longer names will display as garbage. - QMessageBox lengthWarning; - lengthWarning.setText(tr("Name is too long!")); - lengthWarning.exec(); - return; - } - // order is important! first update the current dive (by matching the unchanged event), - // then update the displayed dive (as event is part of the events on displayed dive - // and will be freed as part of changing the name! - update_event_name(current_dive, event, newName.toUtf8().data()); - update_event_name(&displayed_dive, event, newName.toUtf8().data()); - mark_divelist_changed(true); - replot(); - } -} - -void ProfileWidget2::disconnectTemporaryConnections() -{ - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - disconnect(plannerModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(replot())); - disconnect(plannerModel, SIGNAL(cylinderModelEdited()), this, SLOT(replot())); - - disconnect(plannerModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(pointInserted(const QModelIndex &, int, int))); - disconnect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(pointsRemoved(const QModelIndex &, int, int))); - - Q_FOREACH (QAction *action, actionsForKeys.values()) { - action->setShortcut(QKeySequence()); - action->setShortcutContext(Qt::WidgetShortcut); - } -} - -void ProfileWidget2::pointInserted(const QModelIndex &parent, int start, int end) -{ - DiveHandler *item = new DiveHandler(); - scene()->addItem(item); - handles << item; - - connect(item, SIGNAL(moved()), this, SLOT(recreatePlannedDive())); - connect(item, SIGNAL(clicked()), this, SLOT(divePlannerHandlerClicked())); - connect(item, SIGNAL(released()), this, SLOT(divePlannerHandlerReleased())); - QGraphicsSimpleTextItem *gasChooseBtn = new QGraphicsSimpleTextItem(); - scene()->addItem(gasChooseBtn); - gasChooseBtn->setZValue(10); - gasChooseBtn->setFlag(QGraphicsItem::ItemIgnoresTransformations); - gases << gasChooseBtn; - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - if (plannerModel->recalcQ()) - replot(); -} - -void ProfileWidget2::pointsRemoved(const QModelIndex &, int start, int end) -{ // start and end are inclusive. - int num = (end - start) + 1; - for (int i = num; i != 0; i--) { - delete handles.back(); - handles.pop_back(); - delete gases.back(); - gases.pop_back(); - } - scene()->clearSelection(); - replot(); -} - -void ProfileWidget2::repositionDiveHandlers() -{ - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - // Re-position the user generated dive handlers - struct gasmix mix, lastmix; - for (int i = 0; i < plannerModel->rowCount(); i++) { - struct divedatapoint datapoint = plannerModel->at(i); - if (datapoint.time == 0) // those are the magic entries for tanks - continue; - DiveHandler *h = handles.at(i); - h->setVisible(datapoint.entered); - h->setPos(timeAxis->posAtValue(datapoint.time), profileYAxis->posAtValue(datapoint.depth)); - QPointF p1; - if (i == 0) { - if (prefs.drop_stone_mode) - // place the text on the straight line from the drop to stone position - p1 = QPointF(timeAxis->posAtValue(datapoint.depth / prefs.descrate), - profileYAxis->posAtValue(datapoint.depth)); - else - // place the text on the straight line from the origin to the first position - p1 = QPointF(timeAxis->posAtValue(0), profileYAxis->posAtValue(0)); - } else { - // place the text on the line from the last position - p1 = handles[i - 1]->pos(); - } - QPointF p2 = handles[i]->pos(); - QLineF line(p1, p2); - QPointF pos = line.pointAt(0.5); - gases[i]->setPos(pos); - gases[i]->setText(get_divepoint_gas_string(datapoint)); - gases[i]->setVisible(datapoint.entered && - (i == 0 || gases[i]->text() != gases[i-1]->text())); - } -} - -int ProfileWidget2::fixHandlerIndex(DiveHandler *activeHandler) -{ - int index = handles.indexOf(activeHandler); - if (index > 0 && index < handles.count() - 1) { - DiveHandler *before = handles[index - 1]; - if (before->pos().x() > activeHandler->pos().x()) { - handles.swap(index, index - 1); - return index - 1; - } - DiveHandler *after = handles[index + 1]; - if (after->pos().x() < activeHandler->pos().x()) { - handles.swap(index, index + 1); - return index + 1; - } - } - return index; -} - -void ProfileWidget2::recreatePlannedDive() -{ - DiveHandler *activeHandler = qobject_cast<DiveHandler *>(sender()); - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - int index = fixHandlerIndex(activeHandler); - int mintime = 0, maxtime = (timeAxis->maximum() + 10) * 60; - if (index > 0) - mintime = plannerModel->at(index - 1).time; - if (index < plannerModel->size() - 1) - maxtime = plannerModel->at(index + 1).time; - - int minutes = rint(timeAxis->valueAt(activeHandler->pos()) / 60); - if (minutes * 60 <= mintime || minutes * 60 >= maxtime) - return; - - divedatapoint data = plannerModel->at(index); - data.depth = rint(profileYAxis->valueAt(activeHandler->pos()) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); - data.time = rint(timeAxis->valueAt(activeHandler->pos())); - - plannerModel->editStop(index, data); -} - -void ProfileWidget2::keyDownAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - if (dp.depth >= profileYAxis->maximum()) - continue; - - dp.depth += M_OR_FT(1, 5); - plannerModel->editStop(row, dp); - } - } -} - -void ProfileWidget2::keyUpAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - - if (dp.depth <= 0) - continue; - - dp.depth -= M_OR_FT(1, 5); - plannerModel->editStop(row, dp); - } - } -} - -void ProfileWidget2::keyLeftAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - - if (dp.time / 60 <= 0) - continue; - - // don't overlap positions. - // maybe this is a good place for a 'goto'? - double xpos = timeAxis->posAtValue((dp.time - 60) / 60); - bool nextStep = false; - Q_FOREACH (DiveHandler *h, handles) { - if (IS_FP_SAME(h->pos().x(), xpos)) { - nextStep = true; - break; - } - } - if (nextStep) - continue; - - dp.time -= 60; - plannerModel->editStop(row, dp); - } - } -} - -void ProfileWidget2::keyRightAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - if (dp.time / 60.0 >= timeAxis->maximum()) - continue; - - // don't overlap positions. - // maybe this is a good place for a 'goto'? - double xpos = timeAxis->posAtValue((dp.time + 60) / 60); - bool nextStep = false; - Q_FOREACH (DiveHandler *h, handles) { - if (IS_FP_SAME(h->pos().x(), xpos)) { - nextStep = true; - break; - } - } - if (nextStep) - continue; - - dp.time += 60; - plannerModel->editStop(row, dp); - } - } -} - -void ProfileWidget2::keyDeleteAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - int selCount = scene()->selectedItems().count(); - if (selCount) { - QVector<int> selectedIndexes; - Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - selectedIndexes.push_back(handles.indexOf(handler)); - handler->hide(); - } - } - plannerModel->removeSelectedPoints(selectedIndexes); - } -} - -void ProfileWidget2::keyEscAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - if (scene()->selectedItems().count()) { - scene()->clearSelection(); - return; - } - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - if (plannerModel->isPlanner()) - plannerModel->cancelPlan(); -} - -void ProfileWidget2::plotPictures() -{ - Q_FOREACH (DivePictureItem *item, pictures) { - item->hide(); - item->deleteLater(); - } - pictures.clear(); - - if (printMode) - return; - - double x, y, lastX = -1.0, lastY = -1.0; - DivePictureModel *m = DivePictureModel::instance(); - for (int i = 0; i < m->rowCount(); i++) { - int offsetSeconds = m->index(i, 1).data(Qt::UserRole).value<int>(); - // it's a correct picture, but doesn't have a timestamp: only show on the widget near the - // information area. - if (!offsetSeconds) - continue; - DivePictureItem *item = new DivePictureItem(); - item->setPixmap(m->index(i, 0).data(Qt::DecorationRole).value<QPixmap>()); - item->setFileUrl(m->index(i, 1).data().toString()); - // let's put the picture at the correct time, but at a fixed "depth" on the profile - // not sure this is ideal, but it seems to look right. - x = timeAxis->posAtValue(offsetSeconds); - if (i == 0) - y = 10; - else if (fabs(x - lastX) < 4) - y = lastY + 3; - else - y = 10; - lastX = x; - lastY = y; - item->setPos(x, y); - scene()->addItem(item); - pictures.push_back(item); - } -} |