diff options
author | Tomaz Canabrava <tomaz.canabrava@intel.com> | 2015-09-03 15:56:37 -0300 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2015-10-30 10:36:49 -0700 |
commit | 1d6683f3e07d9a73af5fab702bc3a551ec7dabc9 (patch) | |
tree | 80a64ced06489bf0dca866b2097ca7048b1f0ab8 /desktop-widgets | |
parent | 50ec7200e66637abefe685e1875f3d4de2101158 (diff) | |
download | subsurface-1d6683f3e07d9a73af5fab702bc3a551ec7dabc9.tar.gz |
Move Profile widget out of desktop-widgets
The reason for that is, even if profile widget is made with qpainter
and for that reason it should be a desktop widget, it's being used
on the mobile version because of a lack of QML plotting library that
is fast and reliable.
We discovered that it was faster just to encapsulate our Profile in
a QML class and call it directly.
Signed-off-by: Tomaz Canabrava <tomaz.canabrava@intel.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'desktop-widgets')
33 files changed, 9 insertions, 5288 deletions
diff --git a/desktop-widgets/CMakeLists.txt b/desktop-widgets/CMakeLists.txt index 2c373b83f..635a8b68e 100644 --- a/desktop-widgets/CMakeLists.txt +++ b/desktop-widgets/CMakeLists.txt @@ -75,23 +75,6 @@ endif() source_group("Subsurface Interface" FILES ${SUBSURFACE_INTERFACE}) -# the profile widget -set(SUBSURFACE_PROFILE_LIB_SRCS - profile/profilewidget2.cpp - profile/diverectitem.cpp - profile/divepixmapitem.cpp - profile/divelineitem.cpp - profile/divetextitem.cpp - profile/animationfunctions.cpp - profile/divecartesianaxis.cpp - profile/diveprofileitem.cpp - profile/diveeventitem.cpp - profile/divetooltipitem.cpp - profile/ruleritem.cpp - profile/tankitem.cpp -) -source_group("Subsurface Profile" FILES ${SUBSURFACE_PROFILE_LIB_SRCS}) - # the yearly statistics widget. set(SUBSURFACE_STATISTICS_LIB_SRCS statistics/statisticswidget.cpp @@ -101,8 +84,6 @@ set(SUBSURFACE_STATISTICS_LIB_SRCS ) source_group("Subsurface Statistics" FILES ${SUBSURFACE_STATISTICS_LIB_SRCS}) -add_library(subsurface_profile STATIC ${SUBSURFACE_PROFILE_LIB_SRCS}) -target_link_libraries(subsurface_profile ${QT_LIBRARIES}) add_library(subsurface_statistics STATIC ${SUBSURFACE_STATISTICS_LIB_SRCS}) target_link_libraries(subsurface_statistics ${QT_LIBRARIES}) add_library(subsurface_generated_ui STATIC ${SUBSURFACE_UI_HDRS}) diff --git a/desktop-widgets/diveplanner.cpp b/desktop-widgets/diveplanner.cpp index b4413d11a..86f03b1d2 100644 --- a/desktop-widgets/diveplanner.cpp +++ b/desktop-widgets/diveplanner.cpp @@ -5,7 +5,7 @@ #include "helpers.h" #include "cylindermodel.h" #include "models.h" -#include "profile/profilewidget2.h" +#include "profile-widget/profilewidget2.h" #include "diveplannermodel.h" #include <QGraphicsSceneMouseEvent> @@ -328,11 +328,11 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f) modeMapper->setMapping(ui.recreational_deco, int(RECREATIONAL)); modeMapper->setMapping(ui.buehlmann_deco, int(BUEHLMANN)); modeMapper->setMapping(ui.vpmb_deco, int(VPMB)); - + connect(ui.recreational_deco, SIGNAL(clicked()), modeMapper, SLOT(map())); connect(ui.buehlmann_deco, SIGNAL(clicked()), modeMapper, SLOT(map())); connect(ui.vpmb_deco, SIGNAL(clicked()), modeMapper, SLOT(map())); - + connect(ui.lastStop, SIGNAL(toggled(bool)), plannerModel, SLOT(setLastStop6m(bool))); connect(ui.verbatim_plan, SIGNAL(toggled(bool)), plannerModel, SLOT(setVerbatim(bool))); connect(ui.display_duration, SIGNAL(toggled(bool)), plannerModel, SLOT(setDisplayDuration(bool))); diff --git a/desktop-widgets/maintab.cpp b/desktop-widgets/maintab.cpp index 0afb7b4c0..4d4cd3a5e 100644 --- a/desktop-widgets/maintab.cpp +++ b/desktop-widgets/maintab.cpp @@ -13,7 +13,7 @@ #include "diveplannermodel.h" #include "divelistview.h" #include "display.h" -#include "profile/profilewidget2.h" +#include "profile-widget/profilewidget2.h" #include "diveplanner.h" #include "divesitehelpers.h" #include "cylindermodel.h" diff --git a/desktop-widgets/mainwindow.cpp b/desktop-widgets/mainwindow.cpp index e1e0d81a2..43b433d62 100644 --- a/desktop-widgets/mainwindow.cpp +++ b/desktop-widgets/mainwindow.cpp @@ -21,7 +21,7 @@ #include "updatemanager.h" #include "planner.h" #include "filtermodels.h" -#include "profile/profilewidget2.h" +#include "profile-widget/profilewidget2.h" #include "globe.h" #include "divecomputer.h" #include "maintab.h" diff --git a/desktop-widgets/modeldelegates.cpp b/desktop-widgets/modeldelegates.cpp index 881037a83..1b1a31c0b 100644 --- a/desktop-widgets/modeldelegates.cpp +++ b/desktop-widgets/modeldelegates.cpp @@ -5,7 +5,7 @@ #include "cylindermodel.h" #include "models.h" #include "starwidget.h" -#include "profile/profilewidget2.h" +#include "profile-widget/profilewidget2.h" #include "tankinfomodel.h" #include "weigthsysteminfomodel.h" #include "weightmodel.h" diff --git a/desktop-widgets/printer.cpp b/desktop-widgets/printer.cpp index f0197d446..33ee71b55 100644 --- a/desktop-widgets/printer.cpp +++ b/desktop-widgets/printer.cpp @@ -8,6 +8,7 @@ #include <QPainter> #include <QWebElementCollection> #include <QWebElement> +#include "profile-widget/profilewidget2.h" Printer::Printer(QPaintDevice *paintDevice, print_options *printOptions, template_options *templateOptions, PrintMode printMode) { diff --git a/desktop-widgets/printer.h b/desktop-widgets/printer.h index 979cacd6a..e5f16d77d 100644 --- a/desktop-widgets/printer.h +++ b/desktop-widgets/printer.h @@ -6,7 +6,6 @@ #include <QRect> #include <QPainter> -#include "profile/profilewidget2.h" #include "printoptions.h" #include "templateedit.h" diff --git a/desktop-widgets/profile/animationfunctions.cpp b/desktop-widgets/profile/animationfunctions.cpp deleted file mode 100644 index a19d50c9d..000000000 --- a/desktop-widgets/profile/animationfunctions.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "animationfunctions.h" -#include "pref.h" -#include <QPropertyAnimation> - -namespace Animations { - - void hide(QObject *obj) - { - if (prefs.animation_speed != 0) { - QPropertyAnimation *animation = new QPropertyAnimation(obj, "opacity"); - animation->setStartValue(1); - animation->setEndValue(0); - animation->start(QAbstractAnimation::DeleteWhenStopped); - } else { - obj->setProperty("opacity", 0); - } - } - - void show(QObject *obj) - { - if (prefs.animation_speed != 0) { - QPropertyAnimation *animation = new QPropertyAnimation(obj, "opacity"); - animation->setStartValue(0); - animation->setEndValue(1); - animation->start(QAbstractAnimation::DeleteWhenStopped); - } else { - obj->setProperty("opacity", 1); - } - } - - void animDelete(QObject *obj) - { - if (prefs.animation_speed != 0) { - QPropertyAnimation *animation = new QPropertyAnimation(obj, "opacity"); - obj->connect(animation, SIGNAL(finished()), SLOT(deleteLater())); - animation->setStartValue(1); - animation->setEndValue(0); - animation->start(QAbstractAnimation::DeleteWhenStopped); - } else { - obj->setProperty("opacity", 0); - } - } - - void moveTo(QObject *obj, qreal x, qreal y) - { - if (prefs.animation_speed != 0) { - QPropertyAnimation *animation = new QPropertyAnimation(obj, "pos"); - animation->setDuration(prefs.animation_speed); - animation->setStartValue(obj->property("pos").toPointF()); - animation->setEndValue(QPointF(x, y)); - animation->start(QAbstractAnimation::DeleteWhenStopped); - } else { - obj->setProperty("pos", QPointF(x, y)); - } - } - - void scaleTo(QObject *obj, qreal scale) - { - if (prefs.animation_speed != 0) { - QPropertyAnimation *animation = new QPropertyAnimation(obj, "scale"); - animation->setDuration(prefs.animation_speed); - animation->setStartValue(obj->property("scale").toReal()); - animation->setEndValue(QVariant::fromValue(scale)); - animation->setEasingCurve(QEasingCurve::InCubic); - animation->start(QAbstractAnimation::DeleteWhenStopped); - } else { - obj->setProperty("scale", QVariant::fromValue(scale)); - } - } - - void moveTo(QObject *obj, const QPointF &pos) - { - moveTo(obj, pos.x(), pos.y()); - } -} diff --git a/desktop-widgets/profile/animationfunctions.h b/desktop-widgets/profile/animationfunctions.h deleted file mode 100644 index 3cfcff563..000000000 --- a/desktop-widgets/profile/animationfunctions.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef ANIMATIONFUNCTIONS_H -#define ANIMATIONFUNCTIONS_H - -#include <QtGlobal> -#include <QPointF> - -class QObject; - -namespace Animations { - void hide(QObject *obj); - void show(QObject *obj); - void moveTo(QObject *obj, qreal x, qreal y); - void moveTo(QObject *obj, const QPointF &pos); - void animDelete(QObject *obj); - void scaleTo(QObject *obj, qreal scale); -} - -#endif // ANIMATIONFUNCTIONS_H diff --git a/desktop-widgets/profile/divecartesianaxis.cpp b/desktop-widgets/profile/divecartesianaxis.cpp deleted file mode 100644 index bf5a5380c..000000000 --- a/desktop-widgets/profile/divecartesianaxis.cpp +++ /dev/null @@ -1,459 +0,0 @@ -#include "divecartesianaxis.h" -#include "divetextitem.h" -#include "helpers.h" -#include "preferences.h" -#include "diveplotdatamodel.h" -#include "animationfunctions.h" -#include "mainwindow.h" -#include "divelineitem.h" -#include "profilewidget2.h" - -QPen DiveCartesianAxis::gridPen() -{ - QPen pen; - pen.setColor(getColor(TIME_GRID)); - /* cosmetic width() == 0 for lines in printMode - * having setCosmetic(true) and width() > 0 does not work when - * printing on OSX and Linux */ - pen.setWidth(DiveCartesianAxis::printMode ? 0 : 2); - pen.setCosmetic(true); - return pen; -} - -double DiveCartesianAxis::tickInterval() const -{ - return interval; -} - -double DiveCartesianAxis::tickSize() const -{ - return tick_size; -} - -void DiveCartesianAxis::setFontLabelScale(qreal scale) -{ - labelScale = scale; - changed = true; -} - -void DiveCartesianAxis::setPrintMode(bool mode) -{ - printMode = mode; - // update the QPen of all lines depending on printMode - QPen newPen = gridPen(); - QColor oldColor = pen().brush().color(); - newPen.setBrush(oldColor); - setPen(newPen); - Q_FOREACH (DiveLineItem *item, lines) - item->setPen(pen()); -} - -void DiveCartesianAxis::setMaximum(double maximum) -{ - if (IS_FP_SAME(max, maximum)) - return; - max = maximum; - changed = true; - emit maxChanged(); -} - -void DiveCartesianAxis::setMinimum(double minimum) -{ - if (IS_FP_SAME(min, minimum)) - return; - min = minimum; - changed = true; -} - -void DiveCartesianAxis::setTextColor(const QColor &color) -{ - textColor = color; -} - -DiveCartesianAxis::DiveCartesianAxis() : QObject(), - QGraphicsLineItem(), - printMode(false), - unitSystem(0), - orientation(LeftToRight), - min(0), - max(0), - interval(1), - tick_size(0), - textVisibility(true), - lineVisibility(true), - labelScale(1.0), - line_size(1), - changed(true) -{ - setPen(gridPen()); -} - -DiveCartesianAxis::~DiveCartesianAxis() -{ -} - -void DiveCartesianAxis::setLineSize(qreal lineSize) -{ - line_size = lineSize; - changed = true; -} - -void DiveCartesianAxis::setOrientation(Orientation o) -{ - orientation = o; - changed = true; -} - -QColor DiveCartesianAxis::colorForValue(double value) -{ - return QColor(Qt::black); -} - -void DiveCartesianAxis::setTextVisible(bool arg1) -{ - if (textVisibility == arg1) { - return; - } - textVisibility = arg1; - Q_FOREACH (DiveTextItem *item, labels) { - item->setVisible(textVisibility); - } -} - -void DiveCartesianAxis::setLinesVisible(bool arg1) -{ - if (lineVisibility == arg1) { - return; - } - lineVisibility = arg1; - Q_FOREACH (DiveLineItem *item, lines) { - item->setVisible(lineVisibility); - } -} - -template <typename T> -void emptyList(QList<T *> &list, double steps) -{ - if (!list.isEmpty() && list.size() > steps) { - while (list.size() > steps) { - T *removedItem = list.takeLast(); - Animations::animDelete(removedItem); - } - } -} - -void DiveCartesianAxis::updateTicks(color_indice_t color) -{ - if (!scene() || (!changed && !MainWindow::instance()->graphics()->getPrintMode())) - return; - QLineF m = line(); - // unused so far: - // QGraphicsView *view = scene()->views().first(); - double steps = (max - min) / interval; - double currValueText = min; - double currValueLine = min; - - if (steps < 1) - return; - - emptyList(labels, steps); - emptyList(lines, steps); - - // Move the remaining Ticks / Text to it's corerct position - // Regartind the possibly new values for the Axis - qreal begin, stepSize; - if (orientation == TopToBottom) { - begin = m.y1(); - stepSize = (m.y2() - m.y1()); - } else if (orientation == BottomToTop) { - begin = m.y2(); - stepSize = (m.y2() - m.y1()); - } else if (orientation == LeftToRight) { - begin = m.x1(); - stepSize = (m.x2() - m.x1()); - } else /* if (orientation == RightToLeft) */ { - begin = m.x2(); - stepSize = (m.x2() - m.x1()); - } - stepSize = stepSize / steps; - - for (int i = 0, count = labels.size(); i < count; i++, currValueText += interval) { - qreal childPos = (orientation == TopToBottom || orientation == LeftToRight) ? - begin + i * stepSize : - begin - i * stepSize; - - labels[i]->setText(textForValue(currValueText)); - if (orientation == LeftToRight || orientation == RightToLeft) { - Animations::moveTo(labels[i],childPos, m.y1() + tick_size); - } else { - Animations::moveTo(labels[i],m.x1() - tick_size, childPos); - } - } - - for (int i = 0, count = lines.size(); i < count; i++, currValueLine += interval) { - qreal childPos = (orientation == TopToBottom || orientation == LeftToRight) ? - begin + i * stepSize : - begin - i * stepSize; - - if (orientation == LeftToRight || orientation == RightToLeft) { - Animations::moveTo(lines[i],childPos, m.y1()); - } else { - Animations::moveTo(lines[i],m.x1(), childPos); - } - } - - // Add's the rest of the needed Ticks / Text. - for (int i = labels.size(); i < steps; i++, currValueText += interval) { - qreal childPos; - if (orientation == TopToBottom || orientation == LeftToRight) { - childPos = begin + i * stepSize; - } else { - childPos = begin - i * stepSize; - } - DiveTextItem *label = new DiveTextItem(this); - label->setText(textForValue(currValueText)); - label->setBrush(colorForValue(currValueText)); - label->setScale(fontLabelScale()); - label->setZValue(1); - labels.push_back(label); - if (orientation == RightToLeft || orientation == LeftToRight) { - label->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); - label->setPos(scene()->sceneRect().width() + 10, m.y1() + tick_size); // position it outside of the scene); - Animations::moveTo(label,childPos, m.y1() + tick_size); - } else { - label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); - label->setPos(m.x1() - tick_size, scene()->sceneRect().height() + 10); - Animations::moveTo(label,m.x1() - tick_size, childPos); - } - } - - // Add's the rest of the needed Ticks / Text. - for (int i = lines.size(); i < steps; i++, currValueText += interval) { - qreal childPos; - if (orientation == TopToBottom || orientation == LeftToRight) { - childPos = begin + i * stepSize; - } else { - childPos = begin - i * stepSize; - } - DiveLineItem *line = new DiveLineItem(this); - QPen pen = gridPen(); - pen.setBrush(getColor(color)); - line->setPen(pen); - line->setZValue(0); - lines.push_back(line); - if (orientation == RightToLeft || orientation == LeftToRight) { - line->setLine(0, -line_size, 0, 0); - line->setPos(scene()->sceneRect().width() + 10, m.y1()); // position it outside of the scene); - Animations::moveTo(line,childPos, m.y1()); - } else { - QPointF p1 = mapFromScene(3, 0); - QPointF p2 = mapFromScene(line_size, 0); - line->setLine(p1.x(), 0, p2.x(), 0); - line->setPos(m.x1(), scene()->sceneRect().height() + 10); - Animations::moveTo(line,m.x1(), childPos); - } - } - - Q_FOREACH (DiveTextItem *item, labels) - item->setVisible(textVisibility); - Q_FOREACH (DiveLineItem *item, lines) - item->setVisible(lineVisibility); - changed = false; -} - -void DiveCartesianAxis::setLine(const QLineF &line) -{ - QGraphicsLineItem::setLine(line); - changed = true; -} - -void DiveCartesianAxis::animateChangeLine(const QLineF &newLine) -{ - setLine(newLine); - updateTicks(); - sizeChanged(); -} - -QString DiveCartesianAxis::textForValue(double value) -{ - return QString::number(value); -} - -void DiveCartesianAxis::setTickSize(qreal size) -{ - tick_size = size; -} - -void DiveCartesianAxis::setTickInterval(double i) -{ - interval = i; -} - -qreal DiveCartesianAxis::valueAt(const QPointF &p) const -{ - QLineF m = line(); - QPointF relativePosition = p; - relativePosition -= pos(); // normalize p based on the axis' offset on screen - - double retValue = (orientation == LeftToRight || orientation == RightToLeft) ? - max * (relativePosition.x() - m.x1()) / (m.x2() - m.x1()) : - max * (relativePosition.y() - m.y1()) / (m.y2() - m.y1()); - return retValue; -} - -qreal DiveCartesianAxis::posAtValue(qreal value) -{ - QLineF m = line(); - QPointF p = pos(); - - double size = max - min; - // unused for now: - // double distanceFromOrigin = value - min; - double percent = IS_FP_SAME(min, max) ? 0.0 : (value - min) / size; - - - double realSize = orientation == LeftToRight || orientation == RightToLeft ? - m.x2() - m.x1() : - m.y2() - m.y1(); - - // Inverted axis, just invert the percentage. - if (orientation == RightToLeft || orientation == BottomToTop) - percent = 1 - percent; - - double retValue = realSize * percent; - double adjusted = - orientation == LeftToRight ? retValue + m.x1() + p.x() : - orientation == RightToLeft ? retValue + m.x1() + p.x() : - orientation == TopToBottom ? retValue + m.y1() + p.y() : - /* entation == BottomToTop */ retValue + m.y1() + p.y(); - return adjusted; -} - -qreal DiveCartesianAxis::percentAt(const QPointF &p) -{ - qreal value = valueAt(p); - double size = max - min; - double percent = value / size; - return percent; -} - -double DiveCartesianAxis::maximum() const -{ - return max; -} - -double DiveCartesianAxis::minimum() const -{ - return min; -} - -double DiveCartesianAxis::fontLabelScale() const -{ - return labelScale; -} - -void DiveCartesianAxis::setColor(const QColor &color) -{ - QPen defaultPen = gridPen(); - defaultPen.setColor(color); - defaultPen.setJoinStyle(Qt::RoundJoin); - defaultPen.setCapStyle(Qt::RoundCap); - setPen(defaultPen); -} - -QString DepthAxis::textForValue(double value) -{ - if (value == 0) - return QString(); - return get_depth_string(value, false, false); -} - -QColor DepthAxis::colorForValue(double value) -{ - Q_UNUSED(value); - return QColor(Qt::red); -} - -DepthAxis::DepthAxis() -{ - connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); - changed = true; - settingsChanged(); -} - -void DepthAxis::settingsChanged() -{ - static int unitSystem = prefs.units.length; - if ( unitSystem == prefs.units.length ) - return; - changed = true; - updateTicks(); - unitSystem = prefs.units.length; -} - -QColor TimeAxis::colorForValue(double value) -{ - Q_UNUSED(value); - return QColor(Qt::blue); -} - -QString TimeAxis::textForValue(double value) -{ - int nr = value / 60; - if (maximum() < 600) - return QString("%1:%2").arg(nr).arg((int)value % 60, 2, 10, QChar('0')); - return QString::number(nr); -} - -void TimeAxis::updateTicks() -{ - DiveCartesianAxis::updateTicks(); - if (maximum() > 600) { - for (int i = 0; i < labels.count(); i++) { - labels[i]->setVisible(i % 2); - } - } -} - -QString TemperatureAxis::textForValue(double value) -{ - return QString::number(mkelvin_to_C((int)value)); -} - -PartialGasPressureAxis::PartialGasPressureAxis() : - DiveCartesianAxis(), - model(NULL) -{ - connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); -} - -void PartialGasPressureAxis::setModel(DivePlotDataModel *m) -{ - model = m; - connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(settingsChanged())); - settingsChanged(); -} - -void PartialGasPressureAxis::settingsChanged() -{ - bool showPhe = prefs.pp_graphs.phe; - bool showPn2 = prefs.pp_graphs.pn2; - bool showPo2 = prefs.pp_graphs.po2; - setVisible(showPhe || showPn2 || showPo2); - if (!model->rowCount()) - return; - - double max = showPhe ? model->pheMax() : -1; - if (showPn2 && model->pn2Max() > max) - max = model->pn2Max(); - if (showPo2 && model->po2Max() > max) - max = model->po2Max(); - - qreal pp = floor(max * 10.0) / 10.0 + 0.2; - if (IS_FP_SAME(maximum(), pp)) - return; - - setMaximum(pp); - setTickInterval(pp > 4 ? 0.5 : 0.25); - updateTicks(); -} diff --git a/desktop-widgets/profile/divecartesianaxis.h b/desktop-widgets/profile/divecartesianaxis.h deleted file mode 100644 index cc7d0bcf7..000000000 --- a/desktop-widgets/profile/divecartesianaxis.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef DIVECARTESIANAXIS_H -#define DIVECARTESIANAXIS_H - -#include <QObject> -#include <QGraphicsLineItem> -#include "subsurface-core/color.h" - -class QPropertyAnimation; -class DiveTextItem; -class DiveLineItem; -class DivePlotDataModel; - -class DiveCartesianAxis : public QObject, public QGraphicsLineItem { - Q_OBJECT - Q_PROPERTY(QLineF line WRITE setLine READ line) - Q_PROPERTY(QPointF pos WRITE setPos READ pos) - Q_PROPERTY(qreal x WRITE setX READ x) - Q_PROPERTY(qreal y WRITE setY READ y) -private: - bool printMode; - QPen gridPen(); -public: - enum Orientation { - TopToBottom, - BottomToTop, - LeftToRight, - RightToLeft - }; - DiveCartesianAxis(); - virtual ~DiveCartesianAxis(); - void setPrintMode(bool mode); - void setMinimum(double minimum); - void setMaximum(double maximum); - void setTickInterval(double interval); - void setOrientation(Orientation orientation); - void setTickSize(qreal size); - void setFontLabelScale(qreal scale); - double minimum() const; - double maximum() const; - double tickInterval() const; - double tickSize() const; - double fontLabelScale() const; - qreal valueAt(const QPointF &p) const; - qreal percentAt(const QPointF &p); - qreal posAtValue(qreal value); - void setColor(const QColor &color); - void setTextColor(const QColor &color); - void animateChangeLine(const QLineF &newLine); - void setTextVisible(bool arg1); - void setLinesVisible(bool arg1); - void setLineSize(qreal lineSize); - void setLine(const QLineF& line); - int unitSystem; -public -slots: - virtual void updateTicks(color_indice_t color = TIME_GRID); - -signals: - void sizeChanged(); - void maxChanged(); - -protected: - virtual QString textForValue(double value); - virtual QColor colorForValue(double value); - Orientation orientation; - QList<DiveTextItem *> labels; - QList<DiveLineItem *> lines; - double min; - double max; - double interval; - double tick_size; - QColor textColor; - bool textVisibility; - bool lineVisibility; - double labelScale; - qreal line_size; - bool changed; -}; - -class DepthAxis : public DiveCartesianAxis { - Q_OBJECT -public: - DepthAxis(); - -protected: - QString textForValue(double value); - QColor colorForValue(double value); -private -slots: - void settingsChanged(); -}; - -class TimeAxis : public DiveCartesianAxis { - Q_OBJECT -public: - virtual void updateTicks(); - -protected: - QString textForValue(double value); - QColor colorForValue(double value); -}; - -class TemperatureAxis : public DiveCartesianAxis { - Q_OBJECT -protected: - QString textForValue(double value); -}; - -class PartialGasPressureAxis : public DiveCartesianAxis { - Q_OBJECT -public: - PartialGasPressureAxis(); - void setModel(DivePlotDataModel *model); -public -slots: - void settingsChanged(); - -private: - DivePlotDataModel *model; -}; - -#endif // DIVECARTESIANAXIS_H diff --git a/desktop-widgets/profile/diveeventitem.cpp b/desktop-widgets/profile/diveeventitem.cpp deleted file mode 100644 index 0bbc84267..000000000 --- a/desktop-widgets/profile/diveeventitem.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#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(); -} diff --git a/desktop-widgets/profile/diveeventitem.h b/desktop-widgets/profile/diveeventitem.h deleted file mode 100644 index f358fee6d..000000000 --- a/desktop-widgets/profile/diveeventitem.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef DIVEEVENTITEM_H -#define DIVEEVENTITEM_H - -#include "divepixmapitem.h" - -class DiveCartesianAxis; -class DivePlotDataModel; -struct event; - -class DiveEventItem : public DivePixmapItem { - Q_OBJECT -public: - DiveEventItem(QObject *parent = 0); - void setEvent(struct event *ev); - struct event *getEvent(); - void eventVisibilityChanged(const QString &eventName, bool visible); - void setVerticalAxis(DiveCartesianAxis *axis); - void setHorizontalAxis(DiveCartesianAxis *axis); - void setModel(DivePlotDataModel *model); - bool shouldBeHidden(); -public -slots: - void recalculatePos(bool instant = false); - -private: - void setupToolTipString(); - void setupPixmap(); - DiveCartesianAxis *vAxis; - DiveCartesianAxis *hAxis; - DivePlotDataModel *dataModel; - struct event *internalEvent; -}; - -#endif // DIVEEVENTITEM_H diff --git a/desktop-widgets/profile/divelineitem.cpp b/desktop-widgets/profile/divelineitem.cpp deleted file mode 100644 index f9e288a44..000000000 --- a/desktop-widgets/profile/divelineitem.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "divelineitem.h" - -DiveLineItem::DiveLineItem(QGraphicsItem *parent) : QGraphicsLineItem(parent) -{ -} diff --git a/desktop-widgets/profile/divelineitem.h b/desktop-widgets/profile/divelineitem.h deleted file mode 100644 index ec88e9da5..000000000 --- a/desktop-widgets/profile/divelineitem.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DIVELINEITEM_H -#define DIVELINEITEM_H - -#include <QObject> -#include <QGraphicsLineItem> - -class DiveLineItem : public QObject, public QGraphicsLineItem { - Q_OBJECT - Q_PROPERTY(QPointF pos READ pos WRITE setPos) - Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) -public: - DiveLineItem(QGraphicsItem *parent = 0); -}; - -#endif // DIVELINEITEM_H diff --git a/desktop-widgets/profile/divepixmapitem.cpp b/desktop-widgets/profile/divepixmapitem.cpp deleted file mode 100644 index 581f6f9b4..000000000 --- a/desktop-widgets/profile/divepixmapitem.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include "divepixmapitem.h" -#include "animationfunctions.h" -#include "divepicturemodel.h" -#include <preferences.h> - -#include <QDesktopServices> -#include <QGraphicsView> -#include <QUrl> - -DivePixmapItem::DivePixmapItem(QObject *parent) : QObject(parent), QGraphicsPixmapItem() -{ -} - -DiveButtonItem::DiveButtonItem(QObject *parent): DivePixmapItem(parent) -{ -} - -void DiveButtonItem::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - QGraphicsItem::mousePressEvent(event); - emit clicked(); -} - -// If we have many many pictures on screen, maybe a shared-pixmap would be better to -// paint on screen, but for now, this. -CloseButtonItem::CloseButtonItem(QObject *parent): DiveButtonItem(parent) -{ - static QPixmap p = QPixmap(":trash"); - setPixmap(p); - setFlag(ItemIgnoresTransformations); -} - -void CloseButtonItem::hide() -{ - DiveButtonItem::hide(); -} - -void CloseButtonItem::show() -{ - DiveButtonItem::show(); -} - -DivePictureItem::DivePictureItem(QObject *parent): DivePixmapItem(parent), - canvas(new QGraphicsRectItem(this)), - shadow(new QGraphicsRectItem(this)) -{ - setFlag(ItemIgnoresTransformations); - setAcceptHoverEvents(true); - setScale(0.2); - connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); - setVisible(prefs.show_pictures_in_profile); - - canvas->setPen(Qt::NoPen); - canvas->setBrush(QColor(Qt::white)); - canvas->setFlag(ItemStacksBehindParent); - canvas->setZValue(-1); - - shadow->setPos(5,5); - shadow->setPen(Qt::NoPen); - shadow->setBrush(QColor(Qt::lightGray)); - shadow->setFlag(ItemStacksBehindParent); - shadow->setZValue(-2); -} - -void DivePictureItem::settingsChanged() -{ - setVisible(prefs.show_pictures_in_profile); -} - -void DivePictureItem::setPixmap(const QPixmap &pix) -{ - DivePixmapItem::setPixmap(pix); - QRectF r = boundingRect(); - canvas->setRect(0 - 10, 0 -10, r.width() + 20, r.height() + 20); - shadow->setRect(canvas->rect()); -} - -CloseButtonItem *button = NULL; -void DivePictureItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) -{ - Animations::scaleTo(this, 1.0); - setZValue(5); - - if(!button) { - button = new CloseButtonItem(); - button->setScale(0.2); - button->setZValue(7); - scene()->addItem(button); - } - button->setParentItem(this); - button->setPos(boundingRect().width() - button->boundingRect().width() * 0.2, - boundingRect().height() - button->boundingRect().height() * 0.2); - button->setOpacity(0); - button->show(); - Animations::show(button); - button->disconnect(); - connect(button, SIGNAL(clicked()), this, SLOT(removePicture())); -} - -void DivePictureItem::setFileUrl(const QString &s) -{ - fileUrl = s; -} - -void DivePictureItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) -{ - Animations::scaleTo(this, 0.2); - setZValue(0); - if(button){ - button->setParentItem(NULL); - Animations::hide(button); - } -} - -DivePictureItem::~DivePictureItem(){ - if(button){ - button->setParentItem(NULL); - Animations::hide(button); - } -} - -void DivePictureItem::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - QDesktopServices::openUrl(QUrl::fromLocalFile(fileUrl)); -} - -void DivePictureItem::removePicture() -{ - DivePictureModel::instance()->removePicture(fileUrl); -} diff --git a/desktop-widgets/profile/divepixmapitem.h b/desktop-widgets/profile/divepixmapitem.h deleted file mode 100644 index 02c1523f7..000000000 --- a/desktop-widgets/profile/divepixmapitem.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef DIVEPIXMAPITEM_H -#define DIVEPIXMAPITEM_H - -#include <QObject> -#include <QGraphicsPixmapItem> - -class DivePixmapItem : public QObject, public QGraphicsPixmapItem { - Q_OBJECT - Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity) - Q_PROPERTY(QPointF pos WRITE setPos READ pos) - Q_PROPERTY(qreal x WRITE setX READ x) - Q_PROPERTY(qreal y WRITE setY READ y) -public: - DivePixmapItem(QObject *parent = 0); -}; - -class DivePictureItem : public DivePixmapItem { - Q_OBJECT - Q_PROPERTY(qreal scale WRITE setScale READ scale) -public: - DivePictureItem(QObject *parent = 0); - virtual ~DivePictureItem(); - void setPixmap(const QPixmap& pix); -public slots: - void settingsChanged(); - void removePicture(); - void setFileUrl(const QString& s); -protected: - void hoverEnterEvent(QGraphicsSceneHoverEvent *event); - void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - void mousePressEvent(QGraphicsSceneMouseEvent *event); -private: - QString fileUrl; - QGraphicsRectItem *canvas; - QGraphicsRectItem *shadow; -}; - -class DiveButtonItem : public DivePixmapItem { - Q_OBJECT -public: - DiveButtonItem(QObject *parent = 0); -protected: - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); -signals: - void clicked(); -}; - -class CloseButtonItem : public DiveButtonItem { - Q_OBJECT -public: - CloseButtonItem(QObject *parent = 0); -public slots: - void hide(); - void show(); -}; - -#endif // DIVEPIXMAPITEM_H diff --git a/desktop-widgets/profile/diveprofileitem.cpp b/desktop-widgets/profile/diveprofileitem.cpp deleted file mode 100644 index 2c814678a..000000000 --- a/desktop-widgets/profile/diveprofileitem.cpp +++ /dev/null @@ -1,979 +0,0 @@ -#include "diveprofileitem.h" -#include "diveplotdatamodel.h" -#include "divecartesianaxis.h" -#include "divetextitem.h" -#include "animationfunctions.h" -#include "dive.h" -#include "profile.h" -#include "preferences.h" -#include "diveplannermodel.h" -#include "helpers.h" -#include "libdivecomputer/parser.h" -#include "mainwindow.h" -#include "maintab.h" -#include "profile/profilewidget2.h" -#include "diveplanner.h" - -#include <QSettings> - -AbstractProfilePolygonItem::AbstractProfilePolygonItem() : QObject(), QGraphicsPolygonItem(), hAxis(NULL), vAxis(NULL), dataModel(NULL), hDataColumn(-1), vDataColumn(-1) -{ - setCacheMode(DeviceCoordinateCache); - connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); -} - -void AbstractProfilePolygonItem::settingsChanged() -{ -} - -void AbstractProfilePolygonItem::setHorizontalAxis(DiveCartesianAxis *horizontal) -{ - hAxis = horizontal; - connect(hAxis, SIGNAL(sizeChanged()), this, SLOT(modelDataChanged())); - modelDataChanged(); -} - -void AbstractProfilePolygonItem::setHorizontalDataColumn(int column) -{ - hDataColumn = column; - modelDataChanged(); -} - -void AbstractProfilePolygonItem::setModel(DivePlotDataModel *model) -{ - dataModel = model; - connect(dataModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(modelDataChanged(QModelIndex, QModelIndex))); - connect(dataModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex, int, int))); - modelDataChanged(); -} - -void AbstractProfilePolygonItem::modelDataRemoved(const QModelIndex &parent, int from, int to) -{ - setPolygon(QPolygonF()); - qDeleteAll(texts); - texts.clear(); -} - -void AbstractProfilePolygonItem::setVerticalAxis(DiveCartesianAxis *vertical) -{ - vAxis = vertical; - connect(vAxis, SIGNAL(sizeChanged()), this, SLOT(modelDataChanged())); - connect(vAxis, SIGNAL(maxChanged()), this, SLOT(modelDataChanged())); - modelDataChanged(); -} - -void AbstractProfilePolygonItem::setVerticalDataColumn(int column) -{ - vDataColumn = column; - modelDataChanged(); -} - -bool AbstractProfilePolygonItem::shouldCalculateStuff(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - if (!hAxis || !vAxis) - return false; - if (!dataModel || dataModel->rowCount() == 0) - return false; - if (hDataColumn == -1 || vDataColumn == -1) - return false; - if (topLeft.isValid() && bottomRight.isValid()) { - if ((topLeft.column() >= vDataColumn || topLeft.column() >= hDataColumn) && - (bottomRight.column() <= vDataColumn || topLeft.column() <= hDataColumn)) { - return true; - } - } - return true; -} - -void AbstractProfilePolygonItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - // We don't have enougth data to calculate things, quit. - - // Calculate the polygon. This is the polygon that will be painted on screen - // on the ::paint method. Here we calculate the correct position of the points - // regarting our cartesian plane ( made by the hAxis and vAxis ), the QPolygonF - // is an array of QPointF's, so we basically get the point from the model, convert - // to our coordinates, store. no painting is done here. - QPolygonF poly; - for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++) { - qreal horizontalValue = dataModel->index(i, hDataColumn).data().toReal(); - qreal verticalValue = dataModel->index(i, vDataColumn).data().toReal(); - QPointF point(hAxis->posAtValue(horizontalValue), vAxis->posAtValue(verticalValue)); - poly.append(point); - } - setPolygon(poly); - - qDeleteAll(texts); - texts.clear(); -} - -DiveProfileItem::DiveProfileItem() : show_reported_ceiling(0), reported_ceiling_in_red(0) -{ -} - -void DiveProfileItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_UNUSED(widget); - if (polygon().isEmpty()) - return; - - painter->save(); - // This paints the Polygon + Background. I'm setting the pen to QPen() so we don't get a black line here, - // after all we need to plot the correct velocities colors later. - setPen(Qt::NoPen); - QGraphicsPolygonItem::paint(painter, option, widget); - - // Here we actually paint the boundaries of the Polygon using the colors that the model provides. - // Those are the speed colors of the dives. - QPen pen; - pen.setCosmetic(true); - pen.setWidth(2); - QPolygonF poly = polygon(); - // This paints the colors of the velocities. - for (int i = 1, count = dataModel->rowCount(); i < count; i++) { - QModelIndex colorIndex = dataModel->index(i, DivePlotDataModel::COLOR); - pen.setBrush(QBrush(colorIndex.data(Qt::BackgroundRole).value<QColor>())); - painter->setPen(pen); - painter->drawLine(poly[i - 1], poly[i]); - } - painter->restore(); -} - -int DiveProfileItem::maxCeiling(int row) -{ - int max = -1; - plot_data *entry = dataModel->data().entry + row; - for (int tissue = 0; tissue < 16; tissue++) { - if (max < entry->ceilings[tissue]) - max = entry->ceilings[tissue]; - } - return max; -} - -void DiveProfileItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - bool eventAdded = false; - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - - AbstractProfilePolygonItem::modelDataChanged(topLeft, bottomRight); - if (polygon().isEmpty()) - return; - - show_reported_ceiling = prefs.dcceiling; - reported_ceiling_in_red = prefs.redceiling; - profileColor = getColor(DEPTH_BOTTOM); - - int currState = qobject_cast<ProfileWidget2 *>(scene()->views().first())->currentState; - if (currState == ProfileWidget2::PLAN) { - plot_data *entry = dataModel->data().entry; - for (int i = 0; i < dataModel->rowCount(); i++, entry++) { - int max = maxCeiling(i); - // Don't scream if we violate the ceiling by a few cm - if (entry->depth < max - 100 && entry->sec > 0) { - profileColor = QColor(Qt::red); - if (!eventAdded) { - add_event(&displayed_dive.dc, entry->sec, SAMPLE_EVENT_CEILING, -1, max / 1000, "planned waypoint above ceiling"); - eventAdded = true; - } - } - } - } - - /* Show any ceiling we may have encountered */ - if (prefs.dcceiling && !prefs.redceiling) { - QPolygonF p = polygon(); - plot_data *entry = dataModel->data().entry + dataModel->rowCount() - 1; - for (int i = dataModel->rowCount() - 1; i >= 0; i--, entry--) { - if (!entry->in_deco) { - /* not in deco implies this is a safety stop, no ceiling */ - p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(0))); - } else { - p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(qMin(entry->stopdepth, entry->depth)))); - } - } - setPolygon(p); - } - - // This is the blueish gradient that the Depth Profile should have. - // It's a simple QLinearGradient with 2 stops, starting from top to bottom. - QLinearGradient pat(0, polygon().boundingRect().top(), 0, polygon().boundingRect().bottom()); - pat.setColorAt(1, profileColor); - pat.setColorAt(0, getColor(DEPTH_TOP)); - setBrush(QBrush(pat)); - - int last = -1; - for (int i = 0, count = dataModel->rowCount(); i < count; i++) { - - struct plot_data *entry = dataModel->data().entry + i; - if (entry->depth < 2000) - continue; - - if ((entry == entry->max[2]) && entry->depth / 100 != last) { - plot_depth_sample(entry, Qt::AlignHCenter | Qt::AlignBottom, getColor(SAMPLE_DEEP)); - last = entry->depth / 100; - } - - if ((entry == entry->min[2]) && entry->depth / 100 != last) { - plot_depth_sample(entry, Qt::AlignHCenter | Qt::AlignTop, getColor(SAMPLE_SHALLOW)); - last = entry->depth / 100; - } - - if (entry->depth != last) - last = -1; - } -} - -void DiveProfileItem::settingsChanged() -{ - //TODO: Only modelDataChanged() here if we need to rebuild the graph ( for instance, - // if the prefs.dcceiling are enabled, but prefs.redceiling is disabled - // and only if it changed something. let's not waste cpu cycles repoloting something we don't need to. - modelDataChanged(); -} - -void DiveProfileItem::plot_depth_sample(struct plot_data *entry, QFlags<Qt::AlignmentFlag> flags, const QColor &color) -{ - int decimals; - double d = get_depth_units(entry->depth, &decimals, NULL); - DiveTextItem *item = new DiveTextItem(this); - item->setPos(hAxis->posAtValue(entry->sec), vAxis->posAtValue(entry->depth)); - item->setText(QString("%1").arg(d, 0, 'f', 1)); - item->setAlignment(flags); - item->setBrush(color); - texts.append(item); -} - -DiveHeartrateItem::DiveHeartrateItem() -{ - QPen pen; - pen.setBrush(QBrush(getColor(::HR_PLOT))); - pen.setCosmetic(true); - pen.setWidth(1); - setPen(pen); - settingsChanged(); -} - -void DiveHeartrateItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - int last = -300, last_printed_hr = 0, sec = 0; - struct { - int sec; - int hr; - } hist[3] = {}; - - // We don't have enougth data to calculate things, quit. - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - - qDeleteAll(texts); - texts.clear(); - // Ignore empty values. a heartrate of 0 would be a bad sign. - QPolygonF poly; - for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++) { - int hr = dataModel->index(i, vDataColumn).data().toInt(); - if (!hr) - continue; - sec = dataModel->index(i, hDataColumn).data().toInt(); - QPointF point(hAxis->posAtValue(sec), vAxis->posAtValue(hr)); - poly.append(point); - if (hr == hist[2].hr) - // same as last one, no point in looking at printing - continue; - hist[0] = hist[1]; - hist[1] = hist[2]; - hist[2].sec = sec; - hist[2].hr = hr; - // don't print a HR - // if it's not a local min / max - // if it's been less than 5min and less than a 20 beats change OR - // if it's been less than 2min OR if the change from the - // last print is less than 10 beats - // to test min / max requires three points, so we now look at the - // previous one - sec = hist[1].sec; - hr = hist[1].hr; - if ((hist[0].hr < hr && hr < hist[2].hr) || - (hist[0].hr > hr && hr > hist[2].hr) || - ((sec < last + 300) && (abs(hr - last_printed_hr) < 20)) || - (sec < last + 120) || - (abs(hr - last_printed_hr) < 10)) - continue; - last = sec; - createTextItem(sec, hr); - last_printed_hr = hr; - } - setPolygon(poly); - - if (texts.count()) - texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom); -} - -void DiveHeartrateItem::createTextItem(int sec, int hr) -{ - DiveTextItem *text = new DiveTextItem(this); - text->setAlignment(Qt::AlignRight | Qt::AlignBottom); - text->setBrush(getColor(HR_TEXT)); - text->setPos(QPointF(hAxis->posAtValue(sec), vAxis->posAtValue(hr))); - text->setScale(0.7); // need to call this BEFORE setText() - text->setText(QString("%1").arg(hr)); - texts.append(text); -} - -void DiveHeartrateItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (polygon().isEmpty()) - return; - painter->save(); - painter->setPen(pen()); - painter->drawPolyline(polygon()); - painter->restore(); -} - -void DiveHeartrateItem::settingsChanged() -{ - setVisible(prefs.hrgraph); -} - -DivePercentageItem::DivePercentageItem(int i) -{ - QPen pen; - QColor color; - color.setHsl(100 + 10 * i, 200, 100); - pen.setBrush(QBrush(color)); - pen.setCosmetic(true); - pen.setWidth(1); - setPen(pen); - settingsChanged(); -} - -void DivePercentageItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - int sec = 0; - - // We don't have enougth data to calculate things, quit. - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - - // Ignore empty values. a heartrate of 0 would be a bad sign. - QPolygonF poly; - for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++) { - int hr = dataModel->index(i, vDataColumn).data().toInt(); - if (!hr) - continue; - sec = dataModel->index(i, hDataColumn).data().toInt(); - QPointF point(hAxis->posAtValue(sec), vAxis->posAtValue(hr)); - poly.append(point); - } - setPolygon(poly); - - if (texts.count()) - texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom); -} - -void DivePercentageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (polygon().isEmpty()) - return; - painter->save(); - painter->setPen(pen()); - painter->drawPolyline(polygon()); - painter->restore(); -} - -void DivePercentageItem::settingsChanged() -{ - setVisible(prefs.percentagegraph); -} - -DiveAmbPressureItem::DiveAmbPressureItem() -{ - QPen pen; - pen.setBrush(QBrush(getColor(::AMB_PRESSURE_LINE))); - pen.setCosmetic(true); - pen.setWidth(2); - setPen(pen); - settingsChanged(); -} - -void DiveAmbPressureItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - int sec = 0; - - // We don't have enougth data to calculate things, quit. - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - - // Ignore empty values. a heartrate of 0 would be a bad sign. - QPolygonF poly; - for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++) { - int hr = dataModel->index(i, vDataColumn).data().toInt(); - if (!hr) - continue; - sec = dataModel->index(i, hDataColumn).data().toInt(); - QPointF point(hAxis->posAtValue(sec), vAxis->posAtValue(hr)); - poly.append(point); - } - setPolygon(poly); - - if (texts.count()) - texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom); -} - -void DiveAmbPressureItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (polygon().isEmpty()) - return; - painter->save(); - painter->setPen(pen()); - painter->drawPolyline(polygon()); - painter->restore(); -} - -void DiveAmbPressureItem::settingsChanged() -{ - setVisible(prefs.percentagegraph); -} - -DiveGFLineItem::DiveGFLineItem() -{ - QPen pen; - pen.setBrush(QBrush(getColor(::GF_LINE))); - pen.setCosmetic(true); - pen.setWidth(2); - setPen(pen); - settingsChanged(); -} - -void DiveGFLineItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - int sec = 0; - - // We don't have enougth data to calculate things, quit. - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - - // Ignore empty values. a heartrate of 0 would be a bad sign. - QPolygonF poly; - for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++) { - int hr = dataModel->index(i, vDataColumn).data().toInt(); - if (!hr) - continue; - sec = dataModel->index(i, hDataColumn).data().toInt(); - QPointF point(hAxis->posAtValue(sec), vAxis->posAtValue(hr)); - poly.append(point); - } - setPolygon(poly); - - if (texts.count()) - texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom); -} - -void DiveGFLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (polygon().isEmpty()) - return; - painter->save(); - painter->setPen(pen()); - painter->drawPolyline(polygon()); - painter->restore(); -} - -void DiveGFLineItem::settingsChanged() -{ - setVisible(prefs.percentagegraph); -} - -DiveTemperatureItem::DiveTemperatureItem() -{ - QPen pen; - pen.setBrush(QBrush(getColor(::TEMP_PLOT))); - pen.setCosmetic(true); - pen.setWidth(2); - setPen(pen); -} - -void DiveTemperatureItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - int last = -300, last_printed_temp = 0, sec = 0, last_valid_temp = 0; - // We don't have enougth data to calculate things, quit. - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - - qDeleteAll(texts); - texts.clear(); - // Ignore empty values. things do not look good with '0' as temperature in kelvin... - QPolygonF poly; - for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++) { - int mkelvin = dataModel->index(i, vDataColumn).data().toInt(); - if (!mkelvin) - continue; - last_valid_temp = mkelvin; - sec = dataModel->index(i, hDataColumn).data().toInt(); - QPointF point(hAxis->posAtValue(sec), vAxis->posAtValue(mkelvin)); - poly.append(point); - - /* 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) - createTextItem(sec, mkelvin); - last_printed_temp = mkelvin; - } - setPolygon(poly); - - /* 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_valid_temp > 200000 && - ((abs(last_valid_temp - last_printed_temp) > 500) || ((double)last / (double)sec < 0.75))) { - createTextItem(sec, last_valid_temp); - } - if (texts.count()) - texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom); -} - -void DiveTemperatureItem::createTextItem(int sec, int mkelvin) -{ - double deg; - const char *unit; - deg = get_temp_units(mkelvin, &unit); - - DiveTextItem *text = new DiveTextItem(this); - text->setAlignment(Qt::AlignRight | Qt::AlignBottom); - text->setBrush(getColor(TEMP_TEXT)); - text->setPos(QPointF(hAxis->posAtValue(sec), vAxis->posAtValue(mkelvin))); - text->setScale(0.8); // need to call this BEFORE setText() - text->setText(QString("%1%2").arg(deg, 0, 'f', 1).arg(unit)); - texts.append(text); -} - -void DiveTemperatureItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (polygon().isEmpty()) - return; - painter->save(); - painter->setPen(pen()); - painter->drawPolyline(polygon()); - painter->restore(); -} - -DiveMeanDepthItem::DiveMeanDepthItem() -{ - QPen pen; - pen.setBrush(QBrush(getColor(::HR_AXIS))); - pen.setCosmetic(true); - pen.setWidth(2); - setPen(pen); - settingsChanged(); -} - -void DiveMeanDepthItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - double meandepthvalue = 0.0; - // We don't have enougth data to calculate things, quit. - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - - QPolygonF poly; - plot_data *entry = dataModel->data().entry; - for (int i = 0, modelDataCount = dataModel->rowCount(); i < modelDataCount; i++, entry++) { - // Ignore empty values - if (entry->running_sum == 0 || entry->sec == 0) - continue; - - meandepthvalue = entry->running_sum / entry->sec; - QPointF point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(meandepthvalue)); - poly.append(point); - } - lastRunningSum = meandepthvalue; - setPolygon(poly); - createTextItem(); -} - - -void DiveMeanDepthItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (polygon().isEmpty()) - return; - painter->save(); - painter->setPen(pen()); - painter->drawPolyline(polygon()); - painter->restore(); -} - -void DiveMeanDepthItem::settingsChanged() -{ - setVisible(prefs.show_average_depth); -} - -void DiveMeanDepthItem::createTextItem() { - plot_data *entry = dataModel->data().entry; - int sec = entry[dataModel->rowCount()-1].sec; - qDeleteAll(texts); - texts.clear(); - int decimals; - const char *unitText; - double d = get_depth_units(lastRunningSum, &decimals, &unitText); - DiveTextItem *text = new DiveTextItem(this); - text->setAlignment(Qt::AlignRight | Qt::AlignTop); - text->setBrush(getColor(TEMP_TEXT)); - text->setPos(QPointF(hAxis->posAtValue(sec) + 1, vAxis->posAtValue(lastRunningSum))); - text->setScale(0.8); // need to call this BEFORE setText() - text->setText(QString("%1%2").arg(d, 0, 'f', 1).arg(unitText)); - texts.append(text); -} - -void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - // We don't have enougth data to calculate things, quit. - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - int last_index = -1; - int o2mbar; - QPolygonF boundingPoly, o2Poly; // This is the "Whole Item", but a pressure can be divided in N Polygons. - polygons.clear(); - if (displayed_dive.dc.divemode == CCR) - polygons.append(o2Poly); - - for (int i = 0, count = dataModel->rowCount(); i < count; i++) { - o2mbar = 0; - plot_data *entry = dataModel->data().entry + i; - int mbar = GET_PRESSURE(entry); - if (displayed_dive.dc.divemode == CCR) - o2mbar = GET_O2CYLINDER_PRESSURE(entry); - - if (entry->cylinderindex != last_index) { - polygons.append(QPolygonF()); // this is the polygon that will be actually drawn on screen. - last_index = entry->cylinderindex; - } - if (!mbar) { - continue; - } - if (o2mbar) { - QPointF o2point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(o2mbar)); - boundingPoly.push_back(o2point); - polygons.first().push_back(o2point); - } - - QPointF point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(mbar)); - boundingPoly.push_back(point); // The BoundingRect - polygons.last().push_back(point); // The polygon thta will be plotted. - } - setPolygon(boundingPoly); - qDeleteAll(texts); - texts.clear(); - 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; - - cyl = -1; - o2mbar = 0; - - double print_y_offset[8][2] = { { 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 } ,{ 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 } }; - // CCR dives: These are offset values used to print the gas lables and pressures on a CCR dive profile at - // appropriate Y-coordinates: One doublet of values for each of 8 cylinders. - // Order of offsets within a doublet: gas lable offset; gas pressure offset. - // The array is initialised with default values that apply to non-CCR dives. - - bool offsets_initialised = false; - int o2cyl = -1, dilcyl = -1; - QFlags<Qt::AlignmentFlag> alignVar= Qt::AlignTop, align_dil = Qt::AlignBottom, align_o2 = Qt::AlignTop; - double axisRange = (vAxis->maximum() - vAxis->minimum())/1000; // Convert axis pressure range to bar - double axisLog = log10(log10(axisRange)); - for (int i = 0, count = dataModel->rowCount(); i < count; i++) { - entry = dataModel->data().entry + i; - mbar = GET_PRESSURE(entry); - if (displayed_dive.dc.divemode == CCR && displayed_dive.oxygen_cylinder_index >= 0) - o2mbar = GET_O2CYLINDER_PRESSURE(entry); - - if (o2mbar) { // If there is an o2mbar value then this is a CCR dive. Then do: - // The first time an o2 value is detected, see if the oxygen cyl pressure graph starts above or below the dil graph - if (!offsets_initialised) { // Initialise the parameters for placing the text correctly near the graph line: - o2cyl = displayed_dive.oxygen_cylinder_index; - dilcyl = displayed_dive.diluent_cylinder_index; - if ((o2mbar > mbar)) { // If above, write o2 start cyl pressure above graph and diluent pressure below graph: - print_y_offset[o2cyl][0] = -7 * axisLog; // y offset for oxygen gas lable (above); pressure offsets=-0.5, already initialised - print_y_offset[dilcyl][0] = 5 * axisLog; // y offset for diluent gas lable (below) - } else { // ... else write o2 start cyl pressure below graph: - print_y_offset[o2cyl][0] = 5 * axisLog; // o2 lable & pressure below graph; pressure offsets=-0.5, already initialised - print_y_offset[dilcyl][0] = -7.8 * axisLog; // and diluent lable above graph. - align_dil = Qt::AlignTop; - align_o2 = Qt::AlignBottom; - } - offsets_initialised = true; - } - - if (!seen_cyl[displayed_dive.oxygen_cylinder_index]) { //For o2, on the left of profile, write lable and pressure - plotPressureValue(o2mbar, entry->sec, align_o2, print_y_offset[o2cyl][1]); - plotGasValue(o2mbar, entry->sec, displayed_dive.cylinder[displayed_dive.oxygen_cylinder_index].gasmix, align_o2, print_y_offset[o2cyl][0]); - seen_cyl[displayed_dive.oxygen_cylinder_index] = true; - } - last_pressure[displayed_dive.oxygen_cylinder_index] = o2mbar; - last_time[displayed_dive.oxygen_cylinder_index] = entry->sec; - alignVar = align_dil; - } - - if (!mbar) - continue; - - if (cyl != entry->cylinderindex) { // Pressure value near the left hand edge of the profile - other cylinders: - cyl = entry->cylinderindex; // For each other cylinder, write the gas lable and pressure - if (!seen_cyl[cyl]) { - plotPressureValue(mbar, entry->sec, alignVar, print_y_offset[cyl][1]); - plotGasValue(mbar, entry->sec, displayed_dive.cylinder[cyl].gasmix, align_dil, print_y_offset[cyl][0]); - seen_cyl[cyl] = true; - } - } - last_pressure[cyl] = mbar; - last_time[cyl] = entry->sec; - } - - for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { // For each cylinder, on right hand side of profile, write cylinder pressure - alignVar = ((o2cyl >= 0) && (cyl == displayed_dive.oxygen_cylinder_index)) ? align_o2 : align_dil; - if (last_time[cyl]) { - plotPressureValue(last_pressure[cyl], last_time[cyl], (alignVar | Qt::AlignLeft), print_y_offset[cyl][1]); - } - } -} - -void DiveGasPressureItem::plotPressureValue(int mbar, int sec, QFlags<Qt::AlignmentFlag> align, double pressure_offset) -{ - const char *unit; - int pressure = get_pressure_units(mbar, &unit); - DiveTextItem *text = new DiveTextItem(this); - text->setPos(hAxis->posAtValue(sec), vAxis->posAtValue(mbar) + pressure_offset ); - text->setText(QString("%1 %2").arg(pressure).arg(unit)); - text->setAlignment(align); - text->setBrush(getColor(PRESSURE_TEXT)); - texts.push_back(text); -} - -void DiveGasPressureItem::plotGasValue(int mbar, int sec, struct gasmix gasmix, QFlags<Qt::AlignmentFlag> align, double gasname_offset) -{ - QString gas = get_gas_string(gasmix); - DiveTextItem *text = new DiveTextItem(this); - text->setPos(hAxis->posAtValue(sec), vAxis->posAtValue(mbar) + gasname_offset ); - text->setText(gas); - text->setAlignment(align); - text->setBrush(getColor(PRESSURE_TEXT)); - texts.push_back(text); -} - -void DiveGasPressureItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (polygon().isEmpty()) - return; - QPen pen; - pen.setCosmetic(true); - pen.setWidth(2); - painter->save(); - struct plot_data *entry; - Q_FOREACH (const QPolygonF &poly, polygons) { - entry = dataModel->data().entry; - for (int i = 1, count = poly.count(); i < count; i++, entry++) { - if (entry->sac) - pen.setBrush(getSacColor(entry->sac, displayed_dive.sac)); - else - pen.setBrush(MED_GRAY_HIGH_TRANS); - painter->setPen(pen); - painter->drawLine(poly[i - 1], poly[i]); - } - } - painter->restore(); -} - -DiveCalculatedCeiling::DiveCalculatedCeiling() : is3mIncrement(false) -{ - settingsChanged(); -} - -void DiveCalculatedCeiling::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - if (MainWindow::instance()->information()) - connect(MainWindow::instance()->information(), SIGNAL(dateTimeChanged()), this, SLOT(recalc()), Qt::UniqueConnection); - - // We don't have enougth data to calculate things, quit. - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - AbstractProfilePolygonItem::modelDataChanged(topLeft, bottomRight); - // Add 2 points to close the polygon. - QPolygonF poly = polygon(); - if (poly.isEmpty()) - return; - QPointF p1 = poly.first(); - QPointF p2 = poly.last(); - - poly.prepend(QPointF(p1.x(), vAxis->posAtValue(0))); - poly.append(QPointF(p2.x(), vAxis->posAtValue(0))); - setPolygon(poly); - - QLinearGradient pat(0, polygon().boundingRect().top(), 0, polygon().boundingRect().bottom()); - pat.setColorAt(0, getColor(CALC_CEILING_SHALLOW)); - pat.setColorAt(1, getColor(CALC_CEILING_DEEP)); - setPen(QPen(QBrush(Qt::NoBrush), 0)); - setBrush(pat); -} - -void DiveCalculatedCeiling::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (polygon().isEmpty()) - return; - QGraphicsPolygonItem::paint(painter, option, widget); -} - -DiveCalculatedTissue::DiveCalculatedTissue() -{ - settingsChanged(); -} - -void DiveCalculatedTissue::settingsChanged() -{ - setVisible(prefs.calcalltissues && prefs.calcceiling); -} - -void DiveReportedCeiling::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - - QPolygonF p; - p.append(QPointF(hAxis->posAtValue(0), vAxis->posAtValue(0))); - plot_data *entry = dataModel->data().entry; - for (int i = 0, count = dataModel->rowCount(); i < count; i++, entry++) { - if (entry->in_deco && entry->stopdepth) { - p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(qMin(entry->stopdepth, entry->depth)))); - } else { - p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(0))); - } - } - setPolygon(p); - QLinearGradient pat(0, p.boundingRect().top(), 0, p.boundingRect().bottom()); - // does the user want the ceiling in "surface color" or in red? - if (prefs.redceiling) { - pat.setColorAt(0, getColor(CEILING_SHALLOW)); - pat.setColorAt(1, getColor(CEILING_DEEP)); - } else { - pat.setColorAt(0, getColor(BACKGROUND_TRANS)); - pat.setColorAt(1, getColor(BACKGROUND_TRANS)); - } - setPen(QPen(QBrush(Qt::NoBrush), 0)); - setBrush(pat); -} - -void DiveCalculatedCeiling::recalc() -{ - dataModel->calculateDecompression(); -} - -void DiveCalculatedCeiling::settingsChanged() -{ - if (dataModel && is3mIncrement != prefs.calcceiling3m) { - // recalculate that part. - recalc(); - } - is3mIncrement = prefs.calcceiling3m; - setVisible(prefs.calcceiling); -} - -void DiveReportedCeiling::settingsChanged() -{ - setVisible(prefs.dcceiling); -} - -void DiveReportedCeiling::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (polygon().isEmpty()) - return; - QGraphicsPolygonItem::paint(painter, option, widget); -} - -void PartialPressureGasItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - //AbstractProfilePolygonItem::modelDataChanged(); - if (!shouldCalculateStuff(topLeft, bottomRight)) - return; - - plot_data *entry = dataModel->data().entry; - QPolygonF poly; - QPolygonF alertpoly; - alertPolygons.clear(); - QSettings s; - s.beginGroup("TecDetails"); - double threshold = 0.0; - if (thresholdPtr) - threshold = *thresholdPtr; - bool inAlertFragment = false; - for (int i = 0; i < dataModel->rowCount(); i++, entry++) { - double value = dataModel->index(i, vDataColumn).data().toDouble(); - int time = dataModel->index(i, hDataColumn).data().toInt(); - QPointF point(hAxis->posAtValue(time), vAxis->posAtValue(value)); - poly.push_back(point); - if (value >= threshold) { - if (inAlertFragment) { - alertPolygons.back().push_back(point); - } else { - alertpoly.clear(); - alertpoly.push_back(point); - alertPolygons.append(alertpoly); - inAlertFragment = true; - } - } else { - inAlertFragment = false; - } - } - setPolygon(poly); - /* - createPPLegend(trUtf8("pN" UTF8_SUBSCRIPT_2),getColor(PN2), legendPos); - */ -} - -void PartialPressureGasItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - const qreal pWidth = 0.0; - painter->save(); - painter->setPen(QPen(normalColor, pWidth)); - painter->drawPolyline(polygon()); - - QPolygonF poly; - painter->setPen(QPen(alertColor, pWidth)); - Q_FOREACH (const QPolygonF &poly, alertPolygons) - painter->drawPolyline(poly); - painter->restore(); -} - -void PartialPressureGasItem::setThreshouldSettingsKey(double *prefPointer) -{ - thresholdPtr = prefPointer; -} - -PartialPressureGasItem::PartialPressureGasItem() : - thresholdPtr(NULL) -{ -} - -void PartialPressureGasItem::settingsChanged() -{ - QSettings s; - s.beginGroup("TecDetails"); - setVisible(s.value(visibilityKey).toBool()); -} - -void PartialPressureGasItem::setVisibilitySettingsKey(const QString &key) -{ - visibilityKey = key; -} - -void PartialPressureGasItem::setColors(const QColor &normal, const QColor &alert) -{ - normalColor = normal; - alertColor = alert; -} diff --git a/desktop-widgets/profile/diveprofileitem.h b/desktop-widgets/profile/diveprofileitem.h deleted file mode 100644 index 0bba7f7a3..000000000 --- a/desktop-widgets/profile/diveprofileitem.h +++ /dev/null @@ -1,225 +0,0 @@ -#ifndef DIVEPROFILEITEM_H -#define DIVEPROFILEITEM_H - -#include <QObject> -#include <QGraphicsPolygonItem> -#include <QModelIndex> - -#include "divelineitem.h" - -/* This is the Profile Item, it should be used for quite a lot of things - on the profile view. The usage should be pretty simple: - - DiveProfileItem *profile = new DiveProfileItem(); - profile->setVerticalAxis( profileYAxis ); - profile->setHorizontalAxis( timeAxis ); - profile->setModel( DiveDataModel ); - profile->setHorizontalDataColumn( DiveDataModel::TIME ); - profile->setVerticalDataColumn( DiveDataModel::DEPTH ); - scene()->addItem(profile); - - This is a generically item and should be used as a base for others, I think... -*/ - -class DivePlotDataModel; -class DiveTextItem; -class DiveCartesianAxis; -class QAbstractTableModel; -struct plot_data; - -class AbstractProfilePolygonItem : public QObject, public QGraphicsPolygonItem { - Q_OBJECT - Q_PROPERTY(QPointF pos WRITE setPos READ pos) - Q_PROPERTY(qreal x WRITE setX READ x) - Q_PROPERTY(qreal y WRITE setY READ y) -public: - AbstractProfilePolygonItem(); - void setVerticalAxis(DiveCartesianAxis *vertical); - void setHorizontalAxis(DiveCartesianAxis *horizontal); - void setModel(DivePlotDataModel *model); - void setHorizontalDataColumn(int column); - void setVerticalDataColumn(int column); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) = 0; - virtual void clear() - { - } -public -slots: - virtual void settingsChanged(); - virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - virtual void modelDataRemoved(const QModelIndex &parent, int from, int to); - -protected: - /* when the model emits a 'datachanged' signal, this method below should be used to check if the - * modified data affects this particular item ( for example, when setting the '3m increment' - * the data for Ceiling and tissues will be changed, and only those. so, the topLeft will be the CEILING - * column and the bottomRight will have the TISSUE_16 column. this method takes the vDataColumn and hDataColumn - * into consideration when returning 'true' for "yes, continue the calculation', and 'false' for - * 'do not recalculate, we already have the right data. - */ - bool shouldCalculateStuff(const QModelIndex &topLeft, const QModelIndex &bottomRight); - - DiveCartesianAxis *hAxis; - DiveCartesianAxis *vAxis; - DivePlotDataModel *dataModel; - int hDataColumn; - int vDataColumn; - QList<DiveTextItem *> texts; -}; - -class DiveProfileItem : public AbstractProfilePolygonItem { - Q_OBJECT - -public: - DiveProfileItem(); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - virtual void settingsChanged(); - void plot_depth_sample(struct plot_data *entry, QFlags<Qt::AlignmentFlag> flags, const QColor &color); - int maxCeiling(int row); - -private: - unsigned int show_reported_ceiling; - unsigned int reported_ceiling_in_red; - QColor profileColor; -}; - -class DiveMeanDepthItem : public AbstractProfilePolygonItem { - Q_OBJECT -public: - DiveMeanDepthItem(); - virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual void settingsChanged(); - -private: - void createTextItem(); - double lastRunningSum; - QString visibilityKey; -}; - -class DiveTemperatureItem : public AbstractProfilePolygonItem { - Q_OBJECT -public: - DiveTemperatureItem(); - virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - -private: - void createTextItem(int seconds, int mkelvin); -}; - -class DiveHeartrateItem : public AbstractProfilePolygonItem { - Q_OBJECT -public: - DiveHeartrateItem(); - virtual void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - virtual void settingsChanged(); - -private: - void createTextItem(int seconds, int hr); - QString visibilityKey; -}; - -class DivePercentageItem : public AbstractProfilePolygonItem { - Q_OBJECT -public: - DivePercentageItem(int i); - virtual void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - virtual void settingsChanged(); - -private: - QString visibilityKey; -}; - -class DiveAmbPressureItem : public AbstractProfilePolygonItem { - Q_OBJECT -public: - DiveAmbPressureItem(); - virtual void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - virtual void settingsChanged(); - -private: - QString visibilityKey; -}; - -class DiveGFLineItem : public AbstractProfilePolygonItem { - Q_OBJECT -public: - DiveGFLineItem(); - virtual void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - virtual void settingsChanged(); - -private: - QString visibilityKey; -}; - -class DiveGasPressureItem : public AbstractProfilePolygonItem { - Q_OBJECT - -public: - virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - -private: - void plotPressureValue(int mbar, int sec, QFlags<Qt::AlignmentFlag> align, double offset); - void plotGasValue(int mbar, int sec, struct gasmix gasmix, QFlags<Qt::AlignmentFlag> align, double offset); - QVector<QPolygonF> polygons; -}; - -class DiveCalculatedCeiling : public AbstractProfilePolygonItem { - Q_OBJECT - -public: - DiveCalculatedCeiling(); - virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual void settingsChanged(); - -public -slots: - void recalc(); - -private: - bool is3mIncrement; -}; - -class DiveReportedCeiling : public AbstractProfilePolygonItem { - Q_OBJECT - -public: - virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual void settingsChanged(); -}; - -class DiveCalculatedTissue : public DiveCalculatedCeiling { - Q_OBJECT -public: - DiveCalculatedTissue(); - virtual void settingsChanged(); -}; - -class PartialPressureGasItem : public AbstractProfilePolygonItem { - Q_OBJECT -public: - PartialPressureGasItem(); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - virtual void settingsChanged(); - void setThreshouldSettingsKey(double *prefPointer); - void setVisibilitySettingsKey(const QString &setVisibilitySettingsKey); - void setColors(const QColor &normalColor, const QColor &alertColor); - -private: - QVector<QPolygonF> alertPolygons; - double *thresholdPtr; - QString visibilityKey; - QColor normalColor; - QColor alertColor; -}; -#endif // DIVEPROFILEITEM_H diff --git a/desktop-widgets/profile/diverectitem.cpp b/desktop-widgets/profile/diverectitem.cpp deleted file mode 100644 index 8cb60c3f5..000000000 --- a/desktop-widgets/profile/diverectitem.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "diverectitem.h" - -DiveRectItem::DiveRectItem(QObject *parent, QGraphicsItem *parentItem) : QObject(parent), QGraphicsRectItem(parentItem) -{ -} diff --git a/desktop-widgets/profile/diverectitem.h b/desktop-widgets/profile/diverectitem.h deleted file mode 100644 index e616cf591..000000000 --- a/desktop-widgets/profile/diverectitem.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef DIVERECTITEM_H -#define DIVERECTITEM_H - -#include <QObject> -#include <QGraphicsRectItem> - -class DiveRectItem : public QObject, public QGraphicsRectItem { - Q_OBJECT - Q_PROPERTY(QRectF rect WRITE setRect READ rect) - Q_PROPERTY(QPointF pos WRITE setPos READ pos) - Q_PROPERTY(qreal x WRITE setX READ x) - Q_PROPERTY(qreal y WRITE setY READ y) -public: - DiveRectItem(QObject *parent = 0, QGraphicsItem *parentItem = 0); -}; - -#endif // DIVERECTITEM_H diff --git a/desktop-widgets/profile/divetextitem.cpp b/desktop-widgets/profile/divetextitem.cpp deleted file mode 100644 index 3bf00d68f..000000000 --- a/desktop-widgets/profile/divetextitem.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "divetextitem.h" -#include "mainwindow.h" -#include "profilewidget2.h" -#include "subsurface-core/color.h" - -#include <QBrush> - -DiveTextItem::DiveTextItem(QGraphicsItem *parent) : QGraphicsItemGroup(parent), - internalAlignFlags(Qt::AlignHCenter | Qt::AlignVCenter), - textBackgroundItem(new QGraphicsPathItem(this)), - textItem(new QGraphicsPathItem(this)), - printScale(1.0), - scale(1.0), - connected(false) -{ - setFlag(ItemIgnoresTransformations); - textBackgroundItem->setBrush(QBrush(getColor(TEXT_BACKGROUND))); - textBackgroundItem->setPen(Qt::NoPen); - textItem->setPen(Qt::NoPen); -} - -void DiveTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - updateText(); - QGraphicsItemGroup::paint(painter, option, widget); -} - -void DiveTextItem::fontPrintScaleUpdate(double scale) -{ - printScale = scale; -} - -void DiveTextItem::setAlignment(int alignFlags) -{ - if (alignFlags != internalAlignFlags) { - internalAlignFlags = alignFlags; - } -} - -void DiveTextItem::setBrush(const QBrush &b) -{ - textItem->setBrush(b); -} - -void DiveTextItem::setScale(double newscale) -{ - if (scale != newscale) { - scale = newscale; - } -} - -void DiveTextItem::setText(const QString &t) -{ - if (internalText != t) { - if (!connected) { - if (scene()) { - // by now we should be on a scene. grab the profile widget from it and setup our printScale - // and connect to the signal that makes sure we keep track if that changes - ProfileWidget2 *profile = qobject_cast<ProfileWidget2 *>(scene()->views().first()); - connect(profile, SIGNAL(fontPrintScaleChanged(double)), this, SLOT(fontPrintScaleUpdate(double)), Qt::UniqueConnection); - fontPrintScaleUpdate(profile->getFontPrintScale()); - connected = true; - } else { - qDebug() << "called before scene was set up" << t; - } - } - internalText = t; - updateText(); - } -} - -const QString &DiveTextItem::text() -{ - return internalText; -} - -void DiveTextItem::updateText() -{ - double size; - if (internalText.isEmpty()) { - return; - } - - QFont fnt(qApp->font()); - if ((size = fnt.pixelSize()) > 0) { - // set in pixels - so the scale factor may not make a difference if it's too close to 1 - size *= scale * printScale; - fnt.setPixelSize(size); - } else { - size = fnt.pointSizeF(); - size *= scale * printScale; - fnt.setPointSizeF(size); - } - QFontMetrics fm(fnt); - - QPainterPath textPath; - qreal xPos = 0, yPos = 0; - - QRectF rect = fm.boundingRect(internalText); - yPos = (internalAlignFlags & Qt::AlignTop) ? 0 : - (internalAlignFlags & Qt::AlignBottom) ? +rect.height() : - /*(internalAlignFlags & Qt::AlignVCenter ? */ +rect.height() / 4; - - xPos = (internalAlignFlags & Qt::AlignLeft) ? -rect.width() : - (internalAlignFlags & Qt::AlignHCenter) ? -rect.width() / 2 : - /* (internalAlignFlags & Qt::AlignRight) */ 0; - - textPath.addText(xPos, yPos, fnt, internalText); - QPainterPathStroker stroker; - stroker.setWidth(3); - textBackgroundItem->setPath(stroker.createStroke(textPath)); - textItem->setPath(textPath); -} diff --git a/desktop-widgets/profile/divetextitem.h b/desktop-widgets/profile/divetextitem.h deleted file mode 100644 index be0adf292..000000000 --- a/desktop-widgets/profile/divetextitem.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef DIVETEXTITEM_H -#define DIVETEXTITEM_H - -#include <QObject> -#include <QGraphicsItemGroup> - -class QBrush; - -/* A Line Item that has animated-properties. */ -class DiveTextItem : public QObject, public QGraphicsItemGroup { - Q_OBJECT - Q_PROPERTY(QPointF pos READ pos WRITE setPos) - Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) -public: - DiveTextItem(QGraphicsItem *parent = 0); - void setText(const QString &text); - void setAlignment(int alignFlags); - void setScale(double newscale); - void setBrush(const QBrush &brush); - const QString &text(); - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - -private -slots: - void fontPrintScaleUpdate(double scale); - -private: - void updateText(); - int internalAlignFlags; - QGraphicsPathItem *textBackgroundItem; - QGraphicsPathItem *textItem; - QString internalText; - double printScale; - double scale; - bool connected; -}; - -#endif // DIVETEXTITEM_H diff --git a/desktop-widgets/profile/divetooltipitem.cpp b/desktop-widgets/profile/divetooltipitem.cpp deleted file mode 100644 index d4818422b..000000000 --- a/desktop-widgets/profile/divetooltipitem.cpp +++ /dev/null @@ -1,285 +0,0 @@ -#include "divetooltipitem.h" -#include "divecartesianaxis.h" -#include "dive.h" -#include "profile.h" -#include "membuffer.h" -#include "metrics.h" -#include <QPropertyAnimation> -#include <QSettings> -#include <QGraphicsView> -#include <QStyleOptionGraphicsItem> - -#define PORT_IN_PROGRESS 1 -#ifdef PORT_IN_PROGRESS -#include "display.h" -#endif - -void ToolTipItem::addToolTip(const QString &toolTip, const QIcon &icon, const QPixmap& pixmap) -{ - const IconMetrics& iconMetrics = defaultIconMetrics(); - - QGraphicsPixmapItem *iconItem = 0; - double yValue = title->boundingRect().height() + iconMetrics.spacing; - Q_FOREACH (ToolTip t, toolTips) { - yValue += t.second->boundingRect().height(); - } - if (entryToolTip.second) { - yValue += entryToolTip.second->boundingRect().height(); - } - iconItem = new QGraphicsPixmapItem(this); - if (!icon.isNull()) { - iconItem->setPixmap(icon.pixmap(iconMetrics.sz_small, iconMetrics.sz_small)); - } else if (!pixmap.isNull()) { - iconItem->setPixmap(pixmap); - } - iconItem->setPos(iconMetrics.spacing, yValue); - - QGraphicsSimpleTextItem *textItem = new QGraphicsSimpleTextItem(toolTip, this); - textItem->setPos(iconMetrics.spacing + iconMetrics.sz_small + iconMetrics.spacing, yValue); - textItem->setBrush(QBrush(Qt::white)); - textItem->setFlag(ItemIgnoresTransformations); - toolTips.push_back(qMakePair(iconItem, textItem)); -} - -void ToolTipItem::clear() -{ - Q_FOREACH (ToolTip t, toolTips) { - delete t.first; - delete t.second; - } - toolTips.clear(); -} - -void ToolTipItem::setRect(const QRectF &r) -{ - if( r == rect() ) { - return; - } - - QGraphicsRectItem::setRect(r); - updateTitlePosition(); -} - -void ToolTipItem::collapse() -{ - int dim = defaultIconMetrics().sz_small; - - if (prefs.animation_speed) { - QPropertyAnimation *animation = new QPropertyAnimation(this, "rect"); - animation->setDuration(100); - animation->setStartValue(nextRectangle); - animation->setEndValue(QRect(0, 0, dim, dim)); - animation->start(QAbstractAnimation::DeleteWhenStopped); - } else { - setRect(nextRectangle); - } - clear(); - - status = COLLAPSED; -} - -void ToolTipItem::expand() -{ - if (!title) - return; - - const IconMetrics& iconMetrics = defaultIconMetrics(); - - double width = 0, height = title->boundingRect().height() + iconMetrics.spacing; - Q_FOREACH (const ToolTip& t, toolTips) { - QRectF sRect = t.second->boundingRect(); - if (sRect.width() > width) - width = sRect.width(); - height += sRect.height(); - } - - if (entryToolTip.first) { - QRectF sRect = entryToolTip.second->boundingRect(); - if (sRect.width() > width) - width = sRect.width(); - height += sRect.height(); - } - - /* Left padding, Icon Size, space, right padding */ - width += iconMetrics.spacing + iconMetrics.sz_small + iconMetrics.spacing + iconMetrics.spacing; - - if (width < title->boundingRect().width() + iconMetrics.spacing * 2) - width = title->boundingRect().width() + iconMetrics.spacing * 2; - - if (height < iconMetrics.sz_small) - height = iconMetrics.sz_small; - - nextRectangle.setWidth(width); - nextRectangle.setHeight(height); - - if (nextRectangle != rect()) { - if (prefs.animation_speed) { - QPropertyAnimation *animation = new QPropertyAnimation(this, "rect", this); - animation->setDuration(prefs.animation_speed); - animation->setStartValue(rect()); - animation->setEndValue(nextRectangle); - animation->start(QAbstractAnimation::DeleteWhenStopped); - } else { - setRect(nextRectangle); - } - } - - status = EXPANDED; -} - -ToolTipItem::ToolTipItem(QGraphicsItem *parent) : QGraphicsRectItem(parent), - title(new QGraphicsSimpleTextItem(tr("Information"), this)), - status(COLLAPSED), - timeAxis(0), - lastTime(-1) -{ - memset(&pInfo, 0, sizeof(pInfo)); - entryToolTip.first = NULL; - entryToolTip.second = NULL; - setFlags(ItemIgnoresTransformations | ItemIsMovable | ItemClipsChildrenToShape); - - QColor c = QColor(Qt::black); - c.setAlpha(155); - setBrush(c); - - setZValue(99); - - addToolTip(QString(), QIcon(), QPixmap(16,60)); - entryToolTip = toolTips.first(); - toolTips.clear(); - - title->setFlag(ItemIgnoresTransformations); - title->setPen(QPen(Qt::white, 1)); - title->setBrush(Qt::white); - - setPen(QPen(Qt::white, 2)); - refreshTime.start(); -} - -ToolTipItem::~ToolTipItem() -{ - clear(); -} - -void ToolTipItem::updateTitlePosition() -{ - const IconMetrics& iconMetrics = defaultIconMetrics(); - if (rect().width() < title->boundingRect().width() + iconMetrics.spacing * 4) { - QRectF newRect = rect(); - newRect.setWidth(title->boundingRect().width() + iconMetrics.spacing * 4); - newRect.setHeight((newRect.height() && isExpanded()) ? newRect.height() : iconMetrics.sz_small); - setRect(newRect); - } - - title->setPos(rect().width() / 2 - title->boundingRect().width() / 2 - 1, 0); -} - -bool ToolTipItem::isExpanded() const -{ - return status == EXPANDED; -} - -void ToolTipItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - persistPos(); - QGraphicsRectItem::mouseReleaseEvent(event); - Q_FOREACH (QGraphicsItem *item, oldSelection) { - item->setSelected(true); - } -} - -void ToolTipItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_UNUSED(widget); - painter->save(); - painter->setClipRect(option->rect); - painter->setPen(pen()); - painter->setBrush(brush()); - painter->drawRoundedRect(rect(), 10, 10, Qt::AbsoluteSize); - painter->restore(); -} - -void ToolTipItem::persistPos() -{ - QSettings s; - s.beginGroup("ProfileMap"); - s.setValue("tooltip_position", pos()); - s.endGroup(); -} - -void ToolTipItem::readPos() -{ - QSettings s; - s.beginGroup("ProfileMap"); - QPointF value = s.value("tooltip_position").toPoint(); - if (!scene()->sceneRect().contains(value)) { - value = QPointF(0, 0); - } - setPos(value); -} - -void ToolTipItem::setPlotInfo(const plot_info &plot) -{ - pInfo = plot; -} - -void ToolTipItem::setTimeAxis(DiveCartesianAxis *axis) -{ - timeAxis = axis; -} - -void ToolTipItem::refresh(const QPointF &pos) -{ - struct plot_data *entry; - static QPixmap tissues(16,60); - static QPainter painter(&tissues); - static struct membuffer mb = { 0 }; - - if(refreshTime.elapsed() < 40) - return; - refreshTime.start(); - - int time = timeAxis->valueAt(pos); - if (time == lastTime) - return; - - lastTime = time; - clear(); - - mb.len = 0; - entry = get_plot_details_new(&pInfo, time, &mb); - if (entry) { - tissues.fill(); - painter.setPen(QColor(0, 0, 0, 0)); - painter.setBrush(QColor(LIMENADE1)); - painter.drawRect(0, 10 + (100 - AMB_PERCENTAGE) / 2, 16, AMB_PERCENTAGE / 2); - painter.setBrush(QColor(SPRINGWOOD1)); - painter.drawRect(0, 10, 16, (100 - AMB_PERCENTAGE) / 2); - painter.setBrush(QColor(Qt::red)); - painter.drawRect(0,0,16,10); - painter.setPen(QColor(0, 0, 0, 255)); - painter.drawLine(0, 60 - entry->gfline / 2, 16, 60 - entry->gfline / 2); - painter.drawLine(0, 60 - AMB_PERCENTAGE * (entry->pressures.n2 + entry->pressures.he) / entry->ambpressure / 2, - 16, 60 - AMB_PERCENTAGE * (entry->pressures.n2 + entry->pressures.he) / entry->ambpressure /2); - painter.setPen(QColor(0, 0, 0, 127)); - for (int i=0; i<16; i++) { - painter.drawLine(i, 60, i, 60 - entry->percentages[i] / 2); - } - entryToolTip.first->setPixmap(tissues); - entryToolTip.second->setText(QString::fromUtf8(mb.buffer, mb.len)); - } - - Q_FOREACH (QGraphicsItem *item, scene()->items(pos, Qt::IntersectsItemBoundingRect - ,Qt::DescendingOrder, scene()->views().first()->transform())) { - if (!item->toolTip().isEmpty()) - addToolTip(item->toolTip()); - } - expand(); -} - -void ToolTipItem::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - oldSelection = scene()->selectedItems(); - scene()->clearSelection(); - QGraphicsItem::mousePressEvent(event); -} diff --git a/desktop-widgets/profile/divetooltipitem.h b/desktop-widgets/profile/divetooltipitem.h deleted file mode 100644 index 4fa7ec2d7..000000000 --- a/desktop-widgets/profile/divetooltipitem.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef DIVETOOLTIPITEM_H -#define DIVETOOLTIPITEM_H - -#include <QGraphicsRectItem> -#include <QVector> -#include <QPair> -#include <QRectF> -#include <QIcon> -#include <QTime> -#include "display.h" - -class DiveCartesianAxis; -class QGraphicsLineItem; -class QGraphicsSimpleTextItem; -class QGraphicsPixmapItem; -struct graphics_context; - -/* To use a tooltip, simply ->setToolTip on the QGraphicsItem that you want - * or, if it's a "global" tooltip, set it on the mouseMoveEvent of the ProfileGraphicsView. - */ -class ToolTipItem : public QObject, public QGraphicsRectItem { - Q_OBJECT - void updateTitlePosition(); - Q_PROPERTY(QRectF rect READ rect WRITE setRect) - -public: - enum Status { - COLLAPSED, - EXPANDED - }; - - explicit ToolTipItem(QGraphicsItem *parent = 0); - virtual ~ToolTipItem(); - - void collapse(); - void expand(); - void clear(); - void addToolTip(const QString &toolTip, const QIcon &icon = QIcon(), const QPixmap &pixmap = QPixmap()); - void refresh(const QPointF &pos); - bool isExpanded() const; - void persistPos(); - void readPos(); - void mousePressEvent(QGraphicsSceneMouseEvent *event); - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - void setTimeAxis(DiveCartesianAxis *axis); - void setPlotInfo(const plot_info &plot); - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); -public -slots: - void setRect(const QRectF &rect); - -private: - typedef QPair<QGraphicsPixmapItem *, QGraphicsSimpleTextItem *> ToolTip; - QVector<ToolTip> toolTips; - ToolTip entryToolTip; - QGraphicsSimpleTextItem *title; - Status status; - QRectF rectangle; - QRectF nextRectangle; - DiveCartesianAxis *timeAxis; - plot_info pInfo; - int lastTime; - QTime refreshTime; - QList<QGraphicsItem*> oldSelection; -}; - -#endif // DIVETOOLTIPITEM_H diff --git a/desktop-widgets/profile/profilewidget2.cpp b/desktop-widgets/profile/profilewidget2.cpp deleted file mode 100644 index 3ccd1bb6d..000000000 --- a/desktop-widgets/profile/profilewidget2.cpp +++ /dev/null @@ -1,1836 +0,0 @@ -#include "profilewidget2.h" -#include "diveplotdatamodel.h" -#include "helpers.h" -#include "profile.h" -#include "diveeventitem.h" -#include "divetextitem.h" -#include "divetooltipitem.h" -#include "planner.h" -#include "device.h" -#include "ruleritem.h" -#include "tankitem.h" -#include "pref.h" -#include "divepicturewidget.h" -#include "diveplannermodel.h" -#include "models.h" -#include "divepicturemodel.h" -#include "maintab.h" -#include "diveplanner.h" - -#include <libdivecomputer/parser.h> -#include <QScrollBar> -#include <QtCore/qmath.h> -#include <QMessageBox> -#include <QInputDialog> -#include <QDebug> -#include <QWheelEvent> - -#ifndef QT_NO_DEBUG -#include <QTableView> -#endif -#include "mainwindow.h" -#include <preferences.h> - -/* This is the global 'Item position' variable. - * it should tell you where to position things up - * on the canvas. - * - * please, please, please, use this instead of - * hard coding the item on the scene with a random - * value. - */ -static struct _ItemPos { - struct _Pos { - QPointF on; - QPointF off; - }; - struct _Axis { - _Pos pos; - QLineF shrinked; - QLineF expanded; - QLineF intermediate; - }; - _Pos background; - _Pos dcLabel; - _Pos tankBar; - _Axis depth; - _Axis partialPressure; - _Axis partialPressureTissue; - _Axis partialPressureWithTankBar; - _Axis percentage; - _Axis percentageWithTankBar; - _Axis time; - _Axis cylinder; - _Axis temperature; - _Axis temperatureAll; - _Axis heartBeat; - _Axis heartBeatWithTankBar; -} itemPos; - -ProfileWidget2::ProfileWidget2(QWidget *parent) : QGraphicsView(parent), - currentState(INVALID), - dataModel(new DivePlotDataModel(this)), - zoomLevel(0), - zoomFactor(1.15), - background(new DivePixmapItem()), - backgroundFile(":poster"), - toolTipItem(new ToolTipItem()), - isPlotZoomed(prefs.zoomed_plot),// no! bad use of prefs. 'PreferencesDialog::loadSettings' NOT CALLED yet. - profileYAxis(new DepthAxis()), - gasYAxis(new PartialGasPressureAxis()), - temperatureAxis(new TemperatureAxis()), - timeAxis(new TimeAxis()), - diveProfileItem(new DiveProfileItem()), - temperatureItem(new DiveTemperatureItem()), - meanDepthItem(new DiveMeanDepthItem()), - cylinderPressureAxis(new DiveCartesianAxis()), - gasPressureItem(new DiveGasPressureItem()), - diveComputerText(new DiveTextItem()), - diveCeiling(new DiveCalculatedCeiling()), - gradientFactor(new DiveTextItem()), - reportedCeiling(new DiveReportedCeiling()), - pn2GasItem(new PartialPressureGasItem()), - pheGasItem(new PartialPressureGasItem()), - po2GasItem(new PartialPressureGasItem()), - o2SetpointGasItem(new PartialPressureGasItem()), - ccrsensor1GasItem(new PartialPressureGasItem()), - ccrsensor2GasItem(new PartialPressureGasItem()), - ccrsensor3GasItem(new PartialPressureGasItem()), - heartBeatAxis(new DiveCartesianAxis()), - heartBeatItem(new DiveHeartrateItem()), - percentageAxis(new DiveCartesianAxis()), - ambPressureItem(new DiveAmbPressureItem()), - gflineItem(new DiveGFLineItem()), - mouseFollowerVertical(new DiveLineItem()), - mouseFollowerHorizontal(new DiveLineItem()), - rulerItem(new RulerItem2()), - tankItem(new TankItem()), - isGrayscale(false), - printMode(false), - shouldCalculateMaxTime(true), - shouldCalculateMaxDepth(true), - fontPrintScale(1.0) -{ - // would like to be able to ASSERT here that PreferencesDialog::loadSettings has been called. - isPlotZoomed = prefs.zoomed_plot; // now it seems that 'prefs' has loaded our preferences - - memset(&plotInfo, 0, sizeof(plotInfo)); - - setupSceneAndFlags(); - setupItemSizes(); - setupItemOnScene(); - addItemsToScene(); - scene()->installEventFilter(this); - connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); - QAction *action = NULL; -#define ADD_ACTION(SHORTCUT, Slot) \ - action = new QAction(this); \ - action->setShortcut(SHORTCUT); \ - action->setShortcutContext(Qt::WindowShortcut); \ - addAction(action); \ - connect(action, SIGNAL(triggered(bool)), this, SLOT(Slot)); \ - actionsForKeys[SHORTCUT] = action; - - ADD_ACTION(Qt::Key_Escape, keyEscAction()); - ADD_ACTION(Qt::Key_Delete, keyDeleteAction()); - ADD_ACTION(Qt::Key_Up, keyUpAction()); - ADD_ACTION(Qt::Key_Down, keyDownAction()); - ADD_ACTION(Qt::Key_Left, keyLeftAction()); - ADD_ACTION(Qt::Key_Right, keyRightAction()); -#undef ADD_ACTION - -#if !defined(QT_NO_DEBUG) && defined(SHOW_PLOT_INFO_TABLE) - QTableView *diveDepthTableView = new QTableView(); - diveDepthTableView->setModel(dataModel); - diveDepthTableView->show(); -#endif -} - - -ProfileWidget2::~ProfileWidget2() -{ - delete background; - delete toolTipItem; - delete profileYAxis; - delete gasYAxis; - delete temperatureAxis; - delete timeAxis; - delete diveProfileItem; - delete temperatureItem; - delete meanDepthItem; - delete cylinderPressureAxis; - delete gasPressureItem; - delete diveComputerText; - delete diveCeiling; - delete reportedCeiling; - delete pn2GasItem; - delete pheGasItem; - delete po2GasItem; - delete o2SetpointGasItem; - delete ccrsensor1GasItem; - delete ccrsensor2GasItem; - delete ccrsensor3GasItem; - delete heartBeatAxis; - delete heartBeatItem; - delete percentageAxis; - delete ambPressureItem; - delete gflineItem; - delete mouseFollowerVertical; - delete mouseFollowerHorizontal; - delete rulerItem; - delete tankItem; -} - -#define SUBSURFACE_OBJ_DATA 1 -#define SUBSURFACE_OBJ_DC_TEXT 0x42 - -void ProfileWidget2::addItemsToScene() -{ - scene()->addItem(background); - scene()->addItem(toolTipItem); - scene()->addItem(profileYAxis); - scene()->addItem(gasYAxis); - scene()->addItem(temperatureAxis); - scene()->addItem(timeAxis); - scene()->addItem(diveProfileItem); - scene()->addItem(cylinderPressureAxis); - scene()->addItem(temperatureItem); - scene()->addItem(meanDepthItem); - scene()->addItem(gasPressureItem); - // I cannot seem to figure out if an object that I find with itemAt() on the scene - // is the object I am looking for - my guess is there's a simple way in Qt to do that - // but nothing I tried worked. - // so instead this adds a special magic key/value pair to the object to mark it - diveComputerText->setData(SUBSURFACE_OBJ_DATA, SUBSURFACE_OBJ_DC_TEXT); - scene()->addItem(diveComputerText); - scene()->addItem(diveCeiling); - scene()->addItem(gradientFactor); - scene()->addItem(reportedCeiling); - scene()->addItem(pn2GasItem); - scene()->addItem(pheGasItem); - scene()->addItem(po2GasItem); - scene()->addItem(o2SetpointGasItem); - scene()->addItem(ccrsensor1GasItem); - scene()->addItem(ccrsensor2GasItem); - scene()->addItem(ccrsensor3GasItem); - scene()->addItem(percentageAxis); - scene()->addItem(heartBeatAxis); - scene()->addItem(heartBeatItem); - scene()->addItem(rulerItem); - scene()->addItem(rulerItem->sourceNode()); - scene()->addItem(rulerItem->destNode()); - scene()->addItem(tankItem); - scene()->addItem(mouseFollowerHorizontal); - scene()->addItem(mouseFollowerVertical); - QPen pen(QColor(Qt::red).lighter()); - pen.setWidth(0); - mouseFollowerHorizontal->setPen(pen); - mouseFollowerVertical->setPen(pen); - Q_FOREACH (DiveCalculatedTissue *tissue, allTissues) { - scene()->addItem(tissue); - } - Q_FOREACH (DivePercentageItem *percentage, allPercentages) { - scene()->addItem(percentage); - } - scene()->addItem(ambPressureItem); - scene()->addItem(gflineItem); -} - -void ProfileWidget2::setupItemOnScene() -{ - background->setZValue(9999); - toolTipItem->setZValue(9998); - toolTipItem->setTimeAxis(timeAxis); - rulerItem->setZValue(9997); - tankItem->setZValue(100); - - profileYAxis->setOrientation(DiveCartesianAxis::TopToBottom); - profileYAxis->setMinimum(0); - profileYAxis->setTickInterval(M_OR_FT(10, 30)); - profileYAxis->setTickSize(0.5); - profileYAxis->setLineSize(96); - - timeAxis->setLineSize(92); - timeAxis->setTickSize(-0.5); - - gasYAxis->setOrientation(DiveCartesianAxis::BottomToTop); - gasYAxis->setTickInterval(1); - gasYAxis->setTickSize(1); - gasYAxis->setMinimum(0); - gasYAxis->setModel(dataModel); - gasYAxis->setFontLabelScale(0.7); - gasYAxis->setLineSize(96); - - heartBeatAxis->setOrientation(DiveCartesianAxis::BottomToTop); - heartBeatAxis->setTickSize(0.2); - heartBeatAxis->setTickInterval(10); - heartBeatAxis->setFontLabelScale(0.7); - heartBeatAxis->setLineSize(96); - - percentageAxis->setOrientation(DiveCartesianAxis::BottomToTop); - percentageAxis->setTickSize(0.2); - percentageAxis->setTickInterval(10); - percentageAxis->setFontLabelScale(0.7); - percentageAxis->setLineSize(96); - - temperatureAxis->setOrientation(DiveCartesianAxis::BottomToTop); - temperatureAxis->setTickSize(2); - temperatureAxis->setTickInterval(300); - - cylinderPressureAxis->setOrientation(DiveCartesianAxis::BottomToTop); - cylinderPressureAxis->setTickSize(2); - cylinderPressureAxis->setTickInterval(30000); - - - diveComputerText->setAlignment(Qt::AlignRight | Qt::AlignTop); - diveComputerText->setBrush(getColor(TIME_TEXT, isGrayscale)); - - rulerItem->setAxis(timeAxis, profileYAxis); - tankItem->setHorizontalAxis(timeAxis); - - // show the gradient factor at the top in the center - gradientFactor->setY(0); - gradientFactor->setX(50); - gradientFactor->setBrush(getColor(PRESSURE_TEXT)); - gradientFactor->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); - - setupItem(reportedCeiling, timeAxis, profileYAxis, dataModel, DivePlotDataModel::CEILING, DivePlotDataModel::TIME, 1); - setupItem(diveCeiling, timeAxis, profileYAxis, dataModel, DivePlotDataModel::CEILING, DivePlotDataModel::TIME, 1); - for (int i = 0; i < 16; i++) { - DiveCalculatedTissue *tissueItem = new DiveCalculatedTissue(); - setupItem(tissueItem, timeAxis, profileYAxis, dataModel, DivePlotDataModel::TISSUE_1 + i, DivePlotDataModel::TIME, 1 + i); - allTissues.append(tissueItem); - DivePercentageItem *percentageItem = new DivePercentageItem(i); - setupItem(percentageItem, timeAxis, percentageAxis, dataModel, DivePlotDataModel::PERCENTAGE_1 + i, DivePlotDataModel::TIME, 1 + i); - allPercentages.append(percentageItem); - } - setupItem(gasPressureItem, timeAxis, cylinderPressureAxis, dataModel, DivePlotDataModel::TEMPERATURE, DivePlotDataModel::TIME, 1); - setupItem(temperatureItem, timeAxis, temperatureAxis, dataModel, DivePlotDataModel::TEMPERATURE, DivePlotDataModel::TIME, 1); - setupItem(heartBeatItem, timeAxis, heartBeatAxis, dataModel, DivePlotDataModel::HEARTBEAT, DivePlotDataModel::TIME, 1); - setupItem(ambPressureItem, timeAxis, percentageAxis, dataModel, DivePlotDataModel::AMBPRESSURE, DivePlotDataModel::TIME, 1); - setupItem(gflineItem, timeAxis, percentageAxis, dataModel, DivePlotDataModel::GFLINE, DivePlotDataModel::TIME, 1); - setupItem(diveProfileItem, timeAxis, profileYAxis, dataModel, DivePlotDataModel::DEPTH, DivePlotDataModel::TIME, 0); - setupItem(meanDepthItem, timeAxis, profileYAxis, dataModel, DivePlotDataModel::INSTANT_MEANDEPTH, DivePlotDataModel::TIME, 1); - - -#define CREATE_PP_GAS(ITEM, VERTICAL_COLUMN, COLOR, COLOR_ALERT, THRESHOULD_SETTINGS, VISIBILITY_SETTINGS) \ - setupItem(ITEM, timeAxis, gasYAxis, dataModel, DivePlotDataModel::VERTICAL_COLUMN, DivePlotDataModel::TIME, 0); \ - ITEM->setThreshouldSettingsKey(THRESHOULD_SETTINGS); \ - ITEM->setVisibilitySettingsKey(VISIBILITY_SETTINGS); \ - ITEM->setColors(getColor(COLOR, isGrayscale), getColor(COLOR_ALERT, isGrayscale)); \ - ITEM->settingsChanged(); \ - ITEM->setZValue(99); - - CREATE_PP_GAS(pn2GasItem, PN2, PN2, PN2_ALERT, &prefs.pp_graphs.pn2_threshold, "pn2graph"); - CREATE_PP_GAS(pheGasItem, PHE, PHE, PHE_ALERT, &prefs.pp_graphs.phe_threshold, "phegraph"); - CREATE_PP_GAS(po2GasItem, PO2, PO2, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "po2graph"); - CREATE_PP_GAS(o2SetpointGasItem, O2SETPOINT, PO2_ALERT, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "po2graph"); - CREATE_PP_GAS(ccrsensor1GasItem, CCRSENSOR1, CCRSENSOR1, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "ccrsensorgraph"); - CREATE_PP_GAS(ccrsensor2GasItem, CCRSENSOR2, CCRSENSOR2, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "ccrsensorgraph"); - CREATE_PP_GAS(ccrsensor3GasItem, CCRSENSOR3, CCRSENSOR3, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "ccrsensorgraph"); -#undef CREATE_PP_GAS - - temperatureAxis->setTextVisible(false); - temperatureAxis->setLinesVisible(false); - cylinderPressureAxis->setTextVisible(false); - cylinderPressureAxis->setLinesVisible(false); - timeAxis->setLinesVisible(true); - profileYAxis->setLinesVisible(true); - gasYAxis->setZValue(timeAxis->zValue() + 1); - heartBeatAxis->setTextVisible(true); - heartBeatAxis->setLinesVisible(true); - percentageAxis->setTextVisible(true); - percentageAxis->setLinesVisible(true); - - replotEnabled = true; -} - -void ProfileWidget2::replot(struct dive *d) -{ - if (!replotEnabled) - return; - dataModel->clear(); - plotDive(d, true); -} - -void ProfileWidget2::setupItemSizes() -{ - // Scene is *always* (double) 100 / 100. - // Background Config - /* Much probably a better math is needed here. - * good thing is that we only need to change the - * Axis and everything else is auto-adjusted.* - */ - - itemPos.background.on.setX(0); - itemPos.background.on.setY(0); - itemPos.background.off.setX(0); - itemPos.background.off.setY(110); - - //Depth Axis Config - itemPos.depth.pos.on.setX(3); - itemPos.depth.pos.on.setY(3); - itemPos.depth.pos.off.setX(-2); - itemPos.depth.pos.off.setY(3); - itemPos.depth.expanded.setP1(QPointF(0, 0)); - itemPos.depth.expanded.setP2(QPointF(0, 85)); - itemPos.depth.shrinked.setP1(QPointF(0, 0)); - itemPos.depth.shrinked.setP2(QPointF(0, 55)); - itemPos.depth.intermediate.setP1(QPointF(0, 0)); - itemPos.depth.intermediate.setP2(QPointF(0, 65)); - - // Time Axis Config - itemPos.time.pos.on.setX(3); - itemPos.time.pos.on.setY(95); - itemPos.time.pos.off.setX(3); - itemPos.time.pos.off.setY(110); - itemPos.time.expanded.setP1(QPointF(0, 0)); - itemPos.time.expanded.setP2(QPointF(94, 0)); - - // Partial Gas Axis Config - itemPos.partialPressure.pos.on.setX(97); - itemPos.partialPressure.pos.on.setY(75); - itemPos.partialPressure.pos.off.setX(110); - itemPos.partialPressure.pos.off.setY(63); - itemPos.partialPressure.expanded.setP1(QPointF(0, 0)); - itemPos.partialPressure.expanded.setP2(QPointF(0, 19)); - itemPos.partialPressureWithTankBar = itemPos.partialPressure; - itemPos.partialPressureWithTankBar.expanded.setP2(QPointF(0, 17)); - itemPos.partialPressureTissue = itemPos.partialPressure; - itemPos.partialPressureTissue.pos.on.setX(97); - itemPos.partialPressureTissue.pos.on.setY(65); - itemPos.partialPressureTissue.expanded.setP2(QPointF(0, 16)); - - // cylinder axis config - itemPos.cylinder.pos.on.setX(3); - itemPos.cylinder.pos.on.setY(20); - itemPos.cylinder.pos.off.setX(-10); - itemPos.cylinder.pos.off.setY(20); - itemPos.cylinder.expanded.setP1(QPointF(0, 15)); - itemPos.cylinder.expanded.setP2(QPointF(0, 50)); - itemPos.cylinder.shrinked.setP1(QPointF(0, 0)); - itemPos.cylinder.shrinked.setP2(QPointF(0, 20)); - itemPos.cylinder.intermediate.setP1(QPointF(0, 0)); - itemPos.cylinder.intermediate.setP2(QPointF(0, 20)); - - // Temperature axis config - itemPos.temperature.pos.on.setX(3); - itemPos.temperature.pos.on.setY(60); - itemPos.temperatureAll.pos.on.setY(51); - itemPos.temperature.pos.off.setX(-10); - itemPos.temperature.pos.off.setY(40); - itemPos.temperature.expanded.setP1(QPointF(0, 20)); - itemPos.temperature.expanded.setP2(QPointF(0, 33)); - itemPos.temperature.shrinked.setP1(QPointF(0, 2)); - itemPos.temperature.shrinked.setP2(QPointF(0, 12)); - itemPos.temperature.intermediate.setP1(QPointF(0, 2)); - itemPos.temperature.intermediate.setP2(QPointF(0, 12)); - - // Heartbeat axis config - itemPos.heartBeat.pos.on.setX(3); - itemPos.heartBeat.pos.on.setY(82); - itemPos.heartBeat.expanded.setP1(QPointF(0, 0)); - itemPos.heartBeat.expanded.setP2(QPointF(0, 10)); - itemPos.heartBeatWithTankBar = itemPos.heartBeat; - itemPos.heartBeatWithTankBar.expanded.setP2(QPointF(0, 7)); - - // Percentage axis config - itemPos.percentage.pos.on.setX(3); - itemPos.percentage.pos.on.setY(80); - itemPos.percentage.expanded.setP1(QPointF(0, 0)); - itemPos.percentage.expanded.setP2(QPointF(0, 15)); - itemPos.percentageWithTankBar = itemPos.percentage; - itemPos.percentageWithTankBar.expanded.setP2(QPointF(0, 12)); - - itemPos.dcLabel.on.setX(3); - itemPos.dcLabel.on.setY(100); - itemPos.dcLabel.off.setX(-10); - itemPos.dcLabel.off.setY(100); - - itemPos.tankBar.on.setX(0); - itemPos.tankBar.on.setY(91.5); -} - -void ProfileWidget2::setupItem(AbstractProfilePolygonItem *item, DiveCartesianAxis *hAxis, - DiveCartesianAxis *vAxis, DivePlotDataModel *model, - int vData, int hData, int zValue) -{ - item->setHorizontalAxis(hAxis); - item->setVerticalAxis(vAxis); - item->setModel(model); - item->setVerticalDataColumn(vData); - item->setHorizontalDataColumn(hData); - item->setZValue(zValue); -} - -void ProfileWidget2::setupSceneAndFlags() -{ - setScene(new QGraphicsScene(this)); - scene()->setSceneRect(0, 0, 100, 100); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - scene()->setItemIndexMethod(QGraphicsScene::NoIndex); - setOptimizationFlags(QGraphicsView::DontSavePainterState); - setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); - setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - setMouseTracking(true); - background->setFlag(QGraphicsItem::ItemIgnoresTransformations); -} - -void ProfileWidget2::resetZoom() -{ - if (!zoomLevel) - return; - const qreal defScale = 1.0 / qPow(zoomFactor, (qreal)zoomLevel); - scale(defScale, defScale); - zoomLevel = 0; -} - -// Currently just one dive, but the plan is to enable All of the selected dives. -void ProfileWidget2::plotDive(struct dive *d, bool force) -{ - static bool firstCall = true; - QTime measureDuration; // let's measure how long this takes us (maybe we'll turn of TTL calculation later - measureDuration.start(); - - if (currentState != ADD && currentState != PLAN) { - if (!d) { - if (selected_dive == -1) - return; - d = current_dive; // display the current dive - } - - // No need to do this again if we are already showing the same dive - // computer of the same dive, so we check the unique id of the dive - // and the selected dive computer number against the ones we are - // showing (can't compare the dive pointers as those might change). - if (d->id == displayed_dive.id && dc_number == dataModel->dcShown() && !force) - return; - - // this copies the dive and makes copies of all the relevant additional data - copy_dive(d, &displayed_dive); - gradientFactor->setText(QString("GF %1/%2").arg(prefs.gflow).arg(prefs.gfhigh)); - } else { - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - plannerModel->createTemporaryPlan(); - struct diveplan &diveplan = plannerModel->getDiveplan(); - if (!diveplan.dp) { - plannerModel->deleteTemporaryPlan(); - return; - } - gradientFactor->setText(QString("GF %1/%2").arg(diveplan.gflow).arg(diveplan.gfhigh)); - } - - // special handling for the first time we display things - int animSpeedBackup = 0; - if (firstCall && MainWindow::instance()->filesFromCommandLine()) { - animSpeedBackup = prefs.animation_speed; - prefs.animation_speed = 0; - firstCall = false; - } - - // restore default zoom level - resetZoom(); - - // reset some item visibility on printMode changes - toolTipItem->setVisible(!printMode); - rulerItem->setVisible(prefs.rulergraph && !printMode && currentState != PLAN && currentState != ADD); - - if (currentState == EMPTY) - setProfileState(); - - // next get the dive computer structure - if there are no samples - // let's create a fake profile that's somewhat reasonable for the - // data that we have - struct divecomputer *currentdc = select_dc(&displayed_dive); - Q_ASSERT(currentdc); - if (!currentdc || !currentdc->samples) { - currentdc = fake_dc(currentdc); - } - - bool setpointflag = (currentdc->divemode == CCR) && prefs.pp_graphs.po2 && current_dive; - bool sensorflag = setpointflag && prefs.show_ccr_sensors; - o2SetpointGasItem->setVisible(setpointflag && prefs.show_ccr_setpoint); - ccrsensor1GasItem->setVisible(sensorflag); - ccrsensor2GasItem->setVisible(sensorflag && (currentdc->no_o2sensors > 1)); - ccrsensor3GasItem->setVisible(sensorflag && (currentdc->no_o2sensors > 2)); - - /* This struct holds all the data that's about to be plotted. - * I'm not sure this is the best approach ( but since we are - * interpolating some points of the Dive, maybe it is... ) - * The Calculation of the points should be done per graph, - * so I'll *not* calculate everything if something is not being - * shown. - */ - plotInfo = calculate_max_limits_new(&displayed_dive, currentdc); - create_plot_info_new(&displayed_dive, currentdc, &plotInfo, !shouldCalculateMaxDepth); - if (shouldCalculateMaxTime) - maxtime = get_maxtime(&plotInfo); - - /* Only update the max depth if it's bigger than the current ones - * when we are dragging the handler to plan / add dive. - * otherwhise, update normally. - */ - int newMaxDepth = get_maxdepth(&plotInfo); - if (!shouldCalculateMaxDepth) { - if (maxdepth < newMaxDepth) { - maxdepth = newMaxDepth; - } - } else { - maxdepth = newMaxDepth; - } - - dataModel->setDive(&displayed_dive, plotInfo); - toolTipItem->setPlotInfo(plotInfo); - - // It seems that I'll have a lot of boilerplate setting the model / axis for - // each item, I'll mostly like to fix this in the future, but I'll keep at this for now. - profileYAxis->setMaximum(maxdepth); - profileYAxis->updateTicks(); - - temperatureAxis->setMinimum(plotInfo.mintemp); - temperatureAxis->setMaximum(plotInfo.maxtemp - plotInfo.mintemp > 2000 ? plotInfo.maxtemp : plotInfo.mintemp + 2000); - - if (plotInfo.maxhr) { - heartBeatAxis->setMinimum(plotInfo.minhr); - heartBeatAxis->setMaximum(plotInfo.maxhr); - heartBeatAxis->updateTicks(HR_AXIS); // this shows the ticks - } - heartBeatAxis->setVisible(prefs.hrgraph && plotInfo.maxhr); - - percentageAxis->setMinimum(0); - percentageAxis->setMaximum(100); - percentageAxis->setVisible(false); - percentageAxis->updateTicks(HR_AXIS); - - timeAxis->setMaximum(maxtime); - int i, incr; - static int increments[8] = { 10, 20, 30, 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60 }; - /* 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; - timeAxis->setTickInterval(incr); - timeAxis->updateTicks(); - cylinderPressureAxis->setMinimum(plotInfo.minpressure); - cylinderPressureAxis->setMaximum(plotInfo.maxpressure); - - rulerItem->setPlotInfo(plotInfo); - tankItem->setData(dataModel, &plotInfo, &displayed_dive); - - dataModel->emitDataChanged(); - // The event items are a bit special since we don't know how many events are going to - // exist on a dive, so I cant create cache items for that. that's why they are here - // while all other items are up there on the constructor. - qDeleteAll(eventItems); - eventItems.clear(); - struct event *event = currentdc->events; - while (event) { - // if print mode is selected only draw headings, SP change, gas events or bookmark event - if (printMode) { - if (same_string(event->name, "") || - !(strcmp(event->name, "heading") == 0 || - (same_string(event->name, "SP change") && event->time.seconds == 0) || - event_is_gaschange(event) || - event->type == SAMPLE_EVENT_BOOKMARK)) { - event = event->next; - continue; - } - } - DiveEventItem *item = new DiveEventItem(); - item->setHorizontalAxis(timeAxis); - item->setVerticalAxis(profileYAxis); - item->setModel(dataModel); - item->setEvent(event); - item->setZValue(2); - scene()->addItem(item); - eventItems.push_back(item); - event = event->next; - } - // Only set visible the events that should be visible - Q_FOREACH (DiveEventItem *event, eventItems) { - event->setVisible(!event->shouldBeHidden()); - } - QString dcText = get_dc_nickname(currentdc->model, currentdc->deviceid); - int nr; - if ((nr = number_of_computers(&displayed_dive)) > 1) - dcText += tr(" (#%1 of %2)").arg(dc_number + 1).arg(nr); - if (dcText.isEmpty()) - dcText = tr("Unknown dive computer"); - diveComputerText->setText(dcText); - if (MainWindow::instance()->filesFromCommandLine() && animSpeedBackup != 0) { - prefs.animation_speed = animSpeedBackup; - } - - if (currentState == ADD || currentState == PLAN) { // TODO: figure a way to move this from here. - repositionDiveHandlers(); - DivePlannerPointsModel *model = DivePlannerPointsModel::instance(); - model->deleteTemporaryPlan(); - } - plotPictures(); - - // OK, how long did this take us? Anything above the second is way too long, - // so if we are calculation TTS / NDL then let's force that off. - if (measureDuration.elapsed() > 1000 && prefs.calcndltts) { - MainWindow::instance()->turnOffNdlTts(); - MainWindow::instance()->getNotificationWidget()->showNotification(tr("Show NDL / TTS was disabled because of excessive processing time"), KMessageWidget::Error); - } - MainWindow::instance()->getNotificationWidget()->showNotification(get_error_string(), KMessageWidget::Error); - -} - -void ProfileWidget2::recalcCeiling() -{ - diveCeiling->recalc(); -} - -void ProfileWidget2::settingsChanged() -{ - // if we are showing calculated ceilings then we have to replot() - // because the GF could have changed; otherwise we try to avoid replot() - bool needReplot = prefs.calcceiling; - if ((prefs.percentagegraph||prefs.hrgraph) && PP_GRAPHS_ENABLED) { - profileYAxis->animateChangeLine(itemPos.depth.shrinked); - temperatureAxis->setPos(itemPos.temperatureAll.pos.on); - temperatureAxis->animateChangeLine(itemPos.temperature.shrinked); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.shrinked); - - if (prefs.tankbar) { - percentageAxis->setPos(itemPos.percentageWithTankBar.pos.on); - percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded); - heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded); - }else { - percentageAxis->setPos(itemPos.percentage.pos.on); - percentageAxis->animateChangeLine(itemPos.percentage.expanded); - heartBeatAxis->setPos(itemPos.heartBeat.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded); - } - gasYAxis->setPos(itemPos.partialPressureTissue.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressureTissue.expanded); - - } else if (PP_GRAPHS_ENABLED || prefs.hrgraph || prefs.percentagegraph) { - profileYAxis->animateChangeLine(itemPos.depth.intermediate); - temperatureAxis->setPos(itemPos.temperature.pos.on); - temperatureAxis->animateChangeLine(itemPos.temperature.intermediate); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.intermediate); - if (prefs.tankbar) { - percentageAxis->setPos(itemPos.percentageWithTankBar.pos.on); - percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded); - gasYAxis->setPos(itemPos.partialPressureWithTankBar.pos.on); - gasYAxis->setLine(itemPos.partialPressureWithTankBar.expanded); - heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded); - } else { - gasYAxis->setPos(itemPos.partialPressure.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressure.expanded); - percentageAxis->setPos(itemPos.percentage.pos.on); - percentageAxis->setLine(itemPos.percentage.expanded); - heartBeatAxis->setPos(itemPos.heartBeat.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded); - } - } else { - profileYAxis->animateChangeLine(itemPos.depth.expanded); - if (prefs.tankbar) { - temperatureAxis->setPos(itemPos.temperatureAll.pos.on); - } else { - temperatureAxis->setPos(itemPos.temperature.pos.on); - } - temperatureAxis->animateChangeLine(itemPos.temperature.expanded); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.expanded); - } - - tankItem->setVisible(prefs.tankbar); - if (prefs.zoomed_plot != isPlotZoomed) { - isPlotZoomed = prefs.zoomed_plot; - needReplot = true; - } - if (needReplot) - replot(); -} - -void ProfileWidget2::resizeEvent(QResizeEvent *event) -{ - QGraphicsView::resizeEvent(event); - fitInView(sceneRect(), Qt::IgnoreAspectRatio); - fixBackgroundPos(); -} - -void ProfileWidget2::mousePressEvent(QMouseEvent *event) -{ - if (zoomLevel) - return; - QGraphicsView::mousePressEvent(event); - if (currentState == PLAN) - shouldCalculateMaxTime = false; -} - -void ProfileWidget2::divePlannerHandlerClicked() -{ - if (zoomLevel) - return; - shouldCalculateMaxDepth = false; - replot(); -} - -void ProfileWidget2::divePlannerHandlerReleased() -{ - if (zoomLevel) - return; - shouldCalculateMaxDepth = true; - replot(); -} - -void ProfileWidget2::mouseReleaseEvent(QMouseEvent *event) -{ - if (zoomLevel) - return; - QGraphicsView::mouseReleaseEvent(event); - if (currentState == PLAN) { - shouldCalculateMaxTime = true; - replot(); - } -} - -void ProfileWidget2::fixBackgroundPos() -{ - static QPixmap toBeScaled(backgroundFile); - if (currentState != EMPTY) - return; - QPixmap p = toBeScaled.scaledToHeight(viewport()->height() - 40, Qt::SmoothTransformation); - int x = viewport()->width() / 2 - p.width() / 2; - int y = viewport()->height() / 2 - p.height() / 2; - background->setPixmap(p); - background->setX(mapToScene(x, 0).x()); - background->setY(mapToScene(y, 20).y()); -} - -void ProfileWidget2::wheelEvent(QWheelEvent *event) -{ - if (currentState == EMPTY) - return; - QPoint toolTipPos = mapFromScene(toolTipItem->pos()); - if (event->buttons() == Qt::LeftButton) - return; - if (event->delta() > 0 && zoomLevel < 20) { - scale(zoomFactor, zoomFactor); - zoomLevel++; - } else if (event->delta() < 0 && zoomLevel > 0) { - // Zooming out - scale(1.0 / zoomFactor, 1.0 / zoomFactor); - zoomLevel--; - } - scrollViewTo(event->pos()); - toolTipItem->setPos(mapToScene(toolTipPos)); -} - -void ProfileWidget2::mouseDoubleClickEvent(QMouseEvent *event) -{ - if (currentState == PLAN || currentState == ADD) { - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - QPointF mappedPos = mapToScene(event->pos()); - if (isPointOutOfBoundaries(mappedPos)) - return; - - int minutes = rint(timeAxis->valueAt(mappedPos) / 60); - int milimeters = rint(profileYAxis->valueAt(mappedPos) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); - plannerModel->addStop(milimeters, minutes * 60, 0, 0, true); - } -} - -bool ProfileWidget2::isPointOutOfBoundaries(const QPointF &point) const -{ - double xpos = timeAxis->valueAt(point); - double ypos = profileYAxis->valueAt(point); - return (xpos > timeAxis->maximum() || - xpos < timeAxis->minimum() || - ypos > profileYAxis->maximum() || - ypos < profileYAxis->minimum()); -} - -void ProfileWidget2::scrollViewTo(const QPoint &pos) -{ - /* since we cannot use translate() directly on the scene we hack on - * the scroll bars (hidden) functionality */ - if (!zoomLevel || currentState == EMPTY) - return; - QScrollBar *vs = verticalScrollBar(); - QScrollBar *hs = horizontalScrollBar(); - const qreal yRat = (qreal)pos.y() / viewport()->height(); - const qreal xRat = (qreal)pos.x() / viewport()->width(); - vs->setValue(yRat * vs->maximum()); - hs->setValue(xRat * hs->maximum()); -} - -void ProfileWidget2::mouseMoveEvent(QMouseEvent *event) -{ - QPointF pos = mapToScene(event->pos()); - toolTipItem->refresh(pos); - if (zoomLevel == 0) { - QGraphicsView::mouseMoveEvent(event); - } else { - QPoint toolTipPos = mapFromScene(toolTipItem->pos()); - scrollViewTo(event->pos()); - toolTipItem->setPos(mapToScene(toolTipPos)); - } - - qreal vValue = profileYAxis->valueAt(pos); - qreal hValue = timeAxis->valueAt(pos); - if (profileYAxis->maximum() >= vValue && profileYAxis->minimum() <= vValue) { - mouseFollowerHorizontal->setPos(timeAxis->pos().x(), pos.y()); - } - if (timeAxis->maximum() >= hValue && timeAxis->minimum() <= hValue) { - mouseFollowerVertical->setPos(pos.x(), profileYAxis->line().y1()); - } -} - -bool ProfileWidget2::eventFilter(QObject *object, QEvent *event) -{ - QGraphicsScene *s = qobject_cast<QGraphicsScene *>(object); - if (s && event->type() == QEvent::GraphicsSceneHelp) { - event->ignore(); - return true; - } - return QGraphicsView::eventFilter(object, event); -} - -void ProfileWidget2::setEmptyState() -{ - // Then starting Empty State, move the background up. - if (currentState == EMPTY) - return; - - disconnectTemporaryConnections(); - setBackgroundBrush(getColor(::BACKGROUND, isGrayscale)); - dataModel->clear(); - currentState = EMPTY; - MainWindow::instance()->setEnabledToolbar(false); - - fixBackgroundPos(); - background->setVisible(true); - - profileYAxis->setVisible(false); - gasYAxis->setVisible(false); - timeAxis->setVisible(false); - temperatureAxis->setVisible(false); - cylinderPressureAxis->setVisible(false); - toolTipItem->setVisible(false); - diveComputerText->setVisible(false); - diveCeiling->setVisible(false); - gradientFactor->setVisible(false); - reportedCeiling->setVisible(false); - rulerItem->setVisible(false); - tankItem->setVisible(false); - pn2GasItem->setVisible(false); - po2GasItem->setVisible(false); - o2SetpointGasItem->setVisible(false); - ccrsensor1GasItem->setVisible(false); - ccrsensor2GasItem->setVisible(false); - ccrsensor3GasItem->setVisible(false); - pheGasItem->setVisible(false); - ambPressureItem->setVisible(false); - gflineItem->setVisible(false); - mouseFollowerHorizontal->setVisible(false); - mouseFollowerVertical->setVisible(false); - -#define HIDE_ALL(TYPE, CONTAINER) \ - Q_FOREACH (TYPE *item, CONTAINER) item->setVisible(false); - HIDE_ALL(DiveCalculatedTissue, allTissues); - HIDE_ALL(DivePercentageItem, allPercentages); - HIDE_ALL(DiveEventItem, eventItems); - HIDE_ALL(DiveHandler, handles); - HIDE_ALL(QGraphicsSimpleTextItem, gases); -#undef HIDE_ALL -} - -void ProfileWidget2::setProfileState() -{ - // Then starting Empty State, move the background up. - if (currentState == PROFILE) - return; - - disconnectTemporaryConnections(); - connect(DivePictureModel::instance(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(plotPictures())); - connect(DivePictureModel::instance(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(plotPictures())); - connect(DivePictureModel::instance(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(plotPictures())); - /* show the same stuff that the profile shows. */ - - //TODO: Move the DC handling to another method. - MainWindow::instance()->enableShortcuts(); - - currentState = PROFILE; - MainWindow::instance()->setEnabledToolbar(true); - toolTipItem->readPos(); - setBackgroundBrush(getColor(::BACKGROUND, isGrayscale)); - - background->setVisible(false); - toolTipItem->setVisible(true); - profileYAxis->setVisible(true); - gasYAxis->setVisible(true); - timeAxis->setVisible(true); - temperatureAxis->setVisible(true); - cylinderPressureAxis->setVisible(true); - - profileYAxis->setPos(itemPos.depth.pos.on); - if ((prefs.percentagegraph||prefs.hrgraph) && PP_GRAPHS_ENABLED) { - profileYAxis->animateChangeLine(itemPos.depth.shrinked); - temperatureAxis->setPos(itemPos.temperatureAll.pos.on); - temperatureAxis->animateChangeLine(itemPos.temperature.shrinked); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.shrinked); - - if (prefs.tankbar) { - percentageAxis->setPos(itemPos.percentageWithTankBar.pos.on); - percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded); - heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded); - }else { - percentageAxis->setPos(itemPos.percentage.pos.on); - percentageAxis->animateChangeLine(itemPos.percentage.expanded); - heartBeatAxis->setPos(itemPos.heartBeat.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded); - } - gasYAxis->setPos(itemPos.partialPressureTissue.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressureTissue.expanded); - - } else if (PP_GRAPHS_ENABLED || prefs.hrgraph || prefs.percentagegraph) { - profileYAxis->animateChangeLine(itemPos.depth.intermediate); - temperatureAxis->setPos(itemPos.temperature.pos.on); - temperatureAxis->animateChangeLine(itemPos.temperature.intermediate); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.intermediate); - if (prefs.tankbar) { - percentageAxis->setPos(itemPos.percentageWithTankBar.pos.on); - percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded); - gasYAxis->setPos(itemPos.partialPressureWithTankBar.pos.on); - gasYAxis->setLine(itemPos.partialPressureWithTankBar.expanded); - heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded); - } else { - gasYAxis->setPos(itemPos.partialPressure.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressure.expanded); - percentageAxis->setPos(itemPos.percentage.pos.on); - percentageAxis->setLine(itemPos.percentage.expanded); - heartBeatAxis->setPos(itemPos.heartBeat.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded); - } - } else { - profileYAxis->animateChangeLine(itemPos.depth.expanded); - if (prefs.tankbar) { - temperatureAxis->setPos(itemPos.temperatureAll.pos.on); - } else { - temperatureAxis->setPos(itemPos.temperature.pos.on); - } - temperatureAxis->animateChangeLine(itemPos.temperature.expanded); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.expanded); - } - pn2GasItem->setVisible(prefs.pp_graphs.pn2); - po2GasItem->setVisible(prefs.pp_graphs.po2); - pheGasItem->setVisible(prefs.pp_graphs.phe); - - bool setpointflag = current_dive && (current_dc->divemode == CCR) && prefs.pp_graphs.po2; - bool sensorflag = setpointflag && prefs.show_ccr_sensors; - o2SetpointGasItem->setVisible(setpointflag && prefs.show_ccr_setpoint); - ccrsensor1GasItem->setVisible(sensorflag); - ccrsensor2GasItem->setVisible(sensorflag && (current_dc->no_o2sensors > 1)); - ccrsensor3GasItem->setVisible(sensorflag && (current_dc->no_o2sensors > 2)); - - timeAxis->setPos(itemPos.time.pos.on); - timeAxis->setLine(itemPos.time.expanded); - - cylinderPressureAxis->setPos(itemPos.cylinder.pos.on); - heartBeatItem->setVisible(prefs.hrgraph); - meanDepthItem->setVisible(prefs.show_average_depth); - - diveComputerText->setVisible(true); - diveComputerText->setPos(itemPos.dcLabel.on); - - diveCeiling->setVisible(prefs.calcceiling); - gradientFactor->setVisible(prefs.calcceiling); - reportedCeiling->setVisible(prefs.dcceiling); - - if (prefs.calcalltissues) { - Q_FOREACH (DiveCalculatedTissue *tissue, allTissues) { - tissue->setVisible(true); - } - } - - if (prefs.percentagegraph) { - Q_FOREACH (DivePercentageItem *percentage, allPercentages) { - percentage->setVisible(true); - } - - ambPressureItem->setVisible(true); - gflineItem->setVisible(true); - } - - rulerItem->setVisible(prefs.rulergraph); - tankItem->setVisible(prefs.tankbar); - tankItem->setPos(itemPos.tankBar.on); - -#define HIDE_ALL(TYPE, CONTAINER) \ - Q_FOREACH (TYPE *item, CONTAINER) item->setVisible(false); - HIDE_ALL(DiveHandler, handles); - HIDE_ALL(QGraphicsSimpleTextItem, gases); -#undef HIDE_ALL - mouseFollowerHorizontal->setVisible(false); - mouseFollowerVertical->setVisible(false); -} - -void ProfileWidget2::clearHandlers() -{ - if (handles.count()) { - foreach (DiveHandler *handle, handles) { - scene()->removeItem(handle); - delete handle; - } - handles.clear(); - } -} - -void ProfileWidget2::setToolTipVisibile(bool visible) -{ - toolTipItem->setVisible(visible); -} - -void ProfileWidget2::setAddState() -{ - if (currentState == ADD) - return; - - clearHandlers(); - setProfileState(); - mouseFollowerHorizontal->setVisible(true); - mouseFollowerVertical->setVisible(true); - mouseFollowerHorizontal->setLine(timeAxis->line()); - mouseFollowerVertical->setLine(QLineF(0, profileYAxis->pos().y(), 0, timeAxis->pos().y())); - disconnectTemporaryConnections(); - //TODO: Move this method to another place, shouldn't be on mainwindow. - MainWindow::instance()->disableShortcuts(false); - actionsForKeys[Qt::Key_Left]->setShortcut(Qt::Key_Left); - actionsForKeys[Qt::Key_Right]->setShortcut(Qt::Key_Right); - actionsForKeys[Qt::Key_Up]->setShortcut(Qt::Key_Up); - actionsForKeys[Qt::Key_Down]->setShortcut(Qt::Key_Down); - actionsForKeys[Qt::Key_Escape]->setShortcut(Qt::Key_Escape); - actionsForKeys[Qt::Key_Delete]->setShortcut(Qt::Key_Delete); - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - connect(plannerModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(replot())); - connect(plannerModel, SIGNAL(cylinderModelEdited()), this, SLOT(replot())); - connect(plannerModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(pointInserted(const QModelIndex &, int, int))); - connect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(pointsRemoved(const QModelIndex &, int, int))); - /* show the same stuff that the profile shows. */ - currentState = ADD; /* enable the add state. */ - diveCeiling->setVisible(true); - gradientFactor->setVisible(true); - setBackgroundBrush(QColor("#A7DCFF")); -} - -void ProfileWidget2::setPlanState() -{ - if (currentState == PLAN) - return; - - setProfileState(); - mouseFollowerHorizontal->setVisible(true); - mouseFollowerVertical->setVisible(true); - mouseFollowerHorizontal->setLine(timeAxis->line()); - mouseFollowerVertical->setLine(QLineF(0, profileYAxis->pos().y(), 0, timeAxis->pos().y())); - disconnectTemporaryConnections(); - //TODO: Move this method to another place, shouldn't be on mainwindow. - MainWindow::instance()->disableShortcuts(); - actionsForKeys[Qt::Key_Left]->setShortcut(Qt::Key_Left); - actionsForKeys[Qt::Key_Right]->setShortcut(Qt::Key_Right); - actionsForKeys[Qt::Key_Up]->setShortcut(Qt::Key_Up); - actionsForKeys[Qt::Key_Down]->setShortcut(Qt::Key_Down); - actionsForKeys[Qt::Key_Escape]->setShortcut(Qt::Key_Escape); - actionsForKeys[Qt::Key_Delete]->setShortcut(Qt::Key_Delete); - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - connect(plannerModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(replot())); - connect(plannerModel, SIGNAL(cylinderModelEdited()), this, SLOT(replot())); - connect(plannerModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(pointInserted(const QModelIndex &, int, int))); - connect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(pointsRemoved(const QModelIndex &, int, int))); - /* show the same stuff that the profile shows. */ - currentState = PLAN; /* enable the add state. */ - diveCeiling->setVisible(true); - gradientFactor->setVisible(true); - setBackgroundBrush(QColor("#D7E3EF")); -} - -extern struct ev_select *ev_namelist; -extern int evn_allocated; -extern int evn_used; - -bool ProfileWidget2::isPlanner() -{ - return currentState == PLAN; -} - -bool ProfileWidget2::isAddOrPlanner() -{ - return currentState == PLAN || currentState == ADD; -} - -struct plot_data *ProfileWidget2::getEntryFromPos(QPointF pos) -{ - // find the time stamp corresponding to the mouse position - int seconds = timeAxis->valueAt(pos); - struct plot_data *entry = NULL; - - for (int i = 0; i < plotInfo.nr; i++) { - entry = plotInfo.entry + i; - if (entry->sec >= seconds) - break; - } - return entry; -} - -void ProfileWidget2::setReplot(bool state) -{ - replotEnabled = state; -} - -void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) -{ - if (currentState == ADD || currentState == PLAN) { - QGraphicsView::contextMenuEvent(event); - return; - } - QMenu m; - bool isDCName = false; - if (selected_dive == -1) - return; - // figure out if we are ontop of the dive computer name in the profile - QGraphicsItem *sceneItem = itemAt(mapFromGlobal(event->globalPos())); - if (sceneItem) { - QGraphicsItem *parentItem = sceneItem; - while (parentItem) { - if (parentItem->data(SUBSURFACE_OBJ_DATA) == SUBSURFACE_OBJ_DC_TEXT) { - isDCName = true; - break; - } - parentItem = parentItem->parentItem(); - } - if (isDCName) { - if (dc_number == 0 && count_divecomputers() == 1) - // nothing to do, can't delete or reorder - return; - // create menu to show when right clicking on dive computer name - if (dc_number > 0) - m.addAction(tr("Make first divecomputer"), this, SLOT(makeFirstDC())); - if (count_divecomputers() > 1) - m.addAction(tr("Delete this divecomputer"), this, SLOT(deleteCurrentDC())); - m.exec(event->globalPos()); - // don't show the regular profile context menu - return; - } - } - // create the profile context menu - QPointF scenePos = mapToScene(event->pos()); - struct plot_data *entry = getEntryFromPos(scenePos); - GasSelectionModel *model = GasSelectionModel::instance(); - model->repopulate(); - int rowCount = model->rowCount(); - if (rowCount > 1) { - // if we have more than one gas, offer to switch to another one - QMenu *gasChange = m.addMenu(tr("Add gas change")); - for (int i = 0; i < rowCount; i++) { - QAction *action = new QAction(&m); - action->setText(model->data(model->index(i, 0), Qt::DisplayRole).toString() + QString(tr(" (Tank %1)")).arg(i + 1)); - connect(action, SIGNAL(triggered(bool)), this, SLOT(changeGas())); - action->setData(event->globalPos()); - if (i == entry->cylinderindex) - action->setDisabled(true); - gasChange->addAction(action); - } - } - QAction *setpointAction = m.addAction(tr("Add set-point change"), this, SLOT(addSetpointChange())); - setpointAction->setData(event->globalPos()); - QAction *action = m.addAction(tr("Add bookmark"), this, SLOT(addBookmark())); - action->setData(event->globalPos()); - - if (same_string(current_dc->model, "manually added dive")) - QAction *editProfileAction = m.addAction(tr("Edit the profile"), MainWindow::instance(), SLOT(editCurrentDive())); - - if (DiveEventItem *item = dynamic_cast<DiveEventItem *>(sceneItem)) { - 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); - struct event *dcEvent = item->getEvent(); - if (dcEvent->type == SAMPLE_EVENT_BOOKMARK) { - action = new QAction(&m); - action->setText(tr("Edit name")); - action->setData(QVariant::fromValue<void *>(item)); - connect(action, SIGNAL(triggered(bool)), this, SLOT(editName())); - m.addAction(action); - } -#if 0 // FIXME::: FINISH OR DISABLE - // this shows how to figure out if we should ask the user if they want adjust interpolated pressures - // at either side of a gas change - if (dcEvent->type == SAMPLE_EVENT_GASCHANGE || dcEvent->type == SAMPLE_EVENT_GASCHANGE2) { - qDebug() << "figure out if there are interpolated pressures"; - struct plot_data *gasChangeEntry = entry; - struct plot_data *newGasEntry; - while (gasChangeEntry > plotInfo.entry) { - --gasChangeEntry; - if (gasChangeEntry->sec <= dcEvent->time.seconds) - break; - } - qDebug() << "at gas change at" << gasChangeEntry->sec << ": sensor pressure" << gasChangeEntry->pressure[0] << "interpolated" << gasChangeEntry->pressure[1]; - // now gasChangeEntry points at the gas change, that entry has the final pressure of - // the old tank, the next entry has the starting pressure of the next tank - if (gasChangeEntry + 1 <= plotInfo.entry + plotInfo.nr) { - newGasEntry = gasChangeEntry + 1; - qDebug() << "after gas change at " << newGasEntry->sec << ": sensor pressure" << newGasEntry->pressure[0] << "interpolated" << newGasEntry->pressure[1]; - if (SENSOR_PRESSURE(gasChangeEntry) == 0 || displayed_dive.cylinder[gasChangeEntry->cylinderindex].sample_start.mbar == 0) { - // if we have no sensorpressure or if we have no pressure from samples we can assume that - // we only have interpolated pressure (the pressure in the entry may be stored in the sensor - // pressure field if this is the first or last entry for this tank... see details in gaspressures.c - pressure_t pressure; - pressure.mbar = INTERPOLATED_PRESSURE(gasChangeEntry) ? : SENSOR_PRESSURE(gasChangeEntry); - QAction *adjustOldPressure = m.addAction(tr("Adjust pressure of tank %1 (currently interpolated as %2)") - .arg(gasChangeEntry->cylinderindex + 1).arg(get_pressure_string(pressure))); - } - if (SENSOR_PRESSURE(newGasEntry) == 0 || displayed_dive.cylinder[newGasEntry->cylinderindex].sample_start.mbar == 0) { - // we only have interpolated press -- see commend above - pressure_t pressure; - pressure.mbar = INTERPOLATED_PRESSURE(newGasEntry) ? : SENSOR_PRESSURE(newGasEntry); - QAction *adjustOldPressure = m.addAction(tr("Adjust pressure of tank %1 (currently interpolated as %2)") - .arg(newGasEntry->cylinderindex + 1).arg(get_pressure_string(pressure))); - } - } - } -#endif - } - 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 ProfileWidget2::deleteCurrentDC() -{ - delete_current_divecomputer(); - mark_divelist_changed(true); - // we need to force it since it's likely the same dive and same dc_number - but that's a different dive computer now - MainWindow::instance()->graphics()->plotDive(0, true); - MainWindow::instance()->refreshDisplay(); -} - -void ProfileWidget2::makeFirstDC() -{ - make_first_dc(); - mark_divelist_changed(true); - // this is now the first DC, so we need to redraw the profile and refresh the dive list - // (and no, it's not just enough to rewrite the text - the first DC is special so values in the - // dive list may change). - // As a side benefit, this returns focus to the dive list. - dc_number = 0; - MainWindow::instance()->refreshDisplay(); -} - -void ProfileWidget2::hideEvents() -{ - QAction *action = qobject_cast<QAction *>(sender()); - DiveEventItem *item = static_cast<DiveEventItem *>(action->data().value<void *>()); - struct event *event = item->getEvent(); - - 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 (!same_string(event->name, "")) { - for (int i = 0; i < evn_used; i++) { - if (same_string(event->name, ev_namelist[i].ev_name)) { - ev_namelist[i].plot_ev = false; - break; - } - } - Q_FOREACH (DiveEventItem *evItem, eventItems) { - if (same_string(evItem->getEvent()->name, event->name)) - evItem->hide(); - } - } else { - item->hide(); - } - } -} - -void ProfileWidget2::unhideEvents() -{ - for (int i = 0; i < evn_used; i++) { - ev_namelist[i].plot_ev = true; - } - Q_FOREACH (DiveEventItem *item, eventItems) - item->show(); -} - -void ProfileWidget2::removeEvent() -{ - QAction *action = qobject_cast<QAction *>(sender()); - DiveEventItem *item = static_cast<DiveEventItem *>(action->data().value<void *>()); - struct event *event = item->getEvent(); - - 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) { - remove_event(event); - mark_divelist_changed(true); - replot(); - } -} - -void ProfileWidget2::addBookmark() -{ - QAction *action = qobject_cast<QAction *>(sender()); - QPointF scenePos = mapToScene(mapFromGlobal(action->data().toPoint())); - add_event(current_dc, timeAxis->valueAt(scenePos), SAMPLE_EVENT_BOOKMARK, 0, 0, "bookmark"); - mark_divelist_changed(true); - replot(); -} - -void ProfileWidget2::addSetpointChange() -{ - QAction *action = qobject_cast<QAction *>(sender()); - QPointF scenePos = mapToScene(mapFromGlobal(action->data().toPoint())); - SetpointDialog::instance()->setpointData(current_dc, timeAxis->valueAt(scenePos)); - SetpointDialog::instance()->show(); -} - -void ProfileWidget2::changeGas() -{ - QAction *action = qobject_cast<QAction *>(sender()); - QPointF scenePos = mapToScene(mapFromGlobal(action->data().toPoint())); - QString gas = action->text(); - gas.remove(QRegExp(" \\(.*\\)")); - - // backup the things on the dataModel, since we will clear that out. - struct gasmix gasmix; - qreal sec_val = timeAxis->valueAt(scenePos); - - // no gas changes before the dive starts - unsigned int seconds = (sec_val < 0.0) ? 0 : (unsigned int)sec_val; - - // if there is a gas change at this time stamp, remove it before adding the new one - struct event *gasChangeEvent = current_dc->events; - while ((gasChangeEvent = get_next_event(gasChangeEvent, "gaschange")) != NULL) { - if (gasChangeEvent->time.seconds == seconds) { - remove_event(gasChangeEvent); - gasChangeEvent = current_dc->events; - } else { - gasChangeEvent = gasChangeEvent->next; - } - } - validate_gas(gas.toUtf8().constData(), &gasmix); - QRegExp rx("\\(\\D*(\\d+)"); - int tank; - if (rx.indexIn(action->text()) > -1) { - tank = rx.cap(1).toInt() - 1; // we display the tank 1 based - } else { - qDebug() << "failed to parse tank number"; - tank = get_gasidx(&displayed_dive, &gasmix); - } - // add this both to the displayed dive and the current dive - add_gas_switch_event(current_dive, current_dc, seconds, tank); - add_gas_switch_event(&displayed_dive, get_dive_dc(&displayed_dive, dc_number), seconds, tank); - // this means we potentially have a new tank that is being used and needs to be shown - fixup_dive(&displayed_dive); - - // FIXME - this no longer gets written to the dive list - so we need to enableEdition() here - - MainWindow::instance()->information()->updateDiveInfo(); - mark_divelist_changed(true); - replot(); -} - -bool ProfileWidget2::getPrintMode() -{ - return printMode; -} - -void ProfileWidget2::setPrintMode(bool mode, bool grayscale) -{ - printMode = mode; - resetZoom(); - - // set printMode for axes - profileYAxis->setPrintMode(mode); - gasYAxis->setPrintMode(mode); - temperatureAxis->setPrintMode(mode); - timeAxis->setPrintMode(mode); - cylinderPressureAxis->setPrintMode(mode); - heartBeatAxis->setPrintMode(mode); - percentageAxis->setPrintMode(mode); - - isGrayscale = mode ? grayscale : false; - mouseFollowerHorizontal->setVisible(!mode); - mouseFollowerVertical->setVisible(!mode); -} - -void ProfileWidget2::setFontPrintScale(double scale) -{ - fontPrintScale = scale; - emit fontPrintScaleChanged(scale); -} - -double ProfileWidget2::getFontPrintScale() -{ - if (printMode) - return fontPrintScale; - else - return 1.0; -} - -void ProfileWidget2::editName() -{ - QAction *action = qobject_cast<QAction *>(sender()); - DiveEventItem *item = static_cast<DiveEventItem *>(action->data().value<void *>()); - struct event *event = item->getEvent(); - bool ok; - QString newName = QInputDialog::getText(MainWindow::instance(), tr("Edit name of bookmark"), - tr("Custom name:"), QLineEdit::Normal, - event->name, &ok); - if (ok && !newName.isEmpty()) { - if (newName.length() > 22) { //longer names will display as garbage. - QMessageBox lengthWarning; - lengthWarning.setText(tr("Name is too long!")); - lengthWarning.exec(); - return; - } - // order is important! first update the current dive (by matching the unchanged event), - // then update the displayed dive (as event is part of the events on displayed dive - // and will be freed as part of changing the name! - update_event_name(current_dive, event, newName.toUtf8().data()); - update_event_name(&displayed_dive, event, newName.toUtf8().data()); - mark_divelist_changed(true); - replot(); - } -} - -void ProfileWidget2::disconnectTemporaryConnections() -{ - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - disconnect(plannerModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(replot())); - disconnect(plannerModel, SIGNAL(cylinderModelEdited()), this, SLOT(replot())); - - disconnect(plannerModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(pointInserted(const QModelIndex &, int, int))); - disconnect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(pointsRemoved(const QModelIndex &, int, int))); - - Q_FOREACH (QAction *action, actionsForKeys.values()) { - action->setShortcut(QKeySequence()); - action->setShortcutContext(Qt::WidgetShortcut); - } -} - -void ProfileWidget2::pointInserted(const QModelIndex &parent, int start, int end) -{ - DiveHandler *item = new DiveHandler(); - scene()->addItem(item); - handles << item; - - connect(item, SIGNAL(moved()), this, SLOT(recreatePlannedDive())); - connect(item, SIGNAL(clicked()), this, SLOT(divePlannerHandlerClicked())); - connect(item, SIGNAL(released()), this, SLOT(divePlannerHandlerReleased())); - QGraphicsSimpleTextItem *gasChooseBtn = new QGraphicsSimpleTextItem(); - scene()->addItem(gasChooseBtn); - gasChooseBtn->setZValue(10); - gasChooseBtn->setFlag(QGraphicsItem::ItemIgnoresTransformations); - gases << gasChooseBtn; - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - if (plannerModel->recalcQ()) - replot(); -} - -void ProfileWidget2::pointsRemoved(const QModelIndex &, int start, int end) -{ // start and end are inclusive. - int num = (end - start) + 1; - for (int i = num; i != 0; i--) { - delete handles.back(); - handles.pop_back(); - delete gases.back(); - gases.pop_back(); - } - scene()->clearSelection(); - replot(); -} - -void ProfileWidget2::repositionDiveHandlers() -{ - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - // Re-position the user generated dive handlers - struct gasmix mix, lastmix; - for (int i = 0; i < plannerModel->rowCount(); i++) { - struct divedatapoint datapoint = plannerModel->at(i); - if (datapoint.time == 0) // those are the magic entries for tanks - continue; - DiveHandler *h = handles.at(i); - h->setVisible(datapoint.entered); - h->setPos(timeAxis->posAtValue(datapoint.time), profileYAxis->posAtValue(datapoint.depth)); - QPointF p1; - if (i == 0) { - if (prefs.drop_stone_mode) - // place the text on the straight line from the drop to stone position - p1 = QPointF(timeAxis->posAtValue(datapoint.depth / prefs.descrate), - profileYAxis->posAtValue(datapoint.depth)); - else - // place the text on the straight line from the origin to the first position - p1 = QPointF(timeAxis->posAtValue(0), profileYAxis->posAtValue(0)); - } else { - // place the text on the line from the last position - p1 = handles[i - 1]->pos(); - } - QPointF p2 = handles[i]->pos(); - QLineF line(p1, p2); - QPointF pos = line.pointAt(0.5); - gases[i]->setPos(pos); - gases[i]->setText(get_divepoint_gas_string(datapoint)); - gases[i]->setVisible(datapoint.entered && - (i == 0 || gases[i]->text() != gases[i-1]->text())); - } -} - -int ProfileWidget2::fixHandlerIndex(DiveHandler *activeHandler) -{ - int index = handles.indexOf(activeHandler); - if (index > 0 && index < handles.count() - 1) { - DiveHandler *before = handles[index - 1]; - if (before->pos().x() > activeHandler->pos().x()) { - handles.swap(index, index - 1); - return index - 1; - } - DiveHandler *after = handles[index + 1]; - if (after->pos().x() < activeHandler->pos().x()) { - handles.swap(index, index + 1); - return index + 1; - } - } - return index; -} - -void ProfileWidget2::recreatePlannedDive() -{ - DiveHandler *activeHandler = qobject_cast<DiveHandler *>(sender()); - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - int index = fixHandlerIndex(activeHandler); - int mintime = 0, maxtime = (timeAxis->maximum() + 10) * 60; - if (index > 0) - mintime = plannerModel->at(index - 1).time; - if (index < plannerModel->size() - 1) - maxtime = plannerModel->at(index + 1).time; - - int minutes = rint(timeAxis->valueAt(activeHandler->pos()) / 60); - if (minutes * 60 <= mintime || minutes * 60 >= maxtime) - return; - - divedatapoint data = plannerModel->at(index); - data.depth = rint(profileYAxis->valueAt(activeHandler->pos()) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); - data.time = rint(timeAxis->valueAt(activeHandler->pos())); - - plannerModel->editStop(index, data); -} - -void ProfileWidget2::keyDownAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - if (dp.depth >= profileYAxis->maximum()) - continue; - - dp.depth += M_OR_FT(1, 5); - plannerModel->editStop(row, dp); - } - } -} - -void ProfileWidget2::keyUpAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - - if (dp.depth <= 0) - continue; - - dp.depth -= M_OR_FT(1, 5); - plannerModel->editStop(row, dp); - } - } -} - -void ProfileWidget2::keyLeftAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - - if (dp.time / 60 <= 0) - continue; - - // don't overlap positions. - // maybe this is a good place for a 'goto'? - double xpos = timeAxis->posAtValue((dp.time - 60) / 60); - bool nextStep = false; - Q_FOREACH (DiveHandler *h, handles) { - if (IS_FP_SAME(h->pos().x(), xpos)) { - nextStep = true; - break; - } - } - if (nextStep) - continue; - - dp.time -= 60; - plannerModel->editStop(row, dp); - } - } -} - -void ProfileWidget2::keyRightAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - if (dp.time / 60.0 >= timeAxis->maximum()) - continue; - - // don't overlap positions. - // maybe this is a good place for a 'goto'? - double xpos = timeAxis->posAtValue((dp.time + 60) / 60); - bool nextStep = false; - Q_FOREACH (DiveHandler *h, handles) { - if (IS_FP_SAME(h->pos().x(), xpos)) { - nextStep = true; - break; - } - } - if (nextStep) - continue; - - dp.time += 60; - plannerModel->editStop(row, dp); - } - } -} - -void ProfileWidget2::keyDeleteAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - int selCount = scene()->selectedItems().count(); - if (selCount) { - QVector<int> selectedIndexes; - Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - selectedIndexes.push_back(handles.indexOf(handler)); - handler->hide(); - } - } - plannerModel->removeSelectedPoints(selectedIndexes); - } -} - -void ProfileWidget2::keyEscAction() -{ - if (currentState != ADD && currentState != PLAN) - return; - - if (scene()->selectedItems().count()) { - scene()->clearSelection(); - return; - } - - DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); - if (plannerModel->isPlanner()) - plannerModel->cancelPlan(); -} - -void ProfileWidget2::plotPictures() -{ - Q_FOREACH (DivePictureItem *item, pictures) { - item->hide(); - item->deleteLater(); - } - pictures.clear(); - - if (printMode) - return; - - double x, y, lastX = -1.0, lastY = -1.0; - DivePictureModel *m = DivePictureModel::instance(); - for (int i = 0; i < m->rowCount(); i++) { - int offsetSeconds = m->index(i, 1).data(Qt::UserRole).value<int>(); - // it's a correct picture, but doesn't have a timestamp: only show on the widget near the - // information area. - if (!offsetSeconds) - continue; - DivePictureItem *item = new DivePictureItem(); - item->setPixmap(m->index(i, 0).data(Qt::DecorationRole).value<QPixmap>()); - item->setFileUrl(m->index(i, 1).data().toString()); - // let's put the picture at the correct time, but at a fixed "depth" on the profile - // not sure this is ideal, but it seems to look right. - x = timeAxis->posAtValue(offsetSeconds); - if (i == 0) - y = 10; - else if (fabs(x - lastX) < 4) - y = lastY + 3; - else - y = 10; - lastX = x; - lastY = y; - item->setPos(x, y); - scene()->addItem(item); - pictures.push_back(item); - } -} diff --git a/desktop-widgets/profile/profilewidget2.h b/desktop-widgets/profile/profilewidget2.h deleted file mode 100644 index f11ec5be1..000000000 --- a/desktop-widgets/profile/profilewidget2.h +++ /dev/null @@ -1,211 +0,0 @@ -#ifndef PROFILEWIDGET2_H -#define PROFILEWIDGET2_H - -#include <QGraphicsView> - -// /* 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. -// */ -#include "divelineitem.h" -#include "diveprofileitem.h" -#include "display.h" - -class RulerItem2; -struct dive; -struct plot_info; -class ToolTipItem; -class DiveMeanDepth; -class DiveReportedCeiling; -class DiveTextItem; -class TemperatureAxis; -class DiveEventItem; -class DivePlotDataModel; -class DivePixmapItem; -class DiveRectItem; -class DepthAxis; -class DiveCartesianAxis; -class DiveProfileItem; -class TimeAxis; -class DiveTemperatureItem; -class DiveHeartrateItem; -class PercentageItem; -class DiveGasPressureItem; -class DiveCalculatedCeiling; -class DiveCalculatedTissue; -class PartialPressureGasItem; -class PartialGasPressureAxis; -class AbstractProfilePolygonItem; -class TankItem; -class DiveHandler; -class QGraphicsSimpleTextItem; -class QModelIndex; -class DivePictureItem; - -class ProfileWidget2 : public QGraphicsView { - Q_OBJECT -public: - enum State { - EMPTY, - PROFILE, - EDIT, - ADD, - PLAN, - INVALID - }; - enum Items { - BACKGROUND, - PROFILE_Y_AXIS, - GAS_Y_AXIS, - TIME_AXIS, - DEPTH_CONTROLLER, - TIME_CONTROLLER, - COLUMNS - }; - - ProfileWidget2(QWidget *parent = 0); - void resetZoom(); - void plotDive(struct dive *d = 0, bool force = false); - virtual bool eventFilter(QObject *, QEvent *); - void setupItem(AbstractProfilePolygonItem *item, DiveCartesianAxis *hAxis, DiveCartesianAxis *vAxis, DivePlotDataModel *model, int vData, int hData, int zValue); - void setPrintMode(bool mode, bool grayscale = false); - bool getPrintMode(); - bool isPointOutOfBoundaries(const QPointF &point) const; - bool isPlanner(); - bool isAddOrPlanner(); - double getFontPrintScale(); - void setFontPrintScale(double scale); - void clearHandlers(); - void recalcCeiling(); - void setToolTipVisibile(bool visible); - State currentState; - -signals: - void fontPrintScaleChanged(double scale); - -public -slots: // Necessary to call from QAction's signals. - void settingsChanged(); - void setEmptyState(); - void setProfileState(); - void setPlanState(); - void setAddState(); - void changeGas(); - void addSetpointChange(); - void addBookmark(); - void hideEvents(); - void unhideEvents(); - void removeEvent(); - void editName(); - void makeFirstDC(); - void deleteCurrentDC(); - void pointInserted(const QModelIndex &parent, int start, int end); - void pointsRemoved(const QModelIndex &, int start, int end); - void plotPictures(); - void setReplot(bool state); - void replot(dive *d = 0); - - /* this is called for every move on the handlers. maybe we can speed up this a bit? */ - void recreatePlannedDive(); - - /* key press handlers */ - void keyEscAction(); - void keyDeleteAction(); - void keyUpAction(); - void keyDownAction(); - void keyLeftAction(); - void keyRightAction(); - - void divePlannerHandlerClicked(); - void divePlannerHandlerReleased(); - -protected: - virtual ~ProfileWidget2(); - virtual void resizeEvent(QResizeEvent *event); - virtual void wheelEvent(QWheelEvent *event); - virtual void mouseMoveEvent(QMouseEvent *event); - virtual void contextMenuEvent(QContextMenuEvent *event); - virtual void mouseDoubleClickEvent(QMouseEvent *event); - virtual void mousePressEvent(QMouseEvent *event); - virtual void mouseReleaseEvent(QMouseEvent *event); - -private: /*methods*/ - void fixBackgroundPos(); - void scrollViewTo(const QPoint &pos); - void setupSceneAndFlags(); - void setupItemSizes(); - void addItemsToScene(); - void setupItemOnScene(); - void disconnectTemporaryConnections(); - struct plot_data *getEntryFromPos(QPointF pos); - -private: - DivePlotDataModel *dataModel; - int zoomLevel; - qreal zoomFactor; - DivePixmapItem *background; - QString backgroundFile; - ToolTipItem *toolTipItem; - bool isPlotZoomed; - bool replotEnabled; - // All those here should probably be merged into one structure, - // So it's esyer to replicate for more dives later. - // In the meantime, keep it here. - struct plot_info plotInfo; - DepthAxis *profileYAxis; - PartialGasPressureAxis *gasYAxis; - TemperatureAxis *temperatureAxis; - TimeAxis *timeAxis; - DiveProfileItem *diveProfileItem; - DiveTemperatureItem *temperatureItem; - DiveMeanDepthItem *meanDepthItem; - DiveCartesianAxis *cylinderPressureAxis; - DiveGasPressureItem *gasPressureItem; - QList<DiveEventItem *> eventItems; - DiveTextItem *diveComputerText; - DiveCalculatedCeiling *diveCeiling; - DiveTextItem *gradientFactor; - QList<DiveCalculatedTissue *> allTissues; - DiveReportedCeiling *reportedCeiling; - PartialPressureGasItem *pn2GasItem; - PartialPressureGasItem *pheGasItem; - PartialPressureGasItem *po2GasItem; - PartialPressureGasItem *o2SetpointGasItem; - PartialPressureGasItem *ccrsensor1GasItem; - PartialPressureGasItem *ccrsensor2GasItem; - PartialPressureGasItem *ccrsensor3GasItem; - DiveCartesianAxis *heartBeatAxis; - DiveHeartrateItem *heartBeatItem; - DiveCartesianAxis *percentageAxis; - QList<DivePercentageItem *> allPercentages; - DiveAmbPressureItem *ambPressureItem; - DiveGFLineItem *gflineItem; - DiveLineItem *mouseFollowerVertical; - DiveLineItem *mouseFollowerHorizontal; - RulerItem2 *rulerItem; - TankItem *tankItem; - bool isGrayscale; - bool printMode; - - //specifics for ADD and PLAN - QList<DiveHandler *> handles; - QList<QGraphicsSimpleTextItem *> gases; - QList<DivePictureItem *> pictures; - void repositionDiveHandlers(); - int fixHandlerIndex(DiveHandler *activeHandler); - friend class DiveHandler; - QHash<Qt::Key, QAction *> actionsForKeys; - bool shouldCalculateMaxTime; - bool shouldCalculateMaxDepth; - int maxtime; - int maxdepth; - double fontPrintScale; -}; - -#endif // PROFILEWIDGET2_H diff --git a/desktop-widgets/profile/ruleritem.cpp b/desktop-widgets/profile/ruleritem.cpp deleted file mode 100644 index 830985552..000000000 --- a/desktop-widgets/profile/ruleritem.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include "ruleritem.h" -#include "preferences.h" -#include "mainwindow.h" -#include "profilewidget2.h" -#include "display.h" - -#include <qgraphicssceneevent.h> - -#include "profile.h" - -RulerNodeItem2::RulerNodeItem2() : - entry(NULL), - ruler(NULL), - timeAxis(NULL), - depthAxis(NULL) -{ - memset(&pInfo, 0, sizeof(pInfo)); - setRect(-8, -8, 16, 16); - setBrush(QColor(0xff, 0, 0, 127)); - setPen(QColor(Qt::red)); - setFlag(ItemIsMovable); - setFlag(ItemSendsGeometryChanges); - setFlag(ItemIgnoresTransformations); -} - -void RulerNodeItem2::setPlotInfo(plot_info &info) -{ - pInfo = info; - entry = pInfo.entry; -} - -void RulerNodeItem2::setRuler(RulerItem2 *r) -{ - ruler = r; -} - -void RulerNodeItem2::recalculate() -{ - struct plot_data *data = pInfo.entry + (pInfo.nr - 1); - uint16_t count = 0; - if (x() < 0) { - setPos(0, y()); - } else if (x() > timeAxis->posAtValue(data->sec)) { - setPos(timeAxis->posAtValue(data->sec), depthAxis->posAtValue(data->depth)); - } else { - data = pInfo.entry; - count = 0; - while (timeAxis->posAtValue(data->sec) < x() && count < pInfo.nr) { - data = pInfo.entry + count; - count++; - } - setPos(timeAxis->posAtValue(data->sec), depthAxis->posAtValue(data->depth)); - entry = data; - } -} - -void RulerNodeItem2::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - qreal x = event->scenePos().x(); - if (x < 0.0) - x = 0.0; - setPos(x, event->scenePos().y()); - recalculate(); - ruler->recalculate(); -} - -RulerItem2::RulerItem2() : source(new RulerNodeItem2()), - dest(new RulerNodeItem2()), - timeAxis(NULL), - depthAxis(NULL), - textItemBack(new QGraphicsRectItem(this)), - textItem(new QGraphicsSimpleTextItem(this)) -{ - memset(&pInfo, 0, sizeof(pInfo)); - source->setRuler(this); - dest->setRuler(this); - textItem->setFlag(QGraphicsItem::ItemIgnoresTransformations); - textItemBack->setBrush(QColor(0xff, 0xff, 0xff, 190)); - textItemBack->setPen(QColor(Qt::white)); - textItemBack->setFlag(QGraphicsItem::ItemIgnoresTransformations); - setPen(QPen(QColor(Qt::black), 0.0)); - connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); -} - -void RulerItem2::settingsChanged() -{ - ProfileWidget2 *profWidget = NULL; - if (scene() && scene()->views().count()) - profWidget = qobject_cast<ProfileWidget2 *>(scene()->views().first()); - - if (profWidget && profWidget->currentState == ProfileWidget2::PROFILE) - setVisible(prefs.rulergraph); - else - setVisible(false); -} - -void RulerItem2::recalculate() -{ - char buffer[500]; - QPointF tmp; - QFont font; - QFontMetrics fm(font); - - if (timeAxis == NULL || depthAxis == NULL || pInfo.nr == 0) - 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); - setLine(line); - compare_samples(source->entry, dest->entry, buffer, 500, 1); - text = QString(buffer); - - // draw text - QGraphicsView *view = scene()->views().first(); - QPoint begin = view->mapFromScene(mapToScene(startPoint)); - textItem->setText(text); - qreal tgtX = startPoint.x(); - const qreal diff = begin.x() + textItem->boundingRect().width(); - // clamp so that the text doesn't go out of the screen to the right - if (diff > view->width()) { - begin.setX(begin.x() - (diff - view->width())); - tgtX = mapFromScene(view->mapToScene(begin)).x(); - } - // always show the text bellow the lowest of the start and end points - qreal tgtY = (startPoint.y() >= endPoint.y()) ? startPoint.y() : endPoint.y(); - // this isn't exactly optimal, since we want to scale the 1.0, 4.0 distances as well - textItem->setPos(tgtX - 1.0, tgtY + 4.0); - - // setup the text background - textItemBack->setVisible(startPoint.x() != endPoint.x()); - textItemBack->setPos(textItem->x(), textItem->y()); - textItemBack->setRect(0, 0, textItem->boundingRect().width(), textItem->boundingRect().height()); -} - -RulerNodeItem2 *RulerItem2::sourceNode() const -{ - return source; -} - -RulerNodeItem2 *RulerItem2::destNode() const -{ - return dest; -} - -void RulerItem2::setPlotInfo(plot_info info) -{ - pInfo = info; - dest->setPlotInfo(info); - source->setPlotInfo(info); - dest->recalculate(); - source->recalculate(); - recalculate(); -} - -void RulerItem2::setAxis(DiveCartesianAxis *time, DiveCartesianAxis *depth) -{ - timeAxis = time; - depthAxis = depth; - dest->depthAxis = depth; - dest->timeAxis = time; - source->depthAxis = depth; - source->timeAxis = time; - recalculate(); -} - -void RulerItem2::setVisible(bool visible) -{ - QGraphicsLineItem::setVisible(visible); - source->setVisible(visible); - dest->setVisible(visible); -} diff --git a/desktop-widgets/profile/ruleritem.h b/desktop-widgets/profile/ruleritem.h deleted file mode 100644 index 4fad0451c..000000000 --- a/desktop-widgets/profile/ruleritem.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef RULERITEM_H -#define RULERITEM_H - -#include <QObject> -#include <QGraphicsEllipseItem> -#include <QGraphicsObject> -#include "divecartesianaxis.h" -#include "display.h" - -struct plot_data; -class RulerItem2; - -class RulerNodeItem2 : public QObject, public QGraphicsEllipseItem { - Q_OBJECT - friend class RulerItem2; - -public: - explicit RulerNodeItem2(); - void setRuler(RulerItem2 *r); - void setPlotInfo(struct plot_info &info); - void recalculate(); - -protected: - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); -private: - struct plot_info pInfo; - struct plot_data *entry; - RulerItem2 *ruler; - DiveCartesianAxis *timeAxis; - DiveCartesianAxis *depthAxis; -}; - -class RulerItem2 : public QObject, public QGraphicsLineItem { - Q_OBJECT -public: - explicit RulerItem2(); - void recalculate(); - - void setPlotInfo(struct plot_info pInfo); - RulerNodeItem2 *sourceNode() const; - RulerNodeItem2 *destNode() const; - void setAxis(DiveCartesianAxis *time, DiveCartesianAxis *depth); - void setVisible(bool visible); - -public -slots: - void settingsChanged(); - -private: - struct plot_info pInfo; - QPointF startPoint, endPoint; - RulerNodeItem2 *source, *dest; - QString text; - DiveCartesianAxis *timeAxis; - DiveCartesianAxis *depthAxis; - QGraphicsRectItem *textItemBack; - QGraphicsSimpleTextItem *textItem; -}; -#endif diff --git a/desktop-widgets/profile/tankitem.cpp b/desktop-widgets/profile/tankitem.cpp deleted file mode 100644 index c0e75a371..000000000 --- a/desktop-widgets/profile/tankitem.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "tankitem.h" -#include "diveplotdatamodel.h" -#include "divetextitem.h" -#include "profile.h" -#include <QPen> - -TankItem::TankItem(QObject *parent) : - QGraphicsRectItem(), - dataModel(0), - pInfoEntry(0), - pInfoNr(0) -{ - height = 3; - QColor red(PERSIANRED1); - QColor blue(AIR_BLUE); - QColor yellow(NITROX_YELLOW); - QColor green(NITROX_GREEN); - QLinearGradient nitroxGradient(QPointF(0, 0), QPointF(0, height)); - nitroxGradient.setColorAt(0.0, green); - nitroxGradient.setColorAt(0.49, green); - nitroxGradient.setColorAt(0.5, yellow); - nitroxGradient.setColorAt(1.0, yellow); - nitrox = nitroxGradient; - oxygen = green; - QLinearGradient trimixGradient(QPointF(0, 0), QPointF(0, height)); - trimixGradient.setColorAt(0.0, green); - trimixGradient.setColorAt(0.49, green); - trimixGradient.setColorAt(0.5, red); - trimixGradient.setColorAt(1.0, red); - trimix = trimixGradient; - air = blue; - memset(&diveCylinderStore, 0, sizeof(diveCylinderStore)); -} - -TankItem::~TankItem() -{ - // Should this be clear_dive(diveCylinderStore)? - for (int i = 0; i < MAX_CYLINDERS; i++) - free((void *)diveCylinderStore.cylinder[i].type.description); -} - -void TankItem::setData(DivePlotDataModel *model, struct plot_info *plotInfo, struct dive *d) -{ - free(pInfoEntry); - // the plotInfo and dive structures passed in could become invalid before we stop using them, - // so copy the data that we need - int size = plotInfo->nr * sizeof(plotInfo->entry[0]); - pInfoEntry = (struct plot_data *)malloc(size); - pInfoNr = plotInfo->nr; - memcpy(pInfoEntry, plotInfo->entry, size); - copy_cylinders(d, &diveCylinderStore, false); - dataModel = model; - connect(dataModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(modelDataChanged(QModelIndex, QModelIndex)), Qt::UniqueConnection); - modelDataChanged(); -} - -void TankItem::createBar(qreal x, qreal w, struct gasmix *gas) -{ - // pick the right gradient, size, position and text - QGraphicsRectItem *rect = new QGraphicsRectItem(x, 0, w, height, this); - if (gasmix_is_air(gas)) - rect->setBrush(air); - else if (gas->he.permille) - rect->setBrush(trimix); - else if (gas->o2.permille == 1000) - rect->setBrush(oxygen); - else - rect->setBrush(nitrox); - rect->setPen(QPen(QBrush(), 0.0)); // get rid of the thick line around the rectangle - rects.push_back(rect); - DiveTextItem *label = new DiveTextItem(rect); - label->setText(gasname(gas)); - label->setBrush(Qt::black); - label->setPos(x + 1, 0); - label->setAlignment(Qt::AlignBottom | Qt::AlignRight); - label->setZValue(101); -} - -void TankItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - // We don't have enougth data to calculate things, quit. - - if (!dataModel || !pInfoEntry || !pInfoNr) - return; - - // remove the old rectangles - foreach (QGraphicsRectItem *r, rects) { - delete(r); - } - rects.clear(); - - // walk the list and figure out which tanks go where - struct plot_data *entry = pInfoEntry; - int cylIdx = entry->cylinderindex; - int i = -1; - int startTime = 0; - struct gasmix *gas = &diveCylinderStore.cylinder[cylIdx].gasmix; - qreal width, left; - while (++i < pInfoNr) { - entry = &pInfoEntry[i]; - if (entry->cylinderindex == cylIdx) - continue; - width = hAxis->posAtValue(entry->sec) - hAxis->posAtValue(startTime); - left = hAxis->posAtValue(startTime); - createBar(left, width, gas); - cylIdx = entry->cylinderindex; - gas = &diveCylinderStore.cylinder[cylIdx].gasmix; - startTime = entry->sec; - } - width = hAxis->posAtValue(entry->sec) - hAxis->posAtValue(startTime); - left = hAxis->posAtValue(startTime); - createBar(left, width, gas); -} - -void TankItem::setHorizontalAxis(DiveCartesianAxis *horizontal) -{ - hAxis = horizontal; - connect(hAxis, SIGNAL(sizeChanged()), this, SLOT(modelDataChanged())); - modelDataChanged(); -} diff --git a/desktop-widgets/profile/tankitem.h b/desktop-widgets/profile/tankitem.h deleted file mode 100644 index fd685fc82..000000000 --- a/desktop-widgets/profile/tankitem.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef TANKITEM_H -#define TANKITEM_H - -#include <QGraphicsItem> -#include <QModelIndex> -#include <QBrush> -#include "divelineitem.h" -#include "divecartesianaxis.h" -#include "dive.h" - -class TankItem : public QObject, public QGraphicsRectItem -{ - Q_OBJECT - -public: - explicit TankItem(QObject *parent = 0); - ~TankItem(); - void setHorizontalAxis(DiveCartesianAxis *horizontal); - void setData(DivePlotDataModel *model, struct plot_info *plotInfo, struct dive *d); - -signals: - -public slots: - virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - -private: - void createBar(qreal x, qreal w, struct gasmix *gas); - DivePlotDataModel *dataModel; - DiveCartesianAxis *hAxis; - int hDataColumn; - struct dive diveCylinderStore; - struct plot_data *pInfoEntry; - int pInfoNr; - qreal height; - QBrush air, nitrox, oxygen, trimix; - QList<QGraphicsRectItem *> rects; -}; - -#endif // TANKITEM_H diff --git a/desktop-widgets/simplewidgets.cpp b/desktop-widgets/simplewidgets.cpp index 62a9cc646..43ad1ddc0 100644 --- a/desktop-widgets/simplewidgets.cpp +++ b/desktop-widgets/simplewidgets.cpp @@ -14,7 +14,7 @@ #include "libdivecomputer/parser.h" #include "divelistview.h" #include "display.h" -#include "profile/profilewidget2.h" +#include "profile-widget/profilewidget2.h" #include "undocommands.h" class MinMaxAvgWidgetPrivate { diff --git a/desktop-widgets/socialnetworks.cpp b/desktop-widgets/socialnetworks.cpp index 6e191267a..0794c764e 100644 --- a/desktop-widgets/socialnetworks.cpp +++ b/desktop-widgets/socialnetworks.cpp @@ -16,7 +16,7 @@ #include <QMessageBox> #include <QInputDialog> #include "mainwindow.h" -#include "profile/profilewidget2.h" +#include "profile-widget/profilewidget2.h" #include "pref.h" #include "helpers.h" #include "ui_socialnetworksdialog.h" |