Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > Прогресс копирования(сигнал QFile - bytesWritten)


Автор: franzR 23.2.2011, 16:28
Qt 4.7.0, QtCreator 2.0.1, Win XP SP3 (32bit)

Ребят, тут такое дело. 
Не могу понять почему не срабатывает сигнал при копировании. В консоль ничего не пишет. Полазил по инету не смог разрулить, обращаюсь к вам.
Копирование само происходит, а вот прогресс бар не мычит и не телится...

Собственно класс:

.h

Код

#ifndef COPYTHREAD_H
#define COPYTHREAD_H

#include <QThread>
#include <QFile>

class CopyThread : public QThread
{
    Q_OBJECT

public:
    int written;
    void setVariables(QString Ifile, QString Idest);

    void run();
    QFile destCpy;
    QFile fileCpy;
    CopyThread();


private:
    QString file;
    QString dest;



signals:
    void finished();
    void percent(int);
    void report(QString text);

public slots:
    void progres(qint64);
};

#endif // COPYTHREAD_H




.cpp
Код

#include "copythread.h"

CopyThread::CopyThread()
{
}

void CopyThread::progres(qint64 p)
{
   written = p / 1024;
   emit percent(written);
}

void CopyThread::setVariables(QString Ifile, QString Idest)
{
    file = Ifile;
    dest = Idest;
}

void CopyThread::run()
{

    destCpy.setFileName(dest);
    fileCpy.setFileName(file);

    written = 0;

    connect(&fileCpy, SIGNAL(bytesWritten(qint64)), SLOT(progres(qint64)));

    if(fileCpy.copy(destCpy.fileName())){
        emit report("File was copied.");
    }else{
        emit report("ERROR: file wasn't copied!");
    }
}


Запускаю поток так:

Код

thread.setVariables(copyFrom, copyTo);

thread.start();


Ставлю брекпоинт на:
Код

   written = p / 1024;


На место останова никогда не попадаю, значит и emit который далее по тексту не происходит. 

Подскажите что не так сделал... smile 


Автор: bsa 23.2.2011, 20:21
думаю, не будет работать, так как в потоке копирования нет цикла обработки событий (EventLoop).

Автор: alexvs11 23.2.2011, 20:27
для копирования не обязательно новый поток, можно и в один поток с модальным QProgressBar

Автор: Modul 23.2.2011, 23:26
Цитата(franzR @  23.2.2011,  16:28 Найти цитируемый пост)
а вот прогресс бар не мычит и не телится...


А как он у Вас реализован в консоли ? Простите, спросил...

Автор: borisbn 24.2.2011, 03:08
а ты уверен, что ф-ция copy вообще должна выдавать сигнал bytesWritten ?
если реализуешь copy вручную: read из одного, write в другой, то м.б. и будет вызываться

Автор: franzR 24.2.2011, 15:22
Спасибо всем что не остались равнодушными к вопросу! smile 

bsa:
Цитата

думаю, не будет работать, так как в потоке копирования нет цикла обработки событий (EventLoop).

Логично, согласен!

alexvs11:
Цитата

для копирования не обязательно новый поток, можно и в один поток с модальным QProgressBar

это хорошо, но у мну прогресс бар на форме, и хотелось бы его юзать не просто показав что скопировался какой то файл, а вот если он большой то прям весь процесс копирования.

borisbn:
Цитата

а ты уверен, что ф-ция copy вообще должна выдавать сигнал bytesWritten ?
если реализуешь copy вручную: read из одного, write в другой, то м.б. и будет вызываться

Да тут вы совершенно правы QFile не имеет такого сигнала по документации! Хотя при connect выдает в списке доступные сигналы и среди них есть bytesWritten. Странно что при connect не ругается...

borisbn, bsa - спасибо, натолкнули на мысль, буду развивать.

Автор: borisbn 24.2.2011, 15:51
Цитата(franzR @  24.2.2011,  15:22 Найти цитируемый пост)
QFile не имеет такого сигнала по документации!

имеет, т.к. он унаследован от QIODevice, в котором этот сигнал и объявлен
Цитата(franzR @  24.2.2011,  15:22 Найти цитируемый пост)
Странно что при connect не ругается...

потому и не ругается, что всё ОК.

всё-таки попробуй вручную
Цитата(borisbn @  24.2.2011,  03:08 Найти цитируемый пост)
read из одного, write в другой


Автор: franzR 28.2.2011, 15:29
Долго молчал, извиняюсь, подгрузили работой, не было времени разбираться.

Реализовал копирование таким образом:
Код

    qint64 nCopySize = QFileInfo(fileCpy).size();
    qint64 size = 0;
    if(destCpy.exists())
    {
        destCpy.remove();
    }
    if(!destCpy.open(QIODevice::ReadWrite))
    {
        emit report("Can't create file");
    }
    if(!fileCpy.open(QIODevice::ReadOnly))
    {
        emit report("Can't read file");
    }
    while(nCopySize > size)
    {
        if(destCpy.write(fileCpy.read(size)))
        {
            emit report(QString::number(size/divider));
        }
        destCpy.seek(size);
        fileCpy.seek(size);
        size += divider;
        emit percent(size/divider);

    }
    if(nCopySize < size){
        size = size - nCopySize;
        destCpy.write(fileCpy.read(size));
        destCpy.close();
    }else{
        destCpy.close();
    }
    fileCpy.close();



divider - приходит из класса кот. запускает на копирование поток, зависит от размера копируемого файла.

Метод работает медленно до ужаса! С большими файлами жрет оперативу просто капец! Как бы его так оптимизировать чтоб копировалось не хуже чем в Total Comander например или винде?
Там копирование отображает и прогресс, и быстро работает без кушания оперативы...

Автор: borisbn 28.2.2011, 15:34
Для Windows лучше всего использовать winAPI, а именно http://msdn.microsoft.com/en-us/library/aa363852(v=vs.85).aspx
сделать на Qt так же быстро, как в винде и кроссплатформенно, скорее всего не получится.
Если нужно на ОС, отличных от винды - думаю стОит смотреть их API

Автор: franzR 2.3.2011, 11:06
Раз более предложений по копированию нет, то тему можно считать закрытой.

Еще раз спасибо всем кто откликнулся, особенно borisbn!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)