/*! * * Copyright (c) 2020-2024 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * \file FileHandler.h * \author (last) Behrouz NematiPour * \date (last) 04-Apr-2024 * \author (original) Behrouz NematiPour * \date (original) 26-Aug-2020 * */ #pragma once // Qt #include #include // forward declarations class tst_fileHandler; class QDate; namespace Storage { /*! * \brief The FileHandler class * This class is suppose to be the static class * which contains methods to manipulate files and folders * Since it is static it does not have thread so needs to be used with care * and the classes which are using it need to take care of the threading. */ class FileHandler { // friends friend class ::tst_fileHandler; public: enum FileCopyError_Enums { eOK , eSrcFolderNotExist , eSrcFileNotExist , eDstFolderNotExist , eDstFolderMakeError , eSrcOpenError , eDstOpenError , eSrcReadError , eSrcSymlinkError , eDstWriteError , eDstFlushError , }; public: static void errOut (const QString &vMessage); static bool write (const QString &vFileName, const QString &vContent, bool vAppend = true ); static bool read (const QString &vFileName, QString &vContent, bool vAppend = false); static int backupFile (const QString &vSource); static int copyFolder (const QString &vSource , const QString &vDestination); static int moveFolder (const QString &vSource , const QString &vDestination); static int removeFolder(const QString &vFolder); static int removeFiles (const QStringList &vFolders, const QStringList &vNameFilter, const QDate &vDateOlderThan); static bool makeFolder (const QString &vFolder); static bool isMounted (const QString &vPath, bool *vIsReadOnly = nullptr); static bool tmpUsable (); static QFileInfoList find(const QString &vPath, QStringList vNameFilters, quint8 vRetainPercent); static QFileInfoList find(const QString &vPath, QStringList vNameFilters); static quint64 totalSize(const QFileInfoList &vFileInfoList); static QStringList subFolders(const QString &vFolder); static bool isPathSymLink(const QString &vFilePath); static QString sha256sum( QString vFileName, bool *vOk = nullptr ); /*! * \brief FileHandler::copyFile * \details Copies a file chunk by chunk * \return */ template static int copyFile(const QString &vSource, const QString &vDestination, const QString &vFileName, const NotifierFunction *notifier = nullptr, quint32 vIndex = 0) { FileCopyError_Enums err = eOK; QDir srcDir = QFileInfo (vSource ).absoluteDir(); QDir dstDir = QFileInfo (vDestination ).absoluteDir(); QFile srcFile = QFile (vSource + vFileName); QFile dstFile = QFile (vDestination + vFileName); qint64 totalSize = 0; qint64 copySize = 0; quint32 chunkSize = 1024 * 2; bool createFolder = true; static quint8 mO_CopyPercent = 0; quint8 mC_CopyPercent = 0; if ( isPathSymLink(vSource + vFileName) ) { err = eSrcSymlinkError ; goto lErr; } if ( ! srcDir .exists() ) { err = eSrcFolderNotExist ; goto lErr; } if ( ! srcFile.exists() ) { err = eSrcFileNotExist ; goto lErr; } if ( ! createFolder ) { if ( ! dstDir.exists() ) { err = eDstFolderNotExist ; goto lErr; }} else { if ( ! dstDir.mkpath ( dstDir.path() ) ) { err = eDstFolderMakeError ; goto lErr; }} if ( ! srcFile.open(QIODevice::ReadOnly )) { err = eSrcOpenError ; goto lErr; } if ( ! dstFile.open(QIODevice::WriteOnly )) { err = eDstOpenError ; goto lErr; } totalSize = srcFile.size(); copySize = totalSize; qDebug() << "start ..."; qDebug() << "Src: " << vSource << " " << (totalSize > 1024*1024 ? (totalSize / 1024 / 1024) : (totalSize / 1024)) << (totalSize > 1024*1024 ? "M" : "K" ); qDebug() << "Dst: " << vDestination; while ( copySize ) { char chunkData[chunkSize] = {}; const qint64 readSize = srcFile.read (chunkData, chunkSize); if ( readSize < 0 ) { err = eSrcOpenError ; goto lErr; } const qint64 writeSize = dstFile.write(chunkData, readSize); if ( writeSize < 0 ) { err = eDstWriteError ; goto lErr; } if ( readSize >= chunkSize ) { // a full chunk was available to read copySize -= writeSize; // writeSize; } else { // Not a full chunk available EOF copySize = 0; } mC_CopyPercent = int(((float((totalSize - copySize))) / float(totalSize)) * 100); if ( mO_CopyPercent != mC_CopyPercent ) { mO_CopyPercent = mC_CopyPercent; // qDebug() << "\r" << "%" << mC_CopyPercent; if ( notifier ) { (*notifier )(vIndex, vFileName, mC_CopyPercent); } } } // close source srcFile.close(); //DEBUG qDebug()<< dstFile.fileName() <<" destination file size : " << dstFile.size() << " src==dest ? " << (dstFile.size() == totalSize); // close destination if ( ! dstFile.flush() ) { err = eDstFlushError ; goto lErr; } dstFile.close(); qDebug() << "\nFinish"; return eOK; lErr: qDebug() << "\nError: " << err; return err; } }; }