Qt: view file system with QListView and QFileSystemModel. How to transfer the first item to a folder?

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

Here is mainwindow.cpp from a small test project that I did:

#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 does what I want, but LightItUp4 does not. If I change the folders to 2 and 4, then both of them will not be able to do what I want, while 1 and 3 are still working. I suspect that I misunderstood how to use this model / view, but I have no idea what.

Edit: created a simpler example with @buck error checking. See 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 set setRootPath (rp) in the model and then set the view to use the model, the view should move in all rp subfolders if I set the indexes correctly. I will re-read Qtdocs on Model / View, QListView and QFileSystemModel, but would like to publish them in case anyone understands what is going on.

+4
source share
2 answers

I think I'm working now. After changing rootIndex in the list, I have to wait for the model to complete its work. I do not install currentIndex in a new directory until I receive a signal with a directory from the model. Now highlight the work. Data from the model is not sorted, so row = 0 and col = 0 are not the first item in the list, but this is another section :)

Edit: play a little tonight and added the finishing 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; } 
+2
source

I had help here , and these are my findings:

For QFileSystemModel to work properly, you must run the GUI event loop. I assume you added the line QTimer::singleShot(...) because of this? However, you gave only 2 seconds. From the documentation for QFileSystemModel :

Calls in rowCount () return 0 until the model populates the directory.

This means that after creating the MainWindow, you have 2 seconds to create the rest, a GUI event loop to run, and then to populate the QFileSystemModel directory. Are directories where this fails? I think so.

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

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

and the LightUpFirst function makes the selection. Hope this helps!

+2
source

All Articles