diff --git a/src/Resources/xml/video-layout.xml b/src/Resources/xml/video-layout.xml
index d87fedfea..5f5dad050 100644
--- a/src/Resources/xml/video-layout.xml
+++ b/src/Resources/xml/video-layout.xml
@@ -83,4 +83,13 @@
load
+
+
+
+
+
+
+
+
+
diff --git a/src/Train/MeterWidget.cpp b/src/Train/MeterWidget.cpp
index 35305c812..a5ae0f586 100644
--- a/src/Train/MeterWidget.cpp
+++ b/src/Train/MeterWidget.cpp
@@ -19,6 +19,8 @@
#include
#include
#include "MeterWidget.h"
+#include "ErgFile.h"
+#include "Context.h"
MeterWidget::MeterWidget(QString Name, QWidget *parent, QString Source) : QWidget(parent), m_Name(Name), m_container(parent), m_Source(Source)
{
@@ -37,12 +39,13 @@ MeterWidget::MeterWidget(QString Name, QWidget *parent, QString Source) : QWidge
m_OutlineColor = QColor(128,128,128,180);
m_MainFont = QFont(this->font().family(), 64);
m_AltFont = QFont(this->font().family(), 48);
- m_BackgroundColor = QColor(96, 96, 96, 200);
+ m_BackgroundColor = QColor(96, 96, 96, 0);
m_RangeMin = 0;
m_RangeMax = 100;
m_Angle = 180.0;
m_SubRange = 10;
boundingRectVisibility = false;
+ forceSquareRatio = true;
}
void MeterWidget::SetRelativeSize(float RelativeWidth, float RelativeHeight)
@@ -75,7 +78,15 @@ void MeterWidget::AdjustSizePos()
void MeterWidget::ComputeSize()
{
- m_Width = m_Height = (m_container->width() * m_RelativeWidth + m_container->height() * m_RelativeHeight) / 2;
+ if (forceSquareRatio)
+ {
+ m_Width = m_Height = (m_container->width() * m_RelativeWidth + m_container->height() * m_RelativeHeight) / 2;
+ }
+ else
+ {
+ m_Width = m_container->width() * m_RelativeWidth;
+ m_Height = m_container->height() * m_RelativeHeight;
+ }
}
QSize MeterWidget::sizeHint() const
@@ -119,12 +130,7 @@ void MeterWidget::setBoundingRectVisibility(bool show, QColor boundingRectColor
TextMeterWidget::TextMeterWidget(QString Name, QWidget *parent, QString Source) : MeterWidget(Name, parent, Source)
{
-}
-
-void TextMeterWidget::ComputeSize()
-{
- m_Width = m_container->width() * m_RelativeWidth;
- m_Height = m_container->height() * m_RelativeHeight;
+ forceSquareRatio = false;
}
void TextMeterWidget::paintEvent(QPaintEvent* paintevent)
@@ -132,6 +138,7 @@ void TextMeterWidget::paintEvent(QPaintEvent* paintevent)
MeterWidget::paintEvent(paintevent);
m_MainBrush = QBrush(m_MainColor);
+ m_BackgroundBrush = QBrush(m_BackgroundColor);
m_OutlinePen = QPen(m_OutlineColor);
m_OutlinePen.setWidth(1);
m_OutlinePen.setStyle(Qt::SolidLine);
@@ -140,6 +147,12 @@ void TextMeterWidget::paintEvent(QPaintEvent* paintevent)
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
+ //draw background
+ painter.setPen(Qt::NoPen);
+ painter.setBrush(m_BackgroundBrush);
+ if (Text!=QString(""))
+ painter.drawRect (0, 0, m_Width, m_Height);
+
QPainterPath my_painterPath;
my_painterPath.addText(QPointF(0,0),m_MainFont,Text);
my_painterPath.addText(QPointF(QFontMetrics(m_MainFont).width(Text), 0),m_AltFont,AltText);
@@ -297,3 +310,94 @@ void NeedleMeterWidget::paintEvent(QPaintEvent* paintevent)
painter.drawPath(my_painterPath);
painter.restore();
}
+
+ElevationMeterWidget::ElevationMeterWidget(QString Name, QWidget *parent, QString Source, Context *context) : MeterWidget(Name, parent, Source), context(context)
+{
+ forceSquareRatio = false;
+ gradientValue = 0.0;
+}
+
+void ElevationMeterWidget::paintEvent(QPaintEvent* paintevent)
+{
+ // TODO : show Power when not in slope simulation mode
+ if (!context || !context->currentErgFile() || context->currentErgFile()->Points.size()<=1)
+ return;
+
+ MeterWidget::paintEvent(paintevent);
+
+ m_MainBrush = QBrush(m_MainColor);
+ m_BackgroundBrush = QBrush(m_BackgroundColor);
+ m_OutlinePen = QPen(m_OutlineColor);
+ m_OutlinePen.setWidth(1);
+ m_OutlinePen.setStyle(Qt::SolidLine);
+
+ //painter
+ QPainter painter(this);
+ painter.setRenderHint(QPainter::Antialiasing);
+
+ // Find min/max
+ double minX, minY, maxX, maxY, cyclistX=0.0;
+ // (based on ErgFilePlot.cpp)
+ minX=maxX=context->currentErgFile()->Points[0].x; // meters
+ minY=maxY=context->currentErgFile()->Points[0].y; // meters or altitude???
+ foreach(ErgFilePoint x, context->currentErgFile()->Points)
+ {
+ if (x.y > maxY) maxY = x.y;
+ if (x.x > maxX) maxX = x.x;
+ if (x.y < minY) minY = x.y;
+ if (x.x < minX) minX = x.x;
+ }
+ // check if slope shown will not be too inconsistent (based on widget's width/height ratio)
+ // we accept 20 times i.e. 5% gradient will be shown as 45°
+ if ( m_Width!=0 && (maxY-minY) / 0.05 < (double)m_Height * 0.80 * (maxX-minX) / (double)m_Width)
+ maxY = minY + (double)m_Height * 0.80 * (maxX-minX) / (double)m_Width * 0.05;
+ double bubbleSize = (double)m_Height*0.010f;
+ minY -= (maxY-minY) * 0.20f; // add 20% as bottom headroom (slope gradient will be shown there in a bubble)
+
+ // this->Value should hold the current distance in meters.
+ cyclistX = (this->Value * 1000.0 - minX) * (double)m_Width / (maxX-minX);
+
+ //Get point to create the polygon
+ QPolygon polygon;
+ polygon << QPoint(0.0, (double)m_Height);
+ double x, y, pt=0;
+ double nextX = 1;
+ for( pt=0; pt < context->currentErgFile()->Points.size(); pt++)
+ {
+ for ( ; x < nextX && pt < context->currentErgFile()->Points.size(); pt++)
+ {
+ x = (context->currentErgFile()->Points[pt].x - minX) * (double)m_Width / (maxX-minX);
+ y = (context->currentErgFile()->Points[pt].y - minY) * (double)m_Height / (maxY-minY);
+ }
+ // Add points to polygon only once every time the x coordinate integer part changes.
+ polygon << QPoint(x, (double)m_Height - y);
+ nextX = floor(x) + 1.0;
+ }
+ polygon << QPoint((double) m_Width, (double)m_Height);
+ polygon << QPoint(fmin((double) m_Width,cyclistX+bubbleSize), (double)m_Height);
+ polygon << QPoint(cyclistX, (double)m_Height-bubbleSize);
+ polygon << QPoint(fmax(0.0, cyclistX-bubbleSize), (double)m_Height);
+
+ painter.setPen(m_OutlinePen);
+ painter.setBrush(m_BackgroundBrush);
+ painter.drawPolygon(polygon);
+
+ m_OutlinePen = QPen(m_MainColor);
+ m_OutlinePen.setWidth(1);
+ m_OutlinePen.setStyle(Qt::SolidLine);
+ painter.setPen(m_OutlinePen);
+ painter.drawLine(cyclistX, 0.0, cyclistX, (double)m_Height-bubbleSize);
+
+ //Cosmetic enhancment: Display grade as #.#%
+ std::string sGrad;
+ QString s_grad ="";
+ s_grad = ((-1.0 < this->gradientValue && this->gradientValue < 0.0)?QString("-"):QString("")) + QString::number((int) this->gradientValue);
+ s_grad += QString(".") + QString::number(abs((int)(this->gradientValue * 10.0) % 10)) + QString("%");
+
+ // Display gradient text to the right of the line until the middle, then display to the left of the line
+ if (cyclistX < m_Width*0.5) {
+ painter.drawText((double)cyclistX+5, ((double)m_Height * 0.95), s_grad);
+ } else {
+ painter.drawText((double)cyclistX-45, ((double)m_Height * 0.95), s_grad);
+ }
+}
diff --git a/src/Train/MeterWidget.h b/src/Train/MeterWidget.h
index 44eae3469..b699424df 100644
--- a/src/Train/MeterWidget.h
+++ b/src/Train/MeterWidget.h
@@ -20,6 +20,7 @@
#define _MeterWidget_h 1
#include
+#include "Context.h"
class MeterWidget : public QWidget
{
@@ -59,6 +60,7 @@ class MeterWidget : public QWidget
float m_RangeMin, m_RangeMax;
float m_Angle;
int m_SubRange;
+ bool forceSquareRatio;
QColor m_MainColor;
QColor m_ScaleColor;
@@ -83,7 +85,6 @@ class TextMeterWidget : public MeterWidget
{
public:
explicit TextMeterWidget(QString name, QWidget *parent = 0, QString Source = QString("None"));
- virtual void ComputeSize();
virtual void paintEvent(QPaintEvent* paintevent);
};
@@ -109,5 +110,15 @@ class NeedleMeterWidget : public MeterWidget
virtual void paintEvent(QPaintEvent* paintevent);
};
+class ElevationMeterWidget : public MeterWidget
+{
+ public:
+ explicit ElevationMeterWidget(QString name, QWidget *parent = 0, QString Source = QString("None"), Context *context = NULL);
+ virtual void paintEvent(QPaintEvent* paintevent);
+ float gradientValue;
+ void setContext(Context *context) { this->context = context; }
+ private:
+ Context *context;
+};
#endif // _MeterWidget_h
diff --git a/src/Train/VideoLayoutParser.cpp b/src/Train/VideoLayoutParser.cpp
index 002c220bc..43646e6a8 100644
--- a/src/Train/VideoLayoutParser.cpp
+++ b/src/Train/VideoLayoutParser.cpp
@@ -47,7 +47,7 @@ void VideoLayoutParser::SetDefaultValues()
meterWidget->m_MainColor = QColor(255,0,0,200);
meterWidget->m_ScaleColor = QColor(255,255,255,200);
meterWidget->m_OutlineColor = QColor(100,100,100,200);
- meterWidget->m_BackgroundColor = QColor(100,100,100,200);
+ meterWidget->m_BackgroundColor = QColor(100,100,100,0);
meterWidget->m_MainFont = QFont(meterWidget->font().family(), 64);
meterWidget->m_AltFont = QFont(meterWidget->font().family(), 48);
}
@@ -134,6 +134,10 @@ bool VideoLayoutParser::startElement( const QString&, const QString&,
{
meterWidget = new CircularBargraphMeterWidget(meterName, containerWidget, source);
}
+ else if (meterType == QString("Elevation"))
+ {
+ meterWidget = new ElevationMeterWidget(meterName, containerWidget, source);
+ }
else
{
qDebug() << QObject::tr("Error creating meter");
diff --git a/src/Train/VideoWindow.cpp b/src/Train/VideoWindow.cpp
index 7e98bc865..ab35a9f95 100644
--- a/src/Train/VideoWindow.cpp
+++ b/src/Train/VideoWindow.cpp
@@ -316,6 +316,23 @@ void VideoWindow::telemetryUpdate(RealtimeData rtd)
p_meterWidget->Text = QString::number((int)p_meterWidget->Value);
p_meterWidget->AltText = QString(".") +QString::number((int)(p_meterWidget->Value * 10.0) - (((int) p_meterWidget->Value) * 10)) + (metric ? tr(" kph") : tr(" mph"));
}
+ else if (p_meterWidget->Source() == QString("Elevation"))
+ {
+ // Do not show in ERG mode
+ if (rtd.mode == ERG || rtd.mode == MRC)
+ {
+ p_meterWidget->setWindowOpacity(0); // Hide the widget
+ }
+ p_meterWidget->Value = rtd.getDistance();
+ ElevationMeterWidget* elevationMeterWidget = dynamic_cast(p_meterWidget);
+ if (!elevationMeterWidget)
+ qDebug() << "Error: Elevation keyword used but widget is not elevation type";
+ else
+ {
+ elevationMeterWidget->setContext(context);
+ elevationMeterWidget->gradientValue = rtd.getSlope();
+ }
+ }
else if (p_meterWidget->Source() == QString("Cadence"))
{
p_meterWidget->Value = rtd.getCadence();