Fix shortcut key paste

This commit is contained in:
reionwong 2021-06-16 12:43:43 +08:00
parent 8d688cb47a
commit 2f95a413ed
9 changed files with 245 additions and 71 deletions

View file

@ -38,6 +38,7 @@ add_executable(cutefish-filemanager
helper/thumbnailer.cpp helper/thumbnailer.cpp
helper/pathhistory.cpp helper/pathhistory.cpp
helper/fm.cpp helper/fm.cpp
helper/shortcut.cpp
desktopiconprovider.cpp desktopiconprovider.cpp

View file

@ -44,7 +44,7 @@ DesktopView::DesktopView(QQuickView *parent)
setTitle(tr("Desktop")); setTitle(tr("Desktop"));
setScreen(qApp->primaryScreen()); setScreen(qApp->primaryScreen());
setResizeMode(QQuickView::SizeRootObjectToView); setResizeMode(QQuickView::SizeRootObjectToView);
setSource(QStringLiteral("qrc:/qml/Desktop/main.qml")); setSource(QStringLiteral("qrc:/qml/Desktop/Main.qml"));
onGeometryChanged(); onGeometryChanged();
@ -67,7 +67,7 @@ QRect DesktopView::screenAvailableRect()
void DesktopView::onGeometryChanged() void DesktopView::onGeometryChanged()
{ {
m_screenRect = qApp->primaryScreen()->geometry(); m_screenRect = qApp->primaryScreen()->geometry();
setGeometry(qApp->primaryScreen()->geometry()); setGeometry(m_screenRect);
emit screenRectChanged(); emit screenRectChanged();
} }

72
helper/shortcut.cpp Normal file
View file

@ -0,0 +1,72 @@
/***************************************************************************
* Copyright 2021 Reion Wong <aj@cutefishos.com> *
* Copyright Ken <https://stackoverflow.com/users/1568857/ken> *
* Copyright 2016 Leslie Zhai <xiangzhai83@gmail.com> *
* *
* 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 "shortcut.h"
#include <QKeyEvent>
ShortCut::ShortCut(QObject *parent)
: QObject(parent)
, m_object(parent)
{
}
void ShortCut::install(QObject *target)
{
if (m_object) {
m_object->removeEventFilter(this);
}
if (target) {
target->installEventFilter(this);
m_object = target;
}
}
bool ShortCut::eventFilter(QObject *obj, QEvent *e)
{
if (e->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);
// int keyInt = keyEvent->modifiers() + keyEvent->key();
if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) {
emit open();
} else if (keyEvent->key() == Qt::Key_C && keyEvent->modifiers() & Qt::ControlModifier) {
emit copy();
} else if (keyEvent->key() == Qt::Key_X && keyEvent->modifiers() & Qt::ControlModifier) {
emit cut();
} else if (keyEvent->key() == Qt::Key_V && keyEvent->modifiers() & Qt::ControlModifier) {
emit paste();
} else if (keyEvent->key() == Qt::Key_F2) {
emit rename();
} else if (keyEvent->key() == Qt::Key_L && keyEvent->modifiers() & Qt::ControlModifier) {
emit openPathEditor();
} else if (keyEvent->key() == Qt::Key_A && keyEvent->modifiers() & Qt::ControlModifier) {
emit selectAll();
} else if (keyEvent->key() == Qt::Key_Backspace) {
emit backspace();
} else if (keyEvent->key() == Qt::Key_Delete) {
emit deleteFile();
}
}
return QObject::eventFilter(obj, e);
}

65
helper/shortcut.h Normal file
View file

@ -0,0 +1,65 @@
/***************************************************************************
* Copyright 2021 Reion Wong <aj@cutefishos.com> *
* Copyright Ken <https://stackoverflow.com/users/1568857/ken> *
* Copyright 2016 Leslie Zhai <xiangzhai83@gmail.com> *
* *
* 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 SHORTCUT_H
#define SHORTCUT_H
#include <QObject>
/**
* TODO: ShortCut is a stopgap solution and should be dropped when Qt's StandardKey
* gains support for these actions. QTBUG-54926 https://bugreports.qt.io/browse/QTBUG-54926
* And it is *NOT* encouraged registering C++ types with the QML by using EventFilter
* but for special case QTBUG-40327 https://bugreports.qt.io/browse/QTBUG-40327
*
* ShortCut was copied from Ken's answer.
* https://stackoverflow.com/questions/12192780/assigning-keyboard-shortcuts-to-qml-components
* it uses cc by-sa 3.0 license by default compatible with GPL.
* https://www.gnu.org/licenses/license-list.en.html#ccbysa
*/
class ShortCut : public QObject
{
Q_OBJECT
public:
explicit ShortCut(QObject *parent = nullptr);
Q_INVOKABLE void install(QObject *target = nullptr);
signals:
void open();
void copy();
void cut();
void paste();
void rename();
void openPathEditor();
void selectAll();
void backspace();
void deleteFile();
protected:
bool eventFilter(QObject *obj, QEvent *e) override;
private:
QObject *m_object;
};
#endif // SHORTCUT_H

View file

@ -36,6 +36,7 @@
#include "helper/thumbnailer.h" #include "helper/thumbnailer.h"
#include "helper/datehelper.h" #include "helper/datehelper.h"
#include "helper/fm.h" #include "helper/fm.h"
#include "helper/shortcut.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@ -66,6 +67,7 @@ int main(int argc, char *argv[])
qmlRegisterType<ItemViewAdapter>(uri, 1, 0, "ItemViewAdapter"); qmlRegisterType<ItemViewAdapter>(uri, 1, 0, "ItemViewAdapter");
qmlRegisterType<DesktopSettings>(uri, 1, 0, "DesktopSettings"); qmlRegisterType<DesktopSettings>(uri, 1, 0, "DesktopSettings");
qmlRegisterType<Fm>(uri, 1, 0, "Fm"); qmlRegisterType<Fm>(uri, 1, 0, "Fm");
qmlRegisterType<ShortCut>(uri, 1, 0, "ShortCut");
qmlRegisterAnonymousType<QAction>(uri, 1); qmlRegisterAnonymousType<QAction>(uri, 1);
QCommandLineParser parser; QCommandLineParser parser;

View file

@ -665,11 +665,25 @@ void FolderModel::copy()
void FolderModel::paste() void FolderModel::paste()
{ {
if (QAction *action = m_actionCollection.action("paste")) const QMimeData *mimeData = QApplication::clipboard()->mimeData();
if (!action->isEnabled()) bool enable = false;
return;
KIO::paste(QApplication::clipboard()->mimeData(), m_dirModel->dirLister()->url()); // Update paste action
if (QAction *paste = m_actionCollection.action(QStringLiteral("paste"))) {
QList<QUrl> urls = KUrlMimeData::urlsFromMimeData(mimeData);
if (!urls.isEmpty()) {
if (!rootItem().isNull()) {
enable = rootItem().isWritable();
}
}
paste->setEnabled(enable);
}
if (enable) {
KIO::paste(mimeData, m_dirModel->dirLister()->url());
}
} }
void FolderModel::cut() void FolderModel::cut()
@ -1135,10 +1149,13 @@ void FolderModel::updateActions()
if (QAction *paste = m_actionCollection.action(QStringLiteral("paste"))) { if (QAction *paste = m_actionCollection.action(QStringLiteral("paste"))) {
bool enable = false; bool enable = false;
QList<QUrl> urls = KUrlMimeData::urlsFromMimeData(QApplication::clipboard()->mimeData()); const QMimeData *mimeData = QApplication::clipboard()->mimeData();
QList<QUrl> urls = KUrlMimeData::urlsFromMimeData(mimeData);
if (!urls.isEmpty() && rootItem().isWritable()) { if (!urls.isEmpty()) {
enable = rootItem().isWritable(); if (!rootItem().isNull()) {
enable = rootItem().isWritable();
}
} }
paste->setEnabled(enable); paste->setEnabled(enable);

View file

@ -16,7 +16,7 @@
<file>images/light/grid.svg</file> <file>images/light/grid.svg</file>
<file>images/light/list.svg</file> <file>images/light/list.svg</file>
<file>qml/PathBar.qml</file> <file>qml/PathBar.qml</file>
<file>qml/Desktop/main.qml</file> <file>qml/Desktop/Main.qml</file>
<file>qml/FolderGridView.qml</file> <file>qml/FolderGridView.qml</file>
<file>qml/GlobalSettings.qml</file> <file>qml/GlobalSettings.qml</file>
<file>qml/FolderGridItem.qml</file> <file>qml/FolderGridItem.qml</file>

View file

@ -23,14 +23,14 @@ import QtQuick.Layouts 1.12
import QtQuick.Window 2.12 import QtQuick.Window 2.12
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
import Cutefish.FileManager 1.0 import Cutefish.FileManager 1.0 as FM
import FishUI 1.0 as FishUI import FishUI 1.0 as FishUI
import "../" import "../"
Item { Item {
id: rootItem id: rootItem
DesktopSettings { FM.DesktopSettings {
id: settings id: settings
} }
@ -81,14 +81,14 @@ Item {
} }
} }
FolderModel { FM.FolderModel {
id: dirModel id: dirModel
url: desktopPath() url: desktopPath()
isDesktop: true isDesktop: true
viewAdapter: viewAdapter viewAdapter: viewAdapter
} }
ItemViewAdapter { FM.ItemViewAdapter {
id: viewAdapter id: viewAdapter
adapterView: _folderView adapterView: _folderView
adapterModel: dirModel adapterModel: dirModel
@ -97,6 +97,11 @@ Item {
_folderView.contentWidth, _folderView.contentHeight) _folderView.contentWidth, _folderView.contentHeight)
} }
MouseArea {
anchors.fill: parent
onClicked: _folderView.forceActiveFocus()
}
FolderGridView { FolderGridView {
id: _folderView id: _folderView
anchors.fill: parent anchors.fill: parent
@ -118,19 +123,6 @@ Item {
rightMargin: desktopView.screenRect.width - (desktopView.screenAvailableRect.x + desktopView.screenAvailableRect.width) rightMargin: desktopView.screenRect.width - (desktopView.screenAvailableRect.x + desktopView.screenAvailableRect.width)
bottomMargin: desktopView.screenRect.height - (desktopView.screenAvailableRect.y + desktopView.screenAvailableRect.height) bottomMargin: desktopView.screenRect.height - (desktopView.screenAvailableRect.y + desktopView.screenAvailableRect.height)
Behavior on anchors.topMargin {
NumberAnimation { duration: 125; easing.type: Easing.Linear }
}
Behavior on leftMargin {
NumberAnimation { duration: 125; easing.type: Easing.Linear }
}
Behavior on rightMargin {
NumberAnimation { duration: 125; easing.type: Easing.Linear }
}
Behavior on bottomMargin {
NumberAnimation { duration: 125; easing.type: Easing.Linear }
}
flow: GridView.FlowTopToBottom flow: GridView.FlowTopToBottom
delegate: FolderGridItem {} delegate: FolderGridItem {}
@ -151,31 +143,46 @@ Item {
} }
} }
Connections { FM.ShortCut {
target: _folderView id: shortCut
function onKeyPress(event) { Component.onCompleted: {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) shortCut.install(_folderView)
dirModel.openSelected() }
else if (event.key === Qt.Key_C && event.modifiers & Qt.ControlModifier)
dirModel.copy() onOpen: {
else if (event.key === Qt.Key_X && event.modifiers & Qt.ControlModifier) dirModel.openSelected()
dirModel.cut() }
else if (event.key === Qt.Key_V && event.modifiers & Qt.ControlModifier) onCopy: {
dirModel.paste() dirModel.copy()
else if (event.key === Qt.Key_F2) }
dirModel.requestRename() onCut: {
else if (event.key === Qt.Key_A && event.modifiers & Qt.ControlModifier) dirModel.cut()
dirModel.selectAll() }
else if (event.key === Qt.Key_Delete) onPaste: {
dirModel.keyDeletePress() dirModel.paste()
}
onRename: {
dirModel.requestRename()
}
onOpenPathEditor: {
folderPage.requestPathEditor()
}
onSelectAll: {
dirModel.selectAll()
}
onBackspace: {
dirModel.up()
}
onDeleteFile: {
dirModel.keyDeletePress()
} }
} }
Component { Component {
id: rubberBandObject id: rubberBandObject
RubberBand { FM.RubberBand {
id: rubberBand id: rubberBand
width: 0 width: 0

View file

@ -21,7 +21,7 @@ import QtQuick 2.12
import QtQuick.Controls 2.12 import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.12
import Cutefish.FileManager 1.0 import Cutefish.FileManager 1.0 as FM
import FishUI 1.0 as FishUI import FishUI 1.0 as FishUI
import "./Dialogs" import "./Dialogs"
@ -57,7 +57,7 @@ Item {
visible: false visible: false
} }
FolderModel { FM.FolderModel {
id: dirModel id: dirModel
viewAdapter: viewAdapter viewAdapter: viewAdapter
@ -69,7 +69,7 @@ Item {
} }
} }
ItemViewAdapter { FM.ItemViewAdapter {
id: viewAdapter id: viewAdapter
adapterView: _viewLoader.item adapterView: _viewLoader.item
adapterModel: _viewLoader.item.positioner ? _viewLoader.item.positioner : dirModel adapterModel: _viewLoader.item.positioner ? _viewLoader.item.positioner : dirModel
@ -107,8 +107,11 @@ Item {
} }
onSourceComponentChanged: { onSourceComponentChanged: {
// // Focus
_viewLoader.item.forceActiveFocus() _viewLoader.item.forceActiveFocus()
// ShortCut
shortCut.install(_viewLoader.item)
} }
} }
@ -218,7 +221,7 @@ Item {
Component { Component {
id: rubberBandObject id: rubberBandObject
RubberBand { FM.RubberBand {
id: rubberBand id: rubberBand
width: 0 width: 0
@ -251,28 +254,35 @@ Item {
} }
} }
Connections { FM.ShortCut {
target: _viewLoader.item id: shortCut
function onKeyPress(event) { onOpen: {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) dirModel.openSelected()
dirModel.openSelected() }
else if (event.key === Qt.Key_C && event.modifiers & Qt.ControlModifier) onCopy: {
dirModel.copy() dirModel.copy()
else if (event.key === Qt.Key_X && event.modifiers & Qt.ControlModifier) }
dirModel.cut() onCut: {
else if (event.key === Qt.Key_V && event.modifiers & Qt.ControlModifier) dirModel.cut()
dirModel.paste() }
else if (event.key === Qt.Key_F2) onPaste: {
dirModel.requestRename() dirModel.paste()
else if (event.key === Qt.Key_L && event.modifiers & Qt.ControlModifier) }
folderPage.requestPathEditor() onRename: {
else if (event.key === Qt.Key_A && event.modifiers & Qt.ControlModifier) dirModel.requestRename()
dirModel.selectAll() }
else if (event.key === Qt.Key_Backspace) onOpenPathEditor: {
dirModel.up() folderPage.requestPathEditor()
else if (event.key === Qt.Key_Delete) }
dirModel.keyDeletePress() onSelectAll: {
dirModel.selectAll()
}
onBackspace: {
dirModel.up()
}
onDeleteFile: {
dirModel.keyDeletePress()
} }
} }