Чтение онлайн

ЖАНРЫ

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

01 bool Spider::getDirectory(const QUrl &url)

02 {

03 if (!url.isValid) {

04 cerr << "Error: Invalid URL" << endl;

05 return false;

06 }

07 if (url.scheme != "ftp") {

08 cerr << "Error: URL must start with 'ftp:'" << endl;

09 return false;

10 }

11 ftp.connectToHost(url.host, url.port(21));

12 ftp.login;

13 QString path = url.path;

14 if (path.isEmpty)

15 path = "/";

16 pendingDirs.append(path);

17 processNextDirectory;

18 return true;

19 }

Выполнение

функции getDirectory начинается с некоторых основных проверок, и если все нормально, делается попытка установить FTP—соединение. Она отслеживает пути, которые необходимо будет обрабатывать, и вызывает функцию processNextDirectory, чтобы начать скачивание корневого каталога.

01 void Spider::processNextDirectory

02 {

03 if (!pendingDirs.isEmpty) {

04 currentDir = pendingDirs.takeFirst;

05 currentLocalDir = "downloads/" + currentDir;

06 QDir(".").mkpath(currentLocalDir);

07 ftp.cd(currentDir);

08 ftp.list;

09 } else {

10 emit done;

11 }

12 }

Функция processNextDirectory принимает первый удаленный каталог из списка каталогов, ожидающих обработки, pendingDirs, и создает соответствующий каталог в локальной файловой системе. После этого она указывает объекту QFtp на необходимость изменения каталога на принятый ею каталог и затем получения списка его файлов. Для каждого файла, обрабатываемого функцией list, генерируется сигнал listInfo, приводящий к вызову слота ftpListInfo.

Когда все каталоги оказываются обработанными, эта функция генерирует сигнал done, обозначающий завершение скачивания.

01 void Spider::ftpListInfo(const QUrlInfo &urlInfo)

02 {

03 if (urlInfo.isFile) {

04 if (urlInfo.isReadable) {

05 QFile *file = new QFile(currentLocalDir + "/"

06 + urlInfo.name);

07 if (!file->open(QIODevice::WriteOnly)) {

08 cerr << "Warning: Cannot open file << qPrintable(

09 QDir::convertSeparators(file->fileName))

10 << endl;

11 return;

12 }

13 ftp.get(urlInfo.name, file);

14 openedFiles.append(file);

15 }

16 } else if (urlInfo.isDir && !urlInfo.isSymLink) {

17 pendingDirs.append(currentDir + "/" + urlInfo.name);

18 }

19 }

Параметр urlInfo слота ftpListInfo содержит

информацию о файле в сети. Если это обычный файл (не каталог) и его можно считывать, мы вызываем функцию get для его загрузки. Объект QFile, используемый для загрузки файла, создается с помощью оператора new, и указатель на него хранится в списке openedFiles.

Если содержащиеся в QUrlInfo сведения об удаленном каталоге говорят, что он не является символической связью, этот каталог добавляется к списку pendingDirs. Мы пропускаем символические связи, поскольку они легко могут привести к бесконечной рекурсии.

01 void Spider::ftpDone(bool error)

02 {

03 if (error) {

04 cerr << "Error: " << qPrintable(ftp.errorString) << endl;

05 } else {

06 cout << "Downloaded " << qPrintable(currentDir) << " to "

07 << qPrintable(QDir::convertSeparators(

08 QDir(currentLocalDir).canonicalPath));

09 }

10 qDeleteAll(openedFiles);

11 openedFiles.clear;

12 processNextDirectory;

13 }

Слот ftpDone вызывается после завершения всех команд FTP или при возникновении ошибки. Мы удаляем объекты QFile для предотвращения утечек памяти, а также для закрытия всех файлов. Наконец, мы вызываем функцию processNextDirectory. Если какие-нибудь каталоги остались, весь процесс повторяется для следующего каталога в списке; в противном случае скачивание файлов прекращается и генерируется сигнал done.

Если ошибок нет, последовательность команд FTP и сигналов будет такой:

connectToHost(host, port)

login

cd(directory_1)

list

emit listInfo(file_1_1)

get(file_1_1)

emit listInfo(file_1_2)

get(file_1_2)

emit done

cd(directory_N)

list

emit listInfo(file_N_1)

get(file_N_1)

emit listInfo(file_N_2)

get(file_N_2)

emit done

Если файл фактически оказывается каталогом, он добавляется в список pendingDirs и, когда завершается скачивание последнего файла, полученного текущей командой list, выдается новая команда cd, за которой следует новая команда list для следующего каталога, ожидающего обработки, и весь процесс повторяется для нового каталога. Скачиваются новые файлы, и в список pendingDirs добавляются новые каталоги до тех пор, пока не будут скачаны все файлы из всех каталогов и список pendingDirs в результате не станет пустым.

Поделиться с друзьями: