]> sigrok.org Git - pulseview.git/blob - pv/views/tabular_decoder/model.cpp
TabularDecView: Make the model/view work
[pulseview.git] / pv / views / tabular_decoder / model.cpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2020 Soeren Apel <soeren@apelpie.net>
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 <QDebug>
21 #include <QString>
22
23 #include "pv/views/tabular_decoder/view.hpp"
24
25 using std::make_shared;
26
27 namespace pv {
28 namespace views {
29 namespace tabular_decoder {
30
31 AnnotationCollectionModel::AnnotationCollectionModel(QObject* parent) :
32         QAbstractTableModel(parent),
33         all_annotations_(nullptr),
34         prev_segment_(0),
35         prev_last_row_(0)
36 {
37         // TBD Maybe use empty columns as indentation levels to indicate stacked decoders
38         header_data_.emplace_back(tr("Start Sample"));      // Column #0
39         header_data_.emplace_back(tr("Start Time"));        // Column #1
40         header_data_.emplace_back(tr("Ann Row Name"));      // Column #2
41         header_data_.emplace_back(tr("Ann Class Name"));    // Column #3
42         header_data_.emplace_back(tr("Value"));             // Column #4
43 }
44
45 QVariant AnnotationCollectionModel::data(const QModelIndex& index, int role) const
46 {
47         if (!index.isValid())
48                 return QVariant();
49
50         if (role == Qt::DisplayRole) {
51                 const Annotation* ann =
52                         static_cast<const Annotation*>(index.internalPointer());
53
54                 switch (index.column()) {
55                 case 0: return QVariant((qulonglong)ann->start_sample());  // Column #0, Start Sample
56                 case 1: return QVariant(0/*(qulonglong)ann->start_sample()*/);  // Column #1, Start Time
57                 case 2: return QVariant(ann->row()->title());              // Column #2, Ann Row Name
58                 case 3: return QVariant(ann->ann_class_name());            // Column #3, Ann Class Name
59                 case 4: return QVariant(ann->longest_annotation());        // Column #4, Value
60                 default: return QVariant();
61                 }
62         }
63
64         return QVariant();
65 }
66
67 Qt::ItemFlags AnnotationCollectionModel::flags(const QModelIndex& index) const
68 {
69         if (!index.isValid())
70                 return 0;
71
72         return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
73 }
74
75 QVariant AnnotationCollectionModel::headerData(int section, Qt::Orientation orientation,
76         int role) const
77 {
78         if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
79                 return header_data_.at(section);
80
81         return QVariant();
82 }
83
84 QModelIndex AnnotationCollectionModel::index(int row, int column,
85         const QModelIndex& parent_idx) const
86 {
87         (void)parent_idx;
88
89         if (!all_annotations_)
90                 return QModelIndex();
91
92         if ((size_t)row > all_annotations_->size())
93                 return QModelIndex();
94
95         return createIndex(row, column, (void*)(all_annotations_->at(row)));
96 }
97
98 QModelIndex AnnotationCollectionModel::parent(const QModelIndex& index) const
99 {
100         (void)index;
101
102         return QModelIndex();
103 }
104
105 int AnnotationCollectionModel::rowCount(const QModelIndex& parent_idx) const
106 {
107         (void)parent_idx;
108
109         if (!all_annotations_)
110                 return 0;
111
112         return all_annotations_->size();
113 }
114
115 int AnnotationCollectionModel::columnCount(const QModelIndex& parent_idx) const
116 {
117         (void)parent_idx;
118
119         return header_data_.size();
120 }
121
122 void AnnotationCollectionModel::set_signal_and_segment(data::DecodeSignal* signal, uint32_t current_segment)
123 {
124         all_annotations_ = signal->get_all_annotations_by_segment(current_segment);
125
126         if (!all_annotations_ || all_annotations_->empty()) {
127                 prev_segment_ = current_segment;
128                 return;
129         }
130
131         const size_t new_row_count = all_annotations_->size() - 1;
132
133         // Force the view associated with this model to update when the segment changes
134         if (prev_segment_ != current_segment) {
135                 dataChanged(QModelIndex(), QModelIndex());
136                 layoutChanged();
137         } else {
138                 // Force the view associated with this model to update when we have more annotations
139                 if (prev_last_row_ < new_row_count) {
140                         dataChanged(index(prev_last_row_, 0, QModelIndex()),
141                                 index(new_row_count, 0, QModelIndex()));
142                         layoutChanged();
143                 }
144         }
145
146         prev_segment_ = current_segment;
147         prev_last_row_ = new_row_count;
148 }
149
150 } // namespace tabular_decoder
151 } // namespace views
152 } // namespace pv