]> sigrok.org Git - pulseview.git/blobdiff - pv/view/view.cpp
View: Use max time to calculate label length, not offset_
[pulseview.git] / pv / view / view.cpp
index 42b22258dd59d2b0079ef6e1246b9382832e1166..e6be30e0680b48670a885fb0630d25209b9953b7 100644 (file)
@@ -104,6 +104,7 @@ View::View(Session &session, QWidget *parent) :
        always_zoom_to_fit_(false),
        tick_period_(0.0),
        tick_prefix_(0),
+       tick_precision_(0),
        time_unit_(util::Time),
        show_cursors_(false),
        cursors_(new CursorPair(*this)),
@@ -118,7 +119,7 @@ View::View(Session &session, QWidget *parent) :
        connect(&session_, SIGNAL(signals_changed()),
                this, SLOT(signals_changed()));
        connect(&session_, SIGNAL(capture_state_changed(int)),
-               this, SLOT(data_updated()));
+               this, SLOT(capture_state_updated(int)));
        connect(&session_, SIGNAL(data_received()),
                this, SLOT(data_updated()));
        connect(&session_, SIGNAL(frame_ended()),
@@ -236,6 +237,11 @@ unsigned int View::tick_prefix() const
        return tick_prefix_;
 }
 
+unsigned int View::tick_precision() const
+{
+       return tick_precision_;
+}
+
 double View::tick_period() const
 {
        return tick_period_;
@@ -490,7 +496,13 @@ void View::calculate_tick_spacing()
        const double SpacingIncrement = 32.0f;
        const double MinValueSpacing = 32.0f;
 
-       double min_width = SpacingIncrement, typical_width;
+       // Figure out the highest numeric value visible on a label
+       const QSize areaSize = viewport_->size();
+       const double max_time = max(fabs(offset_),
+               fabs(offset_ + scale_ * areaSize.width()));
+
+       double min_width = SpacingIncrement;
+       double label_width, tick_period_width;
 
        QFontMetrics m(QApplication::font());
 
@@ -509,14 +521,22 @@ void View::calculate_tick_spacing()
 
                tick_prefix_ = (order - pv::util::FirstSIPrefixPower) / 3;
 
-               typical_width = m.boundingRect(0, 0, INT_MAX, INT_MAX,
-                       Qt::AlignLeft | Qt::AlignTop,
-                       format_time(offset_, tick_prefix_, time_unit_)).width() +
+               // Precision is the number of fractional digits required, not
+               // taking the prefix into account (and it must never be negative)
+               tick_precision_ = std::max((int)ceil(log10f(1 / tick_period_)), 0);
+
+               tick_period_width = tick_period_ / scale_;
+
+               const QString label_text =
+                       format_time(max_time, tick_prefix_, time_unit_, tick_precision_);
+
+               label_width = m.boundingRect(0, 0, INT_MAX, INT_MAX,
+                       Qt::AlignLeft | Qt::AlignTop, label_text).width() +
                                MinValueSpacing;
 
                min_width += SpacingIncrement;
 
-       } while (typical_width > tick_period_ / scale_);
+       } while (tick_period_width < label_width);
 }
 
 void View::update_scroll()
@@ -647,22 +667,23 @@ vector< shared_ptr<Trace> > View::extract_new_traces_for_channels(
 
 void View::determine_time_unit()
 {
-       time_unit_ = util::Samples;
-
-       shared_lock<shared_mutex> lock(session().signals_mutex());
-       const unordered_set< shared_ptr<Signal> > &sigs(session().signals());
-
-       // Check all signals but...
-       for (const shared_ptr<Signal> signal : sigs) {
-               const shared_ptr<SignalData> data = signal->data();
-
-               // ...only check first segment of each
-               const vector< shared_ptr<Segment> > segments = data->segments();
-               if (!segments.empty())
-                       if (segments[0]->samplerate()) {
-                               time_unit_ = util::Time;
-                               break;
-                       }
+       // Check whether we know the sample rate and hence can use time as the unit
+       if (time_unit_ == util::Samples) {
+               shared_lock<shared_mutex> lock(session().signals_mutex());
+               const unordered_set< shared_ptr<Signal> > &sigs(session().signals());
+
+               // Check all signals but...
+               for (const shared_ptr<Signal> signal : sigs) {
+                       const shared_ptr<SignalData> data = signal->data();
+
+                       // ...only check first segment of each
+                       const vector< shared_ptr<Segment> > segments = data->segments();
+                       if (!segments.empty())
+                               if (segments[0]->samplerate()) {
+                                       time_unit_ = util::Time;
+                                       break;
+                               }
+               }
        }
 }
 
@@ -896,14 +917,20 @@ void View::signals_changed()
        viewport_->update();
 }
 
-void View::data_updated()
+void View::capture_state_updated(int state)
 {
        // Reset "always zoom to fit" when we change to the stopped state
-       if (always_zoom_to_fit_ && (session_.get_capture_state() == Session::Stopped)) {
+       if (always_zoom_to_fit_ && (state == Session::Stopped)) {
                always_zoom_to_fit_ = false;
                always_zoom_to_fit_changed(false);
        }
 
+       if (state == Session::Running)
+               time_unit_ = util::Samples;
+}
+
+void View::data_updated()
+{
        if (always_zoom_to_fit_ || sticky_scrolling_) {
                if (!delayed_view_updater_.isActive())
                        delayed_view_updater_.start();