Wie aktualisiere ich ein QFileSystemModel in einem QTreeView, nachdem sich Dateien durch einen anderen Prozess geändert haben?
-
24-12-2019 - |
Frage
Ich habe ein QTreeView
mit einem QFileSystemModel
als Vorbild.Dateien und Verzeichnisse werden korrekt geladen.
In meinem Anwendungsworkflow kopiert und überschreibt ein anderer Prozess Dateien im Dateisystem.
Allerdings mein QTreeView
aktualisiert das Element/die Zeile für die überschriebene Datei nicht (z. B.:Die Werte „size“ und „lastModified“ für die Datei werden nicht auf die neuen Werte aktualisiert.
Mithilfe des Dateipfads kann ich eine erhalten FileInfo
das hat den aktualisierten lastModified-Wert.Allerdings nutzen wir das gleichen Weg um das zu ergreifen QModelIndex
des lastModified-Werts der Zeile führt dazu, dass der alte Wert zurückgegeben wird.
Ich habe ein paar Dinge ausprobiert (siehe unten), ohne Erfolg.
BITTE teilen Sie mir mit, ob Sie wissen, wie Sie das Problem beheben können.Vielen Dank!:) :)
// ... 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();
[BEARBEITEN – Schritte zur Simulation des Anwendungsworkflows hinzufügen]
Ich glaube, dass die folgenden Schritte das Problem nachahmen können.
Schritte zum Reproduzieren:
Richten Sie eine einfache QTreeView ein, die ein QFileSystemModel als Modell verwendet.
Legen Sie den Root-Pfad auf ein Verzeichnis mit dem Namen fest
Root
Erstellen Sie eine Textdatei,
Test.txt
innerhalb derRoot
dirLaden Sie die Anwendung und beobachten Sie darin die
Test.txt
Dateien Zuletzt geändertes Datum imRoot
dir.Lassen Sie dieses Anwendungsfenster geöffnet.
Kopieren
Test.txt
zu einem anders Verzeichnis, sagen wirTemp
Ändern Sie die Datei und speichern Sie sie unter
Temp
Kopieren und Ersetzen
Test.txt
um die Datei zu überschreibenRoot
dirBeobachte Zuletzt geändertes Datum im Anwendungsfenster
Ergebnis:Der Zuletzt geändertes Datum wird nicht aktualisiert
HINZUGEFÜGTES 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" );
}
Lösung
Du solltest benutzen QFileSystemWatcher
um Ereignisse für jede Datei zu verfolgen, wenn eine Aktualisierung Ihres Modells erforderlich ist.
QFileSystemWatcher
verfolgt aufgrund von Leistungsproblemen keine Ereignisse.Das ist bekanntes Problem.Sie können also Ihr eigenes Modell erstellen und/oder die vorgeschlagene Problemumgehung verwenden:
model.setRootPath("");
model.setRootPath("the_folder_you_want_to_update");