Шаг 93.
Библиотека Qt.
Класс QDir. Просмотр содержимого каталога

    На этом шаге рассмотрим возможность просмотра содержимого каталога при помощи класса QDir.

    При помощи класса QDir можно получить содержимое указанного каталога. При этом допускается применять различные фильтры, чтобы исключить из списка не интересующие вас файлы. Для этих целей в классе определены методы entryList() и entryInfoList(). Первый возвращает список имен элементов (QStringList), а второй — информационный список (QFileInfoList). Если вам нужно узнать лишь количество элементов, находящихся в каталоге, то просто вызовите метод count().

    Программа, окно которой показано на рис. 1, осуществляет рекурсивный поиск файлов в каталоге, указанном в текстовом поле Directory (Каталог).

    Результат работы приложения можно увидеть на рисунке 1.


Рис.1. Программа отображения файлов каталога по маске

    Нажатие кнопки с растровым изображением откроет диалоговое окно выбора нужного каталога. В текстовом поле Mask (Маска) задается фильтр для отображаемых файлов. Например, для отображения исходных файлов на языке C++ нужно задать в поле Mask (Маска) *.cpp и *.h. После нажатия кнопки Find (Поиск) выполняется поиск и отображение файлов в соответствии с заданными параметрами. Результаты отображаются в виджете многострочного текстового поля. Подсчитывается количество файлов, соответствующих маске поиска, в указанном каталоге и всех подкаталогах.

    Рассмотрим реализацию конструктора класса FileFinder.

//Создаются виджеты однострочного и многострочного
//текстовых полей (указатели Directory, Mask и Result).
//Первый виджет инициализируется абсолютным путем,
//возвращаемым методом QDir::absolutePath(), который,
//в свою очередь, инициализируется значением текущего 
//каталога, возвращаемым методом QDir::current()
Directory    = new QLineEdit(QDir::current().absolutePath());
//Второй виджет инициализируется строкой,
//предназначенной для фильтрации найденных файлов
Mask   = new QLineEdit("*.cpp *.h");
Result = new QTextEdit;
//создаются виджеты надписей
QLabel*      labelDirectory  = new QLabel("&Каталог");
QLabel*      labelMask = new QLabel("&Маска");
labelCount = new QLabel("Количество файлов: ");

//Для открытия диалогового окна выбора каталога и запуска 
//операции поиска создаются две кнопки (указатели ButFind 
//и ButDirectory), которые соединяются со слотами slotFind() и slotBrowse()
QPushButton* ButDirectory  = new QPushButton(QPixmap(fileopen), "");
QPushButton* ButFind = new QPushButton("&Найти");
connect(ButDirectory, SIGNAL(clicked()), SLOT(slotBrowse()));
connect(ButFind, SIGNAL(clicked()), SLOT(slotFind()));
//виджеты надписей с помощью метода setBuddy() 
//ассоциируются с виджетами однострочных текстовых полей 
labelDirectory->setBuddy(Directory);
labelMask->setBuddy(Mask);
//Созданные виджеты размещаются в виде таблицы
//при помощи объекта класса QGridLayout 
QGridLayout* pgrdLayout = new QGridLayout;
pgrdLayout->setMargin(5);
pgrdLayout->setSpacing(15);
pgrdLayout->addWidget(labelDirectory, 0, 0);
pgrdLayout->addWidget(labelMask, 1, 0);
pgrdLayout->addWidget(Directory, 0, 1);
pgrdLayout->addWidget(Mask, 1, 1);
pgrdLayout->addWidget(ButDirectory, 0, 2);
pgrdLayout->addWidget(ButFind, 1, 2);
pgrdLayout->addWidget(labelCount, 2, 0, 1, 3);
pgrdLayout->addWidget(Result, 3, 0, 1, 3);
setLayout(pgrdLayout);

    Ниже приведен метод slotBrowse(), который открывает диалоговое окно для выбора каталога поиска. После закрытия этого окна выбранный каталог записывается в текстовое поле Directory (Каталог) методом setText().

//Очистка многострочного текстового поля
Result->clear();
//Открывается диалоговое окно для выбора папки
QString str = QFileDialog::getExistingDirectory(0,
              "Выбор каталога", Directory->text());
//Если выбран каталог, то
if (!str.isEmpty())
{
    //путь до него записывается в текстовое поле
    Directory->setText(str);
}   

    Метод slotFind() запускает операцию поиска, для чего передает в метод start() выбранный пользователем каталог и выводит количество найденных файлов.

//переменная для подсчета количества найденных файлов
i=0;
Result->clear();
//вызов метода start()
start(QDir(Directory->text()));
QString stri = QString::number(i);
//вывод значения переменной i
labelCount->setText("Количество файлов: "+stri); 

    Метод start() использует рекурсию для поиска по подкаталогам.

//Процесс поиска заданных файлов может быть длительным,
//что может привести к "замиранию" графического интерфейса программы.
//Поэтому для подавления этого нежелательного эффекта при каждом вызове метода
//мы вызываем метод QApplication::processEvents() и даем возможность
//обработаться накопившимся событиям.
QApplication::processEvents();
//Переменная listFiles получает список файлов текущего каталога,
//соответствующих маске. Для этого в метод передаются два параметра.
//Первый представляет собой список шаблонов поиска, которые распространяются  
//на имена и расширения файлов. В нашем случае мы преобразуем строку в список,
//разделив ее при помощи пробелов вызовом QString::split(). 
//Второй параметр (флаг QDir::Files) говорит о том,
//что список должен содержать только файлы.
QStringList listFiles =
    dir.entryList(Mask->text().split(" "), QDir::Files);
//Подсчитываем количество найденных по маске файлов в текущем каталоге
i=i+dir.entryList(Mask->text().split(" "), QDir::Files).count();
//Элементы полученного списка добавляются в виджет многострочного 
//текстового поля с помощью метода append()
foreach (QString file, listFiles) {
    Result->append(dir.absoluteFilePath(file));
  }
//В метод entryList() передается флаг QDir::Dirs для получения списка каталогов. 
//Для каждого из элементов списка, кроме "." и "..", вызывается метод start().
QStringList listDir = dir.entryList(QDir::Dirs);
foreach (QString subdir, listDir) {
    if (subdir == "." || subdir == "..") {
        continue;
        }
    start(QDir(dir.absoluteFilePath(subdir)));
    }

    Файлы приложения можно взять здесь.

    Также можно использовать метод entryList() без указания параметров. В этом случае сами критерии фильтрации можно задать при помощи метода setFilter(). Дополнительно можно так же задать критерий сортировки списка, при помощи метода setSorting(). В следующем примере мы получаем список скрытых файлов, отсортированных по их величине (рис. 2):


Рис.2. Сортировка скрытых файлов по размеру

QDir dir;
dir.setFilter(QDir::Files | QDir::Hidden);
dir.setSorting(QDir::Size);
//создаем список имен файлов и их атрибутов, согласно
//условиям фильтрации и сортировки
QFileInfoList list = dir.entryInfoList();
qDebug() <<"    Размер Имя файла" ;
for (int i = 0; i < list.size(); ++i) {
    //создаем объект класса QFileInfo
    QFileInfo fileInfo = list.at(i);
    //qPrintable() преобразует QString в const char *
    qDebug() << qPrintable(QString("%1 %2").arg(fileInfo.size(), 10)
                          .arg(fileInfo.fileName()));
}

    Файлы приложения можно взять здесь.

    На следующем шаге рассмотрим класс QFileInfo.




Предыдущий шаг Содержание Следующий шаг