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.
  • 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