Qt copy File in the Thread

  1. main.cpp
  2. copyfile.h
  3. copyfile.cpp
  4. wrapcopyfile.h
  5. wrapcopyfile.cpp
  6. mainwindow.h
  7. mainwindow.cpp
  8. How it works
  9. Source Code

main.cpp

#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <QtCore>
#include <QtGlobal>
#include <QObject>
#include "wrapcopyfile.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    #ifdef Q_OS_WIN

    qDebug() << "Copy & Freeze";
    CopyFile * cf = new CopyFile(0);
    cf->copy("D:/tools/linuxmint-17.2-mate-64bit.iso",
        "C:/Users/Rolandas/Downloads/linuxmint-17.2-mate-64bit.iso");
    cf->start();
    qDebug() << cf->getStatus();
    cf->~CopyFile();

    qDebug() << "Copy & Run";
    WrapCopyFile * wcf = new WrapCopyFile(0,"D:/tools/linuxmint-17.3-mate-64bit.iso",
        "C:/Users/Rolandas/Downloads/linuxmint-17.3-mate-64bit.iso");
    wcf->~WrapCopyFile();

    #endif //Q_OS_WIN

    #ifdef Q_OS_LINUX

    qDebug() << "Copy & Freeze";
    CopyFile * cf = new CopyFile(0);
    cf->copy("/media/VolumeA/torrent/linuxmint-17.3-mate-32bit.iso",
        "/tmp/linuxmint-17.3-mate-32bit-v2.iso");
    cf->start();
    qDebug() << cf->getStatus();
    cf->~CopyFile();

    qDebug() << "Copy & Run";
    WrapCopyFile * wcf = new WrapCopyFile(0,"/media/VolumeA/torrent/linuxmint-17.3-mate-64bit.iso",
        "/tmp/linuxmint-17.3-mate-64bit-v2.iso");
    if(wcf){;}
    #endif //Q_OS_LINUX

    return a.exec();
}
                

copyfile.h

#ifndef COPYFILE_H
#define COPYFILE_H

#include <QObject>
#include <QDebug>
#include <QFile>
#include <QDateTime>

class CopyFile : public QObject
{
    Q_OBJECT
public:
    explicit CopyFile(QObject *parent = 0);
    ~CopyFile();

    void copy(QString src, QString dst);

    bool getStatus(void);

signals:
    void done();

public slots:
    void start(void);

private:
    QString v_src;
    QString v_dst;
    bool v_status;

};

#endif // COPYFILE_H
                

copyfile.cpp

#include "copyfile.h"

CopyFile::CopyFile(QObject *parent) : QObject(parent)
{
    qDebug() << this << "Created";
}

CopyFile::~CopyFile()
{
    qDebug() << this << "Destroyed";
}

void CopyFile::copy(QString src, QString dst)
{

    v_src = src;
    v_dst = dst;

}

void CopyFile::start(void)
{
    if((!v_src.isEmpty())&&(!v_dst.isEmpty()))
    {
        if(QFile::exists(v_src) && !QFile::exists(v_dst))
        {
            qint64 begin = QDateTime::currentMSecsSinceEpoch();
            v_status = QFile::copy(v_src,v_dst);
            qint64 end = QDateTime::currentMSecsSinceEpoch();
            qDebug() << (end - begin) << "ms";
            emit done();
        }
    }
}

bool CopyFile::getStatus(void)
{
    return v_status;
}
                

wrapcopyfile.h

#ifndef WRAPCOPYFILE_H
#define WRAPCOPYFILE_H

#include <QObject>
#include <QThread>
#include <QDebug>
#include "copyfile.h"


class WrapCopyFile : public QObject
{
    Q_OBJECT
public:
    explicit WrapCopyFile(QObject *parent = 0, QString src = "", QString dst = "");
    ~WrapCopyFile();

signals:

public slots:
    void finished(void);

private:
    QThread * v_thread;
    CopyFile * v_copyFile;
};

#endif // WRAPCOPYFILE_H
                

wrapcopyfile.cpp

#include "wrapcopyfile.h"

WrapCopyFile::WrapCopyFile(QObject *parent, QString src, QString dst) : QObject(parent)
{

    qDebug() << this << "Created";

    this->v_thread = new QThread();
    this->v_copyFile = new CopyFile();
    this->v_copyFile->copy(src,dst);

    connect(v_thread,SIGNAL(started()),v_copyFile,SLOT(start()));
    connect(v_copyFile,SIGNAL(done()),v_thread,SLOT(quit()));
    connect(v_thread,SIGNAL(finished()),this,SLOT(finished()));

    this->v_copyFile->moveToThread(this->v_thread);
    this->v_thread->start();
}

WrapCopyFile::~WrapCopyFile(void)
{
    delete this->v_thread;
    delete this->v_copyFile;
    qDebug() << this << "Destroyed";
}

void WrapCopyFile::finished(void)
{

    qDebug() << this << "Finished" << this->v_copyFile->getStatus();
    this->~WrapCopyFile();
}
                

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
                

                

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    qDebug() << this << "clicked";
}
                
                

How it works

Playing with threads the key things is to make sure it finished and destroyed correctly. I chose copy large file on purpose. It is more clear how it works when thread works for at least couple seconds. Most examples do math in the thread and thread job last only milliseconds and then you can be sure it lock something or not. Making thread dynamically and destroying with the object after thread work is done is good, because if you made the mistake it most likely will crash your program, and you will be able to see it. Much worse if it sill runs in the background, while you think it's finished.

qDebug output:

Copy & Freeze
CopyFile(0x140ac50) Created
22623 ms
true
CopyFile(0x140ac50) Destroyed
Copy & Run
WrapCopyFile(0x140a7a0) Created
CopyFile(0x140a640) Created
MainWindow(0x7ffe2e3450c0, name = "MainWindow") clicked
MainWindow(0x7ffe2e3450c0, name = "MainWindow") clicked
MainWindow(0x7ffe2e3450c0, name = "MainWindow") clicked
MainWindow(0x7ffe2e3450c0, name = "MainWindow") clicked
29832 ms
WrapCopyFile(0x140a7a0) Finished true
CopyFile(0x140a640) Destroyed
WrapCopyFile(0x140a7a0) Destroyed
                

During copy & Freeze stage, imposible to click PushButton

qtCopyFileInThread/freeze.png

During copy & run stage, copying executed in separate thread, and PushButton can be clicked!

qtCopyFileInThread/run.png

Source Code

Download here