Теперь мы рассмотрим более сложный пример. Программа командной строки spider (паук) скачивает все файлы, расположенные в каталоге FTP—сервера, рекурсивно просматривая каждый его подкаталог. Вся логика работы с сетью содержится в классе
01 class Spider : public QObject
02 {
03 Q_OBJECT
04 public:
05 Spider(QObject *parent = 0);
06 bool getDirectory(const QUrl &url);
07 signals:
08 void done;
09 private slots:
10 void ftpDone(bool error);
11 void ftpListInfo(const QUrlInfo &urlInfo);
12 private:
13 void processNextDirectory;
14 QFtp ftp;
15 QList
16 QString currentDir;
17 QString currentLocalDir;
18 QStringList pendingDirs;
19 };
Начальный каталог определяется как объект типа
01 Spider::Spider(QObject *parent)
02 : QObject(parent)
03 {
04 connect(&ftp, SIGNAL(done(bool)), this, SLOT(ftpDone(bool)));
05 connect(&ftp, SIGNAL(listInfo(const QUrlInfo &)),
06 this, SLOT(ftpListInfo(const QUrlInfo &)));
07 }
В конструкторе мы устанавливаем два соединения сигнал—слот. Когда мы выдаем запрос на получение списка элементов каталога в
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 }
Выполнение функции
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 }
Функция
Когда все каталоги оказываются обработанными, эта функция генерирует сигнал
01 void Spider::ftpListInfo(const QUrlInfo &urlInfo)
02 {
03 if (urlInfo.isFile) {
04 if (urlInfo.isReadable) {