summaryrefslogtreecommitdiffstats
path: root/qt-ui/profilegraphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt-ui/profilegraphics.cpp')
-rw-r--r--qt-ui/profilegraphics.cpp1657
1 files changed, 0 insertions, 1657 deletions
diff --git a/qt-ui/profilegraphics.cpp b/qt-ui/profilegraphics.cpp
deleted file mode 100644
index f94a27c8c..000000000
--- a/qt-ui/profilegraphics.cpp
+++ /dev/null
@@ -1,1657 +0,0 @@
-#include "profilegraphics.h"
-#include "mainwindow.h"
-#include "divelistview.h"
-
-#include <QGraphicsScene>
-#include <QResizeEvent>
-#include <QGraphicsLineItem>
-#include <QScrollBar>
-#include <QPen>
-#include <QBrush>
-#include <QDebug>
-#include <QLineF>
-#include <QSettings>
-#include <QIcon>
-#include <QPropertyAnimation>
-#include <QGraphicsSceneHoverEvent>
-#include <QMouseEvent>
-#include <QToolBar>
-#include <qtextdocument.h>
-#include <QMessageBox>
-#include <limits>
-
-#include "../color.h"
-#include "../display.h"
-#include "../dive.h"
-#include "../profile.h"
-#include "../device.h"
-#include "../helpers.h"
-#include "../planner.h"
-#include "../gettextfromc.h"
-#include "profile/divetooltipitem.h"
-
-#include <libdivecomputer/parser.h>
-#include <libdivecomputer/version.h>
-
-static struct graphics_context last_gc;
-
-#if PRINT_IMPLEMENTED
-static double plot_scale = SCALE_SCREEN;
-#endif
-
-extern struct ev_select *ev_namelist;
-extern int evn_allocated;
-extern int evn_used;
-
-#define TOOLBAR_POS QPoint(viewport()->geometry().width() - toolBarProxy->boundingRect().width(), \
- viewport()->geometry().height() - toolBarProxy->boundingRect().height())
-
-ProfileGraphicsView::ProfileGraphicsView(QWidget *parent) : QGraphicsView(parent),
- toolTip(0),
- diveId(0),
- diveDC(0),
- rulerItem(0),
- toolBarProxy(0)
-{
- printMode = false;
- isGrayscale = false;
- rulerEnabled = false;
- gc.printer = false;
- fill_profile_color();
- setScene(new QGraphicsScene(this));
-
- scene()->installEventFilter(this);
-
- setRenderHint(QPainter::Antialiasing);
- setRenderHint(QPainter::HighQualityAntialiasing);
- setRenderHint(QPainter::SmoothPixmapTransform);
-
- defaultPen.setJoinStyle(Qt::RoundJoin);
- defaultPen.setCapStyle(Qt::RoundCap);
- defaultPen.setWidth(2);
- defaultPen.setCosmetic(true);
-
- setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-}
-
-/* since we cannot use translate() directly on the scene we hack on
- * the scroll bars (hidden) functionality */
-void ProfileGraphicsView::scrollViewTo(const QPoint pos)
-{
- if (!zoomLevel)
- return;
- QScrollBar *vs = verticalScrollBar();
- QScrollBar *hs = horizontalScrollBar();
- const qreal yRat = pos.y() / sceneRect().height();
- const qreal xRat = pos.x() / sceneRect().width();
- const int vMax = vs->maximum();
- const int hMax = hs->maximum();
- const int vMin = vs->minimum();
- const int hMin = hs->minimum();
- /* QScrollBar receives crazy negative values for minimum */
- vs->setValue(yRat * (vMax - vMin) + vMin * 0.9);
- hs->setValue(xRat * (hMax - hMin) + hMin * 0.9);
-}
-
-void ProfileGraphicsView::wheelEvent(QWheelEvent *event)
-{
- if (!toolTip)
- return;
-
- // doesn't seem to work for Qt 4.8.1
- // setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
-
- // Scale the view / do the zoom
- QPoint toolTipPos = mapFromScene(toolTip->pos());
-
- double scaleFactor = 1.15;
- if (event->delta() > 0 && zoomLevel < 20) {
- scale(scaleFactor, scaleFactor);
- zoomLevel++;
- } else if (event->delta() < 0 && zoomLevel > 0) {
- // Zooming out
- scale(1.0 / scaleFactor, 1.0 / scaleFactor);
- zoomLevel--;
- }
-
- scrollViewTo(event->pos());
- toolTip->setPos(mapToScene(toolTipPos));
- toolBarProxy->setPos(mapToScene(TOOLBAR_POS));
- if (zoomLevel != 0) {
- toolBarProxy->hide();
- } else {
- toolBarProxy->show();
- }
-}
-
-void ProfileGraphicsView::contextMenuEvent(QContextMenuEvent *event)
-{
- if (selected_dive == -1)
- return;
- QMenu m;
- QMenu *gasChange = m.addMenu(tr("Add Gas Change"));
- GasSelectionModel *model = GasSelectionModel::instance();
- model->repopulate();
- int rowCount = model->rowCount();
- for (int i = 0; i < rowCount; i++) {
- QAction *action = new QAction(&m);
- action->setText(model->data(model->index(i, 0), Qt::DisplayRole).toString());
- connect(action, SIGNAL(triggered(bool)), this, SLOT(changeGas()));
- action->setData(event->globalPos());
- gasChange->addAction(action);
- }
- QAction *action = m.addAction(tr("Add Bookmark"), this, SLOT(addBookmark()));
- action->setData(event->globalPos());
- QList<QGraphicsItem *> itemsAtPos = scene()->items(mapToScene(mapFromGlobal(event->globalPos())));
- Q_FOREACH(QGraphicsItem * i, itemsAtPos) {
- EventItem *item = dynamic_cast<EventItem *>(i);
- if (!item)
- continue;
- action = new QAction(&m);
- action->setText(tr("Remove Event"));
- action->setData(QVariant::fromValue<void *>(item)); // so we know what to remove.
- connect(action, SIGNAL(triggered(bool)), this, SLOT(removeEvent()));
- m.addAction(action);
- action = new QAction(&m);
- action->setText(tr("Hide similar events"));
- action->setData(QVariant::fromValue<void *>(item));
- connect(action, SIGNAL(triggered(bool)), this, SLOT(hideEvents()));
- m.addAction(action);
- break;
- }
- bool some_hidden = false;
- for (int i = 0; i < evn_used; i++) {
- if (ev_namelist[i].plot_ev == false) {
- some_hidden = true;
- break;
- }
- }
- if (some_hidden) {
- action = m.addAction(tr("Unhide all events"), this, SLOT(unhideEvents()));
- action->setData(event->globalPos());
- }
- m.exec(event->globalPos());
-}
-
-void ProfileGraphicsView::addBookmark()
-{
- QAction *action = qobject_cast<QAction *>(sender());
- QPoint globalPos = action->data().toPoint();
- QPoint viewPos = mapFromGlobal(globalPos);
- QPointF scenePos = mapToScene(viewPos);
- int seconds = scenePos.x() / gc.maxx * (gc.rightx - gc.leftx) + gc.leftx;
- add_event(current_dc, seconds, SAMPLE_EVENT_BOOKMARK, 0, 0, "bookmark");
- mark_divelist_changed(true);
- plot(current_dive, true);
-}
-
-void ProfileGraphicsView::changeGas()
-{
- QAction *action = qobject_cast<QAction *>(sender());
- QPoint globalPos = action->data().toPoint();
- QPoint viewPos = mapFromGlobal(globalPos);
- QPointF scenePos = mapToScene(viewPos);
- QString gas = action->text();
- int o2, he;
- validate_gas(gas.toUtf8().constData(), &o2, &he);
- int seconds = scenePos.x() / gc.maxx * (gc.rightx - gc.leftx) + gc.leftx;
- add_gas_switch_event(current_dive, current_dc, seconds, get_gasidx(current_dive, o2, he));
- // this means we potentially have a new tank that is being used and needs to be shown
- fixup_dive(current_dive);
- MainWindow::instance()->information()->updateDiveInfo(selected_dive);
- mark_divelist_changed(true);
- plot(current_dive, true);
-}
-
-void ProfileGraphicsView::hideEvents()
-{
- QAction *action = qobject_cast<QAction *>(sender());
- EventItem *item = static_cast<EventItem *>(action->data().value<void *>());
- struct event *event = item->ev;
-
- if (QMessageBox::question(MainWindow::instance(), TITLE_OR_TEXT(
- tr("Hide events"),
- tr("Hide all %1 events?").arg(event->name)),
- QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
- if (event->name) {
- for (int i = 0; i < evn_used; i++) {
- if (!strcmp(event->name, ev_namelist[i].ev_name)) {
- ev_namelist[i].plot_ev = false;
- break;
- }
- }
- }
- plot(current_dive, true);
- }
-}
-
-void ProfileGraphicsView::unhideEvents()
-{
- for (int i = 0; i < evn_used; i++) {
- ev_namelist[i].plot_ev = true;
- }
- plot(current_dive, true);
-}
-
-void ProfileGraphicsView::removeEvent()
-{
- QAction *action = qobject_cast<QAction *>(sender());
- EventItem *item = static_cast<EventItem *>(action->data().value<void *>());
- struct event *event = item->ev;
-
- if (QMessageBox::question(MainWindow::instance(), TITLE_OR_TEXT(
- tr("Remove the selected event?"),
- tr("%1 @ %2:%3").arg(event->name).arg(event->time.seconds / 60).arg(event->time.seconds % 60, 2, 10, QChar('0'))),
- QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
- struct event **ep = &current_dc->events;
- while (ep && *ep != event)
- ep = &(*ep)->next;
- if (ep) {
- *ep = event->next;
- free(event);
- }
- mark_divelist_changed(true);
- plot(current_dive, true);
- }
-}
-
-
-void ProfileGraphicsView::mouseMoveEvent(QMouseEvent *event)
-{
- if (!toolTip)
- return;
-
- toolTip->refresh(&gc, mapToScene(event->pos()));
- QPoint toolTipPos = mapFromScene(toolTip->pos());
- scrollViewTo(event->pos());
-
- if (zoomLevel == 0) {
- QGraphicsView::mouseMoveEvent(event);
- } else {
- toolTip->setPos(mapToScene(toolTipPos));
- toolBarProxy->setPos(mapToScene(TOOLBAR_POS));
- }
-}
-
-bool ProfileGraphicsView::eventFilter(QObject *obj, QEvent *event)
-{
- if (event->type() == QEvent::Leave) {
- if (toolTip && toolTip->isExpanded())
- toolTip->collapse();
- return true;
- }
-
- // This will "Eat" the default tooltip behavior if it is not on the toolBar.
- if (event->type() == QEvent::GraphicsSceneHelp) {
- if (toolBarProxy && !toolBarProxy->geometry().contains(mapToScene(mapFromGlobal(QCursor::pos())))) {
- event->ignore();
- return true;
- }
- }
- return QGraphicsView::eventFilter(obj, event);
-}
-
-#if PRINT_IMPLEMENTED
-static void plot_set_scale(scale_mode_t scale)
-{
- switch (scale) {
- default:
- case SC_SCREEN:
- plot_scale = SCALE_SCREEN;
- break;
- case SC_PRINT:
- plot_scale = SCALE_PRINT;
- break;
- }
-}
-#endif
-
-void ProfileGraphicsView::showEvent(QShowEvent *event)
-{
- // Program just opened,
- // but the dive was not ploted.
- // force a replot by modifying the dive
- // hold by the view, and issuing a plot.
- if (diveId && !scene()->items().count()) {
- diveId = 0;
- plot(get_dive(selected_dive));
- }
- if (toolBarProxy)
- toolBarProxy->setPos(mapToScene(TOOLBAR_POS));
-}
-
-void ProfileGraphicsView::clear()
-{
- resetTransform();
- zoomLevel = 0;
- if (toolTip) {
- scene()->removeItem(toolTip);
- toolTip->deleteLater();
- toolTip = 0;
- }
- if (toolBarProxy) {
- scene()->removeItem(toolBarProxy);
- toolBarProxy->deleteLater();
- toolBarProxy = 0;
- }
- if (rulerItem) {
- remove_ruler();
- rulerItem->destNode()->deleteLater();
- rulerItem->sourceNode()->deleteLater();
- rulerItem->deleteLater();
- rulerItem = 0;
- }
- scene()->clear();
-}
-
-void ProfileGraphicsView::refresh()
-{
- clear();
- plot(current_dive, true);
-}
-
-void ProfileGraphicsView::setPrintMode(bool mode, bool grayscale)
-{
- printMode = mode;
- isGrayscale = grayscale;
-}
-
-QColor ProfileGraphicsView::getColor(const color_indice_t i)
-{
- return profile_color[i].at((isGrayscale) ? 1 : 0);
-}
-
-void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
-{
- struct divecomputer *dc = NULL;
-
- if (d)
- dc = select_dc(&d->dc);
-
- if (!forceRedraw && getDiveById(diveId) == d && (d && dc == diveDC))
- return;
-
- clear();
- diveId = d ? d->id : 0;
- diveDC = d ? dc : NULL;
-
- if (!isVisible() || !d || !MainWindow::instance()) {
- return;
- }
- setBackgroundBrush(getColor(BACKGROUND));
-
- // best place to put the focus stealer code.
- setFocusProxy(MainWindow::instance()->dive_list());
- scene()->setSceneRect(0, 0, viewport()->width() - 50, viewport()->height() - 50);
-
- toolTip = new ToolTipItem();
- installEventFilter(toolTip);
- scene()->addItem(toolTip);
- if (printMode)
- toolTip->setVisible(false);
-
- // Fix this for printing / screen later.
- // plot_set_scale(scale_mode_t);
-
- if (!dc || !dc->samples) {
- dc = fake_dc(dc);
- }
-
- QString nick = get_dc_nickname(dc->model, dc->deviceid);
- if (nick.isEmpty())
- nick = QString(dc->model);
-
- if (nick.isEmpty())
- nick = tr("unknown divecomputer");
-
- if (tr("unknown divecomputer") == nick) {
- mode = PLAN;
- } else {
- mode = DIVE;
- }
-
- /*
- * Set up limits that are independent of
- * the dive computer
- */
- calculate_max_limits(d, dc, &gc);
-
- QRectF profile_grid_area = scene()->sceneRect();
- gc.maxx = (profile_grid_area.width() - 2 * profile_grid_area.x());
- gc.maxy = (profile_grid_area.height() - 2 * profile_grid_area.y());
-
- /* This is per-dive-computer */
- gc.pi = *create_plot_info(d, dc, &gc, printMode);
-
- /* Bounding box */
- QPen pen = defaultPen;
- pen.setColor(getColor(TIME_GRID));
- QGraphicsRectItem *rect = new QGraphicsRectItem(profile_grid_area);
- rect->setPen(pen);
- scene()->addItem(rect);
-
- /* Depth profile */
- plot_depth_profile(); // TODO: PARTIALLY PORTED.
- plot_events(dc); // PORTED
-
- if (rulerEnabled && !printMode) // TODO: NOT PORTED.
- create_ruler();
-
- /* Temperature profile */
- plot_temperature_profile(); // PORTED
-
- /* Cylinder pressure plot */
- plot_cylinder_pressure(); // PORTED
-
- /* Text on top of all graphs.. */ // TODO: NOT PORTED, ANY TEXT.
- plot_temperature_text();
- plot_depth_text();
- plot_cylinder_pressure_text();
- plot_deco_text();
-
- // NOT PORTED.
- /* Put the dive computer name in the lower left corner */
- gc.leftx = 0;
- gc.rightx = 1.0;
- gc.topy = 0;
- gc.bottomy = 1.0;
-
- text_render_options_t computer = { DC_TEXT_SIZE, TIME_TEXT, LEFT, TOP };
- diveComputer = plot_text(&computer, QPointF(gc.leftx, gc.bottomy), nick);
- // The Time ruler should be right after the DiveComputer:
- timeMarkers->setPos(0, diveComputer->y());
-
- // NOT PORTED.
- if (PP_GRAPHS_ENABLED) {
- plot_pp_gas_profile();
- plot_pp_text();
- }
-
- // NOT PORTED.
- plot_depth_scale();
-
-#if 0
- if (gc->printer) {
- free(pi->entry);
- last_pi_entry = pi->entry = NULL;
- pi->nr = 0;
- }
-#endif
-
- QRectF r = scene()->itemsBoundingRect();
- scene()->setSceneRect(r.x() - 15, r.y() - 15, r.width() + 30, r.height() + 30);
- if (zoomLevel == 0) {
- fitInView(sceneRect());
- }
- toolTip->readPos();
-
- if (mode == PLAN) {
- timeEditor = new GraphicsTextEditor();
- timeEditor->setPlainText(d->duration.seconds ? QString::number(d->duration.seconds / 60) : tr("Set Duration: 10 minutes"));
- timeEditor->setPos(profile_grid_area.width() - timeEditor->boundingRect().width(), timeMarkers->y());
- timeEditor->document();
- connect(timeEditor, SIGNAL(editingFinished(QString)), this, SLOT(edit_dive_time(QString)));
- scene()->addItem(timeEditor);
- }
-
- if (!printMode)
- addControlItems(d);
-
- if (rulerEnabled && !printMode)
- add_ruler();
-
- gc.rightx = get_maxtime(&gc.pi);
-}
-
-void ProfileGraphicsView::plot_depth_scale()
-{
- int i, maxdepth, marker;
- static text_render_options_t tro = { DEPTH_TEXT_SIZE, SAMPLE_DEEP, RIGHT, MIDDLE };
-
- /* Depth markers: every 30 ft or 10 m*/
- maxdepth = get_maxdepth(&gc.pi);
- gc.topy = 0;
- gc.bottomy = maxdepth;
- marker = M_OR_FT(10, 30);
-
- /* don't write depth labels all the way to the bottom as
- * there may be other graphs below the depth plot (like
- * partial pressure graphs) where this would look out
- * of place - so we only make sure that we print the next
- * marker below the actual maxdepth of the dive */
- depthMarkers = new QGraphicsRectItem();
- for (i = marker; i <= gc.pi.maxdepth + marker; i += marker) {
- double d = get_depth_units(i, NULL, NULL);
- plot_text(&tro, QPointF(-0.002, i), QString::number(d), depthMarkers);
- }
- scene()->addItem(depthMarkers);
- depthMarkers->setPos(depthMarkers->pos().x() - 10, 0);
-}
-
-void ProfileGraphicsView::addControlItems(struct dive *d)
-{
- QAction *scaleAction = new QAction(QIcon(":scale"), tr("Scale"), this);
- QAction *rulerAction = new QAction(QIcon(":ruler"), tr("Ruler"), this);
- QToolBar *toolBar = new QToolBar("", 0);
- rulerAction->setToolTip(tr("Measure properties of dive segments"));
- scaleAction->setToolTip(tr("Scale your dive to screen size"));
- toolBar->addAction(rulerAction);
- toolBar->addAction(scaleAction);
- toolBar->setOrientation(Qt::Vertical);
- //make toolbar transparent
- //toolBar->setStyleSheet(QString::fromUtf8 ("background-color: rgba(255,255,255,0);"));
-
- connect(scaleAction, SIGNAL(triggered()), this, SLOT(on_scaleAction()));
- connect(rulerAction, SIGNAL(triggered()), this, SLOT(on_rulerAction()));
- //Put it into the lower right corner of the profile
-
- QString defaultDC(d->dc.model);
- if (defaultDC == "manually added dive" || defaultDC == "planned dive") {
- QAction *editAction = new QAction(QIcon(":edit"), tr("Edit"), this);
- toolBar->addAction(editAction);
- connect(editAction, SIGNAL(triggered()), MainWindow::instance(), SLOT(editCurrentDive()));
- }
- toolBarProxy = scene()->addWidget(toolBar);
- toolBarProxy->setPos(mapToScene(TOOLBAR_POS));
- toolBarProxy->setFlag(QGraphicsItem::ItemIgnoresTransformations);
-}
-
-void ProfileGraphicsView::plot_pp_text()
-{
- double pp, dpp, m;
- int hpos;
- static text_render_options_t tro = { PP_TEXT_SIZE, PP_LINES, LEFT, -0.75 };
- QGraphicsRectItem *pressureMarkers = new QGraphicsRectItem();
-
- setup_pp_limits(&gc);
- pp = floor(gc.pi.maxpp * 10.0) / 10.0 + 0.2;
- dpp = pp > 4 ? 0.5 : 0.25;
- hpos = gc.pi.entry[gc.pi.nr - 1].sec;
- QColor c = getColor(PP_LINES);
-
- bool alt = true;
- for (m = 0.0; m <= pp; m += dpp) {
- QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(0, m), SCALEGC(hpos, m));
- QPen pen(defaultPen);
- pen.setColor(c);
- if (IS_FP_SAME(QString::number(m).toDouble(), QString::number(m).toInt())) {
- pen.setStyle(Qt::DashLine);
- pen.setWidthF(1.2);
- }
- item->setPen(pen);
- scene()->addItem(item);
- qreal textPos = hpos;
- if (alt)
- plot_text(&tro, QPointF(textPos, m), QString::number(m), pressureMarkers);
- alt = !alt;
- }
- scene()->addItem(pressureMarkers);
- pressureMarkers->setPos(pressureMarkers->pos().x() + 10, 0);
-}
-
-void ProfileGraphicsView::plot_add_line(int sec, double val, QColor c, QPointF &from)
-{
- QPointF to = QPointF(SCALEGC(sec, val));
- QGraphicsLineItem *item = new QGraphicsLineItem(from.x(), from.y(), to.x(), to.y());
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
- from = to;
-}
-
-void ProfileGraphicsView::plot_pp_gas_profile()
-{
- int i;
- struct plot_data *entry;
- struct plot_info *pi = &gc.pi;
-
- setup_pp_limits(&gc);
- QColor c;
- QPointF from, to;
- QPointF legendPos = QPointF(scene()->sceneRect().width() * 0.4, scene()->sceneRect().height() - scene()->sceneRect().height() * 0.02);
-
- if (prefs.pp_graphs.pn2) {
- c = getColor(PN2);
- entry = pi->entry;
- from = QPointF(SCALEGC(entry->sec, entry->pn2));
- for (i = 1; i < pi->nr; i++) {
- entry++;
- if (entry->pn2 < prefs.pp_graphs.pn2_threshold)
- plot_add_line(entry->sec, entry->pn2, c, from);
- else
- from = QPointF(SCALEGC(entry->sec, entry->pn2));
- }
-
- c = getColor(PN2_ALERT);
- entry = pi->entry;
- from = QPointF(SCALEGC(entry->sec, entry->pn2));
- for (i = 1; i < pi->nr; i++) {
- entry++;
- if (entry->pn2 >= prefs.pp_graphs.pn2_threshold)
- plot_add_line(entry->sec, entry->pn2, c, from);
- else
- from = QPointF(SCALEGC(entry->sec, entry->pn2));
- }
- createPPLegend(trUtf8("pN" UTF8_SUBSCRIPT_2), getColor(PN2), legendPos);
- }
-
- if (prefs.pp_graphs.phe) {
- c = getColor(PHE);
- entry = pi->entry;
-
- from = QPointF(SCALEGC(entry->sec, entry->phe));
- for (i = 1; i < pi->nr; i++) {
- entry++;
- if (entry->phe < prefs.pp_graphs.phe_threshold)
- plot_add_line(entry->sec, entry->phe, c, from);
- else
- from = QPointF(SCALEGC(entry->sec, entry->phe));
- }
-
- c = getColor(PHE_ALERT);
- entry = pi->entry;
- from = QPointF(SCALEGC(entry->sec, entry->phe));
- for (i = 1; i < pi->nr; i++) {
- entry++;
- if (entry->phe >= prefs.pp_graphs.phe_threshold)
- plot_add_line(entry->sec, entry->phe, c, from);
- else
- from = QPointF(SCALEGC(entry->sec, entry->phe));
- }
- createPPLegend(trUtf8("pHe"), getColor(PHE), legendPos);
- }
- if (prefs.pp_graphs.po2) {
- c = getColor(PO2);
- entry = pi->entry;
- from = QPointF(SCALEGC(entry->sec, entry->po2));
- for (i = 1; i < pi->nr; i++) {
- entry++;
- if (entry->po2 < prefs.pp_graphs.po2_threshold)
- plot_add_line(entry->sec, entry->po2, c, from);
- else
- from = QPointF(SCALEGC(entry->sec, entry->po2));
- }
-
- c = getColor(PO2_ALERT);
- entry = pi->entry;
- from = QPointF(SCALEGC(entry->sec, entry->po2));
- for (i = 1; i < pi->nr; i++) {
- entry++;
- if (entry->po2 >= prefs.pp_graphs.po2_threshold)
- plot_add_line(entry->sec, entry->po2, c, from);
- else
- from = QPointF(SCALEGC(entry->sec, entry->po2));
- }
- createPPLegend(trUtf8("pO" UTF8_SUBSCRIPT_2), getColor(PO2), legendPos);
- }
-}
-
-void ProfileGraphicsView::createPPLegend(QString title, const QColor &c, QPointF &legendPos)
-{
- QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, scene()->sceneRect().width() * 0.01, scene()->sceneRect().width() * 0.01);
- rect->setBrush(QBrush(c));
- rect->setPos(legendPos);
- rect->setPen(QPen(QColor(Qt::transparent)));
- QGraphicsSimpleTextItem *text = new QGraphicsSimpleTextItem(title);
- text->setPos(legendPos.x() + rect->boundingRect().width() + 5, legendPos.y());
- scene()->addItem(rect);
- scene()->addItem(text);
- legendPos.setX(text->pos().x() + text->boundingRect().width() + 20);
- if (printMode) {
- QFont f = text->font();
- f.setPointSizeF(f.pointSizeF() * 0.7);
- text->setFont(f);
- }
-}
-
-void ProfileGraphicsView::plot_deco_text()
-{
- if (prefs.profile_calc_ceiling) {
- float x = gc.leftx + (gc.rightx - gc.leftx) / 2;
- float y = gc.topy = 1.0;
- static text_render_options_t tro = { PRESSURE_TEXT_SIZE, PRESSURE_TEXT, CENTER, BOTTOM };
- gc.bottomy = 0.0;
- plot_text(&tro, QPointF(x, y), QString("GF %1/%2").arg(prefs.gflow).arg(prefs.gfhigh));
- }
-}
-
-void ProfileGraphicsView::plot_cylinder_pressure_text()
-{
- int i;
- int mbar, cyl;
- int seen_cyl[MAX_CYLINDERS] = { false, };
- int last_pressure[MAX_CYLINDERS] = { 0, };
- int last_time[MAX_CYLINDERS] = { 0, };
- struct plot_data *entry;
- struct plot_info *pi = &gc.pi;
- struct dive *dive = getDiveById(diveId);
- Q_ASSERT(dive != NULL);
-
- if (!get_cylinder_pressure_range(&gc))
- return;
-
- cyl = -1;
- for (i = 0; i < pi->nr; i++) {
- entry = pi->entry + i;
- mbar = GET_PRESSURE(entry);
-
- if (!mbar)
- continue;
- if (cyl != entry->cylinderindex) {
- cyl = entry->cylinderindex;
- if (!seen_cyl[cyl]) {
- plot_pressure_value(mbar, entry->sec, LEFT, BOTTOM);
- plot_gas_value(mbar, entry->sec, LEFT, TOP,
- get_o2(&dive->cylinder[cyl].gasmix),
- get_he(&dive->cylinder[cyl].gasmix));
- seen_cyl[cyl] = true;
- }
- }
- last_pressure[cyl] = mbar;
- last_time[cyl] = entry->sec;
- }
-
- for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
- if (last_time[cyl]) {
- plot_pressure_value(last_pressure[cyl], last_time[cyl], CENTER, TOP);
- }
- }
-}
-
-void ProfileGraphicsView::plot_pressure_value(int mbar, int sec, double xalign, double yalign)
-{
- int pressure;
- const char *unit;
-
- pressure = get_pressure_units(mbar, &unit);
- static text_render_options_t tro = { PRESSURE_TEXT_SIZE, PRESSURE_TEXT, xalign, yalign };
- plot_text(&tro, QPointF(sec, mbar), QString("%1 %2").arg(pressure).arg(unit));
-}
-
-void ProfileGraphicsView::plot_gas_value(int mbar, int sec, double xalign, double yalign, int o2, int he)
-{
- QString gas;
- if (is_air(o2, he))
- gas = tr("air");
- else if (he == 0)
- gas = QString(tr("EAN%1")).arg((o2 + 5) / 10);
- else
- gas = QString("%1/%2").arg((o2 + 5) / 10).arg((he + 5) / 10);
- static text_render_options_t tro = { PRESSURE_TEXT_SIZE, PRESSURE_TEXT, xalign, yalign };
- plot_text(&tro, QPointF(sec, mbar), gas);
-}
-
-void ProfileGraphicsView::plot_depth_text()
-{
- int maxtime, maxdepth;
-
- /* Get plot scaling limits */
- maxtime = get_maxtime(&gc.pi);
- maxdepth = get_maxdepth(&gc.pi);
-
- gc.leftx = 0;
- gc.rightx = maxtime;
- gc.topy = 0;
- gc.bottomy = maxdepth;
-
- plot_text_samples();
-}
-
-void ProfileGraphicsView::plot_text_samples()
-{
- static text_render_options_t deep = { 14, SAMPLE_DEEP, CENTER, TOP };
- static text_render_options_t shallow = { 14, SAMPLE_SHALLOW, CENTER, BOTTOM };
- int i;
- int last = -1;
-
- struct plot_info *pi = &gc.pi;
-
- for (i = 0; i < pi->nr; i++) {
- struct plot_data *entry = pi->entry + i;
-
- if (entry->depth < 2000)
- continue;
-
- if ((entry == entry->max[2]) && entry->depth / 100 != last) {
- plot_depth_sample(entry, &deep);
- last = entry->depth / 100;
- }
-
- if ((entry == entry->min[2]) && entry->depth / 100 != last) {
- plot_depth_sample(entry, &shallow);
- last = entry->depth / 100;
- }
-
- if (entry->depth != last)
- last = -1;
- }
-}
-
-void ProfileGraphicsView::plot_depth_sample(struct plot_data *entry, text_render_options_t *tro)
-{
- int sec = entry->sec, decimals;
- double d;
-
- d = get_depth_units(entry->depth, &decimals, NULL);
-
- plot_text(tro, QPointF(sec, entry->depth), QString("%1").arg(d, 0, 'f', 1));
-}
-
-void ProfileGraphicsView::plot_temperature_text()
-{
- int i;
- int last = -300, sec = 0;
- int last_temperature = 0, last_printed_temp = 0;
- plot_info *pi = &gc.pi;
-
- if (!setup_temperature_limits(&gc))
- return;
-
- for (i = 0; i < pi->nr; i++) {
- struct plot_data *entry = pi->entry + i;
- int mkelvin = entry->temperature;
- sec = entry->sec;
-
- if (!mkelvin)
- continue;
- last_temperature = mkelvin;
- /* don't print a temperature
- * if it's been less than 5min and less than a 2K change OR
- * if it's been less than 2min OR if the change from the
- * last print is less than .4K (and therefore less than 1F) */
- if (((sec < last + 300) && (abs(mkelvin - last_printed_temp) < 2000)) ||
- (sec < last + 120) ||
- (abs(mkelvin - last_printed_temp) < 400))
- continue;
- last = sec;
- if (mkelvin > 200000)
- plot_single_temp_text(sec, mkelvin);
- last_printed_temp = mkelvin;
- }
- /* it would be nice to print the end temperature, if it's
- * different or if the last temperature print has been more
- * than a quarter of the dive back */
- if (last_temperature > 200000 &&
- ((abs(last_temperature - last_printed_temp) > 500) || ((double)last / (double)sec < 0.75)))
- plot_single_temp_text(sec, last_temperature);
-}
-
-void ProfileGraphicsView::plot_single_temp_text(int sec, int mkelvin)
-{
- double deg;
- const char *unit;
- static text_render_options_t tro = { TEMP_TEXT_SIZE, TEMP_TEXT, LEFT, TOP };
- deg = get_temp_units(mkelvin, &unit);
- plot_text(&tro, QPointF(sec, mkelvin), QString("%1%2").arg(deg, 0, 'f', 1).arg(unit)); //"%.2g%s"
-}
-
-void ProfileGraphicsView::plot_cylinder_pressure()
-{
- int i;
- int last_index = -1;
- int lift_pen = false;
- int first_plot = true;
-
- if (!get_cylinder_pressure_range(&gc))
- return;
-
- struct dive *dive = getDiveById(diveId);
- Q_ASSERT(dive != NULL);
- QPointF from, to;
- for (i = 0; i < gc.pi.nr; i++) {
- int mbar;
- struct plot_data *entry = gc.pi.entry + i;
-
- mbar = GET_PRESSURE(entry);
- if (entry->cylinderindex != last_index) {
- lift_pen = true;
- }
- if (!mbar) {
- lift_pen = true;
- continue;
- }
-
- QColor c = get_sac_color(entry->sac, dive->sac);
-
- if (lift_pen) {
- if (!first_plot && entry->cylinderindex == last_index) {
- /* if we have a previous event from the same tank,
- * draw at least a short line */
- int prev_pr;
- prev_pr = GET_PRESSURE(entry - 1);
-
- QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC((entry - 1)->sec, prev_pr), SCALEGC(entry->sec, mbar));
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
- } else {
- first_plot = false;
- from = QPointF(SCALEGC(entry->sec, mbar));
- }
- lift_pen = false;
- } else {
- to = QPointF(SCALEGC(entry->sec, mbar));
- QGraphicsLineItem *item = new QGraphicsLineItem(from.x(), from.y(), to.x(), to.y());
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
- }
-
- from = QPointF(SCALEGC(entry->sec, mbar));
- last_index = entry->cylinderindex;
- }
-}
-
-/* set the color for the pressure plot according to temporary sac rate
- * as compared to avg_sac; the calculation simply maps the delta between
- * sac and avg_sac to indexes 0 .. (SAC_COLORS - 1) with everything
- * more than 6000 ml/min below avg_sac mapped to 0 */
-QColor ProfileGraphicsView::get_sac_color(int sac, int avg_sac)
-{
- int sac_index = 0;
- int delta = sac - avg_sac + 7000;
-
- if (!gc.printer) {
- sac_index = delta / 2000;
- if (sac_index < 0)
- sac_index = 0;
- if (sac_index > SAC_COLORS - 1)
- sac_index = SAC_COLORS - 1;
- return getColor((color_indice_t)(SAC_COLORS_START_IDX + sac_index));
- }
- return getColor(SAC_DEFAULT);
-}
-
-void ProfileGraphicsView::plot_events(struct divecomputer *dc)
-{
- struct event *event = dc->events;
-
- // if (gc->printer) {
- // return;
- // }
-
- while (event) {
- plot_one_event(event);
- event = event->next;
- }
-}
-
-void ProfileGraphicsView::plot_one_event(struct event *ev)
-{
- int i;
- struct plot_info *pi = &gc.pi;
- struct plot_data *entry = NULL;
-
- /* is plotting of this event disabled? */
- if (ev->name) {
- for (i = 0; i < evn_used; i++) {
- if (!strcmp(ev->name, ev_namelist[i].ev_name)) {
- if (ev_namelist[i].plot_ev)
- break;
- else
- return;
- }
- }
- }
-
- if (ev->time.seconds < 30 && !strcmp(ev->name, "gaschange"))
- /* a gas change in the first 30 seconds is the way of some dive computers
- * to tell us the gas that is used; let's not plot a marker for that */
- return;
-
- for (i = 0; i < pi->nr; i++) {
- entry = pi->entry + i;
- if (ev->time.seconds < entry->sec)
- break;
- }
-
- /* If we didn't find the right event, don't dereference null */
- if (entry == NULL)
- return;
-
- /* draw a little triangular marker and attach tooltip */
-
- int x = SCALEXGC(ev->time.seconds);
- int y = SCALEYGC(entry->depth);
- struct dive *dive = getDiveById(diveId);
- Q_ASSERT(dive != NULL);
- EventItem *item = new EventItem(ev, 0, isGrayscale);
- item->setPos(x, y);
- scene()->addItem(item);
-
- if (ev->type == 123) {
- QPixmap picture;
- picture.load(ev->name);
- scene()->addPixmap(picture.scaledToHeight(100, Qt::SmoothTransformation))->setPos(x, y + 10);
- }
-
-
- /* we display the event on screen - so translate (with the correct context for events) */
- QString name = gettextFromC::instance()->tr(ev->name);
- if (ev->value) {
- if (ev->name && strcmp(ev->name, "gaschange") == 0) {
- int he = get_he(&dive->cylinder[entry->cylinderindex].gasmix);
- int o2 = get_o2(&dive->cylinder[entry->cylinderindex].gasmix);
-
- name += ": ";
- if (he)
- name += QString("%1/%2").arg((o2 + 5) / 10).arg((he + 5) / 10);
- else if (is_air(o2, he))
- name += tr("air");
- else
- name += QString(tr("EAN%1")).arg((o2 + 5) / 10);
-
- } else if (ev->name && !strcmp(ev->name, "SP change")) {
- name += QString(":%1").arg((double)ev->value / 1000);
- } else {
- name += QString(":%1").arg(ev->value);
- }
- } else if (ev->name && name == "SP change") {
- name += "\n" + tr("Bailing out to OC");
- } else {
- name += ev->flags == SAMPLE_FLAGS_BEGIN ? tr(" begin", "Starts with space!") :
- ev->flags == SAMPLE_FLAGS_END ? tr(" end", "Starts with space!") : "";
- }
-
- //item->setToolTipController(toolTip);
- //item->addToolTip(name);
- item->setToolTip(name);
-}
-
-void ProfileGraphicsView::create_ruler()
-{
- int x, y;
- struct plot_info *pi = &gc.pi;
- struct plot_data *data = pi->entry;
-
- RulerNodeItem *first = new RulerNodeItem(0, gc);
- RulerNodeItem *second = new RulerNodeItem(0, gc);
-
- x = SCALEXGC(data->sec);
- y = data->depth;
-
- first->setPos(x, y);
-
- data = pi->entry + (pi->nr - 1);
- x = SCALEXGC(data->sec);
- y = data->depth;
-
- second->setPos(x, y);
- //Make sure that both points already have their entries
- first->recalculate();
- second->recalculate();
-
- rulerItem = new RulerItem(0, first, second);
- first->setRuler(rulerItem);
- second->setRuler(rulerItem);
-}
-
-void ProfileGraphicsView::add_ruler()
-{
- if (!scene()->items().contains(rulerItem)) {
- scene()->addItem(rulerItem->sourceNode());
- scene()->addItem(rulerItem->destNode());
- scene()->addItem(rulerItem);
- rulerItem->recalculate();
- }
-}
-
-void ProfileGraphicsView::remove_ruler()
-{
- if (rulerItem) {
- if (scene()->items().contains(rulerItem))
- scene()->removeItem(rulerItem);
- if (scene()->items().contains(rulerItem->sourceNode()))
- scene()->removeItem(rulerItem->sourceNode());
- if (scene()->items().contains(rulerItem->destNode()))
- scene()->removeItem(rulerItem->destNode());
- }
-}
-
-void ProfileGraphicsView::plot_depth_profile()
-{
- int i, incr;
- int sec, depth;
- struct plot_data *entry;
- int maxtime, maxdepth, marker, maxline;
- int increments[8] = { 10, 20, 30, 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60 };
-
- /* Get plot scaling limits */
- maxtime = get_maxtime(&gc.pi);
- maxdepth = get_maxdepth(&gc.pi);
-
- gc.maxtime = maxtime;
-
- /* Time markers: at most every 10 seconds, but no more than 12 markers.
- * We start out with 10 seconds and increment up to 30 minutes,
- * depending on the dive time.
- * This allows for 6h dives - enough (I hope) for even the craziest
- * divers - but just in case, for those 8h depth-record-breaking dives,
- * we double the interval if this still doesn't get us to 12 or fewer
- * time markers */
- i = 0;
- while (i < 7 && maxtime / increments[i] > 12)
- i++;
- incr = increments[i];
- while (maxtime / incr > 12)
- incr *= 2;
-
- gc.leftx = 0;
- gc.rightx = maxtime;
- gc.topy = 0;
- gc.bottomy = 1.0;
-
- last_gc = gc;
-
- QColor c = getColor(TIME_GRID);
- for (i = incr; i < maxtime; i += incr) {
- QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(i, 0), SCALEGC(i, 1));
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
- }
-
- timeMarkers = new QGraphicsRectItem();
- /* now the text on the time markers */
- struct text_render_options tro = { DEPTH_TEXT_SIZE, TIME_TEXT, CENTER, LINE_DOWN };
- if (maxtime < 600) {
- /* Be a bit more verbose with shorter dives */
- for (i = incr; i < maxtime; i += incr)
- plot_text(&tro, QPointF(i, 0), QString("%1:%2").arg(i / 60).arg(i % 60, 2, 10, QChar('0')), timeMarkers);
- } else {
- /* Only render the time on every second marker for normal dives */
- for (i = incr; i < maxtime; i += 2 * incr)
- plot_text(&tro, QPointF(i, 0), QString("%1").arg(QString::number(i / 60)), timeMarkers);
- }
- timeMarkers->setPos(0, 0);
- scene()->addItem(timeMarkers);
-
- /* Depth markers: every 30 ft or 10 m*/
- gc.leftx = 0;
- gc.rightx = 1.0;
- gc.topy = 0;
- gc.bottomy = maxdepth;
- marker = M_OR_FT(10, 30);
- maxline = qMax(gc.pi.maxdepth + marker, maxdepth * 2 / 3);
-
- c = getColor(DEPTH_GRID);
-
- for (i = marker; i < maxline; i += marker) {
- QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(0, i), SCALEGC(1, i));
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
- }
-
- gc.leftx = 0;
- gc.rightx = maxtime;
- c = getColor(MEAN_DEPTH);
-
- /* Show mean depth */
- if (!gc.printer) {
- QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(0, gc.pi.meandepth),
- SCALEGC(gc.pi.entry[gc.pi.nr - 1].sec, gc.pi.meandepth));
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
-
- struct text_render_options depth_tro = { DEPTH_TEXT_SIZE, MEAN_DEPTH, LEFT, TOP };
- QString depthLabel = get_depth_string(gc.pi.meandepth, true, true);
- plot_text(&depth_tro, QPointF(gc.leftx, gc.pi.meandepth), depthLabel, item);
- tro.hpos = RIGHT;
- plot_text(&depth_tro, QPointF(gc.pi.entry[gc.pi.nr - 1].sec, gc.pi.meandepth), depthLabel, item);
- }
-
-#if 0
- /*
- * These are good for debugging text placement etc,
- * but not for actual display..
- */
- if (0) {
- plot_smoothed_profile(gc, pi);
- plot_minmax_profile(gc, pi);
- }
-#endif
-
- /* Do the depth profile for the neat fill */
- gc.topy = 0;
- gc.bottomy = maxdepth;
-
- entry = gc.pi.entry;
-
- QPolygonF p;
- QLinearGradient pat(0.0, 0.0, 0.0, scene()->height());
- QGraphicsPolygonItem *neatFill = NULL;
-
- p.append(QPointF(SCALEGC(0, 0)));
- for (i = 0; i < gc.pi.nr; i++, entry++)
- p.append(QPointF(SCALEGC(entry->sec, entry->depth)));
-
- /* Show any ceiling we may have encountered */
- if (prefs.profile_dc_ceiling) {
- for (i = gc.pi.nr - 1; i >= 0; i--, entry--) {
- if (!entry->in_deco) {
- /* not in deco implies this is a safety stop, no ceiling */
- p.append(QPointF(SCALEGC(entry->sec, 0)));
- } else if (entry->stopdepth < entry->depth) {
- p.append(QPointF(SCALEGC(entry->sec, entry->stopdepth)));
- } else {
- p.append(QPointF(SCALEGC(entry->sec, entry->depth)));
- }
- }
- }
- pat.setColorAt(1, getColor(DEPTH_BOTTOM));
- pat.setColorAt(0, getColor(DEPTH_TOP));
-
- neatFill = new QGraphicsPolygonItem();
- neatFill->setPolygon(p);
- neatFill->setBrush(QBrush(pat));
- neatFill->setPen(QPen(QBrush(Qt::transparent), 0));
- scene()->addItem(neatFill);
-
-
- /* if the user wants the deco ceiling more visible, do that here (this
- * basically draws over the background that we had allowed to shine
- * through so far) */
- if (prefs.profile_dc_ceiling && prefs.profile_red_ceiling) {
- p.clear();
- pat.setColorAt(0, getColor(CEILING_SHALLOW));
- pat.setColorAt(1, getColor(CEILING_DEEP));
-
- entry = gc.pi.entry;
- p.append(QPointF(SCALEGC(0, 0)));
- for (i = 0; i < gc.pi.nr; i++, entry++) {
- if (entry->in_deco && entry->stopdepth) {
- if (entry->stopdepth < entry->depth) {
- p.append(QPointF(SCALEGC(entry->sec, entry->stopdepth)));
- } else {
- p.append(QPointF(SCALEGC(entry->sec, entry->depth)));
- }
- } else {
- p.append(QPointF(SCALEGC(entry->sec, 0)));
- }
- }
-
- neatFill = new QGraphicsPolygonItem();
- neatFill->setBrush(QBrush(pat));
- neatFill->setPolygon(p);
- neatFill->setPen(QPen(QBrush(Qt::NoBrush), 0));
- scene()->addItem(neatFill);
- }
-
- /* finally, plot the calculated ceiling over all this */
- if (prefs.profile_calc_ceiling) {
- pat.setColorAt(0, getColor(CALC_CEILING_SHALLOW));
- pat.setColorAt(1, getColor(CALC_CEILING_DEEP));
-
- entry = gc.pi.entry;
- p.clear();
- p.append(QPointF(SCALEGC(0, 0)));
- for (i = 0; i < gc.pi.nr; i++, entry++) {
- if (entry->ceiling)
- p.append(QPointF(SCALEGC(entry->sec, entry->ceiling)));
- else
- p.append(QPointF(SCALEGC(entry->sec, 0)));
- }
- p.append(QPointF(SCALEGC((entry - 1)->sec, 0)));
- neatFill = new QGraphicsPolygonItem();
- neatFill->setPolygon(p);
- neatFill->setPen(QPen(QBrush(Qt::NoBrush), 0));
- neatFill->setBrush(pat);
- scene()->addItem(neatFill);
- }
-
- /* plot the calculated ceiling for all tissues */
- if (prefs.profile_calc_ceiling && prefs.calc_all_tissues) {
- int k;
- for (k = 0; k < 16; k++) {
- pat.setColorAt(0, getColor(CALC_CEILING_SHALLOW));
- pat.setColorAt(1, QColor(100, 100, 100, 50));
-
- entry = gc.pi.entry;
- p.clear();
- p.append(QPointF(SCALEGC(0, 0)));
- for (i = 0; i < gc.pi.nr; i++, entry++) {
- if ((entry->ceilings)[k])
- p.append(QPointF(SCALEGC(entry->sec, (entry->ceilings)[k])));
- else
- p.append(QPointF(SCALEGC(entry->sec, 0)));
- }
- p.append(QPointF(SCALEGC((entry - 1)->sec, 0)));
- neatFill = new QGraphicsPolygonItem();
- neatFill->setPolygon(p);
- neatFill->setBrush(pat);
- scene()->addItem(neatFill);
- }
- }
-
- /* next show where we have been bad and crossed the dc's ceiling */
- if (prefs.profile_dc_ceiling) {
- pat.setColorAt(0, getColor(CEILING_SHALLOW));
- pat.setColorAt(1, getColor(CEILING_DEEP));
-
- entry = gc.pi.entry;
- p.clear();
- p.append(QPointF(SCALEGC(0, 0)));
- for (i = 0; i < gc.pi.nr; i++, entry++)
- p.append(QPointF(SCALEGC(entry->sec, entry->depth)));
-
- for (i--, entry--; i >= 0; i--, entry--) {
- if (entry->in_deco && entry->stopdepth > entry->depth) {
- p.append(QPointF(SCALEGC(entry->sec, entry->stopdepth)));
- } else {
- p.append(QPointF(SCALEGC(entry->sec, entry->depth)));
- }
- }
- }
- neatFill = new QGraphicsPolygonItem();
- neatFill->setPolygon(p);
- neatFill->setPen(QPen(QBrush(Qt::NoBrush), 0));
- neatFill->setBrush(QBrush(pat));
- scene()->addItem(neatFill);
-
- /* Now do it again for the velocity colors */
- entry = gc.pi.entry;
- for (i = 1; i < gc.pi.nr; i++) {
- entry++;
- sec = entry->sec;
- /* we want to draw the segments in different colors
- * representing the vertical velocity, so we need to
- * chop this into short segments */
- depth = entry->depth;
- QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(entry[-1].sec, entry[-1].depth), SCALEGC(sec, depth));
- QPen pen(defaultPen);
- pen.setColor(getColor((color_indice_t)(VELOCITY_COLORS_START_IDX + entry->velocity)));
- item->setPen(pen);
- scene()->addItem(item);
- }
-}
-
-QGraphicsItemGroup *ProfileGraphicsView::plot_text(text_render_options_t *tro, const QPointF &pos, const QString &text, QGraphicsItem *parent)
-{
- QFont fnt(font());
- QFontMetrics fm(fnt);
-
- if (printMode)
- fnt.setPixelSize(tro->size);
-
- QPointF point(SCALEGC(pos.x(), pos.y())); // This is neded because of the SCALE macro.
- double dx = tro->hpos * (fm.width(text));
- double dy = tro->vpos * (fm.height());
-
- QGraphicsItemGroup *group = new QGraphicsItemGroup(parent);
- QPainterPath textPath;
- /* addText() uses bottom-left text baseline and the -3 offset is probably slightly off
- * for different font sizes. */
- textPath.addText(0, fm.height() - 3, fnt, text);
- QPainterPathStroker stroker;
- stroker.setWidth(3);
- QGraphicsPathItem *strokedItem = new QGraphicsPathItem(stroker.createStroke(textPath), group);
- strokedItem->setBrush(QBrush(getColor(TEXT_BACKGROUND)));
- strokedItem->setPen(Qt::NoPen);
-
- QGraphicsPathItem *textItem = new QGraphicsPathItem(textPath, group);
- textItem->setBrush(QBrush(getColor(tro->color)));
- textItem->setPen(Qt::NoPen);
-
- group->setPos(point.x() + dx, point.y() + dy);
- if (!printMode)
- group->setFlag(QGraphicsItem::ItemIgnoresTransformations);
-
- if (!parent)
- scene()->addItem(group);
- return group;
-}
-
-void ProfileGraphicsView::resizeEvent(QResizeEvent *event)
-{
- refresh();
-}
-
-void ProfileGraphicsView::plot_temperature_profile()
-{
- int last = 0;
-
- if (!setup_temperature_limits(&gc))
- return;
-
- QPointF from;
- QPointF to;
- QColor color = getColor(TEMP_PLOT);
-
- for (int i = 0; i < gc.pi.nr; i++) {
- struct plot_data *entry = gc.pi.entry + i;
- int mkelvin = entry->temperature;
- int sec = entry->sec;
- if (!mkelvin) {
- if (!last)
- continue;
- mkelvin = last;
- }
- if (last) {
- to = QPointF(SCALEGC(sec, mkelvin));
- QGraphicsLineItem *item = new QGraphicsLineItem(from.x(), from.y(), to.x(), to.y());
- QPen pen(defaultPen);
- pen.setColor(color);
- item->setPen(pen);
- scene()->addItem(item);
- from = to;
- } else {
- from = QPointF(SCALEGC(sec, mkelvin));
- }
- last = mkelvin;
- }
-}
-
-void ProfileGraphicsView::edit_dive_time(const QString &time)
-{
- // this should set the full time of the dive.
- refresh();
-}
-
-void ProfileGraphicsView::on_rulerAction()
-{
- rulerEnabled = !rulerEnabled;
- refresh();
-}
-
-void ProfileGraphicsView::on_scaleAction()
-{
- prefs.zoomed_plot = !prefs.zoomed_plot;
- refresh();
-}
-
-QColor EventItem::getColor(const color_indice_t i)
-{
- return profile_color[i].at((isGrayscale) ? 1 : 0);
-}
-
-EventItem::EventItem(struct event *ev, QGraphicsItem *parent, bool grayscale) : QGraphicsPixmapItem(parent), ev(ev), isGrayscale(grayscale)
-{
- if (ev->name && (strcmp(ev->name, "bookmark") == 0 || strcmp(ev->name, "heading") == 0)) {
- setPixmap(QPixmap(QString(":flag")).scaled(20, 20, Qt::KeepAspectRatio, Qt::SmoothTransformation));
- } else {
- setPixmap(QPixmap(QString(":warning")).scaled(20, 20, Qt::KeepAspectRatio, Qt::SmoothTransformation));
- }
-}
-
-RulerNodeItem::RulerNodeItem(QGraphicsItem *parent, graphics_context context) : QGraphicsEllipseItem(parent), gc(context), entry(NULL), ruler(NULL)
-{
- setRect(QRect(QPoint(-8, 8), QPoint(8, -8)));
- setBrush(QColor(0xff, 0, 0, 127));
- setPen(QColor("#FF0000"));
- setFlag(QGraphicsItem::ItemIsMovable);
- setFlag(ItemSendsGeometryChanges);
- setFlag(ItemIgnoresTransformations);
-}
-
-void RulerNodeItem::setRuler(RulerItem *r)
-{
- ruler = r;
-}
-
-void RulerNodeItem::recalculate()
-{
- struct plot_info *pi = &gc.pi;
- struct plot_data *data = pi->entry + (pi->nr - 1);
- uint16_t count = 0;
- if (x() < 0) {
- setPos(0, y());
- } else if (x() > SCALEXGC(data->sec)) {
- setPos(SCALEXGC(data->sec), y());
- } else {
- data = pi->entry;
- count = 0;
- while (SCALEXGC(data->sec) < x() && count < pi->nr) {
- data = pi->entry + count;
- count++;
- }
- setPos(SCALEGC(data->sec, data->depth));
- entry = data;
- }
-}
-
-QVariant RulerNodeItem::itemChange(GraphicsItemChange change, const QVariant &value)
-{
- if (change == ItemPositionHasChanged) {
- recalculate();
- if (ruler != NULL)
- ruler->recalculate();
- if (scene()) {
- scene()->update();
- }
- }
- return QGraphicsEllipseItem::itemChange(change, value);
-}
-
-RulerItem::RulerItem(QGraphicsItem *parent, RulerNodeItem *sourceNode, RulerNodeItem *destNode) : QGraphicsObject(parent), source(sourceNode), dest(destNode)
-{
- recalculate();
-}
-
-void RulerItem::recalculate()
-{
- char buffer[500];
- QPointF tmp;
- QFont font;
- QFontMetrics fm(font);
-
- if (source == NULL || dest == NULL)
- return;
-
- prepareGeometryChange();
- startPoint = mapFromItem(source, 0, 0);
- endPoint = mapFromItem(dest, 0, 0);
- if (startPoint.x() > endPoint.x()) {
- tmp = endPoint;
- endPoint = startPoint;
- startPoint = tmp;
- }
- QLineF line(startPoint, endPoint);
-
- compare_samples(source->entry, dest->entry, buffer, 500, 1);
- text = QString(buffer);
-
- QRect r = fm.boundingRect(QRect(QPoint(10, -1 * INT_MAX), QPoint(line.length() - 10, 0)), Qt::TextWordWrap, text);
- if (r.height() < 10)
- height = 10;
- else
- height = r.height();
-
- QLineF line_n = line.normalVector();
- line_n.setLength(height);
- if (scene()) {
- /* Determine whether we draw down or upwards */
- if (scene()->sceneRect().contains(line_n.p2()) &&
- scene()->sceneRect().contains(endPoint + QPointF(line_n.dx(), line_n.dy())))
- paint_direction = -1;
- else
- paint_direction = 1;
- }
-}
-
-RulerNodeItem *RulerItem::sourceNode() const
-{
- return source;
-}
-
-RulerNodeItem *RulerItem::destNode() const
-{
- return dest;
-}
-
-void RulerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- QLineF line(startPoint, endPoint);
- QLineF line_n = line.normalVector();
- painter->setPen(QColor(Qt::black));
- painter->setBrush(Qt::NoBrush);
- line_n.setLength(height);
-
- if (paint_direction == 1)
- line_n.setAngle(line_n.angle() + 180);
- painter->drawLine(line);
- painter->drawLine(line_n);
- painter->drawLine(line_n.p1() + QPointF(line.dx(), line.dy()), line_n.p2() + QPointF(line.dx(), line.dy()));
-
- //Draw Text
- painter->save();
- painter->translate(startPoint.x(), startPoint.y());
- painter->rotate(line.angle() * -1);
- if (paint_direction == 1)
- painter->translate(0, height);
- painter->setPen(Qt::black);
- painter->drawText(QRectF(QPointF(10, -1 * height), QPointF(line.length() - 10, 0)), Qt::TextWordWrap, text);
- painter->restore();
-}
-
-QRectF RulerItem::boundingRect() const
-{
- return shape().controlPointRect();
-}
-
-QPainterPath RulerItem::shape() const
-{
- QPainterPath path;
- QLineF line(startPoint, endPoint);
- QLineF line_n = line.normalVector();
- line_n.setLength(height);
- if (paint_direction == 1)
- line_n.setAngle(line_n.angle() + 180);
- path.moveTo(startPoint);
- path.lineTo(line_n.p2());
- path.lineTo(line_n.p2() + QPointF(line.dx(), line.dy()));
- path.lineTo(endPoint);
- path.lineTo(startPoint);
- return path;
-}
-
-GraphicsTextEditor::GraphicsTextEditor(QGraphicsItem *parent) : QGraphicsTextItem(parent)
-{
-}
-
-void GraphicsTextEditor::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
-{
- // Remove the proxy filter so we can focus here.
- MainWindow::instance()->graphics()->setFocusProxy(0);
- setTextInteractionFlags(Qt::TextEditorInteraction | Qt::TextEditable);
-}
-
-void GraphicsTextEditor::keyReleaseEvent(QKeyEvent *event)
-{
- if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
- setTextInteractionFlags(Qt::NoTextInteraction);
- emit editingFinished(toPlainText());
- MainWindow::instance()->graphics()->setFocusProxy(MainWindow::instance()->dive_list());
- return;
- }
- emit textChanged(toPlainText());
- QGraphicsTextItem::keyReleaseEvent(event);
-}