]> sigrok.org Git - pulseview.git/blob - pv/subwindows/decoder_selector/model.cpp
TabularDecModel: Fix multi-row selection issue
[pulseview.git] / pv / subwindows / decoder_selector / model.cpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2018 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 <QString>
21
22 #include "subwindow.hpp"
23
24 #include <libsigrokdecode/libsigrokdecode.h>
25
26 #define DECODERS_HAVE_TAGS \
27         ((SRD_PACKAGE_VERSION_MAJOR > 0) || \
28          (SRD_PACKAGE_VERSION_MAJOR == 0) && (SRD_PACKAGE_VERSION_MINOR > 5))
29
30 using std::make_shared;
31
32 namespace pv {
33 namespace subwindows {
34 namespace decoder_selector {
35
36 DecoderCollectionModel::DecoderCollectionModel(QObject* parent) :
37         QAbstractItemModel(parent)
38 {
39         vector<QVariant> header_data;
40         header_data.emplace_back(tr("Decoder"));     // Column #0
41         header_data.emplace_back(tr("Name"));        // Column #1
42         header_data.emplace_back(tr("ID"));          // Column #2
43         root_ = make_shared<DecoderCollectionItem>(header_data);
44
45         // Note: the tag groups are sub-items of the root item
46
47         // Create "all decoders" group
48         vector<QVariant> item_data;
49         item_data.emplace_back(tr("All Decoders"));
50         // Add dummy entries to make the row count the same as the
51         // sub-item size, or else we can't query sub-item data
52         item_data.emplace_back();
53         item_data.emplace_back();
54         shared_ptr<DecoderCollectionItem> group_item_all =
55                 make_shared<DecoderCollectionItem>(item_data, root_);
56         root_->appendSubItem(group_item_all);
57
58         for (GSList* li = (GSList*)srd_decoder_list(); li; li = li->next) {
59                 const srd_decoder *const d = (srd_decoder*)li->data;
60                 assert(d);
61
62                 const QString id = QString::fromUtf8(d->id);
63                 const QString name = QString::fromUtf8(d->name);
64                 const QString long_name = QString::fromUtf8(d->longname);
65
66                 // Add decoder to the "all decoders" group
67                 item_data.clear();
68                 item_data.emplace_back(name);
69                 item_data.emplace_back(long_name);
70                 item_data.emplace_back(id);
71                 shared_ptr<DecoderCollectionItem> decoder_item_all =
72                         make_shared<DecoderCollectionItem>(item_data, group_item_all);
73                 group_item_all->appendSubItem(decoder_item_all);
74
75                 // Add decoder to all relevant groups using the tag information
76 #if DECODERS_HAVE_TAGS
77                 for (GSList* ti = (GSList*)d->tags; ti; ti = ti->next) {
78                         const QString tag = tr((char*)ti->data);
79                         const QVariant tag_var = QVariant(tag);
80
81                         // Find tag group and create it if it doesn't exist yet
82                         shared_ptr<DecoderCollectionItem> group_item =
83                                 root_->findSubItem(tag_var, 0);
84
85                         if (!group_item) {
86                                 item_data.clear();
87                                 item_data.emplace_back(tag);
88                                 // Add dummy entries to make the row count the same as the
89                                 // sub-item size, or else we can't query sub-item data
90                                 item_data.emplace_back();
91                                 item_data.emplace_back();
92                                 group_item = make_shared<DecoderCollectionItem>(item_data, root_);
93                                 root_->appendSubItem(group_item);
94                         }
95
96                         // Create decoder item
97                         item_data.clear();
98                         item_data.emplace_back(name);
99                         item_data.emplace_back(long_name);
100                         item_data.emplace_back(id);
101                         shared_ptr<DecoderCollectionItem> decoder_item =
102                                 make_shared<DecoderCollectionItem>(item_data, group_item);
103
104                         // Add decoder to tag group
105                         group_item->appendSubItem(decoder_item);
106                 }
107 #endif
108         }
109 }
110
111 QVariant DecoderCollectionModel::data(const QModelIndex& index, int role) const
112 {
113         if (!index.isValid())
114                 return QVariant();
115
116         if (role == Qt::DisplayRole)
117         {
118                 DecoderCollectionItem* item =
119                         static_cast<DecoderCollectionItem*>(index.internalPointer());
120
121                 return item->data(index.column());
122         }
123
124         if ((role == Qt::FontRole) && (index.parent().isValid()) && (index.column() == 0))
125         {
126                 QFont font;
127                 font.setItalic(true);
128                 return QVariant(font);
129         }
130
131         return QVariant();
132 }
133
134 Qt::ItemFlags DecoderCollectionModel::flags(const QModelIndex& index) const
135 {
136         if (!index.isValid())
137                 return nullptr;
138
139         return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
140 }
141
142 QVariant DecoderCollectionModel::headerData(int section, Qt::Orientation orientation,
143         int role) const
144 {
145         if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole))
146                 return root_->data(section);
147
148         return QVariant();
149 }
150
151 QModelIndex DecoderCollectionModel::index(int row, int column,
152         const QModelIndex& parent_idx) const
153 {
154         if (!hasIndex(row, column, parent_idx))
155                 return QModelIndex();
156
157         DecoderCollectionItem* parent = root_.get();
158
159         if (parent_idx.isValid())
160                 parent = static_cast<DecoderCollectionItem*>(parent_idx.internalPointer());
161
162         DecoderCollectionItem* subItem = parent->subItem(row).get();
163
164         return subItem ? createIndex(row, column, subItem) : QModelIndex();
165 }
166
167 QModelIndex DecoderCollectionModel::parent(const QModelIndex& index) const
168 {
169         if (!index.isValid())
170                 return QModelIndex();
171
172         DecoderCollectionItem* subItem =
173                 static_cast<DecoderCollectionItem*>(index.internalPointer());
174
175         shared_ptr<DecoderCollectionItem> parent = subItem->parent();
176
177         return (parent == root_) ? QModelIndex() :
178                 createIndex(parent->row(), 0, parent.get());
179 }
180
181 int DecoderCollectionModel::rowCount(const QModelIndex& parent_idx) const
182 {
183         DecoderCollectionItem* parent = root_.get();
184
185         if (parent_idx.column() > 0)
186                 return 0;
187
188         if (parent_idx.isValid())
189                 parent = static_cast<DecoderCollectionItem*>(parent_idx.internalPointer());
190
191         return parent->subItemCount();
192 }
193
194 int DecoderCollectionModel::columnCount(const QModelIndex& parent_idx) const
195 {
196         if (parent_idx.isValid())
197                 return static_cast<DecoderCollectionItem*>(
198                         parent_idx.internalPointer())->columnCount();
199         else
200                 return root_->columnCount();
201 }
202
203
204 } // namespace decoder_selector
205 } // namespace subwindows
206 } // namespace pv