Charming manager helps you to easily track downloading stuff from the Internet.
It informs about the download finish.
One single download is represented by DownloadProcess
It contains the URL to stuff and pointer to DownloadTable
DownloadProcess::DownloadProcess(QUrl url, DownloadTable *dataModel){
this->dataModel = dataModel;
this->url = url;
downloadTime.start();
manager = new QNetworkAccessManager(this);
}start method call the request and start the download process.
void DownloadProcess::start(){
QNetworkRequest request(url);
currentDownload = manager->get(request);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SIGNAL(downloadFinished(QNetworkReply*)));
connect(currentDownload, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64,qint64)));
}- connect
currentDownloadtrack pieces of information about the downloading process. - connect
managercall when the download process is finished.
Analogously abort method stop the download and disconnect currentDownload and manager
Track data about the downloading process and put it in the table.
void DownloadProcess::downloadProgress(qint64 received, qint64 total){
double downloadSpeedInfo = received * 1000.0 / downloadTime.elapsed();
double downloadSpeed = downloadSpeedInfo;
int progress = (100*received)/total;
size = sizeHuman(total);
QString unit;
if(downloadSpeedInfo < 1024) unit = "bytes/sec";
else if(downloadSpeedInfo < 1024 * 1024){
downloadSpeedInfo /= 1024;
unit = "kB/s";
}else{
downloadSpeedInfo /= (1024 * 1024);
unit = "MB/s";
}
QString speedFormat;
speedFormat.sprintf("%6.2f", downloadSpeedInfo);
QString speed = speedFormat + " " + unit;
int secondsToFinishDownload = (total-received)/downloadSpeed;
QString timeLeft = timeHuman(secondsToFinishDownload);
QString filenameToFind = url.fileName();
int row = dataModel->getRowOfDownloadByName(filenameToFind);
QModelIndex index = dataModel->index(row, 1, QModelIndex());
dataModel->setData(index, progress, Qt::EditRole);
index = dataModel->index(row, 2, QModelIndex());
dataModel->setData(index, size, Qt::EditRole);
index = dataModel->index(row, 3, QModelIndex());
dataModel->setData(index, speed, Qt::EditRole);
index = dataModel->index(row, 4, QModelIndex());
dataModel->setData(index, timeLeft, Qt::EditRole);
}double downloadSpeed = downloadSpeedInfo;-downloadSpeedInfoContains information in human format about speed like12 Mb/s,downloadSpeedcontains speed only in bytes, its is used to calculatesecondsToFinishDownloadQModelIndex indexIs used to put the data into correct single the data table column.
DownloadTable has a QList of singleDownloadInfo struct which contains necessary info about the download process.
struct singleDownloadInfo{
QString name;
qint64 progress;
QString size;
QString speed;
QString timeLeft;
bool operator==(const singleDownloadInfo &);
};To start new download manager needs URL to data to download.
void DownloadWidget::start(){
QString downloadUrl = getDownloadUrl();
QUrl url = QUrl::fromEncoded(downloadUrl.toLocal8Bit());
if(downloadTable->filenameExist(url.fileName())){
QMessageBox::information(this, "Duplicate data!",
tr("There is %1 already in downloads!").arg(url.fileName()));
return;
}
if(!downloadUrl.isEmpty()){
QRegularExpression urlRegex("^(?:http|ftp)s?://");
QRegularExpressionMatch match = urlRegex.match(downloadUrl);
if(!match.hasMatch()){
QMessageBox::critical(this, "Error", "Incorrect URL", QMessageBox::Ok);
return;
}
insertDownloadingFilenameInTable(url.fileName());
download(url);
}
}QString downloadUrl = getDownloadUrl();Start download dialog and return URL to data.QUrl url = QUrl::fromEncoded(downloadUrl.toLocal8Bit());Convert toQUrlif(downloadTable->filenameExist(url.fileName()))Check for this download file exists.- On true show dialog and return.
if(!downloadUrl.isEmpty())Check for URL is not empty.QRegularExpression urlRegex("^(?:http|ftp)s?://");Prepare regex to validate for URL is correct address to data.if(!match.hasMatch())On not valid show dialog and return.
insertDownloadingFilenameInTable(url.fileName());Put filename into table.download(url);Start the download process.
DownloadDialog is used to get URL from the user.
QString DownloadWidget::getDownloadUrl(){
DownloadDialog dialog;
QString getUrl;
if(dialog.exec()) getUrl = dialog.downloadUrl->text();
return getUrl;
}if(dialog.exec()) getUrl = dialog.downloadUrl->text();On the dialog work convertdownloadUrlto text and assign it intogetUrland return.
Initialize DownloadProcess with URL and start the process.
void DownloadWidget::download(QUrl &url){
DownloadProcess *downloadProcess;
downloadProcess = new DownloadProcess(url, downloadTable);
downloadProcess->start();
downloads[url.fileName()] = downloadProcess;
connect(downloadProcess, SIGNAL(downloadFinished(QNetworkReply*)), this, SLOT(downloadFinished(QNetworkReply*)));
}downloadProcess = new DownloadProcess(url, downloadTable);Initialize with url and pointer to the data table.- The pointer is required to correctly put pieces of information about the download process into the single row.
downloads[url.fileName()] = downloadProcess;downloadswhich is hashmap is used to locate currently working download process.- connect
downloadProcesson finish download.
Catch the finish signal of download and take actions.
void DownloadWidget::downloadFinished(QNetworkReply *reply){
QUrl url = reply->url();
downloads.remove(url.fileName());
if(!reply->error()){
if(isHttpRedricted(reply)) QMessageBox::information(this, "Redricted", "HTTP Redricted");
else{
QString filename = saveFileName(url);
if(saveToDisk(filename, reply))
QMessageBox::information(this, "Download successed!", tr("Download of %1 succesed!").arg(filename));
}
} else QMessageBox::warning(this, "Error", tr("Download error %1").arg(reply->errorString()));
}QUrl url = reply->url();Get url to downloaded data,replycontains informations about the server where data comes.downloads.remove(url.fileName());Data downloaded, the manager doesn't need it anymore.if(!reply->error())Check connection errors happened.if(isHttpRedricted(reply))Is HTTP redricted?- The connection is fix and download finished.
if(saveToDisk(filename, reply)Try to save data to disk.
Save downloaded stuff.
bool DownloadWidget::saveToDisk(const QString & filename, QIODevice *data){
QFile file(filename);
if(!file.open(QIODevice::WriteOnly)) return false;
file.write(data->readAll());
file.close();
return true;
}QFile file(filename);Save with downloaded filename.if(!file.open(QIODevice::WriteOnly))IO errors happened?- Everything is fix.
file.write(data->readAll());Write data.
DownloadWidget saves all data in DownloadTable and URLs of did not finish download processes on program exit.
void DownloadWidget::saveSession(){
QFile file(".downloadManagerSession");
if(file.open(QIODevice::WriteOnly)){
QDataStream stream(&file);
int row = downloadTable->rowCount(QModelIndex());
int column = downloadTable->columnCount(QModelIndex());
stream<<row<<column;
QModelIndex index;
REP(i, row){
REP(j, column){
index = downloadTable->index(i, j, QModelIndex());
stream << downloadTable->data(index, Qt::DisplayRole);
}
}
foreach(QString key, downloads.keys())
stream<<downloads.value(key)->getUrl();
}
file.close();
}- First are numbers of row and column of the data table.
- Second is downloads pieces of information.
- On
downloadscontains some data.- Save URLs.
void DownloadWidget::loadSession(){
QFile file(".downloadManagerSession");
if(file.open(QIODevice::ReadOnly)){
QDataStream stream(&file);
int row, column;
stream >> row >> column;
downloadTable->insertRows(0, row, QModelIndex());
QModelIndex index;
REP(i, row){
REP(j, column){
index = downloadTable->index(i, j);
downloadTable->setData(index, stream, Qt::EditRole);
}
}
while(!stream.atEnd()){
QUrl url;
stream >> url;
DownloadProcess *downloadProcess;
downloadProcess = new DownloadProcess(url, downloadTable);
downloads[url.fileName()] = downloadProcess;
connect(downloadProcess, SIGNAL(downloadFinished(QNetworkReply*)), this, SLOT(downloadFinished(QNetworkReply*)));
}
}
file.close();
}- Build
DownloadTableand put all the data. while(!stream.atEnd())While contains URLs.stream >> url;Get URL.downloadProcess = new DownloadProcess(url, downloadTable);Prepare the download process.downloads[url.fileName()] = downloadProcess;Put filename intodownloads- connect
downloadProcesson download finished.




