profile: improve calculation of the right border

The time axis might need some space and the average depth item
puts a formatted depth at to right of the profile. Consider
these when calculating the right border.

Since I found no way to turn of the average depth, this creates
a permanent border, which might or might not be a good thing.

Contains some refactoring of the label-size functions provided
by DiveTextItem.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2021-11-13 18:05:31 +01:00 committed by Dirk Hohndel
parent 6b33c3e721
commit 176a62f752
8 changed files with 50 additions and 43 deletions

View file

@ -57,14 +57,7 @@ DiveCartesianAxis::DiveCartesianAxis(Position position, bool inverted, int integ
label.append('9');
}
/* Use the label to estimate size of the labels.
* Round up, because non-integers tend to give abysmal rendering.
*/
QFont fnt = DiveTextItem::getFont(dpr, labelScale);
double outlineSpace = DiveTextItem::outlineSpace(dpr);
QFontMetrics fm(fnt);
labelWidth = ceil(fm.size(Qt::TextSingleLine, label).width() + outlineSpace);
labelHeight = ceil(fm.height() + outlineSpace);
std::tie(labelWidth, labelHeight) = DiveTextItem::getLabelSize(dpr, labelScale, label);
}
DiveCartesianAxis::~DiveCartesianAxis()
@ -96,6 +89,11 @@ double DiveCartesianAxis::height() const
return labelHeight + labelSpaceVertical * dpr;
}
double DiveCartesianAxis::horizontalOverhang() const
{
return labelWidth / 2.0;
}
int DiveCartesianAxis::getMinLabelDistance(const DiveCartesianAxis &timeAxis) const
{
// For the plot not being to crowded we want at least two

View file

@ -46,6 +46,7 @@ public:
void updateTicks(int animSpeed);
double width() const; // only for vertical axes
double height() const; // only for horizontal axes
double horizontalOverhang() const; // space needed for labels of horizontal axes
// The minimum space between two labels on the plot in seconds
int getMinLabelDistance(const DiveCartesianAxis &timeAxis) const;

View file

@ -432,9 +432,12 @@ void DiveTemperatureItem::paint(QPainter *painter, const QStyleOptionGraphicsIte
painter->restore();
}
static const double diveMeanDepthItemLabelScale = 0.8;
DiveMeanDepthItem::DiveMeanDepthItem(const DivePlotDataModel &model, const DiveCartesianAxis &hAxis, int hColumn,
const DiveCartesianAxis &vAxis, int vColumn, double dpr) :
AbstractProfilePolygonItem(model, hAxis, hColumn, vAxis, vColumn, dpr)
AbstractProfilePolygonItem(model, hAxis, hColumn, vAxis, vColumn, dpr),
labelWidth(DiveTextItem::getLabelSize(dpr, diveMeanDepthItemLabelScale, QStringLiteral("999.9ft")).first)
{
QPen pen;
pen.setBrush(QBrush(getColor(::HR_AXIS)));
@ -500,7 +503,6 @@ void DiveMeanDepthItem::replot(const dive *, int fromIn, int toIn, bool)
createTextItem(prevSec, prevMeanDepth);
}
void DiveMeanDepthItem::paint(QPainter *painter, const QStyleOptionGraphicsItem*, QWidget*)
{
if (polygon().isEmpty())
@ -515,7 +517,7 @@ void DiveMeanDepthItem::createTextItem(double lastSec, double lastMeanDepth)
{
qDeleteAll(texts);
texts.clear();
DiveTextItem *text = new DiveTextItem(dpr, 0.8, Qt::AlignRight | Qt::AlignTop, this);
DiveTextItem *text = new DiveTextItem(dpr, diveMeanDepthItemLabelScale, Qt::AlignRight | Qt::AlignTop, this);
text->set(get_depth_string(lrint(lastMeanDepth), true), getColor(TEMP_TEXT));
text->setPos(QPointF(hAxis.posAtValue(lastSec) + dpr, vAxis.posAtValue(lastMeanDepth)));
texts.append(text);

View file

@ -75,6 +75,7 @@ public:
DiveMeanDepthItem(const DivePlotDataModel &model, const DiveCartesianAxis &hAxis, int hColumn, const DiveCartesianAxis &vAxis, int vColumn, double dpr);
void replot(const dive *d, int from, int to, bool in_planner) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override;
double labelWidth;
private:
void createTextItem(double lastSec, double lastMeanDepth);

View file

@ -17,6 +17,22 @@ DiveTextItem::DiveTextItem(double dpr, double scale, int alignFlags, QGraphicsIt
setFlag(ItemIgnoresTransformations);
}
static QFont getFont(double dpr, double scale)
{
QFont fnt(qApp->font());
double size = fnt.pixelSize();
if (size > 0) {
// set in pixels - so the scale factor may not make a difference if it's too close to 1
size *= scale * dpr;
fnt.setPixelSize(lrint(size));
} else {
size = fnt.pointSizeF();
size *= scale * dpr;
fnt.setPointSizeF(size);
}
return fnt;
}
void DiveTextItem::set(const QString &t, const QBrush &b)
{
internalText = t;
@ -66,27 +82,6 @@ const QString &DiveTextItem::text()
return internalText;
}
QFont DiveTextItem::getFont(double dpr, double scale)
{
QFont fnt(qApp->font());
double size = fnt.pixelSize();
if (size > 0) {
// set in pixels - so the scale factor may not make a difference if it's too close to 1
size *= scale * dpr;
fnt.setPixelSize(lrint(size));
} else {
size = fnt.pointSizeF();
size *= scale * dpr;
fnt.setPointSizeF(size);
}
return fnt;
}
double DiveTextItem::outlineSpace(double dpr)
{
return outlineSize * dpr;
}
double DiveTextItem::fontHeight(double dpr, double scale)
{
QFont fnt = getFont(dpr, scale);
@ -98,3 +93,14 @@ double DiveTextItem::height() const
{
return fontHeight(dpr, scale) + outlineSize * dpr;
}
std::pair<double, double> DiveTextItem::getLabelSize(double dpr, double scale, const QString &label)
{
QFont fnt = getFont(dpr, scale);
double outlineSpace = outlineSize * dpr;
QFontMetrics fm(fnt);
/* Round up, because non-integers tend to give abysmal rendering. */
double width = ceil(fm.size(Qt::TextSingleLine, label).width() + outlineSpace);
double height = ceil(fm.height() + outlineSpace);
return std::make_pair(width, height);
}

View file

@ -20,9 +20,8 @@ public:
DiveTextItem(double dpr, double scale, int alignFlags, QGraphicsItem *parent);
void set(const QString &text, const QBrush &brush);
const QString &text();
static QFont getFont(double dpr, double scale);
static double fontHeight(double dpr, double scale);
static double outlineSpace(double dpr); // Additional space needed by outline
static std::pair<double, double> getLabelSize(double dpr, double scale, const QString &label);
double height() const;
private:

View file

@ -225,13 +225,16 @@ void ProfileScene::updateAxes(bool diveHasHeartBeat, bool simplified)
if (!currentdc)
return;
// Calculate left and right border needed for the axes.
// viz. the depth axis to the left and the partial pressure axis to the right.
// Thus, calculating the "border" of the graph is trivial.
// Calculate left and right border needed for the axes and other chart items.
double leftBorder = profileYAxis->width();
if (prefs.hrgraph)
leftBorder = std::max(leftBorder, heartBeatAxis->width());
double rightWidth = ppGraphsEnabled(current_dc, simplified) ? gasYAxis->width() : 0.0;
double rightWidth = timeAxis->horizontalOverhang();
if (prefs.show_average_depth)
rightWidth = std::max(rightWidth, meanDepthItem->labelWidth);
if (ppGraphsEnabled(currentdc, simplified))
rightWidth = std::max(rightWidth, gasYAxis->width());
double rightBorder = sceneRect().width() - rightWidth;
double width = rightBorder - leftBorder;
@ -434,8 +437,7 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, DivePlannerPointsM
tankItem->setData(d, firstSecond, lastSecond);
if (ppGraphsEnabled(current_dc, simplified)) {
double max = prefs.pp_graphs.phe ? dataModel->pheMax() : -1;
if (ppGraphsEnabled(currentdc, simplified)) {
if (prefs.pp_graphs.pn2)
max = std::max(dataModel->pn2Max(), max);
if (prefs.pp_graphs.po2)

View file

@ -36,9 +36,7 @@ TankItem::TankItem(const DiveCartesianAxis &axis, double dpr) :
double TankItem::height() const
{
QFont fnt = DiveTextItem::getFont(dpr, 1.0);
QFontMetrics fm(fnt);
return fm.height() + 2.0 * border * dpr;
return DiveTextItem::fontHeight(dpr, 1.0) + 2.0 * border * dpr;
}
void TankItem::createBar(int startTime, int stopTime, struct gasmix gas)