Читаем QT 4: программирование GUI на С++ полностью

Теперь мы рассмотрим более сложный пример. Программа командной строки spider (паук) скачивает все файлы, расположенные в каталоге FTP—сервера, рекурсивно просматривая каждый его подкаталог. Вся логика работы с сетью содержится в классе Spider:

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 openedFiles;

16 QString currentDir;

17 QString currentLocalDir;

18 QStringList pendingDirs;

19 };

Начальный каталог определяется как объект типа QUrl и устанавливается при помощи функции getDirectory.

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 }

В конструкторе мы устанавливаем два соединения сигнал—слот. Когда мы выдаем запрос на получение списка элементов каталога в getDirectory, QFtp генерирует сигнал listInfo(const QUrlInfo &) для каждого найденного имени. Этот сигнал подключается к слоту с именем ftpListInfo, который скачивает файл из сети по указанному адресу URL.

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) {

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже