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