Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Loading time of QFileSystemModel entries
Forum Updated to NodeBB v4.3 + New Features

Loading time of QFileSystemModel entries

Scheduled Pinned Locked Moved General and Desktop
9 Posts 3 Posters 4.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Chris KawaC Offline
    Chris KawaC Offline
    Chris Kawa
    Lifetime Qt Champion
    wrote on last edited by
    #1

    Hi,

    I have a custom file system dialog which uses QFileSystemModel and displays entries in QListView.
    Since there are lots of network drives and other "slow" entries on target machines I would like to indicate to the user that something is going on by QApplication::setOverrideCursor(Qt::WaitCursor) / QApplication::restoreOverrideCursor().

    The problem is that I can't seem to find any reliable pair of signals I could connect to to call those functions.
    First thought was rootPathChanged()/directoryLoaded() of the model, but the second signal is only emitted the first time model visits directory, so if I enter directory, enter another and then go back I'm stuck with the wait cursor because second signal doesn't fire again. The other thing is that it takes few seconds between directoryLoaded() and QListView actually refreshing the view to show those loaded directories.

    I also looked at rowsAboutToBeInserted()/rowsInserted(), but those fire multiple times in a single directory and there are long gaps when loading consecutive network drives.
    The start of loading seems to work fine with rootPathChanged(), but I can't find a reliable way to tell when directory has been fully loaded.

    I'd be grateful for any ideas.

    1 Reply Last reply
    0
    • D Offline
      D Offline
      Dogcat
      wrote on last edited by
      #2

      I'm having the same issue. Is there a chance the author has already found a bypass solution?

      1 Reply Last reply
      0
      • Chris KawaC Offline
        Chris KawaC Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,
        Welcome to DevNet.

        Unfortunately the only way I found was to dig deep into Qt implementation and provide a custom signal for that myself, but since I couldn't modify Qt at that time for licencing reasons I abandoned the idea.
        I was not very happy to remove the wait cursor but oh well, I don't work in that project anymore :P

        1 Reply Last reply
        0
        • D Offline
          D Offline
          Dogcat
          wrote on last edited by
          #4

          [quote author="Chris Kawa" date="1396606381"]Hi,
          Welcome to DevNet.

          Unfortunately the only way I found was to dig deep into Qt implementation and provide a custom signal for that myself, but since I couldn't modify Qt at that time for licencing reasons I abandoned the idea.
          I was not very happy to remove the wait cursor but oh well, I don't work in that project anymore :P[/quote]

          Thank you.

          Heh, I see. Well, I can share the only idea I have so far (I just had it in a grocery store so I haven't actually tried it): to subclass QFileSystemModel and re-implements its "data(..)" method like this:
          @QVariant QCustomFileSystemModel::data(const QModelIndex & index, int role = Qt::DisplayRole) const {
          if (role != Qt::DisplayRole) return QFileSystemModel::data(index,role);

          emit signalStart();
          QVariant data = QFileSystemModel::data(index,role);
          emit signalFinish();
          return data;
          }@

          Probably I will have to do the same with QFileSystemModel::columnCount(...) and QFileSystemModel::rowCount(...)

          1 Reply Last reply
          0
          • Chris KawaC Offline
            Chris KawaC Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on last edited by
            #5

            I don't think this will work. This would emit start/finish before and after a new item is added. So if you connect cursor change to that it will blink like crazy until the whole directory is loaded. But it will also not show anything between the items. so it doesn't solve the issue at all.

            The problem here is that the operation is asynchronous. Qt posts a request to the OS to enumerate the directory and registers a callback that is called whenever OS is ready to list another item. Qt thus doesn't know if there are more items to come or not. To fix this you would need to check these OS dependent enumeration mechanisms and check if they provide something like items count before you start to enumerate them. If it does then you can increase some counter in the mentioned callback and know when you're done.

            My guess (although totally unchecked) is that some platforms don't provide such count and that's why Qt doesn't provide a signal like that.

            Edit: A "link":http://blogs.msdn.com/b/oldnewthing/archive/2009/02/17/9426787.aspx to confirm that theory at least on Windows.

            1 Reply Last reply
            0
            • D Offline
              D Offline
              Dogcat
              wrote on last edited by
              #6

              [quote author="Chris Kawa" date="1396612341"]I don't think this will work. This would emit start/finish before and after a new item is added. So if you connect cursor change to that it will blink like crazy until the whole directory is loaded. But it will also not show anything between the items. so it doesn't solve the issue at all.
              [/quote]

              My problem is a little bit different and I still hope this will help :) Damn, this is going to be hard to explain.

              I work with a Linux embeded device and I have a file browser application which also mounts and unmounts samba shares.
              When a share becomes unavailable (for any possible reason) I'm having major freezes every time the model tries to access it. I can't go to all "low level"(although I've already tried playing with mounting options) so I just wanted to start a timer when the model starts retrieving file list from a remote dir and use its timeout signal as a sing that something went wrong (meaning that I should probably reset the model and lazy umount this share).

              So in my imagination what I proposed will just start/reset a timeout timer properly.

              1 Reply Last reply
              0
              • D Offline
                D Offline
                Dogcat
                wrote on last edited by
                #7

                And you were right, my idea didn't work.

                1 Reply Last reply
                0
                • T Offline
                  T Offline
                  TNick
                  wrote on last edited by
                  #8

                  So this seems to work. Not great, as there still is a delay between clicking on expand button and the cursor being changed to hourglass.

                  It needs an ugly hack as QAbstractModel::data() is const.

                  @
                  // fsmodelenhanced.h
                  #ifndef FSMODELENHANCED_H
                  #define FSMODELENHANCED_H

                  #include <QFileSystemModel>

                  class FsModelEnhanced : public QFileSystemModel
                  {
                  Q_OBJECT

                  public:
                  explicit FsModelEnhanced(QObject *parent = 0);

                  signals:
                  void fsmeLoadStart ();
                  void fsmeLoadEnd ();

                  protected:

                  virtual void
                  timerEvent (
                          QTimerEvent *event);
                  
                  QVariant
                  data(
                          const QModelIndex & index,
                          int role = Qt::DisplayRole) const;
                  

                  private:

                  void
                  startDataRetrieveSequence ();
                  

                  private:
                  int timer_id_;
                  };

                  #endif // FSMODELENHANCED_H
                  @

                  @
                  // fsmodelenhanced.cpp
                  #include "fsmodelenhanced.h"
                  #include <QTimerEvent>

                  FsModelEnhanced::FsModelEnhanced(QObject *parent) :
                  QFileSystemModel(parent),
                  timer_id_(-1)
                  {
                  }

                  void FsModelEnhanced::startDataRetrieveSequence ()
                  {
                  if (timer_id_ == -1) {
                  // this is the first item in the chain
                  emit fsmeLoadStart();
                  } else {
                  killTimer (timer_id_);
                  }

                  // another half second wait
                  timer_id_ = startTimer (100);
                  

                  }

                  QVariant FsModelEnhanced::data (
                  const QModelIndex & index, int role) const
                  {
                  for (;;) {

                      if (role != Qt::DisplayRole) break;
                      if (!index.isValid ()) break;
                      if (!index.column () != 0) break;
                  
                      // this is nasty
                      ((FsModelEnhanced*)this)->startDataRetreieveSequence();
                      break;
                  }
                  return QFileSystemModel::data(index,role);
                  

                  }

                  void FsModelEnhanced::timerEvent (QTimerEvent *event)
                  {
                  for (;;) {
                  if (timer_id_ == -1) break;
                  if (event->timerId () != timer_id_) break;
                  killTimer (timer_id_);
                  timer_id_ = -1;
                  emit fsmeLoadEnd();
                  return;
                  }
                  QFileSystemModel::timerEvent (event);
                  }
                  @

                  @
                  // mainwindow.cpp
                  // ...
                  connect (model, SIGNAL(fsmeLoadStart()),
                  this, SLOT(fsmeLoadStart()));
                  connect (model, SIGNAL(fsmeLoadEnd()),
                  this, SLOT(fsmeLoadEnd()));
                  // ...

                  void MainWindow::fsmeLoadStart()
                  {
                  ui->treeView->setCursor (Qt::WaitCursor);
                  }

                  void MainWindow::fsmeLoadEnd()
                  {
                  ui->treeView->setCursor (Qt::ArrowCursor);
                  }

                  @

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    TNick
                    wrote on last edited by
                    #9

                    So this seems to work. Not great, as there still is a delay between clicking on expand button and the cursor being changed to hourglass.

                    It needs an ugly hack as QAbstractModel::data() is const.

                    @
                    // fsmodelenhanced.h
                    #ifndef FSMODELENHANCED_H
                    #define FSMODELENHANCED_H

                    #include <QFileSystemModel>

                    class FsModelEnhanced : public QFileSystemModel
                    {
                    Q_OBJECT

                    public:
                    explicit FsModelEnhanced(QObject *parent = 0);

                    signals:
                    void fsmeLoadStart ();
                    void fsmeLoadEnd ();

                    protected:

                    virtual void
                    timerEvent (
                            QTimerEvent *event);
                    
                    QVariant
                    data(
                            const QModelIndex & index,
                            int role = Qt::DisplayRole) const;
                    

                    private:

                    void
                    startDataRetrieveSequence ();
                    

                    private:
                    int timer_id_;
                    };

                    #endif // FSMODELENHANCED_H
                    @

                    @
                    // fsmodelenhanced.cpp
                    #include "fsmodelenhanced.h"
                    #include <QTimerEvent>

                    FsModelEnhanced::FsModelEnhanced(QObject *parent) :
                    QFileSystemModel(parent),
                    timer_id_(-1)
                    {
                    }

                    void FsModelEnhanced::startDataRetrieveSequence ()
                    {
                    if (timer_id_ == -1) {
                    // this is the first item in the chain
                    emit fsmeLoadStart();
                    } else {
                    killTimer (timer_id_);
                    }

                    // another half second wait
                    timer_id_ = startTimer (100);
                    

                    }

                    QVariant FsModelEnhanced::data (
                    const QModelIndex & index, int role) const
                    {
                    for (;;) {

                        if (role != Qt::DisplayRole) break;
                        if (!index.isValid ()) break;
                        if (!index.column () != 0) break;
                    
                        // this is nasty
                        ((FsModelEnhanced*)this)->startDataRetreieveSequence();
                        break;
                    }
                    return QFileSystemModel::data(index,role);
                    

                    }

                    void FsModelEnhanced::timerEvent (QTimerEvent *event)
                    {
                    for (;;) {
                    if (timer_id_ == -1) break;
                    if (event->timerId () != timer_id_) break;
                    killTimer (timer_id_);
                    timer_id_ = -1;
                    emit fsmeLoadEnd();
                    return;
                    }
                    QFileSystemModel::timerEvent (event);
                    }
                    @

                    @
                    // mainwindow.cpp
                    // ...
                    connect (model, SIGNAL(fsmeLoadStart()),
                    this, SLOT(fsmeLoadStart()));
                    connect (model, SIGNAL(fsmeLoadEnd()),
                    this, SLOT(fsmeLoadEnd()));
                    // ...

                    void MainWindow::fsmeLoadStart()
                    {
                    ui->treeView->setCursor (Qt::WaitCursor);
                    }

                    void MainWindow::fsmeLoadEnd()
                    {
                    ui->treeView->setCursor (Qt::ArrowCursor);
                    }

                    @

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved