5

I'm doing what the topic says on a system without keyboard/mouse, so I need to make this work "from code". When I change the RootIndex of the QListView I want to highlight the first row.

Here's mainwindow.cpp from a small testproject I've made:

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QEvent>
#include <QKeyEvent>
#include <QDebug>
#include <QTimer>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    model = new QFileSystemModel;
    model->setRootPath("/Users/anders/Downloads/Browser");

    listView = new QListView;
    listView->setModel(model);
    listView->show();

    QTimer::singleShot(2000, this, SLOT(LightItUp1()));

}

void MainWindow::LightItUp1()
{
    qDebug("LightItUp1");
    listView->setRootIndex(model->index("/Users/anders/Downloads"));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));

    QTimer::singleShot(2000, this, SLOT(LightItUp2()));
}

void MainWindow::LightItUp2()
{
    qDebug("LightItUp2");
    listView->setRootIndex(model->index("/Users/anders/Downloads/Browser"));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));

    QTimer::singleShot(2000, this, SLOT(LightItUp3()));
}


void MainWindow::LightItUp3()
{
    qDebug("LightItUp3");
    listView->setRootIndex(model->index("/Users/anders/Downloads"));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));

    QTimer::singleShot(2000, this, SLOT(LightItUp4()));
}


void MainWindow::LightItUp4()
{
    QString p = "/Users/anders/Downloads/Mail";
    listView->setRootIndex(model->index(p));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));
}

MainWindow::~MainWindow()
{
    delete listView;
    delete model;
    delete ui;
}

In this example LightItUp 1-3 do what I want, but LightItUp4 does not. If I swap the folders in 2 & 4 both of them fail to do what I want, while 1 & 3 still work. I suspect I have misunderstood something about how to use this Model/View, but have no idea what.

Edit: created a simpler example with the error checking @buck mentioned. See the comments in the source code.

const QString rp = "/home/anders/src/";

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    model = new QFileSystemModel;
    model->setRootPath(rp); //using model->setRootPath(rp + "/trunk") instead works

    listView = new QListView;
    listView->setModel(model);
    listView->show();

    QTimer::singleShot(2000, this, SLOT(LightItUp1()));

}

void MainWindow::LightItUp1()
{
    qDebug("LightItUp1");
    QModelIndex p = model->index(rp + "/trunk");
    if (!p.isValid()) {
        qDebug("index not valid\n");
        return;
    }

    //model->setRootPath(rp + "/trunk") here does not make it work
    listView->setRootIndex(p);
    listView->setCurrentIndex(model->index(0, 0, p));
}

I thought that when I do setRootPath(rp) on the model, and then set the view to use the model, the view should able to move around in all subfolders of rp if I set the indexes correctly. I'll reread the Qtdocs on Model/View, QListView and QFileSystemModel, but wanted to post this in case someone understands what is happening.

anr78
  • 1,308
  • 2
  • 17
  • 31
  • I'm not quite sure what's going on with all of this. Just to start seeing what's happening, you could make sure the indexes you are using are valid. In LightItUp4 do: QModelIndex i = model->index(p); if(!i.isValid()) // then the model didn't find the directory and you should // not change the root index – buck Aug 10 '11 at 23:54
  • I think @anr78 is trying to write an automated filesystem browser. – IslandCow Aug 11 '11 at 00:17
  • @buck Added the error checking, and all the indexes are valid. – anr78 Aug 11 '11 at 07:36

2 Answers2

2

I had some help from here and these are my conclusions:

In order for the QFileSystemModel to work properly, the GUI event loop needs to be running. I'm guessing you added the QTimer::singleShot(...) line because of this? However, you only gave it 2 seconds. From the documentation for QFileSystemModel:

Calls to rowCount() will return 0 until the model populates a directory.

This means after your MainWindow is constructed, you have 2 seconds for everything else to be constructed, the GUI event loop to start, and then for the QFileSystemModel to populate the directory. Are the directories where this is failing large? I am guessing so.

What you could try would be to give the timer a longer interval. A better solution may be to create a shortcut that selects the first thing in the list, like this:

QShortcut* sh = new QShortcut(QKeySequence("Ctrl+1"), this);
connect(sh, SIGNAL(activated()), this, SLOT(LightUpFirst()));

and the LightUpFirst function does the selecting. Hope that helps!

Community
  • 1
  • 1
buck
  • 1,502
  • 1
  • 20
  • 23
  • I've read that post as well, and it is indeed the reason for the timer. Actually the directories are not very large, and even if I increase it to 20 seconds it fails. – anr78 Aug 11 '11 at 17:10
  • In my real code the time from the model starts to populate until I try the operate on the listView can be several minutes, but it still fails in the same way. – anr78 Aug 11 '11 at 17:24
  • What are the contents of the directory where this is failing? Is it all directories or all files or mixed (maybe this plays a role??)? Also, it could be that the directory where this is failing is not loaded by the QFileSystemModel. Maybe when you change the root index of the view you should also call [setRootPath](http://doc.qt.nokia.com/latest/qfilesystemmodel.html#setRootPath) – buck Aug 11 '11 at 17:53
  • The contents of the dir does not seem to matter. I tried setting rootPath (see the comment in my example) without any luck, but I suspect I should wait for some signals from QFileSystemModel before acting. When I wait for directoryLoaded(QString) I manage to highlight *something*, thought it's not the first directory. But hey, its progress. – anr78 Aug 12 '11 at 07:02
2

I think I have it working now. After changing the rootIndex of the list, I have to wait for the model to do its work. I don't set the currentIndex in the new directory until I get the directoryLoaded signal from the model. Now highlighting works. The data from the model is not sorted, so row=0 & col=0 is not the first item in the list after all, but that's another topic :)

Edit: fiddled a bit more with this tonight, and added the final touches.

const QString rp = "/home/anders/src";

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    model = new QFileSystemModel;
    model->setRootPath(rp);

    list = new QListView;
    list->setModel(model);
    list->show();

    connect(model,
            SIGNAL(directoryLoaded(QString)),
            this,
            SLOT(model_directoryLoaded(QString)));

    QTimer::singleShot(2000, this, SLOT(changeRoot()));
}

void MainWindow::model_directoryLoaded(QString path)
{
    qDebug() << "loaded" << path;
    model->sort(0, Qt::AscendingOrder);
    list->setCurrentIndex(model->index(0, 0, list->rootIndex()));
}

void MainWindow::changeRoot()
{
    qDebug() << "changeRoot";
    model->setRootPath(rp + "/trunk");
    list->setRootIndex(model->index(rp + "/trunk"));
}

MainWindow::~MainWindow()
{
    delete list;
    delete model;
    delete ui;
}
anr78
  • 1,308
  • 2
  • 17
  • 31
  • Hi, Did you manage to highlight specific file ? Is the code posted here the final results ? How do you scroll down and up between files (and highlight each time the selected file) Thanks, Ran – ransh Dec 19 '14 at 09:52
  • I do not remember how this ended. It was a long time ago, and the code does not exist anymore (and never reached a VCS). Sorry. – anr78 Dec 19 '14 at 10:08
  • Thanks, so you do not recommend to use this code, I understand, Right ? – ransh Dec 19 '14 at 13:37
  • If it works it's usable. I honestly don't remember :) – anr78 Dec 19 '14 at 22:14