Interruption des opérations de copie et de renommage de fichiers
Dans les situations où des fichiers volumineux doivent être transférés et où les utilisateurs ont besoin de pouvoir annuler l'opération, le Les méthodes par défaut copy() et rename() proposées par Qt peuvent être limitantes. Le défi réside dans l'interruption de ces processus sans introduire de surcharge de performances significative ni de frustration des utilisateurs.
Interrogation de la prise en charge des interruptions dans Qt
En examinant la documentation de QFile, il devient évident que Qt ne fournit pas de mécanisme intégré pour interrompre les opérations copy() ou rename(). Par conséquent, il est nécessaire d'envisager des stratégies de mise en œuvre personnalisées pour répondre à cette exigence.
Implémentation personnalisée pour l'interruption de copie
Pour créer un assistant de copie non bloquant, une option est pour implémenter un thread dédié ou utiliser le thread principal. Dans les deux cas, une copie fragmentée est nécessaire, où les données sont transférées par morceaux à l'aide d'un tampon. En utilisant un tampon, il est possible de suivre la progression de l'opération et de répondre aux demandes d'annulation des utilisateurs.
Les étapes principales de la mise en œuvre d'un assistant de copie personnalisé peuvent être décrites comme suit :
Implémentez un slot step(), en utilisant QMetaObject::invokeMethod() avec Qt:: QueuedConnection, qui permet le traitement périodique des événements utilisateur. Dans cet emplacement :
Exemple de mise en œuvre
L'extrait de code suivant fournit un exemple d'implémentation d'une classe d'assistance à la copie :
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; };
Conclusion
En implémentant une copie personnalisée helper ou en utilisant l'exemple fourni, il est possible de créer une opération de copie de fichier non bloquante qui peut être interrompue par les utilisateurs. Cette approche permet des transferts de fichiers réactifs et conviviaux, résolvant les frustrations causées par des opérations longues qui ne peuvent pas être annulées.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!