I'm trying to create a small app, which will find, read and export some *.xml documents. App must read the hierarchical folder structure and visualise it in QTreeView on the form. For better managing I want it to expand all objects of treeview on the app's startup. I've tried many different solutions like this:
void expandChildren(const QModelIndex &index, QTreeView *view)
{
if (!index.isValid())
{
return;
}
int childCount = index.model()->rowCount(index);
for (int i = 0; i < childCount; i++)
{
const QModelIndex &child = index.child(i, 0);
expandChildren(child, view);
}
if (!view->isExpanded(index))
{
view->expand(index);
}
}
from some forums and embeded solutions like QTreeView::expandRecursively and QTreeView::expandAll, but I haven't achived what I wanted.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFileSystemModel>
#include <QDebug>
#include <QDirModel>
#include <QTreeView>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
QModelIndex fs_index;
QModelIndex child_1_index;
QModelIndex child_2_index;
QModelIndex child_3_index;
QFileSystemModel *fs_model = new QFileSystemModel;
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_treeView_clicked(const QModelIndex &index);
void on_pushButton_2_clicked();
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
void expandChildren(const QModelIndex &index, QTreeView *view)
{
if (!index.isValid())
{
return;
}
int childCount = index.model()->rowCount(index);
for (int i = 0; i < childCount; i++)
{
const QModelIndex &child = index.child(i, 0);
expandChildren(child, view);
}
if (!view->isExpanded(index))
{
view->expand(index);
}
}
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QString str_root_path;
QDir dir;
qDebug() << "Current user's home folder is: " <<QDir::home().path();
str_root_path = QDir::home().path() + "/AppData/Local/app/settings";
qDebug() << "Settings storing folder id: " << str_root_path;
dir.setPath(str_root_path);
if (!dir.exists())
{
qDebug() << "Settings folder doesn't exist.";
return;
}
if (!dir.isReadable())
{
qDebug() << "Folder found. Read access denied. Check access rights.";
return;
}
qDebug() << "Folder found. Read access granted. Reading...";
ui->treeView->setModel(fs_model);
fs_index = fs_model->index(str_root_path);
qDebug() << fs_model->fileName(fs_index);
fs_model->setRootPath(str_root_path);
QStringList filter;
filter << "*.xml";
fs_model->setNameFilters(filter);
fs_model->setFilter( QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
ui->treeView->setRootIndex(fs_index);
ui->treeView->setCurrentIndex(fs_index);
for (int i = 1; i < fs_model->columnCount(); i++)
{
ui->treeView->setColumnHidden(i, true);
}
ui->treeView->show();
qDebug().nospace() << "View loaded. Expanding....";
ui->treeView->setExpanded(fs_index, true);
int fs_index_rows = fs_model->rowCount(fs_index);
qDebug().nospace() << "Number of found profiles:" << fs_index_rows;
for (int i = 0; i < fs_index_rows; ++i)
{
child_1_index = fs_model->index(i,0,fs_index);
ui->treeView->setExpanded(child_1_index, true);
int child_1_index_rows = fs_model->rowCount(child_1_index);
qDebug().nospace() << "Step #" << i+1 << " Object name: " << fs_model->fileName(child_1_index) << ". Num of children: " << child_1_index_rows;
for (int j = 0; j < child_1_index_rows; ++j)
{
child_2_index = ui->treeView->model()->index(j,0,child_1_index);
//qDebug() << child_2_index;
ui->treeView->setExpanded(child_2_index, true);
int child_2_index_rows = ui->treeView->model()->rowCount(child_2_index);
qDebug().nospace() << "Step #" << i+1 << "/" << j+1 << " Object name: " << fs_model->fileName(child_1_index) << "/" << fs_model->fileName(child_2_index) << ". Num of children: " << child_2_index_rows;
for (int k = 0; k < child_2_index_rows; ++k)
{
child_3_index = ui->treeView->model()->index(k,0,child_2_index);
ui->treeView->setExpanded(child_3_index, true);
int child_3_index_rows = ui->treeView->model()->rowCount(child_3_index);
qDebug().nospace() << "Step #" << i+1 << "/" << j+1 << "/" << k+1 << " Object name: " << fs_model->fileName(child_1_index) << "/" << fs_model->fileName(child_2_index) << "/" << fs_model->fileName(child_3_index) << ". Num of children: " << child_3_index_rows;
}
}
}
}
If I paste that code to the slot which connected to the signal of "pushbutton_Clicked" for example, each click expand the treeview for a one more depth level (the same action appearing if I connect QTreeView::expandRecursively or QTreeView::expandAll to "pushbutton_Clicked"). I've tried to debug every step of app and I understuud that each new index object can't achive parent's index of filesystemmodel.
Please help me understand, where is the error and how to fix it.
I'm new in programming on Qt and my knoledgement is not full but I still searching, reading and trying to understand.
Thank you in advance and sorry for bad English.
All the code of app:
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFileSystemModel>
#include <QDebug>
#include <QDirModel>
#include <QTreeView>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
QModelIndex fs_index;
QFileSystemModel fs_model;
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_treeView_clicked(const QModelIndex &index);
void on_pushButton_2_clicked();
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
void expandChildren(const QModelIndex &index, QTreeView *view)
{
if (!index.isValid()) {
return;
}
int childCount = index.model()->rowCount(index);
for (int i = 0; i < childCount; i++) {
const QModelIndex &child = index.child(i, 0);
// Recursively call the function for each child node.
expandChildren(child, view);
}
if (!view->isExpanded(index))
{
view->expand(index);
}
}
void expand_the_tree(const QModelIndex &root_index, QTreeView *view)
{
qDebug() << fs_model.canFetchMore(root_index);
while (fs_model.canFetchMore(root_index) == true)
{
fs_model.fetchMore(root_index);
}
qDebug().nospace() << "Model fetched on root layer.";
QModelIndex child_1_index;
QModelIndex child_2_index;
QModelIndex child_3_index;
view->expand(root_index);
int root_index_rows = fs_model.rowCount(root_index);
qDebug().nospace() << "Number of found profiles:" << root_index_rows;
for (int i = 0; i < root_index_rows; ++i)
{
child_1_index = fs_model.index(i,0,root_index);
view->expand(child_1_index);
expandChildren(child_1_index, view);
int child_1_index_rows = fs_model.rowCount(child_1_index);
qDebug().nospace() << "Step #" << i+1 << " Object name: " << fs_model.fileName(child_1_index) << ". Num of children: " << child_1_index_rows;
for (int j = 0; j < child_1_index_rows; ++j)
{
child_2_index = fs_model.index(j,0,child_1_index);
//qDebug() << child_2_index;
view->expand(child_2_index);
int child_2_index_rows = fs_model.rowCount(child_2_index);
qDebug().nospace() << "Step #" << i+1 << "/" << j+1 << " Object name: " << fs_model.fileName(child_1_index) << "/" << fs_model.fileName(child_2_index) << ". Num of children: " << child_2_index_rows;
for (int k = 0; k < child_2_index_rows; ++k)
{
child_3_index = fs_model.index(k,0,child_2_index);
view->expand(child_3_index);
int child_3_index_rows = fs_model.rowCount(child_3_index);
qDebug().nospace() << "Step #" << i+1 << "/" << j+1 << "/" << k+1 << " Object name: " << fs_model.fileName(child_1_index) << "/" << fs_model.fileName(child_2_index) << "/" << fs_model.fileName(child_3_index) << ". Num of children: " << child_3_index_rows;
}
}
}
}
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QApplication>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QString str_root_path;
QDir dir;
qDebug() << "Current user's home folder is: " <<QDir::home().path();
str_root_path = QDir::home().path() + "/AppData/Local/app/settings";
qDebug() << "Preset's storing folder id: " << str_root_path;
dir.setPath(str_root_path);
if (!dir.exists())
{
qDebug() << "Settings folder doesn't exist.";
return;
}
if (!dir.isReadable())
{
qDebug() << "Folder found. Read access denied. Check access rights.";
return;
}
qDebug() << "Folder found. Read access granted. Reading...";
fs_index = fs_model.index(str_root_path);
qDebug() << fs_model.fileName(fs_index);
fs_model.setRootPath(str_root_path);
QStringList filter;
filter << "*.xml";
fs_model.setNameFilters(filter);
fs_model.setFilter( QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
ui->treeView->setModel(&fs_model);
ui->treeView->setRootIndex(fs_index);
ui->treeView->setCurrentIndex(fs_index);
qDebug() << fs_model.canFetchMore(fs_index);
for (int c = 1; c < fs_model.columnCount(); c++)
{
ui->treeView->setColumnHidden(c, true);
}
qDebug().nospace() << "View loaded. Expanding....";
expand_the_tree(fs_index, ui->treeView);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_treeView_clicked(const QModelIndex &index)
{
qDebug() << index;
}
void MainWindow::on_pushButton_2_clicked()
{
expandChildren(fs_index, ui->treeView);
}
void MainWindow::on_pushButton_clicked()
{
expand_the_tree(fs_index, ui->treeView);
}
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>712</width>
<height>635</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QTreeView" name="treeView">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>311</width>
<height>531</height>
</rect>
</property>
</widget>
<widget class="QTableView" name="tableView">
<property name="geometry">
<rect>
<x>370</x>
<y>60</y>
<width>321</width>
<height>531</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>20</x>
<y>600</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Refresh</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>110</x>
<y>600</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Retrieve all</string>
</property>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>