Rework decoder infrastructure
authorSoeren Apel <soeren@apelpie.net>
Tue, 24 Dec 2019 22:13:03 +0000 (23:13 +0100)
committerSoeren Apel <soeren@apelpie.net>
Wed, 1 Jan 2020 14:05:05 +0000 (15:05 +0100)
14 files changed:
pv/binding/decoder.cpp
pv/data/decode/annotation.cpp
pv/data/decode/decoder.cpp
pv/data/decode/decoder.hpp
pv/data/decode/row.cpp
pv/data/decode/row.hpp
pv/data/decode/rowdata.cpp
pv/data/decode/rowdata.hpp
pv/data/decodesignal.cpp
pv/data/decodesignal.hpp
pv/dialogs/settings.cpp
pv/globalsettings.cpp
pv/views/trace/decodetrace.cpp
pv/views/trace/decodetrace.hpp

index f51f90774afd0561d130704819528f9fd887a0f1..80725d2a8b35248461ca1c14e57c3d39f5f529d8 100644 (file)
@@ -54,12 +54,11 @@ Decoder::Decoder(
 {
        assert(decoder_);
 
-       const srd_decoder *const dec = decoder_->decoder();
+       const srd_decoder *const dec = decoder_->get_srd_decoder();
        assert(dec);
 
        for (GSList *l = dec->options; l; l = l->next) {
-               const srd_decoder_option *const opt =
-                       (srd_decoder_option*)l->data;
+               const srd_decoder_option *const opt = (srd_decoder_option*)l->data;
 
                const QString name = QString::fromUtf8(opt->desc);
 
@@ -115,12 +114,11 @@ Glib::VariantBase Decoder::getter(const char *id)
        if (iter != options.end())
                val = (*iter).second;
        else {
-               assert(decoder_->decoder());
+               assert(decoder_->get_srd_decoder());
 
                // Get the default value if not
-               for (GSList *l = decoder_->decoder()->options; l; l = l->next) {
-                       const srd_decoder_option *const opt =
-                               (srd_decoder_option*)l->data;
+               for (GSList *l = decoder_->get_srd_decoder()->options; l; l = l->next) {
+                       const srd_decoder_option *const opt = (srd_decoder_option*)l->data;
                        if (strcmp(opt->id, id) == 0) {
                                val = opt->def;
                                break;
index e983b0df1c3e971ba7942c9ccadb86ed10e09bbb..55caa2d7adbfb9810260811ef5b6c0b1372ef2f3 100644 (file)
@@ -24,7 +24,7 @@ extern "C" {
 #include <cassert>
 #include <vector>
 
-#include "annotation.hpp"
+#include <pv/data/decode/annotation.hpp>
 
 using std::vector;
 
@@ -49,6 +49,8 @@ Annotation::Annotation(const srd_proto_data *const pdata, const Row *row) :
                annotations_.push_back(QString::fromUtf8(*annotations));
                annotations++;
        }
+
+       annotations_.shrink_to_fit();
 }
 
 uint64_t Annotation::start_sample() const
index 19f11399fec78bae58fc809d71bfb6b0aded71d1..3769f8898f18fc7736691c4288fde9b175f5c206 100644 (file)
@@ -41,14 +41,44 @@ Decoder::Decoder(const srd_decoder *const dec) :
        shown_(true),
        decoder_inst_(nullptr)
 {
-       // Query the decoder outputs
+       // Query the annotation output classes
        uint32_t i = 0;
+       for (GSList *l = dec->annotations; l; l = l->next) {
+               char **ann_class = (char**)l->data;
+               char *name = ann_class[0];
+               char *desc = ann_class[1];
+               ann_classes_.push_back({i++, name, desc, nullptr, true}); // Visible by default
+       }
+
+       // Query the binary output classes
+       i = 0;
        for (GSList *l = dec->binary; l; l = l->next) {
                char **bin_class = (char**)l->data;
                char *name = bin_class[0];
                char *desc = bin_class[1];
                bin_classes_.push_back({i++, name, desc});
        }
+
+       // Query the annotation rows and reference them by the classes that use them
+       uint32_t row_count = 0;
+       for (const GSList *rl = srd_decoder_->annotation_rows; rl; rl = rl->next)
+               row_count++;
+       rows_.reserve(row_count);
+
+       i = 0;
+       for (const GSList *rl = srd_decoder_->annotation_rows; rl; rl = rl->next) {
+               const srd_decoder_annotation_row *const srd_row = (srd_decoder_annotation_row *)rl->data;
+               assert(srd_row);
+               rows_.push_back({i++, this, srd_row});
+
+               // FIXME PV can crash from .at() if a PD's ann classes are defined incorrectly
+               for (const GSList *cl = srd_row->ann_classes; cl; cl = cl->next)
+                       ann_classes_.at((size_t)cl->data).row = &(rows_.back());
+       }
+
+       if (rows_.empty())
+               // Make sure there is a row for PDs without row declarations
+               rows_.emplace_back(0, this);
 }
 
 Decoder::~Decoder()
@@ -57,7 +87,7 @@ Decoder::~Decoder()
                g_variant_unref(option.second);
 }
 
-const srd_decoder* Decoder::decoder() const
+const srd_decoder* Decoder::get_srd_decoder() const
 {
        return srd_decoder_;
 }
@@ -184,6 +214,42 @@ void Decoder::invalidate_decoder_inst()
        decoder_inst_ = nullptr;
 }
 
+vector<Row*> Decoder::get_rows()
+{
+       vector<Row*> result;
+
+       for (Row& row : rows_)
+               result.push_back(&row);
+
+       return result;
+}
+
+Row* Decoder::get_row_by_id(size_t id)
+{
+       if (id > rows_.size())
+               return nullptr;
+
+       return &(rows_[id]);
+}
+
+vector<const AnnotationClass*> Decoder::ann_classes() const
+{
+       vector<const AnnotationClass*> result;
+
+       for (const AnnotationClass& c : ann_classes_)
+               result.push_back(&c);
+
+       return result;
+}
+
+AnnotationClass* Decoder::get_ann_class_by_id(size_t id)
+{
+       if (id >= ann_classes_.size())
+               return nullptr;
+
+       return &(ann_classes_[id]);
+}
+
 uint32_t Decoder::get_binary_class_count() const
 {
        return bin_classes_.size();
index 282cfe557d0740682ef17d82318ea4d9443463c8..4baf86a026aeb4b62bf140f6af273ebae8d4156c 100644 (file)
@@ -28,6 +28,7 @@
 #include <glib.h>
 
 #include <pv/data/signalbase.hpp>
+#include <pv/data/decode/row.hpp>
 
 using std::map;
 using std::string;
@@ -49,6 +50,15 @@ namespace decode {
 
 class Decoder;
 
+struct AnnotationClass
+{
+       size_t id;
+       char* name;
+       char* description;
+       Row* row;
+       bool visible;
+};
+
 struct DecodeChannel
 {
        uint16_t id;     ///< Global numerical ID for the decode channels in the stack
@@ -76,7 +86,7 @@ public:
 
        virtual ~Decoder();
 
-       const srd_decoder* decoder() const;
+       const srd_decoder* get_srd_decoder() const;
 
        const char* name() const;
 
@@ -97,6 +107,12 @@ public:
        srd_decoder_inst* create_decoder_inst(srd_session *session);
        void invalidate_decoder_inst();
 
+       vector<Row*> get_rows();
+       Row* get_row_by_id(size_t id);
+
+       vector<const AnnotationClass*> ann_classes() const;
+       AnnotationClass* get_ann_class_by_id(size_t id);
+
        uint32_t get_binary_class_count() const;
        const DecodeBinaryClassInfo* get_binary_class(uint32_t id) const;
 
@@ -106,6 +122,8 @@ private:
        bool shown_;
 
        vector<DecodeChannel*> channels_;
+       vector<Row> rows_;
+       vector<AnnotationClass> ann_classes_;
        vector<DecodeBinaryClassInfo> bin_classes_;
        map<string, GVariant*> options_;
        srd_decoder_inst *decoder_inst_;
index 31e4cc8e9add3233cb3f3296554d1d224da5b770..72a6869f94250abcbe731a75d5ebcaffc3b028a2 100644 (file)
@@ -27,15 +27,17 @@ namespace data {
 namespace decode {
 
 Row::Row() :
+       index_(0),
        decoder_(nullptr),
-       row_(nullptr)
+       srd_row_(nullptr),
+       visible_(true)
 {
 }
 
-Row::Row(int index, const Decoder* decoder, const srd_decoder_annotation_row* row) :
+Row::Row(uint32_t index, Decoder* decoder, const srd_decoder_annotation_row* srd_row) :
        index_(index),
        decoder_(decoder),
-       row_(row),
+       srd_row_(srd_row),
        visible_(true)
 {
 }
@@ -45,32 +47,49 @@ const Decoder* Row::decoder() const
        return decoder_;
 }
 
-const srd_decoder_annotation_row* Row::srd_row() const
+const srd_decoder_annotation_row* Row::get_srd_row() const
 {
-       return row_;
+       return srd_row_;
 }
 
 const QString Row::title() const
 {
-       if (decoder_ && decoder_->name() && row_ && row_->desc)
+       if (decoder_ && decoder_->name() && srd_row_ && srd_row_->desc)
                return QString("%1: %2")
                        .arg(QString::fromUtf8(decoder_->name()),
-                            QString::fromUtf8(row_->desc));
+                            QString::fromUtf8(srd_row_->desc));
        if (decoder_ && decoder_->name())
                return QString::fromUtf8(decoder_->name());
-       if (row_ && row_->desc)
-               return QString::fromUtf8(row_->desc);
+       if (srd_row_ && srd_row_->desc)
+               return QString::fromUtf8(srd_row_->desc);
+
        return QString();
 }
 
-const QString Row::class_name() const
+const QString Row::description() const
 {
-       if (row_ && row_->desc)
-               return QString::fromUtf8(row_->desc);
+       if (srd_row_ && srd_row_->desc)
+               return QString::fromUtf8(srd_row_->desc);
        return QString();
 }
 
-int Row::index() const
+vector<AnnotationClass*> Row::ann_classes() const
+{
+       vector<AnnotationClass*> result;
+
+       if (!srd_row_)
+               return result;
+       assert(decoder_);
+
+       for (GSList *l = srd_row_->ann_classes; l; l = l->next) {
+               size_t class_id = (size_t)l->data;
+               result.push_back(decoder_->get_ann_class_by_id(class_id));
+       }
+
+       return result;
+}
+
+uint32_t Row::index() const
 {
        return index_;
 }
@@ -88,12 +107,12 @@ void Row::set_visible(bool visible)
 bool Row::operator<(const Row& other) const
 {
        return (decoder_ < other.decoder_) ||
-               (decoder_ == other.decoder_ && row_ < other.row_);
+               (decoder_ == other.decoder_ && srd_row_ < other.srd_row_);
 }
 
 bool Row::operator==(const Row& other) const
 {
-       return ((decoder_ == other.decoder()) && (row_ == other.srd_row()));
+       return ((decoder_ == other.decoder()) && (srd_row_ == other.srd_row_));
 }
 
 }  // namespace decode
index 9d7992e8ceb0f71b2dd6c80c99a63149079007cd..21f46d22057fccaf71f32f4b419acc24980fb20f 100644 (file)
@@ -22,7 +22,8 @@
 
 #include <vector>
 
-#include "annotation.hpp"
+#include <pv/data/decode/annotation.hpp>
+#include <pv/data/decode/decoder.hpp>
 
 struct srd_decoder;
 struct srd_decoder_annotation_row;
@@ -31,6 +32,7 @@ namespace pv {
 namespace data {
 namespace decode {
 
+struct AnnotationClass;
 class Decoder;
 
 class Row
@@ -38,15 +40,16 @@ class Row
 public:
        Row();
 
-       Row(int index, const Decoder* decoder,
-               const srd_decoder_annotation_row* row = nullptr);
+       Row(uint32_t index, Decoder* decoder,
+               const srd_decoder_annotation_row* srd_row = nullptr);
 
        const Decoder* decoder() const;
-       const srd_decoder_annotation_row* srd_row() const;
+       const srd_decoder_annotation_row* get_srd_row() const;
 
        const QString title() const;
-       const QString class_name() const;
-       int index() const;
+       const QString description() const;
+       vector<AnnotationClass*> ann_classes() const;
+       uint32_t index() const;
 
        bool visible() const;
        void set_visible(bool visible);
@@ -55,9 +58,9 @@ public:
        bool operator==(const Row& other) const;
 
 private:
-       int index_;
-       const Decoder* decoder_;
-       const srd_decoder_annotation_row* row_;
+       uint32_t index_;
+       Decoder* decoder_;
+       const srd_decoder_annotation_row* srd_row_;
        bool visible_;
 };
 
index d3d14f9bd56fb7d2b3c275f5185775ca12dceab8..c1efdde4f16f07bb7a6f55ddb751b8a8e44cbaa5 100644 (file)
@@ -17,7 +17,9 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "rowdata.hpp"
+#include <pv/data/decode/decoder.hpp>
+#include <pv/data/decode/row.hpp>
+#include <pv/data/decode/rowdata.hpp>
 
 using std::vector;
 
@@ -25,6 +27,12 @@ namespace pv {
 namespace data {
 namespace decode {
 
+RowData::RowData(Row* row) :
+       row_(row)
+{
+       assert(row);
+}
+
 uint64_t RowData::get_max_sample() const
 {
        if (annotations_.empty())
@@ -41,15 +49,47 @@ void RowData::get_annotation_subset(
        vector<pv::data::decode::Annotation> &dest,
        uint64_t start_sample, uint64_t end_sample) const
 {
-       for (const auto& annotation : annotations_)
-               if (annotation.end_sample() > start_sample &&
-                       annotation.start_sample() <= end_sample)
-                       dest.push_back(annotation);
+       // Determine whether we must apply per-class filtering or not
+       bool all_ann_classes_enabled = true;
+       bool all_ann_classes_disabled = true;
+
+       uint32_t max_ann_class_id = 0;
+       for (AnnotationClass* c : row_->ann_classes()) {
+               if (!c->visible)
+                       all_ann_classes_enabled = false;
+               else
+                       all_ann_classes_disabled = false;
+               if (c->id > max_ann_class_id)
+                       max_ann_class_id = c->id;
+       }
+
+       if (all_ann_classes_enabled) {
+               // No filtering, send everyting out as-is
+               for (const auto& annotation : annotations_)
+                       if ((annotation.end_sample() > start_sample) &&
+                               (annotation.start_sample() <= end_sample))
+                               dest.push_back(annotation);
+       } else {
+               if (!all_ann_classes_disabled) {
+                       // Filter out invisible annotation classes
+                       vector<size_t> class_visible;
+                       class_visible.resize(max_ann_class_id + 1, 0);
+                       for (AnnotationClass* c : row_->ann_classes())
+                               if (c->visible)
+                                       class_visible[c->id] = 1;
+
+                       for (const auto& annotation : annotations_)
+                               if ((annotation.end_sample() > start_sample) &&
+                                       (annotation.start_sample() <= end_sample) &&
+                                       (class_visible[annotation.ann_class()]))
+                                       dest.push_back(annotation);
+               }
+       }
 }
 
-void RowData::emplace_annotation(srd_proto_data *pdata, const Row *row)
+void RowData::emplace_annotation(srd_proto_data *pdata)
 {
-       annotations_.emplace_back(pdata, row);
+       annotations_.emplace_back(pdata, row_);
 }
 
 }  // namespace decode
index 3c967ff70b1e8998d60903c39bcc35e2e8fcc2ce..0012acd4523ecfc7339a5a30809ab78de2ddef57 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <libsigrokdecode/libsigrokdecode.h>
 
-#include "annotation.hpp"
+#include <pv/data/decode/annotation.hpp>
 
 using std::vector;
 
@@ -37,7 +37,7 @@ class Row;
 class RowData
 {
 public:
-       RowData() = default;
+       RowData(Row* row);
 
 public:
        uint64_t get_max_sample() const;
@@ -53,10 +53,11 @@ public:
                vector<pv::data::decode::Annotation> &dest,
                uint64_t start_sample, uint64_t end_sample) const;
 
-       void emplace_annotation(srd_proto_data *pdata, const Row *row);
+       void emplace_annotation(srd_proto_data *pdata);
 
 private:
        vector<Annotation> annotations_;
+       const Row* row_;
 };
 
 }  // namespace decode
index 593af02fdd796348aac72d3b621fa13239cffa3f..a66e69d967b9fe7c54363da06e0f5703df6798e2 100644 (file)
@@ -42,6 +42,7 @@ using std::out_of_range;
 using std::shared_ptr;
 using std::unique_lock;
 using pv::data::decode::Annotation;
+using pv::data::decode::AnnotationClass;
 using pv::data::decode::DecodeChannel;
 using pv::data::decode::Decoder;
 using pv::data::decode::Row;
@@ -81,15 +82,13 @@ void DecodeSignal::stack_decoder(const srd_decoder *decoder, bool restart_decode
        assert(decoder);
 
        // Set name if this decoder is the first in the list or the name is unchanged
-       const srd_decoder* prev_dec =
-               stack_.empty() ? nullptr : stack_.back()->decoder();
-       const QString prev_dec_name =
-               prev_dec ? QString::fromUtf8(prev_dec->name) : QString();
+       const srd_decoder* prev_dec = stack_.empty() ? nullptr : stack_.back()->get_srd_decoder();
+       const QString prev_dec_name = prev_dec ? QString::fromUtf8(prev_dec->name) : QString();
 
        if ((stack_.empty()) || ((stack_.size() > 0) && (name() == prev_dec_name)))
                set_name(QString::fromUtf8(decoder->name));
 
-       const shared_ptr<Decoder> dec = make_shared<decode::Decoder>(decoder);
+       const shared_ptr<Decoder> dec = make_shared<Decoder>(decoder);
        stack_.push_back(dec);
 
        // Include the newly created decode channels in the channel lists
@@ -165,7 +164,6 @@ void DecodeSignal::reset_decode(bool shutting_down)
 
        resume_decode();  // Make sure the decode thread isn't blocked by pausing
 
-       class_rows_.clear();
        current_segment_id_ = 0;
        segments_.clear();
 
@@ -217,33 +215,13 @@ void DecodeSignal::begin_decode()
                        ch.assigned_signal = nullptr;
 
        // Check that all decoders have the required channels
-       for (const shared_ptr<decode::Decoder>& dec : stack_)
+       for (const shared_ptr<Decoder>& dec : stack_)
                if (!dec->have_required_channels()) {
                        set_error_message(tr("One or more required channels "
                                "have not been specified"));
                        return;
                }
 
-       // Map out all the annotation classes
-       int row_index = 0;
-       for (const shared_ptr<decode::Decoder>& dec : stack_) {
-               assert(dec);
-               const srd_decoder *const decc = dec->decoder();
-               assert(dec->decoder());
-
-               for (const GSList *l = decc->annotation_rows; l; l = l->next) {
-                       const srd_decoder_annotation_row *const ann_row =
-                               (srd_decoder_annotation_row *)l->data;
-                       assert(ann_row);
-
-                       const Row row(row_index++, dec.get(), ann_row);
-
-                       for (const GSList *ll = ann_row->ann_classes;
-                               ll; ll = ll->next)
-                               class_rows_[make_pair(decc, GPOINTER_TO_INT(ll->data))] = row;
-               }
-       }
-
        // Free the logic data and its segment(s) if it needs to be updated
        if (logic_mux_data_invalid_)
                logic_mux_data_.reset();
@@ -453,57 +431,61 @@ int64_t DecodeSignal::get_decoded_sample_count(uint32_t segment_id,
        return result;
 }
 
-vector<Row> DecodeSignal::get_rows(bool visible_only) const
+vector<Row*> DecodeSignal::get_rows(bool visible_only)
 {
-       lock_guard<mutex> lock(output_mutex_);
-
-       vector<Row> rows;
+       vector<Row*> rows;
 
-       for (const shared_ptr<decode::Decoder>& dec : stack_) {
+       for (const shared_ptr<Decoder>& dec : stack_) {
                assert(dec);
                if (visible_only && !dec->shown())
                        continue;
 
-               const srd_decoder *const decc = dec->decoder();
-               assert(dec->decoder());
+               for (Row* row : dec->get_rows())
+                       rows.push_back(row);
+       }
 
-               int row_index = 0;
-               // Add a row for the decoder if it doesn't have a row list
-               if (!decc->annotation_rows)
-                       rows.emplace_back(row_index++, dec.get());
+       return rows;
+}
 
-               // Add the decoder rows
-               for (const GSList *l = decc->annotation_rows; l; l = l->next) {
-                       const srd_decoder_annotation_row *const ann_row =
-                               (srd_decoder_annotation_row *)l->data;
-                       assert(ann_row);
-                       rows.emplace_back(row_index++, dec.get(), ann_row);
-               }
+vector<const Row*> DecodeSignal::get_rows(bool visible_only) const
+{
+       vector<const Row*> rows;
+
+       for (const shared_ptr<Decoder>& dec : stack_) {
+               assert(dec);
+               if (visible_only && !dec->shown())
+                       continue;
+
+               for (const Row* row : dec->get_rows())
+                       rows.push_back(row);
        }
 
        return rows;
 }
 
-uint64_t DecodeSignal::get_annotation_count(const decode::Row &row,
-       uint32_t segment_id) const
+
+uint64_t DecodeSignal::get_annotation_count(const Row* row, uint32_t segment_id) const
 {
        if (segment_id >= segments_.size())
                return 0;
 
-       const DecodeSegment *segment = &(segments_.at(segment_id));
-       const map<const decode::Row, decode::RowData> *rows =
-               &(segment->annotation_rows);
+       const DecodeSegment* segment = &(segments_.at(segment_id));
 
-       const auto iter = rows->find(row);
-       if (iter != rows->end())
-               return (*iter).second.get_annotation_count();
+       auto row_it = segment->annotation_rows.find(row);
 
-       return 0;
+       const RowData* rd;
+       if (row_it == segment->annotation_rows.end()) {
+               // FIXME Use the fallback row, but how?
+               assert(false);
+               return 0;
+       } else
+               rd = &(row_it->second);
+
+       return rd->get_annotation_count();
 }
 
-void DecodeSignal::get_annotation_subset(
-       vector<pv::data::decode::Annotation> &dest,
-       const decode::Row &row, uint32_t segment_id, uint64_t start_sample,
+void DecodeSignal::get_annotation_subset(vector<Annotation> &dest,
+       const Row* row, uint32_t segment_id, uint64_t start_sample,
        uint64_t end_sample) const
 {
        lock_guard<mutex> lock(output_mutex_);
@@ -511,26 +493,29 @@ void DecodeSignal::get_annotation_subset(
        if (segment_id >= segments_.size())
                return;
 
-       const DecodeSegment *segment = &(segments_.at(segment_id));
-       const map<const decode::Row, decode::RowData> *rows = &(segment->annotation_rows);
+       const DecodeSegment* segment = &(segments_.at(segment_id));
+
+       auto row_it = segment->annotation_rows.find(row);
 
-       const auto iter = rows->find(row);
-       if (iter != rows->end())
-               (*iter).second.get_annotation_subset(dest, start_sample, end_sample);
+       const RowData* rd;
+       if (row_it == segment->annotation_rows.end()) {
+               // FIXME Use the fallback row, but how?
+               assert(false);
+               return;
+       } else
+               rd = &(row_it->second);
+
+       rd->get_annotation_subset(dest, start_sample, end_sample);
 }
 
-void DecodeSignal::get_annotation_subset(
-       vector<pv::data::decode::Annotation> &dest,
+void DecodeSignal::get_annotation_subset(vector<Annotation> &dest,
        uint32_t segment_id, uint64_t start_sample, uint64_t end_sample) const
 {
-       // Note: We put all vectors and lists on the heap, not the stack
-
-       const vector<Row> rows = get_rows();
-
        // Use forward_lists for faster merging
        forward_list<Annotation> *all_ann_list = new forward_list<Annotation>();
 
-       for (const Row& row : rows) {
+       vector<const Row*> rows = get_rows();
+       for (const Row* row : rows) {
                vector<Annotation> *ann_vector = new vector<Annotation>();
                get_annotation_subset(*ann_vector, row, segment_id, start_sample, end_sample);
 
@@ -625,8 +610,8 @@ void DecodeSignal::get_merged_binary_data_chunks_by_sample(uint32_t segment_id,
 }
 
 void DecodeSignal::get_merged_binary_data_chunks_by_offset(uint32_t segment_id,
-       const data::decode::Decoder* dec, uint32_t bin_class_id, uint64_t start,
-       uint64_t end, vector<uint8_t> *dest) const
+       const Decoder* dec, uint32_t bin_class_id, uint64_t start, uint64_t end,
+       vector<uint8_t> *dest) const
 {
        assert(dest != nullptr);
 
@@ -667,7 +652,7 @@ void DecodeSignal::get_merged_binary_data_chunks_by_offset(uint32_t segment_id,
 }
 
 const DecodeBinaryClass* DecodeSignal::get_binary_data_class(uint32_t segment_id,
-       const data::decode::Decoder* dec, uint32_t bin_class_id) const
+       const Decoder* dec, uint32_t bin_class_id) const
 {
        try {
                const DecodeSegment *segment = &(segments_.at(segment_id));
@@ -690,10 +675,10 @@ void DecodeSignal::save_settings(QSettings &settings) const
 
        // Save decoder stack
        int decoder_idx = 0;
-       for (const shared_ptr<decode::Decoder>& decoder : stack_) {
+       for (const shared_ptr<Decoder>& decoder : stack_) {
                settings.beginGroup("decoder" + QString::number(decoder_idx++));
 
-               settings.setValue("id", decoder->decoder()->id);
+               settings.setValue("id", decoder->get_srd_decoder()->id);
                settings.setValue("shown", decoder->shown());
 
                // Save decoder options
@@ -701,7 +686,7 @@ void DecodeSignal::save_settings(QSettings &settings) const
 
                settings.setValue("options", (int)options.size());
 
-               // Note: decode::Decoder::options() returns only the options
+               // Note: Decoder::options() returns only the options
                // that differ from the default. See binding::Decoder::getter()
                int i = 0;
                for (auto& option : options) {
@@ -759,8 +744,7 @@ void DecodeSignal::restore_settings(QSettings &settings)
                                continue;
 
                        if (QString::fromUtf8(dec->id) == id) {
-                               shared_ptr<decode::Decoder> decoder =
-                                       make_shared<decode::Decoder>(dec);
+                               shared_ptr<Decoder> decoder = make_shared<Decoder>(dec);
 
                                stack_.push_back(decoder);
                                decoder->show(settings.value("shown", true).toBool());
@@ -872,6 +856,15 @@ uint32_t DecodeSignal::get_input_samplerate(uint32_t segment_id) const
        return samplerate;
 }
 
+Decoder* DecodeSignal::get_decoder_by_instance(const srd_decoder *const srd_dec)
+{
+       for (shared_ptr<Decoder>& d : stack_)
+               if (d->get_srd_decoder() == srd_dec)
+                       return d.get();
+
+       return nullptr;
+}
+
 void DecodeSignal::update_channel_list()
 {
        vector<decode::DecodeChannel> prev_channels = channels_;
@@ -881,11 +874,11 @@ void DecodeSignal::update_channel_list()
 
        // Copy existing entries, create new as needed
        for (shared_ptr<Decoder>& decoder : stack_) {
-               const srd_decoder* srd_d = decoder->decoder();
+               const srd_decoder* srd_dec = decoder->get_srd_decoder();
                const GSList *l;
 
                // Mandatory channels
-               for (l = srd_d->channels; l; l = l->next) {
+               for (l = srd_dec->channels; l; l = l->next) {
                        const struct srd_channel *const pdch = (struct srd_channel *)l->data;
                        bool ch_added = false;
 
@@ -908,7 +901,7 @@ void DecodeSignal::update_channel_list()
                }
 
                // Optional channels
-               for (l = srd_d->opt_channels; l; l = l->next) {
+               for (l = srd_dec->opt_channels; l; l = l->next) {
                        const struct srd_channel *const pdch = (struct srd_channel *)l->data;
                        bool ch_added = false;
 
@@ -956,7 +949,7 @@ void DecodeSignal::update_channel_list()
 void DecodeSignal::commit_decoder_channels()
 {
        // Submit channel list to every decoder, containing only the relevant channels
-       for (shared_ptr<decode::Decoder> dec : stack_) {
+       for (shared_ptr<Decoder> dec : stack_) {
                vector<decode::DecodeChannel*> channel_list;
 
                for (decode::DecodeChannel& ch : channels_)
@@ -1271,7 +1264,7 @@ void DecodeSignal::start_srd_session()
                if (samplerate)
                        srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE,
                                g_variant_new_uint64(samplerate));
-               for (const shared_ptr<decode::Decoder>& dec : stack_)
+               for (const shared_ptr<Decoder>& dec : stack_)
                        dec->apply_all_options();
                srd_session_start(srd_session_);
 
@@ -1284,7 +1277,7 @@ void DecodeSignal::start_srd_session()
 
        // Create the decoders
        srd_decoder_inst *prev_di = nullptr;
-       for (const shared_ptr<decode::Decoder>& dec : stack_) {
+       for (const shared_ptr<Decoder>& dec : stack_) {
                srd_decoder_inst *const di = dec->create_decoder_inst(srd_session_);
 
                if (!di) {
@@ -1334,7 +1327,7 @@ void DecodeSignal::terminate_srd_session()
                if (samplerate)
                        srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE,
                                g_variant_new_uint64(samplerate));
-               for (const shared_ptr<decode::Decoder>& dec : stack_)
+               for (const shared_ptr<Decoder>& dec : stack_)
                        dec->apply_all_options();
        }
 }
@@ -1347,7 +1340,7 @@ void DecodeSignal::stop_srd_session()
                srd_session_ = nullptr;
 
                // Mark the decoder instances as non-existant since they were deleted
-               for (const shared_ptr<decode::Decoder>& dec : stack_)
+               for (const shared_ptr<Decoder>& dec : stack_)
                        dec->invalidate_decoder_inst();
        }
 }
@@ -1377,32 +1370,12 @@ void DecodeSignal::create_decode_segment()
        segments_.emplace_back(DecodeSegment());
 
        // Add annotation classes
-       for (const shared_ptr<decode::Decoder>& dec : stack_) {
-               assert(dec);
-               const srd_decoder *const decc = dec->decoder();
-               assert(dec->decoder());
-
-               int row_index = 0;
-               // Add a row for the decoder if it doesn't have a row list
-               if (!decc->annotation_rows)
-                       (segments_.back().annotation_rows)[Row(row_index++, dec.get())] =
-                               decode::RowData();
-
-               // Add the decoder rows
-               for (const GSList *l = decc->annotation_rows; l; l = l->next) {
-                       const srd_decoder_annotation_row *const ann_row =
-                               (srd_decoder_annotation_row *)l->data;
-                       assert(ann_row);
-
-                       const Row row(row_index++, dec.get(), ann_row);
-
-                       // Add a new empty row data object
-                       (segments_.back().annotation_rows)[row] = decode::RowData();
-               }
-       }
+       for (const shared_ptr<Decoder> dec : stack_)
+               for (Row* row : dec->get_rows())
+                       segments_.back().annotation_rows.emplace(row, RowData(row));
 
        // Prepare our binary output classes
-       for (const shared_ptr<decode::Decoder>& dec : stack_) {
+       for (const shared_ptr<Decoder>& dec : stack_) {
                uint32_t n = dec->get_binary_class_count();
 
                for (uint32_t i = 0; i < n; i++)
@@ -1427,36 +1400,26 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa
        // Get the decoder and the annotation data
        assert(pdata->pdo);
        assert(pdata->pdo->di);
-       const srd_decoder *const decc = pdata->pdo->di->decoder;
-       assert(decc);
+       const srd_decoder *const srd_dec = pdata->pdo->di->decoder;
+       assert(srd_dec);
 
        const srd_proto_data_annotation *const pda = (const srd_proto_data_annotation*)pdata->data;
        assert(pda);
 
        // Find the row
-       auto row_iter = ds->segments_.at(ds->current_segment_id_).annotation_rows.end();
-
-       // Try finding a better row match than the default by looking up the sub-row of this class
-       const auto format = pda->ann_class;
-       const auto r = ds->class_rows_.find(make_pair(decc, format));
-       if (r != ds->class_rows_.end())
-               row_iter = ds->segments_.at(ds->current_segment_id_).annotation_rows.find((*r).second);
-       else {
-               // Failing that, use the decoder as a key
-               for (const shared_ptr<decode::Decoder>& dec : ds->decoder_stack())
-                       if (dec->decoder() == decc)
-                               row_iter = ds->segments_.at(ds->current_segment_id_).annotation_rows.find(Row(0, dec.get()));
-       }
+       Decoder* dec = ds->get_decoder_by_instance(srd_dec);
+       assert(dec);
 
-       if (row_iter == ds->segments_.at(ds->current_segment_id_).annotation_rows.end()) {
-               qDebug() << "Unexpected annotation: decoder = " << decc <<
-                       ", format = " << format;
-               assert(false);
-               return;
-       }
+       AnnotationClass* ann_class = dec->get_ann_class_by_id(pda->ann_class);
+       assert(ann_class);
+
+       const Row* row = ann_class->row;
+
+       if (!row)
+               row = dec->get_row_by_id(0);
 
        // Add the annotation
-       (*row_iter).second.emplace_annotation(pdata, &((*row_iter).first));
+       ds->segments_[ds->current_segment_id_].annotation_rows.at(row).emplace_annotation(pdata);
 }
 
 void DecodeSignal::binary_callback(srd_proto_data *pdata, void *decode_signal)
@@ -1473,8 +1436,8 @@ void DecodeSignal::binary_callback(srd_proto_data *pdata, void *decode_signal)
        // Get the decoder and the binary data
        assert(pdata->pdo);
        assert(pdata->pdo->di);
-       const srd_decoder *const decc = pdata->pdo->di->decoder;
-       assert(decc);
+       const srd_decoder *const srd_dec = pdata->pdo->di->decoder;
+       assert(srd_dec);
 
        const srd_proto_data_binary *const pdb = (const srd_proto_data_binary*)pdata->data;
        assert(pdb);
@@ -1484,7 +1447,8 @@ void DecodeSignal::binary_callback(srd_proto_data *pdata, void *decode_signal)
 
        DecodeBinaryClass* bin_class = nullptr;
        for (DecodeBinaryClass& bc : segment->binary_classes)
-               if ((bc.decoder->decoder() == decc) && (bc.info->bin_class_id == (uint32_t)pdb->bin_class))
+               if ((bc.decoder->get_srd_decoder() == srd_dec) &&
+                       (bc.info->bin_class_id == (uint32_t)pdb->bin_class))
                        bin_class = &bc;
 
        if (!bin_class) {
@@ -1502,13 +1466,7 @@ void DecodeSignal::binary_callback(srd_proto_data *pdata, void *decode_signal)
        chunk->data.resize(pdb->size);
        memcpy(chunk->data.data(), pdb->data, pdb->size);
 
-       // Find decoder class instance
-       Decoder* dec = nullptr;
-       for (const shared_ptr<decode::Decoder>& d : ds->decoder_stack())
-               if (d->decoder() == decc) {
-                       dec = d.get();
-                       break;
-               }
+       Decoder* dec = ds->get_decoder_by_instance(srd_dec);
 
        ds->new_binary_data(ds->current_segment_id_, (void*)dec, pdb->bin_class);
 }
index f3ef9dfaad15a73fe5147c69dbae844647b4e67c..0e5d38c6b2879f4b94461ce4037b4454e7fd4f41 100644 (file)
@@ -46,17 +46,18 @@ using std::pair;
 using std::vector;
 using std::shared_ptr;
 
+using pv::data::decode::Annotation;
+using pv::data::decode::DecodeBinaryClassInfo;
+using pv::data::decode::DecodeChannel;
+using pv::data::decode::Decoder;
+using pv::data::decode::Row;
+using pv::data::decode::RowData;
+
 namespace pv {
 class Session;
 
 namespace data {
 
-namespace decode {
-class Annotation;
-class Decoder;
-class Row;
-}
-
 class Logic;
 class LogicSegment;
 class SignalBase;
@@ -70,14 +71,14 @@ struct DecodeBinaryDataChunk
 
 struct DecodeBinaryClass
 {
-       const decode::Decoder* decoder;
-       const decode::DecodeBinaryClassInfo* info;
+       const Decoder* decoder;
+       const DecodeBinaryClassInfo* info;
        deque<DecodeBinaryDataChunk> chunks;
 };
 
 struct DecodeSegment
 {
-       map<const decode::Row, decode::RowData> annotation_rows;
+       map<const Row*, RowData> annotation_rows;
        pv::util::Timestamp start_time;
        double samplerate;
        int64_t samples_decoded_incl, samples_decoded_excl;
@@ -98,7 +99,7 @@ public:
        virtual ~DecodeSignal();
 
        bool is_decode_signal() const;
-       const vector< shared_ptr<data::decode::Decoder> >& decoder_stack() const;
+       const vector< shared_ptr<Decoder> >& decoder_stack() const;
 
        void stack_decoder(const srd_decoder *decoder, bool restart_decode=true);
        void remove_decoder(int index);
@@ -111,8 +112,8 @@ public:
        bool is_paused() const;
        QString error_message() const;
 
-       const vector<data::decode::DecodeChannel> get_channels() const;
-       void auto_assign_signals(const shared_ptr<pv::data::decode::Decoder> dec);
+       const vector<decode::DecodeChannel> get_channels() const;
+       void auto_assign_signals(const shared_ptr<Decoder> dec);
        void assign_signal(const uint16_t channel_id, const SignalBase *signal);
        int get_assigned_signal_count() const;
 
@@ -139,44 +140,42 @@ public:
        int64_t get_decoded_sample_count(uint32_t segment_id,
                bool include_processing) const;
 
-       vector<decode::Row> get_rows(bool visible_only=false) const;
+       vector<Row*> get_rows(bool visible_only=false);
+       vector<const Row*> get_rows(bool visible_only=false) const;
 
-       uint64_t get_annotation_count(const decode::Row &row, uint32_t segment_id) const;
+       uint64_t get_annotation_count(const Row* row, uint32_t segment_id) const;
 
        /**
         * Extracts annotations from a single row into a vector.
         * Note: The annotations may be unsorted and only annotations that fully
         * fit into the sample range are considered.
         */
-       void get_annotation_subset(
-               vector<pv::data::decode::Annotation> &dest,
-               const decode::Row &row, uint32_t segment_id, uint64_t start_sample,
-               uint64_t end_sample) const;
+       void get_annotation_subset(vector<Annotation> &dest, const Row* row,
+               uint32_t segment_id, uint64_t start_sample, uint64_t end_sample) const;
 
        /**
         * Extracts annotations from all rows into a vector.
         * Note: The annotations may be unsorted and only annotations that fully
         * fit into the sample range are considered.
         */
-       void get_annotation_subset(
-               vector<pv::data::decode::Annotation> &dest,
-               uint32_t segment_id, uint64_t start_sample, uint64_t end_sample) const;
+       void get_annotation_subset(vector<Annotation> &dest, uint32_t segment_id,
+               uint64_t start_sample, uint64_t end_sample) const;
 
        uint32_t get_binary_data_chunk_count(uint32_t segment_id,
-               const data::decode::Decoder* dec, uint32_t bin_class_id) const;
-       void get_binary_data_chunk(uint32_t segment_id, const data::decode::Decoder* dec,
+               const Decoder* dec, uint32_t bin_class_id) const;
+       void get_binary_data_chunk(uint32_t segment_id, const Decoder* dec,
                uint32_t bin_class_id, uint32_t chunk_id, const vector<uint8_t> **dest,
                uint64_t *size);
        void get_merged_binary_data_chunks_by_sample(uint32_t segment_id,
-               const data::decode::Decoder* dec, uint32_t bin_class_id,
+               const Decoder* dec, uint32_t bin_class_id,
                uint64_t start_sample, uint64_t end_sample,
                vector<uint8_t> *dest) const;
        void get_merged_binary_data_chunks_by_offset(uint32_t segment_id,
-               const data::decode::Decoder* dec, uint32_t bin_class_id,
+               const Decoder* dec, uint32_t bin_class_id,
                uint64_t start, uint64_t end,
                vector<uint8_t> *dest) const;
        const DecodeBinaryClass* get_binary_data_class(uint32_t segment_id,
-               const data::decode::Decoder* dec, uint32_t bin_class_id) const;
+               const Decoder* dec, uint32_t bin_class_id) const;
 
        virtual void save_settings(QSettings &settings) const;
 
@@ -186,20 +185,19 @@ private:
        void set_error_message(QString msg);
 
        uint32_t get_input_segment_count() const;
-
        uint32_t get_input_samplerate(uint32_t segment_id) const;
 
+       Decoder* get_decoder_by_instance(const srd_decoder *const srd_dec);
+
        void update_channel_list();
 
        void commit_decoder_channels();
 
        void mux_logic_samples(uint32_t segment_id, const int64_t start, const int64_t end);
-
        void logic_mux_proc();
 
        void decode_data(const int64_t abs_start_samplenum, const int64_t sample_count,
                const shared_ptr<LogicSegment> input_segment);
-
        void decode_proc();
 
        void start_srd_session();
@@ -230,7 +228,7 @@ private Q_SLOTS:
 private:
        pv::Session &session_;
 
-       vector<data::decode::DecodeChannel> channels_;
+       vector<decode::DecodeChannel> channels_;
 
        struct srd_session *srd_session_;
 
@@ -238,9 +236,8 @@ private:
        uint32_t logic_mux_unit_size_;
        bool logic_mux_data_invalid_;
 
-       vector< shared_ptr<decode::Decoder> > stack_;
+       vector< shared_ptr<Decoder> > stack_;
        bool stack_config_changed_;
-       map<pair<const srd_decoder*, int>, decode::Row> class_rows_;
 
        vector<DecodeSegment> segments_;
        uint32_t current_segment_id_;
index 0dc6b055813ea80320e1ba49ab79ff882854b8a2..9854af4fe67a8b2a2e5712154435fb19a17f48cc 100644 (file)
@@ -393,7 +393,7 @@ QWidget *Settings::get_decoder_settings_form(QWidget *parent)
        connect(ann_export_format_, SIGNAL(textChanged(const QString&)),
                this, SLOT(on_dec_exportFormat_changed(const QString&)));
        decoder_layout->addRow(tr("Annotation export format"), ann_export_format_);
-       QLabel *description_1 = new QLabel(tr("%s = sample range; %d: decoder name; %c: row name; %q: use quotations marks"));
+       QLabel *description_1 = new QLabel(tr("%s = sample range; %d: decoder name; %r: row name; %q: use quotation marks"));
        description_1->setAlignment(Qt::AlignRight);
        decoder_layout->addRow(description_1);
        QLabel *description_2 = new QLabel(tr("%1: longest annotation text; %a: all annotation texts"));
index 4b7936565625157ac4cfb420efe85c856bba46e8..f7df48021f481eafd062bb0f5ad653fb6aaa83c8 100644 (file)
@@ -130,8 +130,10 @@ void GlobalSettings::set_defaults_where_needed()
        if (!contains(Key_View_SnapDistance))
                setValue(Key_View_SnapDistance, 15);
 
-       if (!contains(Key_Dec_ExportFormat))
-               setValue(Key_Dec_ExportFormat, "%s %d: %c: %1");
+       // %c was used for the row name in the past so we need to transition such users
+       if (!contains(Key_Dec_ExportFormat) ||
+               value(Key_Dec_ExportFormat).toString() == "%s %d: %c: %1")
+               setValue(Key_Dec_ExportFormat, "%s %d: %r: %1");
 
        // Default to 500 lines of backlog
        if (!contains(Key_Log_BufferSize))
index 8cddcd4510f7f38f6e887ec94b463326385a1d34..d4df80418b64d383fe1e5f0b74c2a0334ad4d5b8 100644 (file)
@@ -72,6 +72,7 @@ using std::tie;
 using std::vector;
 
 using pv::data::decode::Annotation;
+using pv::data::decode::AnnotationClass;
 using pv::data::decode::Row;
 using pv::data::decode::DecodeChannel;
 using pv::data::DecodeSignal;
@@ -146,6 +147,8 @@ DecodeTrace::DecodeTrace(pv::Session &session,
                this, SLOT(on_show_hide_decoder(int)));
        connect(&row_show_hide_mapper_, SIGNAL(mapped(int)),
                this, SLOT(on_show_hide_row(int)));
+       connect(&class_show_hide_mapper_, SIGNAL(mapped(QWidget*)),
+               this, SLOT(on_show_hide_class(QWidget*)));
 
        connect(&delayed_trace_updater_, SIGNAL(timeout()),
                this, SLOT(on_delayed_trace_update()));
@@ -165,7 +168,7 @@ DecodeTrace::~DecodeTrace()
 {
        GlobalSettings::remove_change_handler(this);
 
-       for (RowData& r : rows_) {
+       for (DecodeTraceRow& r : rows_) {
                for (QCheckBox* cb : r.selectors)
                        delete cb;
 
@@ -192,7 +195,7 @@ pair<int, int> DecodeTrace::v_extents() const
                return make_pair(-default_row_height_, default_row_height_);
 
        unsigned int height = 0;
-       for (const RowData& r : rows_)
+       for (const DecodeTraceRow& r : rows_)
                if (r.currently_visible)
                        height += r.height;
 
@@ -220,14 +223,14 @@ void DecodeTrace::paint_mid(QPainter &p, ViewItemPaintParams &pp)
        sample_range.second = min((int64_t)sample_range.second,
                decode_signal_->get_decoded_sample_count(current_segment_, false));
 
-       for (RowData& r : rows_)
-               r.currently_visible = false;
        visible_rows_ = 0;
        int y = get_visual_y();
 
-       for (RowData& r : rows_) {
+       for (DecodeTraceRow& r : rows_) {
                // If the row is hidden, we don't want to fetch annotations
-               if ((!r.decode_row.decoder()->shown()) || (!r.decode_row.visible())) {
+               assert(r.decode_row);
+               assert(r.decode_row->decoder());
+               if ((!r.decode_row->decoder()->shown()) || (!r.decode_row->visible())) {
                        r.currently_visible = false;
                        continue;
                }
@@ -238,12 +241,15 @@ void DecodeTrace::paint_mid(QPainter &p, ViewItemPaintParams &pp)
 
                // Show row if there are visible annotations or when user wants to see
                // all rows that have annotations somewhere and this one is one of them
-               size_t ann_count = decode_signal_->get_annotation_count(r.decode_row, current_segment_);
-               r.currently_visible = !annotations.empty() || (always_show_all_rows_ && (ann_count > 0));
+               r.currently_visible = !annotations.empty();
+               if (!r.currently_visible) {
+                       size_t ann_count = decode_signal_->get_annotation_count(r.decode_row, current_segment_);
+                       r.currently_visible = always_show_all_rows_ && (ann_count > 0);
+               }
 
                if (r.currently_visible) {
                        draw_annotations(annotations, p, annotation_height_, pp, y,
-                               get_row_color(r.decode_row.index()), r.title_width);
+                               get_row_color(r.decode_row->index()), r.title_width);
                        y += r.height;
                        visible_rows_++;
                }
@@ -268,7 +274,7 @@ void DecodeTrace::paint_fore(QPainter &p, ViewItemPaintParams &pp)
 {
        unsigned int y = get_visual_y();
 
-       for (const RowData& r : rows_) {
+       for (const DecodeTraceRow& r : rows_) {
                if (!r.currently_visible)
                        continue;
 
@@ -288,7 +294,7 @@ void DecodeTrace::paint_fore(QPainter &p, ViewItemPaintParams &pp)
 
                const QRect text_rect(pp.left() + ArrowSize * 2, y - r.height / 2,
                        pp.right() - pp.left(), r.height);
-               const QString h(r.decode_row.title());
+               const QString h(r.decode_row->title());
                const int f = Qt::AlignLeft | Qt::AlignVCenter |
                        Qt::TextDontClip;
 
@@ -316,7 +322,7 @@ void DecodeTrace::update_stack_button()
 
        // Only show decoders in the menu that can be stacked onto the last one in the stack
        if (!stack.empty()) {
-               const srd_decoder* d = stack.back()->decoder();
+               const srd_decoder* d = stack.back()->get_srd_decoder();
 
                if (d->outputs) {
                        pv::widgets::DecoderMenu *const decoder_menu =
@@ -414,9 +420,9 @@ QMenu* DecodeTrace::create_view_context_menu(QWidget *parent, QPoint &click_pos)
        }
 
        selected_row_ = nullptr;
-       const RowData* r = get_row_at_point(click_pos);
+       const DecodeTraceRow* r = get_row_at_point(click_pos);
        if (r)
-               selected_row_ = &(r->decode_row);
+               selected_row_ = r->decode_row;
 
        const View *const view = owner_->view();
        assert(view);
@@ -516,10 +522,10 @@ void DecodeTrace::hover_point_changed(const QPoint &hp)
 
        assert(owner_);
 
-       RowData* hover_row = get_row_at_point(hp);
+       DecodeTraceRow* hover_row = get_row_at_point(hp);
 
        // Row expansion marker handling
-       for (RowData& r : rows_)
+       for (DecodeTraceRow& r : rows_)
                r.expand_marker_highlighted = false;
 
        if (hover_row) {
@@ -565,7 +571,7 @@ void DecodeTrace::hover_point_changed(const QPoint &hp)
 void DecodeTrace::mouse_left_press_event(const QMouseEvent* event)
 {
        // Handle row expansion marker
-       for (RowData& r : rows_) {
+       for (DecodeTraceRow& r : rows_) {
                if (!r.expand_marker_highlighted)
                        continue;
 
@@ -941,13 +947,13 @@ QColor DecodeTrace::get_annotation_color(QColor row_color, int annotation_index)
        return color;
 }
 
-unsigned int DecodeTrace::get_row_y(const RowData* row) const
+unsigned int DecodeTrace::get_row_y(const DecodeTraceRow* row) const
 {
        assert(row);
 
        unsigned int y = get_visual_y();
 
-       for (const RowData& r : rows_) {
+       for (const DecodeTraceRow& r : rows_) {
                if (!r.currently_visible)
                        continue;
 
@@ -960,11 +966,11 @@ unsigned int DecodeTrace::get_row_y(const RowData* row) const
        return y;
 }
 
-RowData* DecodeTrace::get_row_at_point(const QPoint &point)
+DecodeTraceRow* DecodeTrace::get_row_at_point(const QPoint &point)
 {
        int y = get_visual_y() - (default_row_height_ / 2);
 
-       for (RowData& r : rows_) {
+       for (DecodeTraceRow& r : rows_) {
                if (!r.currently_visible)
                        continue;
 
@@ -986,7 +992,7 @@ const QString DecodeTrace::get_annotation_at_point(const QPoint &point)
 
        const pair<uint64_t, uint64_t> sample_range =
                get_view_sample_range(point.x(), point.x() + 1);
-       const RowData* r = get_row_at_point(point);
+       const DecodeTraceRow* r = get_row_at_point(point);
 
        if (!r)
                return QString();
@@ -1010,7 +1016,7 @@ void DecodeTrace::create_decoder_form(int index,
        GlobalSettings settings;
 
        assert(dec);
-       const srd_decoder *const decoder = dec->decoder();
+       const srd_decoder *const decoder = dec->get_srd_decoder();
        assert(decoder);
 
        const bool decoder_deletable = index > 0;
@@ -1151,7 +1157,7 @@ void DecodeTrace::export_annotations(vector<Annotation> *annotations) const
                        const QString sample_range = QString("%1-%2") \
                                .arg(QString::number(ann.start_sample()), QString::number(ann.end_sample()));
 
-                       const QString class_name = quote + ann.row()->class_name() + quote;
+                       const QString row_name = quote + ann.row()->description() + quote;
 
                        QString all_ann_text;
                        for (const QString &s : ann.annotations())
@@ -1164,7 +1170,7 @@ void DecodeTrace::export_annotations(vector<Annotation> *annotations) const
                        out_text = out_text.replace("%s", sample_range);
                        out_text = out_text.replace("%d",
                                quote + QString::fromUtf8(ann.row()->decoder()->name()) + quote);
-                       out_text = out_text.replace("%c", class_name);
+                       out_text = out_text.replace("%r", row_name);
                        out_text = out_text.replace("%1", first_ann_text);
                        out_text = out_text.replace("%a", all_ann_text);
                        out_stream << out_text << '\n';
@@ -1181,10 +1187,8 @@ void DecodeTrace::export_annotations(vector<Annotation> *annotations) const
        msg.exec();
 }
 
-void DecodeTrace::update_rows()
+void DecodeTrace::initialize_row_widgets(DecodeTraceRow* r, unsigned int row_id)
 {
-       lock_guard<mutex> lock(row_modification_mutex_);
-
        QFontMetrics m(QApplication::font());
 
        QPalette header_palette = owner_->view()->palette();
@@ -1202,19 +1206,80 @@ void DecodeTrace::update_rows()
                        QColor(0, 0, 0, ExpansionAreaAlpha));
        }
 
-       for (RowData& r : rows_)
+       const int w = m.boundingRect(r->decode_row->title()).width() + RowTitleMargin;
+       r->title_width = w;
+
+       r->container->resize(owner_->view()->viewport()->width() - r->container->pos().x(),
+               r->expanded_height - 2 * default_row_height_);
+       r->container->setVisible(false);
+
+       QVBoxLayout* vlayout = new QVBoxLayout();
+       r->container->setLayout(vlayout);
+
+       // Add header container with checkbox for this row
+       vlayout->addWidget(r->header_container);
+       vlayout->setContentsMargins(0, 0, 0, 0);
+       vlayout->setSpacing(0);
+       r->header_container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+       r->header_container->setMinimumSize(0, default_row_height_);
+       r->header_container->setLayout(new QVBoxLayout());
+       r->header_container->layout()->setContentsMargins(10, 2, 0, 2);
+
+       r->header_container->setAutoFillBackground(true);
+       r->header_container->setPalette(header_palette);
+
+       QCheckBox* cb = new QCheckBox();
+       r->header_container->layout()->addWidget(cb);
+       cb->setText(tr("Show this row"));
+       cb->setChecked(r->decode_row->visible());
+
+       row_show_hide_mapper_.setMapping(cb, row_id);
+       connect(cb, SIGNAL(stateChanged(int)),
+               &row_show_hide_mapper_, SLOT(map()));
+
+       // Add selector container
+       vlayout->addWidget(r->selector_container);
+       r->selector_container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+       r->selector_container->setMinimumSize(0, 3 * default_row_height_);                            // FIXME
+       r->selector_container->setLayout(new QHBoxLayout());
+
+       r->selector_container->setAutoFillBackground(true);
+       r->selector_container->setPalette(selector_palette);
+
+       // Add all classes that can be toggled
+       vector<AnnotationClass*> ann_classes = r->decode_row->ann_classes();
+
+       for (const AnnotationClass* ann_class : ann_classes) {
+               cb = new QCheckBox();
+               cb->setText(tr(ann_class->description));
+               cb->setChecked(ann_class->visible);
+
+               r->selector_container->layout()->addWidget(cb);
+
+               cb->setProperty("ann_class_ptr", QVariant::fromValue((void*)ann_class));
+               class_show_hide_mapper_.setMapping(cb, cb);
+               connect(cb, SIGNAL(stateChanged(int)),
+                       &class_show_hide_mapper_, SLOT(map()));
+       }
+}
+
+void DecodeTrace::update_rows()
+{
+       lock_guard<mutex> lock(row_modification_mutex_);
+
+       for (DecodeTraceRow& r : rows_)
                r.exists = false;
 
        unsigned int row_id = 0;
-       for (const Row& decode_row : decode_signal_->get_rows()) {
+       for (Row* decode_row : decode_signal_->get_rows()) {
                // Find row in our list
                auto r_it = find_if(rows_.begin(), rows_.end(),
-                       [&](RowData& r){ return r.decode_row == decode_row; });
+                       [&](DecodeTraceRow& r){ return r.decode_row == decode_row; });
 
-               RowData* r = nullptr;
+               DecodeTraceRow* r = nullptr;
                if (r_it == rows_.end()) {
                        // Row doesn't exist yet, create and append it
-                       RowData nr;
+                       DecodeTraceRow nr;
                        nr.decode_row = decode_row;
                        nr.height = default_row_height_;
                        nr.expanded_height = default_row_height_;
@@ -1230,54 +1295,11 @@ void DecodeTrace::update_rows()
 
                        rows_.push_back(nr);
                        r = &rows_.back();
+                       initialize_row_widgets(r, row_id);
                } else
                        r = &(*r_it);
 
                r->exists = true;
-
-               const int w = m.boundingRect(r->decode_row.title()).width() + RowTitleMargin;
-               r->title_width = w;
-
-               r->container->resize(owner_->view()->viewport()->width() - r->container->pos().x(),
-                       r->expanded_height - 2 * default_row_height_);
-               r->container->setVisible(false);
-
-               QVBoxLayout* vlayout = new QVBoxLayout();
-               r->container->setLayout(vlayout);
-
-               // Add header container with checkbox for this row
-               vlayout->addWidget(r->header_container);
-               vlayout->setContentsMargins(0, 0, 0, 0);
-               vlayout->setSpacing(0);
-               r->header_container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-               r->header_container->setMinimumSize(0, default_row_height_);
-               r->header_container->setLayout(new QVBoxLayout());
-               r->header_container->layout()->setContentsMargins(10, 2, 0, 2);
-
-               r->header_container->setAutoFillBackground(true);
-               r->header_container->setPalette(header_palette);
-
-               QCheckBox* cb = new QCheckBox();
-               r->header_container->layout()->addWidget(cb);
-               cb->setText(tr("Show this row"));
-               cb->setChecked(r->decode_row.visible());
-
-               row_show_hide_mapper_.setMapping(cb, row_id);
-               connect(cb, SIGNAL(stateChanged(int)),
-                       &row_show_hide_mapper_, SLOT(map()));
-
-               // Add selector container
-               vlayout->addWidget(r->selector_container);
-               r->selector_container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-               r->selector_container->setMinimumSize(0, 3 * default_row_height_);                            // FIXME
-               r->selector_container->setLayout(new QVBoxLayout());
-
-               r->selector_container->setAutoFillBackground(true);
-               r->selector_container->setPalette(selector_palette);
-
-
-               // Add all classes that can be toggled
-
                row_id++;
        }
 
@@ -1302,7 +1324,7 @@ void DecodeTrace::update_rows()
        } while (any_exists);
 }
 
-void DecodeTrace::set_row_expanded(RowData* r)
+void DecodeTrace::set_row_expanded(DecodeTraceRow* r)
 {
        r->height = r->expanded_height;
        r->expanding = false;
@@ -1315,9 +1337,11 @@ void DecodeTrace::set_row_expanded(RowData* r)
 
        r->container->resize(owner_->view()->viewport()->width() - r->container->pos().x(),
                r->height - 2 * default_row_height_);
+
+       max_visible_rows_ = 0;
 }
 
-void DecodeTrace::set_row_collapsed(RowData* r)
+void DecodeTrace::set_row_collapsed(DecodeTraceRow* r)
 {
        r->height = default_row_height_;
        r->collapsing = false;
@@ -1327,11 +1351,13 @@ void DecodeTrace::set_row_collapsed(RowData* r)
 
        r->container->resize(owner_->view()->viewport()->width() - r->container->pos().x(),
                r->height - 2 * default_row_height_);
+
+       max_visible_rows_ = 0;
 }
 
 void DecodeTrace::update_expanded_rows()
 {
-       for (RowData& r : rows_) {
+       for (DecodeTraceRow& r : rows_) {
 
                r.container->move(2 * ArrowSize,
                        get_row_y(&r) + default_row_height_);
@@ -1457,13 +1483,13 @@ void DecodeTrace::on_show_hide_decoder(int index)
        owner_->row_item_appearance_changed(false, true);
 }
 
-void DecodeTrace::on_show_hide_row(int index)
+void DecodeTrace::on_show_hide_row(int row_id)
 {
-       if (index >= (int)rows_.size())
+       if (row_id >= (int)rows_.size())
                return;
 
-       set_row_collapsed(&rows_[index]);
-       rows_[index].decode_row.set_visible(!rows_[index].decode_row.visible());
+       set_row_collapsed(&rows_[row_id]);
+       rows_[row_id].decode_row->set_visible(!rows_[row_id].decode_row->visible());
 
        // Force re-calculation of the trace height, see paint_mid()
        max_visible_rows_ = 0;
@@ -1471,6 +1497,17 @@ void DecodeTrace::on_show_hide_row(int index)
        owner_->row_item_appearance_changed(false, true);
 }
 
+void DecodeTrace::on_show_hide_class(QWidget* sender)
+{
+       void* ann_class_ptr = sender->property("ann_class_ptr").value<void*>();
+       assert(ann_class_ptr);
+
+       AnnotationClass* ann_class = (AnnotationClass*)ann_class_ptr;
+       ann_class->visible = !ann_class->visible;
+
+       owner_->row_item_appearance_changed(false, true);
+}
+
 void DecodeTrace::on_copy_annotation_to_clipboard()
 {
        using namespace pv::data::decode;
@@ -1480,7 +1517,7 @@ void DecodeTrace::on_copy_annotation_to_clipboard()
 
        vector<Annotation> *annotations = new vector<Annotation>();
 
-       decode_signal_->get_annotation_subset(*annotations, *selected_row_,
+       decode_signal_->get_annotation_subset(*annotations, selected_row_,
                current_segment_, selected_sample_range_.first, selected_sample_range_.first);
 
        if (annotations->empty())
@@ -1568,7 +1605,7 @@ void DecodeTrace::on_export_row_from_here()
 
        vector<Annotation> *annotations = new vector<Annotation>();
 
-       decode_signal_->get_annotation_subset(*annotations, *selected_row_,
+       decode_signal_->get_annotation_subset(*annotations, selected_row_,
                current_segment_, selected_sample_range_.first, selected_sample_range_.second);
 
        if (annotations->empty())
@@ -1597,7 +1634,7 @@ void DecodeTrace::on_animation_timer()
 {
        bool animation_finished = true;
 
-       for (RowData& r : rows_) {
+       for (DecodeTraceRow& r : rows_) {
                if (!(r.expanding || r.collapsing))
                        continue;
 
index 42ceb2a5e906404ee9e259d12f2571525fc0db0a..e262498848bf2c2c513498c69a499d6d2bc96bad 100644 (file)
@@ -48,6 +48,8 @@ using std::pair;
 using std::shared_ptr;
 using std::vector;
 
+using pv::data::decode::Row;
+
 struct srd_channel;
 struct srd_decoder;
 
@@ -61,6 +63,7 @@ class DecodeSignal;
 
 namespace decode {
 class Decoder;
+class Row;
 }
 }  // namespace data
 
@@ -71,11 +74,11 @@ class DecoderGroupBox;
 namespace views {
 namespace trace {
 
-struct RowData {
+struct DecodeTraceRow {
        // When adding a field, make sure it's initialized properly in
        // DecodeTrace::update_rows()
 
-       data::decode::Row decode_row;
+       Row* decode_row;
        unsigned int height, expanded_height, title_width, animation_step;
        bool exists, currently_visible;
        bool expand_marker_highlighted, expanding, expanded, collapsing;
@@ -195,9 +198,9 @@ private:
        QColor get_row_color(int row_index) const;
        QColor get_annotation_color(QColor row_color, int annotation_index) const;
 
-       unsigned int get_row_y(const RowData* row) const;
+       unsigned int get_row_y(const DecodeTraceRow* row) const;
 
-       RowData* get_row_at_point(const QPoint &point);
+       DecodeTraceRow* get_row_at_point(const QPoint &point);
 
        const QString get_annotation_at_point(const QPoint &point);
 
@@ -214,17 +217,18 @@ private:
 
        void export_annotations(vector<data::decode::Annotation> *annotations) const;
 
+       void initialize_row_widgets(DecodeTraceRow* r, unsigned int row_id);
        void update_rows();
 
        /**
         * Sets row r to expanded state without forcing an update of the view
         */
-       void set_row_expanded(RowData* r);
+       void set_row_expanded(DecodeTraceRow* r);
 
        /**
         * Sets row r to collapsed state without forcing an update of the view
         */
-       void set_row_collapsed(RowData* r);
+       void set_row_collapsed(DecodeTraceRow* r);
 
        void update_expanded_rows();
 
@@ -250,7 +254,8 @@ private Q_SLOTS:
        void on_delete_decoder(int index);
 
        void on_show_hide_decoder(int index);
-       void on_show_hide_row(int index);
+       void on_show_hide_row(int row_id);
+       void on_show_hide_class(QWidget* sender);
 
        void on_copy_annotation_to_clipboard();
 
@@ -267,14 +272,14 @@ private:
        pv::Session &session_;
        shared_ptr<data::DecodeSignal> decode_signal_;
 
-       deque<RowData> rows_;
+       deque<DecodeTraceRow> rows_;
        mutable mutex row_modification_mutex_;
 
        map<QComboBox*, uint16_t> channel_id_map_;  // channel selector -> decode channel ID
        map<QComboBox*, uint16_t> init_state_map_;  // init state selector -> decode channel ID
        list< shared_ptr<pv::binding::Decoder> > bindings_;
 
-       const data::decode::Row* selected_row_;
+       const Row* selected_row_;
        pair<uint64_t, uint64_t> selected_sample_range_;
 
        vector<pv::widgets::DecoderGroupBox*> decoder_forms_;
@@ -286,7 +291,8 @@ private:
        int min_useful_label_width_;
        bool always_show_all_rows_;
 
-       QSignalMapper delete_mapper_, show_hide_mapper_, row_show_hide_mapper_;
+       QSignalMapper delete_mapper_, show_hide_mapper_;
+       QSignalMapper row_show_hide_mapper_, class_show_hide_mapper_;
 
        QTimer delayed_trace_updater_, animation_timer_;