如何在文件通过另一个进程更改后刷新QTreeView中的QFileSystemModel?

问题描述:

我有一个QTreeView作为模型QFileSystemModel。文件和目录加载正确。如何在文件通过另一个进程更改后刷新QTreeView中的QFileSystemModel?

在我的应用程序工作流程中,不同的进程会复制并覆盖文件系统上的文件。

但是,我的QTreeView不会更新覆盖文件的项目/行(例如:文件的大小和lastModified值不更新为新值)。

使用文件路径,我可以得到一个FileInfo,它具有更新的lastModified值。但是,使用该相同路径来获取该行的lastModified值的QModelIndex会导致它返回旧值。

我试过几件事(见下文)无济于事。

请让我知道你是否知道如何解决这个问题。非常感谢! :)

// ... 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(); 

[编辑 - 添加步骤模拟程序流程]

下面我相信是可以模仿的问题的步骤。

重现步骤:

  • 设置一个使用QFileSystemModel作为其模型简单QTreeView则。

  • 设置根路径到一个名为Root

  • 创建一个文本文件Test.txt目录,Root DIR

  • 加载应用程序的内部和它的Test.txt文件的最后修改日期在观察Root dir。

  • 保持此应用程序窗口打开。

  • 复制Test.txt不同目录,说Temp

  • 修改该文件并保存在Temp

  • 复制和更换Test.txt覆盖该文件中Root目录

  • 观察最后修改日期在应用程序窗口

结果:最后修改日期不更新

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"); 
} 
+0

'emit myFileTreeView-> dataChanged' What is that ??? –

+0

这是我没有受过教育的尝试,广播说我的自定义'QTreeView'模型中的特定行已经根据网上类似但不同的帖子更改了数据并需要更新。它不符合我的希望。我把它放在那里,所以你可以看到我试过的东西。 – GraehamF

+0

添加代码示例,重现问题。 –

您应该使用QFileSystemWatcher跟踪事件对于每个文件,何时需要更新模型。

QFileSystemWatcher由于性能问题没有跟踪事件。这是known issue。因此,您可以创建自己的模型和/或使用建议的解决方法:

model.setRootPath(""); 
model.setRootPath("the_folder_you_want_to_update"); 
+0

谢谢。我不想'重置()',因为它失去了用户扩展节点的状态。我拥有自己的'QFileSystemModel',并将考虑实现'QFileSystemWatcher'。 – GraehamF

+0

我刚刚参加了https://qt-project.org/doc/qt-5.0/qtwidgets/qfilesystemmodel.html - 有一种说法,即QFileSystemModel已经使用QFileSystemWatcher。所以你的promlem在另一个地方。 –

+0

是的,我也了解到。我需要自定义的'QFileSystemModel'来了解文件系统的变化,或者我需要手动更新索引数据。我不知道如何做:/ – GraehamF