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 <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-02-09 14:24:29 +01:00
parent bece0a0652
commit f0fe52d42b
5 changed files with 88 additions and 52 deletions

View file

@ -27,6 +27,12 @@
#include <QDesktopServices>
#include <QElapsedTimer>
#ifndef SUBSURFACE_MOBILE
#include "core/device.h"
#include <QMenu>
#include <QInputDialog>
#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<void()> action;
MenuEntry(QString text, std::function<void()> action)
: text(text), action(std::move(action))
{
}
};
static void execMenu(const std::vector<MenuEntry> &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<MenuEntry> 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<dive *>(d);
}