X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fview%2Fview.cpp;h=5e89397aec8e5e71c7732bd7e27faedadb20f40d;hp=a5114027713c0ffa63aab9f754d4855cc9815230;hb=f84000171de7e569590a2f766ae36290b73442da;hpb=f65cd27bdbf70644052dd43dac4bbe9403f4dfee diff --git a/pv/view/view.cpp b/pv/view/view.cpp index a5114027..5e89397a 100644 --- a/pv/view/view.cpp +++ b/pv/view/view.cpp @@ -22,19 +22,22 @@ #include #endif +#include + #include #include #include #include #include +#include #include +#include #include #include #include -#include "cursorheader.hpp" #include "decodetrace.hpp" #include "header.hpp" #include "logicsignal.hpp" @@ -46,12 +49,16 @@ #include "pv/session.hpp" #include "pv/data/logic.hpp" -#include "pv/data/logicsnapshot.hpp" +#include "pv/data/logicsegment.hpp" +#include "pv/util.hpp" using boost::shared_lock; using boost::shared_mutex; + using pv::data::SignalData; -using std::back_inserter; +using pv::data::Segment; +using pv::util::format_time; + using std::deque; using std::dynamic_pointer_cast; using std::list; @@ -75,29 +82,28 @@ const double View::MinScale = 1e-15; const int View::MaxScrollValue = INT_MAX / 2; -const QColor View::CursorAreaColour(220, 231, 243); - -const QSizeF View::LabelPadding(4, 0); +const int View::ScaleUnits[3] = {1, 2, 5}; View::View(Session &session, QWidget *parent) : QAbstractScrollArea(parent), session_(session), viewport_(new Viewport(*this)), ruler_(new Ruler(*this)), - cursorheader_(new CursorHeader(*this)), header_(new Header(*this)), scale_(1e-6), offset_(0), - v_offset_(0), updating_scroll_(false), + tick_period_(0.0), + tick_prefix_(0), show_cursors_(false), - cursors_(*this), + cursors_(new CursorPair(*this)), + next_flag_text_('A'), hover_point_(-1, -1) { connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(h_scroll_value_changed(int))); connect(verticalScrollBar(), SIGNAL(valueChanged(int)), - this, SLOT(v_scroll_value_changed(int))); + this, SLOT(v_scroll_value_changed())); connect(&session_, SIGNAL(signals_changed()), this, SLOT(signals_changed())); @@ -108,22 +114,14 @@ View::View(Session &session, QWidget *parent) : connect(&session_, SIGNAL(frame_ended()), this, SLOT(data_updated())); - connect(cursors_.first().get(), SIGNAL(time_changed()), - this, SLOT(marker_time_changed())); - connect(cursors_.second().get(), SIGNAL(time_changed()), - this, SLOT(marker_time_changed())); - - connect(header_, SIGNAL(signals_moved()), - this, SLOT(on_signals_moved())); - connect(header_, SIGNAL(selection_changed()), - cursorheader_, SLOT(clear_selection())); - connect(cursorheader_, SIGNAL(selection_changed()), + ruler_, SLOT(clear_selection())); + connect(ruler_, SIGNAL(selection_changed()), header_, SLOT(clear_selection())); connect(header_, SIGNAL(selection_changed()), this, SIGNAL(selection_changed())); - connect(cursorheader_, SIGNAL(selection_changed()), + connect(ruler_, SIGNAL(selection_changed()), this, SIGNAL(selection_changed())); connect(this, SIGNAL(hover_point_changed()), @@ -137,7 +135,6 @@ View::View(Session &session, QWidget *parent) : viewport_->installEventFilter(this); ruler_->installEventFilter(this); - cursorheader_->installEventFilter(this); header_->installEventFilter(this); // Trigger the initial event manually. The default device has signals @@ -145,8 +142,11 @@ View::View(Session &session, QWidget *parent) : signals_changed(); // make sure the transparent widgets are on the top - cursorheader_->raise(); + ruler_->raise(); header_->raise(); + + // Update the zoom state + calculate_tick_spacing(); } Session& View::session() @@ -179,6 +179,16 @@ const Viewport* View::viewport() const return viewport_; } +vector< shared_ptr > View::time_items() const +{ + const vector> f(flags()); + vector> items(f.begin(), f.end()); + items.push_back(cursors_); + items.push_back(cursors_->first()); + items.push_back(cursors_->second()); + return items; +} + double View::scale() const { return scale_; @@ -191,7 +201,7 @@ double View::offset() const int View::owner_visual_v_offset() const { - return -v_offset_; + return -verticalScrollBar()->sliderPosition(); } unsigned int View::depth() const @@ -199,6 +209,16 @@ unsigned int View::depth() const return 0; } +unsigned int View::tick_prefix() const +{ + return tick_prefix_; +} + +double View::tick_period() const +{ + return tick_period_; +} + void View::zoom(double steps) { zoom(steps, viewport_->width() / 2); @@ -237,7 +257,10 @@ void View::zoom_one_to_one() double samplerate = 0.0; for (const shared_ptr d : visible_data) { assert(d); - samplerate = max(samplerate, d->samplerate()); + const vector< shared_ptr > segments = + d->segments(); + for (const shared_ptr &s : segments) + samplerate = max(samplerate, s->samplerate()); } if (samplerate == 0.0) @@ -256,9 +279,10 @@ void View::set_scale_offset(double scale, double offset) scale_ = scale; offset_ = offset; + calculate_tick_spacing(); + update_scroll(); ruler_->update(); - cursorheader_->update(); viewport_->update(); scale_offset_changed(); } @@ -279,22 +303,26 @@ set< shared_ptr > View::get_visible_data() const pair View::get_time_extents() const { - const set< shared_ptr > visible_data = get_visible_data(); - if (visible_data.empty()) - return make_pair(0.0, 0.0); - double left_time = DBL_MAX, right_time = DBL_MIN; + const set< shared_ptr > visible_data = get_visible_data(); for (const shared_ptr d : visible_data) { - const double start_time = d->get_start_time(); - double samplerate = d->samplerate(); - samplerate = (samplerate <= 0.0) ? 1.0 : samplerate; - - left_time = min(left_time, start_time); - right_time = max(right_time, start_time + - d->get_max_sample_count() / samplerate); + const vector< shared_ptr > segments = + d->segments(); + for (const shared_ptr &s : segments) { + double samplerate = s->samplerate(); + samplerate = (samplerate <= 0.0) ? 1.0 : samplerate; + + const double start_time = s->start_time(); + left_time = min(left_time, start_time); + right_time = max(right_time, start_time + + d->get_max_sample_count() / samplerate); + } } + if (left_time == DBL_MAX && right_time == DBL_MIN) + return make_pair(0.0, 0.0); + assert(left_time < right_time); return make_pair(left_time, right_time); } @@ -307,27 +335,48 @@ bool View::cursors_shown() const void View::show_cursors(bool show) { show_cursors_ = show; - cursorheader_->update(); + ruler_->update(); viewport_->update(); } void View::centre_cursors() { const double time_width = scale_ * viewport_->width(); - cursors_.first()->set_time(offset_ + time_width * 0.4); - cursors_.second()->set_time(offset_ + time_width * 0.6); - cursorheader_->update(); + cursors_->first()->set_time(offset_ + time_width * 0.4); + cursors_->second()->set_time(offset_ + time_width * 0.6); + ruler_->update(); viewport_->update(); } -CursorPair& View::cursors() +std::shared_ptr View::cursors() const { return cursors_; } -const CursorPair& View::cursors() const +void View::add_flag(double time) { - return cursors_; + flags_.push_back(shared_ptr(new Flag(*this, time, + QString("%1").arg(next_flag_text_)))); + next_flag_text_ = (next_flag_text_ >= 'Z') ? 'A' : + (next_flag_text_ + 1); + time_item_appearance_changed(true, true); +} + +void View::remove_flag(std::shared_ptr flag) +{ + flags_.remove(flag); + time_item_appearance_changed(true, true); +} + +vector< std::shared_ptr > View::flags() const +{ + vector< std::shared_ptr > flags(flags_.begin(), flags_.end()); + stable_sort(flags.begin(), flags.end(), + [](const shared_ptr &a, const shared_ptr &b) { + return a->time() < b->time(); + }); + + return flags; } const QPoint& View::hover_point() const @@ -379,6 +428,40 @@ void View::set_zoom(double scale, int offset) set_scale_offset(new_scale, new_offset); } +void View::calculate_tick_spacing() +{ + const double SpacingIncrement = 32.0f; + const double MinValueSpacing = 32.0f; + + double min_width = SpacingIncrement, typical_width; + + QFontMetrics m(QApplication::font()); + + do { + const double min_period = scale_ * min_width; + + const int order = (int)floorf(log10f(min_period)); + const double order_decimal = pow(10.0, order); + + unsigned int unit = 0; + + do { + tick_period_ = order_decimal * ScaleUnits[unit++]; + } while (tick_period_ < min_period && + unit < countof(ScaleUnits)); + + 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_)).width() + + MinValueSpacing; + + min_width += SpacingIncrement; + + } while(typical_width > tick_period_ / scale_); +} + void View::update_scroll() { assert(viewport_); @@ -390,7 +473,10 @@ void View::update_scroll() get_scroll_layout(length, offset); length = max(length - areaSize.width(), 0.0); + int major_tick_distance = tick_period_ / scale_; + horizontalScrollBar()->setPageStep(areaSize.width() / 2); + horizontalScrollBar()->setSingleStep(major_tick_distance); updating_scroll_ = true; @@ -407,11 +493,11 @@ void View::update_scroll() // Set the vertical scrollbar verticalScrollBar()->setPageStep(areaSize.height()); + verticalScrollBar()->setSingleStep(areaSize.height() / 8); const pair extents = v_extents(); - const int extra_scroll_height = (extents.second - extents.first) / 4; - verticalScrollBar()->setRange(extents.first - extra_scroll_height, - extents.first + extra_scroll_height); + verticalScrollBar()->setRange(extents.first - (areaSize.height() / 2), + extents.second - (areaSize.height() / 2)); } void View::update_layout() @@ -420,26 +506,22 @@ void View::update_layout() header_->sizeHint().width() - pv::view::Header::BaselineOffset, ruler_->sizeHint().height(), 0, 0); ruler_->setGeometry(viewport_->x(), 0, - viewport_->width(), viewport_->y()); - cursorheader_->setGeometry( - viewport_->x(), - ruler_->sizeHint().height() - cursorheader_->sizeHint().height() / 2, - viewport_->width(), cursorheader_->sizeHint().height()); + viewport_->width(), ruler_->extended_size_hint().height()); header_->setGeometry(0, viewport_->y(), - header_->sizeHint().width(), viewport_->height()); + header_->extended_size_hint().width(), viewport_->height()); update_scroll(); } -void View::paint_label(QPainter &p, int right, bool hover) +void View::paint_label(QPainter &p, const QRect &rect, bool hover) { (void)p; - (void)right; + (void)rect; (void)hover; } -QRectF View::label_rect(int right) +QRectF View::label_rect(const QRectF &rect) { - (void)right; + (void)rect; return QRectF(); } @@ -490,7 +572,7 @@ bool View::eventFilter(QObject *object, QEvent *event) const QMouseEvent *const mouse_event = (QMouseEvent*)event; if (object == viewport_) hover_point_ = mouse_event->pos(); - else if (object == ruler_ || object == cursorheader_) + else if (object == ruler_) hover_point_ = QPoint(mouse_event->x(), 0); else if (object == header_) hover_point_ = QPoint(0, mouse_event->y()); @@ -531,7 +613,7 @@ void View::resizeEvent(QResizeEvent*) update_layout(); } -void View::appearance_changed(bool label, bool content) +void View::row_item_appearance_changed(bool label, bool content) { if (label) header_->update(); @@ -539,11 +621,19 @@ void View::appearance_changed(bool label, bool content) viewport_->update(); } +void View::time_item_appearance_changed(bool label, bool content) +{ + if (label) + ruler_->update(); + if (content) + viewport_->update(); +} + void View::extents_changed(bool horz, bool vert) { sticky_events_ |= - (horz ? SelectableItemHExtentsChanged : 0) | - (vert ? SelectableItemVExtentsChanged : 0); + (horz ? RowItemHExtentsChanged : 0) | + (vert ? RowItemVExtentsChanged : 0); lazy_event_handler_.start(); } @@ -562,13 +652,11 @@ void View::h_scroll_value_changed(int value) } ruler_->update(); - cursorheader_->update(); viewport_->update(); } -void View::v_scroll_value_changed(int value) +void View::v_scroll_value_changed() { - v_offset_ = value; header_->update(); viewport_->update(); } @@ -652,24 +740,14 @@ void View::data_updated() viewport_->update(); } -void View::marker_time_changed() -{ - cursorheader_->update(); - viewport_->update(); -} - -void View::on_signals_moved() -{ - update_scroll(); - signals_moved(); -} - void View::process_sticky_events() { - if (sticky_events_ & SelectableItemHExtentsChanged) + if (sticky_events_ & RowItemHExtentsChanged) update_layout(); - if (sticky_events_ & SelectableItemVExtentsChanged) + if (sticky_events_ & RowItemVExtentsChanged) { restack_all_row_items(); + update_scroll(); + } // Clear the sticky events sticky_events_ = 0;