mirror of https://gitee.com/openkylin/peony.git
365 lines
13 KiB
C++
365 lines
13 KiB
C++
/*
|
||
* Peony-Qt's Library
|
||
*
|
||
* Copyright (C) 2020, KylinSoft Co., Ltd.
|
||
*
|
||
* This library is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU Lesser General Public
|
||
* License as published by the Free Software Foundation; either
|
||
* version 3 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
|
||
* Lesser General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this library. If not, see <https://www.gnu.org/licenses/>.
|
||
*
|
||
* Authors: Yue Lan <lanyue@kylinos.cn>
|
||
*
|
||
*/
|
||
|
||
#ifndef FILEOPERATION_H
|
||
#define FILEOPERATION_H
|
||
|
||
#include <QHash>
|
||
#include <QObject>
|
||
#include <QMetaType>
|
||
#include <QRunnable>
|
||
|
||
#include "gerror-wrapper.h"
|
||
#include "gobject-template.h"
|
||
#include "peony-core_global.h"
|
||
#include "file-operation-error-handler.h"
|
||
#include "file-operation-manager.h"
|
||
|
||
namespace Peony {
|
||
|
||
class FileOperationInfo;
|
||
/*!
|
||
* \brief The FileOperation class
|
||
* <br>
|
||
* This class is an interface for several kinds of file operatrion,
|
||
* like move, copy or delete, etc.
|
||
* </br>
|
||
* \details
|
||
* FileOperation specifies a set of signals as an interactive interface.
|
||
* There a mainly two kinds of interface, operation wizard and error handler.
|
||
* Operation Wizard is used to show the operation progess and cancel the operation
|
||
* in ui. Error Handler is used to handle the error when the operation went error.
|
||
* \note
|
||
* You should not use this class and derived classes in main thread.
|
||
* Insteadly, using QThreadPool::start() is the best choice.
|
||
* \see
|
||
* FileOperationProgressWizard, FileOperationErrorHandler, FileOperationErrorDialog.
|
||
*
|
||
* \todo
|
||
* add disk i/o speed computing function, this should be implement by implement
|
||
* gio's progress callback.
|
||
*/
|
||
class PEONYCORESHARED_EXPORT FileOperation : public QObject, public QRunnable
|
||
{
|
||
friend class FileOperationManager;
|
||
Q_OBJECT
|
||
|
||
public:
|
||
explicit FileOperation(QObject *parent = nullptr);
|
||
~FileOperation();
|
||
virtual void run();
|
||
|
||
void setHasError(bool hasError = true);
|
||
bool hasError() {
|
||
return m_has_error;
|
||
}
|
||
|
||
/*!
|
||
* \brief getOperationInfo
|
||
* \return
|
||
* \details
|
||
* This is a virtual function, some derived operation class should override
|
||
* this function.
|
||
* The FileOperation instance will destroy itself when it finished, but its info might not.
|
||
* The FileOperationInfo is a part of peony-qt's undo/redo stack(s). FileOperationManager
|
||
* will manage the stack(s) made up of these info.
|
||
*/
|
||
virtual std::shared_ptr<FileOperationInfo> getOperationInfo() {
|
||
return nullptr;
|
||
}
|
||
|
||
/*!
|
||
* \deprecated
|
||
* \brief setShouldReversible
|
||
* \param reversible
|
||
* \details
|
||
* If operation is reversible, it should support to be undo and redo.
|
||
* \note
|
||
* Even though a operation has been set should reversible, it doesn't mean
|
||
* that it really reversible. For example, if a file was deleted, it can not
|
||
* be undo, so it should not add into operation's history of undo/redo.
|
||
* If you don't hope your operation keep records, just do not set it.
|
||
*/
|
||
void setShouldReversible(bool reversible = true) {
|
||
m_reversible = reversible;
|
||
}
|
||
virtual bool reversible() {
|
||
return m_reversible;
|
||
}
|
||
|
||
bool isCancelled() {
|
||
return m_is_cancelled;
|
||
}
|
||
/* 移动操作是否为copy文件,默认值为false,例如鼠标拖到文件时实际操作为copy,返回true */
|
||
virtual bool isCopyMove(){
|
||
return false;
|
||
}
|
||
|
||
Q_SIGNALS:
|
||
/*!
|
||
* \brief invalidOperation
|
||
* \param message
|
||
* \details
|
||
* Before a file operation start, peony-qt will do some simple checks.
|
||
* If there is an obvious error, the operation will not be performed.
|
||
* For example, copying/moving a file to the same folder, renaming a file
|
||
* with existed name, etc.
|
||
* The operation will send the invalidOperation() signal and skip the fileoperation.
|
||
*/
|
||
void invalidOperation(const QString &message);
|
||
void invalidExited(const QString &message);
|
||
/*!
|
||
* \brief operationStarted
|
||
* <br>
|
||
* This signal should be sent when operation started.
|
||
* when a derived class implement the run() method, it aslo need send this signal
|
||
* to tell other object that the operation has started. it might use block-queue connect
|
||
* for other object prepared.
|
||
* </br>
|
||
*/
|
||
void operationStarted();
|
||
|
||
/*!
|
||
* \brief errored
|
||
* <br>
|
||
* This signal should be sent when a derived class instance went to an gio error.
|
||
* The return value is needed by the instance for the error handling.
|
||
* </br>
|
||
* \param err, the shared_ptr wrapper of GError.
|
||
* \param isCritical, the error is critical and operation should be interrupted now.
|
||
* \return \retval response type for error handling.
|
||
* \note Qt's signal/slot provide a blocking flag to ensure get return value of signal.
|
||
* If you want to get response value rightly, you must connect this signal with
|
||
* Qt::BlockingQueuedConnection flag set. That also limit you use fileoperation and its
|
||
* derived class in main thread.
|
||
*/
|
||
void errored(FileOperationError& error);
|
||
//int errored(const QString &srcUri, const QString &destUri, const Peony::GErrorWrapperPtr &err, bool isCritical = false);
|
||
void FileProgressCallback(const QString &srcUri, const QString &destUri, const QString& icon,
|
||
const qint64& current_file_offset, const qint64& current_file_size);
|
||
|
||
/*!
|
||
* \brief operationRequestShowWizard
|
||
* \details
|
||
* Instead of connect with operationStarted() signal, using operationRequestShowWizard() for showing
|
||
* a wizard is better. Because you might not want to see a wizard in some operation.
|
||
* \note
|
||
* only fallback-move, copy and delete send this signal.
|
||
*/
|
||
void operationRequestShowWizard();
|
||
|
||
/*!
|
||
* \brief operationFallbackRetried
|
||
* \details
|
||
* In peony-qt, we perfer user using native move function for fast moving.
|
||
* Unfortunatly there are many limitration for native move.
|
||
* If a native move is failed for those reasons, the move operation will
|
||
* retry with copy/delete function as fallback, it might cost much more time.
|
||
*/
|
||
void operationFallbackRetried();
|
||
|
||
/*!
|
||
* \brief operationPreparedOne
|
||
* \param srcUri
|
||
* \param destUri
|
||
* \param size
|
||
* \details
|
||
* This signal should be sent when the operation found a file node.
|
||
* The signal reciver will count the received signals count as the total source files count.
|
||
* The total size should also be accumulated.
|
||
*/
|
||
void operationPreparedOne(const QString &srcUri, const qint64 &size);
|
||
|
||
/*!
|
||
* \brief operationPrepared
|
||
* <br>
|
||
* This signal should be sent when the operation ready to handle the files.
|
||
* Before we really handle the files, we might need to do something preparing.
|
||
* For example, a recursively enumerating. We should send this signal when these
|
||
* works have been done.
|
||
* </br>
|
||
*/
|
||
void operationPrepared();
|
||
|
||
/*!
|
||
* \brief operationProgressedOne
|
||
* \param srcUri
|
||
* \param destUri
|
||
* \param size
|
||
* \details
|
||
* This signal should be sent when the operation progressed one files.
|
||
* The receiver could use operationPreparedOne() and operationProgressedOne()
|
||
* to compute the current progress for most of operations.
|
||
*/
|
||
void operationProgressedOne(const QString& srcUri, const QString &destUri, const qint64 &size);
|
||
|
||
/*!
|
||
* \brief operationProgressed
|
||
* <br>
|
||
* This signal should be sent when the operation is half-finished.
|
||
* Some operation, such as move, might be splitted into 2 parts.
|
||
* Copy and delete both spend a while.
|
||
* If the other object doesn't care the next process of unfinished
|
||
* operation, they can connect this signal instead of operationFinished()
|
||
* signal to ignore the next progress, even thought the operation will
|
||
* continue until it really completed.
|
||
* </br>
|
||
*/
|
||
void operationProgressed();
|
||
|
||
/*!
|
||
* \brief operationRollbackedOne
|
||
* \param destUri
|
||
* \param srcUri
|
||
* \details
|
||
* This signal should be sent when the operation had been cancelled,
|
||
* and one file was rollbacked to the state before operation executed.
|
||
* \note
|
||
* The rollback progress is difficult to count.
|
||
* This would mean the progress inaccuracy
|
||
*/
|
||
/*!
|
||
* \brief operationAfterProgressedOne
|
||
* \param srcUri
|
||
* \details
|
||
* This signal is not necerssary by all operations. It is used by some
|
||
* operations that cannot be implemented in one step.
|
||
* For example, a non-native move operation will use recursive copy and delete method.
|
||
* In this case the operationProgressedOne() and operationProgressed() signal would
|
||
* only show the copy states. Use operationAfterProgressedOne() and operationAfterProgressed()
|
||
* for tell others the progress of the move operation's clearing progress.
|
||
*/
|
||
void operationAfterProgressedOne(const QString &srcUri);
|
||
|
||
/*!
|
||
* \brief operationAfterProgressed
|
||
* \details
|
||
* This signal is not necerssary by all operations.
|
||
* If a multi-step operation finished the last operation, it should be sent.
|
||
*/
|
||
void operationAfterProgressed();
|
||
|
||
/*!
|
||
* \brief operationRollbackedOne
|
||
* \param destUri
|
||
* \param srcUri
|
||
* \details
|
||
* In peony-qt, if a file operation was cancelled, it not just simply cancel the operation.
|
||
* In order to maintain the atomicity of the operation, the cancelled operation will try rolling
|
||
* back to previous state. This signal should be sent when a file which had been handled rollbacked.
|
||
*/
|
||
void operationRollbackedOne(const QString &destUri, const QString &srcUri);
|
||
|
||
/*!
|
||
* \brief operationStartRollbacked
|
||
* <br>
|
||
* This signal is used to tell other object that
|
||
* the operation has cancelled and rollbacked, not all operations
|
||
* send should this signal.
|
||
* </br>
|
||
*/
|
||
void operationStartRollbacked();
|
||
|
||
/*!
|
||
* \brief operationStartSnyc
|
||
* <br>
|
||
* This signal is used to tell other object that file operation has finished and start a sync
|
||
* operation.
|
||
* <br>
|
||
*/
|
||
void operationStartSnyc();
|
||
|
||
/*!
|
||
* \brief operationFinished
|
||
* <br>
|
||
* This signal is used to tell other object that the file operation has finished with data synced.
|
||
* Usually, a progress dialog can connect this signal and close itself when the signal triggered.
|
||
* </br>
|
||
*/
|
||
void operationFinished();
|
||
|
||
/**
|
||
* @brief operationPause
|
||
* <br>
|
||
* This signal tells the thread that the current file operation should be paused.
|
||
* </br>
|
||
*/
|
||
void operationPause();
|
||
|
||
/**
|
||
* @brief operationStart
|
||
* <br>
|
||
* This signal tells the thread that the current file operation should resume from its pause.
|
||
* </br>
|
||
*/
|
||
void operationResume();
|
||
|
||
/**
|
||
* @brief operationCancel
|
||
* <br>
|
||
* This signal tells the thread that the current user has chosen to cancel the operation.
|
||
* this signal is used for custom copy operations to release the lock in the thread.
|
||
* </br>
|
||
*/
|
||
void operationCancel();
|
||
|
||
public Q_SLOTS:
|
||
virtual void cancel();
|
||
|
||
protected:
|
||
void fileSync (QString srcFile, QString destFile);
|
||
bool nameIsValid (QString& uri);
|
||
bool makeFileNameValidForDestFS (QString& srcPath, QString& destPath, QString* newFileName);
|
||
|
||
GCancellableWrapperPtr getCancellable() {
|
||
return m_cancellable_wrapper;
|
||
}
|
||
|
||
/*!
|
||
* \brief notifyFileWatcherOperationFinished
|
||
* tell views operation finished.
|
||
*/
|
||
void notifyFileWatcherOperationFinished();
|
||
|
||
/* 发送给dbus服务关于:复制dsps文件时将复制成功文件的原路径和目的路径通过发信号通知WPS,Link to story#11452 */
|
||
void sendSrcAndDestUrisOfCopyDspsFiles();
|
||
|
||
protected:
|
||
bool m_is_pause = false;
|
||
QStringList m_src_uris;
|
||
|
||
QStringList m_srcUrisOfCopyDspsFiles;/* 复制dsps文件的源路径列表 */
|
||
QStringList m_destUrisOfCopyDspsFiles;/* 复制dsps文件的目的路径列表 */
|
||
|
||
private:
|
||
bool m_has_error = false;
|
||
bool m_reversible = false;
|
||
bool m_is_cancelled = false;
|
||
GCancellableWrapperPtr m_cancellable_wrapper = nullptr;
|
||
};
|
||
|
||
}
|
||
|
||
//Q_DECLARE_METATYPE(Peony::FileOperation::ResponseType)
|
||
|
||
#endif // FILEOPERATION_H
|