From bf0edd2b0cbb5f4bd5d69b0f00bcea7d037e2287 Mon Sep 17 00:00:00 2001 From: Soeren Apel Date: Tue, 16 Aug 2016 21:09:58 +0200 Subject: [PATCH] Introduce pv::data::SignalBase --- CMakeLists.txt | 2 + pv/data/signalbase.cpp | 103 +++++++++++++++++++++++++++++++++ pv/data/signalbase.hpp | 119 +++++++++++++++++++++++++++++++++++++++ pv/popups/channels.cpp | 41 +++++++------- pv/popups/channels.hpp | 10 +++- pv/session.cpp | 30 ++++++---- pv/session.hpp | 5 +- pv/storesession.cpp | 7 ++- pv/storesession.hpp | 4 +- pv/view/analogsignal.cpp | 13 ++--- pv/view/analogsignal.hpp | 3 +- pv/view/decodetrace.cpp | 14 +++-- pv/view/decodetrace.hpp | 4 +- pv/view/logicsignal.cpp | 15 ++--- pv/view/logicsignal.hpp | 2 +- pv/view/signal.cpp | 29 +++++----- pv/view/signal.hpp | 16 +++--- pv/view/trace.cpp | 96 ++++++++++++++++--------------- pv/view/trace.hpp | 31 +++++----- pv/view/view.cpp | 42 +++++++------- pv/view/view.hpp | 4 +- test/CMakeLists.txt | 2 + 22 files changed, 422 insertions(+), 170 deletions(-) create mode 100644 pv/data/signalbase.cpp create mode 100644 pv/data/signalbase.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 49c35ca..532e6f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,6 +216,7 @@ set(pulseview_SOURCES pv/data/analogsegment.cpp pv/data/logic.cpp pv/data/logicsegment.cpp + pv/data/signalbase.cpp pv/data/signaldata.cpp pv/data/segment.cpp pv/devices/device.cpp @@ -280,6 +281,7 @@ set(pulseview_HEADERS pv/session.hpp pv/storesession.hpp pv/binding/device.hpp + pv/data/signalbase.hpp pv/dialogs/about.hpp pv/dialogs/connect.hpp pv/dialogs/inputoutputoptions.hpp diff --git a/pv/data/signalbase.cpp b/pv/data/signalbase.cpp new file mode 100644 index 0000000..55397ed --- /dev/null +++ b/pv/data/signalbase.cpp @@ -0,0 +1,103 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2012 Joel Holdsworth + * Copyright (C) 2016 Soeren Apel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "signalbase.hpp" + +using std::shared_ptr; + +using sigrok::Channel; +using sigrok::ChannelType; + +namespace pv { +namespace data { + +const int SignalBase::ColourBGAlpha = 8*256/100; + +SignalBase::SignalBase(shared_ptr channel) : + channel_(channel) +{ +} + +shared_ptr SignalBase::channel() const +{ + return channel_; +} + +QString SignalBase::name() const +{ + return (channel_) ? QString::fromStdString(channel_->name()) : name_; +} + +void SignalBase::set_name(QString name) +{ + if (channel_) + channel_->set_name(name.toUtf8().constData()); + + name_ = name; + + name_changed(name); +} + +bool SignalBase::enabled() const +{ + return (channel_) ? channel_->enabled() : true; +} + +void SignalBase::set_enabled(bool value) +{ + if (channel_) { + channel_->set_enabled(value); + enabled_changed(value); + } +} + +const ChannelType *SignalBase::type() const +{ + return (channel_) ? channel_->type() : nullptr; +} + +unsigned int SignalBase::index() const +{ + return (channel_) ? channel_->index() : (unsigned int)-1; +} + +QColor SignalBase::colour() const +{ + return colour_; +} + +void SignalBase::set_colour(QColor colour) +{ + colour_ = colour; + + bgcolour_ = colour; + bgcolour_.setAlpha(ColourBGAlpha); + + colour_changed(colour); +} + +QColor SignalBase::bgcolour() const +{ + return bgcolour_; +} + +} // namespace data +} // namespace pv diff --git a/pv/data/signalbase.hpp b/pv/data/signalbase.hpp new file mode 100644 index 0000000..db1af1c --- /dev/null +++ b/pv/data/signalbase.hpp @@ -0,0 +1,119 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2012 Joel Holdsworth + * Copyright (C) 2016 Soeren Apel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef PULSEVIEW_PV_DATA_SIGNALBASE_HPP +#define PULSEVIEW_PV_DATA_SIGNALBASE_HPP + +#include +#include +#include + +#include + + +namespace sigrok { +class Channel; +class ChannelType; +} + +namespace pv { +namespace data { + +class SignalBase : public QObject +{ + Q_OBJECT + +private: + static const int ColourBGAlpha; + +public: + SignalBase(std::shared_ptr channel); + virtual ~SignalBase() {} + +public: + /** + * Returns the underlying SR channel. + */ + std::shared_ptr channel() const; + + /** + * Returns enabled status of this channel. + */ + bool enabled() const; + + /** + * Sets the enabled status of this channel. + * @param value Boolean value to set. + */ + void set_enabled(bool value); + + /** + * Gets the type of this channel. + */ + const sigrok::ChannelType *type() const; + + /** + * Gets the index number of this channel. + */ + unsigned int index() const; + + /** + * Gets the name of this signal. + */ + QString name() const; + + /** + * Sets the name of the signal. + */ + virtual void set_name(QString name); + + /** + * Get the colour of the signal. + */ + QColor colour() const; + + /** + * Set the colour of the signal. + */ + void set_colour(QColor colour); + + /** + * Get the background colour of the signal. + */ + QColor bgcolour() const; + +Q_SIGNALS: + void enabled_changed(const bool &value); + + void name_changed(const QString &name); + + void colour_changed(const QColor &colour); + +private: + std::shared_ptr channel_; + QString name_; + QColor colour_, bgcolour_; +}; + +} // namespace data +} // namespace pv + +#endif // PULSEVIEW_PV_DATA_SIGNALBASE_HPP diff --git a/pv/popups/channels.cpp b/pv/popups/channels.cpp index c338858..7489b93 100644 --- a/pv/popups/channels.cpp +++ b/pv/popups/channels.cpp @@ -36,6 +36,7 @@ #include "channels.hpp" #include +#include #include #include #include @@ -54,12 +55,12 @@ using std::shared_ptr; using std::unordered_set; using std::vector; +using pv::data::SignalBase; + using sigrok::Channel; using sigrok::ChannelGroup; using sigrok::Device; -using pv::view::Signal; - namespace pv { namespace popups { @@ -78,11 +79,13 @@ Channels::Channels(Session &session, QWidget *parent) : assert(device); // Collect a set of signals - map, shared_ptr > signal_map; + map, shared_ptr > signal_map; - const unordered_set< shared_ptr > sigs(session_.signals()); + unordered_set< shared_ptr > sigs; + for (const shared_ptr s : session_.signals()) + sigs.insert(s->channel()); - for (const shared_ptr &sig : sigs) + for (const shared_ptr &sig : sigs) signal_map[sig->channel()] = sig; // Populate channel groups @@ -90,7 +93,7 @@ Channels::Channels(Session &session, QWidget *parent) : shared_ptr group = entry.second; // Make a set of signals, and removed this signals from the // signal map. - vector< shared_ptr > group_sigs; + vector< shared_ptr > group_sigs; for (auto channel : group->channels()) { const auto iter = signal_map.find(channel); @@ -105,9 +108,9 @@ Channels::Channels(Session &session, QWidget *parent) : } // Make a vector of the remaining channels - vector< shared_ptr > global_sigs; + vector< shared_ptr > global_sigs; for (auto channel : device->channels()) { - const map, shared_ptr >:: + const map, shared_ptr >:: const_iterator iter = signal_map.find(channel); if (iter != signal_map.end()) global_sigs.push_back((*iter).second); @@ -140,13 +143,13 @@ void Channels::set_all_channels(bool set) { updating_channels_ = true; - for (map >::const_iterator i = + for (map >::const_iterator i = check_box_signal_map_.begin(); i != check_box_signal_map_.end(); i++) { - const shared_ptr sig = (*i).second; + const shared_ptr sig = (*i).second; assert(sig); - sig->enable(set); + sig->set_enabled(set); (*i).first->setChecked(set); } @@ -154,7 +157,7 @@ void Channels::set_all_channels(bool set) } void Channels::populate_group(shared_ptr group, - const vector< shared_ptr > sigs) + const vector< shared_ptr > sigs) { using pv::binding::Device; @@ -185,12 +188,12 @@ void Channels::populate_group(shared_ptr group, } QGridLayout* Channels::create_channel_group_grid( - const vector< shared_ptr > sigs) + const vector< shared_ptr > sigs) { int row = 0, col = 0; QGridLayout *const grid = new QGridLayout(); - for (const shared_ptr& sig : sigs) { + for (const shared_ptr& sig : sigs) { assert(sig); QCheckBox *const checkbox = new QCheckBox(sig->name()); @@ -215,10 +218,10 @@ void Channels::showEvent(QShowEvent *event) updating_channels_ = true; - for (map >::const_iterator i = + for (map >::const_iterator i = check_box_signal_map_.begin(); i != check_box_signal_map_.end(); i++) { - const shared_ptr sig = (*i).second; + const shared_ptr sig = (*i).second; assert(sig); (*i).first->setChecked(sig->enabled()); @@ -236,14 +239,14 @@ void Channels::on_channel_checked(QWidget *widget) assert(check_box); // Look up the signal of this check-box - map< QCheckBox*, shared_ptr >::const_iterator iter = + map< QCheckBox*, shared_ptr >::const_iterator iter = check_box_signal_map_.find((QCheckBox*)check_box); assert(iter != check_box_signal_map_.end()); - const shared_ptr s = (*iter).second; + const shared_ptr s = (*iter).second; assert(s); - s->enable(check_box->isChecked()); + s->set_enabled(check_box->isChecked()); } void Channels::enable_all_channels() diff --git a/pv/popups/channels.hpp b/pv/popups/channels.hpp index 5ed5d47..25cd0ae 100644 --- a/pv/popups/channels.hpp +++ b/pv/popups/channels.hpp @@ -47,6 +47,10 @@ namespace binding { class Device; } +namespace data { +class SignalBase; +} + namespace view { class Signal; } @@ -64,10 +68,10 @@ private: void set_all_channels(bool set); void populate_group(std::shared_ptr group, - const std::vector< std::shared_ptr > sigs); + const std::vector< std::shared_ptr > sigs); QGridLayout* create_channel_group_grid( - const std::vector< std::shared_ptr > sigs); + const std::vector< std::shared_ptr > sigs); private: void showEvent(QShowEvent *event); @@ -87,7 +91,7 @@ private: std::vector< std::shared_ptr > group_bindings_; - std::map< QCheckBox*, std::shared_ptr > + std::map< QCheckBox*, std::shared_ptr > check_box_signal_map_; QHBoxLayout buttons_bar_; diff --git a/pv/session.cpp b/pv/session.cpp index b8e98ec..9c3a2c2 100644 --- a/pv/session.cpp +++ b/pv/session.cpp @@ -39,6 +39,7 @@ #include "data/decoderstack.hpp" #include "data/logic.hpp" #include "data/logicsegment.hpp" +#include "data/signalbase.hpp" #include "data/decode/decoder.hpp" #include "devices/hardwaredevice.hpp" @@ -298,7 +299,7 @@ bool Session::add_decoder(srd_decoder *const dec) dynamic_pointer_cast(s); if (l && QString::fromUtf8(pdch->name). toLower().contains( - l->name().toLower())) + s->channel()->name().toLower())) channels[pdch] = l; } @@ -308,8 +309,11 @@ bool Session::add_decoder(srd_decoder *const dec) decoder_stack->stack().front()->set_channels(channels); // Create the decode signal + shared_ptr signalbase = + shared_ptr(new data::SignalBase(nullptr)); + shared_ptr d( - new view::DecodeTrace(*this, decoder_stack, + new view::DecodeTrace(*this, signalbase, decoder_stack, decode_traces_.size())); decode_traces_.push_back(d); } catch (std::runtime_error e) { @@ -401,13 +405,14 @@ void Session::update_signals() signals_.clear(); for (auto channel : sr_dev->channels()) { + shared_ptr signalbase; shared_ptr signal; // Find the channel in the old signals const auto iter = std::find_if( prev_sigs.cbegin(), prev_sigs.cend(), [&](const shared_ptr &s) { - return s->channel() == channel; + return s->channel()->channel() == channel; }); if (iter != prev_sigs.end()) { // Copy the signal from the old set to the new @@ -419,13 +424,16 @@ void Session::update_signals() logic_data_); } else { // Create a new signal + signalbase = shared_ptr( + new data::SignalBase(channel)); + switch(channel->type()->id()) { case SR_CHANNEL_LOGIC: signal = shared_ptr( new view::LogicSignal(*this, - device_, channel, - logic_data_)); + device_, signalbase, logic_data_)); all_signal_data_.insert(logic_data_); + signalbases_.insert(signalbase); break; case SR_CHANNEL_ANALOG: @@ -434,8 +442,9 @@ void Session::update_signals() new data::Analog()); signal = shared_ptr( new view::AnalogSignal( - *this, channel, data)); + *this, signalbase, data)); all_signal_data_.insert(data); + signalbases_.insert(signalbase); break; } @@ -453,16 +462,15 @@ void Session::update_signals() signals_changed(); } -shared_ptr Session::signal_from_channel( - shared_ptr channel) const +shared_ptr Session::signal_from_channel( + shared_ptr channel) const { - lock_guard lock(signals_mutex_); - for (shared_ptr sig : signals_) { + for (shared_ptr sig : signalbases_) { assert(sig); if (sig->channel() == channel) return sig; } - return shared_ptr(); + return shared_ptr(); } void Session::sample_thread_proc(function error_handler) diff --git a/pv/session.hpp b/pv/session.hpp index e113cf4..4c6c73e 100644 --- a/pv/session.hpp +++ b/pv/session.hpp @@ -64,6 +64,7 @@ class Analog; class AnalogSegment; class Logic; class LogicSegment; +class SignalBase; class SignalData; } @@ -133,7 +134,7 @@ private: void update_signals(); - std::shared_ptr signal_from_channel( + std::shared_ptr signal_from_channel( std::shared_ptr channel) const; private: @@ -165,6 +166,8 @@ private: mutable boost::shared_mutex signals_mutex_; std::unordered_set< std::shared_ptr > signals_; + + std::set< std::shared_ptr > signalbases_; std::set< std::shared_ptr > all_signal_data_; mutable std::recursive_mutex data_mutex_; diff --git a/pv/storesession.cpp b/pv/storesession.cpp index 2a4c850..f8ab2e6 100644 --- a/pv/storesession.cpp +++ b/pv/storesession.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -109,7 +110,7 @@ bool StoreSession::start() shared_ptr any_segment; shared_ptr lsegment; - vector< shared_ptr > achannel_list; + vector< shared_ptr > achannel_list; vector< shared_ptr > asegment_list; for (shared_ptr signal : sigs) { @@ -214,7 +215,7 @@ void StoreSession::cancel() interrupt_ = true; } -void StoreSession::store_proc(vector< shared_ptr > achannel_list, +void StoreSession::store_proc(vector< shared_ptr > achannel_list, vector< shared_ptr > asegment_list, shared_ptr lsegment) { @@ -259,7 +260,7 @@ void StoreSession::store_proc(vector< shared_ptr > achannel_lis const auto context = session_.device_manager().context(); for (unsigned int i = 0; i < achannel_list.size(); i++) { - shared_ptr achannel = achannel_list.at(i); + shared_ptr achannel = (achannel_list.at(i))->channel(); shared_ptr asegment = asegment_list.at(i); const float *adata = diff --git a/pv/storesession.hpp b/pv/storesession.hpp index 6976b31..07d3c2f 100644 --- a/pv/storesession.hpp +++ b/pv/storesession.hpp @@ -36,7 +36,6 @@ #include namespace sigrok { -class Channel; class Output; class OutputFormat; } @@ -46,6 +45,7 @@ namespace pv { class Session; namespace data { +class SignalBase; class AnalogSegment; class LogicSegment; } @@ -77,7 +77,7 @@ public: void cancel(); private: - void store_proc(std::vector< std::shared_ptr > achannel_list, + void store_proc(std::vector< std::shared_ptr > achannel_list, std::vector< std::shared_ptr > asegment_list, std::shared_ptr lsegment); diff --git a/pv/view/analogsignal.cpp b/pv/view/analogsignal.cpp index 9001924..8ccad39 100644 --- a/pv/view/analogsignal.cpp +++ b/pv/view/analogsignal.cpp @@ -36,6 +36,7 @@ #include "analogsignal.hpp" #include "pv/data/analog.hpp" #include "pv/data/analogsegment.hpp" +#include "pv/data/signalbase.hpp" #include "pv/view/view.hpp" #include @@ -46,8 +47,6 @@ using std::min; using std::shared_ptr; using std::deque; -using sigrok::Channel; - namespace pv { namespace view { @@ -72,7 +71,7 @@ const int AnalogSignal::InfoTextMarginBottom = 5; AnalogSignal::AnalogSignal( pv::Session &session, - shared_ptr channel, + shared_ptr channel, shared_ptr data) : Signal(session, channel), data_(data), @@ -82,7 +81,7 @@ AnalogSignal::AnalogSignal( vdivs_(1), resolution_(0) { - set_colour(SignalColours[channel_->index() % countof(SignalColours)]); + channel_->set_colour(SignalColours[channel_->index() % countof(SignalColours)]); update_scale(); } @@ -187,7 +186,7 @@ void AnalogSignal::paint_fore(QPainter &p, const ViewItemPaintParams &pp) // Show the info section on the right side of the trace const QString infotext = QString("%1 V/div").arg(resolution_); - p.setPen(colour_); + p.setPen(channel_->colour()); p.setFont(QApplication::font()); const QRectF bounding_rect = QRectF(pp.left(), @@ -236,7 +235,7 @@ void AnalogSignal::paint_trace(QPainter &p, const float *const samples = segment->get_samples(start, end); assert(samples); - p.setPen(colour_); + p.setPen(channel_->colour()); QPointF *points = new QPointF[sample_count]; QPointF *point = points; @@ -268,7 +267,7 @@ void AnalogSignal::paint_envelope(QPainter &p, return; p.setPen(QPen(Qt::NoPen)); - p.setBrush(colour_); + p.setBrush(channel_->colour()); QRectF *const rects = new QRectF[e.length]; QRectF *rect = rects; diff --git a/pv/view/analogsignal.hpp b/pv/view/analogsignal.hpp index 47a9980..601ae11 100644 --- a/pv/view/analogsignal.hpp +++ b/pv/view/analogsignal.hpp @@ -32,6 +32,7 @@ namespace pv { namespace data { class Analog; class AnalogSegment; +class SignalBase; } namespace view { @@ -52,7 +53,7 @@ private: public: AnalogSignal(pv::Session &session, - std::shared_ptr channel, + std::shared_ptr channel, std::shared_ptr data); virtual ~AnalogSignal() = default; diff --git a/pv/view/decodetrace.cpp b/pv/view/decodetrace.cpp index c2369e8..3ece130 100644 --- a/pv/view/decodetrace.cpp +++ b/pv/view/decodetrace.cpp @@ -129,10 +129,11 @@ const QColor DecodeTrace::OutlineColours[16] = { }; DecodeTrace::DecodeTrace(pv::Session &session, + shared_ptr signalbase, std::shared_ptr decoder_stack, int index) : - Trace(QString::fromUtf8( - decoder_stack->stack().front()->decoder()->name)), + Trace(signalbase), session_(session), + signalbase_(signalbase), decoder_stack_(decoder_stack), row_height_(0), max_visible_rows_(0), @@ -145,7 +146,8 @@ DecodeTrace::DecodeTrace(pv::Session &session, QFontMetrics m(QApplication::font()); min_useful_label_width_ = m.width("XX"); // e.g. two hex characters - set_colour(DecodeColours[index % countof(DecodeColours)]); + signalbase_->set_name(QString::fromUtf8(decoder_stack->stack().front()->decoder()->name)); + signalbase_->set_colour(DecodeColours[index % countof(DecodeColours)]); connect(decoder_stack_.get(), SIGNAL(new_decode_data()), this, SLOT(on_new_decode_data())); @@ -849,8 +851,8 @@ QComboBox* DecodeTrace::create_channel_selector( vector< shared_ptr > sig_list(sigs.begin(), sigs.end()); std::sort(sig_list.begin(), sig_list.end(), [](const shared_ptr &a, const shared_ptr b) { - return strnatcasecmp(a->name().toStdString(), - b->name().toStdString()) < 0; }); + return strnatcasecmp(a->channel()->name().toStdString(), + b->channel()->name().toStdString()) < 0; }); assert(decoder_stack_); const auto channel_iter = dec->channels().find(pdch); @@ -865,7 +867,7 @@ QComboBox* DecodeTrace::create_channel_selector( for (const shared_ptr &s : sig_list) { assert(s); if (dynamic_pointer_cast(s) && s->enabled()) { - selector->addItem(s->name(), + selector->addItem(s->channel()->name(), qVariantFromValue((void*)s.get())); if (channel_iter != dec->channels().end() && diff --git a/pv/view/decodetrace.hpp b/pv/view/decodetrace.hpp index 2705d3c..96332d9 100644 --- a/pv/view/decodetrace.hpp +++ b/pv/view/decodetrace.hpp @@ -31,6 +31,7 @@ #include #include +#include #include struct srd_channel; @@ -84,7 +85,7 @@ private: static const QColor OutlineColours[16]; public: - DecodeTrace(pv::Session &session, + DecodeTrace(pv::Session &session, std::shared_ptr signalbase, std::shared_ptr decoder_stack, int index); @@ -196,6 +197,7 @@ private Q_SLOTS: private: pv::Session &session_; + std::shared_ptr signalbase_; std::shared_ptr decoder_stack_; uint64_t decode_start_, decode_end_; diff --git a/pv/view/logicsignal.cpp b/pv/view/logicsignal.cpp index 6eb68db..7bb2ee0 100644 --- a/pv/view/logicsignal.cpp +++ b/pv/view/logicsignal.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -49,7 +50,6 @@ using std::pair; using std::shared_ptr; using std::vector; -using sigrok::Channel; using sigrok::ConfigKey; using sigrok::Capability; using sigrok::Error; @@ -99,7 +99,7 @@ QCache LogicSignal::pixmap_cache_; LogicSignal::LogicSignal( pv::Session &session, shared_ptr device, - shared_ptr channel, + shared_ptr channel, shared_ptr data) : Signal(session, channel), signal_height_(QFontMetrics(QApplication::font()).height() * 2), @@ -114,7 +114,7 @@ LogicSignal::LogicSignal( { shared_ptr trigger; - set_colour(SignalColours[channel->index() % countof(SignalColours)]); + channel_->set_colour(SignalColours[channel->index() % countof(SignalColours)]); /* Populate this channel's trigger setting with whatever we * find in the current session trigger, if anything. */ @@ -122,7 +122,7 @@ LogicSignal::LogicSignal( if ((trigger = session_.session()->trigger())) for (auto stage : trigger->stages()) for (auto match : stage->matches()) - if (match->channel() == channel_) + if (match->channel() == channel_->channel()) trigger_match_ = match->type(); } @@ -430,12 +430,12 @@ void LogicSignal::modify_trigger() const auto &matches = stage->matches(); if (std::none_of(matches.begin(), matches.end(), [&](shared_ptr match) { - return match->channel() != channel_; })) + return match->channel() != channel_->channel(); })) continue; auto new_stage = new_trigger->add_stage(); for (auto match : stage->matches()) { - if (match->channel() == channel_) + if (match->channel() == channel_->channel()) continue; new_stage->add_match(match->channel(), match->type()); } @@ -449,7 +449,8 @@ void LogicSignal::modify_trigger() if (new_trigger->stages().empty()) new_trigger->add_stage(); - new_trigger->stages().back()->add_match(channel_, trigger_match_); + new_trigger->stages().back()->add_match(channel_->channel(), + trigger_match_); } session_.session()->set_trigger( diff --git a/pv/view/logicsignal.hpp b/pv/view/logicsignal.hpp index fc0dcab..9bd91ba 100644 --- a/pv/view/logicsignal.hpp +++ b/pv/view/logicsignal.hpp @@ -66,7 +66,7 @@ private: public: LogicSignal(pv::Session &session, std::shared_ptr device, - std::shared_ptr channel, + std::shared_ptr channel, std::shared_ptr data); virtual ~LogicSignal() = default; diff --git a/pv/view/signal.cpp b/pv/view/signal.cpp index 5cd5b18..fc90eba 100644 --- a/pv/view/signal.cpp +++ b/pv/view/signal.cpp @@ -31,14 +31,14 @@ #include +#include "pv/data/signalbase.hpp" + #include "signal.hpp" #include "view.hpp" using std::shared_ptr; using std::make_shared; -using sigrok::Channel; - namespace pv { namespace view { @@ -60,10 +60,9 @@ const char *const ChannelNames[] = { }; Signal::Signal(pv::Session &session, - std::shared_ptr channel) : - Trace(QString::fromUtf8(channel->name().c_str())), + std::shared_ptr channel) : + Trace(channel), session_(session), - channel_(channel), scale_handle_(make_shared(*this)), items_({scale_handle_}), name_widget_(nullptr) @@ -77,10 +76,6 @@ void Signal::set_name(QString name) if (name != name_widget_->currentText()) name_widget_->setEditText(name); - - // Store the channel name in sigrok::Channel so that it - // will end up in the .sr file upon save. - channel_->set_name(name.toUtf8().constData()); } bool Signal::enabled() const @@ -96,7 +91,7 @@ void Signal::enable(bool enable) owner_->extents_changed(true, true); } -shared_ptr Signal::channel() const +shared_ptr Signal::channel() const { return channel_; } @@ -121,17 +116,17 @@ void Signal::populate_popup_form(QWidget *parent, QFormLayout *form) for (unsigned int i = 0; i < countof(ChannelNames); i++) name_widget_->insertItem(i, ChannelNames[i]); - const int index = name_widget_->findText(name_, Qt::MatchExactly); + const int index = name_widget_->findText(channel_->name(), Qt::MatchExactly); if (index == -1) { - name_widget_->insertItem(0, name_); + name_widget_->insertItem(0, channel_->name()); name_widget_->setCurrentIndex(0); } else { name_widget_->setCurrentIndex(index); } connect(name_widget_, SIGNAL(editTextChanged(const QString&)), - this, SLOT(on_text_changed(const QString&))); + this, SLOT(on_nameedit_changed(const QString&))); form->addRow(tr("Name"), name_widget_); @@ -157,6 +152,14 @@ void Signal::delete_pressed() on_disable(); } +void Signal::on_name_changed(const QString &text) +{ + if (text != name_widget_->currentText()) + name_widget_->setEditText(text); + + Trace::on_name_changed(text); +} + void Signal::on_disable() { enable(false); diff --git a/pv/view/signal.hpp b/pv/view/signal.hpp index 517bbf4..36d87d4 100644 --- a/pv/view/signal.hpp +++ b/pv/view/signal.hpp @@ -32,15 +32,12 @@ #include "trace.hpp" #include "viewitemowner.hpp" -namespace sigrok { - class Channel; -} - namespace pv { class Session; namespace data { +class SignalBase; class SignalData; } @@ -52,13 +49,13 @@ class Signal : public Trace, public ViewItemOwner protected: Signal(pv::Session &session, - std::shared_ptr channel); + std::shared_ptr channel); public: /** * Sets the name of the signal. */ - void set_name(QString name); + virtual void set_name(QString name); virtual std::shared_ptr data() const = 0; @@ -69,7 +66,7 @@ public: void enable(bool enable = true); - std::shared_ptr channel() const; + std::shared_ptr channel() const; /** * Returns a list of row items owned by this object. @@ -100,12 +97,13 @@ public: */ virtual void scale_handle_released() {}; -private Q_SLOTS: +protected Q_SLOTS: + virtual void on_name_changed(const QString &text); + void on_disable(); protected: pv::Session &session_; - std::shared_ptr channel_; const std::shared_ptr scale_handle_; const item_list items_; diff --git a/pv/view/trace.cpp b/pv/view/trace.cpp index 87d3dc1..d6a4fec 100644 --- a/pv/view/trace.cpp +++ b/pv/view/trace.cpp @@ -41,39 +41,19 @@ namespace view { const QPen Trace::AxisPen(QColor(0, 0, 0, 30*256/100)); const int Trace::LabelHitPadding = 2; -const int Trace::ColourBGAlpha = 8*256/100; const QColor Trace::BrightGrayBGColour = QColor(0, 0, 0, 10*255/100); const QColor Trace::DarkGrayBGColour = QColor(0, 0, 0, 15*255/100); -Trace::Trace(QString name) : - name_(name), +Trace::Trace(std::shared_ptr channel) : + channel_(channel), coloured_bg_(true), // Default setting is set in MainWindow::setup_ui() popup_(nullptr), popup_form_(nullptr) { -} - -QString Trace::name() const -{ - return name_; -} - -void Trace::set_name(QString name) -{ - name_ = name; -} - -QColor Trace::colour() const -{ - return colour_; -} - -void Trace::set_colour(QColor colour) -{ - colour_ = colour; - - bgcolour_ = colour; - bgcolour_.setAlpha(ColourBGAlpha); + connect(channel.get(), SIGNAL(name_changed(const QString&)), + this, SLOT(on_name_changed(const QString&))); + connect(channel.get(), SIGNAL(colour_changed(const QColor&)), + this, SLOT(on_colour_changed(const QColor&))); } void Trace::set_coloured_bg(bool state) @@ -85,7 +65,7 @@ void Trace::paint_label(QPainter &p, const QRect &rect, bool hover) { const int y = get_visual_y(); - p.setBrush(colour_); + p.setBrush(channel_->colour()); if (!enabled()) return; @@ -116,23 +96,23 @@ void Trace::paint_label(QPainter &p, const QRect &rect, bool hover) } p.setPen(Qt::transparent); - p.setBrush(hover ? colour_.lighter() : colour_); + p.setBrush(hover ? channel_->colour().lighter() : channel_->colour()); p.drawPolygon(points, countof(points)); - p.setPen(colour_.lighter()); + p.setPen(channel_->colour().lighter()); p.setBrush(Qt::transparent); p.drawPolygon(highlight_points, countof(highlight_points)); - p.setPen(colour_.darker()); + p.setPen(channel_->colour().darker()); p.setBrush(Qt::transparent); p.drawPolygon(points, countof(points)); // Paint the text - p.setPen(select_text_colour(colour_)); + p.setPen(select_text_colour(channel_->colour())); p.setFont(QApplication::font()); p.drawText(QRectF(r.x(), r.y(), r.width() - label_arrow_length, r.height()), - Qt::AlignCenter | Qt::AlignVCenter, name_); + Qt::AlignCenter | Qt::AlignVCenter, channel_->name()); } QMenu* Trace::create_context_menu(QWidget *parent) @@ -164,7 +144,7 @@ QRectF Trace::label_rect(const QRectF &rect) const QFontMetrics m(QApplication::font()); const QSize text_size( - m.boundingRect(QRect(), 0, name_).width(), m.height()); + m.boundingRect(QRect(), 0, channel_->name()).width(), m.height()); const QSizeF label_size( text_size.width() + LabelPadding.width() * 2, ceilf((text_size.height() + LabelPadding.height() * 2) / 2) * 2); @@ -179,7 +159,7 @@ QRectF Trace::label_rect(const QRectF &rect) const void Trace::paint_back(QPainter &p, const ViewItemPaintParams &pp) { if (coloured_bg_) - p.setBrush(bgcolour_); + p.setBrush(channel_->bgcolour()); else p.setBrush(bgcolour_state_ ? BrightGrayBGColour : DarkGrayBGColour); @@ -212,9 +192,9 @@ void Trace::add_colour_option(QWidget *parent, QFormLayout *form) ColourButton *const colour_button = new ColourButton( TracePalette::Rows, TracePalette::Cols, parent); colour_button->set_palette(TracePalette::Colours); - colour_button->set_colour(colour_); + colour_button->set_colour(channel_->colour()); connect(colour_button, SIGNAL(selected(const QColor&)), - this, SLOT(on_colour_changed(const QColor&))); + this, SLOT(on_colouredit_changed(const QColor&))); form->addRow(tr("Colour"), colour_button); } @@ -242,35 +222,61 @@ void Trace::create_popup_form() void Trace::populate_popup_form(QWidget *parent, QFormLayout *form) { QLineEdit *const name_edit = new QLineEdit(parent); - name_edit->setText(name_); + name_edit->setText(channel_->name()); connect(name_edit, SIGNAL(textChanged(const QString&)), - this, SLOT(on_text_changed(const QString&))); + this, SLOT(on_nameedit_changed(const QString&))); form->addRow(tr("Name"), name_edit); add_colour_option(parent, form); } -void Trace::on_popup_closed() +void Trace::set_name(QString name) { - popup_ = nullptr; - popup_form_ = nullptr; + channel_->set_name(name); } -void Trace::on_text_changed(const QString &text) +void Trace::set_colour(QColor colour) { - set_name(text); + channel_->set_colour(colour); +} - if (owner_) +void Trace::on_name_changed(const QString &text) +{ + /* This event handler is called by SignalBase when the name was changed there */ + (void)text; + + if (owner_) { owner_->extents_changed(true, false); + owner_->row_item_appearance_changed(true, false); + } } void Trace::on_colour_changed(const QColor &colour) { - set_colour(colour); + /* This event handler is called by SignalBase when the colour was changed there */ + (void)colour; if (owner_) owner_->row_item_appearance_changed(true, true); } +void Trace::on_popup_closed() +{ + popup_ = nullptr; + popup_form_ = nullptr; +} + +void Trace::on_nameedit_changed(const QString &name) +{ + /* This event handler notifies SignalBase that the name changed */ + set_name(name); +} + +void Trace::on_colouredit_changed(const QColor &colour) +{ + /* This event handler notifies SignalBase that the colour changed */ + set_colour(colour); +} + } // namespace view } // namespace pv diff --git a/pv/view/trace.hpp b/pv/view/trace.hpp index 4e95f56..397ec7c 100644 --- a/pv/view/trace.hpp +++ b/pv/view/trace.hpp @@ -31,6 +31,8 @@ #include "tracetreeitem.hpp" +#include "pv/data/signalbase.hpp" + class QFormLayout; namespace pv { @@ -49,33 +51,22 @@ private: static const QPen AxisPen; static const int LabelHitPadding; - static const int ColourBGAlpha; static const QColor BrightGrayBGColour; static const QColor DarkGrayBGColour; protected: - Trace(QString name); + Trace(std::shared_ptr channel); public: - /** - * Gets the name of this signal. - */ - QString name() const; - /** * Sets the name of the signal. */ virtual void set_name(QString name); - /** - * Get the colour of the signal. - */ - QColor colour() const; - /** * Set the colour of the signal. */ - void set_colour(QColor colour); + virtual void set_colour(QColor colour); /** * Enables or disables the coloured background for this trace. @@ -123,16 +114,20 @@ protected: virtual void populate_popup_form(QWidget *parent, QFormLayout *form); -private Q_SLOTS: - void on_text_changed(const QString &text); +protected Q_SLOTS: + virtual void on_name_changed(const QString &text); - void on_colour_changed(const QColor &colour); + virtual void on_colour_changed(const QColor &colour); void on_popup_closed(); +private Q_SLOTS: + void on_nameedit_changed(const QString &name); + + void on_colouredit_changed(const QColor &colour); + protected: - QString name_; - QColor colour_, bgcolour_; + std::shared_ptr channel_; bool coloured_bg_, coloured_bg_state_; private: diff --git a/pv/view/view.cpp b/pv/view/view.cpp index a7dcc20..e7308dd 100644 --- a/pv/view/view.cpp +++ b/pv/view/view.cpp @@ -739,7 +739,7 @@ void View::update_layout() TraceTreeItemOwner* View::find_prevalent_trace_group( const shared_ptr &group, - const unordered_map, shared_ptr > + const unordered_map, shared_ptr > &signal_map) { assert(group); @@ -749,13 +749,13 @@ TraceTreeItemOwner* View::find_prevalent_trace_group( // Make a set and a list of all the owners for (const auto &channel : group->channels()) { - const auto iter = signal_map.find(channel); - if (iter == signal_map.end()) - continue; - - TraceTreeItemOwner *const o = (*iter).second->owner(); - owner_list.push_back(o); - owners.insert(o); + for (auto entry : signal_map) { + if (entry.first->channel() == channel) { + TraceTreeItemOwner *const o = (entry.second)->owner(); + owner_list.push_back(o); + owners.insert(o); + } + } } // Iterate through the list of owners, and find the most prevalent @@ -776,24 +776,24 @@ TraceTreeItemOwner* View::find_prevalent_trace_group( vector< shared_ptr > View::extract_new_traces_for_channels( const vector< shared_ptr > &channels, - const unordered_map, shared_ptr > + const unordered_map, shared_ptr > &signal_map, set< shared_ptr > &add_list) { vector< shared_ptr > filtered_traces; for (const auto &channel : channels) { - const auto map_iter = signal_map.find(channel); - if (map_iter == signal_map.end()) - continue; - - shared_ptr trace = (*map_iter).second; - const auto list_iter = add_list.find(trace); - if (list_iter == add_list.end()) - continue; - - filtered_traces.push_back(trace); - add_list.erase(list_iter); + for (auto entry : signal_map) { + if (entry.first->channel() == channel) { + shared_ptr trace = entry.second; + const auto list_iter = add_list.find(trace); + if (list_iter == add_list.end()) + continue; + + filtered_traces.push_back(trace); + add_list.erase(list_iter); + } + } } return filtered_traces; @@ -973,7 +973,7 @@ void View::signals_changed() inserter(remove_traces, remove_traces.begin())); // Make a look-up table of sigrok Channels to pulseview Signals - unordered_map, shared_ptr > + unordered_map, shared_ptr > signal_map; for (const shared_ptr &sig : sigs) signal_map[sig->channel()] = sig; diff --git a/pv/view/view.hpp b/pv/view/view.hpp index a3610b7..47f1b8d 100644 --- a/pv/view/view.hpp +++ b/pv/view/view.hpp @@ -273,13 +273,13 @@ private: TraceTreeItemOwner* find_prevalent_trace_group( const std::shared_ptr &group, - const std::unordered_map, + const std::unordered_map, std::shared_ptr > &signal_map); static std::vector< std::shared_ptr > extract_new_traces_for_channels( const std::vector< std::shared_ptr > &channels, - const std::unordered_map, + const std::unordered_map, std::shared_ptr > &signal_map, std::set< std::shared_ptr > &add_list); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7e8a9d7..2bd243e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -30,6 +30,7 @@ set(pulseview_TEST_SOURCES ${PROJECT_SOURCE_DIR}/pv/data/logic.cpp ${PROJECT_SOURCE_DIR}/pv/data/logicsegment.cpp ${PROJECT_SOURCE_DIR}/pv/data/segment.cpp + ${PROJECT_SOURCE_DIR}/pv/data/signalbase.cpp ${PROJECT_SOURCE_DIR}/pv/data/signaldata.cpp ${PROJECT_SOURCE_DIR}/pv/devices/device.cpp ${PROJECT_SOURCE_DIR}/pv/devices/file.cpp @@ -87,6 +88,7 @@ set(pulseview_TEST_HEADERS ${PROJECT_SOURCE_DIR}/pv/session.hpp ${PROJECT_SOURCE_DIR}/pv/storesession.hpp ${PROJECT_SOURCE_DIR}/pv/binding/device.hpp + ${PROJECT_SOURCE_DIR}/pv/data/signalbase.hpp ${PROJECT_SOURCE_DIR}/pv/devices/device.hpp ${PROJECT_SOURCE_DIR}/pv/popups/channels.hpp ${PROJECT_SOURCE_DIR}/pv/popups/deviceoptions.hpp -- 2.30.2