/*************************************************************************** * Copyright 2007 by Marco Martin * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "trash.h" // Katie #include #include // KDE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //Solid #include #include #include #include #include #include #include Trash::Trash(QObject *parent, const QVariantList &args) : Plasma::Applet(parent, args), m_icon(0), m_dirLister(0), m_emptyAction(0), m_count(0), m_showText(false), m_places(0), m_proxy(0) { setHasConfigurationInterface(true); setAspectRatioMode(Plasma::ConstrainedSquare); m_icon = new Plasma::IconWidget(KIcon("user-trash"),QString(),this); m_icon->setNumDisplayLines(2); m_icon->setDrawBackground(true); setBackgroundHints(NoBackground); resize(m_icon->sizeFromIconSize(IconSize(KIconLoader::Desktop))); createMenu(); } Trash::~Trash() { delete m_dirLister; } void Trash::init() { Plasma::Applet::init(); QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addItem(m_icon); setAcceptDrops(true); installSceneEventFilter(m_icon); m_dirLister = new KDirLister(); connect(m_dirLister, SIGNAL(clear()), this, SLOT(clear())); connect(m_dirLister, SIGNAL(completed()), this, SLOT(completed())); connect(m_dirLister, SIGNAL(itemsDeleted(KFileItemList)), this, SLOT(itemsDeleted(KFileItemList))); m_dirLister->openUrl(KUrl("trash:/")); connect(m_icon, SIGNAL(activated()), this, SLOT(open())); connect( KGlobalSettings::self(), SIGNAL(iconChanged(int)), this, SLOT(iconSizeChanged(int)) ); } void Trash::createConfigurationInterface(KConfigDialog *parent) { m_proxy = new KCModuleProxy("kcmtrash"); parent->addPage(m_proxy, i18n("Trash"), icon()); connect(parent, SIGNAL(okClicked()), this, SLOT(applyConfig())); m_proxy->load(); } void Trash::createMenu() { QAction* open = new QAction(SmallIcon("document-open"), i18n("&Open"), this); actions.append(open); connect(open, SIGNAL(triggered(bool)), this , SLOT(open())); m_emptyAction = new QAction(SmallIcon("trash-empty"), i18n("&Empty Trashcan"), this); actions.append(m_emptyAction); connect(m_emptyAction, SIGNAL(triggered(bool)), this, SLOT(empty())); m_menu.addTitle(i18n("Trash")); m_menu.addAction(open); m_menu.addAction(m_emptyAction); //add the menu as an action icon QAction* menu = new QAction(SmallIcon("arrow-up-double"),i18n("&Menu"), this); connect(menu, SIGNAL(triggered(bool)), this , SLOT(popup())); m_icon->addIconAction(menu); connect(&m_menu, SIGNAL(aboutToHide()), m_icon, SLOT(setUnpressed())); } void Trash::popup() { if (m_menu.isVisible()) { m_menu.hide(); return; } m_menu.popup(popupPosition(m_menu.sizeHint())); m_icon->setPressed(); } void Trash::constraintsEvent(Plasma::Constraints constraints) { if (constraints & Plasma::FormFactorConstraint) { disconnect(m_icon, SIGNAL(activated()), this, SLOT(open())); disconnect(m_icon, SIGNAL(clicked()), this, SLOT(open())); if (formFactor() == Plasma::Planar || formFactor() == Plasma::MediaCenter) { connect(m_icon, SIGNAL(activated()), this, SLOT(open())); m_icon->setText(i18n("Trash")); m_icon->setInfoText(i18np("One item", "%1 items", m_count)); m_showText = true; m_icon->setDrawBackground(true); //Adding an arbitrary width to make room for a larger count of items setMinimumSize(m_icon->sizeFromIconSize(IconSize(KIconLoader::Desktop))+=QSizeF(20,0)); } else { //in a panel the icon always behaves like a button connect(m_icon, SIGNAL(clicked()), this, SLOT(open())); m_icon->setText(QString()); m_icon->setInfoText(QString()); m_showText = false; m_icon->setDrawBackground(false); setMinimumSize(m_icon->sizeFromIconSize(IconSize(KIconLoader::Small))); } updateIcon(); } } void Trash::open() { KToolInvocation::self()->startServiceForUrl(QString::fromLatin1("trash:/")); } void Trash::empty() { m_emptyAction->setEnabled(false); m_emptyAction->setText(i18n("Emptying Trashcan...")); KonqOperations::emptyTrash(&m_menu); m_emptyAction->setText(i18n("&Empty Trashcan")); } void Trash::updateIcon() { Plasma::ToolTipContent data; data.setMainText(i18n("Trash")); if (m_count > 0) { m_icon->setIcon("user-trash-full"); data.setSubText(i18np("One item", "%1 items", m_count)); if (m_showText) { m_icon->setInfoText(i18np("One item", "%1 items", m_count)); } } else { m_icon->setIcon("user-trash"); data.setSubText(i18nc("The trash is empty. This is not an action, but a state", "Empty")); if (m_showText) { m_icon->setInfoText(i18nc("The trash is empty. This is not an action, but a state", "Empty")); } } m_icon->update(); data.setImage(m_icon->icon().pixmap(IconSize(KIconLoader::Desktop))); if (!m_showText) { Plasma::ToolTipManager::self()->setContent(this, data); } else { Plasma::ToolTipManager::self()->clearContent(this); } m_emptyAction->setEnabled(m_count > 0); } void Trash::clear() { m_count = 0; updateIcon(); } void Trash::completed() { m_count = m_dirLister->items(KDirLister::AllItems).count(); updateIcon(); } void Trash::itemsDeleted(const KFileItemList &items) { Q_UNUSED(items); m_count--; updateIcon(); } void Trash::applyConfig() { m_proxy->save(); } QList Trash::contextualActions() { return actions; } void Trash::dragEnterEvent(QGraphicsSceneDragDropEvent *event) { if (KUrl::List::canDecode(event->mimeData())) { const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); if (urls.count() == 1) { if (!m_places) { m_places = new KFilePlacesModel(this); } KUrl url = urls.at(0); const Solid::Predicate predicate(Solid::DeviceInterface::StorageAccess, "filePath", url.path()); //query for mounted devices const QList devList = Solid::Device::listFromQuery(predicate, QString()); //seek for an item in the places (e.g. Dolphin sidebar) const QModelIndex index = m_places->closestItem(url); if (!devList.isEmpty()) { m_icon->setIcon("arrow-up-double"); } else if (m_places->bookmarkForIndex(index).url() == url) { m_icon->setIcon("edit-delete"); } } } } void Trash::dragLeaveEvent(QGraphicsSceneDragDropEvent *) { updateIcon(); } void Trash::dropEvent(QGraphicsSceneDragDropEvent *event) { if (KUrl::List::canDecode(event->mimeData())) { const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); if (!urls.isEmpty()) { event->accept(); //some special operation was done instead of simply deleting a file bool specialOperation = false; if (!m_places) { m_places = new KFilePlacesModel(this); } foreach (const KUrl& url, urls) { const Solid::Predicate predicate(Solid::DeviceInterface::StorageAccess, "filePath", url.path()); //query for mounted devices const QList devList = Solid::Device::listFromQuery(predicate, QString()); //seek for an item in the places (e.g. Dolphin sidebar) const QModelIndex index = m_places->closestItem(url); if (!devList.isEmpty()) { //Assuming a mountpoint has a single device Solid::Device device = devList.first(); if (device.is()) { device.as()->eject(); } else { device.as()->teardown(); } specialOperation = true; //hide if there is exactly that item in the places model } else if (m_places->bookmarkForIndex(index).url() == url) { m_places->removePlace(index); specialOperation = true; } } if (specialOperation) { updateIcon(); //finally, try to trash a file }else{ KIO::Job* job = KIO::trash(urls); job->ui()->setWindow(0); job->ui()->setAutoErrorHandlingEnabled(true); } } } } QSizeF Trash::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const { if (which == Qt::PreferredSize) { int iconSize = 0; switch (formFactor()) { case Plasma::Planar: case Plasma::MediaCenter: iconSize = IconSize(KIconLoader::Desktop); break; case Plasma::Horizontal: case Plasma::Vertical: iconSize = IconSize(KIconLoader::Panel); break; } return QSizeF(iconSize, iconSize); } return Plasma::Applet::sizeHint(which, constraint); } void Trash::iconSizeChanged(int group) { if (group == KIconLoader::Desktop || group == KIconLoader::Panel) { updateGeometry(); } } #include "moc_trash.cpp"