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"
23 #include <QStandardItemModel>
24 #include <QModelIndex>
26 #include <QVBoxLayout>
27 #include <QtDBus/QDBusInterface>
28 #include <QtDBus/QDBusReply>
29 #include <QHeaderView>
35 #include <KColorScheme>
37 #include <KIconLoader>
38 #include <KGlobalSettings>
39 #include <KMessageBox>
42 #include <Plasma/Dialog>
43 #include <Plasma/Delegate>
44 #include <Plasma/Theme>
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>
54 #include "notifierview.h"
55 #include "devicenotifier.h"
57 using namespace Notifier
;
58 using namespace Plasma
;
60 NotifierDialog::NotifierDialog(DeviceNotifier
* notifier
,QObject
*parent
)
69 m_hotplugModel
= new QStandardItemModel(this);
71 //make the invisible root for tree device
72 m_rootItem
= m_hotplugModel
->invisibleRootItem();
75 NotifierDialog::~NotifierDialog()
80 QWidget
* NotifierDialog::dialog()
85 void NotifierDialog::hide()
90 void NotifierDialog::show()
95 QStandardItem
* NotifierDialog::searchOrCreateDeviceCategory(const QString
&categoryName
)
97 int rowCount
= m_hotplugModel
->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
);
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
);
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
);
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();
142 Solid::Device
device(udi
);
143 QString categoryOfInsertedDevice
= getCategoryNameOfDevice(device
);
144 QStandardItem
*currentCategory
= searchOrCreateDeviceCategory(categoryOfInsertedDevice
);
147 currentCategory
->insertRow(0,item
);
148 currentCategory
->setChild(0, 1, actionItem
);
162 m_notifierView
->calculateRects();
165 void NotifierDialog::setUnMount(bool unmount
, const QString
&name
)
167 QModelIndex index
= indexForUdi(name
);
168 if (!index
.isValid()) {
171 QStandardItem
*currentItem
= m_hotplugModel
->itemFromIndex(index
);
172 QStandardItem
*childAction
= currentItem
->parent()->child(currentItem
->row(), 1);
175 icon
= KIcon("media-eject");
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()) {
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()) {
207 return index
.data(role
);
211 void NotifierDialog::removeDevice(const QString
&name
)
213 QModelIndex index
= indexForUdi(name
);
214 if (!index
.isValid()) {
218 QStandardItem
*device
= m_hotplugModel
->itemFromIndex(index
);
219 QStandardItem
*category
= device
->parent();
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
);
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());
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());
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
)));
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
)));
363 //open (index.data(ScopeRole).toInt() == OpenAction)
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
);
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
);
385 return Solid::DeviceInterface::typeToString(type
);
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"