I have a QTreeView
with a QFileSystemModel
as the model. Files and directories load correctly.
In my application workflow, a different process copies and overwrites files on the file system.
However, my QTreeView
does not update the item/row for the overwritten file (eg: the size and lastModified values for the file do not update to the new values).
Using the file path, I'm able to get a FileInfo
that DOES have the updated lastModified value. However, using that same path to grab the QModelIndex
of the row's lastModified value results in it returning the old value.
I've tried a few things (see below) to no avail.
PLEASE let me know if you are aware of how to resolve this. Many Thanks! :)
// ... 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 - adding steps to simulate application workflow]
The following I believe to be the steps that can mimic the issue.
Steps to Reproduce:
Setup a simple QTreeView that uses a QFileSystemModel as its model.
Set Root Path to a directory called Root
Create a text file, Test.txt
inside of the Root
dir
Load the application and observe in it the Test.txt
file's Last Modified Date in the Root
dir.
Keep this application window open.
Copy Test.txt
to a different directory, say Temp
Modify the file and save in Temp
Copy and Replace Test.txt
to overwrite the file in Root
dir
Observe the Last Modified Date in the application window
Result: The Last Modified Date is not updated
ADDED SAPMLE:
#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" );
}
You should use QFileSystemWatcher
to track events for each file, when it necessary to update your model.
QFileSystemWatcher
does not track an events because of performance issues. This is known issue. So you may create your own model and/or use proposed workaround:
model.setRootPath("");
model.setRootPath("the_folder_you_want_to_update");