00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "trash.h"
00021
00022
00023 #include <QGraphicsSceneDragDropEvent>
00024 #include <QDesktopWidget>
00025 #include <QApplication>
00026 #include <QGraphicsLinearLayout>
00027
00028
00029 #include <KGlobalSettings>
00030 #include <KDebug>
00031 #include <KLocale>
00032 #include <KIconLoader>
00033 #include <KMimeType>
00034 #include <KRun>
00035 #include <KSharedConfig>
00036 #include <KMessageBox>
00037 #include <KUrl>
00038 #include <KProcess>
00039 #include <KStandardDirs>
00040
00041 #include <kfileplacesmodel.h>
00042 #include <KIO/CopyJob>
00043 #include <KIO/JobUiDelegate>
00044
00045
00046 #include <plasma/widgets/icon.h>
00047 #include <plasma/containment.h>
00048
00049
00050 #include <solid/devicenotifier.h>
00051 #include <solid/device.h>
00052 #include <solid/deviceinterface.h>
00053 #include <solid/predicate.h>
00054 #include <solid/storageaccess.h>
00055 #include <solid/opticaldrive.h>
00056 #include <solid/opticaldisc.h>
00057
00058
00059 Trash::Trash(QObject *parent, const QVariantList &args)
00060 : Plasma::Applet(parent, args),
00061 m_icon(0),
00062 m_trashUrl(KUrl("trash:/")),
00063 m_count(0)
00064 {
00065 setAspectRatioMode(Plasma::ConstrainedSquare);
00066 setBackgroundHints(NoBackground);
00067 m_icon = new Plasma::Icon(KIcon("user-trash"),QString(),this);
00068 m_icon->setNumDisplayLines(2);
00069 m_icon->setDrawBackground(true);
00070 QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this);
00071 layout->setContentsMargins(0, 0, 0, 0);
00072 layout->setSpacing(0);
00073
00074 layout->addItem(m_icon);
00075
00076 resize(m_icon->sizeFromIconSize(IconSize(KIconLoader::Desktop)));
00077 }
00078
00079 Trash::~Trash()
00080 {
00081 }
00082
00083 void Trash::init()
00084 {
00085 m_places = new KFilePlacesModel(this);
00086
00087 createMenu();
00088
00089 setAcceptDrops(true);
00090
00091 m_dirLister = new KDirLister();
00092 connect( m_dirLister, SIGNAL( clear() ),
00093 this, SLOT( slotClear() ) );
00094 connect( m_dirLister, SIGNAL( completed() ),
00095 this, SLOT( slotCompleted() ) );
00096 connect( m_dirLister, SIGNAL( deleteItem( const KFileItem & ) ),
00097 this, SLOT( slotDeleteItem( const KFileItem & ) ) );
00098
00099 m_dirLister->openUrl(m_trashUrl);
00100
00101 registerAsDragHandle(m_icon);
00102
00103
00104
00105
00106
00107 connect(m_icon, SIGNAL(activated()), this, SLOT(slotOpen()));
00108 connect(&m_menu, SIGNAL(aboutToHide()),
00109 m_icon, SLOT(setUnpressed()));
00110 }
00111
00112 void Trash::createMenu()
00113 {
00114 QAction* open = new QAction(SmallIcon("document-open"),i18n("&Open"), this);
00115 actions.append(open);
00116 connect(open, SIGNAL(triggered(bool)), this , SLOT(slotOpen()));
00117
00118 emptyTrash = new QAction(SmallIcon("trash-empty"),i18n("&Empty Trashcan"), this);
00119 actions.append(emptyTrash);
00120 connect(emptyTrash, SIGNAL(triggered(bool)), this , SLOT(slotEmpty()));
00121
00122 m_menu.addTitle(i18n("Trash"));
00123 m_menu.addAction(open);
00124 m_menu.addAction(emptyTrash);
00125
00126
00127 QAction* menu = new QAction(SmallIcon("arrow-up-double"),i18n("&Menu"), this);
00128 connect(menu, SIGNAL(triggered(bool)), this , SLOT(popup()));
00129 m_icon->addIconAction(menu);
00130 }
00131
00132 void Trash::popup()
00133 {
00134 if (m_menu.isVisible()) {
00135 m_menu.hide();
00136 return;
00137 }
00138 m_menu.popup(popupPosition(m_menu.sizeHint()));
00139 m_icon->setPressed();
00140 }
00141
00142 void Trash::constraintsEvent(Plasma::Constraints constraints)
00143 {
00144 setBackgroundHints(NoBackground);
00145
00146 if (constraints & Plasma::FormFactorConstraint) {
00147 disconnect(m_icon, SIGNAL(activated()), this, SLOT(slotOpen()));
00148 disconnect(m_icon, SIGNAL(clicked()), this, SLOT(slotOpen()));
00149 if (formFactor() == Plasma::Planar ||
00150 formFactor() == Plasma::MediaCenter) {
00151
00152 connect(m_icon, SIGNAL(activated()), this, SLOT(slotOpen()));
00153
00154 m_icon->setText(i18n("Trash"));
00155 m_icon->setInfoText(i18np("One item", "%1 items", m_count));
00156 m_showText = true;
00157 m_icon->setDrawBackground(true);
00158
00159 setMinimumSize(m_icon->sizeFromIconSize(IconSize(KIconLoader::Desktop))+=QSizeF(20,0));
00160 } else {
00161
00162 connect(m_icon, SIGNAL(clicked()), this, SLOT(slotOpen()));
00163
00164 m_icon->setText(0);
00165 m_icon->setInfoText(0);
00166 m_showText = false;
00167 m_icon->setDrawBackground(false);
00168
00169 setMinimumSize(m_icon->sizeFromIconSize(IconSize(KIconLoader::Small)));
00170 }
00171 setIcon();
00172 }
00173 }
00174
00175 void Trash::slotOpen()
00176 {
00177 emit releaseVisualFocus();
00178 KRun::runUrl(m_trashUrl, "inode/directory", 0);
00179 }
00180
00181 void Trash::slotEmpty()
00182 {
00183 emit releaseVisualFocus();
00184 const QString text(i18nc("@info", "Do you really want to empty the trash? All items will be deleted."));
00185 const bool del = KMessageBox::warningContinueCancel(&m_menu,
00186 text,
00187 QString(),
00188 KGuiItem(i18nc("@action:button", "Empty Trash"),
00189 KIcon("user-trash"))
00190 ) == KMessageBox::Continue;
00191 if (del) {
00192
00193
00194
00195 KProcess process;
00196 process << KStandardDirs::findExe("ktrash") << "--empty";
00197 process.execute();
00198
00199 }
00200 }
00201
00202 void Trash::setIcon()
00203 {
00204 if (m_count > 0) {
00205 m_icon->setIcon(KIcon("user-trash-full"));
00206
00207
00208 if (m_showText) {
00209 m_icon->setInfoText(i18np("One item", "%1 items", m_count));
00210 }
00211 } else {
00212 m_icon->setIcon(KIcon("user-trash"));
00213
00214
00215 if (m_showText){
00216 m_icon->setInfoText(i18nc("The trash is empty. This is not an action, but a state", "Empty"));
00217 }
00218 }
00219
00220 m_icon->update();
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 emptyTrash->setEnabled(m_count>0);
00232 }
00233
00234 void Trash::slotClear()
00235 {
00236 m_count = 0;
00237 setIcon();
00238 }
00239
00240 void Trash::slotCompleted()
00241 {
00242 m_count = m_dirLister->items(KDirLister::AllItems).count();
00243 setIcon();
00244 }
00245
00246 void Trash::slotDeleteItem(const KFileItem &)
00247 {
00248 m_count--;
00249 setIcon();
00250 }
00251
00252 QList<QAction*> Trash::contextualActions()
00253 {
00254 return actions;
00255 }
00256
00257 void Trash::dropEvent(QGraphicsSceneDragDropEvent *event)
00258 {
00259 if (KUrl::List::canDecode(event->mimeData())) {
00260 const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
00261 if (urls.count() > 0) {
00262 event->accept();
00263
00264
00265 bool specialOperation = false;
00266
00267 foreach (const KUrl& url, urls) {
00268 const Solid::Predicate predicate(Solid::DeviceInterface::StorageAccess, "filePath", url.path());
00269
00270
00271 const QList<Solid::Device> devList = Solid::Device::listFromQuery(predicate, QString());
00272
00273
00274
00275 const QModelIndex index = m_places->closestItem(url);
00276
00277 if (devList.count() > 0) {
00278
00279 Solid::Device device = devList.first();
00280
00281 if (device.is<Solid::OpticalDisc>()) {
00282 device.parent().as<Solid::OpticalDrive>()->eject();
00283 } else {
00284 device.as<Solid::StorageAccess>()->teardown();
00285 }
00286
00287 specialOperation = true;
00288
00289 } else if (m_places->bookmarkForIndex(index).url() == url) {
00290 m_places->removePlace(index);
00291 specialOperation = true;
00292 }
00293 }
00294
00295
00296 if (!specialOperation) {
00297 KIO::Job* job = KIO::trash(urls);
00298 job->ui()->setWindow(0);
00299 job->ui()->setAutoErrorHandlingEnabled(true);
00300 }
00301
00302 }
00303 }
00304
00305 }
00306
00307 #include "trash.moc"
00308