hugoruscitti/pilas

View on GitHub
pilas/descargar.py

Summary

Maintainability
A
25 mins
Test Coverage
# -*- encoding: utf-8 -*-
# pilas engine - a video game framework.
#
# copyright 2010 - hugo ruscitti
# license: lgplv3 (see http://www.gnu.org/licenses/lgpl.html)
#
# website - http://www.pilas-engine.com.ar
#
# Creditos: http://stackoverflow.com/questions/6852038/threading-in-pyqt4

from PyQt4.QtCore import QUrl, QFile, QIODevice
from PyQt4.QtGui import QDialog, QProgressBar
from PyQt4.QtGui import QLabel, QPushButton, QDialogButtonBox, QVBoxLayout, QMessageBox
from PyQt4.QtNetwork import QHttp
import os


class Descargar(QDialog):

    def __init__(self, parent, url, archivo_destino):
        super(Descargar, self).__init__(parent)

        self.url = url
        self.httpGetId = 0
        self.httpRequestAborted = False
        self.statusLabel = QLabel('Descargando el manual completo ...')
        self.closeButton = QPushButton("Cerrar")
        self.closeButton.setAutoDefault(False)
        self.barra = QProgressBar()

        buttonBox = QDialogButtonBox()
        buttonBox.addButton(self.closeButton, QDialogButtonBox.RejectRole)

        self.http = QHttp(self)
        self.http.requestFinished.connect(self.cuando_finalizar_request)
        self.http.dataReadProgress.connect(self.cuando_actualiza_descarga)
        self.http.responseHeaderReceived.connect(self.cuando_responder_header)
        self.closeButton.clicked.connect(self.cuando_cancela)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.statusLabel)
        mainLayout.addWidget(self.barra)
        mainLayout.addWidget(buttonBox)
        self.setLayout(mainLayout)

        self.setWindowTitle('Descargando manual')
        self.downloadFile(url, archivo_destino)

    def downloadFile(self, url, archivo_destino):
        url = QUrl(url)
        fileName = archivo_destino
        directorio_usuario_para_pilas = os.path.dirname(archivo_destino)

        if not os.path.exists(directorio_usuario_para_pilas):
            os.mkdir(directorio_usuario_para_pilas)

        if QFile.exists(fileName):
            QFile.remove(fileName)

        self.outFile = QFile(fileName)

        if not self.outFile.open(QIODevice.WriteOnly):
            QMessageBox.information(self, 'Error', 'Lo siento, no se puede descargar el archivo desde %s: %s.' % (self.url, self.outFile.errorString()))
            self.outFile = None
            return

        mode = QHttp.ConnectionModeHttp
        port = url.port()
        if port == -1:
            port = 0
        self.http.setHost(url.host(), mode, port)
        self.httpRequestAborted = False

        path = QUrl.toPercentEncoding(url.path(), "!$&'()*+,;=:@/")
        if path:
            path = str(path)
        else:
            path = '/'

        self.httpGetId = self.http.get(path, self.outFile)

    def cuando_cancela(self):
        self.statusLabel.setText("Descarga cancelada")
        self.httpRequestAborted = True
        self.http.abort()
        self.close()

    def cuando_finalizar_request(self, request_id, error):
        if request_id != self.httpGetId:
            return

        if self.httpRequestAborted:
            if self.outFile is not None:
                self.outFile.close()
                self.outFile.remove()
                self.outFile = None
            return

        self.outFile.close()

        if error:
            self.outFile.remove()
            QMessageBox.information(self, 'Error', u'Hay un error de conexión: %s.' % self.http.errorString())

        self.statusLabel.setText(u'Perfecto, ahora podrás explorar el manual.')

    def cuando_responder_header(self, responseHeader):
        if responseHeader.statusCode() not in (200, 300, 301, 302, 303, 307):
            mensaje = 'Ha fallado la descarga del archivo: \n"%s" \n%s.' %(self.url, responseHeader.reasonPhrase())
            QMessageBox.information(self, 'Error', mensaje)

            self.httpRequestAborted = True
            self.http.abort()
            self.close()

    def cuando_actualiza_descarga(self, bytes_leidos, total_bytes):
        if self.httpRequestAborted:
            return

        self.barra.setMaximum(total_bytes)
        self.barra.setValue(bytes_leidos)