Comment actualiser un QFileSystemModel dans un QTreeView après la modification des fichiers via un autre processus ?
-
24-12-2019 - |
Question
j'ai un QTreeView
avec un QFileSystemModel
comme modèle.Les fichiers et répertoires se chargent correctement.
Dans le flux de travail de mon application, un processus différent copie et écrase les fichiers sur le système de fichiers.
Cependant, mon QTreeView
ne met pas à jour l'élément/la ligne du fichier écrasé (par exemple :les valeurs size et lastModified du fichier ne sont pas mises à jour avec les nouvelles valeurs).
En utilisant le chemin du fichier, je peux obtenir un FileInfo
qui a la valeur lastModified mise à jour.Cependant, en utilisant cela même chemin pour saisir le QModelIndex
de la valeur lastModified de la ligne entraîne le retour de l'ancienne valeur.
J'ai essayé quelques choses (voir ci-dessous) en vain.
VEUILLEZ me faire savoir si vous savez comment résoudre ce problème.Merci beaucoup!:)
// ... at this point the file system has been updated and the file
// has new values for things like last modified date
QFileInfo *updatedFile = new QFileInfo( filePath );
QModelIndex indexOfFileName = myFileTreeView->myFileSystemModel->index( filePath );
QModelIndex indexOfLastModifiedDate = myFileTreeView->myFileSystemModel->index( filePath, lastModifiedColumnIndex );
// attempts to kick the QFileSystemModel and QTreeView to update the model values
// a collection from the internet :)
emit myFileTreeView->dataChanged( indexOfFileName, indexOfLastModifiedDate );
emit myFileTreeView->myFileSystemModel->dataChanged( indexOfFileName, indexOfLastModifiedDate );
myTreeView->repaint();
myTreeView->update( indexOfLastModifiedDate );
myTreeView->viewport()->update();
// looking to see if values changed
QModelIndex newIndexOfLastModifiedDate = myTreeView->myFileSystemModel->index( filePath, lastModifiedColumnIndex );
// this shows the correct row and column for the index, so the index looks correct
qDebug() << "newIndexOfLastModifiedDate: " << newIndexOfLastModifiedDate;
// does not have new value
qDebug() << "newIndexOfLastModifiedDate.data(): " << newIndexOfLastModifiedDate->data();
// has new value
qDebug() << "fileInfo.lastModified(): " << updatedFile->lastModified();
[EDIT - ajout d'étapes pour simuler le flux de travail de l'application]
Je pense que ce qui suit sont les étapes qui peuvent imiter le problème.
Étapes pour reproduire :
Configurez un simple QTreeView qui utilise un QFileSystemModel comme modèle.
Définissez le chemin racine sur un répertoire appelé
Root
Créez un fichier texte,
Test.txt
à l'intérieur duRoot
dirChargez l'application et observez-y les
Test.txt
des dossiers Date de la dernière modification dans leRoot
dir.Gardez cette fenêtre d'application ouverte.
Copie
Test.txt
à un différent répertoire, disonsTemp
Modifiez le fichier et enregistrez-le dans
Temp
Copiez et Remplacer
Test.txt
pour écraser le fichier dansRoot
dirObserver l Date de la dernière modification dans la fenêtre de l'application
Résultat:Le Date de la dernière modification n'est pas mis à jour
SAPMLE AJOUTÉ :
#include <QApplication>
#include <QFileSystemModel>
#include <QFile>
#include <QFileInfo>
#include <QTimer>
#include <QDebug>
#include <QTreeView>
#include <QDateTime>
// Globals
QFileSystemModel *model = NULL;
const QString name = "test.txt";
const int delayOffset = 1000;
// Interface
void onDataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector< int >& roles );
void clean();
void doCreateFile();
void doUpdateFile();
void doTest();
// Implementation
int main( int argc, char *argv[] )
{
QApplication a( argc, argv );
int delay = 0;
// Clean
clean();
// Init model
const QString rootPath = QCoreApplication::applicationDirPath();
model = new QFileSystemModel( &a );
model->setRootPath( rootPath );
QObject::connect( model, &QFileSystemModel::dataChanged, &onDataChanged );
// Init file actions
delay += delayOffset * 2;
QTimer tCreate;
tCreate.setSingleShot( true );
tCreate.setInterval( delay );
QObject::connect( &tCreate, &QTimer::timeout, &doCreateFile );
delay += delayOffset * 4;
QTimer tUpdate;
tUpdate.setSingleShot( true );
tUpdate.setInterval( delay );
QObject::connect( &tUpdate, &QTimer::timeout, &doUpdateFile );
// GUI
QTreeView w;
w.setModel( model );
w.setRootIndex( model->index( rootPath ) );
w.show();
w.expandAll();
qDebug() << "Start";
tCreate.start();
tUpdate.start();
return a.exec();
}
void onDataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector< int >& roles )
{
qDebug() << "Model changed";
}
void clean()
{
const QString path = QString( "%1/%2" ).arg( QCoreApplication::applicationDirPath() ).arg( name );
QFile f( path );
if ( f.exists() )
f.remove();
}
void doCreateFile()
{
const QString path = QString( "%1/%2" ).arg( QCoreApplication::applicationDirPath() ).arg( name );
QFile f( path );
if ( !f.open( QIODevice::WriteOnly ) )
{
qDebug() << "Could not create file";
return ;
}
f.write( "Preved" );
f.close();
qDebug() << "File created";
doTest();
}
void doUpdateFile()
{
const QString path = QString( "%1/%2" ).arg( QCoreApplication::applicationDirPath() ).arg( name );
QFile f( path );
if ( !f.open( QIODevice::Append ) )
{
qDebug() << "Could not open file for modification";
return ;
}
f.write( " medved" );
f.close();
qDebug() << "File updated";
doTest();
}
void doTest()
{
const QString path = QString( "%1/%2" ).arg( QCoreApplication::applicationDirPath() ).arg( name );
QFileInfo info( path );
qDebug() << "Last modified (real): " << info.lastModified().toString( "hh:mm:ss" );
qDebug() << "Last modified (model): " << model->lastModified( model->index( path ) ).toString( "hh:mm:ss" );
}
La solution
Tu devrais utiliser QFileSystemWatcher
pour suivre les événements pour chaque fichier, lorsqu'il est nécessaire de mettre à jour votre modèle.
QFileSystemWatcher
ne suit pas les événements en raison de problèmes de performances.C'est problème connu.Vous pouvez donc créer votre propre modèle et/ou utiliser la solution de contournement proposée :
model.setRootPath("");
model.setRootPath("the_folder_you_want_to_update");