From b3da6c1ff0881dfc9b1d33210a661a582885730a Mon Sep 17 00:00:00 2001 From: liyigang Date: Thu, 23 May 2024 14:42:21 +0800 Subject: [PATCH] feat: Support Ctrl+Y recovery undo (Ctrl+Z) operation to prevent files from being deleted Support Ctrl+Y recovery undo (Ctrl+Z) operation to prevent files from being deleted Log: Support Ctrl+Y recovery undo (Ctrl+Z) operation to prevent files from being deleted Task: https://pms.uniontech.com/task-view-341623.html --- ...emanager.server.OperationsStackManager.xml | 11 + include/dfm-base/dfm_event_defines.h | 3 + .../dfm-base/interfaces/abstractjobhandler.h | 2 + src/dfm-base/shortcut/shortcut.cpp | 5 +- .../fileoperations.cpp | 9 + .../deletefiles/dodeletefilesworker.cpp | 18 +- .../fileoperations/filecopymovejob.cpp | 22 +- .../fileoperations/filecopymovejob.h | 18 +- .../fileoperations/fileoperationsservice.h | 4 +- .../fileoperationutils/abstractjob.cpp | 1 + .../fileoperationutils/abstractjob.h | 1 + .../fileoperationutils/abstractworker.cpp | 35 ++- .../fileoperationutils/abstractworker.h | 2 + .../fileoperations/operationsstackproxy.cpp | 53 +++- .../fileoperations/operationsstackproxy.h | 4 + .../fileoperationseventreceiver.cpp | 280 +++++++++++++++--- .../fileoperationseventreceiver.h | 39 ++- .../trashfileeventreceiver.cpp | 79 ++++- .../trashfileeventreceiver.h | 20 +- .../view/operator/fileoperatorproxy.cpp | 6 + .../view/operator/fileoperatorproxy.h | 1 + .../view/operator/shortcutoper.cpp | 3 + .../view/collectionview.cpp | 9 + .../view/collectionview_p.h | 1 + .../utils/fileoperatorhelper.cpp | 9 + .../utils/fileoperatorhelper.h | 2 + .../utils/shortcuthelper.cpp | 11 + .../utils/shortcuthelper.h | 1 + .../operationsstackmanagerdbus.cpp | 25 +- .../operationsstackmanagerdbus.h | 4 + translations/dde-file-manager.ts | 70 +++-- translations/dde-file-manager_bo.ts | 70 +++-- translations/dde-file-manager_ug.ts | 70 +++-- translations/dde-file-manager_zh_CN.ts | 70 +++-- translations/dde-file-manager_zh_HK.ts | 70 +++-- translations/dde-file-manager_zh_TW.ts | 70 +++-- 36 files changed, 843 insertions(+), 255 deletions(-) diff --git a/assets/dbus/org.deepin.filemanager.server.OperationsStackManager.xml b/assets/dbus/org.deepin.filemanager.server.OperationsStackManager.xml index 9c55f311f5..a5a9b3ea26 100644 --- a/assets/dbus/org.deepin.filemanager.server.OperationsStackManager.xml +++ b/assets/dbus/org.deepin.filemanager.server.OperationsStackManager.xml @@ -11,5 +11,16 @@ + + + + + + + + + + + diff --git a/include/dfm-base/dfm_event_defines.h b/include/dfm-base/dfm_event_defines.h index 1954133c22..fbad339b95 100644 --- a/include/dfm-base/dfm_event_defines.h +++ b/include/dfm-base/dfm_event_defines.h @@ -29,6 +29,9 @@ enum GlobalEventType { kLoadPlugins, kHeadlessStarted, kShowSettingDialog, + kSaveRedoOperator, // save Ctrl+Z operator + kCleanSaveOperatorByUrls, // if file delete,clear all ops which contains url + kRedo, // Ctrl+Y // request file operations kOpenFiles = 200, diff --git a/include/dfm-base/interfaces/abstractjobhandler.h b/include/dfm-base/interfaces/abstractjobhandler.h index 75ec572442..d517106cca 100644 --- a/include/dfm-base/interfaces/abstractjobhandler.h +++ b/include/dfm-base/interfaces/abstractjobhandler.h @@ -33,6 +33,7 @@ class AbstractJobHandler : public QObject kDontFormatFileName = 0x100, // 拷贝时不处理文件名称 kRevocation = 0x200, // 拷贝时不处理文件名称 kCopyRemote = 0x400, // 深信服远程拷贝 + kRedo = 0x800, // 重新执行(ctrl + Y) kCountProgressCustomize = 0x800, // 强制使用自己统计进度 }; Q_ENUM(JobFlag) @@ -244,6 +245,7 @@ class AbstractJobHandler : public QObject void requestShowTipsDialog(DFMBASE_NAMESPACE::AbstractJobHandler::ShowDialogType type, const QList list); void workerFinish(); void requestRemoveTaskWidget(); + void requestSaveRedoOperation(const QString &token, const bool moreThanZero); Q_SIGNALS: // 发送给任务使用的信号 /*! * \brief userAction 用户当前动作 diff --git a/src/dfm-base/shortcut/shortcut.cpp b/src/dfm-base/shortcut/shortcut.cpp index 11c07c809c..c0f6b62f42 100644 --- a/src/dfm-base/shortcut/shortcut.cpp +++ b/src/dfm-base/shortcut/shortcut.cpp @@ -31,7 +31,10 @@ Shortcut::Shortcut(QObject *parent) << ShortcutItem(tr("Cut"), "Ctrl + X ") << ShortcutItem(tr("Paste"), "Ctrl + V ") << ShortcutItem(tr("Rename"), "F2 ") - << ShortcutItem(tr("Open in terminal"), "Shift + T "); + << ShortcutItem(tr("Open in terminal"), "Shift + T ") + << ShortcutItem(tr("Undo"), "Ctrl + Z ") + << ShortcutItem(tr("Redo"), "Ctrl + Y "); + group2.groupName = tr("New/Search"); group2.groupItems << ShortcutItem(tr("New window"), "Ctrl + N ") << ShortcutItem(tr("New folder"), "Ctrl + Shift + N ") diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations.cpp b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations.cpp index 5f8d7545a8..c39aa7fe4c 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations.cpp +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations.cpp @@ -282,6 +282,15 @@ void FileOperations::initEventHandle() const QList, const QVariant, AbstractJobHandler::OperatorCallback)>(&FileOperationsEventReceiver::handleOperationHideFiles)); + dpfSignalDispatcher->subscribe(GlobalEventType::kSaveRedoOperator, + FileOperationsEventReceiver::instance(), + &FileOperationsEventReceiver::handleOperationSaveRedoOperations); + dpfSignalDispatcher->subscribe(GlobalEventType::kCleanSaveOperatorByUrls, + FileOperationsEventReceiver::instance(), + &FileOperationsEventReceiver::handleOperationCleanByUrls); + dpfSignalDispatcher->subscribe(GlobalEventType::kRedo, + FileOperationsEventReceiver::instance(), + &FileOperationsEventReceiver::handleRecoveryOperationRedoRecovery); } void FileOperations::followEvents() diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/deletefiles/dodeletefilesworker.cpp b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/deletefiles/dodeletefilesworker.cpp index d9170c629f..e2c6eb3d2e 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/deletefiles/dodeletefilesworker.cpp +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/deletefiles/dodeletefilesworker.cpp @@ -63,11 +63,18 @@ bool DoDeleteFilesWorker::deleteAllFiles() */ bool DoDeleteFilesWorker::deleteFilesOnCanNotRemoveDevice() { + if (allFilesList.count() == 1) { + auto info = InfoFactory::create(allFilesList.first(), Global::CreateFileInfoType::kCreateFileInfoSync); + if (info && info->isAttributes(OptInfoType::kIsFile) && info->size() > 0) + moreThanZero = true; + } + AbstractJobHandler::SupportAction action { AbstractJobHandler::SupportAction::kNoAction }; for (QList::iterator it = --allFilesList.end(); it != --allFilesList.begin(); --it) { if (!stateCheck()) return false; const QUrl &url = *it; + auto info = InfoFactory::create(url, Global::CreateFileInfoType::kCreateFileInfoSync); emitCurrentTaskNotify(url, QUrl()); do { action = AbstractJobHandler::SupportAction::kNoAction; @@ -78,8 +85,10 @@ bool DoDeleteFilesWorker::deleteFilesOnCanNotRemoveDevice() } while (!isStopped() && action == AbstractJobHandler::SupportAction::kRetryAction); if (sourceUrls.contains(url)) { - if (action == AbstractJobHandler::SupportAction::kNoAction) + if (action == AbstractJobHandler::SupportAction::kNoAction) { completeSourceFiles.append(url); + completeTargetFiles.append(url); + } } deleteFilesCount++; @@ -99,6 +108,11 @@ bool DoDeleteFilesWorker::deleteFilesOnCanNotRemoveDevice() bool DoDeleteFilesWorker::deleteFilesOnOtherDevice() { bool ok = true; + if (sourceUrls.count() == 1) { + auto info = InfoFactory::create(sourceUrls.first(), Global::CreateFileInfoType::kCreateFileInfoSync); + if (info && info->isAttributes(OptInfoType::kIsFile) && info->size() > 0) + moreThanZero = true; + } for (auto &url : sourceUrls) { const auto &info = InfoFactory::create(url, Global::CreateFileInfoType::kCreateFileInfoSync); if (!info) { @@ -116,7 +130,7 @@ bool DoDeleteFilesWorker::deleteFilesOnOtherDevice() if (!ok) return false; - + completeTargetFiles.append(url); completeSourceFiles.append(url); } return true; diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/filecopymovejob.cpp b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/filecopymovejob.cpp index 289b7548ff..2ec2890d3f 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/filecopymovejob.cpp +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/filecopymovejob.cpp @@ -129,7 +129,7 @@ JobHandlePointer FileCopyMoveJob::copyFromTrash(const QList &sources, cons * \return JobHandlePointer 任务控制器 */ JobHandlePointer FileCopyMoveJob::moveToTrash(const QList &sources, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags) + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags, const bool isInit) { if (!getOperationsAndDialogService()) { fmCritical() << "get service fialed !!!!!!!!!!!!!!!!!!!"; @@ -137,7 +137,8 @@ JobHandlePointer FileCopyMoveJob::moveToTrash(const QList &sources, } JobHandlePointer jobHandle = operationsService->moveToTrash(sources, flags); - initArguments(jobHandle); + if (isInit) + initArguments(jobHandle); return jobHandle; } @@ -148,7 +149,7 @@ JobHandlePointer FileCopyMoveJob::moveToTrash(const QList &sources, * \return JobHandlePointer 任务控制器 */ JobHandlePointer FileCopyMoveJob::restoreFromTrash(const QList &sources, const QUrl &target, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags) + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags, const bool isInit) { if (!getOperationsAndDialogService()) { fmCritical() << "get service fialed !!!!!!!!!!!!!!!!!!!"; @@ -156,7 +157,8 @@ JobHandlePointer FileCopyMoveJob::restoreFromTrash(const QList &sources, c } JobHandlePointer jobHandle = operationsService->restoreFromTrash(sources, target, flags); - initArguments(jobHandle); + if (isInit) + initArguments(jobHandle); return jobHandle; } @@ -167,7 +169,7 @@ JobHandlePointer FileCopyMoveJob::restoreFromTrash(const QList &sources, c * \return JobHandlePointer 任务控制器 */ JobHandlePointer FileCopyMoveJob::deletes(const QList &sources, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags) + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags, const bool isInit) { if (!getOperationsAndDialogService()) { fmCritical() << "get service fialed !!!!!!!!!!!!!!!!!!!"; @@ -175,7 +177,9 @@ JobHandlePointer FileCopyMoveJob::deletes(const QList &sources, } JobHandlePointer jobHandle = operationsService->deletes(sources, flags); - initArguments(jobHandle); + + if (isInit) + initArguments(jobHandle); return jobHandle; } @@ -188,7 +192,8 @@ JobHandlePointer FileCopyMoveJob::deletes(const QList &sources, * \return JobHandlePointer 任务控制器 */ JobHandlePointer FileCopyMoveJob::cut(const QList &sources, const QUrl &target, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags) + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags, + const bool isInit) { if (!getOperationsAndDialogService()) { fmCritical() << "get service fialed !!!!!!!!!!!!!!!!!!!"; @@ -196,7 +201,8 @@ JobHandlePointer FileCopyMoveJob::cut(const QList &sources, const QUrl &ta } JobHandlePointer jobHandle = operationsService->cut(sources, target, flags); - initArguments(jobHandle); + if (isInit) + initArguments(jobHandle); return jobHandle; } diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/filecopymovejob.h b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/filecopymovejob.h index a8676710ce..8f02ebfedb 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/filecopymovejob.h +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/filecopymovejob.h @@ -30,18 +30,26 @@ class FileCopyMoveJob : public QObject JobHandlePointer copyFromTrash(const QList &sources, const QUrl &target, const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint); JobHandlePointer moveToTrash(const QList &sources, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint); + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags + = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint, + const bool isInit = true); JobHandlePointer restoreFromTrash(const QList &sources, const QUrl &target, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint); + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint, + const bool isInit = true); JobHandlePointer deletes(const QList &sources, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint); + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags + &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint, + const bool isInit = true); JobHandlePointer cut(const QList &sources, const QUrl &target, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint); + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags + = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint, + const bool isInit = true); JobHandlePointer cleanTrash(const QList &sources); + void initArguments(const JobHandlePointer handler); private: bool getOperationsAndDialogService(); - void initArguments(const JobHandlePointer handler); + private slots: void onHandleAddTask(); void onHandleAddTaskWithArgs(const JobInfoPointer info); diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationsservice.h b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationsservice.h index f1ed2c1c3f..4829d99096 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationsservice.h +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationsservice.h @@ -7,6 +7,7 @@ #include "dfmplugin_fileoperations_global.h" #include +#include #include @@ -31,7 +32,8 @@ class FileOperationsService : public QObject JobHandlePointer restoreFromTrash(const QList &sources, const QUrl &target, const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint); JobHandlePointer deletes(const QList &sources, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint); + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags + &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint); JobHandlePointer cut(const QList &sources, const QUrl &target, const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags &flags = DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint); JobHandlePointer cleanTrash(const QList &sources); diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractjob.cpp b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractjob.cpp index a8c72a2511..37999cae39 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractjob.cpp +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractjob.cpp @@ -31,6 +31,7 @@ void AbstractJob::setJobArgs(const JobHandlePointer handle, const QList &s connect(doWorker.data(), &AbstractWorker::errorNotify, this, &AbstractJob::handleError, Qt::QueuedConnection); connect(this, &AbstractJob::errorNotify, handle.get(), &AbstractJobHandler::onError); connect(doWorker.data(), &AbstractWorker::workerFinish, handle.get(), &AbstractJobHandler::workerFinish, Qt::QueuedConnection); + connect(doWorker.data(), &AbstractWorker::requestSaveRedoOperation, handle.get(), &AbstractJobHandler::requestSaveRedoOperation, Qt::QueuedConnection); doWorker->setWorkArgs(handle, sources, target, flags); } diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractjob.h b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractjob.h index 165d1f865b..70914c6a41 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractjob.h +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractjob.h @@ -6,6 +6,7 @@ #define ABSTRACTJOB_H #include "dfmplugin_fileoperations_global.h" +#include #include #include diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractworker.cpp b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractworker.cpp index 6d4930ffec..d6bbae66ce 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractworker.cpp +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractworker.cpp @@ -542,38 +542,51 @@ void AbstractWorker::saveOperations() || jobType == AbstractJobHandler::JobType::kCutType || jobType == AbstractJobHandler::JobType::kMoveToTrashType || jobType == AbstractJobHandler::JobType::kRestoreType) { - GlobalEventType operatorType = GlobalEventType::kDeleteFiles; - QList targetUrls; + GlobalEventType operatorType = GlobalEventType::kDeleteFiles, redoType = GlobalEventType::kUnknowType; + QList targetUrls, redoSources, redoTargets; + redoSources = completeSourceFiles; + redoTargets.append(targetUrl); switch (jobType) { case AbstractJobHandler::JobType::kCopyType: operatorType = GlobalEventType::kDeleteFiles; targetUrls.append(UrlRoute::urlParent(completeSourceFiles.first())); + redoType = GlobalEventType::kCopy; break; case AbstractJobHandler::JobType::kCutType: operatorType = GlobalEventType::kCutFile; - if (!sourceUrls.isEmpty() && FileUtils::isTrashFile(sourceUrls.first())) + if (!sourceUrls.isEmpty() && FileUtils::isTrashFile(sourceUrls.first())) { operatorType = GlobalEventType::kMoveToTrash; - for (auto url : completeSourceFiles) - targetUrls.append(UrlRoute::urlParent(url)); + } else { + targetUrls.append(UrlRoute::urlParent(completeSourceFiles.first())); + } + redoType = GlobalEventType::kCutFile; break; case AbstractJobHandler::JobType::kMoveToTrashType: operatorType = GlobalEventType::kRestoreFromTrash; + redoType = GlobalEventType::kMoveToTrash; break; case AbstractJobHandler::JobType::kRestoreType: operatorType = GlobalEventType::kMoveToTrash; + redoType = GlobalEventType::kRestoreFromTrash; break; default: - operatorType = GlobalEventType::kDeleteFiles; + operatorType = GlobalEventType::kUnknowType; break; } QVariantMap values; - values.insert("event", QVariant::fromValue(static_cast(operatorType))); - values.insert("sources", QUrl::toStringList(completeTargetFiles)); - values.insert("targets", QUrl::toStringList(targetUrls)); - if (jobType != AbstractJobHandler::JobType::kDeleteType) - dpfSignalDispatcher->publish(GlobalEventType::kSaveOperator, values); + values.insert("undoevent", QVariant::fromValue(static_cast(operatorType))); + values.insert("undosources", QUrl::toStringList(completeTargetFiles)); + values.insert("undotargets", QUrl::toStringList(targetUrls)); + values.insert("redoevent", QVariant::fromValue(static_cast(redoType))); + values.insert("redosources", QUrl::toStringList(completeSourceFiles)); + values.insert("redotargets", QUrl::toStringList(redoTargets)); + dpfSignalDispatcher->publish(GlobalEventType::kSaveOperator, values); } } + + if (handle && isConvert && !completeSourceFiles.isEmpty()) { + emit requestSaveRedoOperation(QString::number(quintptr(handle.data()),16), moreThanZero); + } } AbstractWorker::~AbstractWorker() diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractworker.h b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractworker.h index f0b2b9c0dd..2f3bc9e56e 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractworker.h +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/fileoperationutils/abstractworker.h @@ -88,6 +88,7 @@ class AbstractWorker : public QObject void requestShowTipsDialog(DFMBASE_NAMESPACE::AbstractJobHandler::ShowDialogType type, const QList list); void workerFinish(); + void requestSaveRedoOperation(const QString &token, const bool moreThanZero); signals: // update proccess timer use void startUpdateProgressTimer(); void startWork(); @@ -184,6 +185,7 @@ protected slots: QSharedPointer threadPool { nullptr }; static std::atomic_bool bigFileCopy; QAtomicInteger bigFileSize { 0 }; // bigger than this is big file + std::atomic_bool moreThanZero{ false }; }; DPFILEOPERATIONS_END_NAMESPACE diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/operationsstackproxy.cpp b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/operationsstackproxy.cpp index b903ed25c5..a448061e8e 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/operationsstackproxy.cpp +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/operationsstackproxy.cpp @@ -6,7 +6,7 @@ DPFILEOPERATIONS_BEGIN_NAMESPACE -static constexpr uint8_t kMaxStep { 2 }; // BUG: 116699 +static constexpr uint8_t kMaxStep { 100 }; static const char *kOperationsStackService { "org.deepin.filemanager.server" }; static const char *kOperationsStackPath { "/org/deepin/filemanager/server/OperationsStackManager" }; @@ -69,6 +69,57 @@ QVariantMap OperationsStackProxy::revocationOperations() return {}; } +void OperationsStackProxy::SaveRedoOperations(const QVariantMap &values) +{ + if (dbusValid) { + fmInfo() << "Start call dbus: " << __PRETTY_FUNCTION__; + auto &&reply = operationsStackDbus->SaveRedoOperations(values); + reply.waitForFinished(); + if (!reply.isValid()) { + fmCritical() << "D-Bus reply is invalid " << reply.error(); + return; + } + fmInfo() << "End call dbus: " << __PRETTY_FUNCTION__; + return; + } + + while (redoFileOperations.size() >= kMaxStep) + redoFileOperations.pop_front(); + redoFileOperations.push(values); +} + +QVariantMap OperationsStackProxy::RevocationRedoOperations() +{ + if (dbusValid) { + fmInfo() << "Start call dbus: " << __PRETTY_FUNCTION__; + auto &&reply = operationsStackDbus->RevocationRedoOperations(); + reply.waitForFinished(); + if (!reply.isValid()) { + fmCritical() << "D-Bus reply is invalid " << reply.error(); + return {}; + } + fmInfo() << "End call dbus: " << __PRETTY_FUNCTION__; + + return reply.value(); + } + + if (redoFileOperations.count() > 0) + return redoFileOperations.pop(); + + return {}; +} + +void OperationsStackProxy::CleanOperationsByUrl(const QStringList &urls) +{ + if (dbusValid) { + fmInfo() << "Start call dbus: " << __PRETTY_FUNCTION__; + operationsStackDbus->CleanOperationsByUrl(urls); + fmInfo() << "End call dbus: " << __PRETTY_FUNCTION__; + return; + } + +} + OperationsStackProxy::OperationsStackProxy(QObject *parent) : QObject(parent) { diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/operationsstackproxy.h b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/operationsstackproxy.h index 234f527331..8687797659 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/operationsstackproxy.h +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperations/operationsstackproxy.h @@ -25,6 +25,9 @@ class OperationsStackProxy : public QObject void saveOperations(const QVariantMap &values); void cleanOperations(); QVariantMap revocationOperations(); + void SaveRedoOperations(const QVariantMap &values); + QVariantMap RevocationRedoOperations(); + void CleanOperationsByUrl(const QStringList &urls); private: explicit OperationsStackProxy(QObject *parent = nullptr); @@ -34,6 +37,7 @@ class OperationsStackProxy : public QObject bool dbusValid { false }; std::unique_ptr operationsStackDbus; QStack fileOperations; + QStack redoFileOperations; }; DPFILEOPERATIONS_END_NAMESPACE diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.cpp b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.cpp index 933dff99c8..fccd7e18b4 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.cpp +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.cpp @@ -118,11 +118,11 @@ QString FileOperationsEventReceiver::newDocmentName(const QUrl &url, const QStri bool FileOperationsEventReceiver::revocation(const quint64 windowId, const QVariantMap &ret, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handle) { - if (!ret.contains("event") || !ret.contains("sources") || !ret.contains("targets")) + if (!ret.contains("undoevent") || !ret.contains("undosources") || !ret.contains("undotargets")) return false; - GlobalEventType eventType = static_cast(ret.value("event").value()); - QList sources = QUrl::fromStringList(ret.value("sources").toStringList()); - QList targets = QUrl::fromStringList(ret.value("targets").toStringList()); + GlobalEventType eventType = static_cast(ret.value("undoevent").value()); + QList sources = QUrl::fromStringList(ret.value("undosources").toStringList()); + QList targets = QUrl::fromStringList(ret.value("undotargets").toStringList()); if (eventType != kRestoreFromTrash) { for (const auto &url : sources) { if (!DFMIO::DFile(url).exists()) { @@ -144,22 +144,31 @@ bool FileOperationsEventReceiver::revocation(const quint64 windowId, const QVari case kCutFile: if (targets.isEmpty()) return true; - for (int i = 0; i < sources.size(); ++i) - handleOperationCut(windowId, { sources.at(i) }, targets.at(i), AbstractJobHandler::JobFlag::kRevocation, handle); + handleOperationUndoCut(windowId, sources, targets.first(), AbstractJobHandler::JobFlag::kRevocation, handle, ret); break; case kDeleteFiles: - handleOperationDeletes(windowId, sources, AbstractJobHandler::JobFlag::kRevocation, handle); + handleOperationUndoDeletes(windowId, sources, + AbstractJobHandler::JobFlag::kRevocation, + handle, ret); break; case kMoveToTrash: - TrashFileEventReceiver::instance()->handleOperationMoveToTrash(windowId, sources, AbstractJobHandler::JobFlag::kRevocation, handle); + TrashFileEventReceiver::instance()-> + handleOperationUndoMoveToTrash(windowId, sources, + AbstractJobHandler::JobFlag::kRevocation, + handle, ret); break; case kRestoreFromTrash: - TrashFileEventReceiver::instance()->handleOperationRestoreFromTrash(windowId, sources, QUrl(), AbstractJobHandler::JobFlag::kRevocation, handle); + TrashFileEventReceiver::instance()-> + handleOperationUndoRestoreFromTrash(windowId, sources, QUrl(), + AbstractJobHandler::JobFlag::kRevocation, + handle, ret); break; case kRenameFile: if (targets.isEmpty()) return true; - handleOperationRenameFile(windowId, sources.first(), targets.first(), AbstractJobHandler::JobFlag::kRevocation); + handleOperationRenameFile(windowId, sources.first(), + targets.first(), + AbstractJobHandler::JobFlag::kRevocation); break; case kRenameFiles: if (targets.isEmpty()) @@ -176,6 +185,95 @@ bool FileOperationsEventReceiver::revocation(const quint64 windowId, const QVari return true; } +bool FileOperationsEventReceiver::redo(const quint64 windowId, const QVariantMap &ret, AbstractJobHandler::OperatorHandleCallback handle) +{ + if (!ret.contains("undoevent") || !ret.contains("undosources") || !ret.contains("undotargets")) + return false; + GlobalEventType eventType = static_cast(ret.value("undoevent").value()); + QList sources = QUrl::fromStringList(ret.value("undosources").toStringList()); + QList targets = QUrl::fromStringList(ret.value("undotargets").toStringList()); + if (eventType != kRestoreFromTrash && + eventType != kMkdir && + eventType != kTouchFile) { + for (const auto &url : sources) { + if (!DFMIO::DFile(url).exists()) { + // Their sizes are equal, indicating that the current operation is many-to-many. + // So files that do not exist in sources need to be deleted in targets as well + if (targets.size() == sources.size()) { + int index = sources.indexOf(url); + targets.removeAt(index); + } + sources.removeOne(url); + } + } + } + + if (sources.isEmpty()) + return true; + + switch (eventType) { + case kCopy: + if (targets.isEmpty()) + return true; + handleOperationCopy(windowId, { sources }, targets.first(), AbstractJobHandler::JobFlag::kNoHint, handle); + break; + case kCutFile: + if (targets.isEmpty()) + return true; + handleOperationCut(windowId, { sources }, targets.first(), AbstractJobHandler::JobFlag::kNoHint, handle); + break; + case kDeleteFiles: + handleOperationDeletes(windowId, sources, AbstractJobHandler::JobFlag::kNoHint, handle); + break; + case kMoveToTrash: + TrashFileEventReceiver::instance()->handleOperationMoveToTrash(windowId, sources, AbstractJobHandler::JobFlag::kNoHint, handle); + break; + case kRestoreFromTrash: + TrashFileEventReceiver::instance()->handleOperationRestoreFromTrash(windowId, sources, QUrl(), AbstractJobHandler::JobFlag::kNoHint, handle); + break; + case kRenameFile: + if (targets.isEmpty()) + return true; + if (handleOperationRenameFile(windowId, sources.first(), + targets.first(), AbstractJobHandler::JobFlag::kRedo)) + saveFileOperation(targets, sources, GlobalEventType::kRenameFile, + sources, targets, GlobalEventType::kRenameFile); + break; + case kRenameFiles: + { + if (targets.isEmpty()) + return true; + QList successSources, successTargets; + for (int i = 0; i < sources.size(); ++i) { + if (handleOperationRenameFile(windowId, sources[i], targets[i], + AbstractJobHandler::JobFlag::kRedo)) { + successSources.append(sources[i]); + successTargets.append(targets[i]); + } + } + if (!successSources.isEmpty()) { + saveFileOperation(successTargets, successSources, GlobalEventType::kRenameFile, + successSources, successTargets, GlobalEventType::kRenameFile); + } + + break; + } + case kMkdir: + if (sources.isEmpty()) + return true; + return doMkdir(windowId, sources.first(), QVariant(), nullptr, true); + case kTouchFile: + if (sources.isEmpty()) + return true; + doTouchFilePractically(windowId, sources.first()); + break; + default: + return false; + } + + return true; +} + bool FileOperationsEventReceiver::doRenameFiles(const quint64 windowId, const QList urls, const QPair pair, const QPair pair2, const RenameTypes type, QMap &successUrls, QString &errorMsg, @@ -281,9 +379,11 @@ bool FileOperationsEventReceiver::doRenameDesktopFile(const quint64 windowId, co dpfSignalDispatcher->publish(DFMBASE_NAMESPACE::GlobalEventType::kRenameFileResult, windowId, renamed, true, ""); - if (!flags.testFlag(AbstractJobHandler::JobFlag::kRevocation)) { + if (!flags.testFlag(AbstractJobHandler::JobFlag::kRedo)) { const QString path = QFileInfo(desktopPath).absoluteDir().absoluteFilePath(oldName); - saveFileOperation({ oldUrl }, { QUrl::fromLocalFile(path) }, GlobalEventType::kRenameFile); + saveFileOperation({ oldUrl }, { QUrl::fromLocalFile(path) }, GlobalEventType::kRenameFile, + { QUrl::fromLocalFile(path) }, { oldUrl }, + GlobalEventType::kRenameFile, flags.testFlag(AbstractJobHandler::JobFlag::kRevocation)); } return true; } @@ -373,7 +473,11 @@ JobHandlePointer FileOperationsEventReceiver::doCopyFile(const quint64 windowId, return handle; } -JobHandlePointer FileOperationsEventReceiver::doCutFile(quint64 windowId, const QList sources, const QUrl target, const AbstractJobHandler::JobFlags flags, AbstractJobHandler::OperatorHandleCallback handleCallback) +JobHandlePointer FileOperationsEventReceiver::doCutFile(quint64 windowId, const QList sources, + const QUrl target, + const AbstractJobHandler::JobFlags flags, + AbstractJobHandler::OperatorHandleCallback handleCallback, + const bool isInit) { if (sources.isEmpty()) return nullptr; @@ -402,14 +506,20 @@ JobHandlePointer FileOperationsEventReceiver::doCutFile(quint64 windowId, const } } - JobHandlePointer handle = copyMoveJob->cut(sourcesTrans, target, flags); + JobHandlePointer handle = copyMoveJob->cut(sourcesTrans, target, flags, isInit); + if (!isInit) + return handle; + if (handleCallback) handleCallback(handle); return handle; } -JobHandlePointer FileOperationsEventReceiver::doDeleteFile(const quint64 windowId, const QList sources, const AbstractJobHandler::JobFlags flags, AbstractJobHandler::OperatorHandleCallback handleCallback) +JobHandlePointer FileOperationsEventReceiver::doDeleteFile(const quint64 windowId, + const QList sources, + const AbstractJobHandler::JobFlags flags, + AbstractJobHandler::OperatorHandleCallback handleCallback, const bool isInit) { if (sources.isEmpty()) return nullptr; @@ -433,7 +543,10 @@ JobHandlePointer FileOperationsEventReceiver::doDeleteFile(const quint64 windowI && DialogManagerInstance->showDeleteFilesDialog(sources) != QDialog::Accepted) return nullptr; - JobHandlePointer handle = copyMoveJob->deletes(sources, flags); + JobHandlePointer handle = copyMoveJob->deletes(sources, flags, isInit); + if (!isInit) + return handle; + if (handleCallback) handleCallback(handle); @@ -471,9 +584,9 @@ JobHandlePointer FileOperationsEventReceiver::doCleanTrash(const quint64 windowI bool FileOperationsEventReceiver::doMkdir(const quint64 windowId, const QUrl url, const QVariant custom, - AbstractJobHandler::OperatorCallback callback) + AbstractJobHandler::OperatorCallback callback, const bool useUrlPath) { - const QString newPath = newDocmentName(url, QString(), CreateFileType::kCreateFileTypeFolder); + QString newPath = useUrlPath ? url.path() : newDocmentName(url, QString(), CreateFileType::kCreateFileTypeFolder); if (newPath.isEmpty()) return false; @@ -500,7 +613,7 @@ bool FileOperationsEventReceiver::doMkdir(const quint64 windowId, const QUrl url dpfSignalDispatcher->publish(DFMBASE_NAMESPACE::GlobalEventType::kMkdirResult, windowId, QList() << url, ok, error); - saveFileOperation({ targetUrl }, {}, GlobalEventType::kDeleteFiles); + saveFileOperation({ targetUrl }, {}, GlobalEventType::kDeleteFiles, { targetUrl }, {}, GlobalEventType::kMkdir); if (callback) { AbstractJobHandler::CallbackArgus args(new QMap); @@ -587,14 +700,27 @@ QString FileOperationsEventReceiver::doTouchFilePremature(const quint64 windowId } } -void FileOperationsEventReceiver::saveFileOperation(const QList &sourcesUrls, const QList &targetUrls, GlobalEventType type) +void FileOperationsEventReceiver::saveFileOperation(const QList &sourcesUrls, + const QList &targetUrls, + GlobalEventType type, + const QList &redoSourcesUrls, + const QList &redoTargetUrls, + const GlobalEventType redo, + const bool isUndo) { // save operation by dbus QVariantMap values; - values.insert("event", QVariant::fromValue(static_cast(type))); - values.insert("sources", QUrl::toStringList(sourcesUrls)); - values.insert("targets", QUrl::toStringList(targetUrls)); - dpfSignalDispatcher->publish(GlobalEventType::kSaveOperator, values); + values.insert("undoevent", QVariant::fromValue(static_cast(type))); + values.insert("undosources", QUrl::toStringList(sourcesUrls)); + values.insert("undotargets", QUrl::toStringList(targetUrls)); + values.insert("redoevent", QVariant::fromValue(static_cast(redo))); + values.insert("redosources", QUrl::toStringList(redoSourcesUrls)); + values.insert("redotargets", QUrl::toStringList(redoTargetUrls)); + if (!isUndo) { + dpfSignalDispatcher->publish(GlobalEventType::kSaveOperator, values); + } else { + dpfSignalDispatcher->publish(GlobalEventType::kSaveRedoOperator, values); + } } QUrl FileOperationsEventReceiver::checkTargetUrl(const QUrl &url) @@ -691,7 +817,7 @@ void FileOperationsEventReceiver::handleOperationDeletes(const quint64 windowId, const QVariant custom, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorCallback callback) { - JobHandlePointer handle = doDeleteFile(windowId, sources, flags, handleCallback); + JobHandlePointer handle = doDeleteFile(windowId, sources, flags, handleCallback, false); if (callback) { AbstractJobHandler::CallbackArgus args(new QMap); args->insert(AbstractJobHandler::CallbackKey::kWindowId, QVariant::fromValue(windowId)); @@ -857,8 +983,10 @@ bool FileOperationsEventReceiver::handleOperationRenameFile(const quint64 window if (ok) ClipBoard::instance()->replaceClipboardUrl(oldUrl, newUrl); - if (!flags.testFlag(AbstractJobHandler::JobFlag::kRevocation)) - saveFileOperation({ newUrl }, { oldUrl }, GlobalEventType::kRenameFile); + if (!flags.testFlag(AbstractJobHandler::JobFlag::kRedo)) + saveFileOperation({ newUrl }, { oldUrl }, GlobalEventType::kRenameFile, + { oldUrl }, { newUrl }, GlobalEventType::kRenameFile, + flags.testFlag(AbstractJobHandler::JobFlag::kRevocation)); return ok; } @@ -900,7 +1028,8 @@ bool FileOperationsEventReceiver::handleOperationRenameFiles(const quint64 windo dpfSignalDispatcher->publish(DFMBASE_NAMESPACE::GlobalEventType::kRenameFileResult, windowId, successUrls, ok, error); if (!successUrls.isEmpty()) - saveFileOperation(successUrls.values(), successUrls.keys(), GlobalEventType::kRenameFiles); + saveFileOperation(successUrls.values(), successUrls.keys(), GlobalEventType::kRenameFiles, + successUrls.keys(), successUrls.values(), GlobalEventType::kRenameFiles); return ok; } @@ -917,7 +1046,8 @@ void FileOperationsEventReceiver::handleOperationRenameFiles(const quint64 windo dpfSignalDispatcher->publish(DFMBASE_NAMESPACE::GlobalEventType::kRenameFileResult, windowId, successUrls, ok, error); if (!successUrls.isEmpty()) - saveFileOperation(successUrls.values(), successUrls.keys(), GlobalEventType::kRenameFiles); + saveFileOperation(successUrls.values(), successUrls.keys(), GlobalEventType::kRenameFiles, + successUrls.keys(), successUrls.values(), GlobalEventType::kRenameFiles); } bool FileOperationsEventReceiver::handleOperationRenameFiles(const quint64 windowId, const QList urls, const QPair pair) @@ -931,7 +1061,8 @@ bool FileOperationsEventReceiver::handleOperationRenameFiles(const quint64 windo dpfSignalDispatcher->publish(DFMBASE_NAMESPACE::GlobalEventType::kRenameFileResult, windowId, successUrls, true, error); if (!successUrls.isEmpty()) - saveFileOperation(successUrls.values(), successUrls.keys(), GlobalEventType::kRenameFiles); + saveFileOperation(successUrls.values(), successUrls.keys(), GlobalEventType::kRenameFiles, + successUrls.keys(), successUrls.values(), GlobalEventType::kRenameFiles); return true; } @@ -943,7 +1074,8 @@ bool FileOperationsEventReceiver::handleOperationRenameFiles(const quint64 windo dpfSignalDispatcher->publish(DFMBASE_NAMESPACE::GlobalEventType::kRenameFileResult, windowId, successUrls, ok, error); if (!successUrls.isEmpty()) - saveFileOperation(successUrls.values(), successUrls.keys(), GlobalEventType::kRenameFiles); + saveFileOperation(successUrls.values(), successUrls.keys(), GlobalEventType::kRenameFiles, + successUrls.keys(), successUrls.values(), GlobalEventType::kRenameFiles); return ok; } @@ -957,7 +1089,8 @@ void FileOperationsEventReceiver::handleOperationRenameFiles(const quint64 windo dpfSignalDispatcher->publish(DFMBASE_NAMESPACE::GlobalEventType::kRenameFileResult, windowId, successUrls, ok, error); if (!successUrls.isEmpty()) - saveFileOperation(successUrls.values(), successUrls.keys(), GlobalEventType::kRenameFiles); + saveFileOperation(successUrls.values(), successUrls.keys(), GlobalEventType::kRenameFiles, + successUrls.keys(), successUrls.values(), GlobalEventType::kRenameFiles); } bool FileOperationsEventReceiver::handleOperationMkdir(const quint64 windowId, const QUrl url) @@ -985,7 +1118,7 @@ bool FileOperationsEventReceiver::doTouchFilePractically(const quint64 windowId, } dpfSignalDispatcher->publish(DFMBASE_NAMESPACE::GlobalEventType::kTouchFileResult, windowId, QList() << url, ok, error); - saveFileOperation({ url }, {}, GlobalEventType::kDeleteFiles); + saveFileOperation({ url }, {}, GlobalEventType::kDeleteFiles, { url }, {}, GlobalEventType::kTouchFile); return ok; } @@ -1276,4 +1409,85 @@ bool FileOperationsEventReceiver::handleShortCutPaste(quint64, const QList } return false; } + +void FileOperationsEventReceiver::handleOperationSaveRedoOperations(const QVariantMap values) +{ + OperationsStackProxy::instance().SaveRedoOperations(values); +} + +void FileOperationsEventReceiver::handleOperationCleanByUrls(const QList &urls) +{ + if (urls.isEmpty()) { + qCWarning(logDFMBase) << "error : urls is empty!!"; + return; + } + QStringList strs; + for (const auto &url : urls) { + if (url.isValid()) + strs.append(url.toString()); + } + OperationsStackProxy::instance().CleanOperationsByUrl(strs); +} + +void FileOperationsEventReceiver::handleRecoveryOperationRedoRecovery(const quint64 windowId, AbstractJobHandler::OperatorHandleCallback handle) +{ + const QVariantMap &ret { OperationsStackProxy::instance().RevocationRedoOperations() }; + redo(windowId, ret, handle); +} + +// ctrl + z 执行后保存当前的redo操作 +void FileOperationsEventReceiver::handleSaveRedoOpt(const QString &token, const bool moreThanZero) +{ + QVariantMap ret; + { + QMutexLocker lk(&undoLock); + if (!undoOpts.contains(token)) + return; + ret = undoOpts.take(token); + } + if (ret.isEmpty()) + return; + GlobalEventType undoEventType = static_cast(ret.value("undoevent").value()); + QList undoSources = QUrl::fromStringList(ret.value("undosources").toStringList()); + QList undoTargets = QUrl::fromStringList(ret.value("undotargets").toStringList()); + GlobalEventType redoEventType = static_cast(ret.value("redoevent").value()); + QList redoSources = QUrl::fromStringList(ret.value("redosources").toStringList()); + QList redoTargets = QUrl::fromStringList(ret.value("redotargets").toStringList()); + if (redoEventType != GlobalEventType::kTouchFile || !moreThanZero) + saveFileOperation(redoSources, redoTargets, redoEventType, undoSources, undoTargets, undoEventType, true); +} + +void FileOperationsEventReceiver::handleOperationUndoDeletes(const quint64 windowId, const QList sources, const AbstractJobHandler::JobFlags flags, AbstractJobHandler::OperatorHandleCallback handleCallback, const QVariantMap &op) +{ + auto handle = doDeleteFile(windowId, sources, flags, handleCallback, false); + if (!handle) + return; + connect(handle.get(), &AbstractJobHandler::requestSaveRedoOperation, this, + &FileOperationsEventReceiver::handleSaveRedoOpt, Qt::QueuedConnection); + { + QMutexLocker lk(&undoLock); + undoOpts.insert(QString::number(quintptr(handle.get()), 16), op); + } + copyMoveJob->initArguments(handle); + if (handleCallback) + handleCallback(handle); + FileOperationsEventHandler::instance()->handleJobResult(AbstractJobHandler::JobType::kDeleteType, handle); +} + +void FileOperationsEventReceiver::handleOperationUndoCut(const quint64 windowId, const QList sources, const QUrl target, const AbstractJobHandler::JobFlags flags, AbstractJobHandler::OperatorHandleCallback handleCallback, const QVariantMap &op) +{ + auto handle = doCutFile(windowId, sources, target, flags, handleCallback, false); + if (!handle) + return; + connect(handle.get(), &AbstractJobHandler::requestSaveRedoOperation, this, + &FileOperationsEventReceiver::handleSaveRedoOpt); + { + QMutexLocker lk(&undoLock); + undoOpts.insert(QString::number(quintptr(handle.get()), 16), op); + } + copyMoveJob->initArguments(handle); + if (handleCallback) + handleCallback(handle); + FileOperationsEventHandler::instance()->handleJobResult(AbstractJobHandler::JobType::kCutType, handle); +} } // namespace dfmplugin_fileoperations diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.h b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.h index d691a50512..d64ce2a797 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.h +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.h @@ -185,7 +185,22 @@ public slots: bool handleShortCut(quint64, const QList &urls, const QUrl &rootUrl); bool handleShortCutPaste(quint64, const QList &, const QUrl &target); - + void handleOperationSaveRedoOperations(const QVariantMap values); + void handleOperationCleanByUrls(const QList &urls); + void handleRecoveryOperationRedoRecovery(const quint64 windowId, + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handle); + void handleSaveRedoOpt(const QString &token, const bool moreThanZero); + void handleOperationUndoDeletes(const quint64 windowId, + const QList sources, + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback, + const QVariantMap &op); + void handleOperationUndoCut(const quint64 windowId, + const QList sources, + const QUrl target, + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback, + const QVariantMap &op); private: enum class RenameTypes { kBatchRepalce, @@ -202,6 +217,8 @@ public slots: bool revocation(const quint64 windowId, const QVariantMap &ret, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handle); + bool redo(const quint64 windowId, const QVariantMap &ret, + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handle); bool doRenameFiles(const quint64 windowId, const QList urls, const QPair pair, @@ -221,12 +238,18 @@ public slots: JobHandlePointer doCopyFile(const quint64 windowId, const QList sources, const QUrl target, const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback callbaskHandle); JobHandlePointer doCutFile(quint64 windowId, const QList sources, const QUrl target, const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, - DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback); + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback, + const bool isInit = true); JobHandlePointer doDeleteFile(const quint64 windowId, const QList sources, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback); + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback, + const bool isInit = true); JobHandlePointer doCleanTrash(const quint64 windowId, const QList sources, const DFMBASE_NAMESPACE::AbstractJobHandler::DeleteDialogNoticeType deleteNoticeType, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback); - bool doMkdir(const quint64 windowId, const QUrl url, const QVariant custom, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorCallback callback); + bool doMkdir(const quint64 windowId, const QUrl url, + const QVariant custom, + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorCallback callback, + const bool useUrlPath = false); QString doTouchFilePremature(const quint64 windowId, const QUrl url, const DFMBASE_NAMESPACE::Global::CreateFileType fileType, const QString suffix, const QVariant custom, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorCallback callbackImmediately); @@ -234,12 +257,18 @@ public slots: const QUrl tempUrl, const QString suffix, const QVariant custom, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorCallback callbackImmediately); bool doTouchFilePractically(const quint64 windowId, const QUrl url, const QUrl &tempUrl = QUrl()); - void saveFileOperation(const QList &sourcesUrls, const QList &targetUrls, DFMBASE_NAMESPACE::GlobalEventType type); + void saveFileOperation(const QList &sourcesUrls, const QList &targetUrls, + DFMBASE_NAMESPACE::GlobalEventType type, + const QList &redoSourcesUrls, const QList &redoTargetUrls, + const dfmbase::GlobalEventType redo, + const bool isUndo = false); QUrl checkTargetUrl(const QUrl &url); private: std::unique_ptr copyMoveJob { std::make_unique() }; DFMBASE_NAMESPACE::DialogManager *dialogManager { nullptr }; + QMap undoOpts; + QMutex undoLock; }; } diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/trashfileeventreceiver.cpp b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/trashfileeventreceiver.cpp index 62beab31f9..458ee324fc 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/trashfileeventreceiver.cpp +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/trashfileeventreceiver.cpp @@ -54,7 +54,7 @@ TrashFileEventReceiver::TrashFileEventReceiver(QObject *parent) } JobHandlePointer TrashFileEventReceiver::doMoveToTrash(const quint64 windowId, const QList sources, const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, - DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback) + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback, const bool isInit) { Q_UNUSED(windowId); @@ -92,7 +92,9 @@ JobHandlePointer TrashFileEventReceiver::doMoveToTrash(const quint64 windowId, c if (DialogManagerInstance->showNormalDeleteConfirmDialog(urlsCanTrash) != QDialog::Accepted) return nullptr; } - handle = copyMoveJob->moveToTrash(urlsCanTrash, flags); + handle = copyMoveJob->moveToTrash(urlsCanTrash, flags, isInit); + if (!isInit) + return handle; } if (handleCallback) handleCallback(handle); @@ -100,7 +102,7 @@ JobHandlePointer TrashFileEventReceiver::doMoveToTrash(const quint64 windowId, c } JobHandlePointer TrashFileEventReceiver::doRestoreFromTrash(const quint64 windowId, const QList sources, const QUrl target, - const AbstractJobHandler::JobFlags flags, AbstractJobHandler::OperatorHandleCallback handleCallback) + const AbstractJobHandler::JobFlags flags, AbstractJobHandler::OperatorHandleCallback handleCallback, const bool isInit) { Q_UNUSED(windowId) @@ -108,6 +110,8 @@ JobHandlePointer TrashFileEventReceiver::doRestoreFromTrash(const quint64 window return nullptr; JobHandlePointer handle = copyMoveJob->restoreFromTrash(sources, target, flags); + if (!isInit) + return handle; if (handleCallback) handleCallback(handle); return handle; @@ -297,6 +301,75 @@ void TrashFileEventReceiver::handleOperationCopyFromTrash(const quint64 windowId FileOperationsEventHandler::instance()->handleJobResult(AbstractJobHandler::JobType::kRestoreType, handle); } +void TrashFileEventReceiver::handleSaveRedoOpt(const QString &token, const bool moreThanZero) +{ + QVariantMap ret; + { + QMutexLocker lk(&undoLock); + if (!undoOpts.contains(token)) + return; + ret = undoOpts.take(token); + } + if (ret.isEmpty()) + return; + GlobalEventType undoEventType = static_cast(ret.value("undoevent").value()); + QList undoSources = QUrl::fromStringList(ret.value("undosources").toStringList()); + QList undoTargets = QUrl::fromStringList(ret.value("undotargets").toStringList()); + GlobalEventType redoEventType = static_cast(ret.value("redoevent").value()); + QList redoSources = QUrl::fromStringList(ret.value("redosources").toStringList()); + QList redoTargets = QUrl::fromStringList(ret.value("redotargets").toStringList()); + if (redoEventType == GlobalEventType::kTouchFile && moreThanZero) + return; + // save operation by dbus + QVariantMap values; + values.insert("undoevent", QVariant::fromValue(static_cast(redoEventType))); + values.insert("undosources", QUrl::toStringList(redoSources)); + values.insert("undotargets", QUrl::toStringList(redoTargets)); + values.insert("redoevent", QVariant::fromValue(static_cast(undoEventType))); + values.insert("redosources", QUrl::toStringList(undoSources)); + values.insert("redotargets", QUrl::toStringList(undoTargets)); + dpfSignalDispatcher->publish(GlobalEventType::kSaveRedoOperator, values); +} + +void TrashFileEventReceiver::handleOperationUndoMoveToTrash(const quint64 windowId, + const QList sources, + const AbstractJobHandler::JobFlags flags, + AbstractJobHandler::OperatorHandleCallback handleCallback, + const QVariantMap &op) +{ + auto handle = doMoveToTrash(windowId, sources, flags, handleCallback, false); + + if (!handle) + return; + connect(handle.get(), &AbstractJobHandler::requestSaveRedoOperation, this, + &TrashFileEventReceiver::handleSaveRedoOpt); + { + QMutexLocker lk(&undoLock); + undoOpts.insert(QString::number(quintptr(handle.get()), 16), op); + } + copyMoveJob->initArguments(handle); + if (handleCallback) + handleCallback(handle); + FileOperationsEventHandler::instance()->handleJobResult(AbstractJobHandler::JobType::kMoveToTrashType, handle); +} + +void TrashFileEventReceiver::handleOperationUndoRestoreFromTrash(const quint64 windowId, const QList sources, const QUrl target, const AbstractJobHandler::JobFlags flags, AbstractJobHandler::OperatorHandleCallback handleCallback, const QVariantMap &op) +{ + auto handle = doRestoreFromTrash(windowId, sources, target, flags, handleCallback, false); + if (!handle) + return; + connect(handle.get(), &AbstractJobHandler::requestSaveRedoOperation, this, + &TrashFileEventReceiver::handleSaveRedoOpt); + { + QMutexLocker lk(&undoLock); + undoOpts.insert(QString::number(quintptr(handle.get()), 16), op); + } + copyMoveJob->initArguments(handle); + if (handleCallback) + handleCallback(handle); + FileOperationsEventHandler::instance()->handleJobResult(AbstractJobHandler::JobType::kRestoreType, handle); +} + JobHandlePointer TrashFileEventReceiver::onCleanTrashUrls(const quint64 windowId, const QList sources, const AbstractJobHandler::DeleteDialogNoticeType deleteNoticeType, AbstractJobHandler::OperatorHandleCallback handleCallback) diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/trashfileeventreceiver.h b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/trashfileeventreceiver.h index 17486d7298..9dc2a4ea65 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/trashfileeventreceiver.h +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/trashfileeventreceiver.h @@ -76,6 +76,17 @@ public slots: DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handle, const QVariant custom, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorCallback callback); + void handleSaveRedoOpt(const QString &token, const bool moreThanZero); + void handleOperationUndoMoveToTrash(const quint64 windowId, + const QList sources, + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback, + const QVariantMap &op); + void handleOperationUndoRestoreFromTrash(const quint64 windowId, + const QList sources, const QUrl target, + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback, + const QVariantMap &op); private slots: JobHandlePointer onCleanTrashUrls(const quint64 windowId, const QList sources, const DFMBASE_NAMESPACE::AbstractJobHandler::DeleteDialogNoticeType deleteNoticeType, @@ -85,9 +96,12 @@ private slots: explicit TrashFileEventReceiver(QObject *parent = nullptr); JobHandlePointer doMoveToTrash(const quint64 windowId, const QList sources, const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, - DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback); + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback, + const bool isInit = true); JobHandlePointer doRestoreFromTrash(const quint64 windowId, const QList sources, const QUrl target, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback); + const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback, + const bool isInit = true); JobHandlePointer doCopyFromTrash(const quint64 windowId, const QList sources, const QUrl target, const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlags flags, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handleCallback); JobHandlePointer doCleanTrash(const quint64 windowId, const QList sources, const DFMBASE_NAMESPACE::AbstractJobHandler::DeleteDialogNoticeType deleteNoticeType, @@ -99,6 +113,8 @@ private slots: QSharedPointer copyMoveJob { nullptr }; QSharedPointer trashIterator { nullptr }; QFuture future; + QMap undoOpts; + QMutex undoLock; std::atomic_bool stoped { false }; }; diff --git a/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.cpp b/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.cpp index 5c841daf83..3ec2c7c5a3 100644 --- a/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.cpp +++ b/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.cpp @@ -301,6 +301,12 @@ void FileOperatorProxy::undoFiles(const CanvasView *view) view->winId(), nullptr); } +void FileOperatorProxy::redoFiles(const CanvasView *view) +{ + dpfSignalDispatcher->publish(GlobalEventType::kRedo, + view->winId(), nullptr); +} + void FileOperatorProxy::dropFiles(const Qt::DropAction &action, const QUrl &targetUrl, const QList &urls) { QPair funcData(FileOperatorProxyPrivate::kCallBackPasteFiles, QVariant()); diff --git a/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.h b/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.h index 9ec4359a29..a90f455084 100644 --- a/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.h +++ b/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.h @@ -38,6 +38,7 @@ class FileOperatorProxy : public QObject void showFilesProperty(const CanvasView *view); void sendFilesToBluetooth(const CanvasView *view); void undoFiles(const CanvasView *view); + void redoFiles(const CanvasView *view); void dropFiles(const Qt::DropAction &action, const QUrl &targetUrl, const QList &urls); void dropToTrash(const QList &urls); diff --git a/src/plugins/desktop/core/ddplugin-canvas/view/operator/shortcutoper.cpp b/src/plugins/desktop/core/ddplugin-canvas/view/operator/shortcutoper.cpp index 8e5b733f8b..25c9a75ad5 100644 --- a/src/plugins/desktop/core/ddplugin-canvas/view/operator/shortcutoper.cpp +++ b/src/plugins/desktop/core/ddplugin-canvas/view/operator/shortcutoper.cpp @@ -143,6 +143,9 @@ bool ShortcutOper::keyPressed(QKeyEvent *event) case Qt::Key_D: FileOperatorProxyIns->moveToTrash(view); return true; + case Qt::Key_Y: + FileOperatorProxyIns->redoFiles(view); + return true; default: break; } diff --git a/src/plugins/desktop/ddplugin-organizer/view/collectionview.cpp b/src/plugins/desktop/ddplugin-organizer/view/collectionview.cpp index e81b5d3a49..21b9356de6 100644 --- a/src/plugins/desktop/ddplugin-organizer/view/collectionview.cpp +++ b/src/plugins/desktop/ddplugin-organizer/view/collectionview.cpp @@ -1030,6 +1030,11 @@ bool CollectionViewPrivate::checkTargetEnable(const QUrl &targetUrl) return true; } +void CollectionViewPrivate::redoFiles() +{ + FileOperatorIns->undoFiles(q); +} + void CollectionViewPrivate::updateRowCount(const int &viewHeight, const int &itemHeight) { const int availableHeight = viewHeight - viewMargins.top() - viewMargins.bottom(); @@ -1905,6 +1910,10 @@ void CollectionView::keyPressEvent(QKeyEvent *event) case Qt::Key_Z: d->undoFiles(); return; + case Qt::Key_Y: + // redo + d->redoFiles(); + return; default: break; } diff --git a/src/plugins/desktop/ddplugin-organizer/view/collectionview_p.h b/src/plugins/desktop/ddplugin-organizer/view/collectionview_p.h index 75d1b4a68c..d65b3a6a97 100644 --- a/src/plugins/desktop/ddplugin-organizer/view/collectionview_p.h +++ b/src/plugins/desktop/ddplugin-organizer/view/collectionview_p.h @@ -89,6 +89,7 @@ class CollectionViewPrivate : public QObject void updateDFMMimeData(QDropEvent *event); bool checkTargetEnable(const QUrl &targetUrl); + void redoFiles(); private: void updateRowCount(const int &viewHeight, const int &itemHeight); diff --git a/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.cpp b/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.cpp index 20e4b2c60a..5462a284c6 100644 --- a/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.cpp +++ b/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.cpp @@ -417,6 +417,15 @@ void FileOperatorHelper::renameFilesByCustom(const QWidget *sender, const QList< false); } +void FileOperatorHelper::redoFiles(const FileView *view) +{ + fmInfo() << "Undo files in the directory: " << view->rootUrl(); + auto windowId = WorkspaceHelper::instance()->windowId(view); + + dpfSignalDispatcher->publish(GlobalEventType::kRedo, + windowId, undoCallBack); +} + FileOperatorHelper::FileOperatorHelper(QObject *parent) : QObject(parent) { diff --git a/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.h b/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.h index 281ebb7960..c6f8f7b074 100644 --- a/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.h +++ b/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.h @@ -46,6 +46,7 @@ class FileOperatorHelper : public QObject void renameFilesByReplace(const QWidget *sender, const QList &urlList, const QPair &replacePair); void renameFilesByAdd(const QWidget *sender, const QList &urlList, const QPair &addPair); void renameFilesByCustom(const QWidget *sender, const QList &urlList, const QPair &customPair); + void redoFiles(const FileView *view); private: explicit FileOperatorHelper(QObject *parent = nullptr); @@ -54,6 +55,7 @@ class FileOperatorHelper : public QObject DFMBASE_NAMESPACE::AbstractJobHandler::OperatorCallback callBack; DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback undoCallBack; + DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback redoCallBack; }; #define FileOperatorHelperIns \ diff --git a/src/plugins/filemanager/core/dfmplugin-workspace/utils/shortcuthelper.cpp b/src/plugins/filemanager/core/dfmplugin-workspace/utils/shortcuthelper.cpp index 22efb270bb..94038eba49 100644 --- a/src/plugins/filemanager/core/dfmplugin-workspace/utils/shortcuthelper.cpp +++ b/src/plugins/filemanager/core/dfmplugin-workspace/utils/shortcuthelper.cpp @@ -182,6 +182,12 @@ bool ShortcutHelper::processKeyPressEvent(QKeyEvent *event) moveToTrash(); return true; } + case Qt::Key_Y: + { + // redo + redoFiles(); + return true; + } default: break; } @@ -383,6 +389,11 @@ void ShortcutHelper::cdUp() view->cdUp(); } +void ShortcutHelper::redoFiles() +{ + FileOperatorHelperIns->redoFiles(view); +} + bool ShortcutHelper::reverseSelect() { if (view->selectionMode() == FileView::SingleSelection) diff --git a/src/plugins/filemanager/core/dfmplugin-workspace/utils/shortcuthelper.h b/src/plugins/filemanager/core/dfmplugin-workspace/utils/shortcuthelper.h index 50b93b03a1..d2a0f054b7 100644 --- a/src/plugins/filemanager/core/dfmplugin-workspace/utils/shortcuthelper.h +++ b/src/plugins/filemanager/core/dfmplugin-workspace/utils/shortcuthelper.h @@ -41,6 +41,7 @@ protected slots: void openAction(const QList &urls, const DirOpenMode openMode = DirOpenMode::kOpenInCurrentWindow); void openInTerminal(); void cdUp(); + void redoFiles(); private: bool normalKeyPressEventHandle(const QKeyEvent *event); diff --git a/src/plugins/server/core/serverplugin-core/operationsstackmanagerdbus.cpp b/src/plugins/server/core/serverplugin-core/operationsstackmanagerdbus.cpp index 91dba50911..6f4567e6f4 100644 --- a/src/plugins/server/core/serverplugin-core/operationsstackmanagerdbus.cpp +++ b/src/plugins/server/core/serverplugin-core/operationsstackmanagerdbus.cpp @@ -8,9 +8,7 @@ #include #include - -static constexpr uint8_t kMaxStep { 2 }; - +static constexpr uint8_t kMaxStep { 100 }; OperationsStackManagerDbus::OperationsStackManagerDbus(QObject *parent) : QObject(parent) { @@ -36,3 +34,24 @@ QVariantMap OperationsStackManagerDbus::RevocationOperations() return QVariantMap(); } + +void OperationsStackManagerDbus::SaveRedoOperations(const QVariantMap &values) +{ + while (redoFileOperations.size() >= kMaxStep) + redoFileOperations.pop_front(); + + redoFileOperations.push(values); +} + +QVariantMap OperationsStackManagerDbus::RevocationRedoOperations() +{ + if (redoFileOperations.count() > 0) + return redoFileOperations.pop(); + + return QVariantMap(); +} + +void OperationsStackManagerDbus::CleanOperationsByUrl(const QStringList &urls) +{ + +} diff --git a/src/plugins/server/core/serverplugin-core/operationsstackmanagerdbus.h b/src/plugins/server/core/serverplugin-core/operationsstackmanagerdbus.h index 419314d718..78174a6390 100644 --- a/src/plugins/server/core/serverplugin-core/operationsstackmanagerdbus.h +++ b/src/plugins/server/core/serverplugin-core/operationsstackmanagerdbus.h @@ -22,9 +22,13 @@ public slots: void SaveOperations(const QVariantMap &values); void CleanOperations(); QVariantMap RevocationOperations(); + void SaveRedoOperations(const QVariantMap &values); + QVariantMap RevocationRedoOperations(); + void CleanOperationsByUrl(const QStringList &urls); private: QStack fileOperations; + QStack redoFileOperations; }; #endif // OPERATIONSSTACKMANAGERDBUS_H diff --git a/translations/dde-file-manager.ts b/translations/dde-file-manager.ts index f368c51f93..5a3876656f 100644 --- a/translations/dde-file-manager.ts +++ b/translations/dde-file-manager.ts @@ -3249,126 +3249,136 @@ + Undo + + + + + Redo + + + + New/Search New/Search - + New window New window - + New folder New folder - + Search Search - + New tab New tab - + View View - + Item information Item information - + Help Help - + Keyboard shortcuts Keyboard shortcuts - + Switch display status Switch display status - + Hide item Hide item - + Input in address bar Input in address bar - + Switch to icon view Switch to icon view - + Switch to list view Switch to list view - + Switch to tree view Switch to tree view - + Others Others - + Close Close - + Close current tab Close current tab - + Back Back - + Forward Forward - + Switch to next tab Switch to next tab - + Switch to previous tab Switch to previous tab - + Next file Next file - + Previous file Previous file - + Switch tab by specified number between 1 to 8 Switch tab by specified number between 1 to 8 @@ -4469,28 +4479,28 @@ dfmplugin_fileoperations::FileOperationsEventReceiver - + Rename file error Rename file error - + Failed to create the directory Failed to create the directory - + Failed to create the file Failed to create the file - + link file error link file error - - + + Failed to modify file permissions Failed to modify file permissions diff --git a/translations/dde-file-manager_bo.ts b/translations/dde-file-manager_bo.ts index c5b21b120c..b125756ffb 100644 --- a/translations/dde-file-manager_bo.ts +++ b/translations/dde-file-manager_bo.ts @@ -3249,126 +3249,136 @@ + Undo + + + + + Redo + + + + New/Search གསར་འཛུགས།/བཤེར་འཚོལ། - + New window སྒེའུ་ཁུང་གསར་འཛུགས། - + New folder ཡིག་ཁུག་གསར་འཛུགས། - + Search བཤེར་འཚོལ། - + New tab ཤོག་བྱང་གསར་བཟོ། - + View ལྟ་བཤེར། - + Item information ཡིག་ཆའི་ཆ་འཕྲིན། - + Help རོགས་ལམ་ལག་དེབ། - + Keyboard shortcuts མྱུར་མཐེབ་ཚང་མ། - + Switch display status མངོན་སྟོན་རྣམ་པ་བརྗེ་བ། - + Hide item ཡིབ་པའི་ཡིག་ཆ། - + Input in address bar གནས་ས་ནང་འཇུག - + Switch to icon view རྟགས་རིས་མཐོང་རིས་ལ་བརྗེ་བ། - + Switch to list view རེའུ་མིག་མཐོང་རིས་ལ་བརྗེ་བ། - + Switch to tree view སྡོང་དབྱིབས་མཐོང་རིས་ལ་བརྗེ་བ། - + Others གཞན། - + Close སྒོ་བརྒྱབ། - + Close current tab མིག་སྔའི་ཤོག་བྱང་ཁ་རྒྱོབ། - + Back ཕྱིར་བཤོལ། - + Forward མདུན་སྐྱོད། - + Switch to next tab ཤོག་བྱང་རྗེས་མར་བརྗེ་བ། - + Switch to previous tab ཤོག་བྱང་གོང་མར་བརྗེ་བ། - + Next file ཡིག་ཆ་རྗེས་མ། - + Previous file ཡིག་ཆ་གོང་མ། - + Switch tab by specified number between 1 to 8 1-8བར་དམིགས་འཛུགས་བྱས་པའི་རིམ་པར་བརྗེ་བ། @@ -4469,28 +4479,28 @@ dfmplugin_fileoperations::FileOperationsEventReceiver - + Rename file error ཡིག་ཆའི་བསྐྱར་མིང་ནོར་བ། - + Failed to create the directory དཀར་ཆག་བཟོ་མ་ཐུབ། - + Failed to create the file ཡིག་ཆ་བཟོ་མ་ཐུབ། - + link file error སྦྲེལ་མཐུད་ཡིག་ཆ་ནོར་བ། - - + + Failed to modify file permissions ཡིག་ཆའི་དབང་ཚད་བཅོས་ཐུབ་མ་སོང་། diff --git a/translations/dde-file-manager_ug.ts b/translations/dde-file-manager_ug.ts index beaf2229e3..01dc005d63 100644 --- a/translations/dde-file-manager_ug.ts +++ b/translations/dde-file-manager_ug.ts @@ -3249,126 +3249,136 @@ + Undo + + + + + Redo + + + + New/Search قۇرۇش/ئىزدەش - + New window يېڭى كۆزنەك - + New folder مۇندەرىجە قۇرۇش - + Search ئىزدەش - + New tab يىڭى بەت - + View كۆرۈش - + Item information تەپسىلاتى - + Help ياردەم قوللانمىسى - + Keyboard shortcuts تىز كونۇپكا - + Switch display status كۆرسىتىش ھالىتىنى ئالماشتۇرۇش - + Hide item يوشۇرۇش - + Input in address bar ئادرېس ئىستونىغا كىرگۈزۈش - + Switch to icon view سىنبەلگە كۆرۈنۈشىگە ئالماشتۇرۇش - + Switch to list view تىزىملىك كۆرۈنۈشىگە ئالماشتۇرۇش - + Switch to tree view دەرەخسىمان كۆرۈنۈشكە ئالماشتۇرۇش - + Others باشقىلىرى - + Close تاقاش - + Close current tab نۆۋەتتىكى بەتكۈچى تاقاش - + Back قايتىش - + Forward ئالدىغا - + Switch to next tab كېيىنكى بەتكۈچكە ئالماشتۇرۇش - + Switch to previous tab ئالدىنقى بەتكە ئالمىشىش - + Next file كىيىنكى ھۆججەت - + Previous file ئالدىنقى ھۆججەت - + Switch tab by specified number between 1 to 8 1-8 ئارىلىقىدا بەلگىلەنگەن تەرتىپنى تاللاپ بەتكۈچ ئالماشتۇرۇڭ @@ -4469,28 +4479,28 @@ dfmplugin_fileoperations::FileOperationsEventReceiver - + Rename file error ھۆججەتنى قايتا ناملاشتا خاتالىق كۆرۈلدى - + Failed to create the directory مۇندەرىجە قۇرغىلى بولمىدى - + Failed to create the file ھۆججەت قۇرۇلمىدى - + link file error ئۇلانما ھۆججەتتە خاتالىق كۆرۈلدى - - + + Failed to modify file permissions ھۆججەت ھوقۇقىنى ئۆزگەرتكىلى بولمىدى diff --git a/translations/dde-file-manager_zh_CN.ts b/translations/dde-file-manager_zh_CN.ts index d385dc9a0a..60de448176 100644 --- a/translations/dde-file-manager_zh_CN.ts +++ b/translations/dde-file-manager_zh_CN.ts @@ -3249,126 +3249,136 @@ + Undo + 撤销 + + + + Redo + 重做 + + + New/Search 新建/搜索 - + New window 新建窗口 - + New folder 新建文件夹 - + Search 搜索 - + New tab 新建标签 - + View 视图 - + Item information 文件信息 - + Help 帮助手册 - + Keyboard shortcuts 所有快捷键 - + Switch display status 切换显示状态 - + Hide item 隐藏文件 - + Input in address bar 地址栏输入 - + Switch to icon view 切换到图标视图 - + Switch to list view 切换到列表视图 - + Switch to tree view 切换到树形视图 - + Others 其他 - + Close 关 闭 - + Close current tab 关闭当前标签 - + Back 后退 - + Forward 前进 - + Switch to next tab 切换到下一个标签 - + Switch to previous tab 切换到上一个标签 - + Next file 下一个文件 - + Previous file 上一个文件 - + Switch tab by specified number between 1 to 8 在1-8之间切换标签到指定序号 @@ -4469,28 +4479,28 @@ dfmplugin_fileoperations::FileOperationsEventReceiver - + Rename file error 文件重命名错误 - + Failed to create the directory 目录创建失败 - + Failed to create the file 创建文件失败 - + link file error 链接文件错误 - - + + Failed to modify file permissions 修改文件权限失败 diff --git a/translations/dde-file-manager_zh_HK.ts b/translations/dde-file-manager_zh_HK.ts index 789c367967..3feecdb51c 100644 --- a/translations/dde-file-manager_zh_HK.ts +++ b/translations/dde-file-manager_zh_HK.ts @@ -3249,126 +3249,136 @@ + Undo + + + + + Redo + + + + New/Search 新建/搜索 - + New window 新建窗口 - + New folder 新建文件夾 - + Search 搜索 - + New tab 新建標籤 - + View 視圖 - + Item information 文件訊息 - + Help 幫助手冊 - + Keyboard shortcuts 所有快捷鍵 - + Switch display status 切換顯示狀態 - + Hide item 隱藏文件 - + Input in address bar 地址欄輸入 - + Switch to icon view 切換到圖標視圖 - + Switch to list view 切換到列表視圖 - + Switch to tree view 切換到樹形視圖 - + Others 其他 - + Close 關 閉 - + Close current tab 關閉當前標籤 - + Back 後退 - + Forward 前進 - + Switch to next tab 切換到下一個標籤 - + Switch to previous tab 切換到上一個標籤 - + Next file 下一個文件 - + Previous file 上一個文件 - + Switch tab by specified number between 1 to 8 在1-8之間切換標籤到指定序號 @@ -4469,28 +4479,28 @@ dfmplugin_fileoperations::FileOperationsEventReceiver - + Rename file error 文件重命名錯誤 - + Failed to create the directory 目錄創建失敗 - + Failed to create the file 創建文件失敗 - + link file error 鏈接文件錯誤 - - + + Failed to modify file permissions 修改文件權限失敗 diff --git a/translations/dde-file-manager_zh_TW.ts b/translations/dde-file-manager_zh_TW.ts index 59d4589960..30b76332cb 100644 --- a/translations/dde-file-manager_zh_TW.ts +++ b/translations/dde-file-manager_zh_TW.ts @@ -3249,126 +3249,136 @@ + Undo + + + + + Redo + + + + New/Search 建立/搜尋 - + New window 建立視窗 - + New folder 建立資料夾 - + Search 搜尋 - + New tab 建立標籤 - + View 檢視 - + Item information 文件訊息 - + Help 幫助手冊 - + Keyboard shortcuts 所有快捷鍵 - + Switch display status 切換顯示狀態 - + Hide item 隱藏文件 - + Input in address bar 地址欄輸入 - + Switch to icon view 切換到圖示檢視 - + Switch to list view 切換到列表檢視 - + Switch to tree view 切換到樹形檢視 - + Others 其他 - + Close 關 閉 - + Close current tab 關閉目前標籤 - + Back 後退 - + Forward 前進 - + Switch to next tab 切換到下一個標籤 - + Switch to previous tab 切換到上一個標籤 - + Next file 下一個文件 - + Previous file 上一個文件 - + Switch tab by specified number between 1 to 8 在1-8之間切換標籤到指定序號 @@ -4469,28 +4479,28 @@ dfmplugin_fileoperations::FileOperationsEventReceiver - + Rename file error 文件重新命名錯誤 - + Failed to create the directory 目錄建立失敗 - + Failed to create the file 建立文件失敗 - + link file error 連結文件錯誤 - - + + Failed to modify file permissions 修改文件權限失敗