not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / plasma / applets / devicenotifier / notifierdialog.cpp
blob9e11ddd0b07a3ec57c725ab133b1675d87b3bc98
1 /*
2 Copyright 2008 by Alexis Ménard <darktears31@gmail.com>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
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.
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.
20 #include "notifierdialog.h"
22 //Qt
23 #include <QStandardItemModel>
24 #include <QModelIndex>
25 #include <QLabel>
26 #include <QVBoxLayout>
27 #include <QtDBus/QDBusInterface>
28 #include <QtDBus/QDBusReply>
29 #include <QHeaderView>
30 #include <QTimer>
31 #include <QMetaEnum>
33 //KDE
34 #include <KDebug>
35 #include <KColorScheme>
36 #include <KIcon>
37 #include <KIconLoader>
38 #include <KGlobalSettings>
39 #include <KMessageBox>
41 //plasma
42 #include <Plasma/Dialog>
43 #include <Plasma/Delegate>
44 #include <Plasma/Theme>
46 //solid
47 #include <solid/device.h>
48 #include <solid/opticaldisc.h>
49 #include <solid/storageaccess.h>
50 #include <solid/opticaldrive.h>
51 #include <solid/deviceinterface.h>
53 //own
54 #include "notifierview.h"
55 #include "devicenotifier.h"
57 using namespace Notifier;
58 using namespace Plasma;
60 NotifierDialog::NotifierDialog(DeviceNotifier * notifier,QObject *parent)
61 : QObject(parent),
62 m_hotplugModel(0),
63 m_widget(0),
64 m_notifierView(0),
65 m_label(0),
66 m_notifier(notifier),
67 m_rootItem(0)
69 m_hotplugModel = new QStandardItemModel(this);
70 buildDialog();
71 //make the invisible root for tree device
72 m_rootItem = m_hotplugModel->invisibleRootItem();
75 NotifierDialog::~NotifierDialog()
80 QWidget * NotifierDialog::dialog()
82 return m_widget;
85 void NotifierDialog::hide()
87 m_widget->hide();
90 void NotifierDialog::show()
92 m_widget->show();
95 QStandardItem* NotifierDialog::searchOrCreateDeviceCategory(const QString &categoryName)
97 int rowCount = m_hotplugModel->rowCount();
98 if(rowCount > 0)
100 int i = 0;
101 while (i<rowCount)
103 QModelIndex index = m_hotplugModel->index(i, 0);
104 QString itemUdi = m_hotplugModel->data(index, SolidUdiRole).toString();
105 QStandardItem *currentItem = m_hotplugModel->itemFromIndex(index);
106 if(currentItem)
108 QString currentItemName = currentItem->text();
109 if (currentItemName == categoryName)
111 //the category is find... we have to return the pointer on this category
112 return m_hotplugModel->itemFromIndex(index);
115 i++;
118 //insert a new category for device if not find and return the pointer
119 QStandardItem *newCategory = new QStandardItem(QString(categoryName));
120 m_hotplugModel->setData(newCategory->index(),categoryName,Qt::DisplayRole);
121 m_rootItem->insertRow(0,newCategory);
122 m_hotplugModel->setItem(0, 1, NULL);
123 m_hotplugModel->setHeaderData(0, Qt::Horizontal,QString(""),Qt::EditRole);
124 m_hotplugModel->setHeaderData(1, Qt::Horizontal,QString(""),Qt::EditRole);
125 return newCategory;
128 void NotifierDialog::insertDevice(const QString &name)
130 QStandardItem *item = new QStandardItem();
131 item->setData(name, SolidUdiRole);
132 item->setData(Plasma::Delegate::MainColumn, ScopeRole);
133 item->setData(false, SubTitleMandatoryRole);
135 QStandardItem *actionItem = new QStandardItem();
136 actionItem->setData(name, SolidUdiRole);
137 actionItem->setData(Plasma::Delegate::SecondaryActionColumn, ScopeRole);
139 //search or create the category for inserted device
140 QString udi = item->data(SolidUdiRole).toString();
141 if(!udi.isNull()) {
142 Solid::Device device(udi);
143 QString categoryOfInsertedDevice = getCategoryNameOfDevice(device);
144 QStandardItem *currentCategory = searchOrCreateDeviceCategory(categoryOfInsertedDevice);
145 if(currentCategory)
147 currentCategory->insertRow(0,item);
148 currentCategory->setChild(0, 1, actionItem);
150 else
152 delete item;
153 delete actionItem;
156 else
158 delete item;
159 delete actionItem;
162 m_notifierView->calculateRects();
165 void NotifierDialog::setUnMount(bool unmount, const QString &name)
167 QModelIndex index = indexForUdi(name);
168 if (!index.isValid()) {
169 return;
171 QStandardItem *currentItem = m_hotplugModel->itemFromIndex(index);
172 QStandardItem *childAction = currentItem->parent()->child(currentItem->row(), 1);
173 QVariant icon;
174 if (unmount) {
175 icon = KIcon("media-eject");
177 else {
178 icon = KIcon();
180 m_hotplugModel->setData(childAction->index(),icon,Qt::DecorationRole);
183 void NotifierDialog::setDeviceData(const QString &name, QVariant data, int role)
185 QModelIndex index = indexForUdi(name);
186 if (!index.isValid()) {
187 return;
189 if (role == Qt::DecorationRole) {
190 QStandardItem *device = m_hotplugModel->itemFromIndex(index);
191 QStandardItem *category = device->parent();
192 QModelIndex parentIndex = category->index();
193 if (!parentIndex.data(Qt::DecorationRole).isValid()) {
194 m_hotplugModel->setData(parentIndex,data,role);
197 m_hotplugModel->setData(index,data,role);
200 QVariant NotifierDialog::getDeviceData(const QString &name, int role)
202 QModelIndex index = indexForUdi(name);
203 if (!index.isValid()) {
204 return QVariant();
206 else {
207 return index.data(role);
211 void NotifierDialog::removeDevice(const QString &name)
213 QModelIndex index = indexForUdi(name);
214 if (!index.isValid()) {
215 return;
218 QStandardItem *device = m_hotplugModel->itemFromIndex(index);
219 QStandardItem *category = device->parent();
221 //removing device
222 category->removeRow(device->row());
224 //remove category if there's no devices into it
225 if (!category->hasChildren()) {
226 m_rootItem->removeRow(category->row());
229 m_notifierView->calculateRects();
232 void NotifierDialog::removeDevice(int index)
234 m_hotplugModel->removeRow(index);
235 m_notifierView->calculateRects();
238 int NotifierDialog::countDevices()
240 return m_hotplugModel->rowCount();
243 QString NotifierDialog::getDeviceUdi(int index)
245 QModelIndex modelIndex = m_hotplugModel->index(index, 0);
246 return m_hotplugModel->data(modelIndex, SolidUdiRole).toString();
249 void NotifierDialog::buildDialog()
251 m_widget = new QWidget();
253 QVBoxLayout *l_layout = new QVBoxLayout(m_widget);
254 l_layout->setSpacing(0);
255 l_layout->setMargin(0);
257 m_label = new QLabel(m_widget);
258 updateColors();
260 QLabel *icon = new QLabel(m_widget);
261 icon->setPixmap(KIcon("emblem-mounted").pixmap(KIconLoader::SizeMedium, KIconLoader::SizeMedium));
263 QHBoxLayout *l_layout2 = new QHBoxLayout(m_widget);
264 l_layout2->setSpacing(0);
265 l_layout2->setMargin(0);
267 l_layout2->addWidget(icon);
268 l_layout2->addWidget(m_label);
270 l_layout2->setAlignment(Qt::AlignCenter);
273 m_notifierView = new NotifierView(m_widget);
274 m_notifierView->setModel(m_hotplugModel);
275 m_notifierView->setMinimumSize(150,300);
276 m_notifierView->setFocusPolicy(Qt::NoFocus);
278 Plasma::Delegate *delegate = new Delegate(this);
279 //map the roles of m_hotplugModel into the standard Plasma::Delegate roles
280 delegate->setRoleMapping(Plasma::Delegate::SubTitleRole, ActionRole);
281 delegate->setRoleMapping(Plasma::Delegate::ColumnTypeRole, ScopeRole);
282 delegate->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole, SubTitleMandatoryRole);
283 m_notifierView->setItemDelegate(delegate);
285 l_layout->addLayout(l_layout2);
286 l_layout->addWidget(m_notifierView);
287 m_widget->setLayout(l_layout);
289 connect(m_notifierView, SIGNAL(clicked(const QModelIndex&)),this,SLOT(slotOnItemClicked(const QModelIndex&)));
291 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(updateColors())); // allows updating of colors automatically
294 void NotifierDialog::storageTeardownDone(Solid::ErrorType error, QVariant errorData)
296 if (error && errorData.isValid()) {
297 KMessageBox::error(0, i18n("Cannot unmount the device.\nOne or more files on this device are open within an application."), QString());
299 else {
300 m_notifier->changeNotifierIcon("dialog-ok");
301 m_notifier->update();
302 QTimer::singleShot(5000, this, SLOT(resetNotifierIcon()));
305 //show the message only one time
306 disconnect(sender(), SIGNAL(teardownDone(Solid::ErrorType, QVariant, const QString &)),
307 this, SLOT(storageTeardownDone(Solid::ErrorType, QVariant)));
310 void NotifierDialog::storageEjectDone(Solid::ErrorType error, QVariant errorData)
312 if (error && errorData.isValid()) {
313 KMessageBox::error(0, i18n("Cannot eject the disc.\nOne or more files on this disc are open within an application."), QString());
314 } else {
315 m_notifier->changeNotifierIcon("dialog-ok");
316 m_notifier->update();
317 QTimer::singleShot(2000, this, SLOT(resetNotifierIcon()));
319 //show the message only one time
320 disconnect(sender(), SIGNAL(ejectDone(Solid::ErrorType, QVariant, const QString &)),
321 this, SLOT(storageEjectDone(Solid::ErrorType, QVariant)));
324 QModelIndex NotifierDialog::indexForUdi(const QString &udi) const
326 int rowCount = m_hotplugModel->rowCount();
327 for (int i=0; i < rowCount; ++i) {
328 QModelIndex index = m_hotplugModel->index(i, 0);
329 QStandardItem *currentItem = m_hotplugModel->itemFromIndex(index);
330 for (int j=0; j < currentItem->rowCount(); ++j) {
331 QStandardItem *childItem = currentItem->child(j, 0);
332 QString itemUdi = m_hotplugModel->data(childItem->index(), SolidUdiRole).toString();
333 if (itemUdi == udi) {
334 return childItem->index();
338 //Is it possible to go here?no...
339 kDebug() << "We should not be here!";
340 return QModelIndex();
343 void NotifierDialog::slotOnItemClicked(const QModelIndex &index)
345 QString udi = QString(m_hotplugModel->data(index, SolidUdiRole).toString());
347 //unmount (probably in the future different action types for different device types)
348 if (index.data(ScopeRole).toInt() == Plasma::Delegate::SecondaryActionColumn) {
349 Solid::Device device(udi);
351 if (device.is<Solid::OpticalDisc>()) {
352 Solid::OpticalDrive *drive = device.parent().as<Solid::OpticalDrive>();
353 connect(drive, SIGNAL(ejectDone(Solid::ErrorType, QVariant, const QString &)),
354 this, SLOT(storageEjectDone(Solid::ErrorType, QVariant)));
355 drive->eject();
356 } else if (device.is<Solid::StorageVolume>()) {
357 Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
358 if (access && access->isAccessible()) {
359 connect(access, SIGNAL(teardownDone(Solid::ErrorType, QVariant, const QString &)),this, SLOT(storageTeardownDone(Solid::ErrorType, QVariant)));
360 access->teardown();
363 //open (index.data(ScopeRole).toInt() == OpenAction)
364 } else {
365 QStringList desktopFiles = m_hotplugModel->data(index, PredicateFilesRole).toStringList();
367 kDebug() << "DeviceNotifier:: call Solid Ui Server with params :" << udi \
368 << "," << desktopFiles;
369 QDBusInterface soliduiserver("org.kde.kded", "/modules/soliduiserver", "org.kde.SolidUiServer");
370 QDBusReply<void> reply = soliduiserver.call("showActionsDialog", udi, desktopFiles);
372 emit itemSelected();
375 QString NotifierDialog::getCategoryNameOfDevice(const Solid::Device& device)
377 int index = Solid::DeviceInterface::staticMetaObject.indexOfEnumerator("Type");
378 QMetaEnum typeEnum = Solid::DeviceInterface::staticMetaObject.enumerator(index);
379 for (int i = typeEnum.keyCount() - 1 ; i > 0; i--)
381 Solid::DeviceInterface::Type type = (Solid::DeviceInterface::Type)typeEnum.value(i);
382 const Solid::DeviceInterface *interface = device.asDeviceInterface(type);
383 if (interface)
385 return Solid::DeviceInterface::typeToString(type);
388 return 0;
391 void NotifierDialog::resetNotifierIcon()
393 m_notifier->changeNotifierIcon();
394 m_notifier->update();
397 void NotifierDialog::updateColors()
399 KColorScheme colorTheme = KColorScheme(QPalette::Active, KColorScheme::View,Plasma::Theme::defaultTheme()->colorScheme());
400 m_label->setText(i18n("<font color=\"%1\">Devices recently plugged in:</font>",colorTheme.foreground(KColorScheme::NormalText).color().name()));
402 QPalette p = m_widget->palette();
403 p.setColor(QPalette::Window, Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor));
404 m_widget->setPalette(p);
407 #include "notifierdialog.moc"