PulseView  unreleased development snapshot
A Qt-based sigrok GUI
model.cpp
Go to the documentation of this file.
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 
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 Qt::NoItemFlags;
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 
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 {
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
shared_ptr< DecoderCollectionItem > parent() const
Definition: item.cpp:49
QVariant data(const QModelIndex &index, int role) const override
Definition: model.cpp:111
int rowCount(const QModelIndex &parent_idx=QModelIndex()) const override
Definition: model.cpp:181
QModelIndex index(int row, int column, const QModelIndex &parent_idx=QModelIndex()) const override
Definition: model.cpp:151
QModelIndex parent(const QModelIndex &index) const override
Definition: model.cpp:167
shared_ptr< DecoderCollectionItem > root_
Definition: subwindow.hpp:84
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: model.cpp:134
int columnCount(const QModelIndex &parent_idx=QModelIndex()) const override
Definition: model.cpp:194
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Definition: model.cpp:142
shared_ptr< DecoderCollectionItem > subItem(int row) const
Definition: item.cpp:40