summaryrefslogtreecommitdiffstats
path: root/profile-widget/divecartesianaxis.cpp
diff options
context:
space:
mode:
authorGravatar Tomaz Canabrava <tomaz.canabrava@intel.com>2015-09-03 15:56:37 -0300
committerGravatar Dirk Hohndel <dirk@hohndel.org>2015-10-30 10:36:49 -0700
commit1d6683f3e07d9a73af5fab702bc3a551ec7dabc9 (patch)
tree80a64ced06489bf0dca866b2097ca7048b1f0ab8 /profile-widget/divecartesianaxis.cpp
parent50ec7200e66637abefe685e1875f3d4de2101158 (diff)
downloadsubsurface-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 'profile-widget/divecartesianaxis.cpp')
-rw-r--r--profile-widget/divecartesianaxis.cpp459
1 files changed, 459 insertions, 0 deletions
diff --git a/profile-widget/divecartesianaxis.cpp b/profile-widget/divecartesianaxis.cpp
new file mode 100644
index 000000000..bf5a5380c
--- /dev/null
+++ b/profile-widget/divecartesianaxis.cpp
@@ -0,0 +1,459 @@
+#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();
+}