Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QFile copy multiple files progress bar
Forum Updated to NodeBB v4.3 + New Features

QFile copy multiple files progress bar

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 5 Posters 7.3k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • E Offline
    E Offline
    Eligijus
    wrote on last edited by
    #1

    I copy a bunch of files from one location to another. File paths are stored in QStringlist and I iterate over list using for loop and copy files using QFile::copy. I want to have some kind of progress bar but when I tried to implement one but it didn't refresh. The gui locked up and only refreshed after all files were copied.
    Is there a way to prevent gui from locking up so progress bar can refresh?

    JonBJ 1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi
      The quick hax is to call QApplication::processEvents()
      http://www.informit.com/articles/article.aspx?p=1405544&seqNum=3

      A more solid way is to use a worker thread and signal to it pr file and
      update the progressbar. As far as i know QFile can be used in another thread.

      1 Reply Last reply
      3
      • E Eligijus

        I copy a bunch of files from one location to another. File paths are stored in QStringlist and I iterate over list using for loop and copy files using QFile::copy. I want to have some kind of progress bar but when I tried to implement one but it didn't refresh. The gui locked up and only refreshed after all files were copied.
        Is there a way to prevent gui from locking up so progress bar can refresh?

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #3

        @Eligijus
        Do you intend a progressbar which shows progress through how many files have been copied (i.e. just updated a fixed amount after each file copy completed), or which updates during each file's copy progress (e.g. based on total number of bytes copied)? This will be relevant for whatever solution.

        E 1 Reply Last reply
        2
        • JonBJ JonB

          @Eligijus
          Do you intend a progressbar which shows progress through how many files have been copied (i.e. just updated a fixed amount after each file copy completed), or which updates during each file's copy progress (e.g. based on total number of bytes copied)? This will be relevant for whatever solution.

          E Offline
          E Offline
          Eligijus
          wrote on last edited by
          #4

          @JNBarchan shows progress of how many files have been copied. I.e. I have 100 files and progress bar will go from 1 to 100 incrementing by 1 after a file has been successfully copied.

          JonBJ 1 Reply Last reply
          0
          • E Eligijus

            @JNBarchan shows progress of how many files have been copied. I.e. I have 100 files and progress bar will go from 1 to 100 incrementing by 1 after a file has been successfully copied.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @Eligijus
            So you only need to update progressbar outside of any QFile::copy, in between each call, which makes it much simpler. Show us your attempt "but when I tried to implement one but it didn't refresh"? In some shape or form, it's not getting refreshed while you keep doing copy code, the UI isn't getting any update time till afterwards....

            E 1 Reply Last reply
            0
            • JonBJ JonB

              @Eligijus
              So you only need to update progressbar outside of any QFile::copy, in between each call, which makes it much simpler. Show us your attempt "but when I tried to implement one but it didn't refresh"? In some shape or form, it's not getting refreshed while you keep doing copy code, the UI isn't getting any update time till afterwards....

              E Offline
              E Offline
              Eligijus
              wrote on last edited by
              #6

              @JNBarchan I'm updating progressbar in qml

              for (var i = 0; i < files.length; ++i) {
              	progressBar.value = i
              	manager.copy(sourcePath + files[i],destPath + files[i])
              }
              

              I can't provide c++ widget version at the moment I'll have to write something up.
              But I guess @mrjj answer is valid here. I either have to call processEvents or move copying to another thread.

              mrjjM 1 Reply Last reply
              1
              • E Eligijus

                @JNBarchan I'm updating progressbar in qml

                for (var i = 0; i < files.length; ++i) {
                	progressBar.value = i
                	manager.copy(sourcePath + files[i],destPath + files[i])
                }
                

                I can't provide c++ widget version at the moment I'll have to write something up.
                But I guess @mrjj answer is valid here. I either have to call processEvents or move copying to another thread.

                mrjjM Offline
                mrjjM Offline
                mrjj
                Lifetime Qt Champion
                wrote on last edited by
                #7

                @Eligijus
                Yep that should make it update pr file.
                Make sure to read link about blocking user input so its not possible to choose exit while copying.

                1 Reply Last reply
                3
                • E Offline
                  E Offline
                  Eligijus
                  wrote on last edited by
                  #8

                  This is the solution I came up with. Maybe someone will find it useful.

                  class Copier : public QThread
                  {
                      Q_OBJECT
                      Q_PROPERTY(double minimum READ minimum NOTIFY minimumChanged)
                      Q_PROPERTY(double maximum READ maximum NOTIFY maximumChanged)
                      Q_PROPERTY(double progress READ progress NOTIFY progressChanged)
                  
                  public:
                      Copier(QObject *parent = nullptr);
                  
                      Q_INVOKABLE void copy(const QString &sourceFolder, const QString &destFolder);
                      double minimum() const;
                      double maximum() const;
                      double progress() const;
                  
                  signals:
                      void minimumChanged(double minimum);
                      void maximumChanged(double maximum);
                      void progressChanged(double value);
                  
                  private:
                      QStringList getFolderContents(const QString &sourceFolder) const;
                      qint64 fileSize(const QString &sourceFolder, const QStringList &fileList);
                      void copyFiles();
                  
                      virtual void run() Q_DECL_OVERRIDE;
                  
                      QString mSourceFolder;
                      QString mDestFolder;
                      QStringList mFileList;
                      double mMinimum;
                      double mMaximum;
                      double mProgress;
                  };
                  
                  Copier::Copier(QObject *parent)
                      : QThread(parent),
                        mMinimum(0), mMaximum(0), mProgress(0)
                  {
                  
                  }
                  
                  void Copier::copy(const QString &sourceFolder, const QString &destFolder)
                  {
                      mSourceFolder = sourceFolder;
                      mDestFolder = destFolder;
                      mFileList = getFolderContents(sourceFolder);
                      mMinimum = 0;
                      mMaximum = fileSize(sourceFolder, mFileList);
                      emit minimumChanged(mMinimum);
                      emit maximumChanged(mMaximum);
                  
                      if (!isRunning())
                          start();
                  }
                  
                  double Copier::minimum() const
                  {
                      return mMinimum;
                  }
                  
                  double Copier::maximum() const
                  {
                      return mMaximum;
                  }
                  
                  double Copier::progress() const
                  {
                      return mProgress;
                  }
                  
                  QStringList Copier::getFolderContents(const QString &sourceFolder) const
                  {
                      QStringList fileList;
                      std::function<bool(const QString&, const QString&)> folderContents;
                      folderContents = [&](const QString &sourceFolder, const QString &destFolder)->bool {
                          QDir sourceDir(sourceFolder);
                  
                          if (!sourceDir.exists())
                              return false;
                  
                          foreach (const QFileInfo &fileInfo, sourceDir.entryInfoList(QDir::NoDotAndDotDot | QDir::NoSymLinks
                                                                                      | QDir::Dirs | QDir::Files)) {
                              QString srcFilePath = fileInfo.filePath();
                              QString dstFilePath = destFolder.isEmpty() ? fileInfo.fileName() : destFolder + QDir::separator() + fileInfo.fileName();
                              if (fileInfo.isDir()) {
                                  if (!folderContents(srcFilePath, dstFilePath))
                                      return false;
                              } else {
                                  fileList.append(dstFilePath);
                              }
                          }
                  
                          return true;
                      };
                  
                      if (folderContents(sourceFolder, QString()))
                          return fileList;
                      else
                          return QStringList();
                  }
                  
                  qint64 Copier::fileSize(const QString &sourceFolder, const QStringList &fileList)
                  {
                      qint64 total = 0;
                  
                      foreach (const QString &fileName, fileList)
                          total += QFile(sourceFolder + QDir::separator() + fileName).size();
                  
                      return total;
                  }
                  
                  void Copier::copyFiles()
                  {
                      qint64 bufferSize = 4194304;
                      QByteArray buffer;
                      mProgress = 0;
                      emit progressChanged(mProgress);
                  
                      foreach (const QString &fileName, mFileList) {
                          QString srcFilePath = mSourceFolder + QDir::separator() + fileName;
                          QString dstFilePath = mDestFolder + QDir::separator() + fileName;
                          QFile srcFile(srcFilePath);
                          QFile dstFile(dstFilePath);
                  
                          QFileInfo dst(dstFilePath);
                          QDir dir = dst.dir();
                          if (!dst.isDir() && !dir.exists())
                              dir.mkpath(dir.path());
                  
                          if (srcFile.open(QIODevice::ReadOnly) && dstFile.open(QIODevice::WriteOnly)) {
                              qint64 internalBufferSize = srcFile.size() < bufferSize ? srcFile.size() : bufferSize;
                  
                              while (1) {
                                  buffer = srcFile.read(internalBufferSize);
                                  if (buffer.isEmpty())
                                      break;
                  
                                  dstFile.write(buffer);
                                  mProgress += internalBufferSize;
                                  emit progressChanged(mProgress);
                              }
                              srcFile.close();
                              dstFile.close();
                          }
                      }
                  }
                  
                  void Copier::run()
                  {
                      copyFiles();
                  }
                  
                  Window {
                      visible: true
                      width: 640
                      height: 480
                      title: qsTr("Hello World")
                  
                  
                      ProgressBar {
                          id: control
                          x: 50
                          y: 50
                          width: 400
                          height: 100
                          padding: 2
                          from: copier.minimum
                          to: copier.maximum
                          value: copier.progress
                  
                          background: Rectangle {
                              color: "black"
                          }
                  
                          contentItem: Item {
                              Rectangle {
                                  width: control.visualPosition * parent.width
                                  height: parent.height
                                  color: "red"
                              }
                          }
                      }
                      Copier {
                          id: copier
                      }
                  
                      Button {
                          anchors.top: control.bottom
                          anchors.topMargin: 50
                          anchors.right: control.right
                          text: "copy"
                          onClicked: {
                              copier.copy("/home/eligijus/BigDisk/testArea/testArea", "/media/eligijus/usb")
                          }
                      }
                  }
                  
                  R 1 Reply Last reply
                  2
                  • E Eligijus

                    This is the solution I came up with. Maybe someone will find it useful.

                    class Copier : public QThread
                    {
                        Q_OBJECT
                        Q_PROPERTY(double minimum READ minimum NOTIFY minimumChanged)
                        Q_PROPERTY(double maximum READ maximum NOTIFY maximumChanged)
                        Q_PROPERTY(double progress READ progress NOTIFY progressChanged)
                    
                    public:
                        Copier(QObject *parent = nullptr);
                    
                        Q_INVOKABLE void copy(const QString &sourceFolder, const QString &destFolder);
                        double minimum() const;
                        double maximum() const;
                        double progress() const;
                    
                    signals:
                        void minimumChanged(double minimum);
                        void maximumChanged(double maximum);
                        void progressChanged(double value);
                    
                    private:
                        QStringList getFolderContents(const QString &sourceFolder) const;
                        qint64 fileSize(const QString &sourceFolder, const QStringList &fileList);
                        void copyFiles();
                    
                        virtual void run() Q_DECL_OVERRIDE;
                    
                        QString mSourceFolder;
                        QString mDestFolder;
                        QStringList mFileList;
                        double mMinimum;
                        double mMaximum;
                        double mProgress;
                    };
                    
                    Copier::Copier(QObject *parent)
                        : QThread(parent),
                          mMinimum(0), mMaximum(0), mProgress(0)
                    {
                    
                    }
                    
                    void Copier::copy(const QString &sourceFolder, const QString &destFolder)
                    {
                        mSourceFolder = sourceFolder;
                        mDestFolder = destFolder;
                        mFileList = getFolderContents(sourceFolder);
                        mMinimum = 0;
                        mMaximum = fileSize(sourceFolder, mFileList);
                        emit minimumChanged(mMinimum);
                        emit maximumChanged(mMaximum);
                    
                        if (!isRunning())
                            start();
                    }
                    
                    double Copier::minimum() const
                    {
                        return mMinimum;
                    }
                    
                    double Copier::maximum() const
                    {
                        return mMaximum;
                    }
                    
                    double Copier::progress() const
                    {
                        return mProgress;
                    }
                    
                    QStringList Copier::getFolderContents(const QString &sourceFolder) const
                    {
                        QStringList fileList;
                        std::function<bool(const QString&, const QString&)> folderContents;
                        folderContents = [&](const QString &sourceFolder, const QString &destFolder)->bool {
                            QDir sourceDir(sourceFolder);
                    
                            if (!sourceDir.exists())
                                return false;
                    
                            foreach (const QFileInfo &fileInfo, sourceDir.entryInfoList(QDir::NoDotAndDotDot | QDir::NoSymLinks
                                                                                        | QDir::Dirs | QDir::Files)) {
                                QString srcFilePath = fileInfo.filePath();
                                QString dstFilePath = destFolder.isEmpty() ? fileInfo.fileName() : destFolder + QDir::separator() + fileInfo.fileName();
                                if (fileInfo.isDir()) {
                                    if (!folderContents(srcFilePath, dstFilePath))
                                        return false;
                                } else {
                                    fileList.append(dstFilePath);
                                }
                            }
                    
                            return true;
                        };
                    
                        if (folderContents(sourceFolder, QString()))
                            return fileList;
                        else
                            return QStringList();
                    }
                    
                    qint64 Copier::fileSize(const QString &sourceFolder, const QStringList &fileList)
                    {
                        qint64 total = 0;
                    
                        foreach (const QString &fileName, fileList)
                            total += QFile(sourceFolder + QDir::separator() + fileName).size();
                    
                        return total;
                    }
                    
                    void Copier::copyFiles()
                    {
                        qint64 bufferSize = 4194304;
                        QByteArray buffer;
                        mProgress = 0;
                        emit progressChanged(mProgress);
                    
                        foreach (const QString &fileName, mFileList) {
                            QString srcFilePath = mSourceFolder + QDir::separator() + fileName;
                            QString dstFilePath = mDestFolder + QDir::separator() + fileName;
                            QFile srcFile(srcFilePath);
                            QFile dstFile(dstFilePath);
                    
                            QFileInfo dst(dstFilePath);
                            QDir dir = dst.dir();
                            if (!dst.isDir() && !dir.exists())
                                dir.mkpath(dir.path());
                    
                            if (srcFile.open(QIODevice::ReadOnly) && dstFile.open(QIODevice::WriteOnly)) {
                                qint64 internalBufferSize = srcFile.size() < bufferSize ? srcFile.size() : bufferSize;
                    
                                while (1) {
                                    buffer = srcFile.read(internalBufferSize);
                                    if (buffer.isEmpty())
                                        break;
                    
                                    dstFile.write(buffer);
                                    mProgress += internalBufferSize;
                                    emit progressChanged(mProgress);
                                }
                                srcFile.close();
                                dstFile.close();
                            }
                        }
                    }
                    
                    void Copier::run()
                    {
                        copyFiles();
                    }
                    
                    Window {
                        visible: true
                        width: 640
                        height: 480
                        title: qsTr("Hello World")
                    
                    
                        ProgressBar {
                            id: control
                            x: 50
                            y: 50
                            width: 400
                            height: 100
                            padding: 2
                            from: copier.minimum
                            to: copier.maximum
                            value: copier.progress
                    
                            background: Rectangle {
                                color: "black"
                            }
                    
                            contentItem: Item {
                                Rectangle {
                                    width: control.visualPosition * parent.width
                                    height: parent.height
                                    color: "red"
                                }
                            }
                        }
                        Copier {
                            id: copier
                        }
                    
                        Button {
                            anchors.top: control.bottom
                            anchors.topMargin: 50
                            anchors.right: control.right
                            text: "copy"
                            onClicked: {
                                copier.copy("/home/eligijus/BigDisk/testArea/testArea", "/media/eligijus/usb")
                            }
                        }
                    }
                    
                    R Offline
                    R Offline
                    Raghavendra Surpur
                    wrote on last edited by
                    #9

                    Hi All,

                    I have used Qt 5.7.1 , i have created GUI application in that one of the screen having file copy . When clicked that button file will be copy from source to destination with progress bar , So how to create this please give me any suggestion

                    Thanks,
                    RYS

                    mrjjM 1 Reply Last reply
                    0
                    • R Raghavendra Surpur

                      Hi All,

                      I have used Qt 5.7.1 , i have created GUI application in that one of the screen having file copy . When clicked that button file will be copy from source to destination with progress bar , So how to create this please give me any suggestion

                      Thanks,
                      RYS

                      mrjjM Offline
                      mrjjM Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      @Raghavendra-Surpur

                      Hi and welcome.
                      For a fast solution, simply use QFile
                      QFile::copy("/path/file", "/path/copy-of-file");

                      Progressbar is not possible.

                      If you really want progressbar that can update while copying, you must write your own file copy function.

                      https://stackoverflow.com/questions/10195343/copy-a-file-in-a-sane-safe-and-efficient-way

                      S 1 Reply Last reply
                      3
                      • mrjjM mrjj

                        @Raghavendra-Surpur

                        Hi and welcome.
                        For a fast solution, simply use QFile
                        QFile::copy("/path/file", "/path/copy-of-file");

                        Progressbar is not possible.

                        If you really want progressbar that can update while copying, you must write your own file copy function.

                        https://stackoverflow.com/questions/10195343/copy-a-file-in-a-sane-safe-and-efficient-way

                        S Offline
                        S Offline
                        surfzoid
                        wrote on last edited by
                        #11

                        @mrjj said in QFile copy multiple files progress bar:

                        @Raghavendra-Surpur

                        Hi and welcome.
                        For a fast solution, simply use QFile
                        QFile::copy("/path/file", "/path/copy-of-file");

                        Progressbar is not .

                        If you really want progressbar that can update while copying, you must write your own file copy function.

                        https://stackoverflow.com/questions/10195343/copy-a-file-in-a-sane-safe-and-efficient-way

                        Hi,
                        is Progressbar possible ? if
                        Qfile *FsCopy = new Qfile;
                        FsCopy.copy("/path/file", "/path/copy-of-file");

                        JonBJ 1 Reply Last reply
                        0
                        • S surfzoid

                          @mrjj said in QFile copy multiple files progress bar:

                          @Raghavendra-Surpur

                          Hi and welcome.
                          For a fast solution, simply use QFile
                          QFile::copy("/path/file", "/path/copy-of-file");

                          Progressbar is not .

                          If you really want progressbar that can update while copying, you must write your own file copy function.

                          https://stackoverflow.com/questions/10195343/copy-a-file-in-a-sane-safe-and-efficient-way

                          Hi,
                          is Progressbar possible ? if
                          Qfile *FsCopy = new Qfile;
                          FsCopy.copy("/path/file", "/path/copy-of-file");

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by
                          #12

                          @surfzoid
                          No QFile::copy() methods emit signals for progress. You would need to do your own (just two QFiles) and emit a signal as you go. @mrjj wrote this just above.

                          1 Reply Last reply
                          1

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved