diff options
Diffstat (limited to 'desktop-widgets/profile/diveeventitem.cpp')
-rw-r--r-- | desktop-widgets/profile/diveeventitem.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/desktop-widgets/profile/diveeventitem.cpp b/desktop-widgets/profile/diveeventitem.cpp new file mode 100644 index 000000000..0bbc84267 --- /dev/null +++ b/desktop-widgets/profile/diveeventitem.cpp @@ -0,0 +1,172 @@ +#include "diveeventitem.h" +#include "diveplotdatamodel.h" +#include "divecartesianaxis.h" +#include "animationfunctions.h" +#include "libdivecomputer.h" +#include "profile.h" +#include "gettextfromc.h" +#include "metrics.h" + +extern struct ev_select *ev_namelist; +extern int evn_used; + +DiveEventItem::DiveEventItem(QObject *parent) : DivePixmapItem(parent), + vAxis(NULL), + hAxis(NULL), + dataModel(NULL), + internalEvent(NULL) +{ + setFlag(ItemIgnoresTransformations); +} + + +void DiveEventItem::setHorizontalAxis(DiveCartesianAxis *axis) +{ + hAxis = axis; + recalculatePos(true); +} + +void DiveEventItem::setModel(DivePlotDataModel *model) +{ + dataModel = model; + recalculatePos(true); +} + +void DiveEventItem::setVerticalAxis(DiveCartesianAxis *axis) +{ + vAxis = axis; + recalculatePos(true); + connect(vAxis, SIGNAL(sizeChanged()), this, SLOT(recalculatePos())); +} + +struct event *DiveEventItem::getEvent() +{ + return internalEvent; +} + +void DiveEventItem::setEvent(struct event *ev) +{ + if (!ev) + return; + internalEvent = ev; + setupPixmap(); + setupToolTipString(); + recalculatePos(true); +} + +void DiveEventItem::setupPixmap() +{ + const IconMetrics& metrics = defaultIconMetrics(); + int sz_bigger = metrics.sz_med + metrics.sz_small; // ex 40px + int sz_pix = sz_bigger/2; // ex 20px + +#define EVENT_PIXMAP(PIX) QPixmap(QString(PIX)).scaled(sz_pix, sz_pix, Qt::KeepAspectRatio, Qt::SmoothTransformation) +#define EVENT_PIXMAP_BIGGER(PIX) QPixmap(QString(PIX)).scaled(sz_bigger, sz_bigger, Qt::KeepAspectRatio, Qt::SmoothTransformation) + if (same_string(internalEvent->name, "")) { + setPixmap(EVENT_PIXMAP(":warning")); + } else if (internalEvent->type == SAMPLE_EVENT_BOOKMARK) { + setPixmap(EVENT_PIXMAP(":flag")); + } else if (strcmp(internalEvent->name, "heading") == 0 || + (same_string(internalEvent->name, "SP change") && internalEvent->time.seconds == 0)) { + // 2 cases: + // a) some dive computers have heading in every sample + // b) at t=0 we might have an "SP change" to indicate dive type + // in both cases we want to get the right data into the tooltip but don't want the visual clutter + // so set an "almost invisible" pixmap (a narrow but somewhat tall, basically transparent pixmap) + // that allows tooltips to work when we don't want to show a specific + // pixmap for an event, but want to show the event value in the tooltip + QPixmap transparentPixmap(4, 20); + transparentPixmap.fill(QColor::fromRgbF(1.0, 1.0, 1.0, 0.01)); + setPixmap(transparentPixmap); + } else if (event_is_gaschange(internalEvent)) { + if (internalEvent->gas.mix.he.permille) + setPixmap(EVENT_PIXMAP_BIGGER(":gaschangeTrimix")); + else if (gasmix_is_air(&internalEvent->gas.mix)) + setPixmap(EVENT_PIXMAP_BIGGER(":gaschangeAir")); + else + setPixmap(EVENT_PIXMAP_BIGGER(":gaschangeNitrox")); + } else { + setPixmap(EVENT_PIXMAP(":warning")); + } +#undef EVENT_PIXMAP +} + +void DiveEventItem::setupToolTipString() +{ + // we display the event on screen - so translate + QString name = gettextFromC::instance()->tr(internalEvent->name); + int value = internalEvent->value; + int type = internalEvent->type; + if (value) { + if (event_is_gaschange(internalEvent)) { + name += ": "; + name += gasname(&internalEvent->gas.mix); + + /* Do we have an explicit cylinder index? Show it. */ + if (internalEvent->gas.index >= 0) + name += QString(" (cyl %1)").arg(internalEvent->gas.index+1); + } else if (type == SAMPLE_EVENT_PO2 && name == "SP change") { + name += QString(":%1").arg((double)value / 1000); + } else { + name += QString(":%1").arg(value); + } + } else if (type == SAMPLE_EVENT_PO2 && name == "SP change") { + // this is a bad idea - we are abusing an existing event type that is supposed to + // warn of high or low pO₂ and are turning it into a set point change event + name += "\n" + tr("Manual switch to OC"); + } else { + name += internalEvent->flags == SAMPLE_FLAGS_BEGIN ? tr(" begin", "Starts with space!") : + internalEvent->flags == SAMPLE_FLAGS_END ? tr(" end", "Starts with space!") : ""; + } + // qDebug() << name; + setToolTip(name); +} + +void DiveEventItem::eventVisibilityChanged(const QString &eventName, bool visible) +{ +} + +bool DiveEventItem::shouldBeHidden() +{ + struct event *event = internalEvent; + + /* + * Some gas change events are special. Some dive computers just tell us the initial gas this way. + * Don't bother showing those + */ + struct sample *first_sample = &get_dive_dc(&displayed_dive, dc_number)->sample[0]; + if (!strcmp(event->name, "gaschange") && + (event->time.seconds == 0 || + (first_sample && event->time.seconds == first_sample->time.seconds))) + return true; + + for (int i = 0; i < evn_used; i++) { + if (!strcmp(event->name, ev_namelist[i].ev_name) && ev_namelist[i].plot_ev == false) + return true; + } + return false; +} + +void DiveEventItem::recalculatePos(bool instant) +{ + if (!vAxis || !hAxis || !internalEvent || !dataModel) + return; + + QModelIndexList result = dataModel->match(dataModel->index(0, DivePlotDataModel::TIME), Qt::DisplayRole, internalEvent->time.seconds); + if (result.isEmpty()) { + Q_ASSERT("can't find a spot in the dataModel"); + hide(); + return; + } + if (!isVisible() && !shouldBeHidden()) + show(); + int depth = dataModel->data(dataModel->index(result.first().row(), DivePlotDataModel::DEPTH)).toInt(); + qreal x = hAxis->posAtValue(internalEvent->time.seconds); + qreal y = vAxis->posAtValue(depth); + if (!instant) + Animations::moveTo(this, x, y); + else + setPos(x, y); + if (isVisible() && shouldBeHidden()) + hide(); +} |