mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 00:28:42 +00:00
Dialwindow font scaling (v2) (#4511)
* DialWindow: Scaling font in both dimensions Currently the font in DialWindow is only scaled to make the text fit into the label vertically. This commit scales the font in both dimensions and prevents cutting off the content. The font is rescaled * If the DialWindow itself is resized * If the text set and is longer than the previous one * Every 10 text-changes * Trainmode: Added a global setting to finetune telemetry font scaling * Added option to Options -> Train -> Preferences for configuring the font scaling strategy of Telemetry / DialWindows * "Height only" (default, as before) * "Height and width" * Changed the layout of this Page to QFormLayout to match the other Pages
This commit is contained in:
committed by
GitHub
parent
fb768969ee
commit
ad6a0c30e2
@@ -238,6 +238,7 @@
|
||||
#define TRAIN_USESIMULATEDSPEED "<global-trainmode>train/usesimulatedspeed"
|
||||
#define TRAIN_USESIMULATEDHYPOXIA "<global-trainmode>train/usesimulatedhypoxia"
|
||||
#define TRAIN_COALESCE_SECTIONS "<global-trainmode>train/coalesceSections"
|
||||
#define TRAIN_TELEMETRY_FONT_SCALING "<global-trainmode>train/telemetryFontScaling"
|
||||
#define GC_REMOTE_START "<global-trainmode>remote/start"
|
||||
#define GC_REMOTE_STOP "<global-trainmode>remote/stop"
|
||||
#define GC_REMOTE_LAP "<global-trainmode>remote/lap"
|
||||
|
||||
@@ -757,6 +757,12 @@ TrainOptionsPage::TrainOptionsPage(QWidget *parent, Context *context) : QWidget(
|
||||
coalesce = new QCheckBox(tr("Coalesce contiguous sections of same wattage"), this);
|
||||
coalesce->setChecked(appsettings->value(this, TRAIN_COALESCE_SECTIONS, false).toBool());
|
||||
|
||||
telemetryScalingLabel = new QLabel(tr("Telemetry font scaling"));
|
||||
telemetryScaling = new QComboBox();
|
||||
telemetryScaling->addItem(tr("Fit to height only"), 0);
|
||||
telemetryScaling->addItem(tr("Fit to height and width"), 1);
|
||||
telemetryScaling->setCurrentIndex(appsettings->value(this, TRAIN_TELEMETRY_FONT_SCALING, 0).toInt());
|
||||
|
||||
delayLabel = new QLabel(tr("Start Countdown"));
|
||||
startDelay = new QSpinBox(this);
|
||||
startDelay->setMaximum(600);
|
||||
@@ -765,29 +771,22 @@ TrainOptionsPage::TrainOptionsPage(QWidget *parent, Context *context) : QWidget(
|
||||
startDelay->setValue(appsettings->value(this, TRAIN_STARTDELAY, 0).toUInt());
|
||||
startDelay->setToolTip(tr("Countdown for workout start"));
|
||||
|
||||
QVBoxLayout *all = new QVBoxLayout(this);
|
||||
QFormLayout *all = new QFormLayout(this);
|
||||
|
||||
QGridLayout *wdLayout = new QGridLayout;
|
||||
wdLayout->addWidget(workoutLabel, 0,0, Qt::AlignRight);
|
||||
wdLayout->addWidget(workoutDirectory, 0,1);
|
||||
wdLayout->addWidget(workoutBrowseButton, 0,2);
|
||||
all->addLayout(wdLayout);
|
||||
|
||||
all->addWidget(useSimulatedSpeed);
|
||||
all->addWidget(useSimulatedHypoxia);
|
||||
all->addWidget(multiCheck);
|
||||
all->addWidget(autoConnect);
|
||||
all->addWidget(autoHide);
|
||||
all->addWidget(lapAlert);
|
||||
all->addWidget(coalesce);
|
||||
|
||||
QHBoxLayout *delayLayout = new QHBoxLayout;
|
||||
delayLayout->addWidget(delayLabel);
|
||||
delayLayout->addWidget(startDelay);
|
||||
delayLayout->addStretch();
|
||||
all->addLayout(delayLayout);
|
||||
|
||||
all->addStretch();
|
||||
all->addRow(workoutLabel, wdLayout);
|
||||
all->addRow("", useSimulatedSpeed);
|
||||
all->addRow("", useSimulatedHypoxia);
|
||||
all->addRow("", multiCheck);
|
||||
all->addRow("", autoConnect);
|
||||
all->addRow("", autoHide);
|
||||
all->addRow("", lapAlert);
|
||||
all->addRow("", coalesce);
|
||||
all->addRow(delayLabel, startDelay);
|
||||
all->addRow(telemetryScalingLabel, telemetryScaling);
|
||||
}
|
||||
|
||||
|
||||
@@ -804,6 +803,7 @@ TrainOptionsPage::saveClicked()
|
||||
appsettings->setValue(TRAIN_AUTOHIDE, autoHide->isChecked());
|
||||
appsettings->setValue(TRAIN_LAPALERT, lapAlert->isChecked());
|
||||
appsettings->setValue(TRAIN_COALESCE_SECTIONS, coalesce->isChecked());
|
||||
appsettings->setValue(TRAIN_TELEMETRY_FONT_SCALING, telemetryScaling->currentIndex());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -240,6 +240,8 @@ class TrainOptionsPage : public QWidget
|
||||
QCheckBox *autoHide;
|
||||
QCheckBox *lapAlert;
|
||||
QCheckBox *coalesce;
|
||||
QLabel *telemetryScalingLabel;
|
||||
QComboBox *telemetryScaling;
|
||||
};
|
||||
|
||||
class RemotePage : public QWidget
|
||||
|
||||
@@ -80,7 +80,11 @@ DialWindow::DialWindow(Context *context) :
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(3,3,3,3);
|
||||
valueLabel = new QLabel(this);
|
||||
valueLabel = new ScalingLabel(this);
|
||||
valueLabel->setStrategy(appsettings->value(this, TRAIN_TELEMETRY_FONT_SCALING, 0).toInt() == 0 ? ScalingLabelStrategy::HeightOnly : ScalingLabelStrategy::Linear);
|
||||
QFont vlFont = valueLabel->font();
|
||||
vlFont.setWeight(QFont::Bold);
|
||||
valueLabel->setFont(vlFont);
|
||||
valueLabel->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
|
||||
layout->addWidget(valueLabel);
|
||||
setChartLayout(layout);
|
||||
@@ -99,9 +103,6 @@ DialWindow::DialWindow(Context *context) :
|
||||
// setup colors
|
||||
seriesChanged();
|
||||
|
||||
// setup fontsize etc
|
||||
resizeEvent(NULL);
|
||||
|
||||
// set to zero
|
||||
resetValues();
|
||||
}
|
||||
@@ -546,21 +547,6 @@ DialWindow::telemetryUpdate(const RealtimeData &rtData)
|
||||
}
|
||||
}
|
||||
|
||||
void DialWindow::resizeEvent(QResizeEvent * )
|
||||
{
|
||||
QFont font;
|
||||
|
||||
// set point size within reasonable limits for low dpi screens
|
||||
int size = (geometry().height() - 24) * 72 / logicalDpiY();
|
||||
if (size <= 0) size = 4;
|
||||
if (size >= 64) size = 64;
|
||||
|
||||
font.setPointSize(size);
|
||||
|
||||
font.setWeight(QFont::Bold);
|
||||
valueLabel->setFont(font);
|
||||
}
|
||||
|
||||
void DialWindow::seriesChanged()
|
||||
{
|
||||
// we got some!
|
||||
@@ -719,6 +705,7 @@ void DialWindow::seriesChanged()
|
||||
break;
|
||||
}
|
||||
|
||||
valueLabel->setStrategy(appsettings->value(this, TRAIN_TELEMETRY_FONT_SCALING, 0).toInt() == 0 ? ScalingLabelStrategy::HeightOnly : ScalingLabelStrategy::Linear);
|
||||
// ugh. we use style sheets because palettes don't work on labels
|
||||
background = GColor(CTRAINPLOTBACKGROUND);
|
||||
setProperty("color", background);
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <QLineEdit>
|
||||
#include <QFormLayout>
|
||||
|
||||
#include "ScalingLabel.h"
|
||||
|
||||
#include "Context.h"
|
||||
#include "Zones.h" // for data series types
|
||||
#include "RideFile.h" // for data series types
|
||||
@@ -74,9 +76,6 @@ class DialWindow : public GcChartWindow
|
||||
int style() const { return _style; }
|
||||
int avgSecs() const { return average; }
|
||||
|
||||
// change font as window resizes
|
||||
void resizeEvent(QResizeEvent *);
|
||||
|
||||
public slots:
|
||||
|
||||
// trap signals
|
||||
@@ -148,7 +147,7 @@ class DialWindow : public GcChartWindow
|
||||
QLineEdit *averageEdit;
|
||||
|
||||
// display
|
||||
QLabel *valueLabel;
|
||||
ScalingLabel *valueLabel;
|
||||
|
||||
QColor foreground, background;
|
||||
|
||||
|
||||
221
src/Train/ScalingLabel.cpp
Normal file
221
src/Train/ScalingLabel.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Joachim Kohlhammer (joachim.kohlhammer@gmx.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "ScalingLabel.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
ScalingLabel::ScalingLabel
|
||||
(QWidget *parent, Qt::WindowFlags f)
|
||||
: ScalingLabel(4, 64, parent, f)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ScalingLabel::ScalingLabel
|
||||
(int minFontPointSize, int maxFontPointSize, QWidget *parent, Qt::WindowFlags f)
|
||||
: QLabel(parent, f), minFontPointSize(minFontPointSize), maxFontPointSize(maxFontPointSize)
|
||||
{
|
||||
QFont fnt = font();
|
||||
fnt.setPointSize(minFontPointSize);
|
||||
QLabel::setFont(fnt);
|
||||
}
|
||||
|
||||
|
||||
ScalingLabel::~ScalingLabel
|
||||
()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScalingLabel::resizeEvent
|
||||
(QResizeEvent *evt)
|
||||
{
|
||||
Q_UNUSED(evt)
|
||||
scaleFont(text(), ScalingLabelReason::ResizeEvent);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScalingLabel::setText
|
||||
(const QString &text)
|
||||
{
|
||||
++counter;
|
||||
if (text.length() > QLabel::text().length()) {
|
||||
scaleFont(text, ScalingLabelReason::TextLengthChanged);
|
||||
} else if (counter > 10) {
|
||||
scaleFont(text, ScalingLabelReason::CounterExceeded);
|
||||
}
|
||||
QLabel::setText(text);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScalingLabel::setFont
|
||||
(const QFont &font)
|
||||
{
|
||||
if (! scaleFont(text(), font, ScalingLabelReason::FontChanged)) {
|
||||
QLabel::setFont(font);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ScalingLabel::getMinFontPointSize
|
||||
() const
|
||||
{
|
||||
return minFontPointSize;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScalingLabel::setMinFontPointSize
|
||||
(int size)
|
||||
{
|
||||
minFontPointSize = size;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ScalingLabel::getMaxFontPointSize
|
||||
() const
|
||||
{
|
||||
return maxFontPointSize;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScalingLabel::setMaxFontPointSize
|
||||
(int size)
|
||||
{
|
||||
maxFontPointSize = size;
|
||||
}
|
||||
|
||||
|
||||
ScalingLabelStrategy
|
||||
ScalingLabel::getStrategy
|
||||
() const
|
||||
{
|
||||
return strategy;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScalingLabel::setStrategy
|
||||
(ScalingLabelStrategy strategy)
|
||||
{
|
||||
if (this->strategy != strategy) {
|
||||
this->strategy = strategy;
|
||||
scaleFont(text(), ScalingLabelReason::StrategyChanged);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ScalingLabel::scaleFont
|
||||
(const QString &text, ScalingLabelReason reason)
|
||||
{
|
||||
return scaleFont(text, font(), reason);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ScalingLabel::scaleFont
|
||||
(const QString &text, const QFont &font, ScalingLabelReason reason)
|
||||
{
|
||||
counter = 0;
|
||||
switch (strategy) {
|
||||
case ScalingLabelStrategy::Linear:
|
||||
return scaleFontLinear(text, font, reason);
|
||||
case ScalingLabelStrategy::Exact:
|
||||
return scaleFontExact(text, font, reason);
|
||||
case ScalingLabelStrategy::HeightOnly:
|
||||
default:
|
||||
return scaleFontHeightOnly(text, font, reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ScalingLabel::scaleFontHeightOnly
|
||||
(const QString &text, const QFont &font, ScalingLabelReason reason)
|
||||
{
|
||||
Q_UNUSED(text)
|
||||
if ( reason != ScalingLabelReason::ResizeEvent
|
||||
&& reason != ScalingLabelReason::StrategyChanged) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QFont f(font);
|
||||
// set point size within reasonable limits for low dpi screens
|
||||
int size = (geometry().height() - 24) * 72 / logicalDpiY();
|
||||
size = std::min(maxFontPointSize, std::max(minFontPointSize, size));
|
||||
f.setPointSize(size);
|
||||
setFont(f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ScalingLabel::scaleFontExact
|
||||
(const QString &text, const QFont &font, ScalingLabelReason reason)
|
||||
{
|
||||
int size = maxFontPointSize + 1;
|
||||
if (reason == ScalingLabelReason::CounterExceeded) {
|
||||
size = font.pointSize() + 1;
|
||||
}
|
||||
QFont f(font);
|
||||
QRect br;
|
||||
do {
|
||||
f.setPointSize(--size);
|
||||
QFontMetrics fm = QFontMetrics(f, this);
|
||||
br = fm.boundingRect(text);
|
||||
} while (size >= minFontPointSize && (br.width() > width() || br.height() > height()));
|
||||
QLabel::setFont(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ScalingLabel::scaleFontLinear
|
||||
(const QString &text, const QFont &font, ScalingLabelReason reason)
|
||||
{
|
||||
if (text.length() == 0 || width() <= 0 || height() <= 0) {
|
||||
return false;
|
||||
}
|
||||
int maxSize = maxFontPointSize;
|
||||
if (reason == ScalingLabelReason::CounterExceeded) {
|
||||
maxSize = font.pointSize();
|
||||
}
|
||||
QFont f(font);
|
||||
f.setPointSize(minFontPointSize);
|
||||
QFontMetrics fmS = QFontMetrics(f, this);
|
||||
f.setPointSize(maxSize);
|
||||
QFontMetrics fmL = QFontMetrics(f, this);
|
||||
QRect brS = fmS.boundingRect(text);
|
||||
QRect brL = fmL.boundingRect(text);
|
||||
int sizeWidth = (maxSize - minFontPointSize) / float(brL.width() - brS.width()) * width();
|
||||
int sizeHeight = (maxSize - minFontPointSize) / float(brL.height() - brS.height()) * height();
|
||||
int calcSize = std::min<int>(sizeWidth, sizeHeight);
|
||||
f.setPointSize(std::max<int>(std::min<int>(calcSize, maxSize), minFontPointSize));
|
||||
QLabel::setFont(f);
|
||||
return true;
|
||||
}
|
||||
74
src/Train/ScalingLabel.h
Normal file
74
src/Train/ScalingLabel.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Joachim Kohlhammer (joachim.kohlhammer@gmx.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _GC_ScalingLabel_h
|
||||
#define _GC_ScalingLabel_h 1
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
enum class ScalingLabelReason : uint8_t {
|
||||
TextLengthChanged,
|
||||
FontChanged,
|
||||
ResizeEvent,
|
||||
CounterExceeded,
|
||||
StrategyChanged
|
||||
};
|
||||
|
||||
enum class ScalingLabelStrategy : uint8_t {
|
||||
Exact,
|
||||
Linear,
|
||||
HeightOnly
|
||||
};
|
||||
|
||||
|
||||
class ScalingLabel : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScalingLabel(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
ScalingLabel(int minFontPointSize, int maxFontPointSize, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
virtual ~ScalingLabel();
|
||||
|
||||
virtual void resizeEvent(QResizeEvent *evt);
|
||||
virtual void setFont(const QFont &font);
|
||||
|
||||
int getMinFontPointSize() const;
|
||||
int getMaxFontPointSize() const;
|
||||
ScalingLabelStrategy getStrategy() const;
|
||||
|
||||
public slots:
|
||||
void setText(const QString &text);
|
||||
void setMinFontPointSize(int size);
|
||||
void setMaxFontPointSize(int size);
|
||||
void setStrategy(ScalingLabelStrategy strategy);
|
||||
|
||||
private:
|
||||
bool scaleFont(const QString &text, const QFont &font, ScalingLabelReason reason);
|
||||
bool scaleFont(const QString &text, ScalingLabelReason reason);
|
||||
bool scaleFontExact(const QString &text, const QFont &font, ScalingLabelReason reason);
|
||||
bool scaleFontLinear(const QString &text, const QFont &font, ScalingLabelReason reason);
|
||||
bool scaleFontHeightOnly(const QString &text, const QFont &font, ScalingLabelReason reason);
|
||||
|
||||
int minFontPointSize;
|
||||
int maxFontPointSize;
|
||||
ScalingLabelStrategy strategy = ScalingLabelStrategy::Linear;
|
||||
int counter = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -706,7 +706,7 @@ HEADERS += Train/AddDeviceWizard.h Train/CalibrationData.h Train/ComputrainerCon
|
||||
HEADERS += Train/TrainBottom.h Train/TrainDB.h Train/TrainSidebar.h \
|
||||
Train/VideoLayoutParser.h Train/VideoSyncFile.h Train/WorkoutPlotWindow.h Train/WebPageWindow.h \
|
||||
Train/WorkoutWidget.h Train/WorkoutWidgetItems.h Train/WorkoutWindow.h Train/WorkoutWizard.h Train/ZwoParser.h \
|
||||
Train/LiveMapWebPageWindow.h \
|
||||
Train/LiveMapWebPageWindow.h Train/ScalingLabel.h \
|
||||
Train/InfoWidget.h Train/PowerInfoWidget.h Train/PowerZonesWidget.h Train/RatingWidget.h \
|
||||
Train/ErgOverview.h Train/Shy.h \
|
||||
Train/WorkoutTagWrapper.h
|
||||
@@ -716,7 +716,7 @@ HEADERS += Train/TrainBottom.h Train/TrainDB.h Train/TrainSidebar.h \
|
||||
### SOURCE FILES
|
||||
###=============
|
||||
|
||||
## ANT+
|
||||
## ANT+
|
||||
SOURCES += ANT/ANTChannel.cpp ANT/ANT.cpp ANT/ANTlocalController.cpp ANT/ANTLogger.cpp ANT/ANTMessage.cpp
|
||||
|
||||
## Charts and related
|
||||
@@ -817,7 +817,7 @@ SOURCES += Train/AddDeviceWizard.cpp Train/CalibrationData.cpp Train/Computraine
|
||||
SOURCES += Train/TrainBottom.cpp Train/TrainDB.cpp Train/TrainSidebar.cpp \
|
||||
Train/VideoLayoutParser.cpp Train/VideoSyncFile.cpp Train/WorkoutPlotWindow.cpp Train/WebPageWindow.cpp \
|
||||
Train/WorkoutWidget.cpp Train/WorkoutWidgetItems.cpp Train/WorkoutWindow.cpp Train/WorkoutWizard.cpp Train/ZwoParser.cpp \
|
||||
Train/LiveMapWebPageWindow.cpp \
|
||||
Train/LiveMapWebPageWindow.cpp Train/ScalingLabel.cpp \
|
||||
Train/InfoWidget.cpp Train/PowerInfoWidget.cpp Train/PowerZonesWidget.cpp Train/RatingWidget.cpp \
|
||||
Train/ErgOverview.cpp Train/Shy.cpp \
|
||||
Train/WorkoutTagWrapper.cpp
|
||||
|
||||
Reference in New Issue
Block a user