#ifndef FILEDOWNLOADER_H #define FILEDOWNLOADER_H #include #include #include #include #include #include #ifdef QT_WIDGET #include #include #include #else #include #endif //QT_WIDGET class FileDownloader : #ifdef QT_WIDGET public QProgressDialog #else public QObject #endif //QT_WIDGET { Q_OBJECT Q_PROPERTY(qint64 received READ received NOTIFY receivedChanged) Q_PROPERTY(QString status READ getStatus NOTIFY statusChanged) Q_PROPERTY(DownloadState state READ getState NOTIFY stateChanged ) Q_PROPERTY(QString state_string READ getStateString NOTIFY stateStringChanged ) Q_ENUMS(DownloadState) public: enum DownloadState { NETWORK_ERROR, DOWNLOADING_HASH, DOWNLOADING_FILE, DOWNLOADED } ; explicit FileDownloader(QString localPath, QString targetFile, QObject *parent = 0); virtual ~FileDownloader(); qint64 received() const {return m_received;}; QString getStatus() {return m_status;}; DownloadState getState() { return m_state; }; QString getStateString() { if(m_state == DOWNLOADING_HASH ) return "DOWNLOADING_HASH"; else if(m_state == DOWNLOADING_FILE ) return "DOWNLOADING_FILE"; else return "DOWNLOADED"; } signals: void receivedChanged(int value); void statusChanged(); void stateChanged(DownloadState state); void stateStringChanged(); private slots: void fileDownloaded(){ // let's check some error if(m_downloadReply->error() != QNetworkReply::NoError) { m_state = NETWORK_ERROR; } else { if(m_tmp.write(m_downloadReply->readAll()) == -1) return; if(QFile(m_localPath).exists()) QFile::remove(m_localPath); m_tmp.close(); computeLocalHash(m_tmp); if(m_localHash == m_remoteHash) { if(!m_tmp.rename(m_localPath)) return; m_tmp.setAutoRemove(false); m_state = DOWNLOADED; } else { m_state = NETWORK_ERROR; } } emit stateChanged(m_state); }; void downloadProgress(qint64 bytesReceived, qint64 bytesTotal){ if(m_tmp.write(m_downloadReply->readAll()) == -1) return; if(!bytesTotal) return; m_received = bytesReceived*100/bytesTotal; emit receivedChanged(m_received); }; void setDownloadUrl(QUrl url); void computeLocalHash(QFile& file); void requestHash(QUrl url); void computeRemoteHash(); void handleStateChange(DownloadState state){ #ifdef QT_WIDGET switch(state) { case NETWORK_ERROR: if(m_localHash == "") { setLabelText("Network Error"); setCancelButton(new QPushButton("OK")); show(); } else { emit finished(0); } break; case DOWNLOADED: emit finished(0); break; case DOWNLOADING_HASH: break; case DOWNLOADING_FILE: show(); break; } #else emit stateStringChanged(); #endif //QT_WIDGET }; #ifdef QT_WIDGET void handleCancel(){ QCoreApplication::instance()->exit(1); } #endif //QT_WIDGET private: DownloadState m_state; QNetworkAccessManager m_WebCtrl; qint64 m_received; QTemporaryFile m_tmp; QString m_targetFile; QString m_localPath; QString m_localHash; QString m_remoteHash; bool m_OK; QString m_status; QNetworkReply* m_downloadReply; QNetworkReply* m_hashReply; }; #ifndef QT_WIDGET QML_DECLARE_TYPEINFO(FileDownloader, QML_HAS_ATTACHED_PROPERTIES) #endif //QT_WIDGET #endif // FILEDOWNLOADER_H