From f0fe52d42ba4fa782ad7b64c9fde61931325d78c Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Fri, 9 Feb 2024 14:24:29 +0100 Subject: [PATCH] profile: port divecomputer menu to QtQuick This uses QWidgets and therefore will only compile on desktop. We'll have to see how to integrate that on mobile. Signed-off-by: Berthold Stoeger --- profile-widget/profilescene.cpp | 5 ++ profile-widget/profilescene.h | 1 + profile-widget/profileview.cpp | 78 +++++++++++++++++++++++++++++++ profile-widget/profileview.h | 4 ++ profile-widget/profilewidget2.cpp | 52 --------------------- 5 files changed, 88 insertions(+), 52 deletions(-) diff --git a/profile-widget/profilescene.cpp b/profile-widget/profilescene.cpp index ab76b1565..d91acc2fd 100644 --- a/profile-widget/profilescene.cpp +++ b/profile-widget/profilescene.cpp @@ -367,6 +367,11 @@ bool ProfileScene::pointOnProfile(const QPointF &point) const return timeAxis->pointInRange(point.x()) && profileYAxis->pointInRange(point.y()); } +bool ProfileScene::pointOnDiveComputerText(const QPointF &point) const +{ + return diveComputerText->boundingRect().contains(point - diveComputerText->pos()); +} + static double max_gas(const plot_info &pi, double gas_pressures::*gas) { double ret = -1; diff --git a/profile-widget/profilescene.h b/profile-widget/profilescene.h index 7de2e12aa..915c05742 100644 --- a/profile-widget/profilescene.h +++ b/profile-widget/profilescene.h @@ -37,6 +37,7 @@ public: void resize(QSizeF size); void clear(); bool pointOnProfile(const QPointF &point) const; + bool pointOnDiveComputerText(const QPointF &point) const; void anim(double fraction); // Called by the animation with 0.0-1.0 (start to stop). // Can be compared with literal 1.0 to determine "end" state. diff --git a/profile-widget/profileview.cpp b/profile-widget/profileview.cpp index c0349c95c..f7bafb6d6 100644 --- a/profile-widget/profileview.cpp +++ b/profile-widget/profileview.cpp @@ -27,6 +27,12 @@ #include #include +#ifndef SUBSURFACE_MOBILE +#include "core/device.h" +#include +#include +#endif + static const QColor mouseFollowerColor = QColor(Qt::red).lighter(); // Class templates for animations (if any). Might want to do our own. @@ -375,6 +381,47 @@ void ProfileView::wheelEvent(QWheelEvent *event) } } +// Helper to make menus on mobile and desktop +struct MenuEntry { + QString text; + std::function action; + MenuEntry(QString text, std::function action) + : text(text), action(std::move(action)) + { + } +}; + +static void execMenu(const std::vector &entries, QPoint pos) +{ + if (entries.empty()) + return; +#ifndef SUBSURFACE_MOBILE + QMenu m; + for (const MenuEntry &e: entries) { + // Dang. Qt doesn't support std::function! This is too many indirections for my taste. :( + m.addAction(e.text, [f = e.action] { f(); }); + } + m.exec(pos); +#endif +} + +// TODO: How should that work on mobile? +void ProfileView::renameCurrentDC() +{ +#ifndef SUBSURFACE_MOBILE + bool ok; + struct divecomputer *currentdc = mutable_dive()->get_dc(dc); + if (!currentdc) + return; + // TODO: center on window by passing a QWidget as first argument! + QString newName = QInputDialog::getText(nullptr, tr("Edit nickname"), + tr("Set new nickname for %1 (serial %2):").arg(currentdc->model.c_str()).arg(currentdc->serial.c_str()), + QLineEdit::Normal, get_dc_nickname(currentdc).c_str(), &ok); + if (ok) + Command::editDeviceNickname(currentdc, newName); +#endif +} + void ProfileView::mousePressEvent(QMouseEvent *event) { // Handle dragging of items @@ -382,6 +429,32 @@ void ProfileView::mousePressEvent(QMouseEvent *event) if (event->isAccepted()) return; + // Open context menu if computer name is clicked + if (d && profileScene->pointOnDiveComputerText(event->pos())) { + std::vector m; + const struct divecomputer *currentdc = d->get_dc(dc); + if (!currentdc->deviceid && dc == 0 && d->number_of_computers() == 1) + // nothing to do, can't rename, delete or reorder + return; + // create menu to show when right clicking on dive computer name + if (dc > 0) + m.emplace_back(tr("Make first dive computer"), [this]() { + Command::moveDiveComputerToFront(mutable_dive(), dc); + }); + if (d->number_of_computers() > 1) { + m.emplace_back(tr("Delete this dive computer"), [this]() { + Command::deleteDiveComputer(mutable_dive(), dc); + }); + m.emplace_back(tr("Split this dive computer into own dive"), [this]() { + Command::splitDiveComputer(mutable_dive(), dc); + }); + } + if (currentdc->deviceid) + m.emplace_back(tr("Rename this dive computer"), [this] { renameCurrentDC(); }); + execMenu(m, event->globalPos()); + return; + } + // Check if current picture is clicked if (highlightedPicture && highlightedPicture->thumbnail->underMouse(event->pos()) && @@ -1188,3 +1261,8 @@ void ProfileView::pictureOffsetChanged(dive *dIn, QString filename, offset_t off } update(); } + +dive *ProfileView::mutable_dive() const +{ + return const_cast(d); +} diff --git a/profile-widget/profileview.h b/profile-widget/profileview.h index ec3d53c34..ef879ecc9 100644 --- a/profile-widget/profileview.h +++ b/profile-widget/profileview.h @@ -92,6 +92,7 @@ private: ChartItemPtr profileItem; std::unique_ptr animation; ChartItemPtr mouseFollowerHorizontal, mouseFollowerVertical; + dive *mutable_dive() const; // for functions manipulating the dive void plotAreaChanged(const QSizeF &size) override; void resetPointers() override; @@ -132,6 +133,9 @@ private: void pointsRemoved(const QModelIndex &, int start, int end); void pointsMoved(const QModelIndex &, int start, int end, const QModelIndex &destination, int row); + // DC related + void renameCurrentDC(); + // The list of pictures in this plot. The pictures are sorted by offset in seconds. // For the same offset, sort by filename. // Pictures that are outside of the dive time are not shown. diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp index ece3f4124..dbc0f73b6 100644 --- a/profile-widget/profilewidget2.cpp +++ b/profile-widget/profilewidget2.cpp @@ -362,26 +362,6 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) QMenu m; if (!d) return; - // figure out if we are ontop of the dive computer name in the profile - QGraphicsItem *sceneItem = itemAt(mapFromGlobal(event->globalPos())); - if (isDiveTextItem(sceneItem, profileScene->diveComputerText)) { - const struct divecomputer *currentdc = d->get_dc(dc); - if (!currentdc->deviceid && dc == 0 && d->number_of_computers() == 1) - // nothing to do, can't rename, delete or reorder - return; - // create menu to show when right clicking on dive computer name - if (dc > 0) - m.addAction(tr("Make first dive computer"), this, &ProfileWidget2::makeFirstDC); - if (d->number_of_computers() > 1) { - m.addAction(tr("Delete this dive computer"), this, &ProfileWidget2::deleteCurrentDC); - m.addAction(tr("Split this dive computer into own dive"), this, &ProfileWidget2::splitCurrentDC); - } - if (currentdc->deviceid) - m.addAction(tr("Rename this dive computer"), this, &ProfileWidget2::renameCurrentDC); - m.exec(event->globalPos()); - // don't show the regular profile context menu - return; - } // create the profile context menu QPointF scenePos = mapToScene(mapFromGlobal(event->globalPos())); @@ -479,38 +459,6 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) m.exec(event->globalPos()); } -void ProfileWidget2::deleteCurrentDC() -{ - if (d) - Command::deleteDiveComputer(mutable_dive(), dc); -} - -void ProfileWidget2::splitCurrentDC() -{ - if (d) - Command::splitDiveComputer(mutable_dive(), dc); -} - -void ProfileWidget2::makeFirstDC() -{ - if (d) - Command::moveDiveComputerToFront(mutable_dive(), dc); -} - -void ProfileWidget2::renameCurrentDC() -{ - if (!d) - return; - bool ok; - struct divecomputer *currentdc = mutable_dive()->get_dc(dc); - QString newName = QInputDialog::getText(this, tr("Edit nickname"), - tr("Set new nickname for %1 (serial %2):").arg(QString::fromStdString(currentdc->model)). - arg(QString::fromStdString(currentdc->serial)), - QLineEdit::Normal, QString::fromStdString(get_dc_nickname(currentdc)), &ok); - if (ok) - Command::editDeviceNickname(currentdc, newName); -} - void ProfileWidget2::hideEvent(DiveEventItem *item) { if (!d)