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'); label.append('9');
} }
/* Use the label to estimate size of the labels. std::tie(labelWidth, labelHeight) = DiveTextItem::getLabelSize(dpr, labelScale, label);
* 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);
} }
DiveCartesianAxis::~DiveCartesianAxis() DiveCartesianAxis::~DiveCartesianAxis()
@ -96,6 +89,11 @@ double DiveCartesianAxis::height() const
return labelHeight + labelSpaceVertical * dpr; return labelHeight + labelSpaceVertical * dpr;
} }
double DiveCartesianAxis::horizontalOverhang() const
{
return labelWidth / 2.0;
}
int DiveCartesianAxis::getMinLabelDistance(const DiveCartesianAxis &timeAxis) const int DiveCartesianAxis::getMinLabelDistance(const DiveCartesianAxis &timeAxis) const
{ {
// For the plot not being to crowded we want at least two // For the plot not being to crowded we want at least two

View file

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

View file

@ -432,9 +432,12 @@ void DiveTemperatureItem::paint(QPainter *painter, const QStyleOptionGraphicsIte
painter->restore(); painter->restore();
} }
static const double diveMeanDepthItemLabelScale = 0.8;
DiveMeanDepthItem::DiveMeanDepthItem(const DivePlotDataModel &model, const DiveCartesianAxis &hAxis, int hColumn, DiveMeanDepthItem::DiveMeanDepthItem(const DivePlotDataModel &model, const DiveCartesianAxis &hAxis, int hColumn,
const DiveCartesianAxis &vAxis, int vColumn, double dpr) : 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; QPen pen;
pen.setBrush(QBrush(getColor(::HR_AXIS))); pen.setBrush(QBrush(getColor(::HR_AXIS)));
@ -500,7 +503,6 @@ void DiveMeanDepthItem::replot(const dive *, int fromIn, int toIn, bool)
createTextItem(prevSec, prevMeanDepth); createTextItem(prevSec, prevMeanDepth);
} }
void DiveMeanDepthItem::paint(QPainter *painter, const QStyleOptionGraphicsItem*, QWidget*) void DiveMeanDepthItem::paint(QPainter *painter, const QStyleOptionGraphicsItem*, QWidget*)
{ {
if (polygon().isEmpty()) if (polygon().isEmpty())
@ -515,7 +517,7 @@ void DiveMeanDepthItem::createTextItem(double lastSec, double lastMeanDepth)
{ {
qDeleteAll(texts); qDeleteAll(texts);
texts.clear(); 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->set(get_depth_string(lrint(lastMeanDepth), true), getColor(TEMP_TEXT));
text->setPos(QPointF(hAxis.posAtValue(lastSec) + dpr, vAxis.posAtValue(lastMeanDepth))); text->setPos(QPointF(hAxis.posAtValue(lastSec) + dpr, vAxis.posAtValue(lastMeanDepth)));
texts.append(text); 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); 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 replot(const dive *d, int from, int to, bool in_planner) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override;
double labelWidth;
private: private:
void createTextItem(double lastSec, double lastMeanDepth); void createTextItem(double lastSec, double lastMeanDepth);

View file

@ -17,6 +17,22 @@ DiveTextItem::DiveTextItem(double dpr, double scale, int alignFlags, QGraphicsIt
setFlag(ItemIgnoresTransformations); 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) void DiveTextItem::set(const QString &t, const QBrush &b)
{ {
internalText = t; internalText = t;
@ -66,27 +82,6 @@ const QString &DiveTextItem::text()
return internalText; 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) double DiveTextItem::fontHeight(double dpr, double scale)
{ {
QFont fnt = getFont(dpr, scale); QFont fnt = getFont(dpr, scale);
@ -98,3 +93,14 @@ double DiveTextItem::height() const
{ {
return fontHeight(dpr, scale) + outlineSize * dpr; 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); DiveTextItem(double dpr, double scale, int alignFlags, QGraphicsItem *parent);
void set(const QString &text, const QBrush &brush); void set(const QString &text, const QBrush &brush);
const QString &text(); const QString &text();
static QFont getFont(double dpr, double scale);
static double fontHeight(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; double height() const;
private: private:

View file

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

View file

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