Come aggiornare un QFileSystemModel in un QTreeView dopo che i file sono cambiati attraverso un altro processo?
-
24-12-2019 - |
Domanda
Ho un QTreeView
con un QFileSystemModel
come modello.File e directory vengono caricati correttamente.
Nel flusso di lavoro della mia applicazione, un processo diverso copia e sovrascrive i file nel file system.
Tuttavia, il mio QTreeView
non aggiorna la voce/riga per il file sovrascritto (es:la dimensione e i valori lastModified del file non vengono aggiornati ai nuovi valori).
Utilizzando il percorso del file, sono in grado di ottenere un file FileInfo
che HA il valore lastModified aggiornato.Tuttavia, utilizzando quello stesso percorso per afferrare il QModelIndex
del valore lastModified della riga comporta la restituzione del vecchio valore.
Ho provato alcune cose (vedi sotto) senza alcun risultato.
PER FAVORE, fatemi sapere se siete a conoscenza di come risolvere questo problema.Grazie molto!:)
// ... 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();
[MODIFICA: aggiunta di passaggi per simulare il flusso di lavoro dell'applicazione]
Credo che i seguenti siano i passaggi che possono simulare il problema.
Passaggi per riprodurre:
Imposta un semplice QTreeView che utilizza un QFileSystemModel come modello.
Imposta il percorso root su una directory chiamata
Root
Crea un file di testo,
Test.txt
all'interno delRoot
dirCarica l'applicazione e osserva in essa il file
Test.txt
File Data dell'ultima modifica nelRoot
dir.Mantieni aperta questa finestra dell'applicazione.
copia
Test.txt
ad a diverso directory, diciamoTemp
Modifica il file e salvalo in
Temp
Copia e Sostituire
Test.txt
per sovrascrivere il file inRoot
dirOsservare il Data dell'ultima modifica nella finestra dell'applicazione
Risultato:IL Data dell'ultima modifica non è aggiornato
CAMPIONE AGGIUNTO:
#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" );
}
Soluzione
Dovresti usare QFileSystemWatcher
per tenere traccia degli eventi per ciascun file, quando è necessario aggiornare il modello.
QFileSystemWatcher
non tiene traccia degli eventi a causa di problemi di prestazioni.Questo è problema conosciuto.Quindi puoi creare il tuo modello e/o utilizzare la soluzione alternativa proposta:
model.setRootPath("");
model.setRootPath("the_folder_you_want_to_update");