[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdebase/apps/plasma/applets/folderview
From:       Fredrik Höglund <fredrik () kde ! org>
Date:       2008-06-08 23:49:26
Message-ID: 1212968966.937818.17813.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 818609 by fredrik:

Add the context menu for the icons in the folder view, and add
the "Create New", "Undo" and "Paste" actions to the applet's
context menu.

CCBUG: 155057
BUG: 163043


 M  +1 -1      CMakeLists.txt  
 M  +310 -11   folderview.cpp  
 M  +23 -1     folderview.h  


--- trunk/KDE/kdebase/apps/plasma/applets/folderview/CMakeLists.txt #818608:818609
@@ -6,7 +6,7 @@
 
 kde4_add_ui_files(folderview_SRCS folderviewConfig.ui)
 kde4_add_plugin(plasma_applet_folderview ${folderview_SRCS})
-target_link_libraries(plasma_applet_folderview plasma ${KDE4_KIO_LIBS})
+target_link_libraries(plasma_applet_folderview plasma konq ${KDE4_KIO_LIBS})
 
 install(TARGETS plasma_applet_folderview DESTINATION ${PLUGIN_INSTALL_DIR})
 install(FILES plasma-applet-folderview.desktop DESTINATION ${SERVICES_INSTALL_DIR})
--- trunk/KDE/kdebase/apps/plasma/applets/folderview/folderview.cpp #818608:818609
@@ -21,26 +21,42 @@
 #include "folderview.moc"
 
 #include <QApplication>
+#include <QClipboard>
 #include <QDebug>
 #include <QDrag>
+#include <QGraphicsView>
 #include <QGraphicsSceneHoverEvent>
 #include <QGraphicsSceneMouseEvent>
 #include <QItemSelectionModel>
 #include <QPainter>
 #include <QStyleOptionGraphicsItem>
 
+#include <KAction>
+#include <KAuthorized>
+#include <KBookmarkManager>
 #include <KConfigDialog>
 #include <KDirLister>
 #include <KDirModel>
 #include <KFileItemDelegate>
 #include <KGlobalSettings>
+#include <KMenu>
+#include <KStandardShortcut>
 
+#include <kio/fileundomanager.h>
+#include <kio/paste.h>
+#include <KParts/BrowserExtension>
+
+#include <knewmenu.h>
+#include <konqmimedata.h>
+#include <konq_operations.h>
+#include <konq_popupmenu.h>
+
 #include "proxymodel.h"
 #include "plasma/theme.h"
 
 
 FolderView::FolderView(QObject *parent, const QVariantList &args)
-    : Plasma::Applet(parent, args)
+    : Plasma::Applet(parent, args), m_actionCollection(this)
 {
     setAspectRatioMode(Plasma::IgnoreAspectRatio);
     setHasConfigurationInterface(true);
@@ -65,6 +81,7 @@
     m_delegate = new KFileItemDelegate(this);
     m_selectionModel = new QItemSelectionModel(m_model, this);
 
+    m_newMenu = 0;
     m_layoutValid = false;
     m_doubleClick = false;
     m_dragInProgress = false;
@@ -94,10 +111,13 @@
     m_model->setFilterFixedString(m_filterFiles);
 
     m_dirModel->setDirLister(lister);
+
+    connect(QApplication::clipboard(), SIGNAL(dataChanged()), SLOT(clipboardDataChanged()));
 }
 
 FolderView::~FolderView()
 {
+    delete m_newMenu;
 }
 
 void FolderView::createConfigurationInterface(KConfigDialog *parent)
@@ -193,6 +213,29 @@
     update();
 }
 
+void FolderView::clipboardDataChanged()
+{
+    const QMimeData *mimeData = QApplication::clipboard()->mimeData();
+    if (KonqMimeData::decodeIsCutSelection(mimeData)) {
+        KUrl::List urls = KUrl::List::fromMimeData(mimeData);
+
+        // TODO Mark the cut icons as cut
+    }
+
+    // Update the paste action
+    if (QAction *action = m_actionCollection.action("paste"))
+    {
+        const QString actionText = KIO::pasteActionText();
+        if (!actionText.isEmpty()) {
+            action->setText(actionText);
+            action->setEnabled(true);
+        } else {
+            action->setText(i18n("&Paste"));
+            action->setEnabled(false);
+        }
+    }
+}
+
 int FolderView::columnsForWidth(qreal width) const
 {
     int spacing = 10;
@@ -334,6 +377,245 @@
     }
 }
 
+void FolderView::createActions()
+{
+    KIO::FileUndoManager *manager = KIO::FileUndoManager::self();
+
+    // Remove the Shift+Delete shortcut from the cut action, since it's used for deleting files
+    KAction *cut = KStandardAction::cut(this, SLOT(cut()), this);
+    KShortcut cutShortCut = cut->shortcut();
+    cutShortCut.remove(Qt::SHIFT + Qt::Key_Delete);
+    cut->setShortcut(cutShortCut);
+
+    KAction *copy = KStandardAction::copy(this, SLOT(copy()), this);
+
+    KAction *undo = KStandardAction::undo(manager, SLOT(undo()), this);
+    connect(manager, SIGNAL(undoAvailable(bool)), undo, SLOT(setEnabled(bool)));
+    connect(manager, SIGNAL(undoTextChanged(QString)), SLOT(undoTextChanged(QString)));
+    undo->setEnabled(manager->undoAvailable());
+
+    KAction *paste = KStandardAction::paste(this, SLOT(paste()), this);
+    KAction *pasteTo = KStandardAction::paste(this, SLOT(pasteTo()), this);
+    pasteTo->setEnabled(false); // Only enabled during popupMenu()
+
+    QString actionText = KIO::pasteActionText();
+    if (!actionText.isEmpty()) {
+       paste->setText(actionText);
+    } else {
+       paste->setEnabled(false);
+    }
+
+    KAction *reload  = new KAction(i18n("&Reload"), this);
+    reload->setShortcut(KStandardShortcut::reload());
+    connect(reload, SIGNAL(triggered()), SLOT(refreshIcons()));
+
+    KAction *rename = new KAction(KIcon("edit-rename"), i18n("&Rename"), this);
+    rename->setShortcut(Qt::Key_F2);
+    connect(rename, SIGNAL(triggered()), SLOT(renameSelectedIcon()));
+
+    KAction *trash = new KAction(KIcon("user-trash"), i18n("&Move to Trash"), this);
+    trash->setShortcut(Qt::Key_Delete);
+    connect(trash, SIGNAL(triggered(Qt::MouseButtons, Qt::KeyboardModifiers)),
+            SLOT(moveToTrash(Qt::MouseButtons, Qt::KeyboardModifiers)));
+
+    KAction *del = new KAction(i18n("&Delete"), this);
+    del->setShortcut(Qt::SHIFT + Qt::Key_Delete);
+    connect(del, SIGNAL(triggered()), SLOT(deleteSelectedIcons()));
+
+    m_actionCollection.addAction("cut", cut);
+    m_actionCollection.addAction("undo", undo);
+    m_actionCollection.addAction("copy", copy);
+    m_actionCollection.addAction("paste", paste);
+    m_actionCollection.addAction("pasteto", pasteTo);
+    m_actionCollection.addAction("reload", reload);
+    m_actionCollection.addAction("rename", rename);
+    m_actionCollection.addAction("trash", trash);
+    m_actionCollection.addAction("del", del);
+
+    // Create the new menu
+    if (KAuthorized::authorize("editable_desktop_icons")) {
+        m_newMenu = new KNewMenu(&m_actionCollection, view(), "new_menu");
+        connect(m_newMenu->menu(), SIGNAL(aboutToShow()), this, SLOT(aboutToShowCreateNew()));
+    }
+
+    // Note: We have to create our own action collection, because the one Plasma::Applet
+    //       provides can only be manipulated indirectly, and we need to be able to pass
+    //       a pointer to the collection to KNewMenu and KonqPopupMenu.
+    //       But we still have to add all the actions to the collection in Plasma::Applet
+    //       in order for the shortcuts to work.
+    addAction("cut", cut);
+    addAction("undo", undo);
+    addAction("copy", copy);
+    addAction("paste", paste);
+    addAction("reload", reload);
+    addAction("rename", rename);
+    addAction("trash", trash);
+    addAction("del", del);
+}
+
+QList<QAction*> FolderView::contextualActions()
+{
+    QList<QAction*> actions;
+
+    if (KAuthorized::authorize("action/kdesktop_rmb"))
+    {
+        if (m_actionCollection.isEmpty()) {
+            createActions();
+        }
+
+        if (QAction *action = m_actionCollection.action("new_menu")) {
+            actions.append(action);
+            QAction *separator = new QAction(this);
+            separator->setSeparator(true);
+            actions.append(separator);
+        }
+
+        actions.append(m_actionCollection.action("undo"));
+        actions.append(m_actionCollection.action("paste"));
+
+        QAction *separator = new QAction(this);
+        separator->setSeparator(true);
+        actions.append(separator);
+    }
+
+    return actions;
+}
+
+void FolderView::aboutToShowCreateNew()
+{
+    if (m_newMenu) {
+        m_newMenu->slotCheckUpToDate();
+        m_newMenu->setPopupFiles(m_url);
+    }
+}
+
+KUrl::List FolderView::selectedUrls() const
+{
+    KUrl::List urls;
+    foreach (const QModelIndex &index, m_selectionModel->selectedIndexes())
+    {
+        KFileItem item = m_model->itemForIndex(index);
+        // Prefer the local URL if there is one, since we can't trash remote URL's
+        const QString path = item.localPath();
+        if (!path.isEmpty()) {
+            urls.append(path);
+        } else {
+            urls.append(item.url());
+        }
+    }
+    return urls;
+}
+
+void FolderView::copy()
+{
+    QMimeData *mimeData = new QMimeData;
+    KonqMimeData::populateMimeData(mimeData, selectedUrls(), KUrl::List(), false);
+    QApplication::clipboard()->setMimeData(mimeData);
+}
+
+void FolderView::cut()
+{
+    QMimeData *mimeData = new QMimeData;
+    KonqMimeData::populateMimeData(mimeData, selectedUrls(), KUrl::List(), true);
+    QApplication::clipboard()->setMimeData(mimeData);
+}
+
+void FolderView::paste()
+{
+    KonqOperations::doPaste(view(), m_url);
+}
+
+void FolderView::pasteTo()
+{
+    KUrl::List urls = selectedUrls();
+    Q_ASSERT(urls.count() == 1);
+    KonqOperations::doPaste(view(), urls.first());
+}
+
+void FolderView::refreshIcons()
+{
+    // TODO Implement me!
+}
+
+void FolderView::renameSelectedIcon()
+{
+    // TODO Implement me!
+}
+
+void FolderView::moveToTrash(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+{
+    Q_UNUSED(buttons)    
+
+    KonqOperations::Operation op = (modifiers & Qt::ShiftModifier) ?
+            KonqOperations::DEL : KonqOperations::TRASH;
+
+    KonqOperations::del(view(), op, selectedUrls());
+}
+
+void FolderView::deleteSelectedIcons()
+{
+    KonqOperations::del(view(), KonqOperations::DEL, selectedUrls());
+}
+
+void FolderView::undoTextChanged(const QString &text)
+{
+    if (QAction *action = m_actionCollection.action("undo")) {
+        action->setText(text);
+    }
+}
+
+void FolderView::showContextMenu(QWidget *widget, const QPoint &pos, const QModelIndexList &indexes)
+{
+    if (!KAuthorized::authorize("action/kdesktop_rmb")) {
+        return;
+    }
+
+    if (m_actionCollection.isEmpty()) {
+        createActions();
+    }
+
+    KFileItemList items;
+    bool hasRemoteFiles = false;
+
+    foreach (const QModelIndex &index, indexes) {
+        KFileItem item = m_model->itemForIndex(index);
+        hasRemoteFiles |= item.localPath().isEmpty();
+        items.append(item);
+    }
+
+    QAction* pasteTo = m_actionCollection.action("pasteto");
+    if (pasteTo) {
+        pasteTo->setEnabled(m_actionCollection.action("paste")->isEnabled());
+        pasteTo->setText(m_actionCollection.action("paste")->text());
+    }
+
+    QList<QAction*> editActions;
+    editActions.append(m_actionCollection.action("rename"));
+    if (!hasRemoteFiles) {
+        editActions.append(m_actionCollection.action("trash"));
+    } else {
+        editActions.append(m_actionCollection.action("del"));
+    }
+
+    KParts::BrowserExtension::ActionGroupMap actionGroups;
+    actionGroups.insert("editactions", editActions);
+
+    KParts::BrowserExtension::PopupFlags flags = 
+         KParts::BrowserExtension::ShowUrlOperations | KParts::BrowserExtension::ShowProperties;
+
+    KonqPopupMenu *contextMenu = new KonqPopupMenu(items, m_url, m_actionCollection, m_newMenu,
+                                                   KonqPopupMenu::ShowNewWindow, flags, widget,
+                                                   KBookmarkManager::userBookmarksManager(),
+                                                   actionGroups);
+
+    contextMenu->exec(pos);
+    delete contextMenu;
+
+    if (pasteTo) {
+        pasteTo->setEnabled(false);
+    }
+}
+
 void FolderView::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
 {
     const QModelIndex index = indexAt(event->pos());
@@ -363,6 +645,28 @@
 
 void FolderView::mousePressEvent(QGraphicsSceneMouseEvent *event)
 {
+    if (!contentsRect().contains(event->pos())) {
+        Plasma::Applet::mousePressEvent(event);
+        return;
+    }
+
+    if (event->button() == Qt::RightButton) {
+        const QModelIndex index = indexAt(event->pos());
+        if (index.isValid()) {
+            if (!m_selectionModel->isSelected(index)) {
+                m_selectionModel->select(index, QItemSelectionModel::ClearAndSelect);
+                m_selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
+                update();
+            }
+            showContextMenu(event->widget(), event->screenPos(), m_selectionModel->selectedIndexes());
+        } else if (m_selectionModel->hasSelection()) {
+            m_selectionModel->clearSelection();
+            update();
+        }
+        event->accept();
+        return;
+    }
+
     if (event->button() == Qt::LeftButton) {
         const QModelIndex index = indexAt(event->pos());
 
@@ -384,19 +688,14 @@
         }
 
         // If empty space was pressed
-        if (contentsRect().contains(event->pos()))
-        {
-            m_pressedIndex = QModelIndex();
-            if (m_selectionModel->hasSelection()) {
-                m_selectionModel->clearSelection();
-                update();
-            }
-            event->accept();
-            return;
+        m_pressedIndex = QModelIndex();
+        if (m_selectionModel->hasSelection()) {
+            m_selectionModel->clearSelection();
+            update();
         }
+        event->accept();
     }
 
-    Plasma::Applet::mousePressEvent(event);
 }
 
 void FolderView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
--- trunk/KDE/kdebase/apps/plasma/applets/folderview/folderview.h #818608:818609
@@ -23,11 +23,14 @@
 #include <QPersistentModelIndex>
 #include <QStyleOption>
 
+#include <KActionCollection>
+
 #include <plasma/applet.h>
 #include "ui_folderviewConfig.h"
 
 class KDirModel;
 class KFileItemDelegate;
+class KNewMenu;
 class QItemSelectionModel;
 class ProxyModel;
 
@@ -50,8 +53,9 @@
 
 protected:
     void createConfigurationInterface(KConfigDialog *parent);
+    QList<QAction*> contextualActions();
 
-private slots:    
+private slots:
     void rowsInserted(const QModelIndex &parent, int first, int last);
     void rowsRemoved(const QModelIndex &parent, int first, int last);
     void modelReset();
@@ -59,8 +63,24 @@
     void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
     void configAccepted();
     void customFolderToggled(bool checked);
+    void aboutToShowCreateNew();
+    void clipboardDataChanged();
 
+    // These slots are for KonqPopupMenu
+    void copy();
+    void cut();
+    void paste();
+    void pasteTo();
+    void refreshIcons();
+    void renameSelectedIcon();
+    void moveToTrash(Qt::MouseButtons, Qt::KeyboardModifiers);
+    void deleteSelectedIcons();
+    void undoTextChanged(const QString &text);
+
 private:
+    void createActions();
+    KUrl::List selectedUrls() const;
+    void showContextMenu(QWidget *widget, const QPoint &pos, const QModelIndexList &indexes);
     int columnsForWidth(qreal width) const;
     void layoutItems() const;
     QModelIndex indexAt(const QPointF &point) const;
@@ -89,6 +109,8 @@
     KUrl m_url;
     QString m_filterFiles;
     QFont m_font;
+    KNewMenu *m_newMenu;
+    KActionCollection m_actionCollection;
     mutable QVector<ViewItem> m_items;
     mutable int m_columns;
     mutable bool m_layoutValid;
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic