2017-04-27 20:26:36 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2021-06-05 18:42:56 +02:00
|
|
|
#include "profile-widget/profilescene.h"
|
2021-08-03 09:51:37 +02:00
|
|
|
#include "core/device.h"
|
2020-10-25 09:14:16 +01:00
|
|
|
#include "core/event.h"
|
2024-02-14 10:59:13 +01:00
|
|
|
#include "core/eventtype.h"
|
2018-05-11 08:25:41 -07:00
|
|
|
#include "core/subsurface-string.h"
|
2018-06-03 22:15:19 +02:00
|
|
|
#include "core/qthelper.h"
|
2022-09-24 14:06:56 +02:00
|
|
|
#include "core/range.h"
|
2018-08-15 11:52:50 +02:00
|
|
|
#include "core/settings/qPrefTechnicalDetails.h"
|
|
|
|
#include "core/settings/qPrefPartialPressureGas.h"
|
2016-04-04 22:02:03 -07:00
|
|
|
#include "profile-widget/diveeventitem.h"
|
|
|
|
#include "profile-widget/divetextitem.h"
|
|
|
|
#include "profile-widget/divetooltipitem.h"
|
2020-11-25 18:30:49 +01:00
|
|
|
#include "profile-widget/divehandler.h"
|
2016-04-04 22:02:03 -07:00
|
|
|
#include "core/planner.h"
|
|
|
|
#include "core/pref.h"
|
2016-03-06 06:52:55 -08:00
|
|
|
#include "qt-models/diveplannermodel.h"
|
|
|
|
#include "qt-models/models.h"
|
2019-08-05 19:41:15 +02:00
|
|
|
#include "core/errorhelper.h"
|
2015-11-05 16:05:44 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2016-04-04 22:02:03 -07:00
|
|
|
#include "desktop-widgets/simplewidgets.h"
|
2019-11-13 15:08:40 +01:00
|
|
|
#include "commands/command.h"
|
2018-06-17 08:48:54 +02:00
|
|
|
#include "core/gettextfromc.h"
|
2018-06-30 11:36:37 +02:00
|
|
|
#include "core/imagedownloader.h"
|
2015-11-05 16:05:44 -08:00
|
|
|
#endif
|
2015-02-09 18:27:59 -02:00
|
|
|
|
2014-03-15 21:12:34 -07:00
|
|
|
#include <QMessageBox>
|
2014-04-03 21:16:15 +02:00
|
|
|
#include <QInputDialog>
|
2015-02-09 18:58:40 -02:00
|
|
|
#include <QWheelEvent>
|
2015-11-05 12:50:51 -08:00
|
|
|
#include <QMenu>
|
2021-04-25 21:31:44 +02:00
|
|
|
#include <QMimeData>
|
2018-05-29 12:49:47 +02:00
|
|
|
#include <QElapsedTimer>
|
2014-01-16 15:02:32 -02:00
|
|
|
|
2014-01-15 13:20:05 -02:00
|
|
|
#ifndef QT_NO_DEBUG
|
|
|
|
#include <QTableView>
|
|
|
|
#endif
|
|
|
|
|
2018-07-15 17:56:18 +02:00
|
|
|
// Constant describing at which z-level the thumbnails are located.
|
|
|
|
// We might add more constants here for easier customability.
|
|
|
|
static const double thumbnailBaseZValue = 100.0;
|
2021-10-04 21:41:17 +02:00
|
|
|
|
2022-08-28 22:42:54 +02:00
|
|
|
static double calcZoom(int zoomLevel)
|
|
|
|
{
|
|
|
|
// Base of exponential zoom function: one wheel-click will increase the zoom by 15%.
|
|
|
|
constexpr double zoomFactor = 1.15;
|
|
|
|
return zoomLevel == 0 ? 1.0 : pow(zoomFactor, zoomLevel);
|
|
|
|
}
|
2018-07-15 17:56:18 +02:00
|
|
|
|
2021-08-09 16:48:08 +02:00
|
|
|
ProfileWidget2::ProfileWidget2(DivePlannerPointsModel *plannerModelIn, double dpr, QWidget *parent) : QGraphicsView(parent),
|
|
|
|
profileScene(new ProfileScene(dpr, false, false)),
|
2021-07-01 18:56:50 +02:00
|
|
|
currentState(INIT),
|
2021-01-25 15:06:53 +01:00
|
|
|
plannerModel(plannerModelIn),
|
2014-02-04 21:47:50 -02:00
|
|
|
zoomLevel(0),
|
2022-03-12 14:06:12 +01:00
|
|
|
zoomedPosition(0.0),
|
2016-02-06 13:25:58 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2014-02-05 14:34:45 -02:00
|
|
|
toolTipItem(new ToolTipItem()),
|
2016-02-06 13:25:58 -08:00
|
|
|
#endif
|
2021-07-01 18:56:50 +02:00
|
|
|
d(nullptr),
|
|
|
|
dc(0),
|
2021-12-03 08:50:52 +01:00
|
|
|
empty(true),
|
2022-08-28 22:42:54 +02:00
|
|
|
panning(false),
|
2021-07-29 06:50:59 +02:00
|
|
|
shouldCalculateMax(true)
|
2014-01-14 14:30:13 -02:00
|
|
|
{
|
2014-02-07 14:59:58 -02:00
|
|
|
setupSceneAndFlags();
|
|
|
|
setupItemOnScene();
|
|
|
|
addItemsToScene();
|
|
|
|
scene()->installEventFilter(this);
|
2015-11-12 01:37:18 +01:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2015-11-03 21:17:50 +01:00
|
|
|
setAcceptDrops(true);
|
|
|
|
|
2018-06-30 11:36:37 +02:00
|
|
|
connect(Thumbnailer::instance(), &Thumbnailer::thumbnailChanged, this, &ProfileWidget2::updateThumbnail, Qt::QueuedConnection);
|
2020-03-03 22:42:51 +01:00
|
|
|
connect(&diveListNotifier, &DiveListNotifier::cylinderEdited, this, &ProfileWidget2::profileChanged);
|
|
|
|
connect(&diveListNotifier, &DiveListNotifier::eventsChanged, this, &ProfileWidget2::profileChanged);
|
2021-01-27 23:41:51 +01:00
|
|
|
connect(&diveListNotifier, &DiveListNotifier::divesChanged, this, &ProfileWidget2::divesChanged);
|
2021-08-17 11:19:41 -07:00
|
|
|
connect(&diveListNotifier, &DiveListNotifier::deviceEdited, this, &ProfileWidget2::replot);
|
2022-02-19 18:47:25 +01:00
|
|
|
connect(&diveListNotifier, &DiveListNotifier::diveComputerEdited, this, &ProfileWidget2::replot);
|
2015-11-12 01:37:18 +01:00
|
|
|
#endif // SUBSURFACE_MOBILE
|
2014-05-24 12:39:40 -03:00
|
|
|
|
2015-02-02 13:12:11 -08:00
|
|
|
#if !defined(QT_NO_DEBUG) && defined(SHOW_PLOT_INFO_TABLE)
|
2014-02-07 14:59:58 -02:00
|
|
|
QTableView *diveDepthTableView = new QTableView();
|
2021-06-28 20:29:46 +02:00
|
|
|
diveDepthTableView->setModel(profileScene->dataModel);
|
2014-03-07 12:42:13 -03:00
|
|
|
diveDepthTableView->show();
|
2014-02-07 14:59:58 -02:00
|
|
|
#endif
|
2020-11-25 20:03:49 +01:00
|
|
|
|
2021-07-01 18:56:50 +02:00
|
|
|
setProfileState();
|
2014-02-07 14:59:58 -02:00
|
|
|
}
|
2014-01-15 12:23:40 -02:00
|
|
|
|
2019-07-15 20:41:42 +02:00
|
|
|
ProfileWidget2::~ProfileWidget2()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:50:57 +01:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2022-02-19 14:06:58 +01:00
|
|
|
void ProfileWidget2::keyPressEvent(QKeyEvent *e)
|
|
|
|
{
|
|
|
|
switch (e->key()) {
|
|
|
|
case Qt::Key_Delete: return keyDeleteAction();
|
|
|
|
case Qt::Key_Up: return keyUpAction();
|
|
|
|
case Qt::Key_Down: return keyDownAction();
|
|
|
|
case Qt::Key_Left: return keyLeftAction();
|
|
|
|
case Qt::Key_Right: return keyRightAction();
|
|
|
|
}
|
|
|
|
QGraphicsView::keyPressEvent(e);
|
2018-01-10 16:50:57 +01:00
|
|
|
}
|
|
|
|
#endif // SUBSURFACE_MOBILE
|
|
|
|
|
2014-02-07 14:59:58 -02:00
|
|
|
void ProfileWidget2::addItemsToScene()
|
|
|
|
{
|
2017-03-25 13:03:37 +01:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
|
|
|
scene()->addItem(toolTipItem);
|
2014-08-05 15:47:02 -07:00
|
|
|
QPen pen(QColor(Qt::red).lighter());
|
|
|
|
pen.setWidth(0);
|
2016-02-06 13:25:58 -08:00
|
|
|
#endif
|
2014-02-07 14:59:58 -02:00
|
|
|
}
|
2014-01-15 12:23:40 -02:00
|
|
|
|
2014-02-07 14:59:58 -02:00
|
|
|
void ProfileWidget2::setupItemOnScene()
|
|
|
|
{
|
2016-02-06 13:25:58 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2014-03-12 00:09:54 +02:00
|
|
|
toolTipItem->setZValue(9998);
|
2021-06-28 20:29:46 +02:00
|
|
|
toolTipItem->setTimeAxis(profileScene->timeAxis);
|
2016-02-06 13:25:58 -08:00
|
|
|
#endif
|
2014-02-07 14:59:58 -02:00
|
|
|
}
|
2014-01-15 13:01:29 -02:00
|
|
|
|
2020-04-12 12:20:25 +02:00
|
|
|
void ProfileWidget2::replot()
|
2014-03-09 10:59:31 -03:00
|
|
|
{
|
2021-10-20 11:50:44 +02:00
|
|
|
plotDive(d, dc);
|
2014-03-09 10:59:31 -03:00
|
|
|
}
|
|
|
|
|
2014-02-07 14:59:58 -02:00
|
|
|
void ProfileWidget2::setupSceneAndFlags()
|
|
|
|
{
|
2021-06-05 18:42:56 +02:00
|
|
|
setScene(profileScene.get());
|
2014-02-07 14:59:58 -02:00
|
|
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
setOptimizationFlags(QGraphicsView::DontSavePainterState);
|
|
|
|
setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
|
|
|
|
setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
|
|
|
setMouseTracking(true);
|
|
|
|
}
|
2014-01-14 14:30:13 -02:00
|
|
|
|
|
|
|
// Currently just one dive, but the plan is to enable All of the selected dives.
|
2021-10-22 14:30:56 +02:00
|
|
|
void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, int flags)
|
2014-01-14 14:30:13 -02:00
|
|
|
{
|
2021-01-28 14:24:38 +01:00
|
|
|
d = dIn;
|
|
|
|
dc = dcIn;
|
|
|
|
if (!d) {
|
2021-07-01 18:56:50 +02:00
|
|
|
clear();
|
2021-01-28 14:24:38 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-12-03 08:50:52 +01:00
|
|
|
// If there was no previously displayed dive, turn off animations
|
|
|
|
if (empty)
|
|
|
|
flags |= RenderFlags::Instant;
|
|
|
|
empty = false;
|
|
|
|
|
2018-05-29 12:49:47 +02:00
|
|
|
QElapsedTimer measureDuration; // let's measure how long this takes us (maybe we'll turn of TTL calculation later
|
2014-06-04 13:41:50 -07:00
|
|
|
measureDuration.start();
|
2014-03-11 18:54:28 -03:00
|
|
|
|
2021-08-03 09:51:37 +02:00
|
|
|
DivePlannerPointsModel *model = currentState == EDIT || currentState == PLAN ? plannerModel : nullptr;
|
|
|
|
bool inPlanner = currentState == PLAN;
|
|
|
|
|
2022-08-28 22:42:54 +02:00
|
|
|
double zoom = calcZoom(zoomLevel);
|
2021-10-22 18:23:15 +02:00
|
|
|
profileScene->plotDive(d, dc, model, inPlanner, flags & RenderFlags::Instant,
|
|
|
|
flags & RenderFlags::DontRecalculatePlotInfo,
|
|
|
|
shouldCalculateMax, zoom, zoomedPosition);
|
2021-08-03 09:51:37 +02:00
|
|
|
|
2015-12-01 15:36:20 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2023-06-18 15:28:51 +12:00
|
|
|
toolTipItem->setVisible(prefs.infobox);
|
2021-08-03 09:51:37 +02:00
|
|
|
toolTipItem->setPlotInfo(profileScene->plotInfo);
|
2014-02-07 17:59:21 -02:00
|
|
|
|
2021-06-30 07:49:56 +02:00
|
|
|
if ((currentState == EDIT || currentState == PLAN) && plannerModel) {
|
2014-05-21 23:31:26 -03:00
|
|
|
repositionDiveHandlers();
|
2021-01-25 15:06:53 +01:00
|
|
|
plannerModel->deleteTemporaryPlan();
|
2014-05-21 23:31:26 -03:00
|
|
|
}
|
2021-10-26 07:42:13 +02:00
|
|
|
|
|
|
|
// On zoom / pan don't recreate the picture thumbnails, only change their position.
|
|
|
|
if (flags & RenderFlags::DontRecalculatePlotInfo)
|
|
|
|
updateThumbnails();
|
|
|
|
else
|
|
|
|
plotPicturesInternal(d, flags & RenderFlags::Instant);
|
2018-10-17 11:28:33 +02:00
|
|
|
|
2021-01-28 14:24:38 +01:00
|
|
|
toolTipItem->refresh(d, mapToScene(mapFromGlobal(QCursor::pos())), currentState == PLAN);
|
2018-01-10 13:55:29 +01:00
|
|
|
#endif
|
2014-07-21 18:54:28 -03:00
|
|
|
|
2014-06-04 13:41:50 -07:00
|
|
|
// 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.
|
2021-01-04 17:55:42 -08:00
|
|
|
qint64 elapsedTime = measureDuration.elapsed();
|
|
|
|
if (verbose)
|
2024-03-26 18:33:22 +01:00
|
|
|
report_info("Profile calculation for dive %d took %lld ms -- calculated ceiling preference is %d", d->number, elapsedTime, prefs.calcceiling);
|
2021-01-04 17:55:42 -08:00
|
|
|
if (elapsedTime > 1000 && prefs.calcndltts) {
|
2018-08-15 11:52:50 +02:00
|
|
|
qPrefTechnicalDetails::set_calcndltts(false);
|
2024-03-12 09:17:50 +01:00
|
|
|
report_error("%s", qPrintable(tr("Show NDL / TTS was disabled because of excessive processing time")));
|
2014-06-04 13:41:50 -07:00
|
|
|
}
|
2014-01-14 14:30:13 -02:00
|
|
|
}
|
|
|
|
|
2021-01-27 23:41:51 +01:00
|
|
|
void ProfileWidget2::divesChanged(const QVector<dive *> &dives, DiveField field)
|
|
|
|
{
|
|
|
|
// If the mode of the currently displayed dive changed, replot
|
|
|
|
if (field.mode &&
|
2022-09-17 19:51:53 +02:00
|
|
|
std::find(dives.begin(), dives.end(), d) != dives.end())
|
2021-01-27 23:41:51 +01:00
|
|
|
replot();
|
|
|
|
}
|
|
|
|
|
2018-05-21 18:20:29 +02:00
|
|
|
void ProfileWidget2::actionRequestedReplot(bool)
|
2016-01-25 15:54:23 -02:00
|
|
|
{
|
|
|
|
settingsChanged();
|
|
|
|
}
|
|
|
|
|
2021-06-15 18:16:44 +02:00
|
|
|
void ProfileWidget2::settingsChanged()
|
|
|
|
{
|
2020-12-29 23:03:38 +01:00
|
|
|
replot();
|
2014-01-14 14:30:13 -02:00
|
|
|
}
|
|
|
|
|
2014-02-27 20:09:57 -08:00
|
|
|
void ProfileWidget2::resizeEvent(QResizeEvent *event)
|
2014-01-14 14:30:13 -02:00
|
|
|
{
|
2014-02-10 20:45:08 -08:00
|
|
|
QGraphicsView::resizeEvent(event);
|
2021-08-28 23:36:09 +02:00
|
|
|
profileScene->resize(viewport()->size());
|
2021-10-22 18:23:15 +02:00
|
|
|
plotDive(d, dc, RenderFlags::Instant | RenderFlags::DontRecalculatePlotInfo); // disable animation on resize events
|
2014-01-15 12:55:33 -02:00
|
|
|
}
|
|
|
|
|
2016-02-06 13:25:58 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2014-02-05 16:15:59 -02:00
|
|
|
bool ProfileWidget2::eventFilter(QObject *object, QEvent *event)
|
|
|
|
{
|
2014-02-27 20:09:57 -08:00
|
|
|
QGraphicsScene *s = qobject_cast<QGraphicsScene *>(object);
|
|
|
|
if (s && event->type() == QEvent::GraphicsSceneHelp) {
|
2014-02-05 16:15:59 -02:00
|
|
|
event->ignore();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return QGraphicsView::eventFilter(object, event);
|
|
|
|
}
|
2016-02-06 13:25:58 -08:00
|
|
|
#endif
|
2014-02-07 16:34:42 -02:00
|
|
|
|
2018-01-10 16:36:45 +01:00
|
|
|
template <typename T>
|
2019-04-01 22:15:19 +02:00
|
|
|
static void hideAll(const T &container)
|
2018-01-10 16:36:45 +01:00
|
|
|
{
|
2021-01-24 09:13:56 +01:00
|
|
|
for (auto &item: container)
|
2018-01-10 16:36:45 +01:00
|
|
|
item->setVisible(false);
|
|
|
|
}
|
|
|
|
|
2021-01-28 14:24:38 +01:00
|
|
|
void ProfileWidget2::setProfileState(const dive *dIn, int dcIn)
|
|
|
|
{
|
|
|
|
d = dIn;
|
|
|
|
dc = dcIn;
|
|
|
|
|
|
|
|
setProfileState();
|
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:42 -02:00
|
|
|
void ProfileWidget2::setProfileState()
|
|
|
|
{
|
2014-02-07 16:54:12 -02:00
|
|
|
if (currentState == PROFILE)
|
|
|
|
return;
|
2014-02-07 16:34:42 -02:00
|
|
|
|
2014-02-07 16:54:12 -02:00
|
|
|
currentState = PROFILE;
|
2021-07-29 06:50:59 +02:00
|
|
|
setBackgroundBrush(getColor(::BACKGROUND, profileScene->isGrayscale));
|
2014-02-07 17:38:00 -02:00
|
|
|
|
2016-02-06 13:25:58 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
|
|
|
toolTipItem->readPos();
|
2023-06-18 15:28:51 +12:00
|
|
|
toolTipItem->setVisible(prefs.infobox);
|
2015-11-05 16:05:44 -08:00
|
|
|
#endif
|
2021-07-01 18:56:50 +02:00
|
|
|
|
|
|
|
handles.clear();
|
|
|
|
gases.clear();
|
2014-02-07 16:34:42 -02:00
|
|
|
}
|
2014-02-17 19:15:40 -03:00
|
|
|
|
2015-11-05 16:05:44 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2021-06-30 07:49:56 +02:00
|
|
|
void ProfileWidget2::setEditState(const dive *d, int dc)
|
2014-05-21 15:52:24 -03:00
|
|
|
{
|
2021-06-30 07:49:56 +02:00
|
|
|
if (currentState == EDIT)
|
2014-05-21 15:52:24 -03:00
|
|
|
return;
|
|
|
|
|
2021-01-28 14:24:38 +01:00
|
|
|
setProfileState(d, dc);
|
2014-05-24 12:39:40 -03:00
|
|
|
|
2022-03-12 13:10:29 +01:00
|
|
|
currentState = EDIT;
|
2021-02-27 16:01:28 +01:00
|
|
|
|
|
|
|
repositionDiveHandlers();
|
2014-05-21 15:52:24 -03:00
|
|
|
}
|
|
|
|
|
2021-01-28 14:24:38 +01:00
|
|
|
void ProfileWidget2::setPlanState(const dive *d, int dc)
|
2014-05-21 15:52:24 -03:00
|
|
|
{
|
|
|
|
if (currentState == PLAN)
|
|
|
|
return;
|
2014-05-25 15:12:00 -03:00
|
|
|
|
2021-01-28 14:24:38 +01:00
|
|
|
setProfileState(d, dc);
|
2014-05-25 14:16:43 -03:00
|
|
|
|
2022-03-12 13:10:29 +01:00
|
|
|
currentState = PLAN;
|
2014-06-30 18:46:51 -03:00
|
|
|
setBackgroundBrush(QColor("#D7E3EF"));
|
2021-02-27 16:01:28 +01:00
|
|
|
|
|
|
|
repositionDiveHandlers();
|
2014-05-21 15:52:24 -03:00
|
|
|
}
|
2016-02-06 13:25:58 -08:00
|
|
|
#endif
|
2014-05-21 15:52:24 -03:00
|
|
|
|
2021-01-10 14:04:43 +01:00
|
|
|
bool ProfileWidget2::isPlanner() const
|
2014-05-26 15:17:34 -07:00
|
|
|
{
|
|
|
|
return currentState == PLAN;
|
|
|
|
}
|
|
|
|
|
2019-07-06 12:09:15 +02:00
|
|
|
#if 0 // TODO::: FINISH OR DISABLE
|
2019-07-06 12:35:33 +02:00
|
|
|
struct int ProfileWidget2::getEntryFromPos(QPointF pos)
|
2014-11-19 22:31:28 +00:00
|
|
|
{
|
|
|
|
// find the time stamp corresponding to the mouse position
|
2017-03-23 08:13:49 +07:00
|
|
|
int seconds = lrint(timeAxis->valueAt(pos));
|
2014-11-19 22:31:28 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < plotInfo.nr; i++) {
|
2019-07-06 12:35:33 +02:00
|
|
|
if (plotInfo.entry[i].sec >= seconds)
|
|
|
|
return i;
|
2014-11-19 22:31:28 +00:00
|
|
|
}
|
2019-07-06 12:35:33 +02:00
|
|
|
return plotInfo.nr - 1;
|
2014-11-19 22:31:28 +00:00
|
|
|
}
|
2019-07-06 12:09:15 +02:00
|
|
|
#endif
|
2014-11-19 22:31:28 +00:00
|
|
|
|
2015-11-05 16:05:44 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2021-04-25 22:35:41 +02:00
|
|
|
static bool isDiveTextItem(const QGraphicsItem *item, const DiveTextItem *textItem)
|
|
|
|
{
|
|
|
|
while (item) {
|
|
|
|
if (item == textItem)
|
|
|
|
return true;
|
|
|
|
item = item->parentItem();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-05-15 17:23:39 +12:00
|
|
|
void ProfileWidget2::addGasChangeMenu(QMenu &m, QString menuTitle, const struct dive &d, int dcNr, int changeTime)
|
|
|
|
{
|
|
|
|
QMenu *gasChange = m.addMenu(menuTitle);
|
|
|
|
std::vector<std::pair<int, QString>> gases = get_dive_gas_list(&d, dcNr, true);
|
|
|
|
for (unsigned i = 0; i < gases.size(); i++) {
|
|
|
|
int cylinderIndex = gases[i].first;
|
|
|
|
gasChange->addAction(gases[i].second, [this, cylinderIndex, changeTime] { addGasSwitch(cylinderIndex, changeTime); });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-27 20:09:57 -08:00
|
|
|
void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
|
2014-02-17 19:15:40 -03:00
|
|
|
{
|
2021-06-30 07:49:56 +02:00
|
|
|
if (currentState == EDIT || currentState == PLAN) {
|
2014-05-25 00:33:39 -03:00
|
|
|
QGraphicsView::contextMenuEvent(event);
|
|
|
|
return;
|
|
|
|
}
|
2014-05-19 14:39:34 +09:00
|
|
|
QMenu m;
|
2021-01-28 14:24:38 +01:00
|
|
|
if (!d)
|
2014-02-17 19:15:40 -03:00
|
|
|
return;
|
2021-04-25 22:35:41 +02:00
|
|
|
|
2014-05-19 14:39:34 +09:00
|
|
|
// create the profile context menu
|
2020-01-30 15:03:48 +01:00
|
|
|
QPointF scenePos = mapToScene(mapFromGlobal(event->globalPos()));
|
2021-06-28 20:29:46 +02:00
|
|
|
qreal sec_val = profileScene->timeAxis->valueAt(scenePos);
|
2020-01-30 15:03:48 +01:00
|
|
|
int seconds = (sec_val < 0.0) ? 0 : (int)sec_val;
|
2020-08-25 05:37:08 +09:00
|
|
|
DiveEventItem *item = dynamic_cast<DiveEventItem *>(sceneItem);
|
|
|
|
|
|
|
|
// Add or edit Gas Change
|
2024-05-25 20:12:10 +02:00
|
|
|
if (d && item && item->ev.is_gaschange()) {
|
2024-05-28 21:31:11 +02:00
|
|
|
} else if (d && d->cylinders.size() > 1) {
|
2014-11-19 21:03:58 +00:00
|
|
|
// if we have more than one gas, offer to switch to another one
|
2024-09-09 23:53:06 +12:00
|
|
|
const struct divecomputer *currentdc = d->get_dc(dc);
|
|
|
|
if (seconds == 0 || (!currentdc->samples.empty() && seconds <= currentdc->samples[0].time.seconds))
|
|
|
|
addGasChangeMenu(m, tr("Set initial gas"), *d, dc, 0);
|
|
|
|
else
|
|
|
|
addGasChangeMenu(m, tr("Add gas change"), *d, dc, seconds);
|
2014-02-17 19:15:40 -03:00
|
|
|
}
|
2020-03-02 22:02:33 +01:00
|
|
|
m.addAction(tr("Add setpoint change"), [this, seconds]() { ProfileWidget2::addSetpointChange(seconds); });
|
|
|
|
m.addAction(tr("Add bookmark"), [this, seconds]() { addBookmark(seconds); });
|
|
|
|
m.addAction(tr("Split dive into two"), [this, seconds]() { splitDive(seconds); });
|
2018-04-08 22:09:26 +02:00
|
|
|
|
2024-06-30 20:38:12 +02:00
|
|
|
divemode_loop loop(*d->get_dc(dc));
|
2024-09-03 19:48:49 +12:00
|
|
|
divemode_t divemode = loop.at(seconds);
|
2018-04-08 22:09:26 +02:00
|
|
|
QMenu *changeMode = m.addMenu(tr("Change divemode"));
|
2020-03-02 22:34:39 +01:00
|
|
|
if (divemode != OC)
|
|
|
|
changeMode->addAction(gettextFromC::tr(divemode_text_ui[OC]),
|
|
|
|
[this, seconds](){ addDivemodeSwitch(seconds, OC); });
|
|
|
|
if (divemode != CCR)
|
|
|
|
changeMode->addAction(gettextFromC::tr(divemode_text_ui[CCR]),
|
|
|
|
[this, seconds](){ addDivemodeSwitch(seconds, CCR); });
|
|
|
|
if (divemode != PSCR)
|
|
|
|
changeMode->addAction(gettextFromC::tr(divemode_text_ui[PSCR]),
|
|
|
|
[this, seconds](){ addDivemodeSwitch(seconds, PSCR); });
|
2015-04-23 13:56:24 -07:00
|
|
|
|
2014-02-17 19:15:40 -03:00
|
|
|
m.exec(event->globalPos());
|
|
|
|
}
|
|
|
|
|
2020-03-02 22:02:33 +01:00
|
|
|
void ProfileWidget2::addBookmark(int seconds)
|
2014-03-15 21:12:34 -07:00
|
|
|
{
|
2021-01-28 14:24:38 +01:00
|
|
|
if (d)
|
|
|
|
Command::addEventBookmark(mutable_dive(), dc, seconds);
|
2014-03-15 21:12:34 -07:00
|
|
|
}
|
|
|
|
|
2020-03-02 21:48:53 +01:00
|
|
|
void ProfileWidget2::addDivemodeSwitch(int seconds, int divemode)
|
2018-04-07 20:39:41 +02:00
|
|
|
{
|
2021-01-28 14:24:38 +01:00
|
|
|
if (d)
|
|
|
|
Command::addEventDivemodeSwitch(mutable_dive(), dc, seconds, divemode);
|
2018-04-07 20:39:41 +02:00
|
|
|
}
|
|
|
|
|
2020-03-02 22:02:33 +01:00
|
|
|
void ProfileWidget2::addSetpointChange(int seconds)
|
2014-11-26 14:22:41 +01:00
|
|
|
{
|
2021-01-28 14:24:38 +01:00
|
|
|
if (!d)
|
|
|
|
return;
|
|
|
|
SetpointDialog dialog(mutable_dive(), dc, seconds);
|
2020-03-03 23:09:25 +01:00
|
|
|
dialog.exec();
|
2014-11-26 14:22:41 +01:00
|
|
|
}
|
|
|
|
|
2020-03-02 22:02:33 +01:00
|
|
|
void ProfileWidget2::splitDive(int seconds)
|
2018-07-02 21:13:44 +02:00
|
|
|
{
|
2018-07-20 20:26:06 +02:00
|
|
|
if (!d)
|
|
|
|
return;
|
2024-09-01 21:48:31 +02:00
|
|
|
Command::splitDives(mutable_dive(), duration_t{ .seconds = seconds });
|
2018-07-02 21:13:44 +02:00
|
|
|
}
|
|
|
|
|
2024-05-25 00:33:44 +12:00
|
|
|
void ProfileWidget2::connectPlannerModel()
|
|
|
|
{
|
|
|
|
connect(plannerModel, &DivePlannerPointsModel::dataChanged, this, &ProfileWidget2::replot);
|
|
|
|
connect(plannerModel, &DivePlannerPointsModel::cylinderModelEdited, this, &ProfileWidget2::replot);
|
|
|
|
connect(plannerModel, &DivePlannerPointsModel::modelReset, this, &ProfileWidget2::pointsReset);
|
|
|
|
connect(plannerModel, &DivePlannerPointsModel::rowsInserted, this, &ProfileWidget2::pointInserted);
|
|
|
|
connect(plannerModel, &DivePlannerPointsModel::rowsRemoved, this, &ProfileWidget2::pointsRemoved);
|
|
|
|
connect(plannerModel, &DivePlannerPointsModel::rowsMoved, this, &ProfileWidget2::pointsMoved);
|
|
|
|
}
|
2015-11-05 16:05:44 -08:00
|
|
|
#endif
|
2014-05-21 21:18:10 -03:00
|
|
|
|
2021-01-28 14:24:38 +01:00
|
|
|
void ProfileWidget2::profileChanged(dive *dive)
|
2020-03-01 17:16:08 +01:00
|
|
|
{
|
2021-01-28 14:24:38 +01:00
|
|
|
if (dive != d)
|
2020-03-01 17:16:08 +01:00
|
|
|
return; // Cylinders of a differnt dive than the shown one changed.
|
|
|
|
replot();
|
|
|
|
}
|
|
|
|
|
2018-01-10 13:55:29 +01:00
|
|
|
#endif
|
2015-11-03 21:17:50 +01:00
|
|
|
|
2021-01-28 14:24:38 +01:00
|
|
|
struct dive *ProfileWidget2::mutable_dive() const
|
|
|
|
{
|
|
|
|
return const_cast<dive *>(d);
|
|
|
|
}
|