diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -211,7 +211,6 @@ panels/places/placesview.cpp panels/panel.cpp panels/folders/foldersitemlistwidget.cpp - panels/folders/treeviewcontextmenu.cpp panels/folders/folderspanel.cpp panels/terminal/terminalpanel.cpp search/dolphinfacetswidget.cpp diff --git a/src/dolphincontextmenu.h b/src/dolphincontextmenu.h --- a/src/dolphincontextmenu.h +++ b/src/dolphincontextmenu.h @@ -70,7 +70,8 @@ DolphinContextMenu(DolphinMainWindow* parent, const QPoint& pos, const KFileItem& fileInfo, - const QUrl& baseUrl); + const QUrl& baseUrl, + const KFileItemList selection); ~DolphinContextMenu() override; diff --git a/src/dolphincontextmenu.cpp b/src/dolphincontextmenu.cpp --- a/src/dolphincontextmenu.cpp +++ b/src/dolphincontextmenu.cpp @@ -57,25 +57,22 @@ DolphinContextMenu::DolphinContextMenu(DolphinMainWindow* parent, const QPoint& pos, const KFileItem& fileInfo, - const QUrl& baseUrl) : + const QUrl& baseUrl, + const KFileItemList selection) : QMenu(parent), m_pos(pos), m_mainWindow(parent), m_fileInfo(fileInfo), m_baseUrl(baseUrl), m_baseFileItem(nullptr), - m_selectedItems(), + m_selectedItems(selection), m_selectedItemsProperties(nullptr), m_context(NoContext), m_copyToMenu(parent), m_customActions(), m_command(None), m_removeAction(nullptr) { - // The context menu either accesses the URLs of the selected items - // or the items itself. To increase the performance both lists are cached. - const DolphinView* view = m_mainWindow->activeViewContainer()->view(); - m_selectedItems = view->selectedItems(); } DolphinContextMenu::~DolphinContextMenu() @@ -302,6 +299,8 @@ addVersionControlPluginActions(); + addCustomActions(); + // insert 'Copy To' and 'Move To' sub menus if (GeneralSettings::showCopyMoveMenu()) { m_copyToMenu.setUrls(m_selectedItems.urlList()); diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h --- a/src/dolphinmainwindow.h +++ b/src/dolphinmainwindow.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -43,8 +44,6 @@ class DolphinViewContainer; class DolphinRemoteEncoding; class DolphinTabWidget; -class KFileItem; -class KFileItemList; class KJob; class KNewFileMenu; class KHelpMenu; @@ -460,6 +459,21 @@ const KFileItem& item, const QUrl& url, const QList& customActions); + /** + * Opens the context menu on the current mouse position. + * @pos Position in screen coordinates. + * @item File item context. If item is null, the context menu + * should be applied to \a url. + * @url URL which contains \a item. + * @selection The items selected + * @customActions Actions that should be added to the context menu, + * if the file item is null. + */ + void openContextMenuWithSelection(const QPoint& pos, + const KFileItem& item, + const QUrl& url, + const QList& customActions, + const KFileItemList& selection); void updateControlMenu(); void updateToolBar(); diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -1090,7 +1091,16 @@ const QUrl& url, const QList& customActions) { - QPointer contextMenu = new DolphinContextMenu(this, pos, item, url); + openContextMenuWithSelection(pos, item, url, customActions, activeViewContainer()->view()->selectedItems()); +} + +void DolphinMainWindow::openContextMenuWithSelection(const QPoint& pos, + const KFileItem& item, + const QUrl& url, + const QList& customActions, + const KFileItemList& selection) +{ + QPointer contextMenu = new DolphinContextMenu(this, pos, item, url, selection); contextMenu.data()->setCustomActions(customActions); const DolphinContextMenu::Command command = contextMenu.data()->open(); @@ -1741,6 +1751,8 @@ this, &DolphinMainWindow::openNewTabAfterCurrentTab); connect(foldersPanel, &FoldersPanel::errorMessage, this, &DolphinMainWindow::showErrorMessage); + connect(foldersPanel, &Panel::requestOpenContextMenu, + this, &DolphinMainWindow::openContextMenuWithSelection); actionCollection()->action(QStringLiteral("show_folders_panel")) ->setWhatsThis(xi18nc("@info:whatsthis", "This toggles the " diff --git a/src/panels/folders/folderspanel.h b/src/panels/folders/folderspanel.h --- a/src/panels/folders/folderspanel.h +++ b/src/panels/folders/folderspanel.h @@ -110,6 +110,8 @@ void updateCurrentItem(int index); private: + QList folderPanelContextMenuActions(); + bool m_updateCurrentItem; KItemListController* m_controller; KFileItemModel* m_model; diff --git a/src/panels/folders/folderspanel.cpp b/src/panels/folders/folderspanel.cpp --- a/src/panels/folders/folderspanel.cpp +++ b/src/panels/folders/folderspanel.cpp @@ -28,15 +28,17 @@ #include "kitemviews/kitemlistcontainer.h" #include "kitemviews/kitemlistcontroller.h" #include "kitemviews/kitemlistselectionmanager.h" -#include "treeviewcontextmenu.h" #include "views/draganddrophelper.h" #include #include #include #include #include #include +#include +#include +#include #include #include @@ -212,23 +214,64 @@ } } +QList FoldersPanel::folderPanelContextMenuActions() +{ + QList actions; + + QAction* showHiddenFilesAction = new QAction(i18nc("@action:inmenu", "Show Hidden Files"), this); + showHiddenFilesAction->setCheckable(true); + showHiddenFilesAction->setChecked(showHiddenFiles()); + actions.append(showHiddenFilesAction); + connect(showHiddenFilesAction, &QAction::toggled, this, &FoldersPanel::setShowHiddenFiles); + + // insert 'Limit to Home Directory' + QAction* limitFoldersPanelToHomeAction = new QAction(i18nc("@action:inmenu", "Limit to Home Directory"), this); + limitFoldersPanelToHomeAction->setCheckable(true); + limitFoldersPanelToHomeAction->setChecked(limitFoldersPanelToHome()); + actions.append(limitFoldersPanelToHomeAction); + connect(limitFoldersPanelToHomeAction, &QAction::toggled, this, &FoldersPanel::setLimitFoldersPanelToHome); + + // TODO: Temporary disabled. Horizontal autoscrolling will be implemented later either + // in KItemViews or manually as part of the FoldersPanel + /* + // insert 'Automatic Scrolling' + QAction* autoScrollingAction = new QAction(i18nc("@action:inmenu", "Automatic Scrolling"), this); + autoScrollingAction->setCheckable(true); + autoScrollingAction->setChecked(autoScrolling()); + connect(autoScrollingAction, &QAction::toggled, this, &FoldersPanel::setAutoScrolling); + actions->addAction(autoScrollingAction); + */ + + const QList customActions = customContextMenuActions(); + if (!customActions.isEmpty()) { + QAction *separatorAction = new QAction(); + separatorAction->setSeparator(true); + actions.append(separatorAction); + for (QAction* action: customActions) { + actions.append(action); + } + } + + return actions; +} + void FoldersPanel::slotItemContextMenuRequested(int index, const QPointF& pos) { const KFileItem fileItem = m_model->fileItem(index); + const KFileItemList list({fileItem}); - QPointer contextMenu = new TreeViewContextMenu(this, fileItem); - contextMenu.data()->open(pos.toPoint()); - if (contextMenu.data()) { - delete contextMenu.data(); - } + requestOpenContextMenu(pos.toPoint(), fileItem, fileItem.url(), folderPanelContextMenuActions(), list); } void FoldersPanel::slotViewContextMenuRequested(const QPointF& pos) { - QPointer contextMenu = new TreeViewContextMenu(this, KFileItem()); - contextMenu.data()->open(pos.toPoint()); - if (contextMenu.data()) { - delete contextMenu.data(); + QMenu* popup = new QMenu(this); + popup->addActions(folderPanelContextMenuActions()); + + QPointer popupPtr = popup; + popup->exec(pos.toPoint()); + if (popupPtr.data()) { + popupPtr.data()->deleteLater(); } } diff --git a/src/panels/folders/treeviewcontextmenu.h b/src/panels/folders/treeviewcontextmenu.h deleted file mode 100644 --- a/src/panels/folders/treeviewcontextmenu.h +++ /dev/null @@ -1,102 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Peter Penz * - * * - * 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 * - ***************************************************************************/ - -#ifndef TREEVIEWCONTEXTMENU_H -#define TREEVIEWCONTEXTMENU_H - -#include - -#include - -class QMimeData; -class FoldersPanel; - -/** - * @brief Represents the context menu which appears when doing a right - * click on an item of the treeview. - */ -class TreeViewContextMenu : public QObject -{ - Q_OBJECT - -public: - /** - * @parent Pointer to the folders panel the context menu - * belongs to. - * @fileInfo Pointer to the file item the context menu - * is applied. If 0 is passed, the context menu - * is above the viewport. - */ - TreeViewContextMenu(FoldersPanel* parent, - const KFileItem& fileInfo); - - ~TreeViewContextMenu() override; - - /** Opens the context menu modal. */ - void open(const QPoint& pos); - -private slots: - /** Cuts the item m_fileItem. */ - void cut(); - - /** Copies the item m_fileItem. */ - void copy(); - - /** Paste the clipboard to m_fileItem. */ - void paste(); - - /** Renames the item m_fileItem. */ - void rename(); - - /** Moves the item m_fileItem to the trash. */ - void moveToTrash(); - - /** Deletes the item m_fileItem. */ - void deleteItem(); - - /** Shows the properties of the item m_fileItem. */ - void showProperties(); - - /** - * Sets the 'Show Hidden Files' setting for the - * folders panel to \a show. - */ - void setShowHiddenFiles(bool show); - - /** - * Sets the 'Limit folders panel to home' setting for the - * folders panel to \a enable. - */ - void setLimitFoldersPanelToHome(bool enable); - - /** - * Sets the 'Automatic Scrolling' setting for the - * folders panel to \a enable. - */ - void setAutoScrolling(bool enable); - -private: - void populateMimeData(QMimeData* mimeData, bool cut); - -private: - FoldersPanel* m_parent; - KFileItem m_fileItem; -}; - -#endif diff --git a/src/panels/folders/treeviewcontextmenu.cpp b/src/panels/folders/treeviewcontextmenu.cpp deleted file mode 100644 --- a/src/panels/folders/treeviewcontextmenu.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006-2010 by Peter Penz * - * Copyright (C) 2006 by Cvetoslav Ludmiloff * - * * - * 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 "treeviewcontextmenu.h" - -#include "folderspanel.h" -#include "global.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -TreeViewContextMenu::TreeViewContextMenu(FoldersPanel* parent, - const KFileItem& fileInfo) : - QObject(parent), - m_parent(parent), - m_fileItem(fileInfo) -{ -} - -TreeViewContextMenu::~TreeViewContextMenu() -{ -} - -void TreeViewContextMenu::open(const QPoint& pos) -{ - QMenu* popup = new QMenu(m_parent); - - if (!m_fileItem.isNull()) { - KFileItemListProperties capabilities(KFileItemList() << m_fileItem); - - // insert 'Cut', 'Copy' and 'Paste' - QAction* cutAction = new QAction(QIcon::fromTheme(QStringLiteral("edit-cut")), i18nc("@action:inmenu", "Cut"), this); - cutAction->setEnabled(capabilities.supportsMoving()); - connect(cutAction, &QAction::triggered, this, &TreeViewContextMenu::cut); - - QAction* copyAction = new QAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18nc("@action:inmenu", "Copy"), this); - connect(copyAction, &QAction::triggered, this, &TreeViewContextMenu::copy); - - const QMimeData *mimeData = QApplication::clipboard()->mimeData(); - bool canPaste; - const QString text = KIO::pasteActionText(mimeData, &canPaste, m_fileItem); - QAction* pasteAction = new QAction(QIcon::fromTheme(QStringLiteral("edit-paste")), text, this); - connect(pasteAction, &QAction::triggered, this, &TreeViewContextMenu::paste); - pasteAction->setEnabled(canPaste); - - popup->addAction(cutAction); - popup->addAction(copyAction); - popup->addAction(pasteAction); - popup->addSeparator(); - - // insert 'Rename' - QAction* renameAction = new QAction(i18nc("@action:inmenu", "Rename..."), this); - renameAction->setEnabled(capabilities.supportsMoving()); - renameAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename"))); - connect(renameAction, &QAction::triggered, this, &TreeViewContextMenu::rename); - popup->addAction(renameAction); - - // insert 'Move to Trash' and (optionally) 'Delete' - KSharedConfig::Ptr globalConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::IncludeGlobals); - KConfigGroup configGroup(globalConfig, "KDE"); - bool showDeleteCommand = configGroup.readEntry("ShowDeleteCommand", false); - - const QUrl url = m_fileItem.url(); - if (url.isLocalFile()) { - QAction* moveToTrashAction = new QAction(QIcon::fromTheme(QStringLiteral("user-trash")), - i18nc("@action:inmenu", "Move to Trash"), this); - const bool enableMoveToTrash = capabilities.isLocal() && capabilities.supportsMoving(); - moveToTrashAction->setEnabled(enableMoveToTrash); - connect(moveToTrashAction, &QAction::triggered, this, &TreeViewContextMenu::moveToTrash); - popup->addAction(moveToTrashAction); - } else { - showDeleteCommand = true; - } - - if (showDeleteCommand) { - QAction* deleteAction = new QAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18nc("@action:inmenu", "Delete"), this); - deleteAction->setEnabled(capabilities.supportsDeleting()); - connect(deleteAction, &QAction::triggered, this, &TreeViewContextMenu::deleteItem); - popup->addAction(deleteAction); - } - - popup->addSeparator(); - } - - // insert 'Show Hidden Files' - QAction* showHiddenFilesAction = new QAction(i18nc("@action:inmenu", "Show Hidden Files"), this); - showHiddenFilesAction->setCheckable(true); - showHiddenFilesAction->setChecked(m_parent->showHiddenFiles()); - popup->addAction(showHiddenFilesAction); - connect(showHiddenFilesAction, &QAction::toggled, this, &TreeViewContextMenu::setShowHiddenFiles); - - if (!m_fileItem.isNull()) { - // insert 'Limit to Home Directory' - const QUrl url = m_fileItem.url(); - const bool enableLimitToHomeDirectory = url.isLocalFile(); - QAction* limitFoldersPanelToHomeAction = new QAction(i18nc("@action:inmenu", "Limit to Home Directory"), this); - limitFoldersPanelToHomeAction->setCheckable(true); - limitFoldersPanelToHomeAction->setEnabled(enableLimitToHomeDirectory); - limitFoldersPanelToHomeAction->setChecked(m_parent->limitFoldersPanelToHome()); - popup->addAction(limitFoldersPanelToHomeAction); - connect(limitFoldersPanelToHomeAction, &QAction::toggled, this, &TreeViewContextMenu::setLimitFoldersPanelToHome); - } - - // insert 'Automatic Scrolling' - QAction* autoScrollingAction = new QAction(i18nc("@action:inmenu", "Automatic Scrolling"), this); - autoScrollingAction->setCheckable(true); - autoScrollingAction->setChecked(m_parent->autoScrolling()); - // TODO: Temporary disabled. Horizontal autoscrolling will be implemented later either - // in KItemViews or manually as part of the FoldersPanel - //popup->addAction(autoScrollingAction); - connect(autoScrollingAction, &QAction::toggled, this, &TreeViewContextMenu::setAutoScrolling); - - if (!m_fileItem.isNull()) { - // insert 'Properties' entry - QAction* propertiesAction = new QAction(i18nc("@action:inmenu", "Properties"), this); - propertiesAction->setIcon(QIcon::fromTheme(QStringLiteral("document-properties"))); - connect(propertiesAction, &QAction::triggered, this, &TreeViewContextMenu::showProperties); - popup->addAction(propertiesAction); - } - - QList customActions = m_parent->customContextMenuActions(); - if (!customActions.isEmpty()) { - popup->addSeparator(); - foreach (QAction* action, customActions) { - popup->addAction(action); - } - } - - QPointer popupPtr = popup; - popup->exec(pos); - if (popupPtr.data()) { - popupPtr.data()->deleteLater(); - } -} - -void TreeViewContextMenu::populateMimeData(QMimeData* mimeData, bool cut) -{ - QList kdeUrls; - kdeUrls.append(m_fileItem.url()); - QList mostLocalUrls; - bool dummy; - mostLocalUrls.append(m_fileItem.mostLocalUrl(&dummy)); - KIO::setClipboardDataCut(mimeData, cut); - KUrlMimeData::setUrls(kdeUrls, mostLocalUrls, mimeData); -} - -void TreeViewContextMenu::cut() -{ - QMimeData* mimeData = new QMimeData(); - populateMimeData(mimeData, true); - QApplication::clipboard()->setMimeData(mimeData); -} - -void TreeViewContextMenu::copy() -{ - QMimeData* mimeData = new QMimeData(); - populateMimeData(mimeData, false); - QApplication::clipboard()->setMimeData(mimeData); -} - -void TreeViewContextMenu::paste() -{ - KIO::PasteJob *job = KIO::paste(QApplication::clipboard()->mimeData(), m_fileItem.url()); - KJobWidgets::setWindow(job, m_parent); -} - -void TreeViewContextMenu::rename() -{ - m_parent->rename(m_fileItem); -} - -void TreeViewContextMenu::moveToTrash() -{ - const QList list{m_fileItem.url()}; - KIO::JobUiDelegate uiDelegate; - uiDelegate.setWindow(m_parent); - if (uiDelegate.askDeleteConfirmation(list, KIO::JobUiDelegate::Trash, KIO::JobUiDelegate::DefaultConfirmation)) { - KIO::Job* job = KIO::trash(list); - KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Trash, list, QUrl(QStringLiteral("trash:/")), job); - KJobWidgets::setWindow(job, m_parent); - job->uiDelegate()->setAutoErrorHandlingEnabled(true); - } -} - -void TreeViewContextMenu::deleteItem() -{ - const QList list{m_fileItem.url()}; - KIO::JobUiDelegate uiDelegate; - uiDelegate.setWindow(m_parent); - if (uiDelegate.askDeleteConfirmation(list, KIO::JobUiDelegate::Delete, KIO::JobUiDelegate::DefaultConfirmation)) { - KIO::Job* job = KIO::del(list); - KJobWidgets::setWindow(job, m_parent); - job->uiDelegate()->setAutoErrorHandlingEnabled(true); - } -} - -void TreeViewContextMenu::showProperties() -{ - KPropertiesDialog* dialog = new KPropertiesDialog(m_fileItem.url(), m_parent); - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->show(); -} - -void TreeViewContextMenu::setShowHiddenFiles(bool show) -{ - m_parent->setShowHiddenFiles(show); -} - -void TreeViewContextMenu::setLimitFoldersPanelToHome(bool enable) -{ - m_parent->setLimitFoldersPanelToHome(enable); -} - -void TreeViewContextMenu::setAutoScrolling(bool enable) -{ - m_parent->setAutoScrolling(enable); -} - diff --git a/src/panels/panel.h b/src/panels/panel.h --- a/src/panels/panel.h +++ b/src/panels/panel.h @@ -24,6 +24,9 @@ #include #include +class KFileItem; +class KFileItemList; + /** * @brief Base widget for all panels that can be docked on the window borders. * @@ -51,6 +54,17 @@ QSize sizeHint() const override; +signals: + + /** + * Use it to ask the main view to open a context menu + */ + void requestOpenContextMenu(const QPoint& pos, + const KFileItem& item, + const QUrl& url, + const QList& customActions, + const KFileItemList& selection); + public slots: /** * This is invoked every time the folder being displayed in the