Search code examples
qtsortingqt4qfiledialog

What determines sorting of files in a QFileDialog?


Users open files in our app through a QFileDialog. The order of the filenames is bizarre. What is determining the sorting order, and how can we make it sort by filenames, or otherwise impose our own sorting, perhaps giving it a pointer to our own comparison function?

The documentation and online forums haven't been helpful. Unless it's well hidden, there doesn't seem to be any sorting method, property, etc.

This is a primarily Linux app, but also runs on Macs. (I know nothing about Mac.)

Here is the juicy part of the source code:

QtFileDialog chooser(parent, caption, directory, filter);
/// QtFileDialog is our class derived from QFileDialog

chooser.setModal(true);
chooser.setAcceptMode(acceptMode);
chooser.setFileMode(fileMode);

QStringList hist = chooser.history();
chooser.setHistory(hist);

/* point "x" */

if(chooser.exec()) {    
    QStringList files = chooser.selectedFiles();
    ...blah blah blah...

From one of the answers, I tried an evil experiment, adding this ill-informed guesswork code at "point x":

QSortFilterProxyModel *sorter = new QSortFilterProxyModel();
sorter->sort(1);  // ???
chooser.setProxyModel(sorter);

But this crashed spectacularly at a point about 33 subroutine calls deep from this level of code. I admit, even after reading the Qt4 documentation and sample code, I have no idea of the proper usage of QSortFilterProxyModel.


Solution

  • Are you using QFileDialog by calling exec()? If you are, you should have a button to switch the view to Detail View. This will give you some column headers that you can click on to sort the files. It should remember that mode the next time the dialog opens but you can force it by calling setViewMode(QFileDialog::Detail) before calling exec().

    An alternative is to call the static function QFileDialog::getOpenFileName() which will open a file dialog that is native to the OS on which you are running. Your users may like the familiarity of this option better.

    Update 1:

    About sort order in screen cap from OP: alt text

    This screen capture is actually showing a sorted list. I don't know if the listing behaviour is originating from the Qt dialog or the underlying file system but I know Windows XP and later do it this way.

    When sorting filenames with embedded numbers, any runs of consecutive digits are treated as a single number. With the more classic plain string sorting, files would be sorted like this:

    A_A_10e0
    A_A_9a05
    

    Going character by character, the first 1 sorts before the 9.

    .. But with numerical interpretation (as in Windows 7 at least), they are sorted as:

    A_A_9a05
    A_A_10e0
    

    The 9 sorts before the 10.

    So, the sorting you are seeing is alphabetical with numerical interpretation and not just straight character by character. Some deep digging may be required to see if that is Qt behaviour or OS behaviour and whether or not it can be configured.

    Update 2:

    The QSortFilterProxyModel will sort the strings alphabetically by default so there is not much work to using it to get the behavior you are looking for. Use the following code where you have "point x" in your example.. (you almost had it :)

    QSortFilterProxyModel *sorter = new QSortFilterProxyModel();
    sorter->setDynamicSortFilter(true); // This ensures the proxy will resort when the model changes
    chooser.setProxyModel(sorter);