Line data Source code
1 : /* Copyright (c) 2015, Human Brain Project
2 : * Daniel.Nachbaur@epfl.ch
3 : *
4 : * This file is part of Servus <https://github.com/HBPVIS/Servus>
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 3.0 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #include "itemModel.h"
21 :
22 : #include <servus/listener.h>
23 : #include <servus/servus.h>
24 :
25 : #include <QTimer>
26 :
27 : namespace servus
28 : {
29 : namespace qt
30 : {
31 : class ItemModel::Impl : public Listener
32 : {
33 : public:
34 4 : Impl(Servus& service_, ItemModel& parent_)
35 4 : : parent(parent_)
36 : , service(service_)
37 4 : , rootItem(new QObject())
38 : {
39 4 : rootItem->setObjectName(
40 8 : QString("Instances for %1")
41 16 : .arg(QString::fromStdString(service.getName())));
42 :
43 4 : for (const std::string& i : service.getInstances())
44 0 : _addInstanceItem(QString::fromStdString(i));
45 :
46 4 : service.addListener(this);
47 4 : service.beginBrowsing(Servus::IF_ALL);
48 :
49 4 : browseTimer.connect(&browseTimer, &QTimer::timeout,
50 74 : [this]() { service.browse(0); });
51 4 : browseTimer.start(100);
52 4 : }
53 :
54 8 : ~Impl()
55 8 : {
56 4 : browseTimer.stop();
57 4 : service.removeListener(this);
58 4 : service.endBrowsing();
59 8 : }
60 :
61 6 : void instanceAdded(const std::string& instance) final
62 : {
63 8 : const QString& qstr = QString::fromStdString(instance);
64 6 : if (rootItem->findChild<QObject*>(qstr))
65 4 : return;
66 :
67 6 : parent.beginInsertRows(QModelIndex(), rootItem->children().size(),
68 6 : rootItem->children().size());
69 2 : _addInstanceItem(qstr);
70 2 : parent.endInsertRows();
71 : }
72 :
73 2 : void instanceRemoved(const std::string& instance) final
74 : {
75 4 : const QString& qstr = QString::fromStdString(instance);
76 2 : QObject* child = rootItem->findChild<QObject*>(qstr);
77 2 : if (!child)
78 0 : return;
79 :
80 2 : const QObjectList& children = rootItem->children();
81 2 : const int childIdx = children.indexOf(child);
82 2 : parent.beginRemoveRows(QModelIndex(), childIdx, childIdx);
83 2 : _removeInstanceItem(qstr);
84 2 : parent.endRemoveRows();
85 : }
86 :
87 : ItemModel& parent;
88 : Servus& service;
89 : std::unique_ptr<QObject> rootItem;
90 : QTimer browseTimer;
91 :
92 : private:
93 2 : void _addInstanceItem(const QString& instance)
94 : {
95 4 : const std::string& instanceStr = instance.toStdString();
96 2 : QObject* instanceItem = new QObject(rootItem.get());
97 2 : instanceItem->setObjectName(instance);
98 4 : const Strings& keys = service.getKeys(instanceStr);
99 6 : for (const std::string& key : keys)
100 : {
101 : const QString data =
102 8 : QString("%1 = %2")
103 16 : .arg(QString::fromStdString(key))
104 16 : .arg(QString::fromStdString(service.get(instanceStr, key)));
105 4 : QObject* kvItem = new QObject(instanceItem);
106 4 : kvItem->setObjectName(data);
107 : }
108 2 : }
109 :
110 2 : void _removeInstanceItem(const QString& instance)
111 : {
112 2 : QObject* child = rootItem->findChild<QObject*>(instance);
113 2 : delete child;
114 2 : }
115 : };
116 :
117 4 : ItemModel::ItemModel(Servus& service, QObject* parent_)
118 : : QAbstractItemModel(parent_)
119 4 : , _impl(new Impl(service, *this))
120 : {
121 4 : }
122 :
123 4 : ItemModel::~ItemModel()
124 : {
125 4 : }
126 :
127 8 : QModelIndex ItemModel::index(const int row, const int column,
128 : const QModelIndex& parent_) const
129 : {
130 8 : if (!hasIndex(row, column, parent_))
131 2 : return QModelIndex();
132 :
133 : QObject* parentItem;
134 6 : if (!parent_.isValid())
135 2 : parentItem = _impl->rootItem.get();
136 : else
137 4 : parentItem = static_cast<QObject*>(parent_.internalPointer());
138 :
139 6 : QObject* childItem = parentItem->children()[row];
140 6 : if (childItem)
141 6 : return createIndex(row, column, childItem);
142 0 : return QModelIndex();
143 : }
144 :
145 6 : QModelIndex ItemModel::parent(const QModelIndex& index_) const
146 : {
147 6 : if (!index_.isValid())
148 2 : return QModelIndex();
149 :
150 4 : QObject* childItem = static_cast<QObject*>(index_.internalPointer());
151 4 : QObject* parentItem = childItem->parent();
152 :
153 4 : if (parentItem == _impl->rootItem.get())
154 2 : return QModelIndex();
155 :
156 2 : if (!parentItem->parent())
157 0 : return createIndex(0, 0, parentItem);
158 2 : const int row = parentItem->parent()->children().indexOf(parentItem);
159 2 : return createIndex(row, 0, parentItem);
160 : }
161 :
162 20 : int ItemModel::rowCount(const QModelIndex& parent_) const
163 : {
164 : QObject* parentItem;
165 20 : if (!parent_.isValid())
166 12 : parentItem = _impl->rootItem.get();
167 : else
168 8 : parentItem = static_cast<QObject*>(parent_.internalPointer());
169 :
170 20 : return parentItem->children().size();
171 : }
172 :
173 10 : int ItemModel::columnCount(const QModelIndex& index_) const
174 : {
175 : Q_UNUSED(index_);
176 10 : return 1;
177 : }
178 :
179 14 : QVariant ItemModel::data(const QModelIndex& index_, const int role) const
180 : {
181 14 : if (!index_.isValid())
182 2 : return QVariant();
183 :
184 12 : QObject* item = static_cast<QObject*>(index_.internalPointer());
185 :
186 12 : switch (role)
187 : {
188 : case Qt::DisplayRole:
189 6 : return item->objectName();
190 : case Qt::ToolTipRole:
191 : case Qt::UserRole:
192 4 : if (item->children().isEmpty())
193 2 : return QVariant();
194 4 : return QString::fromStdString(
195 6 : _impl->service.getHost(item->objectName().toStdString()));
196 : default:
197 2 : return QVariant();
198 : }
199 : }
200 :
201 4 : QVariant ItemModel::headerData(const int section,
202 : const Qt::Orientation orientation,
203 : const int role) const
204 : {
205 : Q_UNUSED(section);
206 4 : if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
207 2 : return _impl->rootItem->objectName();
208 :
209 2 : return QVariant();
210 : }
211 : }
212 30 : }
|