blacksad | Bonjour,
Contexte : j'ai une application Qt/C++ qui me permet de copier des fichiers dans un répertoire que j'ai choisi : j'ai une interface où je rentre le nom du dossier qui contiendra mes fichiers copiés (via QFileDialog::getExistingDirectory()), et un tableu à deux colonnes où je mets d'un coté le nom du fichier à copier ( via QFileDialog::getOpenFileName() ) et de l'autre son état d'avancement. Pour la copie proprement dite, j'appelle un programme C++ externe (nommé ici "copy" ) que je lance en tant que processus (je pourrais faire autrement mais le but de cette application est justement d'apprendre à gérer les processus...). J'ai donc une boucle qui me parcourt mon tableau, et me lance un nouveau processus "copy" tant qu'il y a des fichiers à copier. Jusque là, tout va bien.
Là où ça se corse, c'est pour l'affichage de l'état d'avancement de chaque processus. Au début j'avais fait ça :
Code :
- void CopyBoard::setSource()
- {
- QString source = QFileDialog::getOpenFileName(this);
- listSource->insert(listSource->size(),source);
-
- currentIndice++;
- int i = currentIndice;
- QTableWidgetItem *tableSource = new QTableWidgetItem((*listSource)[i]);
- tableSource->setText((*listSource)[i]);
- table->setItem(i,0,tableSource);
- setEtatQueue();
- }
- /*
- Affiche un explorateur de fichier où l'on chosit le dossier qui contiendra les copies de
- fichier. Affiche le chemin du dossier dans un QLineEdit.
- */
- void CopyBoard::setDestRep()
- {
- QString destRep = QFileDialog::getExistingDirectory(this);
- line->setText(destRep);
- }
- /*
- Met le fichier désigné par "currentIndice" dans l'état "En attente".
- La copie n'a pas été commencée.
- */
- void CopyBoard::setEtatQueue()
- {
- QString etat = "En attente";
- QTableWidgetItem *tableEtat = new QTableWidgetItem(etat);
- tableEtat->setText(etat);
- cout << "attente : " << currentIndice << endl;
- table->setItem(currentIndice,1,tableEtat);
- table->show();
- }
- /*
- Met le fichier désigné par "currentIndice" dans l'état "En cours".
- La copie a commencé.
- */
- void CopyBoard::setEtatRunning()
- {
- QString etat = "En cours";
- QTableWidgetItem *tableEtat = new QTableWidgetItem(etat);
- tableEtat->setText(etat);
- cout << "running : " << currentIndice << endl;
- table->setItem(currentIndice,1,tableEtat);
- table->show();
- }
- /*
- Met le fichier désigné par "currentIndice" dans l'état "Terminé".
- La copie est terminée.
- */
- void CopyBoard::setEtatEnd(int reussite)
- {
- QString etat;
- if (reussite) {etat = "Terminé avec succès";}
- else {etat = "ECHEC !";}
- QTableWidgetItem *tableEtat = new QTableWidgetItem(etat);
- tableEtat->setText(etat);
- cout << "Fin : " << currentIndice << endl;
- table->setItem(currentIndice,1,tableEtat);
- table->show();
- }
- void CopyBoard::copier()
- {
- QString repDest = line->text();
- QString program = "[repertoire du programme de copie]/copy";
-
- for(int i=0; i<listSource->size(); i++)
- {
- currentIndice = i;
- QString source = (*listSource)[i];
- QString dest = repDest + source.right(source.length()-source.lastIndexOf('/')-1);
- //Appel du programme "copy".
- QStringList arguments;
- arguments << source << dest;
- QProcess *myProcess = new QProcess(this);
- myProcess->start(program,arguments);
- connect(myProcess, SIGNAL(started()), this, SLOT(setEtatRunning()));
- connect(myProcess, SIGNAL(finished(int)), this, SLOT(setEtatEnd(int)));
- //myProcess->waitForFinished();
- }
- }
|
Mais le problème eqt au niveau du lancement des signaux lignes 87 et 88. En fait le programme exécute la boucle de la ligne 74 autant de fois qu'il y a de fichiers, puis envoie les signaux started(), puis les signaux finished(), et à ce moment là, mon currentIndice, qui désigne le fichiers en cours de traitement (le ième tour de boucle en fait), est le nombre de fichiers - 1. Et comme les fonctions setEtatRunning() et setEtatEnd() font leurs modifications dans la case désignée par currentIndice, et bien toutes les modifs se font sur la dernière ligne...
J'ai ensuite tenté de "bloquer" ce currentIndice, en ajoutant myProcess->waitForFinished(); à la ligne 90. Les processus se sont bien lancé un par un, les signaux ont bien été envoyés aux bons moments, mais waitForFinished() gèle l'affichage du QWidget, si bien que les modification des changement d'état sont au bon endroit, mais modifiées que lorsque tout est fini...
Dernière tentative, j'ai essayé de remettre à 0 mon currentIndice une fois qu'il a fini tout ses tours de boucle, comme ça la méthode setEtatRunning() se lance avec les bons indices, j'ai fait pareil pour setEtatEnd() , mais les indices ainsi bricolés ne correspondent pas forcément aux indices des processus qui viennent de se terminer : c'est forcément la ligne une qui aura la première l'état "Terminé avec succès", même si la copie du premier fichier est celle qui dure le plus longtemps.
"Et la question dans tout ça, c'est quoi ?"
En fait mes questions sont :
Est-il possible d'identifier quel processus envoie le signal started() ou finished() ? (Comme ça je saurais quelle ligne il faut modifer dans mon tableau)
Actuellement les processus se lancent en parallèle, est il possible de les lancer en série ? (Comme pourrai incrémenter mon currentIndice en sachant qu'un processus ne "doublera" pas l'autre)
Toute autre idée, piste, suggestion pour résoudre mon problème et/ou améliorer mon programme est la bienvenue Merci d'être arrivé jusque là.
Blacksad. Message édité par blacksad le 19-09-2006 à 12:46:11
|