profile: port context menu to QtQuick

This is for desktop only. We will have to think about what to
do on mobile. Either a "hamburger menu" or a "long click" seem
to be the most reasonable options.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-03-03 19:43:22 +01:00
parent b099e17042
commit c1c35ad48b
4 changed files with 84 additions and 15 deletions

View file

@ -33,6 +33,7 @@
#ifndef SUBSURFACE_MOBILE
#include "core/device.h"
#include "desktop-widgets/simplewidgets.h"
#include <QInputDialog>
#include <QMenu>
#include <QMessageBox>
@ -108,7 +109,7 @@ ProfileView::ProfileView(QQuickItem *parent) :
setFlag(ItemHasContents, true);
setAcceptHoverEvents(true);
setAcceptedMouseButtons(Qt::LeftButton);
setAcceptedMouseButtons(Qt::RightButton | Qt::LeftButton);
auto tec = qPrefTechnicalDetails::instance();
connect(tec, &qPrefTechnicalDetails::calcalltissuesChanged , this, &ProfileView::replot);
@ -499,6 +500,15 @@ void ProfileView::removeEvent(DiveEventItem &item)
#endif
}
// TODO: How should that work on mobile?
void ProfileView::addSetpointChange(int seconds)
{
#ifndef SUBSURFACE_MOBILE
SetpointDialog dialog(mutable_dive(), dc, seconds);
dialog.exec();
#endif
}
// Formats cylinder information for display.
// eg : "Cyl 1 (AL80 EAN32)"
static QString formatCylinderDescription(int i, const cylinder_t &cylinder)
@ -519,6 +529,64 @@ void ProfileView::unhideEvents()
replot();
}
void ProfileView::contextMenu(const QPointF pos, const QPoint globalPos)
{
// No context menu in Plan mode
if (mode == Mode::Plan)
return;
// Only open the contextmenu on the profile
if (!d || !profileScene->pointOnProfile(pos))
return;
std::vector<MenuEntry> m;
int seconds = profileScene->timeAt(pos);
// if we have more than one gas, offer to switch to another one
if (d->cylinders.size() > 1) {
std::vector<MenuEntry> gasChangeMenu;
// If this is before the first sample, offer an "initial gas change".
// This is signaled by seconds = 0
const struct divecomputer *currentdc = d->get_dc(dc);
if (seconds < 0 || (!currentdc->samples.empty() && seconds <= currentdc->samples[0].time.seconds))
seconds = 0;
for (auto [i, cylinder]: enumerated_range(d->cylinders)) {
QString label = formatCylinderDescription(i, cylinder);
gasChangeMenu.emplace_back(label, [this, idx = i, seconds] {
Command::addGasSwitch(mutable_dive(), dc, seconds, idx);
});
}
m.emplace_back(seconds == 0 ? tr("Set initial gas") : tr("Add gas change"), std::move(gasChangeMenu));
}
m.emplace_back(tr("Add setpoint change"), [this, seconds]() { addSetpointChange(seconds); });
m.emplace_back(tr("Add bookmark"), [this, seconds]() {
Command::addEventBookmark(mutable_dive(), dc, seconds);
});
m.emplace_back(tr("Split dive into two"), [this, seconds]() {
Command::splitDives(mutable_dive(), duration_t{ seconds });
});
std::vector<MenuEntry> changeModeMenu;
divemode_loop loop(*d->get_dc(dc));
divemode_t divemode = loop.at(seconds);
if (divemode != OC)
changeModeMenu.emplace_back(gettextFromC::tr(divemode_text_ui[OC]), [this, seconds]() {
Command::addEventDivemodeSwitch(mutable_dive(), dc, seconds, OC);
});
if (divemode != CCR)
changeModeMenu.emplace_back(gettextFromC::tr(divemode_text_ui[CCR]), [this, seconds]() {
Command::addEventDivemodeSwitch(mutable_dive(), dc, seconds, CCR);
});
if (divemode != PSCR)
changeModeMenu.emplace_back(gettextFromC::tr(divemode_text_ui[PSCR]), [this, seconds]() {
Command::addEventDivemodeSwitch(mutable_dive(), dc, seconds, PSCR);
});
m.emplace_back(tr("Change divemode"), changeModeMenu);
execMenu(m, globalPos);
}
void ProfileView::mousePressEvent(QMouseEvent *event)
{
// Handle dragging of items
@ -526,6 +594,12 @@ void ProfileView::mousePressEvent(QMouseEvent *event)
if (event->isAccepted())
return;
// On Desktop, the right botton opens the menu.
// For Mobile, we will have to think about something.
// Perhaps a "hamburger menu"?
if (event->button() == Qt::RightButton)
return contextMenu(event->pos(), event->globalPos());
// Open context menu if computer name is clicked
if (d && profileScene->pointOnDiveComputerText(event->pos())) {
std::vector<MenuEntry> m;

View file

@ -109,6 +109,8 @@ private:
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void keyPressEvent(QKeyEvent *e) override;
void contextMenu(const QPointF pos, const QPoint globalPos);
void addSetpointChange(int seconds);
ChartItemPtr<ToolTipItem> tooltip;
void updateTooltip(QPointF pos, bool plannerMode, int animSpeed);

View file

@ -292,21 +292,8 @@ bool ProfileWidget2::isPlanner() const
return currentState == PLAN;
}
#if 0 // TODO::: FINISH OR DISABLE
struct int ProfileWidget2::getEntryFromPos(QPointF pos)
{
// find the time stamp corresponding to the mouse position
int seconds = lrint(timeAxis->valueAt(pos));
for (int i = 0; i < plotInfo.nr; i++) {
if (plotInfo.entry[i].sec >= seconds)
return i;
}
return plotInfo.nr - 1;
}
#endif
#ifndef SUBSURFACE_MOBILE
<<<<<<< HEAD
static bool isDiveTextItem(const QGraphicsItem *item, const DiveTextItem *textItem)
{
while (item) {
@ -410,6 +397,8 @@ void ProfileWidget2::connectPlannerModel()
connect(plannerModel, &DivePlannerPointsModel::rowsMoved, this, &ProfileWidget2::pointsMoved);
}
#endif
=======
>>>>>>> 28d057ffb (profile: port context menu to QtQuick)
void ProfileWidget2::profileChanged(dive *dive)
{

View file

@ -307,6 +307,10 @@ void ChartView::setLayerVisibility(size_t z, bool visible)
void ChartView::mousePressEvent(QMouseEvent *event)
{
// Only left-button for drag events.
if (event->button() != Qt::LeftButton)
return event->ignore();
QPointF pos = event->localPos();
for (auto item: dragableItems) {