2

I've been struggling with this for a while.

Qt's QFileSystemModel is really slow when fetching several hundred files because of a really bad icon fetching algorithm.

I want to completely disable icons. They are fetched in QFileSystemModel::data method which is not virtual (the source of QFileSystemModel is available here: http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/dialogs/qfilesystemmodel.cpp)

This is the code I'm trying to run:

class FileModel : public QFileSystemModel {
    using QFileSystemModel::data;
public:
    QVariant QFileSystemModel::data(const QModelIndex &index, int role) const
    {
     // my own implementation here
    }
}

but it fails with

cannot define member function QFileSystemModel::data witin FileModel

UPDATE

I've managed to override the function and this is what I have now:

class FileModel : public QFileSystemModel {
public:
    QVariant data(const QModelIndex &index, int role) const
    {
    // Here goes Qt's implementation
    Q_D(const QFileSystemModel);
    if (!index.isValid() || index.model() != this)
        return QVariant();
    switch (role) {
    case Qt::EditRole:
    case Qt::DisplayRole:
        switch (index.column()) {
        case 0: return d->name(index);
        case 1: return d->size(index);
        case 2: return d->type(index);
        case 3: return d->time(index);
        default:
            qWarning("data: invalid display value column %d", index.column());
            break;
        }
        break;
    case FilePathRole:
        return filePath(index);
    case FileNameRole:
        return d->name(index);
    case Qt::DecorationRole:
        if (index.column() == 0) {
            QIcon icon = d->icon(index); // This is the part I need to change
            if (icon.isNull()) {
                if (d->node(index)->isDir())
                    icon = d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::Folder);
                else
                    icon = d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::File);
            }
            return icon;
        }
        break;
    case Qt::TextAlignmentRole:
        if (index.column() == 1)
            return Qt::AlignRight;
        break;
    case FilePermissions:
        int p = permissions(index);
        return p;
    }
    return QVariant();
}
};

However this code doesn't compile. This is the error I get: 'const QFileSystemModelPrivate* QFileSystemModel::d_func() const' is private

3
  • 2
    remove QFileSystemModel:: part from your declaration, also don't put using part. It is not required here Commented Apr 20, 2012 at 13:17
  • data must be virtual. QFileSystemModel derives from QAbstractItemModel, and in that class data is a pure virtual function. See qt-project.org/doc/qt-4.8/qabstractitemmodel.html#data Commented Apr 20, 2012 at 14:15
  • What Kamil says. Moritz: you don't need virtual keyword if the base already declares a function virtual, pure or otherwise. Commented Apr 20, 2012 at 14:25

2 Answers 2

4

Looks like this was anticipated, as there is a method for setting the "icon provider":

http://doc.qt.io/archives/qt-4.7/qfilesystemmodel.html#setIconProvider

The parameter, a QFileIconProvider, looks to be a fairly simple class that you can implement an instance of yourself, with a method that fetches an icon from a QFileInfo (basically, a file name):

http://doc.qt.io/archives/qt-4.7/qfileinfo.html

You could implement one of these that just returns the same icon for everything. If you find that doesn't address your problem, the following compiled fine for me...FWIW:

class FileModel : public QFileSystemModel {
public:
    QVariant data(const QModelIndex &index, int role) const
    {
        if (role == Qt::DecorationRole) {
            return QVariant (QIcon ());
        }    

        return QFileSystemModel::data(index, role);
    }
};
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks, but that doesn't work. QFileSystemModel uses QFileIconProvider only to build icons for folders and general files and only if calling QFileSystemNode::icon() failed. I couldn't find the QFileSystemNode class, even if I did, changing it would be a lot harder than changing the QFileSystemModel class.
Looking at the source...are you saying in getting the decoration role that it is going through the d->icon path here (which is slow for you) and not calling the provider? Or do you think it's something else? This is in the source of the method you are trying to override: qt.gitorious.org/qt/qt/blobs/4.8/src/gui/dialogs/…
Yes, d->icon() calls QFileSystemNode::icon which takes about 2 milliseconds to run. Multiply it by 5000 files and you get 10 seconds of a UI freeze since QIcon can only be used in a main UI thread.
@Alex QFileSystemNode::icon is initially populated by QFileIconProvider too: qt.gitorious.org/qt/qt/blobs/4.8/src/gui/dialogs/…
That's due to the "pimpl idiom"...there's some private implementation stuff that doesn't make it into the public header set. You shouldn't need to worry about reaching into the implementation of QFileSystemModel though, can't you just test the parameters and handle it if they are the case you want, otherwise pass through to the base...? See updated code.
|
2

If a function in a base class is virtual then it is virtual in derived classes as well. The following will print "C":

#include <iostream>

class A {
public:
  virtual void data() = 0;
};

class B: public A {
public:
  void data() { std::cout << "B\n"; }
};

class C: public B {
public:
  void data() { std::cout << "C\n"; }
};

int
main() {
  C c;
  A *a = &c;
  a->data();

  return 0;
}

QFileSystemDialog is derived from QAbstractItemModel in which data() is pure virtual. You couldn't even instatiate the former if it didn't override data() with its own implementation.

See http://qt-project.org/doc/qt-4.8/qabstractitemmodel.html#data

2 Comments

You are right, it's virtual. However I'm getting this error: invalid use of incomplete type 'const struct QFileSystemModelPrivate'
Why don't you post the full source code to your class somewhere so that we can look at actual code and don't have to mind read what you've written?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.