From 2ebe6e3684ec9cb712307badf3c1b1d5438e1d69 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger <bstoeger@mail.tuwien.ac.at> Date: Thu, 12 Aug 2021 22:57:57 +0200 Subject: [PATCH] profile: set alignment and scale of DiveTextItem at construction Alignment and scale of DiveTextItems are never changed. Therefore, pass them at construction time. This makes things much easier if we want to cache the rendered text [currently the text is rerendered at every paint() event]. This also removes the "parent=0" default parameter of the constructor, because inadvertently leaving out the last argument led to a subtle bug. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at> --- profile-widget/divecartesianaxis.cpp | 7 ++-- profile-widget/diveprofileitem.cpp | 52 +++++++++++++++------------- profile-widget/diveprofileitem.h | 4 +-- profile-widget/divetextitem.cpp | 20 ++--------- profile-widget/divetextitem.h | 4 +-- profile-widget/profilescene.cpp | 6 ++-- profile-widget/tankitem.cpp | 3 +- 7 files changed, 39 insertions(+), 57 deletions(-) diff --git a/profile-widget/divecartesianaxis.cpp b/profile-widget/divecartesianaxis.cpp index 2c78c62c5..ee4756cdc 100644 --- a/profile-widget/divecartesianaxis.cpp +++ b/profile-widget/divecartesianaxis.cpp @@ -198,18 +198,17 @@ void DiveCartesianAxis::updateTicks(int animSpeed, color_index_t color) } else { childPos = begin - i * stepSize; } - DiveTextItem *label = new DiveTextItem(dpr, this); + int alignFlags = orientation == RightToLeft || orientation == LeftToRight ? Qt::AlignBottom | Qt::AlignHCenter : + Qt::AlignVCenter | Qt::AlignLeft; + DiveTextItem *label = new DiveTextItem(dpr, labelScale, alignFlags, this); label->setText(textForValue(currValueText)); label->setBrush(colorForValue(currValueText)); - label->setScale(labelScale); label->setZValue(1); labels.push_back(label); if (orientation == RightToLeft || orientation == LeftToRight) { - label->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); label->setPos(scene.sceneRect().width() + 10, m.y1() + tick_size); // position it outside of the scene; Animations::moveTo(label, animSpeed,childPos , m.y1() + tick_size); } else { - label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); label->setPos(m.x1() - tick_size, scene.sceneRect().height() + 10); Animations::moveTo(label, animSpeed, m.x1() - tick_size, childPos); } diff --git a/profile-widget/diveprofileitem.cpp b/profile-widget/diveprofileitem.cpp index 91b898bb4..146e19880 100644 --- a/profile-widget/diveprofileitem.cpp +++ b/profile-widget/diveprofileitem.cpp @@ -142,10 +142,9 @@ void DiveProfileItem::replot(const dive *d, bool in_planner) void DiveProfileItem::plot_depth_sample(struct plot_data *entry, QFlags<Qt::AlignmentFlag> flags, const QColor &color) { - DiveTextItem *item = new DiveTextItem(dpr, this); + DiveTextItem *item = new DiveTextItem(dpr, 1.0, flags, this); item->setPos(hAxis.posAtValue(entry->sec), vAxis.posAtValue(entry->depth)); item->setText(get_depth_string(entry->depth, true)); - item->setAlignment(flags); item->setBrush(color); texts.append(item); } @@ -164,10 +163,11 @@ DiveHeartrateItem::DiveHeartrateItem(const DivePlotDataModel &model, const DiveC void DiveHeartrateItem::replot(const dive *, bool) { int last = -300, last_printed_hr = 0, sec = 0; - struct { + struct sec_hr { int sec; int hr; } hist[3] = {}; + std::vector<sec_hr> textItems; qDeleteAll(texts); texts.clear(); @@ -203,22 +203,24 @@ void DiveHeartrateItem::replot(const dive *, bool) (abs(hr - last_printed_hr) < 10)) continue; last = sec; - createTextItem(sec, hr); + textItems.push_back({ sec, hr }); last_printed_hr = hr; } setPolygon(poly); - if (texts.count()) - texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom); + for (size_t i = 0; i < textItems.size(); ++i) { + auto [sec, hr] = textItems[i]; + createTextItem(sec, hr, i == textItems.size() - 1); + } } -void DiveHeartrateItem::createTextItem(int sec, int hr) +void DiveHeartrateItem::createTextItem(int sec, int hr, bool last) { - DiveTextItem *text = new DiveTextItem(dpr, this); - text->setAlignment(Qt::AlignRight | Qt::AlignBottom); + int flags = last ? Qt::AlignLeft | Qt::AlignBottom : + Qt::AlignRight | Qt::AlignBottom; + DiveTextItem *text = new DiveTextItem(dpr, 0.7, flags, this); text->setBrush(getColor(HR_TEXT)); text->setPos(QPointF(hAxis.posAtValue(sec), vAxis.posAtValue(hr))); - text->setScale(0.7); // need to call this BEFORE setText() text->setText(QString("%1").arg(hr)); texts.append(text); } @@ -315,6 +317,7 @@ DiveTemperatureItem::DiveTemperatureItem(const DivePlotDataModel &model, const D void DiveTemperatureItem::replot(const dive *, bool) { int last = -300, last_printed_temp = 0, sec = 0, last_valid_temp = 0; + std::vector<std::pair<int, int>> textItems; qDeleteAll(texts); texts.clear(); @@ -339,7 +342,7 @@ void DiveTemperatureItem::replot(const dive *, bool) continue; last = sec; if (mkelvin > 200000) - createTextItem(sec, mkelvin); + textItems.push_back({ sec, mkelvin }); last_printed_temp = mkelvin; } setPolygon(poly); @@ -349,22 +352,25 @@ void DiveTemperatureItem::replot(const dive *, bool) * than a quarter of the dive back */ if (last_valid_temp > 200000 && ((abs(last_valid_temp - last_printed_temp) > 500) || ((double)last / (double)sec < 0.75))) { - createTextItem(sec, last_valid_temp); + textItems.push_back({ sec, last_valid_temp }); + } + + for (size_t i = 0; i < textItems.size(); ++i) { + auto [sec, mkelvin] = textItems[i]; + createTextItem(sec, mkelvin, i == textItems.size() - 1); } - if (texts.count()) - texts.last()->setAlignment(Qt::AlignLeft | Qt::AlignBottom); } -void DiveTemperatureItem::createTextItem(int sec, int mkelvin) +void DiveTemperatureItem::createTextItem(int sec, int mkelvin, bool last) { temperature_t temp; temp.mkelvin = mkelvin; - DiveTextItem *text = new DiveTextItem(dpr, this); - text->setAlignment(Qt::AlignRight | Qt::AlignBottom); + int flags = last ? Qt::AlignLeft | Qt::AlignBottom : + Qt::AlignRight | Qt::AlignBottom; + DiveTextItem *text = new DiveTextItem(dpr, 0.8, flags, this); text->setBrush(getColor(TEMP_TEXT)); text->setPos(QPointF(hAxis.posAtValue(sec), vAxis.posAtValue(mkelvin))); - text->setScale(0.8); // need to call this BEFORE setText() text->setText(get_temperature_string(temp, true)); texts.append(text); } @@ -428,11 +434,9 @@ void DiveMeanDepthItem::createTextItem() int sec = entry[dataModel.rowCount()-1].sec; qDeleteAll(texts); texts.clear(); - DiveTextItem *text = new DiveTextItem(dpr, this); - text->setAlignment(Qt::AlignRight | Qt::AlignTop); + DiveTextItem *text = new DiveTextItem(dpr, 0.8, Qt::AlignRight | Qt::AlignTop, this); text->setBrush(getColor(TEMP_TEXT)); text->setPos(QPointF(hAxis.posAtValue(sec) + 1, vAxis.posAtValue(lastRunningSum))); - text->setScale(0.8); // need to call this BEFORE setText() text->setText(get_depth_string(lrint(lastRunningSum), true)); texts.append(text); } @@ -566,10 +570,9 @@ void DiveGasPressureItem::plotPressureValue(int mbar, int sec, QFlags<Qt::Alignm { const char *unit; int pressure = get_pressure_units(mbar, &unit); - DiveTextItem *text = new DiveTextItem(dpr, this); + DiveTextItem *text = new DiveTextItem(dpr, 1.0, align, this); text->setPos(hAxis.posAtValue(sec), vAxis.posAtValue(mbar) + pressure_offset ); text->setText(QString("%1%2").arg(pressure).arg(unit)); - text->setAlignment(align); text->setBrush(getColor(PRESSURE_TEXT)); texts.push_back(text); } @@ -577,10 +580,9 @@ void DiveGasPressureItem::plotPressureValue(int mbar, int sec, QFlags<Qt::Alignm void DiveGasPressureItem::plotGasValue(int mbar, int sec, struct gasmix gasmix, QFlags<Qt::AlignmentFlag> align, double gasname_offset) { QString gas = get_gas_string(gasmix); - DiveTextItem *text = new DiveTextItem(dpr, this); + DiveTextItem *text = new DiveTextItem(dpr, 1.0, align, this); text->setPos(hAxis.posAtValue(sec), vAxis.posAtValue(mbar) + gasname_offset ); text->setText(gas); - text->setAlignment(align); text->setBrush(getColor(PRESSURE_TEXT)); texts.push_back(text); } diff --git a/profile-widget/diveprofileitem.h b/profile-widget/diveprofileitem.h index 1c34abfcf..f5bcd3fe2 100644 --- a/profile-widget/diveprofileitem.h +++ b/profile-widget/diveprofileitem.h @@ -82,7 +82,7 @@ public: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override; private: - void createTextItem(int seconds, int mkelvin); + void createTextItem(int seconds, int mkelvin, bool last); }; class DiveHeartrateItem : public AbstractProfilePolygonItem { @@ -93,7 +93,7 @@ public: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; private: - void createTextItem(int seconds, int hr); + void createTextItem(int seconds, int hr, bool last); QString visibilityKey; }; diff --git a/profile-widget/divetextitem.cpp b/profile-widget/divetextitem.cpp index 5b955058a..fde530bc7 100644 --- a/profile-widget/divetextitem.cpp +++ b/profile-widget/divetextitem.cpp @@ -8,12 +8,12 @@ #include <QDebug> #include <QApplication> -DiveTextItem::DiveTextItem(double dpr, QGraphicsItem *parent) : QGraphicsItemGroup(parent), - internalAlignFlags(Qt::AlignHCenter | Qt::AlignVCenter), +DiveTextItem::DiveTextItem(double dpr, double scale, int alignFlags, QGraphicsItem *parent) : QGraphicsItemGroup(parent), + internalAlignFlags(alignFlags), textBackgroundItem(new QGraphicsPathItem(this)), textItem(new QGraphicsPathItem(this)), dpr(dpr), - scale(1.0) + scale(scale) { setFlag(ItemIgnoresTransformations); textBackgroundItem->setBrush(QBrush(getColor(TEXT_BACKGROUND))); @@ -27,25 +27,11 @@ void DiveTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti QGraphicsItemGroup::paint(painter, option, widget); } -void DiveTextItem::setAlignment(int alignFlags) -{ - if (alignFlags != internalAlignFlags) { - internalAlignFlags = alignFlags; - } -} - void DiveTextItem::setBrush(const QBrush &b) { textItem->setBrush(b); } -void DiveTextItem::setScale(double newscale) -{ - if (scale != newscale) { - scale = newscale; - } -} - void DiveTextItem::setText(const QString &t) { if (internalText != t) { diff --git a/profile-widget/divetextitem.h b/profile-widget/divetextitem.h index 5c86e462c..ebe3561d8 100644 --- a/profile-widget/divetextitem.h +++ b/profile-widget/divetextitem.h @@ -14,10 +14,8 @@ class DiveTextItem : public QObject, public QGraphicsItemGroup { Q_PROPERTY(QPointF pos READ pos WRITE setPos) Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) public: - DiveTextItem(double dpr, QGraphicsItem *parent = 0); + DiveTextItem(double dpr, double scale, int alignFlags, QGraphicsItem *parent); void setText(const QString &text); - void setAlignment(int alignFlags); - void setScale(double newscale); void setBrush(const QBrush &brush); const QString &text(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); diff --git a/profile-widget/profilescene.cpp b/profile-widget/profilescene.cpp index d870c4a84..51f916de5 100644 --- a/profile-widget/profilescene.cpp +++ b/profile-widget/profilescene.cpp @@ -81,7 +81,7 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) : temperatureItem(createItem<DiveTemperatureItem>(*temperatureAxis, DivePlotDataModel::TEMPERATURE, 1, dpr)), meanDepthItem(createItem<DiveMeanDepthItem>(*profileYAxis, DivePlotDataModel::INSTANT_MEANDEPTH, 1, dpr)), gasPressureItem(createItem<DiveGasPressureItem>(*cylinderPressureAxis, DivePlotDataModel::TEMPERATURE, 1, dpr)), - diveComputerText(new DiveTextItem(dpr)), + diveComputerText(new DiveTextItem(dpr, 1.0, Qt::AlignRight | Qt::AlignTop, nullptr)), reportedCeiling(createItem<DiveReportedCeiling>(*profileYAxis, DivePlotDataModel::CEILING, 1, dpr)), pn2GasItem(createPPGas(DivePlotDataModel::PN2, PN2, PN2_ALERT, NULL, &prefs.pp_graphs.pn2_threshold)), pheGasItem(createPPGas(DivePlotDataModel::PHE, PHE, PHE_ALERT, NULL, &prefs.pp_graphs.phe_threshold)), @@ -92,7 +92,7 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) : ccrsensor3GasItem(createPPGas(DivePlotDataModel::CCRSENSOR3, CCRSENSOR3, PO2_ALERT, &prefs.pp_graphs.po2_threshold_min, &prefs.pp_graphs.po2_threshold_max)), ocpo2GasItem(createPPGas(DivePlotDataModel::SCR_OC_PO2, SCR_OCPO2, PO2_ALERT, &prefs.pp_graphs.po2_threshold_min, &prefs.pp_graphs.po2_threshold_max)), diveCeiling(createItem<DiveCalculatedCeiling>(*profileYAxis, DivePlotDataModel::CEILING, 1, dpr)), - decoModelParameters(new DiveTextItem(dpr)), + decoModelParameters(new DiveTextItem(dpr, 1.0, Qt::AlignHCenter | Qt::AlignBottom, nullptr)), heartBeatItem(createItem<DiveHeartrateItem>(*heartBeatAxis, DivePlotDataModel::HEARTBEAT, 1, dpr)), tankItem(new TankItem(*timeAxis, dpr)) { @@ -158,9 +158,7 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) : decoModelParameters->setY(0); decoModelParameters->setX(50); decoModelParameters->setBrush(getColor(PRESSURE_TEXT)); - decoModelParameters->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); - diveComputerText->setAlignment(Qt::AlignRight | Qt::AlignTop); diveComputerText->setBrush(getColor(TIME_TEXT, isGrayscale)); diveComputerText->setPos(itemPos.dcLabel.on); diff --git a/profile-widget/tankitem.cpp b/profile-widget/tankitem.cpp index 53ea5abbc..a53f70a97 100644 --- a/profile-widget/tankitem.cpp +++ b/profile-widget/tankitem.cpp @@ -51,11 +51,10 @@ void TankItem::createBar(int startTime, int stopTime, struct gasmix gas) rect->setBrush(nitrox); rect->setPen(QPen(QBrush(), 0.0)); // get rid of the thick line around the rectangle rects.push_back(rect); - DiveTextItem *label = new DiveTextItem(dpr, rect); + DiveTextItem *label = new DiveTextItem(dpr, 1.0, Qt::AlignBottom | Qt::AlignRight, rect); label->setText(gasname(gas)); label->setBrush(Qt::black); label->setPos(x + 1, 0); - label->setAlignment(Qt::AlignBottom | Qt::AlignRight); #ifdef SUBSURFACE_MOBILE label->setPos(x + 1, -2.5); #endif