2017-04-27 20:26:36 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2014-01-14 14:30:13 -02:00
|
|
|
#ifndef PROFILEWIDGET2_H
|
|
|
|
#define PROFILEWIDGET2_H
|
|
|
|
|
|
|
|
#include <QGraphicsView>
|
2018-04-06 17:58:16 +02:00
|
|
|
#include <vector>
|
|
|
|
#include <memory>
|
2014-01-14 14:30:13 -02:00
|
|
|
|
|
|
|
// /* The idea of this widget is to display and edit the profile.
|
|
|
|
// * It has:
|
|
|
|
// * 1 - ToolTip / Legend item, displays every information of the current mouse position on it, plus the legends of the maps.
|
|
|
|
// * 2 - ToolBox, displays the QActions that are used to do special stuff on the profile ( like activating the plugins. )
|
|
|
|
// * 3 - Cartesian Axis for depth ( y )
|
|
|
|
// * 4 - Cartesian Axis for Gases ( y )
|
|
|
|
// * 5 - Cartesian Axis for Time ( x )
|
|
|
|
// *
|
|
|
|
// * It needs to be dynamic, things should *flow* on it, not just appear / disappear.
|
|
|
|
// */
|
2016-04-04 22:02:03 -07:00
|
|
|
#include "profile-widget/divelineitem.h"
|
2020-04-17 23:18:58 +02:00
|
|
|
#include "core/pictureobj.h"
|
2018-06-30 11:36:37 +02:00
|
|
|
#include "core/units.h"
|
2021-01-27 23:41:51 +01:00
|
|
|
#include "core/subsurface-qt/divelistnotifier.h"
|
2014-01-16 15:02:32 -02:00
|
|
|
|
2021-06-05 18:42:56 +02:00
|
|
|
class ProfileScene;
|
2014-02-27 15:20:03 -03:00
|
|
|
class RulerItem2;
|
2014-02-10 20:28:33 -08:00
|
|
|
struct dive;
|
2014-02-05 14:34:45 -02:00
|
|
|
class ToolTipItem;
|
2014-01-16 15:02:32 -02:00
|
|
|
class DiveEventItem;
|
2021-01-25 15:06:53 +01:00
|
|
|
class DivePlannerPointsModel;
|
2014-05-21 21:18:10 -03:00
|
|
|
class DiveHandler;
|
|
|
|
class QGraphicsSimpleTextItem;
|
|
|
|
class QModelIndex;
|
2014-06-08 12:43:04 -03:00
|
|
|
class DivePictureItem;
|
2014-01-14 14:30:13 -02:00
|
|
|
|
|
|
|
class ProfileWidget2 : public QGraphicsView {
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
2014-02-27 20:09:57 -08:00
|
|
|
enum State {
|
|
|
|
PROFILE,
|
2021-06-30 07:49:56 +02:00
|
|
|
EDIT,
|
2014-02-27 20:09:57 -08:00
|
|
|
PLAN,
|
2021-07-01 18:56:50 +02:00
|
|
|
INIT
|
2014-02-27 20:09:57 -08:00
|
|
|
};
|
2014-01-14 14:30:13 -02:00
|
|
|
|
2021-10-22 14:30:56 +02:00
|
|
|
struct RenderFlags {
|
|
|
|
static constexpr int None = 0;
|
|
|
|
static constexpr int Instant = 1 << 0;
|
|
|
|
static constexpr int DontRecalculatePlotInfo = 1 << 1;
|
|
|
|
};
|
|
|
|
|
2021-01-25 15:06:53 +01:00
|
|
|
// Pass null as plannerModel if no support for planning required
|
2021-08-09 16:48:08 +02:00
|
|
|
ProfileWidget2(DivePlannerPointsModel *plannerModel, double dpr, QWidget *parent = 0);
|
2019-07-15 20:41:42 +02:00
|
|
|
~ProfileWidget2();
|
2015-10-11 14:21:13 +03:00
|
|
|
void resetZoom();
|
2021-10-22 14:30:56 +02:00
|
|
|
void plotDive(const struct dive *d, int dc, int flags = RenderFlags::None);
|
2021-01-28 14:24:38 +01:00
|
|
|
void setProfileState(const struct dive *d, int dc);
|
|
|
|
void setPlanState(const struct dive *d, int dc);
|
2021-06-30 07:49:56 +02:00
|
|
|
void setEditState(const struct dive *d, int dc);
|
2021-01-10 14:04:43 +01:00
|
|
|
bool isPlanner() const;
|
2021-07-01 18:56:50 +02:00
|
|
|
void clear();
|
2015-11-05 16:05:44 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2018-09-29 22:13:44 +02:00
|
|
|
bool eventFilter(QObject *, QEvent *) override;
|
2015-11-05 16:05:44 -08:00
|
|
|
#endif
|
2021-06-05 18:42:56 +02:00
|
|
|
std::unique_ptr<ProfileScene> profileScene;
|
2014-05-21 14:24:19 -03:00
|
|
|
State currentState;
|
2014-01-14 14:30:13 -02:00
|
|
|
|
2015-07-29 12:21:27 -07:00
|
|
|
signals:
|
2022-02-19 11:58:36 +01:00
|
|
|
void stopAdded(); // only emitted in edit mode
|
|
|
|
void stopRemoved(int count); // only emitted in edit mode
|
|
|
|
void stopMoved(int count); // only emitted in edit mode
|
2015-07-29 12:21:27 -07:00
|
|
|
|
2014-02-27 20:09:57 -08:00
|
|
|
public
|
|
|
|
slots: // Necessary to call from QAction's signals.
|
2014-01-14 14:30:13 -02:00
|
|
|
void settingsChanged();
|
2016-01-25 15:54:23 -02:00
|
|
|
void actionRequestedReplot(bool triggered);
|
2021-01-27 23:41:51 +01:00
|
|
|
void divesChanged(const QVector<dive *> &dives, DiveField field);
|
2015-11-05 16:05:44 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2018-01-10 13:55:29 +01:00
|
|
|
void plotPictures();
|
2020-04-17 23:18:58 +02:00
|
|
|
void picturesRemoved(dive *d, QVector<QString> filenames);
|
|
|
|
void picturesAdded(dive *d, QVector<PictureObj> pics);
|
2021-01-24 23:29:28 +01:00
|
|
|
void pointsReset();
|
2014-05-21 21:18:10 -03:00
|
|
|
void pointInserted(const QModelIndex &parent, int start, int end);
|
|
|
|
void pointsRemoved(const QModelIndex &, int start, int end);
|
2021-01-24 23:29:28 +01:00
|
|
|
void pointsMoved(const QModelIndex &, int start, int end, const QModelIndex &destination, int row);
|
2018-07-15 17:56:18 +02:00
|
|
|
void updateThumbnail(QString filename, QImage thumbnail, duration_t duration);
|
2020-03-03 22:42:51 +01:00
|
|
|
void profileChanged(dive *d);
|
2020-04-14 22:07:00 +02:00
|
|
|
void pictureOffsetChanged(dive *d, QString filename, offset_t offset);
|
2020-12-19 12:32:32 +01:00
|
|
|
void removePicture(const QString &fileUrl);
|
2014-02-27 20:09:57 -08:00
|
|
|
|
2014-05-23 20:51:30 -03:00
|
|
|
/* this is called for every move on the handlers. maybe we can speed up this a bit? */
|
2021-01-25 15:51:37 +01:00
|
|
|
void divePlannerHandlerMoved();
|
2014-06-30 19:08:16 -03:00
|
|
|
void divePlannerHandlerClicked();
|
|
|
|
void divePlannerHandlerReleased();
|
2015-11-05 16:05:44 -08:00
|
|
|
#endif
|
2015-01-01 16:28:37 -08:00
|
|
|
|
2020-04-13 19:37:24 +02:00
|
|
|
private:
|
2021-01-28 14:24:38 +01:00
|
|
|
void setProfileState(); // keep currently displayed dive
|
2018-09-29 22:13:44 +02:00
|
|
|
void resizeEvent(QResizeEvent *event) override;
|
2016-02-06 13:25:58 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2018-09-29 22:13:44 +02:00
|
|
|
void wheelEvent(QWheelEvent *event) override;
|
|
|
|
void mouseMoveEvent(QMouseEvent *event) override;
|
|
|
|
void contextMenuEvent(QContextMenuEvent *event) override;
|
|
|
|
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
|
|
|
void mousePressEvent(QMouseEvent *event) override;
|
|
|
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
2022-02-19 14:06:58 +01:00
|
|
|
void keyPressEvent(QKeyEvent *e) override;
|
2016-02-06 13:25:58 -08:00
|
|
|
#endif
|
2018-09-29 22:13:44 +02:00
|
|
|
void dropEvent(QDropEvent *event) override;
|
|
|
|
void dragEnterEvent(QDragEnterEvent *event) override;
|
|
|
|
void dragMoveEvent(QDragMoveEvent *event) override;
|
2015-11-03 21:17:50 +01:00
|
|
|
|
2020-04-12 12:48:38 +02:00
|
|
|
void replot();
|
2021-10-06 21:01:58 +02:00
|
|
|
void setZoom(int level);
|
2020-01-30 15:03:48 +01:00
|
|
|
void changeGas(int tank, int seconds);
|
2014-02-07 15:32:39 -02:00
|
|
|
void setupSceneAndFlags();
|
|
|
|
void addItemsToScene();
|
|
|
|
void setupItemOnScene();
|
2014-05-21 21:23:19 -03:00
|
|
|
void disconnectTemporaryConnections();
|
2014-11-19 22:31:28 +00:00
|
|
|
struct plot_data *getEntryFromPos(QPointF pos);
|
2018-04-06 17:58:16 +02:00
|
|
|
void clearPictures();
|
2019-02-03 13:28:33 +01:00
|
|
|
void plotPicturesInternal(const struct dive *d, bool synchronous);
|
2021-10-26 07:42:13 +02:00
|
|
|
void updateThumbnails();
|
2020-03-02 21:48:53 +01:00
|
|
|
void addDivemodeSwitch(int seconds, int divemode);
|
2020-03-02 22:02:33 +01:00
|
|
|
void addBookmark(int seconds);
|
|
|
|
void splitDive(int seconds);
|
|
|
|
void addSetpointChange(int seconds);
|
2020-03-02 22:23:40 +01:00
|
|
|
void removeEvent(DiveEventItem *item);
|
2023-07-28 01:21:25 +12:00
|
|
|
void hideEvent(DiveEventItem *item);
|
2024-02-19 09:04:14 +01:00
|
|
|
void hideEventType(DiveEventItem *item);
|
2020-03-02 22:23:40 +01:00
|
|
|
void editName(DiveEventItem *item);
|
2020-03-02 22:48:12 +01:00
|
|
|
void unhideEvents();
|
2024-02-19 09:04:14 +01:00
|
|
|
void unhideEventTypes();
|
2020-03-02 22:48:12 +01:00
|
|
|
void makeFirstDC();
|
|
|
|
void deleteCurrentDC();
|
|
|
|
void splitCurrentDC();
|
2021-08-16 19:51:07 -10:00
|
|
|
void renameCurrentDC();
|
2020-04-13 19:37:24 +02:00
|
|
|
|
2021-01-25 15:06:53 +01:00
|
|
|
DivePlannerPointsModel *plannerModel; // If null, no planning supported.
|
2014-02-04 21:47:50 -02:00
|
|
|
int zoomLevel;
|
2021-10-06 21:01:58 +02:00
|
|
|
double zoomedPosition; // Position, when zoomed: 0.0 = beginning, 1.0 = end.
|
2016-02-06 13:25:58 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2014-02-05 14:34:45 -02:00
|
|
|
ToolTipItem *toolTipItem;
|
2016-02-06 13:25:58 -08:00
|
|
|
#endif
|
2021-01-28 14:24:38 +01:00
|
|
|
const struct dive *d;
|
|
|
|
int dc;
|
2021-12-03 08:50:52 +01:00
|
|
|
bool empty; // No dive shown.
|
2022-08-28 22:42:54 +02:00
|
|
|
bool panning; // Currently panning.
|
|
|
|
double panningOriginalMousePosition;
|
|
|
|
double panningOriginalProfilePosition;
|
2021-01-04 17:55:42 -08:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2014-08-05 18:27:00 -03:00
|
|
|
DiveLineItem *mouseFollowerVertical;
|
|
|
|
DiveLineItem *mouseFollowerHorizontal;
|
2014-02-27 15:20:03 -03:00
|
|
|
RulerItem2 *rulerItem;
|
2016-02-06 13:25:58 -08:00
|
|
|
#endif
|
2014-05-21 21:18:10 -03:00
|
|
|
|
2021-01-24 09:13:56 +01:00
|
|
|
std::vector<std::unique_ptr<QGraphicsSimpleTextItem>> gases;
|
2018-04-06 17:58:16 +02:00
|
|
|
|
2018-04-09 19:58:58 +02:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2018-06-30 11:36:37 +02:00
|
|
|
// 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.
|
|
|
|
struct PictureEntry {
|
|
|
|
offset_t offset;
|
2018-07-15 17:56:18 +02:00
|
|
|
duration_t duration;
|
2018-06-30 11:36:37 +02:00
|
|
|
QString filename;
|
|
|
|
std::unique_ptr<DivePictureItem> thumbnail;
|
2018-07-15 17:56:18 +02:00
|
|
|
// For videos with known duration, we represent the duration of the video by a line
|
|
|
|
std::unique_ptr<QGraphicsRectItem> durationLine;
|
2020-12-19 12:32:32 +01:00
|
|
|
PictureEntry (offset_t offsetIn, const QString &filenameIn, ProfileWidget2 *profile, bool synchronous);
|
2018-06-30 11:36:37 +02:00
|
|
|
bool operator< (const PictureEntry &e) const;
|
|
|
|
};
|
2018-06-30 21:32:14 +02:00
|
|
|
void updateThumbnailXPos(PictureEntry &e);
|
2018-06-30 11:36:37 +02:00
|
|
|
std::vector<PictureEntry> pictures;
|
2018-06-30 12:55:55 +02:00
|
|
|
void calculatePictureYPositions();
|
2018-07-15 17:56:18 +02:00
|
|
|
void updateDurationLine(PictureEntry &e);
|
|
|
|
void updateThumbnailPaintOrder();
|
2022-02-19 14:06:58 +01:00
|
|
|
|
|
|
|
void keyDeleteAction();
|
|
|
|
void keyUpAction();
|
|
|
|
void keyDownAction();
|
|
|
|
void keyLeftAction();
|
|
|
|
void keyRightAction();
|
2020-11-25 18:30:49 +01:00
|
|
|
#endif
|
2015-11-05 16:05:44 -08:00
|
|
|
|
2021-01-24 09:13:56 +01:00
|
|
|
std::vector<std::unique_ptr<DiveHandler>> handles;
|
|
|
|
int handleIndex(const DiveHandler *h) const;
|
2020-11-25 18:30:49 +01:00
|
|
|
#ifndef SUBSURFACE_MOBILE
|
2021-01-25 14:38:57 +01:00
|
|
|
void connectPlannerModel();
|
2014-05-21 23:31:26 -03:00
|
|
|
void repositionDiveHandlers();
|
2014-05-23 22:22:02 -03:00
|
|
|
int fixHandlerIndex(DiveHandler *activeHandler);
|
2021-01-24 23:29:28 +01:00
|
|
|
DiveHandler *createHandle();
|
|
|
|
QGraphicsSimpleTextItem *createGas();
|
2015-11-05 16:05:44 -08:00
|
|
|
#endif
|
2020-11-25 18:30:49 +01:00
|
|
|
friend class DiveHandler;
|
2021-07-29 17:19:50 +02:00
|
|
|
bool shouldCalculateMax; // Calculate maximum time and depth (default). False when dragging handles.
|
2022-02-19 11:58:36 +01:00
|
|
|
std::vector<int> selectedDiveHandleIndices() const;
|
2021-01-28 14:24:38 +01:00
|
|
|
|
|
|
|
// We store a const pointer to the shown dive. However, the undo commands want
|
|
|
|
// (understandably) a non-const pointer. Since the profile has a context-menu
|
|
|
|
// with actions, it needs such a non-const pointer. This function turns the
|
|
|
|
// currently shown dive into such a pointer. Ugly, yes.
|
|
|
|
struct dive *mutable_dive() const;
|
2014-01-14 14:30:13 -02:00
|
|
|
};
|
|
|
|
|
2014-02-11 19:14:46 +01:00
|
|
|
#endif // PROFILEWIDGET2_H
|