KIO
kdevicelistmodel.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 2006 Michael Larouche <michael.larouche@kdemail.net> 00003 2007 Kevin Ottens <ervin@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License version 2 as published by the Free Software Foundation. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 00019 */ 00020 #include "kdevicelistmodel.h" 00021 #include "kdevicelistitem_p.h" 00022 00023 #include <solid/devicenotifier.h> 00024 #include <solid/device.h> 00025 #include <solid/deviceinterface.h> 00026 00027 #include <QTimer> 00028 00029 #include <kdebug.h> 00030 #include <klocale.h> 00031 #include <kicon.h> 00032 00033 class KDeviceListModel::Private 00034 { 00035 public: 00036 Private(KDeviceListModel *self) : q(self), rootItem(new KDeviceListItem()) {} 00037 ~Private() { delete rootItem; } 00038 00039 00040 KDeviceListModel *q; 00041 00042 KDeviceListItem *rootItem; 00043 QMap<QString, KDeviceListItem*> deviceItems; 00044 Solid::Predicate predicate; 00045 00046 00047 void initialize(const Solid::Predicate &p); 00048 QModelIndex indexForItem(KDeviceListItem *item) const; 00049 void addDevice(const Solid::Device &device); 00050 void removeBranch(const QString &udi); 00051 00052 // Private slots 00053 void _k_initDeviceList(); 00054 void _k_deviceAdded(const QString &udi); 00055 void _k_deviceRemoved(const QString &udi); 00056 }; 00057 00058 KDeviceListModel::KDeviceListModel(QObject *parent) 00059 : QAbstractItemModel(parent), d(new Private(this)) 00060 { 00061 d->deviceItems[QString()] = d->rootItem; 00062 d->initialize(Solid::Predicate()); 00063 } 00064 00065 KDeviceListModel::KDeviceListModel(const QString &predicate, QObject *parent) 00066 : QAbstractItemModel(parent), d(new Private(this)) 00067 { 00068 d->initialize(Solid::Predicate::fromString(predicate)); 00069 } 00070 00071 KDeviceListModel::KDeviceListModel(const Solid::Predicate &predicate, QObject *parent) 00072 : QAbstractItemModel(parent), d(new Private(this)) 00073 { 00074 d->initialize(predicate); 00075 } 00076 00077 KDeviceListModel::~KDeviceListModel() 00078 { 00079 delete d; 00080 } 00081 00082 void KDeviceListModel::Private::initialize(const Solid::Predicate &p) 00083 { 00084 predicate = p; 00085 00086 // Delay load of hardware list when the event loop start 00087 QTimer::singleShot( 0, q, SLOT(_k_initDeviceList()) ); 00088 } 00089 00090 QVariant KDeviceListModel::data(const QModelIndex &index, int role) const 00091 { 00092 if( !index.isValid() ) 00093 return QVariant(); 00094 00095 KDeviceListItem *deviceItem = static_cast<KDeviceListItem*>(index.internalPointer()); 00096 Solid::Device device = deviceItem->device(); 00097 00098 QVariant returnData; 00099 if (role == Qt::DisplayRole) { 00100 returnData = device.product(); 00101 } 00102 // Only display icons in the first column 00103 else if (role == Qt::DecorationRole && index.column() == 0) { 00104 returnData = KIcon(device.icon()); 00105 } 00106 00107 return returnData; 00108 } 00109 00110 QVariant KDeviceListModel::headerData(int section, Qt::Orientation orientation, int role) const 00111 { 00112 Q_UNUSED(section) 00113 00114 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) 00115 { 00116 return i18n("Device name"); 00117 } 00118 00119 return QVariant(); 00120 } 00121 00122 QModelIndex KDeviceListModel::index(int row, int column, const QModelIndex &parent) const 00123 { 00124 if (row<0 || column!=0) 00125 return QModelIndex(); 00126 00127 KDeviceListItem *parentItem; 00128 if (parent.isValid()) { 00129 parentItem = static_cast<KDeviceListItem*>(parent.internalPointer()); 00130 } else { 00131 parentItem = d->rootItem; 00132 } 00133 00134 KDeviceListItem *childItem = parentItem->child(row); 00135 00136 if (childItem) { 00137 return createIndex(row, column, childItem); 00138 } else { 00139 return QModelIndex(); 00140 } 00141 } 00142 00143 QModelIndex KDeviceListModel::rootIndex() const 00144 { 00145 return d->indexForItem(d->rootItem); 00146 } 00147 00148 QModelIndex KDeviceListModel::parent(const QModelIndex &child) const 00149 { 00150 if (!child.isValid()) 00151 return QModelIndex(); 00152 00153 KDeviceListItem *childItem = static_cast<KDeviceListItem*>(child.internalPointer()); 00154 KDeviceListItem *parentItem = childItem->parent(); 00155 00156 if (!parentItem) 00157 return QModelIndex(); 00158 else 00159 return d->indexForItem(parentItem); 00160 } 00161 00162 int KDeviceListModel::rowCount(const QModelIndex &parent) const 00163 { 00164 if( !parent.isValid() ) 00165 return d->rootItem->childCount(); 00166 00167 KDeviceListItem *item = static_cast<KDeviceListItem*>(parent.internalPointer()); 00168 00169 return item->childCount(); 00170 } 00171 00172 int KDeviceListModel::columnCount(const QModelIndex &parent) const 00173 { 00174 Q_UNUSED(parent); 00175 // We only know 1 information for a particualiar device. 00176 return 1; 00177 } 00178 00179 Solid::Device KDeviceListModel::deviceForIndex(const QModelIndex& index) const 00180 { 00181 KDeviceListItem *deviceItem = static_cast<KDeviceListItem*>(index.internalPointer()); 00182 return deviceItem->device(); 00183 } 00184 00185 void KDeviceListModel::Private::_k_initDeviceList() 00186 { 00187 Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance(); 00188 00189 connect(notifier, SIGNAL(deviceAdded(const QString&)), 00190 q, SLOT(_k_deviceAdded(const QString&))); 00191 connect(notifier, SIGNAL(deviceRemoved(const QString&)), 00192 q, SLOT(_k_deviceRemoved(const QString&))); 00193 00194 // Use allDevices() from the manager if the predicate is not valid 00195 // otherwise the returned list is empty 00196 const QList<Solid::Device> &deviceList = predicate.isValid()? 00197 Solid::Device::listFromQuery(predicate) 00198 : Solid::Device::allDevices(); 00199 00200 foreach(const Solid::Device &device, deviceList) 00201 { 00202 addDevice(device); 00203 } 00204 00205 emit q->modelInitialized(); 00206 } 00207 00208 void KDeviceListModel::Private::addDevice(const Solid::Device &device) 00209 { 00210 // Don't insert invalid devices 00211 if (!device.isValid()) return; 00212 00213 // Don't insert devices that doesn't match the predicate set 00214 // (except for the root) 00215 if (!device.parentUdi().isEmpty() 00216 && predicate.isValid() && !predicate.matches(device)) { 00217 return; 00218 } 00219 00220 KDeviceListItem *item; 00221 if (deviceItems.contains(device.udi())) { // It was already inserted as a parent 00222 item = deviceItems[device.udi()]; 00223 } else { 00224 item = new KDeviceListItem(); 00225 deviceItems[device.udi()] = item; 00226 } 00227 item->setDevice(device); 00228 00229 KDeviceListItem *parent = rootItem; 00230 00231 if (!deviceItems.contains(device.parentUdi()) ) // The parent was not present, try to insert it in the model 00232 addDevice( Solid::Device(device.parentUdi()) ); 00233 00234 if (deviceItems.contains(device.parentUdi())) // Update the parent if the device is now present 00235 parent = deviceItems[device.parentUdi()]; 00236 00237 if (item->parent()!=parent) { // If it's already our parent no need to signal the new row 00238 q->beginInsertRows(indexForItem(parent), parent->childCount(), parent->childCount()); 00239 item->setParent(parent); 00240 q->endInsertRows(); 00241 } 00242 } 00243 00244 void KDeviceListModel::Private::removeBranch(const QString &udi) 00245 { 00246 if (!deviceItems.contains(udi)) return; 00247 00248 KDeviceListItem *item = deviceItems[udi]; 00249 KDeviceListItem *parent = item->parent(); 00250 00251 QList<KDeviceListItem*> children = item->children(); 00252 00253 foreach(KDeviceListItem *child, children) { 00254 removeBranch(child->device().udi()); 00255 } 00256 00257 q->beginRemoveRows(indexForItem(parent), 00258 item->row(), item->row()); 00259 00260 item->setParent(0); 00261 deviceItems.remove(udi); 00262 delete item; 00263 00264 q->endRemoveRows(); 00265 } 00266 00267 void KDeviceListModel::Private::_k_deviceAdded(const QString &udi) 00268 { 00269 Solid::Device device(udi); 00270 addDevice(device); 00271 } 00272 00273 void KDeviceListModel::Private::_k_deviceRemoved(const QString &udi) 00274 { 00275 removeBranch(udi); 00276 } 00277 00278 QModelIndex KDeviceListModel::Private::indexForItem(KDeviceListItem *item) const 00279 { 00280 if (item==rootItem) { 00281 return QModelIndex(); 00282 } else { 00283 return q->createIndex(item->row(), 0, item); 00284 } 00285 } 00286 00287 #include "kdevicelistmodel.moc"
KDE 4.6 API Reference