Russian Qt Forum
Ноябрь 25, 2024, 13:56 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Копирование через QFileSystemModel dropmimedata  (Прочитано 4060 раз)
folax
Гость
« : Июнь 08, 2015, 14:57 »

Добрый день. Подскажите пожалуйста, реализовал просмотр файловой системы через QTableView и QFileSystemModel, для копирования и вставки элементов использую 

Код:
QApplication::clipboard()->setMimeData
и
Код:
fileModel->dropMimeData(QApplication::clipboard()->mimeData(), cutOrCopy, 0, 0, qobject_cast<QAbstractItemView *>(focus)->rootIndex());

Вопрос состоит в следующем. При копировании больших файлов, программа зависает до тех пор пока не произойдёт копирование. Как реализовать правильно процесс копирования этого большого файла (в будущем группу файлов) и видеть процесс копирования чтоб потом например его передавать в QProgressBar, и как сделать чтобы программа не зависала.

На второй вопрос есть где то мысль что нужно использовать потоки, но как быть с большим файлов и прогрессом копирования его. Спасибо.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #1 : Июнь 08, 2015, 15:46 »

Да, нужны потоки. Для больших файлов нужен свой класс с двумя QFile. Один для чтения, другой для записи. Данные копировать порциями.
Записан
folax
Гость
« Ответ #2 : Июнь 10, 2015, 14:52 »

Хотел бы спросить совета. Я пока что до потока не дошёл. Сделал так для проверки. Создал класс как вы и советовали с двумя QFile, решил попробовать делать emit для QProgressBar, я разделил файл который копируется на 100 частей, и делаю его копирование по частям и делаю инкремент каждый раз для QProgressBar. Я думал программа не должна виснуть раз создаётся сигнал, по идее должен же передаваться статус из класса в виджет.  А получается класс отработал и сразу показует 100% готовности. Подскажите что делать, реализовать эту процедуру через потоки ? Код ниже, подставляется файл для копирования и указывается путь куда копируется.

Код:
void FilesCopy::loadFile(QString fPath, QString fDest)
{
    if (fPath.isEmpty())
        return;

    //input file;
    QFile inputFile(fPath);
    if (!inputFile.open(QFile::ReadOnly))
    {
        qDebug()<<"Could not open the input file";
    }

    //output file;
    QFileInfo fileInfo(inputFile.fileName());
    QString destination = fDest + (fileInfo.fileName());
    qDebug()<<destination;
    QFile outputFile(destination);
    if (!outputFile.open(QFile::WriteOnly))
    {
        qDebug()<<"Could not open the output file";
    }
    //div file size to 100;
    int copyPart = inputFile.size() / 100;
    int status = 0;

    //if file size bigger then 100mb;
    if (inputFile.size() > 104857600)
    {
        QByteArray dataFromFile;
        qint64 tmp = 0;

        for (int i = 0; i < 100; ++i)
        {
            qDebug()<<i<<" i = "<<inputFile.pos()<<"\n";
            inputFile.seek(tmp);
            tmp += copyPart;
            if (i == 100)
            {
                dataFromFile = inputFile.readAll();
            }
            else
            {
                dataFromFile = inputFile.read(copyPart);
            }
            outputFile.write(dataFromFile);
            dataFromFile.clear();
            ++status;
        }
    }
    else
    {
        QFile::copy(fPath, destination);
        status = 100;
    }
    qDebug()<<outputFile.size()<< "= output file\n";
    qDebug()<<inputFile.size()<<" = input file\n";
    qDebug()<<status;

    outputFile.flush();
    outputFile.close();
    emit copyStatus(status);
}

изображение


код
https://drive.google.com/file/d/0B_J3Y23JUfbmMHdrdGF2OXVJSU0/view?usp=sharing
« Последнее редактирование: Июнь 11, 2015, 10:59 от folax » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #3 : Июнь 10, 2015, 14:56 »

Нужно копирование вынести в поток.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июнь 10, 2015, 15:23 »

Я думал программа не должна виснуть раз создаётся сигнал, по идее должен же передаваться статус из класса в виджет.  А получается класс отработал и сразу показует 100% готовности.
В приведенном коде прогресс обновляется 1 раз (emit в конце) - ну он один раз и покажет. Вставьте эту строку (emit copyStatis) в тело цикла, ++status само по себе UI не обновит
Записан
folax
Гость
« Ответ #5 : Июнь 11, 2015, 14:23 »

Спасибо всем за помощь, получилось, так как и советовали вынес процесс копирования в отдельный слот, в вызывающем классе создал очередь, подключил к слоту очереди процесс копирования, потом запустил саму очередь.
Код:

Код:
void FilesCopy::process()
{
    //div file size to 100;
    int copyPart = inputFile.size() / 100;
    int status = 0;

    //if file size bigger then 100mb;
    if (inputFile.size() > 104857600)
    {
        QByteArray dataFromFile;
        qint64 span = 0;

        for (int i = 0; i < 100; ++i)
        {
            qDebug()<<i<<" i = "<<inputFile.pos()<<"\n";
            inputFile.seek(span);
            span += copyPart;
            if (i == 100)
            {
                dataFromFile = inputFile.readAll();
            }
            else
            {
                dataFromFile = inputFile.read(copyPart);
            }
            outputFile.write(dataFromFile);
            dataFromFile.clear();
            ++status;
            emit copyStatus(status);
        }
    }
    else
    {
        QFile::copy(filePatch, fileDestination);
        status = 100;
    }
    outputFile.flush();
    outputFile.close();
}

С сам поток:
 
Код:
thread = new QThread;

    fc = new FilesCopy();
    connect(fc, SIGNAL(copyStatus(int)), ui->progressBar, SLOT(setValue(int)));
    connect(thread, SIGNAL(started()), fc, SLOT(process()));
    fc->moveToThread(thread);

void Widget::on_copyBtn_clicked()
{
    fc->loadFile(file_Source, file_Destionation);
    thread->start();
}

В перспективе сейчас сделать, так чтобы можно было передавать несколько файлов а не одиночные.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.048 секунд. Запросов: 23.