summaryrefslogblamecommitdiffstats
path: root/src/DownloadManager.cpp
blob: 5c2b123ba1d99d61d82f22deb34c34f16dad84c3 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                            
                 
                    
 
                                    
                                                                                           



                                           
                                                 










                                                                                                        
                                                      
                                                                      



                                                   
                                                                                           
                                                  
                                                                              
                                              
 
                                                                                           
                                                       
 





                                                                                  


                                                            
                                                                                            
                                                                     
                                 

                       
                                                                 
                         
                                                                       
                            
 
                                                                                           
                                         
 

                          
                                          
                                                                     

                       

                                                                                  
                                        
                                 
 
                                 
                                 
                                                       


                                                                                
                                                                                 




                                                                                           
                                                 

                                                
                                                                                          

                                    
         
                                          
                                                                                          
                                     
                                             
                                                       

                                                               
                                                                                   


                       
                            
                                                                                            

                                                                                       

                                                                                              
                                                                                           
                                                                                     

                                                                                           
                                     
  
                                                        
                                                  
 
                                                                                           
                                                            

                                                                         
 
                                                                                           
                                                                 







                                                                            
 


                                                                                           

                                        
                                                                             
                                          

                                                                                          
                             
                        
                                       
                     
                    

                                          
                                          
                                                                     
                       
         
                                                     
                            
 
 
#include "DownloadManager.h"
//#include <QDir>
#include <QFileInfo>

int DownloadManager::downloaded = 0;
// ----------------------------------------------------------------------------------------
DownloadManager::DownloadManager()
{
	qnam = new QNetworkAccessManager();
	dip = false;
	// the whole QDir thing is questionable..
	downloadDir = QDir(downloadPath);
	// Check if downloadPath exists, if not create it.
	if (!downloadDir.exists()){
		if (debug) qDebug() << "Download directory: " << downloadDir.path() << "doesn't exist.";
		QDir::current().mkdir(downloadPath);
		if (downloadDir.exists() && debug)
			qDebug() << "Created download directory: " << downloadDir.path();
	}
	else if (debug) qDebug() << "Download directory: " << downloadDir.path() << "exists.";
}
// ----------------------------------------------------------------------------------------
void DownloadManager::downloadFile(QString& filename){
	if (debug) qDebug() << "DM received signal for: " << filename;
	QUrl fileUrl;
	fileUrl = baseURL.resolved(QUrl(filename));
	this->processDownloadRequest(fileUrl);
}
// ----------------------------------------------------------------------------------------
void DownloadManager::downloadFile(QUrl& fileUrl){
	if (debug) qDebug() << "Received downloadFile signal for:" << fileUrl;
	this->processDownloadRequest(fileUrl);
}
// ----------------------------------------------------------------------------------------
void DownloadManager::processDownloadRequest(QUrl& url)
{
	// Test on empty URL in case such a call happens, which should not
	// happen given how javascriptInterface::startDownload(..) is implemented.
	if (url.isEmpty()){
		if (debug) qDebug() << "No URL specified for download.";
		return;
	}
	// If download in progress, enqueue file and return.
	if (dip)
	{
		if (debug) qDebug() << "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);
	if (debug) qDebug() << "Enqueueing:" << url.toString() << endl;
	startNextDownload();
}
// ----------------------------------------------------------------------------------------
void DownloadManager::startNextDownload()
{
	if (dlQ.isEmpty())
	{
		emit downloadQueueEmpty();
		if (debug) qDebug() << "Download manager ready. (1)";
		return;
	}
	if (debug) qDebug() << "Starting next download: " << dlQ.head().toString()
			 << "(" << dlQ.size() << "in queue.)";
	// Dequeue next URL to download.
	QUrl url = dlQ.dequeue();

	// Get filename from URL.
	QString tmp = url.path();
	tmp.remove(0, tmp.lastIndexOf(QChar('/')) + 1);
	if (debug) qDebug() << "Extracted " << tmp << "from " << url.toString();
	// TODO: check for if relative path, if so prepend binPath
	outfile.setFileName(downloadPath + "/" + tmp);
	if (debug) qDebug() << "Trying to save to: " << downloadPath + "/" + tmp;
	if (outfile.exists()){
		if (debug) qDebug() << "File already exists. Skipping: " << url.toString();
		startNextDownload();
		return;
	}
	// If error upon opening, skip this file.
	if (!outfile.open(QIODevice::WriteOnly))
	{
		if (debug) qDebug() << "Couldn't open file! Skipping: " << url.toString();
		startNextDownload();
		return;
	}
	// Start the request for this URL.
	if (debug) qDebug() << "Saving " << url.toString() << "to " << outfile.fileName();
	QNetworkRequest request(url);
	currentDownload = qnam->get(request);
	// TODO: Error handling not working properly...
	if (currentDownload->error() != QNetworkReply::NoError)
	{
		if (debug) qDebug() << "Network reply error, skipping download...";
		return;
	}
	dip = true;
	currentProgress = 0;
	QObject::connect(currentDownload, SIGNAL(readyRead()), this, SLOT(downloadReady()));
	QObject::connect(currentDownload, SIGNAL(downloadProgress(qint64, qint64)),
					 this, SLOT(downloadProgress(qint64, qint64)));
	QObject::connect(currentDownload, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
// ----------------------------------------------------------------------------------------
//									Private slots
// ----------------------------------------------------------------------------------------
// This slot listens to readyRead() emmited when data is available for reading.
void DownloadManager::downloadReady()
{ 
	// readyRead() fired, so save the readable data.
	outfile.write(currentDownload->readAll());
}
// ----------------------------------------------------------------------------------------
// This triggers sends the update progress back to the site.
void DownloadManager::downloadProgress(qint64 bytesIn, qint64 bytesTotal)
{

	if (debug) qDebug() << "Download progress of " << currentDownload->url().toString()
			 << ": " << bytesIn << "/" << bytesTotal;

	int tmp = ((bytesIn * 100) / bytesTotal);
	if (tmp > currentProgress){
		currentProgress = tmp;
		emit updateProgress(currentDownload->url().toString(), tmp);
	}
	// Progress difference < 1%
	return;
}
// ----------------------------------------------------------------------------------------
// This slot listens to the finished() which is emmited
// when all the data from the reply has been read.
void DownloadManager::downloadFinished()
{
	// Second check if the download actually is finished just to be sure.
	if (currentDownload->isFinished())
		if (debug) qDebug() << "Download of " << currentDownload->url().toString()
							<< "finished." << endl;
	// Close output file.
	outfile.close();
	currentDownload->deleteLater();
	downloaded++;
	dip = false;
	// If queue is empty, we are done.
	if (dlQ.isEmpty()){
		emit downloadQueueEmpty();
		if (debug) qDebug() << "Download manager ready. (2)";
		return;
	}
	// Queue not empty: initialise next download.
	startNextDownload();
}