          if (value_pos.x() > pos.x()) pos = value_pos;
        }
        text_list.push_back(QString("&nbsp;%1 : %2&nbsp;").arg(sigs.size() > 1 ? s.sig->name.c_str() : "Value").arg(value));
      }
  
      QString time = QString::number(chart()->mapToValue(pos).x(), 'f', 3);
      value_text->setHtml(QString("<div style=\"background-color: darkGray;color: white;\">&nbsp;Time: %1 &nbsp;<br />%2</div>")
                              .arg(time).arg(text_list.join("<br />")));
  
      QRectF text_rect = value_text->boundingRect();
 
</s> remove     if (!text_list.isEmpty()) {
      value_text->setHtml("<div style=\"background-color: darkGray;color: white;\">&nbsp;Time: " +
                          QString::number(tm, 'f', 3) + "&nbsp;<br />" + text_list.join("<br />") + "</div>");
      track_line->setLine(pos.x(), plot_area.top(), pos.x(), plot_area.bottom());
      int text_x = pos.x() + 8;
      QRectF text_rect = value_text->boundingRect();
      if ((text_x + text_rect.width()) > plot_area.right()) {
        text_x = pos.x() - text_rect.width() - 8;
      }
      value_text->setPos(text_x, pos.y() - text_rect.height() / 2);
      track_ellipse->setRect(pos.x() - 5, pos.y() - 5, 10, 10);
 </s> add     QString time = QString::number(chart()->mapToValue(pos).x(), 'f', 3);
    value_text->setHtml(QString("<div style=\"background-color: darkGray;color: white;\">&nbsp;Time: %1 &nbsp;<br />%2</div>")
                            .arg(time).arg(text_list.join("<br />")));

    QRectF text_rect = value_text->boundingRect();
    int text_x = pos.x() + 8;
    if ((text_x + text_rect.width()) > plot_area.right()) {
      text_x = pos.x() - text_rect.width() - 8; </s> remove       auto value = std::upper_bound(s.vals.begin(), s.vals.end(), sec, [](double x, auto &p) { return x < p.x(); });
      if (value != s.vals.end()) {
        text_list.push_back(QString("&nbsp;%1 : %2&nbsp;").arg(sigs.size() > 1 ? s.sig->name.c_str() : "Value").arg(value->y()));
        tm = value->x();
        auto y_pos = chart()->mapToPosition(*value);
        if (y_pos.y() < pos.y()) pos = y_pos;
 </s> add       QString value = "--";
      // use reverse iterator to find last item <= sec.
      auto it = std::lower_bound(s.vals.rbegin(), s.vals.rend(), sec, [](auto &p, double x) { return p.x() > x; });
      if (it != s.vals.rend() && it->x() >= axis_x->min()) {
        value = QString::number(it->y());
        auto value_pos = chart()->mapToPosition(*it);
        if (value_pos.x() > pos.x()) pos = value_pos; </s> remove     QPointF pos = plot_area.bottomRight();
    double tm = 0.0;

 </s> add     QPointF pos = {};
    const double sec = chart()->mapToValue(ev->pos()).x(); </s> remove     double sec = chart()->mapToValue(ev->pos()).x();
 </s> add 
    if (pos.x() == 0) pos = ev->pos();
          if (value_pos.x() > pos.x()) pos = value_pos;
        }
        text_list.push_back(QString("&nbsp;%1 : %2&nbsp;").arg(sigs.size() > 1 ? s.sig->name.c_str() : "Value").arg(value));
      }
    if (pos.x() == 0) pos = ev->pos();
  
      QString time = QString::number(chart()->mapToValue(pos).x(), 'f', 3);
      value_text->setHtml(QString("<div style=\"background-color: darkGray;color: white;\">&nbsp;Time: %1 &nbsp;<br />%2</div>")
                              .arg(time).arg(text_list.join("<br />")));
  
      QRectF text_rect = value_text->boundingRect();
keep keep keep add keep keep keep keep keep keep
 Cabana: display dashes if no value available (#26557)

show dot if no value 
tools/cabana/chartswidget.cc