Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Allow Text meter widgets to be of same size and well aligned (#3506)
The y scale is computed from the font instead of only from the current content, to avoid having different scales between different Text widgets of the same size. For example, "kph" has a high k and low p, resulting in a text widget with bigger bounding box, and thus smaller scale than a text widget with "watts". Options are added for alignment and for text width, to help align the different entries. The formatting of metrics with the integer part as Text and fraction as AltText is more systematic and it is possible to add an AltTextSuffix, to specify the units when they are not provided in VideoWindow. The visibility of the BoundingRect and Background car be controlled.
  • Loading branch information
michelrdagenais committed Jun 24, 2020
1 parent 028e822 commit a270656
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 61 deletions.
55 changes: 38 additions & 17 deletions src/Train/MeterWidget.cpp
Expand Up @@ -54,6 +54,7 @@ MeterWidget::MeterWidget(QString Name, QWidget *parent, QString Source) : QWidge
m_SubRange = 10;
m_Zoom = 16;
boundingRectVisibility = false;
backgroundVisibility = false;
forceSquareRatio = true;
}

Expand Down Expand Up @@ -117,19 +118,29 @@ QSize MeterWidget::minimumSize() const
void MeterWidget::paintEvent(QPaintEvent* paintevent)
{
Q_UNUSED(paintevent);
if(!boundingRectVisibility && !backgroundVisibility) return;

QPainter painter(this);
painter.setClipRegion(videoContainerRegion);
painter.setRenderHint(QPainter::Antialiasing);

int radius = qMin(m_Width, m_Height) * 0.1;
if(backgroundVisibility) painter.setBrush(QBrush(m_BackgroundColor));
else painter.setBrush(Qt::NoBrush);

if (boundingRectVisibility)
{
m_OutlinePen = QPen(boundingRectColor);
m_OutlinePen = QPen(m_BoundingRectColor);
m_OutlinePen.setWidth(2);
m_OutlinePen.setStyle(Qt::SolidLine);

//painter
QPainter painter(this);
painter.setClipRegion(videoContainerRegion);
painter.setRenderHint(QPainter::Antialiasing);

painter.setPen(m_OutlinePen);
painter.drawRect (1, 1, m_Width-2, m_Height-2);
painter.drawRoundedRect (1, 1, m_Width-2, m_Height-2, radius, radius);
}
else
{
painter.setPen(Qt::NoPen);
painter.drawRoundedRect (0, 0, m_Width, m_Height, radius, radius);
}
}

Expand All @@ -141,7 +152,7 @@ void MeterWidget::setColor(QColor mainColor)
void MeterWidget::setBoundingRectVisibility(bool show, QColor boundingRectColor)
{
this->boundingRectVisibility=show;
this->boundingRectColor = boundingRectColor;
this->m_BoundingRectColor = boundingRectColor;
}

TextMeterWidget::TextMeterWidget(QString Name, QWidget *parent, QString Source) : MeterWidget(Name, parent, Source)
Expand All @@ -154,7 +165,6 @@ 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);
Expand All @@ -164,21 +174,32 @@ void TextMeterWidget::paintEvent(QPaintEvent* paintevent)
painter.setClipRegion(videoContainerRegion);
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);
QRectF ValueBoundingRct = my_painterPath.boundingRect();

// define scale
// We use leading whitespace for alignment which boundingRect() does not count
ValueBoundingRct.setLeft(qMin(0.0, ValueBoundingRct.left()));

// The scale should not change with the string content, we use Font ascent and descent
ValueBoundingRct.setTop(qMin(ValueBoundingRct.top(), qreal(qMin(-QFontMetrics(m_MainFont).ascent(),
-QFontMetrics(m_AltFont).ascent()))));
ValueBoundingRct.setBottom(qMax(ValueBoundingRct.bottom(), qreal(qMax(QFontMetrics(m_MainFont).descent(),
QFontMetrics(m_AltFont).descent()))));

// scale to fit the available space
float fontscale = qMin(m_Width / ValueBoundingRct.width(), m_Height / ValueBoundingRct.height());
painter.scale(fontscale, fontscale);
painter.translate(-ValueBoundingRct.x()+(m_Width/fontscale - ValueBoundingRct.width())/2, -ValueBoundingRct.y()+(m_Height/fontscale - ValueBoundingRct.height())/2);

float translationX = -ValueBoundingRct.x(); // AlignLeft

if(alignment == Qt::AlignHCenter)
translationX += (m_Width/fontscale - ValueBoundingRct.width())/2;
else if(alignment == Qt::AlignRight)
translationX += (m_Width/fontscale - ValueBoundingRct.width());

painter.translate(translationX, -ValueBoundingRct.y()+(m_Height/fontscale - ValueBoundingRct.height())/2);

// Write Value
painter.setPen(m_OutlinePen);
Expand Down
7 changes: 5 additions & 2 deletions src/Train/MeterWidget.h
Expand Up @@ -51,7 +51,9 @@ class MeterWidget : public QWidget
void setBoundingRectVisibility(bool show, QColor boundingRectColor = QColor(255,0,0,255));

float Value, ValueMin, ValueMax;
QString Text, AltText;
QString Text, AltText, AltTextSuffix;
Qt::Alignment alignment;
int textWidth;

protected:
QString m_Name;
Expand All @@ -72,6 +74,7 @@ class MeterWidget : public QWidget
QColor m_ScaleColor;
QColor m_OutlineColor;
QColor m_BackgroundColor;
QColor m_BoundingRectColor;
QFont m_MainFont;
QFont m_AltFont;

Expand All @@ -81,8 +84,8 @@ class MeterWidget : public QWidget
QPen m_OutlinePen;
QPen m_ScalePen;

bool backgroundVisibility;
bool boundingRectVisibility;
QColor boundingRectColor;

friend class VideoLayoutParser;
};
Expand Down
89 changes: 71 additions & 18 deletions src/Train/VideoLayoutParser.cpp
Expand Up @@ -37,23 +37,23 @@ VideoLayoutParser::VideoLayoutParser (QList<MeterWidget*>* metersWidget, QList<Q

void VideoLayoutParser::SetDefaultValues()
{
if (meterWidget)
{
meterWidget->m_RelativeWidth = 20.0;
meterWidget->m_RelativeHeight = 20.0;
meterWidget->m_RelativePosX = 50.0;
meterWidget->m_RelativePosY = 80.0;

meterWidget->m_RangeMin = 0.0;
meterWidget->m_RangeMax = 80.0;
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,0);
meterWidget->m_MainFont = QFont(meterWidget->font().family(), 64);
meterWidget->m_AltFont = QFont(meterWidget->font().family(), 48);
meterWidget->m_VideoContainer = VideoContainer;
}
meterWidget->m_RelativeWidth = 20.0;
meterWidget->m_RelativeHeight = 20.0;
meterWidget->m_RelativePosX = 50.0;
meterWidget->m_RelativePosY = 80.0;
meterWidget->m_RangeMin = 0.0;
meterWidget->m_RangeMax = 80.0;
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,0);
meterWidget->m_BoundingRectColor = QColor(150,150,150,100);
meterWidget->m_MainFont = QFont(meterWidget->font().family(), 64);
meterWidget->m_AltFont = QFont(meterWidget->font().family(), 48);
meterWidget->m_VideoContainer = VideoContainer;
meterWidget->Text = "";
meterWidget->AltText = "";
meterWidget->AltTextSuffix = "";
}

QColor GetColorFromFields(const QXmlAttributes& qAttributes)
Expand All @@ -77,6 +77,15 @@ bool VideoLayoutParser::startElement( const QString&, const QString&,
const QString& qName,
const QXmlAttributes& qAttributes)
{
QString source;
QString meterName;
QString meterType;
QString container; // will be "Video" when not defined otherwise another meter name (allows positioning of one meter inside another one)
int textWidth;
Qt::Alignment alignment;
bool boundingRectVisibility;
bool backgroundVisibility;

if(skipLayout) return true;

buffer.clear();
Expand Down Expand Up @@ -114,6 +123,32 @@ bool VideoLayoutParser::startElement( const QString&, const QString&,
else
meterType = QString("Text");

i = qAttributes.index("alignment");
if(i >= 0)
if(qAttributes.value(i) == QString("AlignLeft")) alignment = Qt::AlignLeft;
else if(qAttributes.value(i) == QString("AlignRight")) alignment = Qt::AlignRight;
else alignment = Qt::AlignHCenter;
else
alignment = Qt::AlignHCenter;

i = qAttributes.index("textWidth");
if(i >= 0)
textWidth = qAttributes.value(i).toInt();
else
textWidth = 0;

i = qAttributes.index("BoundingRect");
if(i >= 0 && qAttributes.value(i) == QString("true"))
boundingRectVisibility = true;
else
boundingRectVisibility = false;

i = qAttributes.index("Background");
if(i >= 0 && qAttributes.value(i) == QString("true"))
backgroundVisibility = true;
else
backgroundVisibility = false;

//TODO: allow creation of meter when container will be created later
QWidget* containerWidget = NULL;
if (container == QString("Video"))
Expand Down Expand Up @@ -159,7 +194,14 @@ bool VideoLayoutParser::startElement( const QString&, const QString&,
qDebug() << QObject::tr("Error creating meter");
}

SetDefaultValues();
if (meterWidget)
{
SetDefaultValues();
meterWidget->textWidth = textWidth;
meterWidget->alignment = alignment;
meterWidget->boundingRectVisibility = boundingRectVisibility;
meterWidget->backgroundVisibility = backgroundVisibility;
}
}
else if ((qName == "MainColor") && meterWidget)
meterWidget->m_MainColor = GetColorFromFields(qAttributes);
Expand All @@ -169,6 +211,8 @@ bool VideoLayoutParser::startElement( const QString&, const QString&,
meterWidget->m_ScaleColor = GetColorFromFields(qAttributes);
else if ((qName == "BackgroundColor") && meterWidget)
meterWidget->m_BackgroundColor = GetColorFromFields(qAttributes);
else if ((qName == "BoundingRectColor") && meterWidget)
meterWidget->m_BoundingRectColor = GetColorFromFields(qAttributes);

else if ((qName == "RelativeSize") && meterWidget)
{
Expand Down Expand Up @@ -204,6 +248,8 @@ bool VideoLayoutParser::startElement( const QString&, const QString&,
if ((i = qAttributes.index("Size")) >= 0)
FontSize = qAttributes.value(i).toInt();
meterWidget->m_MainFont = QFont(FontName, FontSize);
// Set fixed width, otherwise the meter digits keep moving sideways from a thin "1" to a fat "5"
meterWidget->m_MainFont.setFixedPitch(true);
}
else if ((qName == "AltFont") && meterWidget)
{
Expand All @@ -215,6 +261,11 @@ bool VideoLayoutParser::startElement( const QString&, const QString&,
if ((i = qAttributes.index("Size")) >= 0)
FontSize = qAttributes.value(i).toInt();
meterWidget->m_AltFont = QFont(FontName, FontSize);
meterWidget->m_AltFont.setFixedPitch(true);
}
else if(qName != "layouts" && qName != "Text" && qName != "AltText" && qName != "Angle" && qName != "SubRange")
{
qDebug() << QObject::tr("Unknown start element ") << qName;
}

return true;
Expand All @@ -241,6 +292,8 @@ bool VideoLayoutParser::endElement( const QString&, const QString&, const QStrin
meterWidget->m_Zoom = buffer.toInt();
else if (qName == "Text")
meterWidget->Text = QString(buffer);
else if (qName == "AltText")
meterWidget->AltTextSuffix = QString(buffer);

else if (qName == "meter")
{
Expand Down
9 changes: 1 addition & 8 deletions src/Train/VideoLayoutParser.h
Expand Up @@ -46,18 +46,11 @@ class VideoLayoutParser : public QXmlDefaultHandler
QList<QString>* layoutNames;
QWidget* VideoContainer;

MeterWidget* meterWidget;
QString buffer;

int nonameindex;
int layoutPosition;
bool skipLayout;

QString source;
QString meterName;
QString meterType;
QString container; // will be "Video" when not defined otherwise another meter name (allows positioning of one meter inside another one)

MeterWidget* meterWidget;
};

#endif // _VideoLayoutParser_h
Expand Down

0 comments on commit a270656

Please sign in to comment.