Bienvenue sur le forum !

Si vous souhaitez rejoindre la communauté, cliquez sur l'un de ces boutons !

Qt 5 : 5.8.0 - Qt Creator : 4.2.2 - Qt Installer : 2.0.3 - JOM : 1.1.2 - Qt Build suite : 1.7.0 - VS Qt 5 : 2.0.0

Selectionner tous les fichiers [QTableView et QFileSystemModel]

December 2011 modifié dans Année 2011
Bonjour à tous !

J'ai besoin de sélectionner tous les fichiers de mon QTableView, qui a pour model un QFileSystemModel.
Le problème est que mon QTableView affiche aussi bien des fichiers que des dossiers. Or, je souhaite sélectionner uniquement les fichiers.

La méthode Qt suivante sélectionne aussi bien les fichiers que les dossiers : c'est pourquoi je pense que je ne peux pas l'utiliser.

tableView->selectAll();
J'ai donc écris une fonction qui parcourt tous les éléments affichés par mon QTableView et sélectionne seulement les fichiers :

//Je récupère le model index root
QModelIndex rootIndex = tableView->rootIndex();

//Si le model index n'est pas valide, j'annule
if(false == rootIndex.isValid())
return;

//Je parcours toutes les lignes à partir du répertoire root
for(int i = 0 ; i < fileSystemModel->rowCount(rootIndex) ; i++)
{
//Je récupère une ligne
QModelIndex currentIndex = fileSystemModel->index(i, 0, rootIndex);
//Si le modelindex est valide, je continue
if(true == currentIndex.isValid())
//Si le modelindex courrant n'est pas un répertoire
if(false == fileSystemModel->fileInfo(currentIndex).isDir())
//Et si il n'est pas deja sélectionné
if(false == tableView->selectionModel()->isSelected(currentIndex))
//Je le sélectionne
tableView->setCurrentIndex(currentIndex);
}
Ce code semble fonctionner. Mais, lorsqu'il s'agit de sélectionner de nombreux fichiers (par exemple 600), la fonction est incroyablement lente...
Elle est beaucoup plus lente que tableView->selectAll() qui elle, s'exécute instantanément.

Avez vous une solution pour soit :
- optimiser mon actuelle fonction ?
- une solution plus simple pour sélectionner tous les fichiers ?

Je vous remercie d'avance !

Réponses

  • December 2011 modifié
    Bonjour,
    j'ai également beaucoup de problèmes avec le system file de Qt qui est assez lent. Un des gros défauts est le isDir() qui demande au système des lstat à répétition. Donc je ne vois pas trop comment optimiser ta fonction actuelle, et je n'ai pas de solution plus simple.
    Je te propose en fait une solution qui pourrait éventuellement améliorer ton opération mais c'est lourd : L'idée serait de garder ton QFileSystemModel et ta vue mappée dessus, et de créer en interne un proxy (QAbstractProxyModel) mappé sur le filesystemodel qui filtre les répertoires. Tu aurais alors 2 modèles reliés avec l'un ne contenant que les fichiers. Tu pourrais alors faire le parcours sur ce proxy sans aucun isDir et retrourner les index du filesystemmodel, obtenus par un mapping depuis le proxy. En gros, le proxy serait rempli silencieusement dès que tu choisis un nouveau rootindex sur ta vue, donc ta fonction de sélection des fichiers serait de suite plus légère. Mais je te l'accorde, c'est prendre un bazooka pour chasser les mouches.


    Edit: petite modification. On peut utiliser comme proxy un QSortFilterProxyModel et surcharger simplement la méthode filterAcceptsRow pour n'accepter que les fichiers.
  • December 2011 modifié
    Je te remercie pour ta réponse.

    Malheureusement, je ne pense pas que la solution que tu proposes puisse améliorer la performance de ma fonction.
    En effet, j'ai trouvé l'origine de la lenteur d'exécution de mon code, il semblerait que cela vienne de l'appel suivant :

    tableView->setCurrentIndex(currentIndex);
    La ligne servant à détecter un répertoire n'affecte pas (ou peu) les performances.

    J'ai donc cherché à utiliser un autre appel pour valider ma sélection.
    Je suis arrivé au code suivant :

    //Je récupère le model index root
    QModelIndex rootIndex = tableView->rootIndex();
    //Si le model index n'est pas valide, j'annule
    if(false == rootIndex.isValid())
    return;

    //Objet pour le stockage de ma sélection
    QItemSelection itemSelection;

    //Je parcours toutes les lignes à partir du répertoire root
    for(int i = 0 ; i < fileSystemModel->rowCount(rootIndex) ; i++)
    {
    //Je récupère une ligne (1ère et dernière colonne)
    QModelIndex indexColumn0 = fileSystemModel->index(i, 0, rootIndex);
    QModelIndex indexColumn3 = fileSystemModel->index(i, 3, rootIndex);

    //Si le modelindex est valide, je continue
    if(true == indexColumn0.isValid() && true == indexColumn3.isValid())
    //Si le modelindex courrant n'est pas un répertoire
    if(false == fileSystemModel->fileInfo(indexColumn0).isDir())
    //Et si il n'est pas deja sélectionné
    if(false == tableView->selectionModel()->isSelected(indexColumn0))
    //Je stocke la nouvelle ligne à sélectionner dans l'objet de sélection
    itemSelection.select(indexColumn0, indexColumn3);
    }

    //J'active la nouvelle sélection
    tableView->selectionModel()->select(itemSelection, QItemSelectionModel::Select);
    Cette nouvelle fonction est plus rapide : environ 1 seconde pour sélectionner 800 fichiers contre plus d'une minute avec la précédente solution.

    Merci pour ton aide !
Connectez-vous ou Inscrivez-vous pour répondre.