Qt: просмотр файловой системы с помощью QListView и QFileSystemModel.Как выделить первый элемент в папке? - PullRequest
4 голосов
/ 10 августа 2011

Я делаю то, что говорится в теме, в системе без клавиатуры / мыши, поэтому мне нужно сделать эту работу "из кода".Когда я изменяю RootIndex QListView, я хочу выделить первую строку.

Вот mainwindow.cpp из небольшого тестового проекта, который я сделал:

#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;
}

В этом примере LightItUp 1-3 делай что хочу, а LightItUp4 нет.Если я поменяю местами папки 2 и 4, они не смогут делать то, что я хочу, а 1 и 3 все еще работают.Я подозреваю, что что-то неправильно понял о том, как использовать эту модель / представление, но понятия не имею, что.

Редактировать: создал более простой пример с упомянутой проверкой ошибок @buck.См. Комментарии в исходном коде.

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));
}

Я подумал, что когда я делаю setRootPath (rp) для модели, а затем устанавливаю представление для использования модели, представление должно иметь возможность перемещаться во всехподпапки rp, если я правильно установил индексы.Я перечитываю Qtdocs в Model / View, QListView и QFileSystemModel, но хотел опубликовать это на тот случай, если кто-то поймет, что происходит.

Ответы [ 2 ]

2 голосов
/ 12 августа 2011

Я думаю, у меня сейчас работает. После изменения корневого индекса в списке, я должен ждать, пока модель сделает свою работу. Я не устанавливаю currentIndex в новый каталог, пока не получу сигнал directoryLoaded от модели. Сейчас подсветка работает. Данные из модели не сортируются, поэтому row = 0 & col = 0, в конце концов, не первый элемент в списке, но это другая тема:)

Редактировать: немного больше повозился с этим вечером и добавил последние штрихи.

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 голосов
/ 11 августа 2011

Я получил некоторую помощь от здесь , и вот мои выводы:

Для правильной работы QFileSystemModel должен быть запущен цикл событий GUI. Я предполагаю, что вы добавили строку QTimer::singleShot(...) из-за этого? Тем не менее, вы дали только 2 секунды. Из документации для QFileSystemModel :

Вызовы rowCount () будут возвращать 0, пока модель не заполнит каталог.

Это означает, что после создания вашего MainWindow у вас есть 2 секунды для создания всего остального, запуска цикла обработки событий GUI, а затем для заполнения QFileSystemModel каталога. Являются ли каталоги, где это не удается, большой? Я так и думаю.

То, что вы могли бы попробовать, это дать таймеру более длительный интервал. Лучшим решением может быть создание ярлыка, который выбирает первую вещь в списке, например:

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

и функция LightUpFirst делает выбор. Надеюсь, это поможет!

...