From: jaseg Date: Sun, 9 Jun 2019 10:35:20 +0000 (+0900) Subject: Make cursor pair drop precision when too small X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=commitdiff_plain;h=ef85cfa4599d3741e7007921e39a44490e97cfaf Make cursor pair drop precision when too small Currently, often the label just displays "...". With this change, it will gracefully drop precision and less important parts (frequency, unit) when there's not enough space to print the full string. The full string is still available in the tooltip appearing on hover. --- diff --git a/pv/util.cpp b/pv/util.cpp index 49b9467c..237ca7f0 100644 --- a/pv/util.cpp +++ b/pv/util.cpp @@ -138,8 +138,9 @@ QString format_time_si(const Timestamp& v, SIPrefix prefix, QTextStream ts(&s); if (sign && !v.is_zero()) ts << forcesign; - ts << qSetRealNumberPrecision(precision) << (v * multiplier) << ' ' - << prefix << unit; + ts << qSetRealNumberPrecision(precision) << (v * multiplier); + if (!unit.isNull()) + ts << ' ' << prefix << unit; return s; } diff --git a/pv/views/trace/cursorpair.cpp b/pv/views/trace/cursorpair.cpp index 933eb8ff..562584c2 100644 --- a/pv/views/trace/cursorpair.cpp +++ b/pv/views/trace/cursorpair.cpp @@ -129,19 +129,14 @@ void CursorPair::paint_label(QPainter &p, const QRect &rect, bool hover) const QColor text_color = ViewItem::select_text_color(Cursor::FillColor); p.setPen(text_color); - QString text = format_string(); - text_size_ = p.boundingRect(QRectF(), 0, text).size(); - QRectF delta_rect(label_rect(rect)); const int radius = delta_rect.height() / 2; QRectF text_rect(delta_rect.intersected(rect).adjusted(radius, 0, -radius, 0)); - if (text_rect.width() < text_size_.width()) { - text = "..."; - text_size_ = p.boundingRect(QRectF(), 0, text).size(); - label_incomplete_ = true; - } else - label_incomplete_ = false; + QString text = format_string(text_rect.width(), [&p](const QString& s) -> qreal { + return p.boundingRect(QRectF(), 0, s).width(); + }); + text_size_ = p.boundingRect(QRectF(), 0, text).size(); if (selected()) { p.setBrush(Qt::transparent); @@ -178,17 +173,50 @@ void CursorPair::paint_back(QPainter &p, ViewItemPaintParams &pp) p.drawRect(l, pp.top(), r - l, pp.height()); } -QString CursorPair::format_string() +QString CursorPair::format_string(qreal max_width, std::function query_size) { + constexpr int time_precision = 12; + constexpr int freq_precision = 4; + const pv::util::SIPrefix prefix = view_.tick_prefix(); const pv::util::Timestamp diff = abs(second_->time() - first_->time()); - const QString s1 = Ruler::format_time_with_distance( - diff, diff, prefix, view_.time_unit(), 12, false); /* Always use 12 precision digits */ - const QString s2 = util::format_time_si( - 1 / diff, pv::util::SIPrefix::unspecified, 4, "Hz", false); + const QString time = Ruler::format_time_with_distance( + diff, diff, prefix, view_.time_unit(), time_precision, false); + const QString freq = util::format_time_si( + 1 / diff, pv::util::SIPrefix::unspecified, freq_precision, "Hz", false); + const QString out = QString("%1 / %2").arg(time, freq); + + // Try full "{time} ms / {freq} Hz" format + if (max_width <= 0 || query_size(out) <= max_width) { + label_incomplete_ = false; + return out; + } + + label_incomplete_ = true; + + // Try just "{time}ms" format and gradually reduce time precision down to zero + for (int shrinkage=0; shrinkage <= time_precision; shrinkage++) { + int prec = time_precision - shrinkage ; + + const QString time = Ruler::format_time_with_distance( + diff, diff, prefix, view_.time_unit(), + prec, false); + + if (query_size(time) <= max_width) + return time; + } + + // Try no trailing digits and drop the unit to at least display something. The unit should be obvious from the ruler + // anyway. + const QString bare_number = Ruler::format_time_with_distance( + diff, diff, prefix, view_.time_unit(), + 0, false, false); + if (query_size(bare_number) <= max_width) + return bare_number; - return QString("%1 / %2").arg(s1, s2); + // Give up. + return "..."; } pair CursorPair::get_cursor_offsets() const diff --git a/pv/views/trace/cursorpair.hpp b/pv/views/trace/cursorpair.hpp index 9d450df6..1dc66a32 100644 --- a/pv/views/trace/cursorpair.hpp +++ b/pv/views/trace/cursorpair.hpp @@ -102,7 +102,8 @@ public: /** * Constructs the string to display. */ - QString format_string(); + QString format_string(qreal max_width = 0, std::function query_size + = [](const QString& s) -> qreal { Q_UNUSED(s); return 0; }); pair get_cursor_offsets() const; diff --git a/pv/views/trace/ruler.cpp b/pv/views/trace/ruler.cpp index 8e7e0b67..98f55ddb 100644 --- a/pv/views/trace/ruler.cpp +++ b/pv/views/trace/ruler.cpp @@ -88,7 +88,8 @@ QString Ruler::format_time_with_distance( pv::util::SIPrefix prefix, pv::util::TimeUnit unit, unsigned precision, - bool sign) + bool sign, + bool show_unit) { const unsigned limit = 60; @@ -97,7 +98,7 @@ QString Ruler::format_time_with_distance( // If we have to use samples then we have no alternative formats if (unit == pv::util::TimeUnit::Samples) - return pv::util::format_time_si_adjusted(t, prefix, precision, "sa", sign); + return pv::util::format_time_si_adjusted(t, prefix, precision, show_unit ? "sa" : NULL, sign); // View zoomed way out -> low precision (0), big distance (>=60s) // -> DD:HH:MM @@ -109,7 +110,7 @@ QString Ruler::format_time_with_distance( // View zoomed way in -> high precision (>3), low step size (<1s) // -> HH:MM:SS.mmm... or xxxx (si unit) if less than limit seconds if (abs(t) < limit) - return pv::util::format_time_si_adjusted(t, prefix, precision, "s", sign); + return pv::util::format_time_si_adjusted(t, prefix, precision, show_unit ? "s" : NULL, sign); else return pv::util::format_time_minutes(t, precision, sign); } diff --git a/pv/views/trace/ruler.hpp b/pv/views/trace/ruler.hpp index 5035bfc8..3a9fea91 100644 --- a/pv/views/trace/ruler.hpp +++ b/pv/views/trace/ruler.hpp @@ -115,7 +115,8 @@ public: pv::util::SIPrefix prefix = pv::util::SIPrefix::unspecified, pv::util::TimeUnit unit = pv::util::TimeUnit::Time, unsigned precision = 0, - bool sign = true); + bool sign = true, + bool show_unit = true); pv::util::Timestamp get_absolute_time_from_x_pos(uint32_t x) const; pv::util::Timestamp get_ruler_time_from_x_pos(uint32_t x) const;