00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "notifierdialog.h"
00021
00022
00023 #include <QStandardItemModel>
00024 #include <QModelIndex>
00025 #include <QLabel>
00026 #include <QVBoxLayout>
00027 #include <QtDBus/QDBusInterface>
00028 #include <QtDBus/QDBusReply>
00029 #include <QHeaderView>
00030 #include <QTimer>
00031 #include <QMetaEnum>
00032
00033
00034 #include <KDebug>
00035 #include <KColorScheme>
00036 #include <KIcon>
00037 #include <KIconLoader>
00038 #include <KGlobalSettings>
00039 #include <KMessageBox>
00040
00041
00042 #include <Plasma/Dialog>
00043 #include <Plasma/Delegate>
00044 #include <Plasma/Theme>
00045
00046
00047 #include <solid/device.h>
00048 #include <solid/opticaldisc.h>
00049 #include <solid/storageaccess.h>
00050 #include <solid/opticaldrive.h>
00051 #include <solid/deviceinterface.h>
00052
00053
00054 #include "notifierview.h"
00055 #include "devicenotifier.h"
00056
00057 using namespace Notifier;
00058 using namespace Plasma;
00059
00060 NotifierDialog::NotifierDialog(DeviceNotifier * notifier,QObject *parent)
00061 : QObject(parent),
00062 m_hotplugModel(0),
00063 m_widget(0),
00064 m_notifierView(0),
00065 m_label(0),
00066 m_notifier(notifier),
00067 m_rootItem(0)
00068 {
00069 m_hotplugModel = new QStandardItemModel(this);
00070 buildDialog();
00071
00072 m_rootItem = m_hotplugModel->invisibleRootItem();
00073 }
00074
00075 NotifierDialog::~NotifierDialog()
00076 {
00077
00078 }
00079
00080 QWidget * NotifierDialog::dialog()
00081 {
00082 return m_widget;
00083 }
00084
00085 void NotifierDialog::hide()
00086 {
00087 m_widget->hide();
00088 }
00089
00090 void NotifierDialog::show()
00091 {
00092 m_widget->show();
00093 }
00094
00095 QStandardItem* NotifierDialog::searchOrCreateDeviceCategory(const QString &categoryName)
00096 {
00097 int rowCount = m_hotplugModel->rowCount();
00098 if(rowCount > 0)
00099 {
00100 int i = 0;
00101 while (i<rowCount)
00102 {
00103 QModelIndex index = m_hotplugModel->index(i, 0);
00104 QString itemUdi = m_hotplugModel->data(index, SolidUdiRole).toString();
00105 QStandardItem *currentItem = m_hotplugModel->itemFromIndex(index);
00106 if(currentItem)
00107 {
00108 QString currentItemName = currentItem->text();
00109 if (currentItemName == categoryName)
00110 {
00111
00112 return m_hotplugModel->itemFromIndex(index);
00113 }
00114 }
00115 i++;
00116 }
00117 }
00118
00119 QStandardItem *newCategory = new QStandardItem(QString(categoryName));
00120 m_hotplugModel->setData(newCategory->index(),categoryName,Qt::DisplayRole);
00121 m_rootItem->insertRow(0,newCategory);
00122 m_hotplugModel->setItem(0, 1, NULL);
00123 m_hotplugModel->setHeaderData(0, Qt::Horizontal,QString(""),Qt::EditRole);
00124 m_hotplugModel->setHeaderData(1, Qt::Horizontal,QString(""),Qt::EditRole);
00125 return newCategory;
00126 }
00127
00128 void NotifierDialog::insertDevice(const QString &name)
00129 {
00130 QStandardItem *item = new QStandardItem();
00131 item->setData(name, SolidUdiRole);
00132 item->setData(Plasma::Delegate::MainColumn, ScopeRole);
00133 item->setData(false, SubTitleMandatoryRole);
00134
00135 QStandardItem *actionItem = new QStandardItem();
00136 actionItem->setData(name, SolidUdiRole);
00137 actionItem->setData(Plasma::Delegate::SecondaryActionColumn, ScopeRole);
00138
00139
00140 QString udi = item->data(SolidUdiRole).toString();
00141 if(!udi.isNull()) {
00142 Solid::Device device(udi);
00143 QString categoryOfInsertedDevice = getCategoryNameOfDevice(device);
00144 QStandardItem *currentCategory = searchOrCreateDeviceCategory(categoryOfInsertedDevice);
00145 if(currentCategory)
00146 {
00147 currentCategory->insertRow(0,item);
00148 currentCategory->setChild(0, 1, actionItem);
00149 }
00150 else
00151 {
00152 delete item;
00153 delete actionItem;
00154 }
00155 }
00156 else
00157 {
00158 delete item;
00159 delete actionItem;
00160 }
00161
00162 m_notifierView->calculateRects();
00163 }
00164
00165 void NotifierDialog::setUnMount(bool unmount, const QString &name)
00166 {
00167 QModelIndex index = indexForUdi(name);
00168 if (!index.isValid()) {
00169 return;
00170 }
00171 QStandardItem *currentItem = m_hotplugModel->itemFromIndex(index);
00172 QStandardItem *childAction = currentItem->parent()->child(currentItem->row(), 1);
00173 QVariant icon;
00174 if (unmount) {
00175 icon = KIcon("media-eject");
00176 }
00177 else {
00178 icon = KIcon();
00179 }
00180 m_hotplugModel->setData(childAction->index(),icon,Qt::DecorationRole);
00181 }
00182
00183 void NotifierDialog::setDeviceData(const QString &name, QVariant data, int role)
00184 {
00185 QModelIndex index = indexForUdi(name);
00186 if (!index.isValid()) {
00187 return;
00188 }
00189 if (role == Qt::DecorationRole) {
00190 QStandardItem *device = m_hotplugModel->itemFromIndex(index);
00191 QStandardItem *category = device->parent();
00192 QModelIndex parentIndex = category->index();
00193 if (!parentIndex.data(Qt::DecorationRole).isValid()) {
00194 m_hotplugModel->setData(parentIndex,data,role);
00195 }
00196 }
00197 m_hotplugModel->setData(index,data,role);
00198 }
00199
00200 QVariant NotifierDialog::getDeviceData(const QString &name, int role)
00201 {
00202 QModelIndex index = indexForUdi(name);
00203 if (!index.isValid()) {
00204 return QVariant();
00205 }
00206 else {
00207 return index.data(role);
00208 }
00209 }
00210
00211 void NotifierDialog::removeDevice(const QString &name)
00212 {
00213 QModelIndex index = indexForUdi(name);
00214 if (!index.isValid()) {
00215 return;
00216 }
00217
00218 QStandardItem *device = m_hotplugModel->itemFromIndex(index);
00219 QStandardItem *category = device->parent();
00220
00221
00222 category->removeRow(device->row());
00223
00224
00225 if (!category->hasChildren()) {
00226 m_rootItem->removeRow(category->row());
00227 }
00228
00229 m_notifierView->calculateRects();
00230 }
00231
00232 void NotifierDialog::removeDevice(int index)
00233 {
00234 m_hotplugModel->removeRow(index);
00235 m_notifierView->calculateRects();
00236 }
00237
00238 int NotifierDialog::countDevices()
00239 {
00240 return m_hotplugModel->rowCount();
00241 }
00242
00243 QString NotifierDialog::getDeviceUdi(int index)
00244 {
00245 QModelIndex modelIndex = m_hotplugModel->index(index, 0);
00246 return m_hotplugModel->data(modelIndex, SolidUdiRole).toString();
00247 }
00248
00249 void NotifierDialog::buildDialog()
00250 {
00251 m_widget = new QWidget();
00252
00253 QVBoxLayout *l_layout = new QVBoxLayout(m_widget);
00254 l_layout->setSpacing(0);
00255 l_layout->setMargin(0);
00256
00257 m_label = new QLabel(m_widget);
00258 updateColors();
00259
00260 QLabel *icon = new QLabel(m_widget);
00261 icon->setPixmap(KIcon("emblem-mounted").pixmap(KIconLoader::SizeMedium, KIconLoader::SizeMedium));
00262
00263 QHBoxLayout *l_layout2 = new QHBoxLayout(m_widget);
00264 l_layout2->setSpacing(0);
00265 l_layout2->setMargin(0);
00266
00267 l_layout2->addWidget(icon);
00268 l_layout2->addWidget(m_label);
00269
00270 l_layout2->setAlignment(Qt::AlignCenter);
00271
00272
00273 m_notifierView = new NotifierView(m_widget);
00274 m_notifierView->setModel(m_hotplugModel);
00275 m_notifierView->setMinimumSize(150,300);
00276 m_notifierView->setFocusPolicy(Qt::NoFocus);
00277
00278 Plasma::Delegate *delegate = new Delegate(this);
00279
00280 delegate->setRoleMapping(Plasma::Delegate::SubTitleRole, ActionRole);
00281 delegate->setRoleMapping(Plasma::Delegate::ColumnTypeRole, ScopeRole);
00282 delegate->setRoleMapping(Plasma::Delegate::SubTitleMandatoryRole, SubTitleMandatoryRole);
00283 m_notifierView->setItemDelegate(delegate);
00284
00285 l_layout->addLayout(l_layout2);
00286 l_layout->addWidget(m_notifierView);
00287 m_widget->setLayout(l_layout);
00288
00289 connect(m_notifierView, SIGNAL(clicked(const QModelIndex&)),this,SLOT(slotOnItemClicked(const QModelIndex&)));
00290
00291 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(updateColors()));
00292 }
00293
00294 void NotifierDialog::storageTeardownDone(Solid::ErrorType error, QVariant errorData)
00295 {
00296 if (error && errorData.isValid()) {
00297 KMessageBox::error(0, i18n("Cannot unmount the device.\nOne or more files on this device are open within an application."), QString());
00298 }
00299 else {
00300 m_notifier->changeNotifierIcon("dialog-ok");
00301 m_notifier->update();
00302 QTimer::singleShot(5000, this, SLOT(resetNotifierIcon()));
00303 }
00304
00305
00306 disconnect(sender(), SIGNAL(teardownDone(Solid::ErrorType, QVariant, const QString &)),
00307 this, SLOT(storageTeardownDone(Solid::ErrorType, QVariant)));
00308 }
00309
00310 void NotifierDialog::storageEjectDone(Solid::ErrorType error, QVariant errorData)
00311 {
00312 if (error && errorData.isValid()) {
00313 KMessageBox::error(0, i18n("Cannot eject the disc.\nOne or more files on this disc are open within an application."), QString());
00314 } else {
00315 m_notifier->changeNotifierIcon("dialog-ok");
00316 m_notifier->update();
00317 QTimer::singleShot(2000, this, SLOT(resetNotifierIcon()));
00318 }
00319
00320 disconnect(sender(), SIGNAL(ejectDone(Solid::ErrorType, QVariant, const QString &)),
00321 this, SLOT(storageEjectDone(Solid::ErrorType, QVariant)));
00322 }
00323
00324 QModelIndex NotifierDialog::indexForUdi(const QString &udi) const
00325 {
00326 int rowCount = m_hotplugModel->rowCount();
00327 for (int i=0; i < rowCount; ++i) {
00328 QModelIndex index = m_hotplugModel->index(i, 0);
00329 QStandardItem *currentItem = m_hotplugModel->itemFromIndex(index);
00330 for (int j=0; j < currentItem->rowCount(); ++j) {
00331 QStandardItem *childItem = currentItem->child(j, 0);
00332 QString itemUdi = m_hotplugModel->data(childItem->index(), SolidUdiRole).toString();
00333 if (itemUdi == udi) {
00334 return childItem->index();
00335 }
00336 }
00337 }
00338
00339 kDebug() << "We should not be here!";
00340 return QModelIndex();
00341 }
00342
00343 void NotifierDialog::slotOnItemClicked(const QModelIndex &index)
00344 {
00345 QString udi = QString(m_hotplugModel->data(index, SolidUdiRole).toString());
00346
00347
00348 if (index.data(ScopeRole).toInt() == Plasma::Delegate::SecondaryActionColumn) {
00349 Solid::Device device(udi);
00350
00351 if (device.is<Solid::OpticalDisc>()) {
00352 Solid::OpticalDrive *drive = device.parent().as<Solid::OpticalDrive>();
00353 connect(drive, SIGNAL(ejectDone(Solid::ErrorType, QVariant, const QString &)),
00354 this, SLOT(storageEjectDone(Solid::ErrorType, QVariant)));
00355 drive->eject();
00356 } else if (device.is<Solid::StorageVolume>()) {
00357 Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
00358 if (access && access->isAccessible()) {
00359 connect(access, SIGNAL(teardownDone(Solid::ErrorType, QVariant, const QString &)),this, SLOT(storageTeardownDone(Solid::ErrorType, QVariant)));
00360 access->teardown();
00361 }
00362 }
00363
00364 } else {
00365 QStringList desktopFiles = m_hotplugModel->data(index, PredicateFilesRole).toStringList();
00366
00367 kDebug() << "DeviceNotifier:: call Solid Ui Server with params :" << udi \
00368 << "," << desktopFiles;
00369 QDBusInterface soliduiserver("org.kde.kded", "/modules/soliduiserver", "org.kde.SolidUiServer");
00370 QDBusReply<void> reply = soliduiserver.call("showActionsDialog", udi, desktopFiles);
00371 }
00372 emit itemSelected();
00373 }
00374
00375 QString NotifierDialog::getCategoryNameOfDevice(const Solid::Device& device)
00376 {
00377 int index = Solid::DeviceInterface::staticMetaObject.indexOfEnumerator("Type");
00378 QMetaEnum typeEnum = Solid::DeviceInterface::staticMetaObject.enumerator(index);
00379 for (int i = typeEnum.keyCount() - 1 ; i > 0; i--)
00380 {
00381 Solid::DeviceInterface::Type type = (Solid::DeviceInterface::Type)typeEnum.value(i);
00382 const Solid::DeviceInterface *interface = device.asDeviceInterface(type);
00383 if (interface)
00384 {
00385 return Solid::DeviceInterface::typeToString(type);
00386 }
00387 }
00388 return 0;
00389 }
00390
00391 void NotifierDialog::resetNotifierIcon()
00392 {
00393 m_notifier->changeNotifierIcon();
00394 m_notifier->update();
00395 }
00396
00397 void NotifierDialog::updateColors()
00398 {
00399 KColorScheme colorTheme = KColorScheme(QPalette::Active, KColorScheme::View,Plasma::Theme::defaultTheme()->colorScheme());
00400 m_label->setText(i18n("<font color=\"%1\">Devices recently plugged in:</font>",colorTheme.foreground(KColorScheme::NormalText).color().name()));
00401
00402 QPalette p = m_widget->palette();
00403 p.setColor(QPalette::Window, Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor));
00404 m_widget->setPalette(p);
00405 }
00406
00407 #include "notifierdialog.moc"