#include "downloadManager.h" #include "fbgui.h" int downloadManager::downloaded = 0; // ---------------------------------------------------------------------------------------- downloadManager::downloadManager() { qxtLog->debug() << "Initializing download manager..."; checkDownloadDirectory(); qnam = new QNetworkAccessManager(); dip = false; } // ---------------------------------------------------------------------------------------- void downloadManager::checkDownloadDirectory(){ /* check if downloadPath exists, if not create it. */ QDir downloadDir = QDir(downloadPath); if (!downloadDir.exists()){ qxtLog->debug() << "Download directory: " << downloadDir.path() << " doesn't exist."; QDir::current().mkdir(downloadPath); if (downloadDir.exists()){ qxtLog->debug() << "Created download directory: " << downloadDir.path(); } else { qxtLog->debug() << "Failed to create directory: " << downloadDir.path(); emit notify(QString("Failed to create download directory!")); } } else qxtLog->debug() << "Download directory: " << downloadDir.path() << " exists."; } // ---------------------------------------------------------------------------------------- void downloadManager::downloadFile(QString& filename) { QUrl fileUrl(baseURL.resolved(QUrl(filename))); this->processDownloadRequest(fileUrl); } // ---------------------------------------------------------------------------------------- void downloadManager::downloadFile(QUrl& fileUrl) { this->processDownloadRequest(fileUrl); } // ---------------------------------------------------------------------------------------- void downloadManager::processDownloadRequest(QUrl& url) { if (url.isEmpty()){ qxtLog->debug() << "No URL specified for download."; return; } /* if download in progress, enqueue file and return. */ if (dip){ qxtLog->debug() << "Download in progress! Enqueueing:" << url.toString() << "(" << dlQ.size() << " in queue)"; dlQ.enqueue(url); return; } /* no running downloads: enqueue and start next download. */ dlQ.enqueue(url); qxtLog->debug() << "Enqueueing:" << url.toString(); startNextDownload(); } // ---------------------------------------------------------------------------------------- void downloadManager::startNextDownload() { if (dlQ.isEmpty()){ emit downloadQueueEmpty(); qxtLog->debug() << "Download manager ready. (1)"; return; } qxtLog->debug() << "Starting next download: " << dlQ.head().toString() << " (" << dlQ.size() - 1 << " in queue.)"; /* dequeue next URL to download. */ QUrl url = dlQ.dequeue(); /* get temporary filename from URL. */ QString tmp = url.path(); tmp.remove(0, tmp.lastIndexOf(QChar('/')) + 1); /* check if filename exists on target file system */ QFileInfo fi(downloadPath + "/" + tmp); if (fi.exists()){ QString qs = QString(fi.absoluteFilePath() + ".\%1").arg(downloaded); outfile.setFileName(qs); } else outfile.setFileName(downloadPath + "/" + tmp); if (!outfile.open(QIODevice::WriteOnly)){ qxtLog->debug() << "Couldn't open file! Skipping..."; emit notify(QString("Couldn't open " + downloadPath + "/" + tmp + "! Skipping...")); return; } /* send the request for the file */ QNetworkRequest request(url); currentDownload = qnam->get(request); lastProgress = 0; currentProgress = 0; dip = true; dltime.start(); QObject::connect(currentDownload, SIGNAL(readyRead()), this, SLOT(downloadReady())); QObject::connect(currentDownload, SIGNAL(metaDataChanged()), this, SLOT(processMetaInfo())); QObject::connect(currentDownload, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64))); QObject::connect(currentDownload, SIGNAL(finished()), this, SLOT(downloadFinished())); } // ---------------------------------------------------------------------------------------- // Private slots // ---------------------------------------------------------------------------------------- void downloadManager::processMetaInfo(){ /* fetch filesize from header & filename from url (for now) */ const QByteArray cltag = "Content-Length"; QByteArray clinfo = currentDownload->rawHeader(cltag); QFileInfo fi(outfile); emit downloadInfo(outfile.fileName(), clinfo.toDouble()); } // ---------------------------------------------------------------------------------------- void downloadManager::downloadReady() { /* data ready, save it */ outfile.write(currentDownload->readAll()); } // ---------------------------------------------------------------------------------------- void downloadManager::downloadProgress(qint64 bytesIn, qint64 bytesTotal) { if (bytesIn > bytesTotal) return; /* calculate current speed */ double speed = bytesIn * 1000 / dltime.elapsed(); QString unit; if (speed < 1024) { unit = "bytes/sec"; } else if (speed < 1024*1024) { speed /= 1024; unit = "KB/s"; } else { speed /= 1024*1024; unit = "MB/s"; } /* update progress only if difference higher than the updateInterval setting */ currentProgress = ((bytesIn * 100) / bytesTotal); if (currentProgress - lastProgress >= updateInterval){ lastProgress = currentProgress; emit updateProgress(currentProgress, speed, unit); qxtLog->debug() << "Download progress of " << currentDownload->url().toString() << ": " << bytesIn << "/" << bytesTotal << "(" << currentProgress << "\%)"; } return; } // ---------------------------------------------------------------------------------------- void downloadManager::downloadFinished() { /* check for errors */ if (currentDownload->error()){ currentDownload->deleteLater(); outfile.remove(); int statusCode = currentDownload->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); qxtLog->debug() << "Download of " << currentDownload->url().toString() << " failed with HTTP error code: " << statusCode; emit notify(QString("HTTP Error: %1").arg(statusCode)); } else{ /* end download */ currentDownload->deleteLater(); outfile.close(); downloaded++; qxtLog->debug() << "Download of " << currentDownload->url().toString() << " finished. (downloaded = "<< downloaded << ")"; } dip = false; /* process next in queue */ if (dlQ.isEmpty()){ emit downloadQueueEmpty(); qxtLog->debug() << "Download manager ready. (2)"; return; } startNextDownload(); } /* ---------------------------------------------------------------------------------------- * ** dead code: Header filename fetching & renaming ** const QByteArray cd = "Content-Disposition"; QByteArray cdc = currentDownload->rawHeader(cd); int x = cdc.indexOf("filename=\"") + 10; cdc.remove(0, x).chop(1); if (!cdc.isEmpty()) currentTargetFilename = cdc; else currentTargetFilename = QString("download.\%1").arg(downloaded); QString tmp = outfile.fileName(); tmp.remove(0, tmp.lastIndexOf(QChar('/')) + 1); qDebug() << "Trying to rename " << tmp << " to --> " << currentTargetFilename; if (outfile.rename(downloadPath + "/" + currentTargetFilename)) { qxtLog->debug() << "Renamed file!"; } else { qxtLog->debug() << "Failure to rename file!"; } */