KDELibs4Support

kdevicelistmodel.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2006 Michael Larouche <[email protected]>
3  2007 Kevin Ottens <[email protected]>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License version 2 as published by the Free Software Foundation.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 
19 */
20 #include "kdevicelistmodel.h"
21 #include "kdevicelistitem_p.h"
22 
23 #include <solid/devicenotifier.h>
24 #include <solid/deviceinterface.h>
25 
26 #include <QTimer>
27 #include <QIcon>
28 
29 #include <klocalizedstring.h>
30 
31 class Q_DECL_HIDDEN KDeviceListModel::Private
32 {
33 public:
34  Private(KDeviceListModel *self) : q(self), rootItem(new KDeviceListItem()) {}
35  ~Private()
36  {
37  delete rootItem;
38  }
39 
41 
42  KDeviceListItem *rootItem;
44  Solid::Predicate predicate;
45 
46  void initialize(const Solid::Predicate &p);
47  QModelIndex indexForItem(KDeviceListItem *item) const;
48  void addDevice(const Solid::Device &device);
49  void removeBranch(const QString &udi);
50 
51  // Private slots
52  void _k_initDeviceList();
53  void _k_deviceAdded(const QString &udi);
54  void _k_deviceRemoved(const QString &udi);
55 };
56 
57 KDeviceListModel::KDeviceListModel(QObject *parent)
58  : QAbstractItemModel(parent), d(new Private(this))
59 {
60  d->deviceItems[QString()] = d->rootItem;
61  d->initialize(Solid::Predicate());
62 }
63 
64 KDeviceListModel::KDeviceListModel(const QString &predicate, QObject *parent)
65  : QAbstractItemModel(parent), d(new Private(this))
66 {
67  d->initialize(Solid::Predicate::fromString(predicate));
68 }
69 
70 KDeviceListModel::KDeviceListModel(const Solid::Predicate &predicate, QObject *parent)
71  : QAbstractItemModel(parent), d(new Private(this))
72 {
73  d->initialize(predicate);
74 }
75 
76 KDeviceListModel::~KDeviceListModel()
77 {
78  delete d;
79 }
80 
81 void KDeviceListModel::Private::initialize(const Solid::Predicate &p)
82 {
83  predicate = p;
84 
85  // Delay load of hardware list when the event loop start
86  QTimer::singleShot(0, q, SLOT(_k_initDeviceList()));
87 }
88 
90 {
91  if (!index.isValid()) {
92  return QVariant();
93  }
94 
95  KDeviceListItem *deviceItem = static_cast<KDeviceListItem *>(index.internalPointer());
96  Solid::Device device = deviceItem->device();
97 
98  QVariant returnData;
99  if (role == Qt::DisplayRole) {
100  returnData = device.product();
101  }
102  // Only display icons in the first column
103  else if (role == Qt::DecorationRole && index.column() == 0) {
104  returnData = QIcon::fromTheme(device.icon());
105  }
106 
107  return returnData;
108 }
109 
110 QVariant KDeviceListModel::headerData(int section, Qt::Orientation orientation, int role) const
111 {
112  Q_UNUSED(section)
113 
114  if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
115  return i18n("Device name");
116  }
117 
118  return QVariant();
119 }
120 
121 QModelIndex KDeviceListModel::index(int row, int column, const QModelIndex &parent) const
122 {
123  if (row < 0 || column != 0) {
124  return QModelIndex();
125  }
126 
127  KDeviceListItem *parentItem;
128  if (parent.isValid()) {
129  parentItem = static_cast<KDeviceListItem *>(parent.internalPointer());
130  } else {
131  parentItem = d->rootItem;
132  }
133 
134  KDeviceListItem *childItem = parentItem->child(row);
135 
136  if (childItem) {
137  return createIndex(row, column, childItem);
138  } else {
139  return QModelIndex();
140  }
141 }
142 
143 QModelIndex KDeviceListModel::rootIndex() const
144 {
145  return d->indexForItem(d->rootItem);
146 }
147 
149 {
150  if (!child.isValid()) {
151  return QModelIndex();
152  }
153 
154  KDeviceListItem *childItem = static_cast<KDeviceListItem *>(child.internalPointer());
155  KDeviceListItem *parentItem = childItem->parent();
156 
157  if (!parentItem) {
158  return QModelIndex();
159  } else {
160  return d->indexForItem(parentItem);
161  }
162 }
163 
164 int KDeviceListModel::rowCount(const QModelIndex &parent) const
165 {
166  if (!parent.isValid()) {
167  return d->rootItem->childCount();
168  }
169 
170  KDeviceListItem *item = static_cast<KDeviceListItem *>(parent.internalPointer());
171 
172  return item->childCount();
173 }
174 
176 {
177  Q_UNUSED(parent);
178  // We only know 1 information for a particualiar device.
179  return 1;
180 }
181 
182 Solid::Device KDeviceListModel::deviceForIndex(const QModelIndex &index) const
183 {
184  KDeviceListItem *deviceItem = static_cast<KDeviceListItem *>(index.internalPointer());
185  return deviceItem->device();
186 }
187 
188 void KDeviceListModel::Private::_k_initDeviceList()
189 {
190  Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance();
191 
192  connect(notifier, SIGNAL(deviceAdded(QString)),
193  q, SLOT(_k_deviceAdded(QString)));
194  connect(notifier, SIGNAL(deviceRemoved(QString)),
195  q, SLOT(_k_deviceRemoved(QString)));
196 
197  // Use allDevices() from the manager if the predicate is not valid
198  // otherwise the returned list is empty
199  const QList<Solid::Device> &deviceList = predicate.isValid() ?
202 
203  foreach (const Solid::Device &device, deviceList) {
204  addDevice(device);
205  }
206 
207  emit q->modelInitialized();
208 }
209 
210 void KDeviceListModel::Private::addDevice(const Solid::Device &device)
211 {
212  // Don't insert invalid devices
213  if (!device.isValid()) {
214  return;
215  }
216 
217  // Don't insert devices that doesn't match the predicate set
218  // (except for the root)
219  if (!device.parentUdi().isEmpty()
220  && predicate.isValid() && !predicate.matches(device)) {
221  return;
222  }
223 
224  KDeviceListItem *item;
225  if (deviceItems.contains(device.udi())) { // It was already inserted as a parent
226  item = deviceItems[device.udi()];
227  } else {
228  item = new KDeviceListItem();
229  deviceItems[device.udi()] = item;
230  }
231  item->setDevice(device);
232 
233  KDeviceListItem *parent = rootItem;
234 
235  if (!deviceItems.contains(device.parentUdi())) { // The parent was not present, try to insert it in the model
236  addDevice(Solid::Device(device.parentUdi()));
237  }
238 
239  if (deviceItems.contains(device.parentUdi())) { // Update the parent if the device is now present
240  parent = deviceItems[device.parentUdi()];
241  }
242 
243  if (item->parent() != parent) { // If it's already our parent no need to signal the new row
244  q->beginInsertRows(indexForItem(parent), parent->childCount(), parent->childCount());
245  item->setParent(parent);
246  q->endInsertRows();
247  }
248 }
249 
250 void KDeviceListModel::Private::removeBranch(const QString &udi)
251 {
252  if (!deviceItems.contains(udi)) {
253  return;
254  }
255 
256  KDeviceListItem *item = deviceItems[udi];
257  KDeviceListItem *parent = item->parent();
258 
259  QList<KDeviceListItem *> children = item->children();
260 
261  foreach (KDeviceListItem *child, children) {
262  removeBranch(child->device().udi());
263  }
264 
265  q->beginRemoveRows(indexForItem(parent),
266  item->row(), item->row());
267 
268  item->setParent(nullptr);
269  deviceItems.remove(udi);
270  delete item;
271 
272  q->endRemoveRows();
273 }
274 
275 void KDeviceListModel::Private::_k_deviceAdded(const QString &udi)
276 {
277  Solid::Device device(udi);
278  addDevice(device);
279 }
280 
281 void KDeviceListModel::Private::_k_deviceRemoved(const QString &udi)
282 {
283  removeBranch(udi);
284 }
285 
286 QModelIndex KDeviceListModel::Private::indexForItem(KDeviceListItem *item) const
287 {
288  if (item == rootItem) {
289  return QModelIndex();
290  } else {
291  return q->createIndex(item->row(), 0, item);
292  }
293 }
294 
295 #include "moc_kdevicelistmodel.cpp"
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Get the header data for a given section, orientation and role.
const QObjectList & children() const const
KCRASH_EXPORT void initialize()
bool matches(const Device &device) const
bool isValid() const const
static QList< Device > listFromQuery(const Predicate &predicate, const QString &parentUdi=QString())
DisplayRole
bool isEmpty() const const
static Predicate fromString(const QString &predicate)
void * internalPointer() const const
bool isValid() const
QString udi() const
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Get the number of rows for a model index.
QModelIndex createIndex(int row, int column, void *ptr) const const
bool isValid() const
QString icon() const
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Get the children model index for the given row and column.
QString i18n(const char *text, const TYPE &arg...)
Device list model in Qt&#39;s Interview framework.
static QList< Device > allDevices()
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Get the number of columns for a model index.
int column() const const
QIcon fromTheme(const QString &name)
Orientation
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
QVariant data(const QModelIndex &index, int role) const override
Get a visible data based on Qt role for the given index.
QString product() const
QString parentUdi() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Jun 20 2021 22:58:13 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.