Я не думаю, что размер файла влияет на продолжительность переименования.
Для копии - Qt не предлагает ничего встроенного, вы должны реализовать его самостоятельно. Ключевым вопросом здесь является то, что вам нужно будет найти способ опроса для отмены копирования непрерывно. Это означает, что вы не можете заблокировать основной поток, чтобы иметь возможность обрабатывать события.
Если вы идете на дополнительный поток, чтобы не реагировать на основной поток или не решили использовать основной поток - в обоих случаях вам понадобится реализовать «фрагментированное» копирование - по одному фрагменту за один раз с использованием буфера, пока файл не будет скопирован или копирование отменено. Это нужно, чтобы обрабатывать пользовательские события и отслеживать ход копирования.
Я предлагаю вам создать класс рабочего помощника-помощника QObject
, который отслеживает имя файла, общий размер, размер буфера, прогресс и очистку от отмены. Тогда будет вопросом, будете ли вы использовать его в основном потоке или в выделенном потоке.
EDIT: Нашел, но лучше дважды проверить это, так как это было сделано в качестве примера и не были тщательно протестированы:
class CopyHelper : public QObject {
Q_OBJECT
Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
public:
CopyHelper(QString sPath, QString dPath, quint64 bSize = 1024 * 1024) :
isCancelled(false), bufferSize(bSize), prog(0.0), source(sPath), destination(dPath), position(0) { }
~CopyHelper() { free(buff); }
qreal progress() const { return prog; }
void setProgress(qreal p) {
if (p != prog) {
prog = p;
emit progressChanged();
}
}
public slots:
void begin() {
if (!source.open(QIODevice::ReadOnly)) {
qDebug() << "could not open source, aborting";
emit done();
return;
}
fileSize = source.size();
if (!destination.open(QIODevice::WriteOnly)) {
qDebug() << "could not open destination, aborting";
// maybe check for overwriting and ask to proceed
emit done();
return;
}
if (!destination.resize(fileSize)) {
qDebug() << "could not resize, aborting";
emit done();
return;
}
buff = (char*)malloc(bufferSize);
if (!buff) {
qDebug() << "could not allocate buffer, aborting";
emit done();
return;
}
QMetaObject::invokeMethod(this, "step", Qt::QueuedConnection);
//timer.start();
}
void step() {
if (!isCancelled) {
if (position < fileSize) {
quint64 chunk = fileSize - position;
quint64 l = chunk > bufferSize ? bufferSize : chunk;
source.read(buff, l);
destination.write(buff, l);
position += l;
source.seek(position);
destination.seek(position);
setProgress((qreal)position/fileSize);
//std::this_thread::sleep_for(std::chrono::milliseconds(100)); // for testing
QMetaObject::invokeMethod(this, "step", Qt::QueuedConnection);
} else {
//qDebug() << timer.elapsed();
emit done();
return;
}
} else {
if (!destination.remove()) qDebug() << "delete failed";
emit done();
}
}
void cancel() { isCancelled = true; }
signals:
void progressChanged();
void done();
private:
bool isCancelled;
quint64 bufferSize;
qreal prog;
QFile source, destination;
quint64 fileSize, position;
char * buff;
//QElapsedTimer timer;
};
Сигнал done()
используется для deleteLater()
копия хелперов/закрыть копию диалог или что угодно. Вы можете включить истекший таймер и использовать его для реализации свойства истекшего времени и расчетного времени. Приостановка - еще одна возможная функция для реализации. Использование QMetaObject::invokeMethod()
позволяет циклу событий периодически обрабатывать пользовательские события, чтобы вы могли отменить и обновить ход, который идет от 0 до 1. Вы можете легко настроить его для перемещения файлов.
Я боялся этого. Просто случай часов, который я бы предпочел провести в другом месте. Я сделаю что-то с шаблоном, который вы предложили, и он должен быть в другом потоке, чтобы гарантировать, что графический интерфейс может обновиться с прогрессом. С яркой стороны я смогу дать конкретный прогресс файла таким образом. – MildWolfie
Что касается rename(), я использую его для перемещения файлов. Когда вы переходите в другой каталог на одном диске, он постоянно, но переход с одного диска на другой занимает много времени в зависимости от размера файла. – MildWolfie
@MildWolfie - Я думаю, что уже сделал что-то подобное, проверит, когда вернусь домой через пару часов. – dtech