PulseView  unreleased development snapshot
A Qt-based sigrok GUI
rowdata.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <cassert>
21 
23 #include <pv/data/decode/row.hpp>
25 
26 using std::vector;
27 
28 namespace pv {
29 namespace data {
30 namespace decode {
31 
33  row_(row),
34  prev_ann_start_sample_(0)
35 {
36  assert(row);
37 }
38 
39 const Row* RowData::row() const
40 {
41  return row_;
42 }
43 
44 uint64_t RowData::get_max_sample() const
45 {
46  if (annotations_.empty())
47  return 0;
48  return annotations_.back().end_sample();
49 }
50 
52 {
53  return annotations_.size();
54 }
55 
57  deque<const pv::data::decode::Annotation*> &dest,
58  uint64_t start_sample, uint64_t end_sample) const
59 {
60  // Determine whether we must apply per-class filtering or not
61  bool all_ann_classes_enabled = true;
62  bool all_ann_classes_disabled = true;
63 
64  uint32_t max_ann_class_id = 0;
65  for (AnnotationClass* c : row_->ann_classes()) {
66  if (!c->visible())
67  all_ann_classes_enabled = false;
68  else
69  all_ann_classes_disabled = false;
70  if (c->id > max_ann_class_id)
71  max_ann_class_id = c->id;
72  }
73 
74  if (all_ann_classes_enabled) {
75  // No filtering, send everyting out as-is
76  for (const auto& annotation : annotations_)
77  if ((annotation.end_sample() > start_sample) &&
78  (annotation.start_sample() <= end_sample))
79  dest.push_back(&annotation);
80  } else {
81  if (!all_ann_classes_disabled) {
82  // Filter out invisible annotation classes
83  vector<size_t> class_visible;
84  class_visible.resize(max_ann_class_id + 1, 0);
85  for (AnnotationClass* c : row_->ann_classes())
86  if (c->visible())
87  class_visible[c->id] = 1;
88 
89  for (const auto& annotation : annotations_)
90  if ((class_visible[annotation.ann_class_id()]) &&
91  (annotation.end_sample() > start_sample) &&
92  (annotation.start_sample() <= end_sample))
93  dest.push_back(&annotation);
94  }
95  }
96 }
97 
98 const deque<Annotation>& RowData::annotations() const
99 {
100  return annotations_;
101 }
102 
103 const Annotation* RowData::emplace_annotation(srd_proto_data *pdata)
104 {
105  const srd_proto_data_annotation *const pda = (const srd_proto_data_annotation*)pdata->data;
106 
107  uint32_t ann_class_id = pda->ann_class;
108 
109  // Look up the longest annotation text to see if we have it in storage.
110  // This implies that if the longest text is the same, the shorter texts
111  // are expected to be the same, too. PDs that violate this assumption
112  // should be considered broken.
113  const char* const* ann_texts = (char**)pda->ann_text;
114  const QString ann0 = QString::fromUtf8(ann_texts[0]);
115  vector<QString>* storage_entry = &(ann_texts_[ann0]);
116 
117  if (storage_entry->empty()) {
118  while (*ann_texts) {
119  storage_entry->emplace_back(QString::fromUtf8(*ann_texts));
120  ann_texts++;
121  }
122  storage_entry->shrink_to_fit();
123  }
124 
125 
126  const Annotation* result = nullptr;
127 
128  // We insert the annotation in a way so that the annotation list
129  // is sorted by start sample. Otherwise, we'd have to sort when
130  // painting, which is expensive
131 
132  if (pdata->start_sample < prev_ann_start_sample_) {
133  // Find location to insert the annotation at
134 
135  auto it = annotations_.end();
136  do {
137  it--;
138  } while ((it->start_sample() > pdata->start_sample) && (it != annotations_.begin()));
139 
140  // Allow inserting at the front
141  if (it != annotations_.begin())
142  it++;
143 
144  it = annotations_.emplace(it, pdata->start_sample, pdata->end_sample,
145  storage_entry, ann_class_id, this);
146  result = &(*it);
147  } else {
148  annotations_.emplace_back(pdata->start_sample, pdata->end_sample,
149  storage_entry, ann_class_id, this);
150  result = &(annotations_.back());
151  prev_ann_start_sample_ = pdata->start_sample;
152  }
153 
154  return result;
155 }
156 
157 } // namespace decode
158 } // namespace data
159 } // namespace pv
static std::string data()
Definition: exprtk.hpp:39024
uint64_t get_max_sample() const
Definition: rowdata.cpp:44
uint64_t get_annotation_count() const
Definition: rowdata.cpp:51
void get_annotation_subset(deque< const pv::data::decode::Annotation * > &dest, uint64_t start_sample, uint64_t end_sample) const
Definition: rowdata.cpp:56
const Annotation * emplace_annotation(srd_proto_data *pdata)
Definition: rowdata.cpp:103
vector< AnnotationClass * > ann_classes() const
Definition: row.cpp:79
const Row * row() const
Definition: rowdata.cpp:39
uint64_t prev_ann_start_sample_
Definition: rowdata.hpp:80
deque< Annotation > annotations_
Definition: rowdata.hpp:77
unordered_map< QString, vector< QString > > ann_texts_
Definition: rowdata.hpp:78
const deque< Annotation > & annotations() const
Definition: rowdata.cpp:98