2015-07-25 17:51:40 +03:00
|
|
|
/*
|
|
|
|
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library 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
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public License
|
|
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "popupview.h"
|
|
|
|
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QClipboard>
|
|
|
|
#include <QDesktopWidget>
|
|
|
|
#include <QGraphicsScene>
|
|
|
|
#include <QGraphicsView>
|
|
|
|
#include <QGraphicsWidget>
|
|
|
|
#include <QItemSelectionModel>
|
|
|
|
#include <QStyle>
|
|
|
|
|
|
|
|
#include <KAction>
|
|
|
|
#include <KBookmarkManager>
|
|
|
|
#include <KDesktopFile>
|
|
|
|
#include <KDirModel>
|
|
|
|
#include <kfileitemactions.h>
|
|
|
|
#include <KFileItemDelegate>
|
|
|
|
#include <kfileitemlistproperties.h>
|
|
|
|
#include <kfilepreviewgenerator.h>
|
|
|
|
#include <knewfilemenu.h>
|
|
|
|
#include <KWindowSystem>
|
|
|
|
#include <KMenu>
|
2016-04-16 16:05:41 +00:00
|
|
|
#include <KIcon>
|
2015-07-25 17:51:40 +03:00
|
|
|
|
|
|
|
#include <kio/fileundomanager.h>
|
|
|
|
#include <kio/paste.h>
|
|
|
|
|
|
|
|
#include <konqmimedata.h>
|
|
|
|
#include <konq_operations.h>
|
|
|
|
#include <konq_popupmenu.h>
|
|
|
|
|
|
|
|
#include "dirlister.h"
|
|
|
|
#include "folderviewadapter.h"
|
|
|
|
#include "iconview.h"
|
|
|
|
#include "proxymodel.h"
|
|
|
|
|
|
|
|
#include <Plasma/Applet>
|
|
|
|
#include <Plasma/BusyWidget>
|
|
|
|
#include <Plasma/FrameSvg>
|
|
|
|
#include <Plasma/Theme>
|
|
|
|
#include <Plasma/WindowEffects>
|
2022-11-07 18:23:05 +02:00
|
|
|
#include <Plasma/DialogShadows>
|
2015-07-25 17:51:40 +03:00
|
|
|
|
|
|
|
|
2023-06-07 12:57:37 +03:00
|
|
|
QElapsedTimer PopupView::s_lastOpenClose;
|
2015-07-25 17:51:40 +03:00
|
|
|
|
|
|
|
PopupView::PopupView(const QModelIndex &index, const QPoint &pos,
|
|
|
|
const bool &showPreview, const QStringList &previewPlugins,
|
|
|
|
const IconView *parentView)
|
|
|
|
: QWidget(0, Qt::X11BypassWindowManagerHint),
|
2022-11-07 18:23:05 +02:00
|
|
|
m_dialogshadows(0),
|
|
|
|
m_background(0),
|
2015-07-25 17:51:40 +03:00
|
|
|
m_view(0),
|
|
|
|
m_parentView(parentView),
|
|
|
|
m_busyWidget(0),
|
|
|
|
m_iconView(0),
|
|
|
|
m_parentViewModel(0),
|
|
|
|
m_dirModel(0),
|
|
|
|
m_model(0),
|
|
|
|
m_actionCollection(this),
|
|
|
|
m_newMenu(0),
|
|
|
|
m_itemActions(0),
|
|
|
|
m_showingMenu(false),
|
|
|
|
m_showPreview(showPreview),
|
|
|
|
m_delayedClose(false),
|
|
|
|
m_previewPlugins(previewPlugins)
|
|
|
|
{
|
|
|
|
setAttribute(Qt::WA_TranslucentBackground);
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
if (KWindowSystem::compositingActive()) {
|
|
|
|
setAttribute(Qt::WA_NoSystemBackground, false);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
KWindowSystem::setState(effectiveWinId(), NET::SkipTaskbar | NET::SkipPager);
|
|
|
|
|
|
|
|
setAcceptDrops(true);
|
|
|
|
|
|
|
|
QPalette pal = palette();
|
|
|
|
pal.setColor(backgroundRole(), Qt::transparent);
|
|
|
|
pal.setColor(QPalette::Text, Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor));
|
|
|
|
setPalette(pal);
|
|
|
|
|
|
|
|
m_parentViewModel = static_cast<const ProxyModel*>(index.model());
|
|
|
|
|
|
|
|
KFileItem item = m_parentViewModel->itemForIndex(index);
|
|
|
|
if (item.isDesktopFile()) {
|
|
|
|
KDesktopFile file(item.localPath());
|
|
|
|
m_url = file.readUrl();
|
|
|
|
} else {
|
|
|
|
m_url = item.targetUrl();
|
|
|
|
}
|
|
|
|
|
2022-11-07 18:23:05 +02:00
|
|
|
m_dialogshadows = new Plasma::DialogShadows(this, "dialogs/background");
|
2015-07-25 17:51:40 +03:00
|
|
|
m_background = new Plasma::FrameSvg(this);
|
|
|
|
m_background->setImagePath("dialogs/background");
|
|
|
|
|
|
|
|
int left = m_background->marginSize(Plasma::LeftMargin);
|
|
|
|
int top = m_background->marginSize(Plasma::TopMargin);
|
|
|
|
int right = m_background->marginSize(Plasma::RightMargin);
|
|
|
|
int bottom = m_background->marginSize(Plasma::BottomMargin);
|
|
|
|
|
|
|
|
setContentsMargins(left, top, right, bottom);
|
|
|
|
|
|
|
|
resize(parentView->sizeForRowsColumns(2, 3) + QSize(left + right, top + bottom));
|
|
|
|
|
|
|
|
const QRect available = QApplication::desktop()->availableGeometry(pos);
|
|
|
|
QPoint pt = pos;
|
|
|
|
|
|
|
|
if (pt.x() + width() > available.right()) {
|
|
|
|
pt.rx() -= width();
|
|
|
|
}
|
|
|
|
if (pt.x() < available.left()) {
|
|
|
|
pt.rx() = available.left();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pt.y() + height() > available.bottom()) {
|
|
|
|
pt.ry() -= height();
|
|
|
|
}
|
|
|
|
if (pt.y() < available.top()) {
|
|
|
|
pt.ry() = available.top();
|
|
|
|
}
|
|
|
|
|
|
|
|
move(pt);
|
|
|
|
show();
|
|
|
|
|
|
|
|
QTimer::singleShot(10, this, SLOT(init()));
|
|
|
|
s_lastOpenClose.restart();
|
|
|
|
}
|
|
|
|
|
|
|
|
PopupView::~PopupView()
|
|
|
|
{
|
|
|
|
delete m_newMenu;
|
|
|
|
s_lastOpenClose.restart();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::delayedHide()
|
|
|
|
{
|
|
|
|
if (!m_iconView || !m_iconView->dragInProgress()) {
|
|
|
|
m_hideTimer.start(400, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PopupView::dragInProgress()
|
|
|
|
{
|
|
|
|
return m_iconView && m_iconView->dragInProgress();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::init()
|
|
|
|
{
|
|
|
|
if (m_model) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_scene = new QGraphicsScene(this);
|
|
|
|
m_view = new QGraphicsView(m_scene, this);
|
|
|
|
m_view->setFrameShape(QFrame::NoFrame);
|
|
|
|
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
m_view->viewport()->setAutoFillBackground(false);
|
|
|
|
m_view->setGeometry(contentsRect());
|
|
|
|
m_view->show();
|
|
|
|
|
|
|
|
DirLister *lister = new DirLister(this);
|
|
|
|
lister->setDelayedMimeTypes(true);
|
|
|
|
lister->setAutoErrorHandlingEnabled(false, 0);
|
|
|
|
lister->openUrl(m_url);
|
|
|
|
|
|
|
|
m_dirModel = new KDirModel(this);
|
|
|
|
m_dirModel->setDropsAllowed(KDirModel::DropOnDirectory | KDirModel::DropOnLocalExecutable);
|
|
|
|
m_dirModel->setDirLister(lister);
|
|
|
|
|
|
|
|
m_model = new ProxyModel(this);
|
|
|
|
m_model->setSourceModel(m_dirModel);
|
|
|
|
m_model->setSortLocaleAware(m_parentViewModel->isSortLocaleAware());
|
|
|
|
m_model->setParseDesktopFiles(m_parentViewModel->parseDesktopFiles());
|
|
|
|
m_model->setFilterMode(m_parentViewModel->ProxyModel::NoFilter);
|
|
|
|
m_model->setDynamicSortFilter(true);
|
|
|
|
|
|
|
|
if (!m_parentViewModel->dynamicSortFilter()) {
|
|
|
|
m_model->setSortDirectoriesFirst(true);
|
|
|
|
m_model->sort(int(KDirModel::Name), Qt::AscendingOrder);
|
|
|
|
} else {
|
|
|
|
m_model->setSortDirectoriesFirst(m_parentViewModel->sortDirectoriesFirst());
|
|
|
|
m_model->sort(m_parentViewModel->sortColumn(), m_parentViewModel->sortOrder());
|
|
|
|
}
|
|
|
|
|
|
|
|
m_delegate = new KFileItemDelegate(this);
|
|
|
|
m_selectionModel = new QItemSelectionModel(m_model, this);
|
|
|
|
|
|
|
|
m_iconView = new IconView(0);
|
|
|
|
m_iconView->setModel(m_model);
|
|
|
|
m_iconView->setItemDelegate(m_delegate);
|
|
|
|
m_iconView->setSelectionModel(m_selectionModel);
|
|
|
|
m_iconView->setFont(m_parentView->font());
|
|
|
|
m_iconView->setPalette(palette());
|
|
|
|
m_iconView->setDrawShadows(m_parentView->drawShadows());
|
|
|
|
m_iconView->setIconSize(m_parentView->iconSize());
|
|
|
|
m_iconView->setGridSize(m_parentView->gridSize());
|
|
|
|
m_iconView->setTextLineCount(m_parentView->textLineCount());
|
|
|
|
m_iconView->setWordWrap(m_parentView->wordWrap());
|
|
|
|
m_iconView->setIconsMoveable(false);
|
|
|
|
m_iconView->setClickToViewFolders(false);
|
|
|
|
m_iconView->setShowSelectionMarker(m_parentView->showSelectionMarker());
|
|
|
|
|
|
|
|
connect(m_iconView, SIGNAL(activated(QModelIndex)), SLOT(activated(QModelIndex)));
|
|
|
|
connect(m_iconView, SIGNAL(contextMenuRequest(QWidget*,QPoint)), SLOT(contextMenuRequest(QWidget*,QPoint)));
|
|
|
|
connect(m_iconView, SIGNAL(busy(bool)), SLOT(setBusy(bool)));
|
|
|
|
connect(m_iconView, SIGNAL(popupViewClosed()), SLOT(maybeClose()));
|
|
|
|
|
|
|
|
FolderViewAdapter *adapter = new FolderViewAdapter(m_iconView);
|
|
|
|
m_previewGenerator = new KFilePreviewGenerator(adapter, m_model);
|
|
|
|
m_previewGenerator->setPreviewShown(m_showPreview);
|
|
|
|
m_previewGenerator->setEnabledPlugins(m_previewPlugins);
|
|
|
|
|
|
|
|
m_iconView->setGeometry(contentsRect());
|
|
|
|
m_iconView->show();
|
|
|
|
|
|
|
|
m_scene->addItem(m_iconView);
|
|
|
|
setBusy(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::createActions()
|
|
|
|
{
|
|
|
|
// Remove the Shift+Delete shortcut from the cut action, since it's used for deleting files
|
|
|
|
KAction *cut = KStandardAction::cut(this, SLOT(cut()), this);
|
2024-04-24 10:25:20 +03:00
|
|
|
QKeySequence cutShortcut = cut->shortcut();
|
|
|
|
static const int shiftdelete = (Qt::SHIFT | Qt::Key_Delete);
|
|
|
|
if (cutShortcut[0] == shiftdelete) {
|
|
|
|
cutShortcut = QKeySequence(cutShortcut[1]);
|
|
|
|
}
|
|
|
|
if (cutShortcut[0] == shiftdelete) {
|
|
|
|
cutShortcut = QKeySequence();
|
|
|
|
}
|
|
|
|
cut->setShortcut(cutShortcut);
|
2015-07-25 17:51:40 +03:00
|
|
|
|
|
|
|
KAction *copy = KStandardAction::copy(this, SLOT(copy()), this);
|
|
|
|
|
|
|
|
KIO::FileUndoManager *manager = KIO::FileUndoManager::self();
|
|
|
|
|
|
|
|
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 *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 *emptyTrash = new KAction(KIcon("trash-empty"), i18n("&Empty Trash Bin"), this);
|
|
|
|
KConfig trashConfig("trashrc", KConfig::SimpleConfig);
|
|
|
|
emptyTrash->setEnabled(!trashConfig.group("Status").readEntry("Empty", true));
|
|
|
|
connect(emptyTrash, SIGNAL(triggered()), SLOT(emptyTrashBin()));
|
|
|
|
|
|
|
|
KAction *del = new KAction(i18n("&Delete"), this);
|
|
|
|
del->setIcon(KIcon("edit-delete"));
|
|
|
|
del->setShortcut(Qt::SHIFT + Qt::Key_Delete);
|
|
|
|
connect(del, SIGNAL(triggered()), SLOT(deleteSelectedIcons()));
|
|
|
|
|
|
|
|
// Create the new menu
|
|
|
|
m_newMenu = new KNewFileMenu(&m_actionCollection, "new_menu", this);
|
|
|
|
connect(m_newMenu->menu(), SIGNAL(aboutToShow()), this, SLOT(aboutToShowCreateNew()));
|
|
|
|
|
|
|
|
m_actionCollection.addAction("undo", undo);
|
|
|
|
m_actionCollection.addAction("cut", cut);
|
|
|
|
m_actionCollection.addAction("copy", copy);
|
|
|
|
m_actionCollection.addAction("paste", paste);
|
|
|
|
m_actionCollection.addAction("pasteto", pasteTo);
|
|
|
|
m_actionCollection.addAction("rename", rename);
|
|
|
|
m_actionCollection.addAction("trash", trash);
|
|
|
|
m_actionCollection.addAction("del", del);
|
|
|
|
m_actionCollection.addAction("empty_trash", emptyTrash);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::contextMenuRequest(QWidget *widget, const QPoint& screenPos)
|
|
|
|
{
|
|
|
|
showContextMenu(widget, screenPos, m_selectionModel->selectedIndexes());
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::showContextMenu(QWidget *widget, const QPoint &screenPos, const QList<QModelIndex> &indexes)
|
|
|
|
{
|
|
|
|
Q_UNUSED(widget)
|
|
|
|
// contextMenuRequest is only called from the icon view, which is created in init()
|
|
|
|
// which mean m_model should always be initialized
|
|
|
|
Q_ASSERT(m_model);
|
|
|
|
|
|
|
|
if (indexes.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_actionCollection.isEmpty()) {
|
|
|
|
createActions();
|
|
|
|
}
|
|
|
|
|
|
|
|
KFileItemList items;
|
|
|
|
bool hasRemoteFiles = false;
|
|
|
|
bool isTrashLink = false;
|
|
|
|
|
|
|
|
foreach (const QModelIndex &index, m_selectionModel->selectedIndexes()) {
|
|
|
|
KFileItem item = m_model->itemForIndex(index);
|
|
|
|
if (!item.isNull()) {
|
|
|
|
hasRemoteFiles |= item.localPath().isEmpty();
|
|
|
|
items.append(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we're showing the menu for the trash link
|
|
|
|
if (items.count() == 1 && items.at(0).isDesktopFile()) {
|
|
|
|
KDesktopFile file(items.at(0).localPath());
|
|
|
|
if (file.readType() == "Link" && file.readUrl() == "trash:/") {
|
|
|
|
isTrashLink = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QAction *pasteTo = m_actionCollection.action("pasteto");
|
|
|
|
if (pasteTo) {
|
|
|
|
if (QAction *paste = m_actionCollection.action("paste")) {
|
|
|
|
pasteTo->setEnabled(paste->isEnabled());
|
|
|
|
pasteTo->setText(paste->text());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<QAction*> editActions;
|
|
|
|
editActions.append(m_actionCollection.action("rename"));
|
|
|
|
|
|
|
|
KConfigGroup configGroup(KGlobal::config(), "KDE");
|
|
|
|
bool showDeleteCommand = configGroup.readEntry("ShowDeleteCommand", false);
|
|
|
|
|
|
|
|
// Don't add the "Move to Trash" action if we're showing the menu for the trash link
|
|
|
|
if (!isTrashLink) {
|
|
|
|
if (!hasRemoteFiles) {
|
|
|
|
editActions.append(m_actionCollection.action("trash"));
|
|
|
|
} else {
|
|
|
|
showDeleteCommand = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (showDeleteCommand) {
|
|
|
|
editActions.append(m_actionCollection.action("del"));
|
|
|
|
}
|
|
|
|
|
2023-08-31 04:10:49 +03:00
|
|
|
KonqPopupMenu::ActionGroupMap actionGroups;
|
2015-07-25 17:51:40 +03:00
|
|
|
actionGroups.insert("editactions", editActions);
|
|
|
|
|
2023-08-31 04:10:49 +03:00
|
|
|
KonqPopupMenu::PopupFlags flags = KonqPopupMenu::ShowProperties;
|
|
|
|
flags |= KonqPopupMenu::ShowNewWindow;
|
|
|
|
flags |= KonqPopupMenu::ShowUrlOperations;
|
2015-07-25 17:51:40 +03:00
|
|
|
|
|
|
|
// m_newMenu can be NULL here but KonqPopupMenu does handle this.
|
|
|
|
KonqPopupMenu *contextMenu = new KonqPopupMenu(items, m_url, m_actionCollection, m_newMenu,
|
2023-08-31 04:10:49 +03:00
|
|
|
flags,
|
2015-07-25 17:51:40 +03:00
|
|
|
QApplication::desktop(),
|
|
|
|
KBookmarkManager::userBookmarksManager(),
|
|
|
|
actionGroups);
|
|
|
|
|
|
|
|
connect(contextMenu->fileItemActions(), SIGNAL(openWithDialogAboutToBeShown()), this, SLOT(openWithDialogAboutToShow()));
|
|
|
|
|
|
|
|
m_showingMenu = true;
|
|
|
|
contextMenu->exec(screenPos);
|
|
|
|
delete contextMenu;
|
|
|
|
m_showingMenu = false;
|
|
|
|
|
|
|
|
if (pasteTo) {
|
|
|
|
pasteTo->setEnabled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_delayedClose) {
|
|
|
|
m_delayedClose = false;
|
|
|
|
closeThisAndParentPopup();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KUrl::List PopupView::selectedUrls() const
|
|
|
|
{
|
|
|
|
Q_ASSERT(m_model);
|
|
|
|
|
|
|
|
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 PopupView::cut()
|
|
|
|
{
|
|
|
|
QMimeData *mimeData = m_model->mimeData(m_selectionModel->selectedIndexes());
|
|
|
|
KonqMimeData::addIsCutSelection(mimeData, true);
|
|
|
|
QApplication::clipboard()->setMimeData(mimeData);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::copy()
|
|
|
|
{
|
|
|
|
QMimeData *mimeData = m_model->mimeData(m_selectionModel->selectedIndexes());
|
|
|
|
QApplication::clipboard()->setMimeData(mimeData);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::paste()
|
|
|
|
{
|
|
|
|
KonqOperations::doPaste(QApplication::desktop(), m_url);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::pasteTo()
|
|
|
|
{
|
|
|
|
KUrl::List urls = selectedUrls();
|
|
|
|
Q_ASSERT(urls.count() == 1);
|
|
|
|
KonqOperations::doPaste(QApplication::desktop(), urls.first());
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::moveToTrash(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
|
|
|
|
{
|
|
|
|
Q_UNUSED(buttons)
|
|
|
|
if (!m_iconView->renameInProgress()) {
|
|
|
|
KonqOperations::Operation op = (modifiers & Qt::ShiftModifier) ?
|
|
|
|
KonqOperations::DEL : KonqOperations::TRASH;
|
|
|
|
|
|
|
|
KonqOperations::del(QApplication::desktop(), op, selectedUrls());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::deleteSelectedIcons()
|
|
|
|
{
|
|
|
|
if (!m_iconView->renameInProgress()) {
|
|
|
|
KonqOperations::del(QApplication::desktop(), KonqOperations::DEL, selectedUrls());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::renameSelectedIcon()
|
|
|
|
{
|
|
|
|
activateWindow();
|
|
|
|
m_iconView->renameSelectedIcon();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::activated(const QModelIndex &index)
|
|
|
|
{
|
|
|
|
const KFileItem item = m_model->itemForIndex(index);
|
|
|
|
item.run();
|
|
|
|
|
|
|
|
closeThisAndParentPopup();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::openWithDialogAboutToShow()
|
|
|
|
{
|
|
|
|
m_delayedClose = true;
|
|
|
|
hideThisAndParentPopup();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::setBusy(bool busy)
|
|
|
|
{
|
|
|
|
m_busy = busy;
|
|
|
|
if (busy && !m_busyWidget) {
|
|
|
|
QTimer::singleShot(100, this, SLOT(createBusyWidgetIfNeeded()));
|
|
|
|
} else {
|
|
|
|
delete m_busyWidget;
|
|
|
|
m_busyWidget = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::createBusyWidgetIfNeeded()
|
|
|
|
{
|
|
|
|
if (m_busy && !m_busyWidget) {
|
|
|
|
const int size = qMin(width(), height()) * .3;
|
|
|
|
m_busyWidget = new Plasma::BusyWidget;
|
|
|
|
m_busyWidget->setGeometry(QStyle::alignedRect(layoutDirection(), Qt::AlignCenter, QSize(size, size), contentsRect()));
|
|
|
|
m_scene->addItem(m_busyWidget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::emptyTrashBin()
|
|
|
|
{
|
|
|
|
KonqOperations::emptyTrash(QApplication::desktop());
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::undoTextChanged(const QString &text)
|
|
|
|
{
|
|
|
|
if (QAction *action = m_actionCollection.action("undo")) {
|
|
|
|
action->setText(text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::aboutToShowCreateNew()
|
|
|
|
{
|
|
|
|
if (m_newMenu) {
|
|
|
|
m_newMenu->checkUpToDate();
|
|
|
|
m_newMenu->setPopupFiles(m_url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::resizeEvent(QResizeEvent *event)
|
|
|
|
{
|
|
|
|
Q_UNUSED(event)
|
|
|
|
|
|
|
|
m_background->resizeFrame(rect().size());
|
|
|
|
|
|
|
|
if (m_view) {
|
|
|
|
m_view->setGeometry(contentsRect());
|
|
|
|
}
|
|
|
|
|
2021-07-19 14:34:49 +03:00
|
|
|
setMask(m_background->mask());
|
2015-07-25 17:51:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::showEvent(QShowEvent *event)
|
|
|
|
{
|
|
|
|
Q_UNUSED(event)
|
|
|
|
|
2022-11-07 18:23:05 +02:00
|
|
|
m_dialogshadows->addWindow(this);
|
2015-07-25 17:51:40 +03:00
|
|
|
}
|
|
|
|
|
2022-11-08 19:13:18 +02:00
|
|
|
void PopupView::hideEvent(QHideEvent *event)
|
|
|
|
{
|
|
|
|
Q_UNUSED(event)
|
|
|
|
|
|
|
|
m_dialogshadows->removeWindow(this);
|
|
|
|
}
|
|
|
|
|
2015-07-25 17:51:40 +03:00
|
|
|
void PopupView::paintEvent(QPaintEvent *event)
|
|
|
|
{
|
|
|
|
Q_UNUSED(event)
|
|
|
|
|
|
|
|
QPainter p(this);
|
|
|
|
p.setCompositionMode(QPainter::CompositionMode_Source);
|
|
|
|
p.fillRect(rect(), Qt::transparent);
|
|
|
|
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
|
|
|
m_background->paintFrame(&p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::contextMenuEvent(QContextMenuEvent *event)
|
|
|
|
{
|
|
|
|
if (!m_model) {
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_actionCollection.isEmpty()) {
|
|
|
|
createActions();
|
|
|
|
}
|
|
|
|
|
|
|
|
KFileItem rootItem = m_model->itemForIndex(QModelIndex());
|
|
|
|
//The root item is invalid (non-existent)
|
|
|
|
if (rootItem.isNull()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QMenu menu;
|
|
|
|
menu.addAction(m_actionCollection.action("new_menu"));
|
|
|
|
menu.addSeparator();
|
|
|
|
menu.addAction(m_actionCollection.action("undo"));
|
|
|
|
menu.addAction(m_actionCollection.action("paste"));
|
|
|
|
menu.addSeparator();
|
|
|
|
|
|
|
|
// Add an action for opening the folder in the preferred application.
|
|
|
|
if (!m_itemActions) {
|
|
|
|
// Create a new KFileItem to prevent the target URL in the root item
|
|
|
|
// from being used. In this case we want the configured URL instead.
|
|
|
|
KFileItem item(rootItem.mode(), rootItem.permissions(), m_url);
|
|
|
|
|
|
|
|
KFileItemListProperties itemList(KFileItemList() << item);
|
|
|
|
|
|
|
|
m_itemActions = new KFileItemActions(this);
|
|
|
|
m_itemActions->setItemListProperties(itemList);
|
|
|
|
}
|
|
|
|
menu.addAction(m_itemActions->preferredOpenWithAction(QString()));
|
|
|
|
|
|
|
|
if (m_url.protocol() == "trash") {
|
|
|
|
menu.addAction(m_actionCollection.action("empty_trash"));
|
|
|
|
}
|
|
|
|
|
|
|
|
m_showingMenu = true;
|
|
|
|
menu.exec(event->globalPos());
|
|
|
|
m_showingMenu = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This function calls a given method in the parent PopupView, and returns true
|
|
|
|
// if successful or false otherwise.
|
|
|
|
bool PopupView::callOnParent(const char *method)
|
|
|
|
{
|
|
|
|
// Since the scene is a child of the popup view, we can get to the parent view easily
|
|
|
|
PopupView *parentView = qobject_cast<PopupView*>(m_parentView->scene()->parent());
|
|
|
|
|
|
|
|
if (parentView) {
|
|
|
|
// We use a delayed call to give enter and leave events time be delivered
|
|
|
|
QMetaObject::invokeMethod(parentView, method, Qt::QueuedConnection);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::maybeClose()
|
|
|
|
{
|
|
|
|
if (!underMouse() && !m_showingMenu &&
|
|
|
|
(!m_iconView || (!m_iconView->isUnderMouse() && !m_iconView->dragInProgress())) &&
|
|
|
|
!callOnParent("maybeClose") && !m_hideTimer.isActive()) {
|
|
|
|
m_hideTimer.start(400, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::closeThisAndParentPopup() {
|
|
|
|
hide();
|
|
|
|
deleteLater();
|
|
|
|
callOnParent("closeThisAndParentPopup");
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::hideThisAndParentPopup()
|
|
|
|
{
|
|
|
|
hide();
|
|
|
|
callOnParent("hideThisAndParentPopup");
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::cancelHideTimer()
|
|
|
|
{
|
|
|
|
m_hideTimer.stop();
|
|
|
|
|
|
|
|
// Propagate the call down the chain of popups
|
|
|
|
callOnParent("cancelHideTimer");
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::enterEvent(QEvent *event)
|
|
|
|
{
|
|
|
|
Q_UNUSED(event)
|
|
|
|
|
|
|
|
// Make sure that any hide timer down the popup chain is stopped
|
|
|
|
cancelHideTimer();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::leaveEvent(QEvent *event)
|
|
|
|
{
|
|
|
|
Q_UNUSED(event)
|
|
|
|
|
|
|
|
// The popups are normally closed by the icon views that created them
|
|
|
|
// in response to hover events, but when the cursor leaves a popup and
|
|
|
|
// enters a widget that isn't an icon view in the popup chain, that
|
|
|
|
// mechanism doesn't work.
|
|
|
|
//
|
|
|
|
// To make sure that the popups are closed when this happens, we call
|
|
|
|
// maybeClose() which checks if the popup is under the mouse cursor,
|
|
|
|
// and if it isn't it calls maybeClose() in the next popup in the chain
|
|
|
|
// and so on. If no popups in the chain is under the mouse cursor,
|
|
|
|
// the root popup will start the hide timer which will close the whole
|
|
|
|
// chain when it fires.
|
|
|
|
if (!m_iconView || !m_iconView->popupVisible()) {
|
|
|
|
maybeClose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::dragEnterEvent(QDragEnterEvent *event)
|
|
|
|
{
|
|
|
|
m_hideTimer.stop();
|
|
|
|
callOnParent("cancelHideTimer");
|
|
|
|
|
|
|
|
// If the popup is open during a drag and drop operation,
|
|
|
|
// assume that we accept the mimetype.
|
|
|
|
event->setAccepted(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::dragLeaveEvent(QDragLeaveEvent *event)
|
|
|
|
{
|
|
|
|
if (!m_iconView || !m_iconView->popupVisible()) {
|
|
|
|
maybeClose();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the popup is open during a drag and drop operation,
|
|
|
|
// assume that we accept the mimetype.
|
|
|
|
event->setAccepted(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupView::timerEvent(QTimerEvent *event)
|
|
|
|
{
|
|
|
|
if (event->timerId() == m_hideTimer.timerId()) {
|
|
|
|
m_hideTimer.stop();
|
|
|
|
emit requestClose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "moc_popupview.cpp"
|
|
|
|
|