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.
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!
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With