Russian Qt Forum

Qt => Дополнительные компоненты => Тема начата: IGHOR от Август 07, 2009, 00:48



Название: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: IGHOR от Август 07, 2009, 00:48
Я написал универсальный класс для поиска файлов в папках JulyScanDir.
Используя его можно сделать прогрессбар перебора файлов или что-то другое не нагружая основной поток

Пример использования запуска с одной строки параметров:
Код:
JulyScanDir *scanDir = new JulyScanDir(this);
             scanDir->scanDir("C:\\Films","*.avi");  // задание параметров поиска и запуск

Пример использования запуска с отдельными параметрами:
Код:
JulyScanDir *scanDir = new JulyScanDir(this);
             scanDir->setStartDir("C:\\Films"); // задает папку или список папок разделенных ;; или через QStringList
             scanDir->setSearchSubFolders(false); // ищем файлы только в одной папке
             scanDir->setSubFoldersFirst(true);   // класс в текущей директории сначала сканирует папки а потом файлы
QStringList  filtersList;
             filtersList << "*.avi" << "*.mpg";   // задание маски файлов
             scanDir->setFilesFilter(filtersList);
             scanDir->scanDir();                // запуск поиска

В ответ получаем сигналы которые можно прикрутить к переменной класса:
Код:
void dirChanged(QString);      // Во время поиска возвращает полный адрес следующей директории
void fileChanged(QString);     // Во время поиска возвращает полный адрес текущего файла
void fileChanged(QFileInfo);   // Во время поиска возвращает полную информацию о файле
void numChanged(int);          // Во время поиска возвращает последовательный номер найденого файла
void loadedList(QStringList);  // По завершению поиска возвращает список найденых файлов
void errorHeppend(int);        // Если случилась ошибка то возвращает: 0 если не найдено никаких файлов
                               // и 1 если заданая папка поиска не существует

При начале сканирования и по окончании fileChanged возвращает пустую строку (так удобнее при перерисовке результата)

Добавлено:
Код:
void setIgnoreDirs(QStringList); // задает список полных адресов папок что будут пропущены в поиске
void setIgnoreDirs(QString); // задает одну папку что будет пропущена в поиске или список папок через ;;
void clearIgnoreDirs(); // очищает и отключает список игнорируемых папок
void setRegExp(QRegExp fileRegExp); // задание регулярного выражения, если оно верно к имени файла он будет выведен в результате, в противном случае пропущен
void clearRegExp();  // очищает и отключает RegExp
void setScanHidden(bool hidden); // задает фильтр поиска, искать ли скрытые файлы и папки

setStartDir(), setIgnoreDirs(), setFilesFilter() задаються как QStringList так и QString.
QString будет разбит на список разделенный ;;

Надеюсь услышать критику, отзывы о работе и помощь в улучшении класса

Прикрепленная в файлах версия класса: v1.25


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отд&
Отправлено: Пантер от Август 07, 2009, 06:19
> scanDir->setSearchSubFolders(false); // ищем файлы только в одной папке
Сделай еще уровень рекурсии.
> void fileChanged(QString)
Еще добавь fileChanged(QFileInfo)

Регекспы поддерживает?
===============================
Убери банер в подписи.
Еще нужно scanDir->setStartDirs(QStringList()) и scanDir->setIgnoreDirs(QStringList())


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: IGHOR от Август 07, 2009, 13:35
scanDir->setSearchSubFolders(false); заменю на scanDir->setSubFoldersLevel(int);
добавлю void fileChanged(QFileInfo),
> Еще нужно scanDir->setStartDirs(QStringList()) и scanDir->setIgnoreDirs(QStringList())
ето мне понравилось, постараюсь сегодня ето дописать.
А с регекспами ето для чего? Для поиска имен файлов по маске?


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отд&
Отправлено: Пантер от Август 07, 2009, 17:44
Угу. Регекспы бывают очень необходимы.
Нужно будет дополнить поиском по атрибутам(время, дата, и т.п.) и сохранением поисковых запросов, если конечно захочешь. Если что, обращайся, мне все равно такое нужно в PantherCommander, так что можем твой вариант довести до ума и я его себе включу. Если, конечно, будешь не против. ;)


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: IGHOR от Август 07, 2009, 19:02
panter_dsd, с регекспами я ещё не пробовал ничего, буду рад помощи в до-писании класса,
сохранение поисковых запросов думаю ето дело проги к которой подключается класс,
а сам класс должен только прошвырнуться по файлах и возвращать их свойства на все случаи жизни.
И конечно я не против чтобы вы использовали его в PantherCommander, заодно будет возможность его хорошо протестировать.
Думаю многим Qt программерам пригодиться этот класс, буду рад комментариям от тестеров класса.


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: IGHOR от Август 08, 2009, 01:05
Файлы обновил. Тестируйте. Глубину рекурсии потом допишу, когда обдумаю насколько оно нужно и в чем может применяться.


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: IGHOR от Октябрь 07, 2009, 21:10
Кто еще пробовал? Все работает хорошо?


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: pastor от Октябрь 07, 2009, 21:55
Глубину рекурсии потом допишу, когда обдумаю насколько оно нужно и в чем может применяться.

Рекурсия ненужна. Можно обойтись и без нее, при помощи листа:

Код
C++ (Qt)
QFileInfoList dirs;
dirs << QFileInfo( path );
while ( !dirs.isEmpty() )
{
 
 QFileInfo dirInfo = dirs.takeFirst();
 for ( QListIterator<QFileInfo> it( QDir( dirInfo.path() ).entryInfoList( flags ) ); it.hasNext(); )
 {
   const QFileInfo & newDirInfo = it.next();
   // handle it
   dirs << newDirInfo;
 }
}

Также обрати внимание на QDirIterator


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: IGHOR от Октябрь 08, 2009, 19:39
pastor, очень спасибо
изучу QFileInfoList и QDirIterator
так же проверю производительность двух вариантов и отпишусь о результатах


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: CProger от Апрель 03, 2010, 21:21
pastor
Вы не подскажите почему у меня не работает Ваш код?
Я вот так его подызменил (на месте flags):
Код
C++ (Qt)
QFileInfoList dirs;
dirs << QFileInfo( "." );
 
while ( !dirs.isEmpty() ) {
 
QFileInfo dirInfo = dirs.takeFirst();
 
for ( QListIterator<QFileInfo> it( QDir( dirInfo.path() ).entryInfoList( QDir::NoDotAndDotDot ) ); it.hasNext(); ) {
 
const QFileInfo & newDirInfo = it.next();
dirs << newDirInfo;
 
}
}
 

но вот на это ругается (gcc):
Код:
main.cpp: In member function ‘void MyClass::MyFunc()’:
main.cpp:46: ошибка: invalid use of incomplete type ‘struct QDir’
/usr/include/qt4/QtCore/qfileinfo.h:55: ошибка: forward declaration of ‘struct QDir’
main.cpp:46: ошибка: неполный тип ‘QDir’ использован во вложенном спецификаторе имени
make: *** [main.o] Ошибка 1
смущает вот эта ошибка: "forward declaration of ‘struct QDir’". Посмотрел документацию к этой функции.. да вроде ничего плохого...))


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: niXman от Апрель 03, 2010, 22:21
Цитировать
Посмотрел документацию к этой функции
это класс.

Цитировать
почему у меня не работает Ваш код?
#include <QtCore/QDir>


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: CProger от Апрель 03, 2010, 22:57
Точно! Спасибо!

Код заработал, сейчас он такой у меня. Но знаете.. он почему-то зацикливается :) Он выводит в цикле все имена файлов текущей директории и так до бесконечности.. т.е. чередуются имён пять файлов) Не знаете почему такое может быть?
Код
C++ (Qt)
QFileInfoList dirs;
 
dirs << QFileInfo( "." );
 
while ( !dirs.isEmpty() ) {
 
QFileInfo dirInfo = dirs.takeFirst();
 
for ( QListIterator<QFileInfo> it( QDir( dirInfo.path() ).entryInfoList( QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files ) ); it.hasNext(); ) {
 
const QFileInfo &newDirInfo = it.next();
dirs << newDirInfo;
 
printf( "%s\n", newDirInfo.absoluteFilePath().toAscii().constData() );
 
}
 
}
 


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: Kolobok от Апрель 03, 2010, 23:40
Код:
while ( !dirs.isEmpty() )

Чего ты хотел добиться этой строчкой?


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: CProger от Апрель 03, 2010, 23:45
Код:
while ( !dirs.isEmpty() )

Чего ты хотел добиться этой строчкой?
а я и не подумал над этой строчкой, скопировал вышеприведённый код. Подумал.. ну видимо цикл продолжается до тех пор пока список директорий не пуст. Как только пуст, так я понимаю - завершиться должен.. но не завершается.. :)


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: niXman от Апрель 04, 2010, 00:49
вообще-то, тот код, какой-то мудреный.
Код
C++ (Qt)
void ScanDir(const QString& path) {
QDirIterator it(path,
QDir::Files|QDir::Dirs|QDir::NoDotAndDotDot,
QDirIterator::Subdirectories
);
while ( it.hasNext() ) {
QFileInfo fi = it.fileInfo();
               ...
it.next();
}
}
 
 


Название: Re: JulyScanDir - класс рекурсивного поиска файлов в отдельном потоке
Отправлено: IGHOR от Апрель 11, 2010, 20:18
Мой клас можно заменить двумя строчками и поместить их в QThread:
Код:
QDirIterator dirScan(someDir,fileMask, QDir::Files | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot ,QDirIterator::Subdirectories);
while(dirScan.hasNext())filesList << dirScan.next();
Примечание что и в моем классе и в этом примере если маска файлов *.* то не будут копироваться файлы без расширения поэтому чтобы искать все файлы использовать надо * (может кто-то тоже на это не обратил внимание)