Rename a lot of files by QFile and QFileSystemModel



  • my pc : lenovo G770
    compiler : minGW 4.6.2(32bits)
    Qt version : 4.8.1

    I would like to show the files by QTableView and select the files
    I want to rename, but when the files are more than 1000, the speed
    would be pretty slow, the GUI will stall at there too.

    [code]
    int manyFiles(QApplication &app)
    {
    QFileSystemModel model;
    QString const rootPath = "E:/file_test/very big";

    QTableView view;
    view.setModel(&model);
    view.setRootIndex(model.setRootPath(rootPath));
    
    view.show();
    //....select the data you want to rename from the view
    //let us assume I select 8000 of jpg files
    
    //don't know how to rename the file by QFileSystemModel, so I use QFile instead
    QDir::setCurrent(rootPath);
    for(int i = 0; i != 8000; ++i)
    {
      QFile file(rootPath + "/jjj" + QString::number(i) + ".jpg");
      //qDebug() <<file.isOpen();
      file.rename("kkk" + QString::number(i) + ".jpg");
    }    
    
    //the program will stall
    
    app.exec();
    

    }
    [/code]

    I find out that the view and the model will update after I rename the file
    Could I ask the model and view don't update automatically before I rename all of the files?

    Thanks



  • You can modify the model using setData() as soon as you've set readOnly to false.

    I'm not quite sure if there is a convenient way of disabling view updates, but have you tried disabling the view (or its updates), removing the model and/or just blocking signals?



  • bq. disabling the view

    I tried to change the rootIndex of the view, but the model
    still update automatically

    bq. removing the model

    I removed the model but it would crash(by delete)
    sometimes(some sort of undefined behavior?).

    bq. blocking signals

    I am searching the document but can't find a way to do it, could
    you show me how?

    I found a suggestion book-- "advanced Qt
    programming" from amazon, looks like this book spend several
    hundreds pages to explain how to make a good use of Model/View.

    Since rename would involve I/O, I would not expect it could be
    some fast process, but If I could prevent the model to update
    automatically, it should make the GUI smoother.

    Thanks a lot



  • I block the signal of QTableView and QFileSystemModel, it really stop to update the view
    and model(looks like), but the GUI still stall at there, multi-thread can't solve the problem
    at will emit a warning message like "it is unsafe to use QPixmap in other
    thread", so I better don't use it.

    [code]
    int manyFiles(QApplication &app)
    {
    QFileSystemModel model;
    QString const rootPath = "E:/file_test/very big";

    QTableView view;
    view.setModel(&model);
    view.setRootIndex(model.setRootPath(rootPath));
    
    view.show();
    //....select the data you want to rename from the view
    //let us assume I select 8000 of jpg files
    
    //don't know how to rename the file by QFileSystemModel, so I use QFile instead
    QDir::setCurrent(rootPath);
    model.blockSignals(true);
    view.blockSignals(true);
    for(int i = 0; i != 8000; ++i)
    {
      QFile file&#40;rootPath + "/kkk" + QString::number(i&#41; + ".jpg");
      file.rename("jjj" + QString::number(i) + ".jpg");
    }
    
    //the program will stall
    qDebug() << "finish";
    
    app.exec();
    

    }
    [/code]

    I added a progress bar to show the progress, but the progress bar also stall
    How could I make the UI become alive when the files being rename?Thanks



  • The problem is your tight loop in the main GUI thread in lines 18-22. I think this is typically a job for a worker thread. You should look into creating a class that subclasses QRunnable, like this:

    @
    class FileRenameRunnable: public QRunnable
    {
    FileRenameRunnable(QString fromPath, QString toPath)
    : m_fromPath(fromPath), m_toPath(toPath)
    {
    setAutoDelete(true);
    }

    virtual void run()
    {
        QFile file&#40;m_fromPath&#41;;
        file.rename(m_toPath);
    }
    

    private:
    QString m_fromPath;
    QString m_toPath;
    }

    //instead of your loop
    //...
    for(int i = 0; i != 8000; ++i)
    {
    QThreadPool::globalInstance()->start(new FileRenameRunnable(
    rootPath + "/kkk" + QString::number(i) + ".jpg",
    rootPath + "/kkk" + QString::number(i) + ".jpg"));
    }
    @

    Or look into other alternatives like basic QThreads or QtConcurrent::run for other options. Note: the code above is brain-to-terminal and not tested. Use as an example only.



  • When I use boost::thread to rename the files(didn't emit any signal)
    I always get warning message, but QRunnable don't get any warning message, weird

    I let QRunnable inherit QObject and emit a signal to update the QProgressBar
    Even all of the file are already rename(I print out "finish" after the task finish their job)
    the GUI still "stall" and need to wait a long time for it to "wake up" but the progress bar is alive now.

    I use two FileSystemModel to nagivate the files in the same folder(since I don't familiar with
    model/view yet), looks like I should use proxyModel to alleviate the burden of CPU.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.