コード例 #1
0
class HistoriqueTests( unittest.TestCase ):
	
	## Initialisation
	def setUp( self ):
		self.historique = Historique()
		
	## Fin
	def tearDown( self ):
		pass
	
	def testSingleton( self ):
		"""Test si le pattern singleton est bien en place"""
		self.assertEqual( id( self.historique ), id( Historique() ) )
	
	def testMauvaisType( self ):
		"""Test si l'historique renvoit bien faux si on lui demande s'il contient une variable qui n'est pas un fichier"""
		variable = "jeSuisUnString"
		self.assertEqual( self.historique.comparerHistorique( variable ), False )
	
	def testPresenceElement( self ):
		"""Test si l'historique est capable de retrouver un element"""
		element = Fichier( "Napoleon", "1804", "Notre Dame", "Sacre Napoleon" )
		# On ajoute l'element a l'historique
		self.historique.ajouterHistorique( element )
		# On verifie si l'element y est present
		self.assertEqual( self.historique.comparerHistorique( element ), True )
コード例 #2
0
class HistoriqueTests(unittest.TestCase):

    ## Initialisation
    def setUp(self):
        self.historique = Historique()

    ## Fin
    def tearDown(self):
        pass

    def testSingleton(self):
        """Test si le pattern singleton est bien en place"""
        self.assertEqual(id(self.historique), id(Historique()))

    def testMauvaisType(self):
        """Test si l'historique renvoit bien faux si on lui demande s'il contient une variable qui n'est pas un fichier"""
        variable = "jeSuisUnString"
        self.assertEqual(self.historique.comparerHistorique(variable), False)

    def testPresenceElement(self):
        """Test si l'historique est capable de retrouver un element"""
        element = Fichier("Napoleon", "1804", "Notre Dame", "Sacre Napoleon")
        # On ajoute l'element a l'historique
        self.historique.ajouterHistorique(element)
        # On verifie si l'element y est present
        self.assertEqual(self.historique.comparerHistorique(element), True)
コード例 #3
0
ファイル: PluzzDL.py プロジェクト: btuduri/tvdownloader
	def __init__( self, m3u8URL, nomFichier, navigateur, stopDownloadEvent, progressFnct ):
		self.m3u8URL = m3u8URL
		self.nomFichier = nomFichier
		self.navigateur = navigateur
		self.stopDownloadEvent = stopDownloadEvent
		self.progressFnct = progressFnct

		self.historique = Historique()

		self.nomFichierFinal = "%s.mkv" % ( self.nomFichier[ :-3 ] )
コード例 #4
0
ファイル: PluzzDL.py プロジェクト: btuduri/tvdownloader
	def __init__( self, manifestURL, nomFichier, navigateur, stopDownloadEvent, progressFnct ):
		self.manifestURL = manifestURL
		self.nomFichier = nomFichier
		self.navigateur = navigateur
		self.stopDownloadEvent = stopDownloadEvent
		self.progressFnct = progressFnct

		self.historique = Historique()
		self.configuration = Configuration()
		self.hmacKey = self.configuration[ "hmac_key" ].decode( "hex" )
		self.playerHash = self.configuration[ "player_hash" ]
コード例 #5
0
ファイル: PluzzDL.py プロジェクト: pierri/Pluzz
	def __init__( self, m3u8URL, nomFichier, navigateur, stopDownloadEvent, progressFnct ):
		self.m3u8URL = m3u8URL
		self.nomFichier = nomFichier
		self.navigateur = navigateur
		self.stopDownloadEvent = stopDownloadEvent
		self.progressFnct = progressFnct

		self.historique = Historique()

		self.nomFichierFinal = "%s.mkv" % ( self.nomFichier[ :-3 ] )
コード例 #6
0
ファイル: PluzzDL.py プロジェクト: pierri/Pluzz
	def __init__( self, manifestURL, nomFichier, navigateur, stopDownloadEvent, progressFnct ):
		self.manifestURL = manifestURL
		self.nomFichier = nomFichier
		self.navigateur = navigateur
		self.stopDownloadEvent = stopDownloadEvent
		self.progressFnct = progressFnct

		self.historique = Historique()
		self.configuration = Configuration()
		self.hmacKey = self.configuration[ "hmac_key" ].decode( "hex" )
		self.playerHash = self.configuration[ "player_hash" ]
コード例 #7
0
ファイル: DownloaderM3u8.py プロジェクト: pacomod/replaydlr
 def __init__(self,
              m3u8Url,
              outDir,
              codeProgramme,
              timeStamp,
              navigateur,
              stopDownloadEvent,
              progressFnct):
     self.m3u8Url = m3u8Url
     super(DlM3u8, self).__init__(outDir, codeProgramme, timeStamp, "ts",
                                  navigateur, stopDownloadEvent, progressFnct)
     self.historique = Historique()
コード例 #8
0
    def __init__(self):

        # On cree l'instance de la classe dialog
        self.dialog = Dialog()
        self.dialog.setBackgroundTitle("TVDownloader")

        # On recupere l'instance de API
        self.api = API.getInstance()
        # On instancie le gestionnaire de download
        self.downloader = Downloader()
        # On instancie le gestionnaire d'historique
        self.historique = Historique()
        # On instancie le gestionnaire de preferences
        self.preferences = Preferences()

        # Liste des telechargements
        self.listeTelechargements = []

        # Quand le programme se termine, on execute la fonction actionsAvantQuitter
        atexit.register(self.actionsAvantQuitter)

        # On commence
        self.bouclePrincipale()
コード例 #9
0
ファイル: DownloaderF4m.py プロジェクト: pacomod/replaydlr
    def __init__(self,
                 manifestUrl,
                 manifestUrlToken,
                 outDir,
                 codeProgramme,
                 timeStamp,
                 navigateur,
                 stopDownloadEvent,
                 progressFnct):
        self.manifestUrl = manifestUrl
        self.manifestUrlToken = manifestUrlToken
        super(DlF4m, self).__init__(outDir, codeProgramme, timeStamp, "tmp.flv",
                                    navigateur, stopDownloadEvent, progressFnct)

        self.historique = Historique()
        self.configuration = Configuration()
        self.hmacKey = self.configuration["hmac_key"].decode("hex")
        self.playerHash = self.configuration["player_hash"]
コード例 #10
0
def Menu_principal():
    os.system('cls')
    print("--".center(92, "-"))
    print("{0:^32}".format("RESTO DU PEUPLE").center(92, "-"))
    print("{0:^32}".format("18 RUE DU CUL").center(92, "-"))
    print("{0:^32}".format("TOMBOUKTOU").center(92, "-"))
    print("--".center(92, "-"))

    print("\nMENU PRINCIPAL :\n")

    print("1. PRISE DE COMMANDE")
    print("2. GESTION DES STOCK")
    print("3. GESTION DU MENU")
    print("4. HISTORIQUE DES COMMANDES")
    print("5. QUITTER")

    choice = 0
    while choice != 5:
        choice = int(input("\nQUE VOULEZ VOUS FAIRE ? (1-5)  :  "))

        if choice == 1:
            Commande()
            Menu_principal()
            return
        elif choice == 2:
            Stock()
            Menu_principal()
            return
        elif choice == 3:
            Gestionnaire_menu()
            Menu_principal()
            return
        elif choice == 4:
            Historique()
            Menu_principal()
            return
コード例 #11
0
ファイル: MainWindow.py プロジェクト: btuduri/tvdownloader
    def __init__(self):
        # Appel au constructeur de la classe mere
        QtGui.QMainWindow.__init__(self)

        ###########
        # Fenetre #
        ###########

        ###
        # Reglages de la fenetre principale
        ###

        # Nom de la fenetre
        self.setWindowTitle("TVDownloader")
        # Mise en place de son icone
        self.setWindowIcon(QtGui.QIcon("ico/TVDownloader.png"))

        ###
        # Mise en place des widgets dans la fenetre
        ###

        # Widget central qui contiendra tout
        self.centralWidget = QtGui.QWidget(self)

        #
        # Barre du haut
        #

        # Layout horizontal qui contiendra les listes deroulantes
        self.horizontalLayoutBarreHaut = QtGui.QHBoxLayout()

        # Liste deroulante pour choisir le site (plugin)
        self.comboBoxSite = QtGui.QComboBox(self.centralWidget)
        self.horizontalLayoutBarreHaut.addWidget(self.comboBoxSite)

        # Liste deroulante pour choisir une chaine du site courant
        self.comboBoxChaine = QtGui.QComboBox(self.centralWidget)
        self.horizontalLayoutBarreHaut.addWidget(self.comboBoxChaine)

        # Liste deroulante pour choisir une emission de la chaine courante
        self.comboBoxEmission = QtGui.QComboBox(self.centralWidget)
        self.horizontalLayoutBarreHaut.addWidget(self.comboBoxEmission)

        #
        # Onglets
        #

        # Gestionnaire onglets
        self.tabWidget = QtGui.QTabWidget(self.centralWidget)

        # Onglet Fichiers
        self.tabFichiers = QtGui.QSplitter(
            self.centralWidget)  # L'onglet Fichier contient un splitter
        self.tabWidget.addTab(self.tabFichiers, u"Choix des fichiers")

        # Onglet Telechargements
        self.tabTelechargements = QtGui.QWidget(self.centralWidget)
        self.tabWidget.addTab(self.tabTelechargements, u"Téléchargements")

        #
        # Liste des fichiers
        #

        # Layout de grille qui contient le tableau qui liste les fichiers + boutons
        self.gridLayoutFichiers = QtGui.QGridLayout(self.tabFichiers)

        # Tableau qui contient la liste des fichiers disponibles pour l'emission courante
        self.tableWidgetFichier = MyQTableWidget(self.tabFichiers)
        # Il a 4 colonnes et 0 ligne (pour l'instant)
        self.tableWidgetFichier.setColumnCount(3)
        self.tableWidgetFichier.setRowCount(0)
        # On ajoute les titres
        self.tableWidgetFichier.setHorizontalHeaderItem(
            0, self.tableWidgetFichier.creerItem(""))
        self.tableWidgetFichier.setHorizontalHeaderItem(
            1, self.tableWidgetFichier.creerItem("Date"))
        self.tableWidgetFichier.setHorizontalHeaderItem(
            2, self.tableWidgetFichier.creerItem("Emission"))
        # On l'ajoute au layout
        self.gridLayoutFichiers.addWidget(self.tableWidgetFichier, 0, 1, 6, 1)

        # Icones du tableWidget
        self.iconeFichier = QtGui.QIcon("ico/gtk-file.svg")
        self.iconeAjoute = QtGui.QIcon("ico/gtk-add.svg")
        self.iconeTelecharge = QtGui.QIcon("ico/gtk-apply.svg")

        # Bouton pour ajouter tous les fichiers a la liste des telechargements
        self.pushButtonToutAjouter = MyQPushButton(self.tabFichiers)
        self.pushButtonToutAjouter.setIcon(QtGui.QIcon("ico/gtk-add.svg"))
        self.pushButtonToutAjouter.setToolTip(
            u"Ajouter tous les fichiers à la liste des téléchargements")
        self.gridLayoutFichiers.addWidget(self.pushButtonToutAjouter, 0, 0, 2,
                                          1)

        # Bouton pour rafraichir le plugin courant
        self.pushButtonRafraichirPlugin = MyQPushButton(self.tabFichiers)
        self.pushButtonRafraichirPlugin.setIcon(
            QtGui.QIcon("ico/gtk-refresh.svg"))
        self.pushButtonRafraichirPlugin.setToolTip("Rafraichir le plugin")
        self.gridLayoutFichiers.addWidget(self.pushButtonRafraichirPlugin, 2,
                                          0, 2, 1)

        # Bouton pour ouvrir la fenetre des preferences du plugin courant
        self.pushButtonPreferencesPlugin = MyQPushButton(self.tabFichiers)
        self.pushButtonPreferencesPlugin.setIcon(
            QtGui.QIcon("ico/gtk-preferences.svg"))
        self.pushButtonPreferencesPlugin.setToolTip(
            u"Ouvrir les préférences du plugin")
        self.gridLayoutFichiers.addWidget(self.pushButtonPreferencesPlugin, 4,
                                          0, 2, 1)

        # On met en place ce layout sur un widget (pour le splitter)
        self.widgetFichiers = QtGui.QWidget()
        self.widgetFichiers.setLayout(self.gridLayoutFichiers)

        #
        # Descriptif des fichiers
        #

        # Layout de grille
        self.gridLayoutDescriptif = QtGui.QGridLayout()

        # Label pour afficher un logo
        self.logoFichierDefaut = QtGui.QPixmap()
        self.logoFichierDefaut.load("img/gtk-dialog-question.svg")

        self.labelLogo = QtGui.QLabel(self.centralWidget)
        self.labelLogo.setPixmap(
            self.logoFichierDefaut.scaled(QtCore.QSize(150, 150),
                                          QtCore.Qt.KeepAspectRatio))

        self.gridLayoutDescriptif.addWidget(self.labelLogo, 0, 0, 1, 1)

        # Zone de texte pour afficher un descriptif
        self.plainTextEdit = QtGui.QPlainTextEdit(self.centralWidget)
        self.gridLayoutDescriptif.addWidget(self.plainTextEdit, 0, 1, 1, 2)

        # On met en place ce layout sur un widget (pour le splitter)
        self.widgetDescriptif = QtGui.QWidget()
        self.widgetDescriptif.setLayout(self.gridLayoutDescriptif)

        # Onrientation verticale du splitter
        self.tabFichiers.setOrientation(QtCore.Qt.Vertical)

        # On ajoute les 2 elements au splitter (qui est notre onglet)
        self.tabFichiers.addWidget(self.widgetFichiers)
        self.tabFichiers.addWidget(self.widgetDescriptif)

        #
        # Liste des telechargements
        #

        # Layout de grille qui contient le tableau qui liste les fichiers a telecharger + les boutons pour le controller
        self.gridLayoutTelechargement = QtGui.QGridLayout(
            self.tabTelechargements)

        # Tableau qui contient la liste des fichiers a telecharger
        self.tableWidgetTelechargement = MyQTableWidget(
            self.tabTelechargements)
        # Il a 5 colonnes et 0 ligne (pour l'instant)
        self.tableWidgetTelechargement.setColumnCount(3)
        self.tableWidgetTelechargement.setRowCount(0)
        # On ajoute le titre des 5 colonnes
        self.tableWidgetTelechargement.setHorizontalHeaderItem(
            0, self.tableWidgetTelechargement.creerItem("Date"))
        self.tableWidgetTelechargement.setHorizontalHeaderItem(
            1, self.tableWidgetTelechargement.creerItem("Emission"))
        self.tableWidgetTelechargement.setHorizontalHeaderItem(
            2, self.tableWidgetTelechargement.creerItem("Etat"))
        # On l'ajoute au layout
        self.gridLayoutTelechargement.addWidget(self.tableWidgetTelechargement,
                                                0, 1, 4, 1)

        # Bouton pour monter l'element selectionne tout en haut de la liste
        self.pushButtonExtremiteMonter = MyQPushButton(self.tabTelechargements)
        self.pushButtonExtremiteMonter.setIcon(
            QtGui.QIcon("ico/gtk-jump-to-rtl.svg"))
        self.pushButtonExtremiteMonter.setToolTip(
            u"Placer l'élément sélectionné tout en haut")
        self.gridLayoutTelechargement.addWidget(self.pushButtonExtremiteMonter,
                                                0, 0, 1, 1)

        # Bouton pour monter l'element selectionne d'un cran dans la liste
        self.pushButtonMonter = MyQPushButton(self.tabTelechargements)
        self.pushButtonMonter.setIcon(QtGui.QIcon("ico/gtk-go-up.svg"))
        self.pushButtonMonter.setToolTip(u"Monter l'élément sélectionné")
        self.gridLayoutTelechargement.addWidget(self.pushButtonMonter, 1, 0, 1,
                                                1)

        # Bouton pour descendre l'element selectionne d'un cran dans la liste
        self.pushButtonDescendre = MyQPushButton(self.tabTelechargements)
        self.pushButtonDescendre.setIcon(QtGui.QIcon("ico/gtk-go-down.svg"))
        self.pushButtonDescendre.setToolTip(u"Descendre l'élément selectionné")
        self.gridLayoutTelechargement.addWidget(self.pushButtonDescendre, 2, 0,
                                                1, 1)

        # Bouton pour descendre l'element selectionne tout en bas de la liste
        self.pushButtonExtremiteDescendre = MyQPushButton(
            self.tabTelechargements)
        self.pushButtonExtremiteDescendre.setIcon(
            QtGui.QIcon("ico/gtk-jump-to-ltr.svg"))
        self.pushButtonExtremiteDescendre.setToolTip(
            u"Placer l'élément sélectionné tout en bas")
        self.gridLayoutTelechargement.addWidget(
            self.pushButtonExtremiteDescendre, 3, 0, 1, 1)

        # Bouton pour supprimer tous les elements de la liste
        self.pushButtonToutSupprimer = MyQPushButton(self.tabTelechargements)
        self.pushButtonToutSupprimer.setIcon(QtGui.QIcon("ico/gtk-cancel.svg"))
        self.pushButtonToutSupprimer.setToolTip(
            u"Supprimer tous les téléchargements")
        self.gridLayoutTelechargement.addWidget(self.pushButtonToutSupprimer,
                                                0, 2, 1, 1)

        # Bouton pour supprimer de la liste les telechargements termines
        self.pushButtonNettoyer = MyQPushButton(self.tabTelechargements)
        self.pushButtonNettoyer.setIcon(QtGui.QIcon("ico/gtk-delete-full.svg"))
        self.pushButtonNettoyer.setToolTip(
            u"Supprimer les téléchargement terminés")
        self.gridLayoutTelechargement.addWidget(self.pushButtonNettoyer, 1, 2,
                                                1, 1)

        # Bouton pour ouvrir le dossier des telechargements
        self.pushButtonOuvrirDossierTelechargement = MyQPushButton(
            self.tabTelechargements)
        self.pushButtonOuvrirDossierTelechargement.setIcon(
            QtGui.QIcon("ico/gtk-folder.svg"))
        self.pushButtonOuvrirDossierTelechargement.setToolTip(
            u"Ouvrir le dossier des téléchargements")
        self.gridLayoutTelechargement.addWidget(
            self.pushButtonOuvrirDossierTelechargement, 2, 2, 1, 1)

        #
        # Barre progression de telechargement d'un fichier
        #
        self.progressBarTelechargementFichier = QtGui.QProgressBar(
            self.centralWidget)
        self.progressBarTelechargementFichier.setProperty("value", 0)

        #
        # Barre de progression de telechargement des fichiers
        #
        self.progressBarTelechargement = QtGui.QProgressBar(self.centralWidget)
        self.progressBarTelechargement.setProperty("value", 0)

        #
        # Boutons du bas pour gerer ajouter/supprimer/lancer telechargements
        #

        # Layout horizontal qui contiendra les boutons
        self.horizontalLayoutBarreBas = QtGui.QHBoxLayout()

        # Bouton pour lancer les telechargements
        self.pushButtonLancer = QtGui.QPushButton(
            QtGui.QIcon("ico/gtk-media-play-ltr.svg"),
            u"Lancer téléchargement", self.centralWidget)
        self.horizontalLayoutBarreBas.addWidget(self.pushButtonLancer)

        # Bouton pour stopper les telechargements
        self.pushButtonStop = QtGui.QPushButton(
            QtGui.QIcon("ico/gtk-media-stop.svg"),
            u"Stopper le téléchargement", self.centralWidget)
        self.pushButtonStop.setEnabled(False)
        self.horizontalLayoutBarreBas.addWidget(self.pushButtonStop)

        ###
        # Positionnement des differents widgets/layouts sur le layout de grille
        ###

        # Layout de grille dans lequel on va placer nos widgets/layouts
        self.gridLayout = QtGui.QGridLayout(self.centralWidget)
        # On ajoute la barre du haut
        self.gridLayout.addLayout(self.horizontalLayoutBarreHaut, 0, 0, 1, 3)
        # On ajoute le gestionnaire d'onglets
        self.gridLayout.addWidget(self.tabWidget, 1, 0, 1, 3)
        # On ajoute la barre de progression de telechargement d'un fichier
        self.gridLayout.addWidget(self.progressBarTelechargementFichier, 2, 0,
                                  1, 3)
        # On ajoute la barre de progression de telechargement des fichiers
        self.gridLayout.addWidget(self.progressBarTelechargement, 3, 0, 1, 3)
        # On ajoute les boutons ajouter/supprimer/lancer
        self.gridLayout.addLayout(self.horizontalLayoutBarreBas, 4, 0, 1, 3)

        ###
        # Mise en place le central widget dans la fenetre
        ###
        self.setCentralWidget(self.centralWidget)

        ###
        # Mise en place du menu
        ###

        # Menu barre
        self.menubar = QtGui.QMenuBar(self)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 480, 25))

        # Menu Fichier
        self.menuFichier = QtGui.QMenu("&Fichier", self.menubar)
        self.menubar.addAction(self.menuFichier.menuAction())

        # Action Fichier -> Quitter
        self.actionQuitter = QtGui.QAction(QtGui.QIcon("ico/gtk-quit.svg"),
                                           "&Quitter", self)
        self.actionQuitter.setIconVisibleInMenu(True)
        self.menuFichier.addAction(self.actionQuitter)

        # Menu Edition
        self.menuEdition = QtGui.QMenu("&Edition", self.menubar)
        self.menubar.addAction(self.menuEdition.menuAction())

        # Action Edition -> Mise a jour
        self.actionMAJ = QtGui.QAction(QtGui.QIcon("ico/gtk-refresh.svg"),
                                       u"&Mise à jour des plugins", self)
        self.actionMAJ.setIconVisibleInMenu(True)
        self.menuEdition.addAction(self.actionMAJ)

        # Action Edition -> Preferences
        self.actionPreferences = QtGui.QAction(
            QtGui.QIcon("ico/gtk-preferences.svg"), u"&Préférences", self)
        self.actionPreferences.setIconVisibleInMenu(True)
        self.menuEdition.addAction(self.actionPreferences)

        # Menu Aide
        self.menuAide = QtGui.QMenu("&Aide", self.menubar)
        self.menubar.addAction(self.menuAide.menuAction())

        # Action Aide -> A propos
        self.actionAPropos = QtGui.QAction(QtGui.QIcon("ico/gtk-about.svg"),
                                           u"À p&ropos", self)
        self.actionAPropos.setIconVisibleInMenu(True)
        self.menuAide.addAction(self.actionAPropos)

        # Ajout du menu a l'interface
        self.setMenuBar(self.menubar)

        ###
        # Signaux provenants de l'interface
        ###

        QtCore.QObject.connect(self.tableWidgetFichier,
                               QtCore.SIGNAL("cellClicked(int,int)"),
                               self.afficherInformationsFichier)

        QtCore.QObject.connect(self.tableWidgetFichier,
                               QtCore.SIGNAL("cellDoubleClicked(int,int)"),
                               self.gererTelechargement)

        QtCore.QObject.connect(self.pushButtonToutAjouter,
                               QtCore.SIGNAL("clicked()"),
                               self.ajouterTousLesFichiers)

        QtCore.QObject.connect(self.pushButtonRafraichirPlugin,
                               QtCore.SIGNAL("clicked()"),
                               self.rafraichirPlugin)

        QtCore.QObject.connect(self.tableWidgetTelechargement,
                               QtCore.SIGNAL("cellDoubleClicked(int,int)"),
                               self.supprimerTelechargement)

        QtCore.QObject.connect(
            self.pushButtonExtremiteMonter,
            QtCore.SIGNAL("clicked()"),
            lambda versLeHaut=True, extremite=True: self.
            tableWidgetTelechargement.deplacerLigne(versLeHaut, extremite))

        QtCore.QObject.connect(
            self.pushButtonMonter,
            QtCore.SIGNAL("clicked()"),
            lambda versLeHaut=True, extremite=False: self.
            tableWidgetTelechargement.deplacerLigne(versLeHaut, extremite))

        QtCore.QObject.connect(
            self.pushButtonDescendre,
            QtCore.SIGNAL("clicked()"),
            lambda versLeHaut=False, extremite=False: self.
            tableWidgetTelechargement.deplacerLigne(versLeHaut, extremite))

        QtCore.QObject.connect(
            self.pushButtonExtremiteDescendre,
            QtCore.SIGNAL("clicked()"),
            lambda versLeHaut=False, extremite=True: self.
            tableWidgetTelechargement.deplacerLigne(versLeHaut, extremite))

        QtCore.QObject.connect(self.pushButtonToutSupprimer,
                               QtCore.SIGNAL("clicked()"),
                               self.supprimerTousLesTelechargements)

        QtCore.QObject.connect(self.pushButtonNettoyer,
                               QtCore.SIGNAL("clicked()"), self.nettoyer)

        QtCore.QObject.connect(self.pushButtonLancer,
                               QtCore.SIGNAL("clicked()"),
                               self.lancerTelechargement)

        QtCore.QObject.connect(self.pushButtonStop, QtCore.SIGNAL("clicked()"),
                               self.stopperTelechargement)

        QtCore.QObject.connect(self.actionQuitter,
                               QtCore.SIGNAL("triggered()"), self.close)

        ################################################
        # Instanciations + initialisation de variables #
        ################################################

        # Fenetre About
        self.aProposDialog = None
        # Fenetre des preferences du logiciel
        self.preferencesDialog = None
        # Fenetre de mise a jour des plugins
        self.updateManagerDialog = None
        # Nom plugin courant
        self.nomPluginCourant = ""
        # Liste des fichiers
        self.listeFichiers = []
        # Liste des fichiers a telecharger
        self.listeFichiersATelecharger = []
        # Cache des images descriptive
        # Clef : urlImage Valeur : image (binaire)
        self.cacheImage = {}

        # On intancie le lanceur de signaux
        self.signaux = Signaux()
        # On instancie le gestionnaire de preferences
        self.preferences = Preferences()
        # On instancie le gestionnaire de preferences des plugins
        self.preferencesPluginDialog = PreferencePluginDialog(self)
        # On instancie le gestionnaire de download
        self.downloader = Downloader(self.signaux)
        # On recupere l'instance de API
        self.api = API.getInstance()
        # On instancie le gestionnaire d'historique
        self.historique = Historique()
        # On instancie la fenetre d'attente
        self.fenetreAttenteProgressDialog = FenetreAttenteProgressDialog(self)
        # On instancie le gest

        #
        # Fenetre de confirmation pour quitter le logiciel
        #
        self.quitterMessageBox = QtGui.QMessageBox(self)
        self.quitterMessageBox.setWindowTitle("Fermeture de TVDownloader")
        self.quitterMessageBox.setText(
            u"Voulez-vous réellement quitter TVDownloader ?")
        self.quitterMessageBox.setInformativeText(
            u"Votre liste de téléchargement sera perdue")
        self.quitterMessageBox.addButton("Oui", QtGui.QMessageBox.AcceptRole)
        self.quitterMessageBox.addButton("Non", QtGui.QMessageBox.RejectRole)

        ############################################################
        # On connecte les signaux des instances precedements crees #
        ############################################################

        QtCore.QObject.connect(self.pushButtonOuvrirDossierTelechargement,
                               QtCore.SIGNAL("clicked()"),
                               self.ouvrirRepertoireTelechargement)

        QtCore.QObject.connect(self.comboBoxSite,
                               QtCore.SIGNAL("activated(QString)"),
                               self.listerChaines)

        QtCore.QObject.connect(self.comboBoxChaine,
                               QtCore.SIGNAL("activated(QString)"),
                               self.listerEmissions)

        QtCore.QObject.connect(self.comboBoxEmission,
                               QtCore.SIGNAL("activated(QString)"),
                               self.listerFichiers)

        QtCore.QObject.connect(self.pushButtonPreferencesPlugin,
                               QtCore.SIGNAL("clicked()"),
                               self.ouvrirPreferencesPlugin)

        QtCore.QObject.connect(self.actionPreferences,
                               QtCore.SIGNAL("triggered()"),
                               self.ouvrirPreferencesLogiciel)

        QtCore.QObject.connect(self.actionMAJ, QtCore.SIGNAL("triggered()"),
                               self.ouvrirFenetreMiseAJour)

        QtCore.QObject.connect(self.actionAPropos,
                               QtCore.SIGNAL("triggered()"),
                               self.ouvrirFenetreAPropos)

        QtCore.QObject.connect(
            self.signaux, QtCore.SIGNAL("debutActualisation(PyQt_PyObject)"),
            self.fenetreAttenteProgressDialog.ouvrirFenetreAttente)
        QtCore.QObject.connect(
            self.signaux, QtCore.SIGNAL("finActualisation()"),
            self.fenetreAttenteProgressDialog.fermerFenetreAttente)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("actualiserListesDeroulantes()"),
                               self.actualiserListesDeroulantes)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("listeChaines(PyQt_PyObject)"),
                               self.ajouterChaines)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("listeEmissions(PyQt_PyObject)"),
                               self.ajouterEmissions)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("listeFichiers(PyQt_PyObject)"),
                               self.ajouterFichiers)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("nouvelleImage(PyQt_PyObject)"),
                               self.mettreEnPlaceImage)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("debutTelechargement(int)"),
                               self.debutTelechargement)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("finTelechargement(int)"),
                               self.finTelechargement)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("finDesTelechargements()"),
                               self.activerDesactiverInterface)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("pourcentageFichier(int)"),
                               self.progressBarTelechargementFichier.setValue)

        #########
        # Début #
        #########

        # La fenetre prend la dimension qu'elle avait a sa fermeture
        taille = self.preferences.getPreference("tailleFenetre")
        self.resize(taille[0], taille[1])

        # Si aucun plugin n'est active, on ouvre la fenetre des preferences
        if (len(self.preferences.getPreference("pluginsActifs")) == 0):
            self.ouvrirPreferencesLogiciel()

        # On actualise tous les plugins
        self.rafraichirTousLesPlugins()
コード例 #12
0
ファイル: MainWindow.py プロジェクト: btuduri/tvdownloader
class MainWindow(QtGui.QMainWindow):

    ## Constructeur
    # Le constructeur va creer la fenetre principale en y ajoutant tous les widgets necessaires au programme
    def __init__(self):
        # Appel au constructeur de la classe mere
        QtGui.QMainWindow.__init__(self)

        ###########
        # Fenetre #
        ###########

        ###
        # Reglages de la fenetre principale
        ###

        # Nom de la fenetre
        self.setWindowTitle("TVDownloader")
        # Mise en place de son icone
        self.setWindowIcon(QtGui.QIcon("ico/TVDownloader.png"))

        ###
        # Mise en place des widgets dans la fenetre
        ###

        # Widget central qui contiendra tout
        self.centralWidget = QtGui.QWidget(self)

        #
        # Barre du haut
        #

        # Layout horizontal qui contiendra les listes deroulantes
        self.horizontalLayoutBarreHaut = QtGui.QHBoxLayout()

        # Liste deroulante pour choisir le site (plugin)
        self.comboBoxSite = QtGui.QComboBox(self.centralWidget)
        self.horizontalLayoutBarreHaut.addWidget(self.comboBoxSite)

        # Liste deroulante pour choisir une chaine du site courant
        self.comboBoxChaine = QtGui.QComboBox(self.centralWidget)
        self.horizontalLayoutBarreHaut.addWidget(self.comboBoxChaine)

        # Liste deroulante pour choisir une emission de la chaine courante
        self.comboBoxEmission = QtGui.QComboBox(self.centralWidget)
        self.horizontalLayoutBarreHaut.addWidget(self.comboBoxEmission)

        #
        # Onglets
        #

        # Gestionnaire onglets
        self.tabWidget = QtGui.QTabWidget(self.centralWidget)

        # Onglet Fichiers
        self.tabFichiers = QtGui.QSplitter(
            self.centralWidget)  # L'onglet Fichier contient un splitter
        self.tabWidget.addTab(self.tabFichiers, u"Choix des fichiers")

        # Onglet Telechargements
        self.tabTelechargements = QtGui.QWidget(self.centralWidget)
        self.tabWidget.addTab(self.tabTelechargements, u"Téléchargements")

        #
        # Liste des fichiers
        #

        # Layout de grille qui contient le tableau qui liste les fichiers + boutons
        self.gridLayoutFichiers = QtGui.QGridLayout(self.tabFichiers)

        # Tableau qui contient la liste des fichiers disponibles pour l'emission courante
        self.tableWidgetFichier = MyQTableWidget(self.tabFichiers)
        # Il a 4 colonnes et 0 ligne (pour l'instant)
        self.tableWidgetFichier.setColumnCount(3)
        self.tableWidgetFichier.setRowCount(0)
        # On ajoute les titres
        self.tableWidgetFichier.setHorizontalHeaderItem(
            0, self.tableWidgetFichier.creerItem(""))
        self.tableWidgetFichier.setHorizontalHeaderItem(
            1, self.tableWidgetFichier.creerItem("Date"))
        self.tableWidgetFichier.setHorizontalHeaderItem(
            2, self.tableWidgetFichier.creerItem("Emission"))
        # On l'ajoute au layout
        self.gridLayoutFichiers.addWidget(self.tableWidgetFichier, 0, 1, 6, 1)

        # Icones du tableWidget
        self.iconeFichier = QtGui.QIcon("ico/gtk-file.svg")
        self.iconeAjoute = QtGui.QIcon("ico/gtk-add.svg")
        self.iconeTelecharge = QtGui.QIcon("ico/gtk-apply.svg")

        # Bouton pour ajouter tous les fichiers a la liste des telechargements
        self.pushButtonToutAjouter = MyQPushButton(self.tabFichiers)
        self.pushButtonToutAjouter.setIcon(QtGui.QIcon("ico/gtk-add.svg"))
        self.pushButtonToutAjouter.setToolTip(
            u"Ajouter tous les fichiers à la liste des téléchargements")
        self.gridLayoutFichiers.addWidget(self.pushButtonToutAjouter, 0, 0, 2,
                                          1)

        # Bouton pour rafraichir le plugin courant
        self.pushButtonRafraichirPlugin = MyQPushButton(self.tabFichiers)
        self.pushButtonRafraichirPlugin.setIcon(
            QtGui.QIcon("ico/gtk-refresh.svg"))
        self.pushButtonRafraichirPlugin.setToolTip("Rafraichir le plugin")
        self.gridLayoutFichiers.addWidget(self.pushButtonRafraichirPlugin, 2,
                                          0, 2, 1)

        # Bouton pour ouvrir la fenetre des preferences du plugin courant
        self.pushButtonPreferencesPlugin = MyQPushButton(self.tabFichiers)
        self.pushButtonPreferencesPlugin.setIcon(
            QtGui.QIcon("ico/gtk-preferences.svg"))
        self.pushButtonPreferencesPlugin.setToolTip(
            u"Ouvrir les préférences du plugin")
        self.gridLayoutFichiers.addWidget(self.pushButtonPreferencesPlugin, 4,
                                          0, 2, 1)

        # On met en place ce layout sur un widget (pour le splitter)
        self.widgetFichiers = QtGui.QWidget()
        self.widgetFichiers.setLayout(self.gridLayoutFichiers)

        #
        # Descriptif des fichiers
        #

        # Layout de grille
        self.gridLayoutDescriptif = QtGui.QGridLayout()

        # Label pour afficher un logo
        self.logoFichierDefaut = QtGui.QPixmap()
        self.logoFichierDefaut.load("img/gtk-dialog-question.svg")

        self.labelLogo = QtGui.QLabel(self.centralWidget)
        self.labelLogo.setPixmap(
            self.logoFichierDefaut.scaled(QtCore.QSize(150, 150),
                                          QtCore.Qt.KeepAspectRatio))

        self.gridLayoutDescriptif.addWidget(self.labelLogo, 0, 0, 1, 1)

        # Zone de texte pour afficher un descriptif
        self.plainTextEdit = QtGui.QPlainTextEdit(self.centralWidget)
        self.gridLayoutDescriptif.addWidget(self.plainTextEdit, 0, 1, 1, 2)

        # On met en place ce layout sur un widget (pour le splitter)
        self.widgetDescriptif = QtGui.QWidget()
        self.widgetDescriptif.setLayout(self.gridLayoutDescriptif)

        # Onrientation verticale du splitter
        self.tabFichiers.setOrientation(QtCore.Qt.Vertical)

        # On ajoute les 2 elements au splitter (qui est notre onglet)
        self.tabFichiers.addWidget(self.widgetFichiers)
        self.tabFichiers.addWidget(self.widgetDescriptif)

        #
        # Liste des telechargements
        #

        # Layout de grille qui contient le tableau qui liste les fichiers a telecharger + les boutons pour le controller
        self.gridLayoutTelechargement = QtGui.QGridLayout(
            self.tabTelechargements)

        # Tableau qui contient la liste des fichiers a telecharger
        self.tableWidgetTelechargement = MyQTableWidget(
            self.tabTelechargements)
        # Il a 5 colonnes et 0 ligne (pour l'instant)
        self.tableWidgetTelechargement.setColumnCount(3)
        self.tableWidgetTelechargement.setRowCount(0)
        # On ajoute le titre des 5 colonnes
        self.tableWidgetTelechargement.setHorizontalHeaderItem(
            0, self.tableWidgetTelechargement.creerItem("Date"))
        self.tableWidgetTelechargement.setHorizontalHeaderItem(
            1, self.tableWidgetTelechargement.creerItem("Emission"))
        self.tableWidgetTelechargement.setHorizontalHeaderItem(
            2, self.tableWidgetTelechargement.creerItem("Etat"))
        # On l'ajoute au layout
        self.gridLayoutTelechargement.addWidget(self.tableWidgetTelechargement,
                                                0, 1, 4, 1)

        # Bouton pour monter l'element selectionne tout en haut de la liste
        self.pushButtonExtremiteMonter = MyQPushButton(self.tabTelechargements)
        self.pushButtonExtremiteMonter.setIcon(
            QtGui.QIcon("ico/gtk-jump-to-rtl.svg"))
        self.pushButtonExtremiteMonter.setToolTip(
            u"Placer l'élément sélectionné tout en haut")
        self.gridLayoutTelechargement.addWidget(self.pushButtonExtremiteMonter,
                                                0, 0, 1, 1)

        # Bouton pour monter l'element selectionne d'un cran dans la liste
        self.pushButtonMonter = MyQPushButton(self.tabTelechargements)
        self.pushButtonMonter.setIcon(QtGui.QIcon("ico/gtk-go-up.svg"))
        self.pushButtonMonter.setToolTip(u"Monter l'élément sélectionné")
        self.gridLayoutTelechargement.addWidget(self.pushButtonMonter, 1, 0, 1,
                                                1)

        # Bouton pour descendre l'element selectionne d'un cran dans la liste
        self.pushButtonDescendre = MyQPushButton(self.tabTelechargements)
        self.pushButtonDescendre.setIcon(QtGui.QIcon("ico/gtk-go-down.svg"))
        self.pushButtonDescendre.setToolTip(u"Descendre l'élément selectionné")
        self.gridLayoutTelechargement.addWidget(self.pushButtonDescendre, 2, 0,
                                                1, 1)

        # Bouton pour descendre l'element selectionne tout en bas de la liste
        self.pushButtonExtremiteDescendre = MyQPushButton(
            self.tabTelechargements)
        self.pushButtonExtremiteDescendre.setIcon(
            QtGui.QIcon("ico/gtk-jump-to-ltr.svg"))
        self.pushButtonExtremiteDescendre.setToolTip(
            u"Placer l'élément sélectionné tout en bas")
        self.gridLayoutTelechargement.addWidget(
            self.pushButtonExtremiteDescendre, 3, 0, 1, 1)

        # Bouton pour supprimer tous les elements de la liste
        self.pushButtonToutSupprimer = MyQPushButton(self.tabTelechargements)
        self.pushButtonToutSupprimer.setIcon(QtGui.QIcon("ico/gtk-cancel.svg"))
        self.pushButtonToutSupprimer.setToolTip(
            u"Supprimer tous les téléchargements")
        self.gridLayoutTelechargement.addWidget(self.pushButtonToutSupprimer,
                                                0, 2, 1, 1)

        # Bouton pour supprimer de la liste les telechargements termines
        self.pushButtonNettoyer = MyQPushButton(self.tabTelechargements)
        self.pushButtonNettoyer.setIcon(QtGui.QIcon("ico/gtk-delete-full.svg"))
        self.pushButtonNettoyer.setToolTip(
            u"Supprimer les téléchargement terminés")
        self.gridLayoutTelechargement.addWidget(self.pushButtonNettoyer, 1, 2,
                                                1, 1)

        # Bouton pour ouvrir le dossier des telechargements
        self.pushButtonOuvrirDossierTelechargement = MyQPushButton(
            self.tabTelechargements)
        self.pushButtonOuvrirDossierTelechargement.setIcon(
            QtGui.QIcon("ico/gtk-folder.svg"))
        self.pushButtonOuvrirDossierTelechargement.setToolTip(
            u"Ouvrir le dossier des téléchargements")
        self.gridLayoutTelechargement.addWidget(
            self.pushButtonOuvrirDossierTelechargement, 2, 2, 1, 1)

        #
        # Barre progression de telechargement d'un fichier
        #
        self.progressBarTelechargementFichier = QtGui.QProgressBar(
            self.centralWidget)
        self.progressBarTelechargementFichier.setProperty("value", 0)

        #
        # Barre de progression de telechargement des fichiers
        #
        self.progressBarTelechargement = QtGui.QProgressBar(self.centralWidget)
        self.progressBarTelechargement.setProperty("value", 0)

        #
        # Boutons du bas pour gerer ajouter/supprimer/lancer telechargements
        #

        # Layout horizontal qui contiendra les boutons
        self.horizontalLayoutBarreBas = QtGui.QHBoxLayout()

        # Bouton pour lancer les telechargements
        self.pushButtonLancer = QtGui.QPushButton(
            QtGui.QIcon("ico/gtk-media-play-ltr.svg"),
            u"Lancer téléchargement", self.centralWidget)
        self.horizontalLayoutBarreBas.addWidget(self.pushButtonLancer)

        # Bouton pour stopper les telechargements
        self.pushButtonStop = QtGui.QPushButton(
            QtGui.QIcon("ico/gtk-media-stop.svg"),
            u"Stopper le téléchargement", self.centralWidget)
        self.pushButtonStop.setEnabled(False)
        self.horizontalLayoutBarreBas.addWidget(self.pushButtonStop)

        ###
        # Positionnement des differents widgets/layouts sur le layout de grille
        ###

        # Layout de grille dans lequel on va placer nos widgets/layouts
        self.gridLayout = QtGui.QGridLayout(self.centralWidget)
        # On ajoute la barre du haut
        self.gridLayout.addLayout(self.horizontalLayoutBarreHaut, 0, 0, 1, 3)
        # On ajoute le gestionnaire d'onglets
        self.gridLayout.addWidget(self.tabWidget, 1, 0, 1, 3)
        # On ajoute la barre de progression de telechargement d'un fichier
        self.gridLayout.addWidget(self.progressBarTelechargementFichier, 2, 0,
                                  1, 3)
        # On ajoute la barre de progression de telechargement des fichiers
        self.gridLayout.addWidget(self.progressBarTelechargement, 3, 0, 1, 3)
        # On ajoute les boutons ajouter/supprimer/lancer
        self.gridLayout.addLayout(self.horizontalLayoutBarreBas, 4, 0, 1, 3)

        ###
        # Mise en place le central widget dans la fenetre
        ###
        self.setCentralWidget(self.centralWidget)

        ###
        # Mise en place du menu
        ###

        # Menu barre
        self.menubar = QtGui.QMenuBar(self)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 480, 25))

        # Menu Fichier
        self.menuFichier = QtGui.QMenu("&Fichier", self.menubar)
        self.menubar.addAction(self.menuFichier.menuAction())

        # Action Fichier -> Quitter
        self.actionQuitter = QtGui.QAction(QtGui.QIcon("ico/gtk-quit.svg"),
                                           "&Quitter", self)
        self.actionQuitter.setIconVisibleInMenu(True)
        self.menuFichier.addAction(self.actionQuitter)

        # Menu Edition
        self.menuEdition = QtGui.QMenu("&Edition", self.menubar)
        self.menubar.addAction(self.menuEdition.menuAction())

        # Action Edition -> Mise a jour
        self.actionMAJ = QtGui.QAction(QtGui.QIcon("ico/gtk-refresh.svg"),
                                       u"&Mise à jour des plugins", self)
        self.actionMAJ.setIconVisibleInMenu(True)
        self.menuEdition.addAction(self.actionMAJ)

        # Action Edition -> Preferences
        self.actionPreferences = QtGui.QAction(
            QtGui.QIcon("ico/gtk-preferences.svg"), u"&Préférences", self)
        self.actionPreferences.setIconVisibleInMenu(True)
        self.menuEdition.addAction(self.actionPreferences)

        # Menu Aide
        self.menuAide = QtGui.QMenu("&Aide", self.menubar)
        self.menubar.addAction(self.menuAide.menuAction())

        # Action Aide -> A propos
        self.actionAPropos = QtGui.QAction(QtGui.QIcon("ico/gtk-about.svg"),
                                           u"À p&ropos", self)
        self.actionAPropos.setIconVisibleInMenu(True)
        self.menuAide.addAction(self.actionAPropos)

        # Ajout du menu a l'interface
        self.setMenuBar(self.menubar)

        ###
        # Signaux provenants de l'interface
        ###

        QtCore.QObject.connect(self.tableWidgetFichier,
                               QtCore.SIGNAL("cellClicked(int,int)"),
                               self.afficherInformationsFichier)

        QtCore.QObject.connect(self.tableWidgetFichier,
                               QtCore.SIGNAL("cellDoubleClicked(int,int)"),
                               self.gererTelechargement)

        QtCore.QObject.connect(self.pushButtonToutAjouter,
                               QtCore.SIGNAL("clicked()"),
                               self.ajouterTousLesFichiers)

        QtCore.QObject.connect(self.pushButtonRafraichirPlugin,
                               QtCore.SIGNAL("clicked()"),
                               self.rafraichirPlugin)

        QtCore.QObject.connect(self.tableWidgetTelechargement,
                               QtCore.SIGNAL("cellDoubleClicked(int,int)"),
                               self.supprimerTelechargement)

        QtCore.QObject.connect(
            self.pushButtonExtremiteMonter,
            QtCore.SIGNAL("clicked()"),
            lambda versLeHaut=True, extremite=True: self.
            tableWidgetTelechargement.deplacerLigne(versLeHaut, extremite))

        QtCore.QObject.connect(
            self.pushButtonMonter,
            QtCore.SIGNAL("clicked()"),
            lambda versLeHaut=True, extremite=False: self.
            tableWidgetTelechargement.deplacerLigne(versLeHaut, extremite))

        QtCore.QObject.connect(
            self.pushButtonDescendre,
            QtCore.SIGNAL("clicked()"),
            lambda versLeHaut=False, extremite=False: self.
            tableWidgetTelechargement.deplacerLigne(versLeHaut, extremite))

        QtCore.QObject.connect(
            self.pushButtonExtremiteDescendre,
            QtCore.SIGNAL("clicked()"),
            lambda versLeHaut=False, extremite=True: self.
            tableWidgetTelechargement.deplacerLigne(versLeHaut, extremite))

        QtCore.QObject.connect(self.pushButtonToutSupprimer,
                               QtCore.SIGNAL("clicked()"),
                               self.supprimerTousLesTelechargements)

        QtCore.QObject.connect(self.pushButtonNettoyer,
                               QtCore.SIGNAL("clicked()"), self.nettoyer)

        QtCore.QObject.connect(self.pushButtonLancer,
                               QtCore.SIGNAL("clicked()"),
                               self.lancerTelechargement)

        QtCore.QObject.connect(self.pushButtonStop, QtCore.SIGNAL("clicked()"),
                               self.stopperTelechargement)

        QtCore.QObject.connect(self.actionQuitter,
                               QtCore.SIGNAL("triggered()"), self.close)

        ################################################
        # Instanciations + initialisation de variables #
        ################################################

        # Fenetre About
        self.aProposDialog = None
        # Fenetre des preferences du logiciel
        self.preferencesDialog = None
        # Fenetre de mise a jour des plugins
        self.updateManagerDialog = None
        # Nom plugin courant
        self.nomPluginCourant = ""
        # Liste des fichiers
        self.listeFichiers = []
        # Liste des fichiers a telecharger
        self.listeFichiersATelecharger = []
        # Cache des images descriptive
        # Clef : urlImage Valeur : image (binaire)
        self.cacheImage = {}

        # On intancie le lanceur de signaux
        self.signaux = Signaux()
        # On instancie le gestionnaire de preferences
        self.preferences = Preferences()
        # On instancie le gestionnaire de preferences des plugins
        self.preferencesPluginDialog = PreferencePluginDialog(self)
        # On instancie le gestionnaire de download
        self.downloader = Downloader(self.signaux)
        # On recupere l'instance de API
        self.api = API.getInstance()
        # On instancie le gestionnaire d'historique
        self.historique = Historique()
        # On instancie la fenetre d'attente
        self.fenetreAttenteProgressDialog = FenetreAttenteProgressDialog(self)
        # On instancie le gest

        #
        # Fenetre de confirmation pour quitter le logiciel
        #
        self.quitterMessageBox = QtGui.QMessageBox(self)
        self.quitterMessageBox.setWindowTitle("Fermeture de TVDownloader")
        self.quitterMessageBox.setText(
            u"Voulez-vous réellement quitter TVDownloader ?")
        self.quitterMessageBox.setInformativeText(
            u"Votre liste de téléchargement sera perdue")
        self.quitterMessageBox.addButton("Oui", QtGui.QMessageBox.AcceptRole)
        self.quitterMessageBox.addButton("Non", QtGui.QMessageBox.RejectRole)

        ############################################################
        # On connecte les signaux des instances precedements crees #
        ############################################################

        QtCore.QObject.connect(self.pushButtonOuvrirDossierTelechargement,
                               QtCore.SIGNAL("clicked()"),
                               self.ouvrirRepertoireTelechargement)

        QtCore.QObject.connect(self.comboBoxSite,
                               QtCore.SIGNAL("activated(QString)"),
                               self.listerChaines)

        QtCore.QObject.connect(self.comboBoxChaine,
                               QtCore.SIGNAL("activated(QString)"),
                               self.listerEmissions)

        QtCore.QObject.connect(self.comboBoxEmission,
                               QtCore.SIGNAL("activated(QString)"),
                               self.listerFichiers)

        QtCore.QObject.connect(self.pushButtonPreferencesPlugin,
                               QtCore.SIGNAL("clicked()"),
                               self.ouvrirPreferencesPlugin)

        QtCore.QObject.connect(self.actionPreferences,
                               QtCore.SIGNAL("triggered()"),
                               self.ouvrirPreferencesLogiciel)

        QtCore.QObject.connect(self.actionMAJ, QtCore.SIGNAL("triggered()"),
                               self.ouvrirFenetreMiseAJour)

        QtCore.QObject.connect(self.actionAPropos,
                               QtCore.SIGNAL("triggered()"),
                               self.ouvrirFenetreAPropos)

        QtCore.QObject.connect(
            self.signaux, QtCore.SIGNAL("debutActualisation(PyQt_PyObject)"),
            self.fenetreAttenteProgressDialog.ouvrirFenetreAttente)
        QtCore.QObject.connect(
            self.signaux, QtCore.SIGNAL("finActualisation()"),
            self.fenetreAttenteProgressDialog.fermerFenetreAttente)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("actualiserListesDeroulantes()"),
                               self.actualiserListesDeroulantes)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("listeChaines(PyQt_PyObject)"),
                               self.ajouterChaines)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("listeEmissions(PyQt_PyObject)"),
                               self.ajouterEmissions)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("listeFichiers(PyQt_PyObject)"),
                               self.ajouterFichiers)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("nouvelleImage(PyQt_PyObject)"),
                               self.mettreEnPlaceImage)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("debutTelechargement(int)"),
                               self.debutTelechargement)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("finTelechargement(int)"),
                               self.finTelechargement)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("finDesTelechargements()"),
                               self.activerDesactiverInterface)
        QtCore.QObject.connect(self.signaux,
                               QtCore.SIGNAL("pourcentageFichier(int)"),
                               self.progressBarTelechargementFichier.setValue)

        #########
        # Début #
        #########

        # La fenetre prend la dimension qu'elle avait a sa fermeture
        taille = self.preferences.getPreference("tailleFenetre")
        self.resize(taille[0], taille[1])

        # Si aucun plugin n'est active, on ouvre la fenetre des preferences
        if (len(self.preferences.getPreference("pluginsActifs")) == 0):
            self.ouvrirPreferencesLogiciel()

        # On actualise tous les plugins
        self.rafraichirTousLesPlugins()

    ## Methode qui execute les actions necessaires avant de quitter le programme
    def actionsAvantQuitter(self):
        # On sauvegarde les options des plugins
        self.api.fermeture()
        # On sauvegarde la taille de la fenetre
        taille = self.size()
        self.preferences.setPreference(
            "tailleFenetre", [taille.width(), taille.height()])
        # On sauvegarde les options du logiciel
        self.preferences.sauvegarderConfiguration()
        # On sauvegarde l'historique
        self.historique.sauverHistorique()
        # On stoppe les telechargements
        self.stopperTelechargement()

    #########################################
    # Surcharge des methodes de QMainWindow #
    #########################################

    ## Surcharge de la methode appelee lors de la fermeture de la fenetre
    # Ne doit pas etre appele explicitement
    # @param evenement Evenement qui a provoque la fermeture
    def closeEvent(self, evenement):
        # On affiche une fenetre pour demander la fermeture si des fichiers sont dans la liste de telechargement
        if (self.tableWidgetTelechargement.rowCount() > 0):
            # On affiche une fenetre qui demande si on veut quitter
            retour = self.quitterMessageBox.exec_()
            # Si on veut quitter
            if (retour == 0):
                # On execute les actions necessaires
                self.actionsAvantQuitter()
                # On accept la fermeture
                evenement.accept()
            else:
                # On refuse la fermeture
                evenement.ignore()
        else:  # S'il n'y a pas de fichier
            # On execute les actions necessaires
            self.actionsAvantQuitter()
            # On accept la fermeture
            evenement.accept()

    ##############################################
    # Methodes pour remplir les menus deroulants #
    ##############################################

    ## Methode qui actualise les listes deroulantes
    def actualiserListesDeroulantes(self):
        # On lance juste l'ajout des sites en se basant sur les plugins actifs
        self.ajouterSites(self.preferences.getPreference("pluginsActifs"))

    ## Methode qui lance le listage des chaines
    # @param site Nom du plugin/site pour lequel on va lister les chaines
    def listerChaines(self, site):
        def threadListerChaines(self, nomPlugin):
            self.signaux.signal("debutActualisation", nomPlugin)
            listeChaines = self.api.getPluginListeChaines(nomPlugin)
            self.signaux.signal("listeChaines", listeChaines)
            self.signaux.signal("finActualisation")

        if (site != ""):
            self.nomPluginCourant = qstringToString(site)
            threading.Thread(target=threadListerChaines,
                             args=(self, self.nomPluginCourant)).start()
            # On active (ou pas) le bouton de preference du plugin
            self.pushButtonPreferencesPlugin.setEnabled(
                self.api.getPluginListeOptions(self.nomPluginCourant) != [])

    ## Methode qui lance le listage des emissions
    # @param chaine Nom de la chaine pour laquelle on va lister les emissions
    def listerEmissions(self, chaine):
        def threadListerEmissions(self, nomPlugin, chaine):
            self.signaux.signal("debutActualisation", nomPlugin)
            listeEmissions = self.api.getPluginListeEmissions(
                nomPlugin, chaine)
            self.signaux.signal("listeEmissions", listeEmissions)
            self.signaux.signal("finActualisation")

        if (chaine != ""):
            threading.Thread(target=threadListerEmissions,
                             args=(self, self.nomPluginCourant,
                                   qstringToString(chaine))).start()

    ## Methode qui lance le listage des fichiers
    # @param emission Nom de l'emission pour laquelle on va lister les fichiers
    def listerFichiers(self, emission):
        def threadListerFichiers(self, nomPlugin, emission):
            self.signaux.signal("debutActualisation", nomPlugin)
            listeFichiers = self.api.getPluginListeFichiers(
                nomPlugin, emission)
            self.signaux.signal("listeFichiers", listeFichiers)
            self.signaux.signal("finActualisation")

        if (emission != ""):
            threading.Thread(target=threadListerFichiers,
                             args=(self, self.nomPluginCourant,
                                   qstringToString(emission))).start()

    ## Methode qui met en place une liste de sites sur l'interface
    # @param listeSites Liste des sites a mettre en place
    def ajouterSites(self, listeSites):
        # On efface la liste des sites
        self.comboBoxSite.clear()
        # On met en place les sites
        for site in listeSites:
            self.comboBoxSite.addItem(stringToQstring(site))
        # On selectionne par defaut celui choisis dans les preference
        index = self.comboBoxSite.findText(
            stringToQstring(self.preferences.getPreference("pluginParDefaut")))
        if (index != -1):
            self.comboBoxSite.setCurrentIndex(index)
        # On lance l'ajout des chaines
        self.listerChaines(self.comboBoxSite.currentText())

    ## Methode qui met en place une liste de chaines sur l'interface
    # @param listeChaines Liste des chaines a mettre en place
    def ajouterChaines(self, listeChaines):
        # On trie la liste des chaines
        listeChaines.sort()
        # On efface la liste des chaines
        self.comboBoxChaine.clear()
        # On efface la liste des emissions
        self.comboBoxEmission.clear()
        # On efface la liste des fichiers
        self.tableWidgetFichier.toutSupprimer()
        # On met en place les chaines
        for chaine in listeChaines:
            self.comboBoxChaine.addItem(stringToQstring(chaine))
        # Si on a juste une seule chaine
        if (self.comboBoxChaine.count() == 1):
            # On lance l'ajout des emissions
            self.listerEmissions(self.comboBoxChaine.currentText())
        else:
            # On ne selectionne pas de chaine
            self.comboBoxChaine.setCurrentIndex(-1)

    ## Methode qui met en place une liste d'emissions sur l'interface
    # @param listeEmissions Liste des emissions a mettre en place
    def ajouterEmissions(self, listeEmissions):
        # On trie la liste des emissions
        listeEmissions.sort()
        # On efface la liste des emissions
        self.comboBoxEmission.clear()
        # On efface la liste des fichiers
        self.tableWidgetFichier.toutSupprimer()
        # On met en place la liste des emissions
        for emission in listeEmissions:
            self.comboBoxEmission.addItem(stringToQstring(emission))
        # Si on a juste une seule emission
        if (self.comboBoxEmission.count() == 1):
            # On lance l'ajout des fichiers
            self.listerFichiers(self.comboBoxEmission.currentText())
        else:
            # On ne selectionne pas d'emission
            self.comboBoxEmission.setCurrentIndex(-1)

    ###############################################
    # Methodes pour remplir la liste des fichiers #
    ###############################################

    ## Methode pour ajouter des fichiers a l'interface
    # @param listeFichiers Liste des fichiers a ajouter
    def ajouterFichiers(self, listeFichiers):
        self.listeFichiers = listeFichiers
        # On efface la liste des fichiers
        self.tableWidgetFichier.toutSupprimer()
        # On commence au depart
        ligneCourante = 0
        # On met en place chacun des fichiers
        for fichier in listeFichiers:
            # On ajoute une ligne
            self.tableWidgetFichier.insertRow(ligneCourante)
            # On ajoute les informations au tableWidgetFichier
            liste = []
            liste.append(self.tableWidgetFichier.creerItem(""))
            liste.append(
                self.tableWidgetFichier.creerItem(getattr(fichier, "date")))
            liste.append(
                self.tableWidgetFichier.creerItem(getattr(fichier, "nom")))
            self.tableWidgetFichier.setLigne(ligneCourante, liste)
            # On met en place l'icone qui va bien
            self.gererIconeListeFichier(fichier)
            ligneCourante += 1
        # On adapte la taille des colonnes
        self.tableWidgetFichier.adapterColonnes()

    ## Methode qui rafraichit le plugin courant
    def rafraichirPlugin(self):
        def threadRafraichirPlugin(self, nomPlugin):
            self.signaux.signal("debutActualisation", nomPlugin)
            self.api.pluginRafraichir(nomPlugin)
            self.signaux.signal("finActualisation")

        threading.Thread(target=threadRafraichirPlugin,
                         args=(self, self.nomPluginCourant)).start()

    ## Methode qui met en place l'image de la description d'un fichier
    # @param image Image a mettre en place (binaire)
    def mettreEnPlaceImage(self, image):
        logoFichier = QtGui.QPixmap()
        logoFichier.loadFromData(image)
        self.labelLogo.setPixmap(
            logoFichier.scaled(QtCore.QSize(150, 150),
                               QtCore.Qt.KeepAspectRatio))

    ## Methode qui affiche des informations sur le fichier selectionne
    def afficherInformationsFichier(self, ligne, colonne):
        def threadRecupererImage(self, urlImage):
            image = self.api.getPage(urlImage)
            self.cacheImage[urlImage] = image
            self.signaux.signal("nouvelleImage", image)

        fichier = self.listeFichiers[ligne]
        # On recupere le lien de l'image et le texte descriptif
        urlImage = getattr(fichier, "urlImage")
        texteDescriptif = getattr(fichier, "descriptif")

        self.plainTextEdit.clear()
        # Si on a un texte descriptif, on l'affiche
        if (texteDescriptif != ""):
            self.plainTextEdit.appendPlainText(
                stringToQstring(texteDescriptif))
        else:
            self.plainTextEdit.appendPlainText(
                u"Aucune information disponible")

        # Si on n'a pas d'image
        if (urlImage == ""):
            # On met en place celle par defaut
            self.logoFichier = self.logoFichierDefaut
            self.labelLogo.setPixmap(
                self.logoFichier.scaled(QtCore.QSize(150, 150),
                                        QtCore.Qt.KeepAspectRatio))
        else:  # Si on en a une
            # Si elle est dans le cache des images
            if (self.cacheImage.has_key(urlImage)):
                self.mettreEnPlaceImage(self.cacheImage[urlImage])
            else:  # Sinon
                # On lance le thread pour la recuperer
                threading.Thread(target=threadRecupererImage,
                                 args=(self, urlImage)).start()

    ## Methode qui gere l'icone d'un fichier dans la liste des telechargements
    # Il y a 3 icones possible :
    #  - C'est un fichier
    #  - C'est un fichier present dans l'historique (donc deja telecharge)
    #  - C'est un fichier present dans la liste des telechargements
    # @param fichier Fichier a gerer
    def gererIconeListeFichier(self, fichier):
        if (fichier in self.listeFichiers):
            ligneFichier = self.listeFichiers.index(fichier)
            # On cherche quel icone mettre en place
            if (fichier in self.listeFichiersATelecharger):
                icone = self.iconeAjoute
            elif (self.historique.comparerHistorique(fichier)):
                icone = self.iconeTelecharge
            else:
                icone = self.iconeFichier
            # On met en place l'icone
            self.tableWidgetFichier.item(ligneFichier, 0).setIcon(icone)

    ######################################################
    # Methodes pour remplir la liste des telechargements #
    ######################################################

    ## Methode qui gere la liste des telechargements
    # @param ligne   Numero de la ligne (dans la liste des fichiers) de l'element a ajouter
    # @param colonne Numero de colonne (inutile, juste pour le slot)
    def gererTelechargement(self, ligne, colonne=0):
        fichier = self.listeFichiers[ligne]
        # Si le fichier est deja dans la liste des telechargements
        if (fichier in self.listeFichiersATelecharger):
            ligneTelechargement = self.listeFichiersATelecharger.index(fichier)
            self.supprimerTelechargement(ligneTelechargement)
        else:  # S'il n'y est pas, on l'ajoute
            self.listeFichiersATelecharger.append(fichier)
            numLigne = self.tableWidgetTelechargement.rowCount()
            # On insere une nouvelle ligne dans la liste des telechargements
            self.tableWidgetTelechargement.insertRow(numLigne)
            # On y insere les elements qui vont biens
            self.tableWidgetTelechargement.setLigne(numLigne, [
                self.tableWidgetTelechargement.creerItem(
                    getattr(fichier, "date")),
                self.tableWidgetTelechargement.creerItem(
                    getattr(fichier, "nom")),
                self.tableWidgetTelechargement.creerItem(
                    u"En attente de téléchargement")
            ])
            # On adapte la taille des colonnes
            self.tableWidgetTelechargement.adapterColonnes()
            # On modifie l'icone dans la liste des fichiers
            self.gererIconeListeFichier(fichier)

    ## Methode qui ajoute tous les fichiers a la liste des telechargements
    def ajouterTousLesFichiers(self):
        for i in range(self.tableWidgetFichier.rowCount()):
            self.gererTelechargement(i)

    ## Methode qui supprime un fichier de la liste des telechargements
    # @param ligne   Numero de la ligne a supprimer
    # @param colonne Numero de colonne (inutile, juste pour le slot)
    def supprimerTelechargement(self, ligne, colonne=0):
        fichier = self.listeFichiersATelecharger[ligne]
        # On supprime l'element du tableWidgetTelechargement
        self.tableWidgetTelechargement.removeRow(ligne)
        # On supprime l'element de la liste des fichiers a telecharger
        self.listeFichiersATelecharger.remove(fichier)
        # On modifie l'icone dans la liste des fichiers
        self.gererIconeListeFichier(fichier)

    ## Methode qui supprime tous les telechargement de la liste des telechargements
    def supprimerTousLesTelechargements(self):
        for i in range(self.tableWidgetTelechargement.rowCount() - 1, -1, -1):
            self.supprimerTelechargement(i)

    ## Methode qui lance le telechargement des fichiers
    def lancerTelechargement(self):
        # On liste les emissions a telecharger avec leurs numeros de ligne
        listeFichiers = []
        for i in range(self.tableWidgetTelechargement.rowCount()
                       ):  # Pour chaque ligne
            fichier = self.listeFichiersATelecharger[i]
            listeFichiers.append([
                i,
                getattr(fichier, "lien"),
                getattr(fichier, "nomFichierSortie")
            ])

        nbATelecharger = len(listeFichiers)
        # Si on a des elements a charger
        if (nbATelecharger > 0):
            # On met en place la valeur du progressBar
            self.progressBarTelechargement.setMaximum(nbATelecharger)
            self.progressBarTelechargement.setValue(0)
            # On lance le telechargement
            threading.Thread(target=self.downloader.lancerTelechargement,
                             args=(listeFichiers, )).start()
            # On active/desactive ce qui va bien sur l'interface
            self.activerDesactiverInterface(True)

    ## Methode qui stoppe le telechargement
    def stopperTelechargement(self):
        # On stoppe le telechargement
        self.downloader.stopperTelechargement()

    ############################################
    # Methodes pour ouvrir les autres fenetres #
    ############################################

    #
    # Fenetre About
    #

    ## Methode pour afficher la fenetre About
    def ouvrirFenetreAPropos(self):
        if (self.aProposDialog == None):
            self.aProposDialog = AProposDialog()
        self.aProposDialog.show()

    #
    # Fenetre de preference du logiciel
    #

    ## Methode pour ouvrir les preferences du logiciel
    def ouvrirPreferencesLogiciel(self):
        if (self.preferencesDialog == None):
            self.preferencesDialog = PreferencesDialog(self, self.signaux)
        self.preferencesDialog.afficher()

    #
    # Fenetre de mise a jour des plugins
    #

    ## Methode pour ouvrir la fenetre de mise a jour des plugins
    def ouvrirFenetreMiseAJour(self):
        if (self.updateManagerDialog == None):
            self.updateManagerDialog = UpdateManagerDialog(self)
        self.updateManagerDialog.afficher()

    #
    # Fenetre de preference des plugins
    #

    ## Methode pour ouvrir les preferences du plugin courant
    def ouvrirPreferencesPlugin(self):
        listeOptions = self.api.getPluginListeOptions(self.nomPluginCourant)
        self.preferencesPluginDialog.ouvrirDialogPreferences(
            self.nomPluginCourant, listeOptions)

    #########
    # Slots #
    #########

    ## Methode qui ouvre le repertoire de telechargement
    def ouvrirRepertoireTelechargement(self):
        QtGui.QDesktopServices.openUrl(
            QtCore.QUrl.fromLocalFile(
                self.preferences.getPreference("repertoireTelechargement")))

    ## Methode qui rafraichit le plugin courant
    def rafraichirPlugin(self):
        def threadRafraichirPlugin(self, nomPlugin):
            self.signaux.signal("debutActualisation", nomPlugin)
            self.api.pluginRafraichir(nomPlugin)
            self.signaux.signal("finActualisation")

        threading.Thread(target=threadRafraichirPlugin,
                         args=(self, self.nomPluginCourant)).start()

    ## Methode qui rafraichit tous les plugins
    # A utiliser au lancement du programme
    def rafraichirTousLesPlugins(self):
        def threadRafraichirTousLesPlugins(self):
            self.signaux.signal("debutActualisation", "TVDownloader")
            self.api.pluginRafraichirAuto()
            self.signaux.signal("finActualisation")
            self.signaux.signal("actualiserListesDeroulantes")

        threading.Thread(target=threadRafraichirTousLesPlugins,
                         args=(self, )).start()

    ## Slot qui active/desactive des elements de l'interface pendant un telechargement
    # @param telechargementEnCours Indique si on telecharge ou pas
    def activerDesactiverInterface(self, telechargementEnCours=False):
        # Les boutons
        self.pushButtonLancer.setEnabled(not telechargementEnCours)
        self.pushButtonStop.setEnabled(telechargementEnCours)
        self.pushButtonExtremiteMonter.setEnabled(not telechargementEnCours)
        self.pushButtonMonter.setEnabled(not telechargementEnCours)
        self.pushButtonDescendre.setEnabled(not telechargementEnCours)
        self.pushButtonExtremiteDescendre.setEnabled(not telechargementEnCours)
        self.pushButtonToutSupprimer.setEnabled(not telechargementEnCours)
        self.pushButtonNettoyer.setEnabled(not telechargementEnCours)

        # Le table widget
        self.tableWidgetTelechargement.setEnabled(not telechargementEnCours)

    ## Slot appele lors ce qu'un le debut d'un telechargement commence
    # @param numero Position dans la liste des telechargement du telechargement qui commence
    def debutTelechargement(self, numero):
        self.tableWidgetTelechargement.item(numero, 2).setText(
            stringToQstring(u"Téléchargement en cours..."))
        self.tableWidgetTelechargement.adapterColonnes()
        self.progressBarTelechargementFichier.setValue(0)

    ## Slot appele lorsqu'un telechargement se finit
    # @param numero Position dans la liste des telechargement du telechargement qui se finit
    def finTelechargement(self, numero):
        fichier = self.listeFichiersATelecharger[numero]
        # On ajoute le fichier a l'historique
        self.historique.ajouterHistorique(fichier)
        # On modifie l'icone dans la liste des fichiers
        self.gererIconeListeFichier(fichier)
        # On modifie l'interface
        self.tableWidgetTelechargement.item(numero, 2).setText(
            stringToQstring(u"Fini !"))
        self.progressBarTelechargement.setValue(
            self.progressBarTelechargement.value() + 1)
        self.tableWidgetTelechargement.adapterColonnes()
        self.progressBarTelechargementFichier.setValue(100)

    ## Slot qui nettoie la liste des telechargements de tous les telechargements finis
    def nettoyer(self):
        for i in range(self.tableWidgetTelechargement.rowCount() - 1, -1,
                       -1):  # [ nbLignes - 1, nbLignes - 2, ..., 1, 0 ]
            if (self.tableWidgetTelechargement.item(
                    i, 2).text() == u"Fini !"):  # Si c'est telecharge
                self.supprimerTelechargement(i)
コード例 #13
0
ファイル: HistoriqueAdmin.py プロジェクト: CheikhKB/CHIFOUMI
	def __init__(self, session):
		self.sessionLogin = session
		Historique.__init__(self)
コード例 #14
0
	def setUp( self ):
		self.historique = Historique()
コード例 #15
0
ファイル: PluzzDL.py プロジェクト: pierri/Pluzz
class PluzzDLF4M( object ):
	"""
	Telechargement des liens f4m
	"""

	adobePlayer = "http://fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf"

	def __init__( self, manifestURL, nomFichier, navigateur, stopDownloadEvent, progressFnct ):
		self.manifestURL = manifestURL
		self.nomFichier = nomFichier
		self.navigateur = navigateur
		self.stopDownloadEvent = stopDownloadEvent
		self.progressFnct = progressFnct

		self.historique = Historique()
		self.configuration = Configuration()
		self.hmacKey = self.configuration[ "hmac_key" ].decode( "hex" )
		self.playerHash = self.configuration[ "player_hash" ]

	def parseManifest( self ):
		"""
		Parse le manifest
		"""
		try :
			arbre = xml.etree.ElementTree.fromstring( self.manifest )
			# Duree
			self.duree = float( arbre.find( "{http://ns.adobe.com/f4m/1.0}duration" ).text )
			self.pv2 = arbre.find( "{http://ns.adobe.com/f4m/1.0}pv-2.0" ).text
			media = arbre.findall( "{http://ns.adobe.com/f4m/1.0}media" )[ -1 ]
			# Bitrate
			self.bitrate = int( media.attrib[ "bitrate" ] )
			# URL des fragments
			urlbootstrap = media.attrib[ "url" ]
			self.urlFrag = "%s%sSeg1-Frag" % ( self.manifestURLToken[ : self.manifestURLToken.find( "manifest.f4m" ) ], urlbootstrap )
			# Header du fichier final
			self.flvHeader = base64.b64decode( media.find( "{http://ns.adobe.com/f4m/1.0}metadata" ).text )
		except :
			raise PluzzDLException( "Impossible de parser le manifest" )

	def ouvrirNouvelleVideo( self ):
		"""
		Creer une nouvelle video
		"""
		try :
			# Ouverture du fichier
			self.fichierVideo = open( self.nomFichier, "wb" )
		except :
			raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) )
		# Ajout de l'en-tête FLV
		self.fichierVideo.write( binascii.a2b_hex( "464c56010500000009000000001200010c00000000000000" ) )
		# Ajout de l'header du fichier
		self.fichierVideo.write( self.flvHeader )
		self.fichierVideo.write( binascii.a2b_hex( "00000000" ) )  # Padding pour avoir des blocs de 8

	def ouvrirVideoExistante( self ):
		"""
		Ouvre une video existante
		"""
		try :
			# Ouverture du fichier
			self.fichierVideo = open( self.nomFichier, "a+b" )
		except :
			raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) )

	def decompressSWF( self, swfData ):
		"""
		Decompresse un fichier swf
		"""
		# Adapted from :
		#    Prozacgod
		#    http://www.python-forum.org/pythonforum/viewtopic.php?f=2&t=14693
		if( type( swfData ) is str ):
			swfData = StringIO.StringIO( swfData )

		swfData.seek( 0, 0 )
		magic = swfData.read( 3 )

		if( magic == "CWS" ):
			return "FWS" + swfData.read( 5 ) + zlib.decompress( swfData.read() )
		else:
			return None

	def getPlayerHash( self ):
		"""
		Recupere le sha256 du player flash
		"""
		# Get SWF player
		playerData = self.navigateur.getFichier( "http://static.francetv.fr/players/Flash.H264/player.swf" )
		# Uncompress SWF player
		playerDataUncompress = self.decompressSWF( playerData )
		# Perform sha256 of uncompressed SWF player
		hashPlayer = hashlib.sha256( playerDataUncompress ).hexdigest()
		# Perform base64
		return base64.encodestring( hashPlayer.decode( 'hex' ) )

	def debutVideo( self, fragID, fragData ):
		"""
		Trouve le debut de la video dans un fragment
		"""
		# Skip fragment header
		start = fragData.find( "mdat" ) + 4
		# For all fragment (except frag1)
		if( fragID > 1 ):
			# Skip 2 FLV tags
			for dummy in range( 2 ):
				tagLen, = struct.unpack_from( ">L", fragData, start )  # Read 32 bits (big endian)
				tagLen &= 0x00ffffff  # Take the last 24 bits
				start += tagLen + 11 + 4  # 11 = tag header len ; 4 = tag footer len
		return start

	def telecharger( self ):
		# Verifie si le lien du manifest contient la chaine "media-secure"
		if( self.manifestURL.find( "media-secure" ) != -1 ):
			raise PluzzDLException( "pluzzdl ne sait pas gérer ce type de vidéo (utilisation de DRMs)..." )
		# Lien du manifest (apres le token)
		self.manifestURLToken = self.navigateur.getFichier( "http://hdfauth.francetv.fr/esi/urltokengen2.html?url=%s" % ( self.manifestURL[ self.manifestURL.find( "/z/" ) : ] ) )
		# Recupere le manifest
		self.manifest = self.navigateur.getFichier( self.manifestURLToken )
		# Parse le manifest
		self.parseManifest()
		# Calcul les elements
		self.hdnea = self.manifestURLToken[ self.manifestURLToken.find( "hdnea" ) : ]
		self.pv20, self.hdntl = self.pv2.split( ";" )
		self.pvtokenData = r"st=0000000000~exp=9999999999~acl=%2f%2a~data=" + self.pv20 + "!" + self.playerHash
		self.pvtoken = "pvtoken=%s~hmac=%s" % ( urllib.quote( self.pvtokenData ), hmac.new( self.hmacKey, self.pvtokenData, hashlib.sha256 ).hexdigest() )

		#
		# Creation de la video
		#
		self.premierFragment = 1
		self.telechargementFini = False

		video = self.historique.getVideo( self.urlFrag )
		# Si la video est dans l'historique
		if( video is not None ):
			# Si la video existe sur le disque
			if( os.path.exists( self.nomFichier ) ):
				if( video.finie ):
					logger.info( "La vidéo a déjà été entièrement téléchargée" )
					return
				else:
					self.ouvrirVideoExistante()
					self.premierFragment = video.fragments
					logger.info( "Reprise du téléchargement de la vidéo au fragment %d" % ( video.fragments ) )
			else:
				self.ouvrirNouvelleVideo()
				logger.info( "Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % ( self.nomFichier ) )
		else:  # Si la video n'est pas dans l'historique
			self.ouvrirNouvelleVideo()

		# Calcul l'estimation du nombre de fragments
		self.nbFragMax = round( self.duree / 6 )
		logger.debug( "Estimation du nombre de fragments : %d" % ( self.nbFragMax ) )

		# Ajout des fragments
		logger.info( "Début du téléchargement des fragments" )
		try :
			i = self.premierFragment
			self.navigateur.appendCookie( "hdntl", self.hdntl )
			while( not self.stopDownloadEvent.isSet() ):
				# frag  = self.navigateur.getFichier( "%s%d?%s&%s&%s" %( self.urlFrag, i, self.pvtoken, self.hdntl, self.hdnea ) )
				frag = self.navigateur.getFichier( "%s%d" % ( self.urlFrag, i ), referer = self.adobePlayer )
				debut = self.debutVideo( i, frag )
				self.fichierVideo.write( frag[ debut : ] )
				# Affichage de la progression
				self.progressFnct( min( int( ( i / self.nbFragMax ) * 100 ), 100 ) )
				i += 1
		except urllib2.URLError, e :
			if( hasattr( e, 'code' ) ):
				if( e.code == 403 ):
					if( e.reason == "Forbidden" ):
						logger.info( "Le hash du player semble invalide ; calcul du nouveau hash" )
						newPlayerHash = self.getPlayerHash()
						if( newPlayerHash != self.playerHash ):
							self.configuration[ "player_hash" ] = newPlayerHash
							self.configuration.writeConfig()
							logger.info( "Un nouveau hash a été trouvé ; essayez de relancer l'application" )
						else:
							logger.critical( "Pas de nouveau hash disponible..." )
					else:
						logger.critical( "Impossible de charger la vidéo" )
				elif( e.code == 404 ):
					self.progressFnct( 100 )
					self.telechargementFini = True
					logger.info( "Fin du téléchargement" )
		except KeyboardInterrupt:
			logger.info( "Interruption clavier" )
コード例 #16
0
ファイル: PluzzDL.py プロジェクト: pierri/Pluzz
class PluzzDLM3U8( object ):
	"""
	Telechargement des liens m3u8
	"""

	def __init__( self, m3u8URL, nomFichier, navigateur, stopDownloadEvent, progressFnct ):
		self.m3u8URL = m3u8URL
		self.nomFichier = nomFichier
		self.navigateur = navigateur
		self.stopDownloadEvent = stopDownloadEvent
		self.progressFnct = progressFnct

		self.historique = Historique()

		self.nomFichierFinal = "%s.mkv" % ( self.nomFichier[ :-3 ] )

	def ouvrirNouvelleVideo( self ):
		"""
		Creer une nouvelle video
		"""
		try :
			# Ouverture du fichier
			self.fichierVideo = open( self.nomFichier, "wb" )
		except :
			raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) )
		# Ajout de l'en-tête
		# 	Fait dans creerMKV

	def ouvrirVideoExistante( self ):
		"""
		Ouvre une video existante
		"""
		try :
			# Ouverture du fichier
			self.fichierVideo = open( self.nomFichier, "a+b" )
		except :
			raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) )

	def creerMKV( self ):
		"""
		Creer un mkv a partir de la video existante (cree l'en-tete de la video)
		"""
		logger.info( "Création du fichier MKV (vidéo finale) ; veuillez attendre quelques instants" )
		try:
			if( os.name == "nt" ):
				commande = "ffmpeg.exe -i %s -vcodec copy -acodec copy %s 1>NUL 2>NUL" % ( self.nomFichier, self.nomFichierFinal )
			else:
				commande = "ffmpeg -i %s -vcodec copy -acodec copy %s 1>/dev/null 2>/dev/null" % ( self.nomFichier, self.nomFichierFinal )
			if( os.system( commande ) == 0 ):
				os.remove( self.nomFichier )
				logger.info( "Fin !" )
			else:
				logger.warning( "Problème lors de la création du MKV avec FFmpeg ; le fichier %s est néanmoins disponible" % ( self.nomFichier ) )
		except:
			raise PluzzDLException( "Impossible de créer la vidéo finale" )

	def telecharger( self ):
		# Recupere le fichier master.m3u8
		self.m3u8 = self.navigateur.getFichier( self.m3u8URL )
		# Extrait l'URL de base pour tous les fragments
		self.urlBase = "/".join( self.m3u8URL.split( "/" )[ :-1 ] )
		# Recupere le lien avec le plus gros bitrate
		try:
			self.listeFragmentsURL = re.findall( ".+?\.m3u8.*", self.m3u8 )[ -1 ]
			if "://" not in self.listeFragmentsURL:
				self.listeFragmentsURL = "%s/%s" % ( self.urlBase, self.listeFragmentsURL )
		except:
			raise PluzzDLException( "Impossible de trouver le lien vers la liste des fragments" )
		# Recupere la liste des fragments
		self.listeFragmentsPage = self.navigateur.getFichier( self.listeFragmentsURL )
		# Extrait l'URL de tous les fragments
		self.listeFragments = re.findall( ".+?\.ts", self.listeFragmentsPage )
		#
		# Creation de la video
		#
		self.premierFragment = 1
		self.telechargementFini = False
		video = self.historique.getVideo( self.listeFragmentsURL )
		# Si la video est dans l'historique
		if( video is not None ):
			# Si la video existe sur le disque
			if( os.path.exists( self.nomFichier ) or os.path.exists( self.nomFichierFinal ) ):
				if( video.finie ):
					logger.info( "La vidéo a déjà été entièrement téléchargée" )
					if( not os.path.exists( self.nomFichierFinal ) ):
						self.creerMKV()
					return
				else:
					self.ouvrirVideoExistante()
					self.premierFragment = video.fragments
					logger.info( "Reprise du téléchargement de la vidéo au fragment %d" % ( video.fragments ) )
			else:
				self.ouvrirNouvelleVideo()
				logger.info( u"Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % ( self.nomFichier ) )
		else:  # Si la video n'est pas dans l'historique
			self.ouvrirNouvelleVideo()
		# Nombre de fragments
		self.nbFragMax = float( len( self.listeFragments ) )
		logger.debug( "Nombre de fragments : %d" % ( self.nbFragMax ) )
		# Ajout des fragments
		logger.info( "Début du téléchargement des fragments" )
		try :
			i = self.premierFragment
			while( i <= self.nbFragMax and not self.stopDownloadEvent.isSet() ):
				fragURL = self.listeFragments[ i - 1 ]
				if "://" not in fragURL:
					fragURL = "%s/%s" % ( self.urlBase, fragURL )
				frag = self.navigateur.getFichier( fragURL )
				self.fichierVideo.write( frag )
				# Affichage de la progression
				self.progressFnct( min( int( ( i / self.nbFragMax ) * 100 ), 100 ) )
				i += 1
			if( i == self.nbFragMax + 1 ):
				self.progressFnct( 100 )
				self.telechargementFini = True
				logger.info( "Fin du téléchargement" )
				self.creerMKV()
		except KeyboardInterrupt:
			logger.info( "Interruption clavier" )
		except:
			logger.critical( "Erreur inconnue" )
		finally :
			# Ajout dans l'historique
			self.historique.ajouter( Video( lien = self.listeFragmentsURL, fragments = i, finie = self.telechargementFini ) )
			# Fermeture du fichier
			self.fichierVideo.close()
コード例 #17
0
ファイル: PluzzDL.py プロジェクト: BantouTV/Pluzzdl
class PluzzDL( object ):

	def __init__( self, url, useFragments = False, proxy = None, resume = False, progressFnct = lambda x : None, stopDownloadEvent = threading.Event(), outDir = ".", manifest = False, playlist = False ):
		self.url               = url
		self.useFragments      = useFragments
		self.proxy             = proxy
		self.resume            = resume
		self.progressFnct      = progressFnct
		self.stopDownloadEvent = stopDownloadEvent
		self.outDir            = outDir
		self.navigateur        = Navigateur( self.proxy )
		self.historique        = Historique()
		self.configuration     = Configuration()
		self.lienMMS           = None
		self.lienRTMP          = None
		self.manifestURL       = None
		self.drm               = None
		if playlist:
			self.mode = "playlist"
			self.ext  = "ts"
		else:
			self.mode = "manifest"
			self.ext  = "flv"

		self.hmacKey           = self.configuration[ "hmac_key" ].decode( "hex" )
		self.playerHash        = self.configuration[ "player_hash" ]

		if( re.match( "http://www.pluzz.fr/[^\.]+?\.html", self.url ) ):
			# Recupere l'ID de l'emission
			self.getID()
			# Recupere la page d'infos de l'emission
			self.pageInfos = self.navigateur.getFichier( "http://www.pluzz.fr/appftv/webservices/video/getInfosOeuvre.php?mode=zeri&id-diffusion=%s" %( self.id ) )
			# Parse la page d'infos
			self.parseInfos()
			# Petit message en cas de DRM
			if( self.drm == "oui" ):
				logger.warning( "La vidéo posséde un DRM ; elle sera sans doute illisible" )
			# Lien MMS trouve
			if( self.lienMMS is not None ):
				logger.info( "Lien MMS : %s\nUtiliser par exemple mimms ou msdl pour la recuperer directement ou l'option -f de pluzzdl pour essayer de la charger via ses fragments" %( self.lienMMS ) )
			# Lien RTMP trouve
			if( self.lienRTMP is not None ):
				logger.info( "Lien RTMP : %s\nUtiliser par exemple rtmpdump pour la recuperer directement ou l'option -f de pluzzdl pour essayer de la charger via ses fragments" %( self.lienRTMP ) )
			# N'utilise pas les fragments si cela n'a pas ete demande et que des liens directs ont ete trouves
			if( ( ( self.lienMMS is not None ) or ( self.lienRTMP is not None ) ) and not self.useFragments ):
				sys.exit( 0 )

			if self.mode == "manifest":
				# Lien du manifest non trouve
				if( self.manifestURL is None ):
					logger.critical( "Pas de lien vers le manifest" )
					sys.exit( -1 )

			if self.mode == "playlist":
				# Lien de la playlist M3U8 non trouve
				if( self.playlistM3U8 is None ):
					logger.critical( "Pas de lien vers la playlist" )
					sys.exit( -1 )

			self.nomFichier = os.path.join( self.outDir, "%s.%s" %( re.findall( "http://www.pluzz.fr/([^\.]+?)\.html", self.url )[ 0 ], self.ext ) )
		else:
			if self.mode == "manifest":
				page = self.navigateur.getFichier( self.url )
				try:
					self.manifestURL = re.findall( "(http://.+?manifest.f4m)", page )[ 0 ]
				except:
					logger.critical( "Pas de lien vers le manifest" )
					sys.exit( -1 )
				try:
					self.nomFichier = os.path.join( self.outDir, "%s.flv" %( self.url.split( "/" )[ -1 ] ) )
				except:
					self.nomFichier = os.path.join( self.outDir, "video.flv" )

		self.generateNomFichier()

		if self.mode == "manifest":
			self.getVideoViaManifest()

		if self.mode == "playlist":
			self.getVideoViaPlaylist()

	def getVideoViaManifest( self ):
		# Verifie si le lien du manifest contient la chaine "media-secure"
		if( self.manifestURL.find( "media-secure" ) != -1 ):
			logger.critical( "pluzzdl ne sait pas encore gérer ce type de vidéo..." )
			sys.exit( 0 )
		# Lien du manifest (apres le token)
		self.manifestURLToken = self.navigateur.getFichier( "http://hdfauth.francetv.fr/esi/urltokengen2.html?url=%s" %( self.manifestURL[ self.manifestURL.find( "/z/" ) : ] ) )
		# Recupere le manifest
		self.manifest = self.navigateur.getFichier( self.manifestURLToken )
		# Parse le manifest
		self.parseManifest()
		# Calcul les elements
		self.hdnea = self.manifestURLToken[ self.manifestURLToken.find( "hdnea" ) : ]
		self.pv20, self.hdntl = self.pv2.split( ";" )
		self.pvtokenData = r"st=0000000000~exp=9999999999~acl=%2f%2a~data=" + self.pv20 + "!" + self.playerHash
		self.pvtoken = "pvtoken=%s~hmac=%s" %( urllib.quote( self.pvtokenData ), hmac.new( self.hmacKey, self.pvtokenData, hashlib.sha256 ).hexdigest() )

		#
		# Creation de la video
		#
		self.premierFragment    = 1
		self.telechargementFini = False

		# S'il faut reprendre le telechargement
		if( self.resume ):
			video = self.historique.getVideo( self.urlFrag )
			# Si la video est dans l'historique
			if( video is not None ):
				# Si la video existe sur le disque
				if( os.path.exists( self.nomFichier ) ):
					if( video.finie ):
						logger.info( "La vidéo a déjà été entièrement téléchargée" )
						sys.exit( 0 )
					else:
						self.ouvrirVideoExistante()
						self.premierFragment = video.fragments
						logger.info( "Reprise du téléchargement de la vidéo au fragment %d" %( video.fragments ) )
				else:
					self.ouvrirNouvelleVideo()
					logger.info( "Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" %( self.nomFichier ) )
			else: # Si la video n'est pas dans l'historique
				self.ouvrirNouvelleVideo()
		else: # S'il ne faut pas reprendre le telechargement
			self.ouvrirNouvelleVideo()

		# Calcul l'estimation du nombre de fragments
		self.nbFragMax = round( self.duree / 6 )
		logger.debug( "Estimation du nombre de fragments : %d" %( self.nbFragMax ) )

		# Ajout des fragments
		logger.info( "Début du téléchargement des fragments" )
		try :
			i = self.premierFragment
			while( not self.stopDownloadEvent.isSet() ):
				frag  = self.navigateur.getFichier( "%s%d?%s&%s&%s" %( self.urlFrag, i, self.pvtoken, self.hdntl, self.hdnea ) )
				debut = self.debutVideo( i, frag )
				self.fichierVideo.write( frag[ debut : ] )
				# Affichage de la progression
				self.progressFnct( min( int( ( i / self.nbFragMax ) * 100 ), 100 ) )
				i += 1
		except urllib2.URLError, e :
			if( hasattr( e, 'code' ) ):
				if( e.code == 403 ):
					if( e.reason == "Forbidden" ):
						logger.info( "Le hash du player semble invalide ; calcul du nouveau hash" )
						newPlayerHash = self.getPlayerHash()
						if( newPlayerHash != self.playerHash ):
							self.configuration[ "player_hash" ] = newPlayerHash
							self.configuration.writeConfig()
							logger.info( "Un nouveau hash a été trouvé ; essayez de relancer l'application" )
						else:
							logger.critical( "Pas de nouveau hash disponible..." )
					else:
						logger.critical( "Impossible de charger la vidéo" )
				elif( e.code == 404 ):
					self.progressFnct( 100 )
					self.telechargementFini = True
					logger.info( "Fin du téléchargement" )
					self.convertVideo()
		except KeyboardInterrupt:
			logger.info( "Interruption clavier" )
コード例 #18
0
class CLIDialog():

    ## Constructeur
    def __init__(self):

        # On cree l'instance de la classe dialog
        self.dialog = Dialog()
        self.dialog.setBackgroundTitle("TVDownloader")

        # On recupere l'instance de API
        self.api = API.getInstance()
        # On instancie le gestionnaire de download
        self.downloader = Downloader()
        # On instancie le gestionnaire d'historique
        self.historique = Historique()
        # On instancie le gestionnaire de preferences
        self.preferences = Preferences()

        # Liste des telechargements
        self.listeTelechargements = []

        # Quand le programme se termine, on execute la fonction actionsAvantQuitter
        atexit.register(self.actionsAvantQuitter)

        # On commence
        self.bouclePrincipale()

    ## Debut
    def bouclePrincipale(self):

        choix = (1, "")
        while (choix != (0, "Quitter")):
            # On affiche le menu principal
            choix = self.dialog.menu(
                text="Menu Principal",
                choices=[
                    ["Commencer", "Afficher la liste des plugins"],
                    ["Téléchargements", "Gérer les téléchargements"],
                    ["Préférences", "Modifier les préférences"],
                    ["Quitter", "Quitter TVDownloader"],
                ])
            # On lance la methode qui va bien
            if (choix == (0, "Commencer")):
                self.utilisationPlugins()
            elif (choix == (0, "Téléchargements")):
                self.utlisationTelechargements()
            elif (choix == (0, "Préférences")):
                pass
            elif (choix == (0, "Quitter")):
                # Rien a faire, atexit gere cela
                pass

    ## Methode pour selectionner les fichiers a telecharger avec les plugins
    def utilisationPlugins(self):

        # Liste des plugins actifs
        listePlugins = []
        for nomPlugin in self.preferences.getPreference("pluginsActifs"):
            listePlugins.append([nomPlugin, ""])

        choixPlugin = (0, "")
        while (choixPlugin[0] != 1):
            # On affiche le menu de selection de plugins
            choixPlugin = self.dialog.menu(
                text="De quelle plugin voulez-vous voir les chaines ?",
                choices=listePlugins)

            if (choixPlugin[0] != 1):
                # Liste des chaines du plugin
                listeChaines = []
                for nomChaine in self.api.getPluginListeChaines(
                        choixPlugin[1]):
                    listeChaines.append([nomChaine, ""])

                choixChaine = (0, "")
                while (choixChaine[0] != 1):
                    # On affiche le menu de selection de la chaine
                    choixChaine = self.dialog.menu(
                        text=
                        "De quelle chaine voulez-vous voir les emissions ?",
                        choices=listeChaines)

                    if (choixChaine[0] != 1):
                        # Liste des emissions de la chaine
                        listeEmissions = []
                        for nomEmission in self.api.getPluginListeEmissions(
                                choixPlugin[1], choixChaine[1]):
                            listeEmissions.append([nomEmission, ""])

                        choixEmission = (0, "")
                        while (choixEmission[0] != 1):
                            # On affiche le menu de selection de l'emission
                            choixEmission = self.dialog.menu(
                                text=
                                "De quelle emission voulez-vous voir les fichiers ?",
                                choices=listeEmissions)

                            if (choixEmission[0] != 1):
                                listeFichiersAAfficher = []
                                listeFichiersCoches = []
                                listeFichiersPrecedementCoches = []
                                listeFichiersAPI = self.api.getPluginListeFichiers(
                                    choixPlugin[1], choixEmission[1])
                                i = 0
                                for fichier in listeFichiersAPI:
                                    texteAAfficher = "(%s) %s" % (getattr(
                                        fichier,
                                        "date"), getattr(fichier, "nom"))
                                    if (fichier in self.listeTelechargements):
                                        listeFichiersPrecedementCoches.append(
                                            fichier)
                                        cochee = 1
                                    else:
                                        cochee = 0
                                    listeFichiersAAfficher.append(
                                        [str(i), texteAAfficher, cochee])
                                    i += 1

                                choixFichiers = (0, [])
                                while (choixFichiers[0] != 1):
                                    choixFichiers = self.dialog.checklist(
                                        text=
                                        "Quels fichiers voulez-vous ajouter à la liste des téléchargements ?",
                                        choices=listeFichiersAAfficher)

                                    if (choixFichiers[0] != 1):
                                        for numeroFichier in choixFichiers[1]:
                                            fichier = listeFichiersAPI[int(
                                                numeroFichier)]
                                            listeFichiersCoches.append(fichier)

                                        for fichier in listeFichiersCoches:
                                            if not (fichier in
                                                    listeFichiersPrecedementCoches
                                                    ):
                                                self.listeTelechargements.append(
                                                    fichier)

                                        for fichier in listeFichiersPrecedementCoches:
                                            if not (fichier
                                                    in listeFichiersCoches):
                                                self.listeTelechargements.remove(
                                                    fichier)

                                        # On retourne au menu precedent
                                        choixFichiers = (1, "")

    ## Methode qui gere le gestionnaire de telechargement
    def utlisationTelechargements(self):

        choix = (0, "")
        while (choix[0] != 1):
            # On affiche le menu principal
            choix = self.dialog.menu(
                text="Gestionnaire de téléchargement",
                choices=[["Consulter", "Consulter la liste"],
                         ["Lancer", "Lancer les téléchargements"]])

            # On lance la methode qui va bien
            if (choix == (0, "Consulter")):

                if (len(self.listeTelechargements) > 0):
                    texte = ""
                    for fichier in self.listeTelechargements:
                        texte += "(%s) %s\n" % (getattr(
                            fichier, "date"), getattr(fichier, "nom"))
                else:
                    texte = "La liste des téléchargements est vide"

                # On affiche la liste des fichiers a telecharger
                self.dialog.msgbox(text=texte)

            elif (choix == (0, "Lancer")):

                if (len(self.listeTelechargements) > 0):
                    liste = []

                    for fichier in self.listeTelechargements:
                        lien = getattr(fichier, "lien")
                        nomFichierSortie = getattr(fichier, "nomFichierSortie")
                        if (
                                nomFichierSortie == ""
                        ):  # Si le nom du fichier de sortie n'existe pas, on l'extrait de l'URL
                            nomFichierSortie = os.path.basename(lien)

                        liste.append([0, lien, nomFichierSortie])

                    # On lance le telechargement
                    self.downloader.lancerTelechargement(liste)

                    self.dialog.msgbox(
                        text="Fin du téléchargement des fichiers")
                    del self.listeTelechargements[:]
                else:
                    self.dialog.msgbox(text="Aucun fichier à télécharger")

    ## Methode qui execute les actions necessaires avant de quitter le programme
    def actionsAvantQuitter(self):
        print "Fermeture"
        # On sauvegarde les options des plugins
        self.api.fermeture()
        # On sauvegarde l'historique
        self.historique.sauverHistorique()
        # On sauvegarde les options du logiciel
        self.preferences.sauvegarderConfiguration()
コード例 #19
0
ファイル: Option.py プロジェクト: oogl-import/tvdownloader
	def __init__(self, DLlist):
		# On instancie le gestionnaire de preferences et sa fenetre
		self.preferences = Preferences()
		# On instancie le gestionnaire de download
		self.downloader = Downloader()
		# On instancie le gestionnaire d'historique et sa fenetre
		self.historique = Historique()
		current=0
		global choice
		choice=''
		while choice!='r' and choice!='R':	
			if choice=='s' or choice=='S':
				os.system(['clear','cls'][os.name == 'nt'])
				header ('','','Liste de telechargement\t')
				print "\n\n\n\tSupprimer tous les fichiers de la liste de telchargement"
				#pour chaque fichier de la liste  ***(len(DLlist))!=0
				while len(DLlist)>0:
					print "Supprimer le fichier :",DLlist[0].nom
					#supprimer le fichier de la liste
					DLlist.remove(DLlist[0])
					#ajouter le fichier au log
					time.sleep (1)	
			if choice=='t' or choice=='T':
				os.system(['clear','cls'][os.name == 'nt'])
				header ('','','Liste de telechargement\t')
				print "\n\n\n\ttelecharger tous les fichiers"
				#pour chaque fichier de la liste  ***(len(DLlist))!=0
				while len(DLlist)>0:
					if not self.historique.comparerHistorique(DLlist[0]):
						os.system(['clear','cls'][os.name == 'nt'])
						header ('','','Liste de telechargement\t')
						print "\n\n\n\ttelecharger le fichier :",DLlist[0].nom
						if(DLlist[0].nomFichierSortie=="" ):
							DLlist[0].nomFichierSortie=os.path.basename(getattr(DLlist[0],"lien" ))
						#telecharger le fichier
						self.downloader.lancerTelechargement([[0,DLlist[0].lien,DLlist[0].nomFichierSortie]])
						#ajouter le fichier a l'historique de telechargement
						self.historique.ajouterHistorique(DLlist[0])		
					else:
						os.system(['clear','cls'][os.name == 'nt'])
						header ('','','Liste de telechargement\t')
						print "\n\n\n\tFichier deja telecharge"
					#supprimer le fichier de la liste
					DLlist.remove(DLlist[0])
					time.sleep (1)
			elif choice=='q' or choice=='Q':
				quitter()
			elif choice.isdigit() and len(DLlist)>int(choice)+10*current and int(choice)>=0:
				value=''
				while (value!='r' and value!='t' and value!='s'):
					os.system(['clear','cls'][os.name == 'nt'])
					header ('','','Liste de telechargement\t')
					print "\n\n\n\tFichier :",DLlist[int(choice)+10*current].nom,"\n\n\tQue voulez vous faire?\n\n\t\tt:telecharger le fichier\n\t\ts:supprimer le fichier de la liste de telechargement\n\t\tr:retour a liste de telechargement\n\n\n\n\n"
					value=getch()
				if value=='t':
					if not self.historique.comparerHistorique(DLlist[int(choice)+10*current]):
						os.system(['clear','cls'][os.name == 'nt'])
						header ('','','Liste de telechargement\t')
						print "\n\n\n\ttelecharger le fichier :",DLlist[int(choice)].nom
						# Si le nom du fichier de sortie n'existe pas, on l'extrait de l'URL
						if(DLlist[int(choice)+10*current].nomFichierSortie=="" ):
							DLlist[int(choice)+10*current].nomFichierSortie=os.path.basename(getattr(DLlist[int(choice)+10*current],"lien" ))
						#telecharger le fichier
						self.historique.ajouterHistorique(DLlist[int(choice)+10*current])
						self.downloader.lancerTelechargement([[0,DLlist[int(choice)].lien,DLlist[int(choice)].nomFichierSortie]])
						#ajouter le fichier a l'historique de telechargement
					else:
						os.system(['clear','cls'][os.name == 'nt'])
						header ('','','Liste de telechargement\t')
						print "\n\n\n\tFichier deja telecharge"
					time.sleep(1)
					#supprimer le fichier de la liste
					DLlist.remove(DLlist[int(choice)])
				elif value=='s':
					os.system(['clear','cls'][os.name == 'nt'])
					header ('','','Liste de telechargement\t')
					print "\n\n\n\tSuppression de la liste de telechargement du fichier :\n\n\t\t",DLlist[int(choice)].nom
					#supprimer le fichier de la liste
					DLlist.remove(DLlist[int(choice)])
				elif value=='r':
					os.system(['clear','cls'][os.name == 'nt'])
					header ('','','Liste de telechargement\t')
					print "\n\n\n\tRetour a la liste de telechargement"
				#ajouter le fichier au log
				time.sleep(1)
			elif choice=='*' :
				value=''
				os.system(['clear','cls'][os.name == 'nt'])
				header ('','','Liste de telechargement\t')
				print "\n\n\n\n\n\tQue voulez vous faire?\n\n\t\tt:telecharger les fichiers\n\t\ts:supprimer les fichiers de la liste de telechargement\n\n\n\n\n\n"
				value=getch()
				while len(DLlist)>0:
					if value=='t':
						if not self.historique.comparerHistorique(DLlist[0]):
							os.system(['clear','cls'][os.name == 'nt'])
							header ('','','Liste de telechargement\t')
							print "\n\n\n\ttelecharger le fichier :",DLlist[0].nom
							# Si le nom du fichier de sortie n'existe pas, on l'extrait de l'URL
							if(DLlist[0].nomFichierSortie=="" ):
								DLlist[0].nomFichierSortie=os.path.basename(getattr(DLlist[0],"lien" ))
							#telecharger le fichier
							self.downloader.lancerTelechargement([[0,DLlist[0].lien,DLlist[0].nomFichierSortie]])
							#ajouter le fichier a l'historique de telechargement
							self.historique.ajouterHistorique(DLlist[0])
						else:
							os.system(['clear','cls'][os.name == 'nt'])
							header ('','','Liste de telechargement\t')
							print "\n\n\n\tFichier deja telecharge"	
							time.sleep(0.5)
					#supprimer le fichier de la liste
					DLlist.remove(DLlist[0])
					#ajouter le fichier au log
			elif choice=='+':
				if len(DLlist)>current*10+10: current+=1
			elif choice=='-':
				if current!=0: current-=1
			choice=''
			#sauvegarder l'historique de telechargement
			self.historique.sauverHistorique()
			#affichage a l'ecran de la liste
			header ('','','Liste de telechargement\t')
			for i in range(10):
				if len(DLlist)>i+10*current:
					if len(DLlist[int(i+10*current)].nom)>74: print " ",i,":",DLlist[int(i+10*current)].nom[:71]+"..."
					elif len(DLlist[int(i+10*current)].nom)<=74: print " ",i,":",DLlist[int(i+10*current)].nom
				else: print ""
			if len(DLlist)>10:print "\n\t+:fichiers suivants\t-:fichiers precedents  (page",current+1,"/",len(DLlist)/10+1,",",len(DLlist),"chaines)"
			else:print"\n"
			print "\n\tt:telecharger tous les fichiers  s:supprimer tous les fichiers"
			footer()
			if len(DLlist)==0:
				os.system(['clear','cls'][os.name == 'nt'])
				header ('','','Liste de telechargement\t')
				print "\n\n\n\n\n\t\tAucun fichier dans la liste"
				footer()
				choice='r'
				time.sleep(1)
			if not choice:choice=getch()
コード例 #20
0
ファイル: PluzzDL.py プロジェクト: btuduri/tvdownloader
class PluzzDLF4M( object ):
	"""
	Telechargement des liens f4m
	"""

	adobePlayer = "http://fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf"

	def __init__( self, manifestURL, nomFichier, navigateur, stopDownloadEvent, progressFnct ):
		self.manifestURL = manifestURL
		self.nomFichier = nomFichier
		self.navigateur = navigateur
		self.stopDownloadEvent = stopDownloadEvent
		self.progressFnct = progressFnct

		self.historique = Historique()
		self.configuration = Configuration()
		self.hmacKey = self.configuration[ "hmac_key" ].decode( "hex" )
		self.playerHash = self.configuration[ "player_hash" ]

	def parseManifest( self ):
		"""
		Parse le manifest
		"""
		try :
			arbre = xml.etree.ElementTree.fromstring( self.manifest )
			# Duree
			self.duree = float( arbre.find( "{http://ns.adobe.com/f4m/1.0}duration" ).text )
			self.pv2 = arbre.find( "{http://ns.adobe.com/f4m/1.0}pv-2.0" ).text
			media = arbre.findall( "{http://ns.adobe.com/f4m/1.0}media" )[ -1 ]
			# Bitrate
			self.bitrate = int( media.attrib[ "bitrate" ] )
			# URL des fragments
			urlbootstrap = media.attrib[ "url" ]
			self.urlFrag = "%s%sSeg1-Frag" % ( self.manifestURLToken[ : self.manifestURLToken.find( "manifest.f4m" ) ], urlbootstrap )
			# Header du fichier final
			self.flvHeader = base64.b64decode( media.find( "{http://ns.adobe.com/f4m/1.0}metadata" ).text )
		except :
			raise PluzzDLException( "Impossible de parser le manifest" )

	def ouvrirNouvelleVideo( self ):
		"""
		Creer une nouvelle video
		"""
		try :
			# Ouverture du fichier
			self.fichierVideo = open( self.nomFichier, "wb" )
		except :
			raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) )
		# Ajout de l'en-tête FLV
		self.fichierVideo.write( binascii.a2b_hex( "464c56010500000009000000001200010c00000000000000" ) )
		# Ajout de l'header du fichier
		self.fichierVideo.write( self.flvHeader )
		self.fichierVideo.write( binascii.a2b_hex( "00000000" ) )  # Padding pour avoir des blocs de 8

	def ouvrirVideoExistante( self ):
		"""
		Ouvre une video existante
		"""
		try :
			# Ouverture du fichier
			self.fichierVideo = open( self.nomFichier, "a+b" )
		except :
			raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) )

	def decompressSWF( self, swfData ):
		"""
		Decompresse un fichier swf
		"""
		# Adapted from :
		#    Prozacgod
		#    http://www.python-forum.org/pythonforum/viewtopic.php?f=2&t=14693
		if( type( swfData ) is str ):
			swfData = StringIO.StringIO( swfData )

		swfData.seek( 0, 0 )
		magic = swfData.read( 3 )

		if( magic == "CWS" ):
			return "FWS" + swfData.read( 5 ) + zlib.decompress( swfData.read() )
		else:
			return None

	def getPlayerHash( self ):
		"""
		Recupere le sha256 du player flash
		"""
		# Get SWF player
		playerData = self.navigateur.getFichier( "http://static.francetv.fr/players/Flash.H264/player.swf" )
		# Uncompress SWF player
		playerDataUncompress = self.decompressSWF( playerData )
		# Perform sha256 of uncompressed SWF player
		hashPlayer = hashlib.sha256( playerDataUncompress ).hexdigest()
		# Perform base64
		return base64.encodestring( hashPlayer.decode( 'hex' ) )

	def debutVideo( self, fragID, fragData ):
		"""
		Trouve le debut de la video dans un fragment
		"""
		# Skip fragment header
		start = fragData.find( "mdat" ) + 4
		# For all fragment (except frag1)
		if( fragID > 1 ):
			# Skip 2 FLV tags
			for dummy in range( 2 ):
				tagLen, = struct.unpack_from( ">L", fragData, start )  # Read 32 bits (big endian)
				tagLen &= 0x00ffffff  # Take the last 24 bits
				start += tagLen + 11 + 4  # 11 = tag header len ; 4 = tag footer len
		return start

	def telecharger( self ):
		# Verifie si le lien du manifest contient la chaine "media-secure"
		if( self.manifestURL.find( "media-secure" ) != -1 ):
			raise PluzzDLException( "pluzzdl ne sait pas gérer ce type de vidéo (utilisation de DRMs)..." )
		# Lien du manifest (apres le token)
		self.manifestURLToken = self.navigateur.getFichier( "http://hdfauth.francetv.fr/esi/urltokengen2.html?url=%s" % ( self.manifestURL[ self.manifestURL.find( "/z/" ) : ] ) )
		# Recupere le manifest
		self.manifest = self.navigateur.getFichier( self.manifestURLToken )
		# Parse le manifest
		self.parseManifest()
		# Calcul les elements
		self.hdnea = self.manifestURLToken[ self.manifestURLToken.find( "hdnea" ) : ]
		self.pv20, self.hdntl = self.pv2.split( ";" )
		self.pvtokenData = r"st=0000000000~exp=9999999999~acl=%2f%2a~data=" + self.pv20 + "!" + self.playerHash
		self.pvtoken = "pvtoken=%s~hmac=%s" % ( urllib.quote( self.pvtokenData ), hmac.new( self.hmacKey, self.pvtokenData, hashlib.sha256 ).hexdigest() )

		#
		# Creation de la video
		#
		self.premierFragment = 1
		self.telechargementFini = False

		video = self.historique.getVideo( self.urlFrag )
		# Si la video est dans l'historique
		if( video is not None ):
			# Si la video existe sur le disque
			if( os.path.exists( self.nomFichier ) ):
				if( video.finie ):
					logger.info( "La vidéo a déjà été entièrement téléchargée" )
					return
				else:
					self.ouvrirVideoExistante()
					self.premierFragment = video.fragments
					logger.info( "Reprise du téléchargement de la vidéo au fragment %d" % ( video.fragments ) )
			else:
				self.ouvrirNouvelleVideo()
				logger.info( "Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % ( self.nomFichier ) )
		else:  # Si la video n'est pas dans l'historique
			self.ouvrirNouvelleVideo()

		# Calcul l'estimation du nombre de fragments
		self.nbFragMax = round( self.duree / 6 )
		logger.debug( "Estimation du nombre de fragments : %d" % ( self.nbFragMax ) )

		# Ajout des fragments
		logger.info( "Début du téléchargement des fragments" )
		try :
			i = self.premierFragment
			self.navigateur.appendCookie( "hdntl", self.hdntl )
			while( not self.stopDownloadEvent.isSet() ):
				# frag  = self.navigateur.getFichier( "%s%d?%s&%s&%s" %( self.urlFrag, i, self.pvtoken, self.hdntl, self.hdnea ) )
				frag = self.navigateur.getFichier( "%s%d" % ( self.urlFrag, i ), referer = self.adobePlayer )
				debut = self.debutVideo( i, frag )
				self.fichierVideo.write( frag[ debut : ] )
				# Affichage de la progression
				self.progressFnct( min( int( ( i / self.nbFragMax ) * 100 ), 100 ) )
				i += 1
		except urllib2.URLError, e :
			if( hasattr( e, 'code' ) ):
				if( e.code == 403 ):
					if( e.reason == "Forbidden" ):
						logger.info( "Le hash du player semble invalide ; calcul du nouveau hash" )
						newPlayerHash = self.getPlayerHash()
						if( newPlayerHash != self.playerHash ):
							self.configuration[ "player_hash" ] = newPlayerHash
							self.configuration.writeConfig()
							logger.info( "Un nouveau hash a été trouvé ; essayez de relancer l'application" )
						else:
							logger.critical( "Pas de nouveau hash disponible..." )
					else:
						logger.critical( "Impossible de charger la vidéo" )
				elif( e.code == 404 ):
					self.progressFnct( 100 )
					self.telechargementFini = True
					logger.info( "Fin du téléchargement" )
		except KeyboardInterrupt:
			logger.info( "Interruption clavier" )
コード例 #21
0
class MainWindow( QtGui.QMainWindow ):
	
	## Constructeur
	# Le constructeur va creer la fenetre principale en y ajoutant tous les widgets necessaires au programme
	def __init__( self ):
		# Appel au constructeur de la classe mere
		QtGui.QMainWindow.__init__( self )
		
		###########
		# Fenetre #
		###########
		
		###
		# Reglages de la fenetre principale
		###
		
		# Nom de la fenetre
		self.setWindowTitle( "TVDownloader" )
		# Mise en place de son icone
		self.setWindowIcon( QtGui.QIcon( "ico/TVDownloader.png" ) )
		
		###
		# Mise en place des widgets dans la fenetre
		###
		
		# Widget central qui contiendra tout
		self.centralWidget = QtGui.QWidget( self )
		
		#
		# Barre du haut
		#
		
		# Layout horizontal qui contiendra les listes deroulantes
		self.horizontalLayoutBarreHaut = QtGui.QHBoxLayout()
		
		# Liste deroulante pour choisir le site (plugin)
		self.comboBoxSite = QtGui.QComboBox( self.centralWidget )
		self.horizontalLayoutBarreHaut.addWidget( self.comboBoxSite )
		
		# Liste deroulante pour choisir une chaine du site courant
		self.comboBoxChaine = QtGui.QComboBox( self.centralWidget)
		self.horizontalLayoutBarreHaut.addWidget( self.comboBoxChaine )
		
		# Liste deroulante pour choisir une emission de la chaine courante
		self.comboBoxEmission = QtGui.QComboBox( self.centralWidget )
		self.horizontalLayoutBarreHaut.addWidget( self.comboBoxEmission )
		
		#
		# Onglets
		#
		
		# Gestionnaire onglets
		self.tabWidget = QtGui.QTabWidget( self.centralWidget )
		
		# Onglet Fichiers
		self.tabFichiers = QtGui.QSplitter( self.centralWidget ) # L'onglet Fichier contient un splitter
		self.tabWidget.addTab( self.tabFichiers, u"Choix des fichiers" )
		
		# Onglet Telechargements
		self.tabTelechargements = QtGui.QWidget( self.centralWidget )
		self.tabWidget.addTab( self.tabTelechargements, u"Téléchargements" )
		
		#
		# Liste des fichiers
		#
		
		# Layout de grille qui contient le tableau qui liste les fichiers + boutons
		self.gridLayoutFichiers = QtGui.QGridLayout( self.tabFichiers )
		
		# Tableau qui contient la liste des fichiers disponibles pour l'emission courante
		self.tableWidgetFichier = MyQTableWidget( self.tabFichiers )
		# Il a 4 colonnes et 0 ligne (pour l'instant)
		self.tableWidgetFichier.setColumnCount( 3 )
		self.tableWidgetFichier.setRowCount( 0 )
		# On ajoute les titres
		self.tableWidgetFichier.setHorizontalHeaderItem( 0,
														 self.tableWidgetFichier.creerItem( "" ) )
		self.tableWidgetFichier.setHorizontalHeaderItem( 1,
														 self.tableWidgetFichier.creerItem( "Date" ) )
		self.tableWidgetFichier.setHorizontalHeaderItem( 2,
														 self.tableWidgetFichier.creerItem( "Emission" ) )
		# On l'ajoute au layout
		self.gridLayoutFichiers.addWidget( self.tableWidgetFichier, 0, 1, 6, 1 )
		
		# Icones du tableWidget
		self.iconeFichier     = QtGui.QIcon( "ico/gtk-file.svg" )
		self.iconeAjoute      = QtGui.QIcon( "ico/gtk-add.svg" )
		self.iconeTelecharge  = QtGui.QIcon( "ico/gtk-apply.svg" )
		
		# Bouton pour ajouter tous les fichiers a la liste des telechargements
		self.pushButtonToutAjouter = MyQPushButton( self.tabFichiers )
		self.pushButtonToutAjouter.setIcon( QtGui.QIcon( "ico/gtk-add.svg" ) )
		self.pushButtonToutAjouter.setToolTip( u"Ajouter tous les fichiers à la liste des téléchargements" )
		self.gridLayoutFichiers.addWidget( self.pushButtonToutAjouter, 0, 0, 2, 1 )
		
		# Bouton pour rafraichir le plugin courant
		self.pushButtonRafraichirPlugin = MyQPushButton( self.tabFichiers )
		self.pushButtonRafraichirPlugin.setIcon( QtGui.QIcon( "ico/gtk-refresh.svg" ) )
		self.pushButtonRafraichirPlugin.setToolTip( "Rafraichir le plugin" )
		self.gridLayoutFichiers.addWidget( self.pushButtonRafraichirPlugin, 2, 0, 2, 1 )

		# Bouton pour ouvrir la fenetre des preferences du plugin courant
		self.pushButtonPreferencesPlugin = MyQPushButton( self.tabFichiers )
		self.pushButtonPreferencesPlugin.setIcon( QtGui.QIcon( "ico/gtk-preferences.svg" ) )
		self.pushButtonPreferencesPlugin.setToolTip( u"Ouvrir les préférences du plugin" )
		self.gridLayoutFichiers.addWidget( self.pushButtonPreferencesPlugin, 4, 0, 2, 1 )
		
		# On met en place ce layout sur un widget (pour le splitter)
		self.widgetFichiers = QtGui.QWidget()
		self.widgetFichiers.setLayout( self.gridLayoutFichiers )
		
		#
		# Descriptif des fichiers
		#
		
		# Layout de grille
		self.gridLayoutDescriptif = QtGui.QGridLayout()
		
		# Label pour afficher un logo
		self.logoFichierDefaut = QtGui.QPixmap()
		self.logoFichierDefaut.load( "img/gtk-dialog-question.svg" )
		
		self.labelLogo = QtGui.QLabel( self.centralWidget )
		self.labelLogo.setPixmap( self.logoFichierDefaut.scaled( QtCore.QSize( 150, 150 ), QtCore.Qt.KeepAspectRatio ) )
		
		self.gridLayoutDescriptif.addWidget( self.labelLogo, 0, 0, 1, 1 )
		
		# Zone de texte pour afficher un descriptif
		self.plainTextEdit = QtGui.QPlainTextEdit( self.centralWidget )
		self.gridLayoutDescriptif.addWidget( self.plainTextEdit, 0, 1, 1, 2 )
		
		# On met en place ce layout sur un widget (pour le splitter)
		self.widgetDescriptif = QtGui.QWidget()
		self.widgetDescriptif.setLayout( self.gridLayoutDescriptif )
		

		# Onrientation verticale du splitter
		self.tabFichiers.setOrientation( QtCore.Qt.Vertical )
		
		# On ajoute les 2 elements au splitter (qui est notre onglet)
		self.tabFichiers.addWidget( self.widgetFichiers )
		self.tabFichiers.addWidget( self.widgetDescriptif )
		
		#
		# Liste des telechargements
		#
		
		# Layout de grille qui contient le tableau qui liste les fichiers a telecharger + les boutons pour le controller
		self.gridLayoutTelechargement = QtGui.QGridLayout( self.tabTelechargements )
		
		# Tableau qui contient la liste des fichiers a telecharger
		self.tableWidgetTelechargement = MyQTableWidget( self.tabTelechargements )
		# Il a 5 colonnes et 0 ligne (pour l'instant)
		self.tableWidgetTelechargement.setColumnCount( 3 )
		self.tableWidgetTelechargement.setRowCount( 0 )
		# On ajoute le titre des 5 colonnes
		self.tableWidgetTelechargement.setHorizontalHeaderItem( 0,
																self.tableWidgetTelechargement.creerItem( "Date" ) )
		self.tableWidgetTelechargement.setHorizontalHeaderItem( 1,
																self.tableWidgetTelechargement.creerItem( "Emission" ) )
		self.tableWidgetTelechargement.setHorizontalHeaderItem( 2,
																self.tableWidgetTelechargement.creerItem( "Etat" ) )
		# On l'ajoute au layout
		self.gridLayoutTelechargement.addWidget( self.tableWidgetTelechargement, 0, 1, 4, 1 )
		
		# Bouton pour monter l'element selectionne tout en haut de la liste
		self.pushButtonExtremiteMonter = MyQPushButton( self.tabTelechargements )
		self.pushButtonExtremiteMonter.setIcon( QtGui.QIcon( "ico/gtk-jump-to-rtl.svg" ) )
		self.pushButtonExtremiteMonter.setToolTip( u"Placer l'élément sélectionné tout en haut" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonExtremiteMonter, 0, 0, 1, 1 )
		
		# Bouton pour monter l'element selectionne d'un cran dans la liste
		self.pushButtonMonter = MyQPushButton( self.tabTelechargements )
		self.pushButtonMonter.setIcon( QtGui.QIcon( "ico/gtk-go-up.svg" ) )
		self.pushButtonMonter.setToolTip( u"Monter l'élément sélectionné" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonMonter, 1, 0, 1, 1 )

		# Bouton pour descendre l'element selectionne d'un cran dans la liste
		self.pushButtonDescendre = MyQPushButton( self.tabTelechargements )
		self.pushButtonDescendre.setIcon( QtGui.QIcon( "ico/gtk-go-down.svg" ) )
		self.pushButtonDescendre.setToolTip( u"Descendre l'élément selectionné" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonDescendre, 2, 0, 1, 1 )
		
		# Bouton pour descendre l'element selectionne tout en bas de la liste
		self.pushButtonExtremiteDescendre = MyQPushButton( self.tabTelechargements )
		self.pushButtonExtremiteDescendre.setIcon( QtGui.QIcon( "ico/gtk-jump-to-ltr.svg" ) )
		self.pushButtonExtremiteDescendre.setToolTip( u"Placer l'élément sélectionné tout en bas" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonExtremiteDescendre, 3, 0, 1, 1 )
		
		# Bouton pour supprimer tous les elements de la liste
		self.pushButtonToutSupprimer = MyQPushButton( self.tabTelechargements )
		self.pushButtonToutSupprimer.setIcon( QtGui.QIcon( "ico/gtk-cancel.svg" ) )
		self.pushButtonToutSupprimer.setToolTip( u"Supprimer tous les téléchargements" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonToutSupprimer, 0, 2, 1, 1 )
		
		# Bouton pour supprimer de la liste les telechargements termines
		self.pushButtonNettoyer = MyQPushButton( self.tabTelechargements )
		self.pushButtonNettoyer.setIcon( QtGui.QIcon( "ico/gtk-delete-full.svg" ) )
		self.pushButtonNettoyer.setToolTip( u"Supprimer les téléchargement terminés" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonNettoyer, 1, 2, 1, 1 )
		
		# Bouton pour ouvrir le dossier des telechargements
		self.pushButtonOuvrirDossierTelechargement = MyQPushButton( self.tabTelechargements )
		self.pushButtonOuvrirDossierTelechargement.setIcon( QtGui.QIcon( "ico/gtk-folder.svg" ) )
		self.pushButtonOuvrirDossierTelechargement.setToolTip( u"Ouvrir le dossier des téléchargements" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonOuvrirDossierTelechargement, 2, 2, 1, 1 )
		
		#
		# Barre progression de telechargement d'un fichier
		#
		self.progressBarTelechargementFichier = QtGui.QProgressBar( self.centralWidget )
		self.progressBarTelechargementFichier.setProperty( "value", 0 )
		
		#
		# Barre de progression de telechargement des fichiers
		#
		self.progressBarTelechargement = QtGui.QProgressBar( self.centralWidget )
		self.progressBarTelechargement.setProperty( "value", 0 )
		
		#
		# Boutons du bas pour gerer ajouter/supprimer/lancer telechargements
		#
		
		# Layout horizontal qui contiendra les boutons
		self.horizontalLayoutBarreBas = QtGui.QHBoxLayout()
		
		# Bouton pour lancer les telechargements
		self.pushButtonLancer = QtGui.QPushButton( QtGui.QIcon( "ico/gtk-media-play-ltr.svg" ), u"Lancer téléchargement", self.centralWidget )
		self.horizontalLayoutBarreBas.addWidget( self.pushButtonLancer )

		# Bouton pour stopper les telechargements
		self.pushButtonStop = QtGui.QPushButton( QtGui.QIcon( "ico/gtk-media-stop.svg" ), u"Stopper le téléchargement", self.centralWidget )
		self.pushButtonStop.setEnabled( False )
		self.horizontalLayoutBarreBas.addWidget( self.pushButtonStop )	
	
		###
		# Positionnement des differents widgets/layouts sur le layout de grille
		###
		
		# Layout de grille dans lequel on va placer nos widgets/layouts
		self.gridLayout = QtGui.QGridLayout( self.centralWidget )
		# On ajoute la barre du haut
		self.gridLayout.addLayout( self.horizontalLayoutBarreHaut, 0, 0, 1, 3 )
		# On ajoute le gestionnaire d'onglets
		self.gridLayout.addWidget( self.tabWidget, 1, 0, 1, 3 )
		# On ajoute la barre de progression de telechargement d'un fichier
		self.gridLayout.addWidget( self.progressBarTelechargementFichier, 2, 0, 1, 3 )
		# On ajoute la barre de progression de telechargement des fichiers
		self.gridLayout.addWidget( self.progressBarTelechargement, 3, 0, 1, 3 )
		# On ajoute les boutons ajouter/supprimer/lancer
		self.gridLayout.addLayout( self.horizontalLayoutBarreBas, 4, 0, 1, 3 )
		
		###
		# Mise en place le central widget dans la fenetre
		###
		self.setCentralWidget( self.centralWidget )

		###
		# Mise en place du menu
		###
		
		# Menu barre
		self.menubar = QtGui.QMenuBar( self )
		self.menubar.setGeometry( QtCore.QRect( 0, 0, 480, 25 ) )
		
		# Menu Fichier
		self.menuFichier = QtGui.QMenu( "&Fichier", self.menubar )
		self.menubar.addAction( self.menuFichier.menuAction() )
		
		# Action Fichier -> Quitter
		self.actionQuitter = QtGui.QAction( QtGui.QIcon( "ico/gtk-quit.svg" ), "&Quitter", self )
		self.actionQuitter.setIconVisibleInMenu( True )
		self.menuFichier.addAction( self.actionQuitter )
		
		# Menu Edition
		self.menuEdition = QtGui.QMenu( "&Edition", self.menubar )
		self.menubar.addAction( self.menuEdition.menuAction() )
		
		# Action Edition -> Mise a jour
		self.actionMAJ = QtGui.QAction( QtGui.QIcon( "ico/gtk-refresh.svg" ), u"&Mise à jour des plugins", self )
		self.actionMAJ.setIconVisibleInMenu( True )
		self.menuEdition.addAction( self.actionMAJ )
		
		# Action Edition -> Preferences
		self.actionPreferences = QtGui.QAction( QtGui.QIcon( "ico/gtk-preferences.svg" ), u"&Préférences", self )
		self.actionPreferences.setIconVisibleInMenu( True )
		self.menuEdition.addAction( self.actionPreferences )
		
		# Menu Aide
		self.menuAide = QtGui.QMenu( "&Aide", self.menubar )
		self.menubar.addAction( self.menuAide.menuAction() )
		
		# Action Aide -> A propos
		self.actionAPropos = QtGui.QAction( QtGui.QIcon( "ico/gtk-about.svg" ), u"À p&ropos", self )
		self.actionAPropos.setIconVisibleInMenu( True )
		self.menuAide.addAction( self.actionAPropos )
		
		# Ajout du menu a l'interface
		self.setMenuBar( self.menubar )

		###
		# Signaux provenants de l'interface
		###

		QtCore.QObject.connect( self.tableWidgetFichier,
								QtCore.SIGNAL( "cellClicked(int,int)" ),
								self.afficherInformationsFichier )	
		
		QtCore.QObject.connect( self.tableWidgetFichier,
								QtCore.SIGNAL( "cellDoubleClicked(int,int)" ),
								self.gererTelechargement )	
								
		QtCore.QObject.connect( self.pushButtonToutAjouter,
								QtCore.SIGNAL( "clicked()" ),
								self.ajouterTousLesFichiers )								

		QtCore.QObject.connect( self.pushButtonRafraichirPlugin,
								QtCore.SIGNAL( "clicked()" ),
								self.rafraichirPlugin )

		QtCore.QObject.connect( self.tableWidgetTelechargement,
								QtCore.SIGNAL( "cellDoubleClicked(int,int)" ),
								self.supprimerTelechargement )	
		
		QtCore.QObject.connect( self.pushButtonExtremiteMonter,
								QtCore.SIGNAL( "clicked()" ),
								lambda versLeHaut = True, extremite = True : self.tableWidgetTelechargement.deplacerLigne( versLeHaut, extremite ) )
		
		QtCore.QObject.connect( self.pushButtonMonter,
								QtCore.SIGNAL( "clicked()" ),
								lambda versLeHaut = True, extremite = False : self.tableWidgetTelechargement.deplacerLigne( versLeHaut, extremite ) )
		
		QtCore.QObject.connect( self.pushButtonDescendre,
								QtCore.SIGNAL( "clicked()" ),
								lambda versLeHaut = False, extremite = False : self.tableWidgetTelechargement.deplacerLigne( versLeHaut, extremite ) )
		
		QtCore.QObject.connect( self.pushButtonExtremiteDescendre,
								QtCore.SIGNAL( "clicked()" ),
								lambda versLeHaut = False, extremite = True : self.tableWidgetTelechargement.deplacerLigne( versLeHaut, extremite ) )
		
		QtCore.QObject.connect( self.pushButtonToutSupprimer,
								QtCore.SIGNAL( "clicked()" ),
								self.supprimerTousLesTelechargements )
		
		QtCore.QObject.connect( self.pushButtonNettoyer,
								QtCore.SIGNAL( "clicked()" ),
								self.nettoyer )
		
		QtCore.QObject.connect( self.pushButtonLancer,
								QtCore.SIGNAL( "clicked()" ),
								self.lancerTelechargement )

		QtCore.QObject.connect( self.pushButtonStop,
								QtCore.SIGNAL( "clicked()" ),
								self.stopperTelechargement )
		
		QtCore.QObject.connect( self.actionQuitter,
								QtCore.SIGNAL( "triggered()" ),
								self.close )						
	
		################################################
		# Instanciations + initialisation de variables #
		################################################
		
		# Fenetre About
		self.aProposDialog = None
		# Fenetre des preferences du logiciel
		self.preferencesDialog = None
		# Fenetre de mise a jour des plugins
		self.updateManagerDialog = None
		# Nom plugin courant
		self.nomPluginCourant = ""
		# Liste des fichiers
		self.listeFichiers = []
		# Liste des fichiers a telecharger
		self.listeFichiersATelecharger = []
		# Cache des images descriptive
		# Clef : urlImage Valeur : image (binaire)
		self.cacheImage = {}
		
		# On intancie le lanceur de signaux
		self.signaux = Signaux()
		# On instancie le gestionnaire de preferences
		self.preferences = Preferences()
		# On instancie le gestionnaire de preferences des plugins
		self.preferencesPluginDialog = PreferencePluginDialog( self )
		# On instancie le gestionnaire de download
		self.downloader = Downloader( self.signaux )	
		# On recupere l'instance de API
		self.api = API.getInstance()
		# On instancie le gestionnaire d'historique
		self.historique = Historique()
		# On instancie la fenetre d'attente
		self.fenetreAttenteProgressDialog = FenetreAttenteProgressDialog( self )
		# On instancie le gest								 
		
		#
		# Fenetre de confirmation pour quitter le logiciel
		#
		self.quitterMessageBox = QtGui.QMessageBox( self )
		self.quitterMessageBox.setWindowTitle( "Fermeture de TVDownloader" )
		self.quitterMessageBox.setText( u"Voulez-vous réellement quitter TVDownloader ?" )
		self.quitterMessageBox.setInformativeText( u"Votre liste de téléchargement sera perdue" )
		self.quitterMessageBox.addButton( "Oui", QtGui.QMessageBox.AcceptRole )
		self.quitterMessageBox.addButton( "Non", QtGui.QMessageBox.RejectRole )
		
		############################################################
		# On connecte les signaux des instances precedements crees #
		############################################################	

		QtCore.QObject.connect( self.pushButtonOuvrirDossierTelechargement,
								QtCore.SIGNAL( "clicked()" ),
								self.ouvrirRepertoireTelechargement )
		
		QtCore.QObject.connect( self.comboBoxSite,
								QtCore.SIGNAL( "activated(QString)" ),
								self.listerChaines )
		
		QtCore.QObject.connect( self.comboBoxChaine,
								QtCore.SIGNAL( "activated(QString)" ),
								self.listerEmissions )
		
		QtCore.QObject.connect( self.comboBoxEmission,
								QtCore.SIGNAL( "activated(QString)" ),
								self.listerFichiers )

		QtCore.QObject.connect( self.pushButtonPreferencesPlugin,
								QtCore.SIGNAL( "clicked()" ),
								self.ouvrirPreferencesPlugin )

		QtCore.QObject.connect( self.actionPreferences,
								QtCore.SIGNAL( "triggered()" ),
								self.ouvrirPreferencesLogiciel )	
								
		QtCore.QObject.connect( self.actionMAJ,
								QtCore.SIGNAL( "triggered()" ),
								self.ouvrirFenetreMiseAJour )	

		QtCore.QObject.connect( self.actionAPropos,
								QtCore.SIGNAL( "triggered()" ),
								self.ouvrirFenetreAPropos )
		
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "debutActualisation(PyQt_PyObject)" ) , self.fenetreAttenteProgressDialog.ouvrirFenetreAttente )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "finActualisation()" ) , self.fenetreAttenteProgressDialog.fermerFenetreAttente )		
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "actualiserListesDeroulantes()" ) , self.actualiserListesDeroulantes )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "listeChaines(PyQt_PyObject)" ) , self.ajouterChaines )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "listeEmissions(PyQt_PyObject)" ) , self.ajouterEmissions )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "listeFichiers(PyQt_PyObject)" ) , self.ajouterFichiers )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "nouvelleImage(PyQt_PyObject)" ) , self.mettreEnPlaceImage )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "debutTelechargement(int)" ) , self.debutTelechargement )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "finTelechargement(int)" ) , self.finTelechargement )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "finDesTelechargements()" ) , self.activerDesactiverInterface )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "pourcentageFichier(int)" ) , self.progressBarTelechargementFichier.setValue )		

		#########
		# Début #
		#########			
		
		# La fenetre prend la dimension qu'elle avait a sa fermeture
		taille = self.preferences.getPreference( "tailleFenetre" )
		self.resize( taille[ 0 ], taille[ 1 ] )
		
		# Si aucun plugin n'est active, on ouvre la fenetre des preferences
		if( len( self.preferences.getPreference( "pluginsActifs" ) ) == 0 ):
			self.ouvrirPreferencesLogiciel()
		
		# On actualise tous les plugins
		self.rafraichirTousLesPlugins()

	## Methode qui execute les actions necessaires avant de quitter le programme
	def actionsAvantQuitter( self ):
		# On sauvegarde les options des plugins
		self.api.fermeture()
		# On sauvegarde la taille de la fenetre
		taille = self.size()
		self.preferences.setPreference( "tailleFenetre", [ taille.width(), taille.height() ] )
		# On sauvegarde les options du logiciel
		self.preferences.sauvegarderConfiguration()
		# On sauvegarde l'historique
		self.historique.sauverHistorique()
		# On stoppe les telechargements
		self.stopperTelechargement()

	#########################################
	# Surcharge des methodes de QMainWindow #
	#########################################
	
	## Surcharge de la methode appelee lors de la fermeture de la fenetre
	# Ne doit pas etre appele explicitement
	# @param evenement Evenement qui a provoque la fermeture
	def closeEvent( self, evenement ):
		# On affiche une fenetre pour demander la fermeture si des fichiers sont dans la liste de telechargement
		if( self.tableWidgetTelechargement.rowCount() > 0 ):
			# On affiche une fenetre qui demande si on veut quitter
			retour = self.quitterMessageBox.exec_()
			# Si on veut quitter
			if( retour == 0 ):
				# On execute les actions necessaires
				self.actionsAvantQuitter()
				# On accept la fermeture
				evenement.accept()
			else:
				# On refuse la fermeture
				evenement.ignore()
		else: # S'il n'y a pas de fichier
			# On execute les actions necessaires
			self.actionsAvantQuitter()
			# On accept la fermeture
			evenement.accept()		

	##############################################
	# Methodes pour remplir les menus deroulants #
	##############################################

	## Methode qui actualise les listes deroulantes
	def actualiserListesDeroulantes( self ):
		# On lance juste l'ajout des sites en se basant sur les plugins actifs
		self.ajouterSites( self.preferences.getPreference( "pluginsActifs" ) )

	## Methode qui lance le listage des chaines
	# @param site Nom du plugin/site pour lequel on va lister les chaines
	def listerChaines( self, site ):
		def threadListerChaines( self, nomPlugin ):
			self.signaux.signal( "debutActualisation", nomPlugin )
			listeChaines = self.api.getPluginListeChaines( nomPlugin )
			self.signaux.signal( "listeChaines", listeChaines )
			self.signaux.signal( "finActualisation" )
			
		if( site != "" ):
			self.nomPluginCourant = qstringToString( site )
			threading.Thread( target = threadListerChaines, args = ( self, self.nomPluginCourant ) ).start()
			# On active (ou pas) le bouton de preference du plugin
			self.pushButtonPreferencesPlugin.setEnabled( self.api.getPluginListeOptions( self.nomPluginCourant ) != [] )
		
	## Methode qui lance le listage des emissions
	# @param chaine Nom de la chaine pour laquelle on va lister les emissions
	def listerEmissions( self, chaine ):
		def threadListerEmissions( self, nomPlugin, chaine ):
			self.signaux.signal( "debutActualisation", nomPlugin )
			listeEmissions = self.api.getPluginListeEmissions( nomPlugin, chaine )
			self.signaux.signal( "listeEmissions", listeEmissions )
			self.signaux.signal( "finActualisation" )
			
		if( chaine != "" ):
			threading.Thread( target = threadListerEmissions, args = ( self, self.nomPluginCourant, qstringToString( chaine ) ) ).start()
		
	## Methode qui lance le listage des fichiers
	# @param emission Nom de l'emission pour laquelle on va lister les fichiers
	def listerFichiers( self, emission ):
		def threadListerFichiers( self, nomPlugin, emission ):
			self.signaux.signal( "debutActualisation", nomPlugin )
			listeFichiers = self.api.getPluginListeFichiers( nomPlugin, emission )
			self.signaux.signal( "listeFichiers", listeFichiers )
			self.signaux.signal( "finActualisation" )
			
		if( emission != "" ):
			threading.Thread( target = threadListerFichiers, args = ( self, self.nomPluginCourant, qstringToString( emission ) ) ).start()
	
	## Methode qui met en place une liste de sites sur l'interface
	# @param listeSites Liste des sites a mettre en place
	def ajouterSites( self, listeSites ):
		# On efface la liste des sites
		self.comboBoxSite.clear()
		# On met en place les sites
		for site in listeSites:
			self.comboBoxSite.addItem( stringToQstring( site ) )
		# On selectionne par defaut celui choisis dans les preference
		index = self.comboBoxSite.findText( stringToQstring( self.preferences.getPreference( "pluginParDefaut" ) ) )
		if( index != -1 ):
			self.comboBoxSite.setCurrentIndex( index )
		# On lance l'ajout des chaines
		self.listerChaines( self.comboBoxSite.currentText() )
	
	## Methode qui met en place une liste de chaines sur l'interface
	# @param listeChaines Liste des chaines a mettre en place
	def ajouterChaines( self, listeChaines ):
		# On trie la liste des chaines
		listeChaines.sort()
		# On efface la liste des chaines
		self.comboBoxChaine.clear()
		# On efface la liste des emissions
		self.comboBoxEmission.clear()
		# On efface la liste des fichiers
		self.tableWidgetFichier.toutSupprimer()		
		# On met en place les chaines
		for chaine in listeChaines:
			self.comboBoxChaine.addItem( stringToQstring( chaine ) )
		# Si on a juste une seule chaine
		if( self.comboBoxChaine.count() == 1 ):
			# On lance l'ajout des emissions
			self.listerEmissions( self.comboBoxChaine.currentText() )
		else:
			# On ne selectionne pas de chaine
			self.comboBoxChaine.setCurrentIndex( -1 )			

	## Methode qui met en place une liste d'emissions sur l'interface
	# @param listeEmissions Liste des emissions a mettre en place	
	def ajouterEmissions( self, listeEmissions ):
		# On trie la liste des emissions
		listeEmissions.sort()
		# On efface la liste des emissions
		self.comboBoxEmission.clear()
		# On efface la liste des fichiers
		self.tableWidgetFichier.toutSupprimer()
		# On met en place la liste des emissions
		for emission in listeEmissions:
			self.comboBoxEmission.addItem( stringToQstring( emission ) )
		# Si on a juste une seule emission
		if( self.comboBoxEmission.count() == 1 ):
			# On lance l'ajout des fichiers
			self.listerFichiers( self.comboBoxEmission.currentText() )
		else:
			# On ne selectionne pas d'emission
			self.comboBoxEmission.setCurrentIndex( -1 )
	
	###############################################
	# Methodes pour remplir la liste des fichiers #
	###############################################
	
	## Methode pour ajouter des fichiers a l'interface
	# @param listeFichiers Liste des fichiers a ajouter
	def ajouterFichiers( self, listeFichiers ):
		self.listeFichiers = listeFichiers
		# On efface la liste des fichiers
		self.tableWidgetFichier.toutSupprimer()
		# On commence au depart
		ligneCourante = 0
		# On met en place chacun des fichiers
		for fichier in listeFichiers:
			# On ajoute une ligne
			self.tableWidgetFichier.insertRow( ligneCourante )
			# On ajoute les informations au tableWidgetFichier
			liste = []
			liste.append( self.tableWidgetFichier.creerItem( "" ) )
			liste.append( self.tableWidgetFichier.creerItem( getattr( fichier, "date" ) ) )
			liste.append( self.tableWidgetFichier.creerItem( getattr( fichier, "nom" ) ) )
			self.tableWidgetFichier.setLigne( ligneCourante, liste )
			# On met en place l'icone qui va bien
			self.gererIconeListeFichier( fichier )
			ligneCourante += 1
		# On adapte la taille des colonnes
		self.tableWidgetFichier.adapterColonnes()

	## Methode qui rafraichit le plugin courant
	def rafraichirPlugin( self ):
		def threadRafraichirPlugin( self, nomPlugin ):
			self.signaux.signal( "debutActualisation", nomPlugin )
			self.api.pluginRafraichir( nomPlugin )
			self.signaux.signal( "finActualisation" )
			
		threading.Thread( target = threadRafraichirPlugin, args = ( self, self.nomPluginCourant ) ).start()	


	## Methode qui met en place l'image de la description d'un fichier
	# @param image Image a mettre en place (binaire)
	def mettreEnPlaceImage( self, image ):
		logoFichier = QtGui.QPixmap()
		logoFichier.loadFromData( image )
		self.labelLogo.setPixmap( logoFichier.scaled( QtCore.QSize( 150, 150 ), QtCore.Qt.KeepAspectRatio ) )
	
	## Methode qui affiche des informations sur le fichier selectionne	
	def afficherInformationsFichier( self, ligne, colonne ):
		def threadRecupererImage( self, urlImage ):
			image = self.api.getPage( urlImage )
			self.cacheImage[ urlImage ] = image
			self.signaux.signal( "nouvelleImage", image )
		
		fichier = self.listeFichiers[ ligne ]
		# On recupere le lien de l'image et le texte descriptif
		urlImage        = getattr( fichier, "urlImage" )
		texteDescriptif = getattr( fichier, "descriptif" )
		
		self.plainTextEdit.clear()
		# Si on a un texte descriptif, on l'affiche
		if( texteDescriptif != "" ):
			self.plainTextEdit.appendPlainText( stringToQstring( texteDescriptif ) )
		else:
			self.plainTextEdit.appendPlainText( u"Aucune information disponible" )
		
		# Si on n'a pas d'image
		if( urlImage == "" ):
			# On met en place celle par defaut
			self.logoFichier = self.logoFichierDefaut
			self.labelLogo.setPixmap( self.logoFichier.scaled( QtCore.QSize( 150, 150 ), QtCore.Qt.KeepAspectRatio ) )
		else: # Si on en a une
			# Si elle est dans le cache des images
			if( self.cacheImage.has_key( urlImage ) ):
				self.mettreEnPlaceImage( self.cacheImage[ urlImage ] )
			else: # Sinon
				# On lance le thread pour la recuperer
				threading.Thread( target = threadRecupererImage, args = ( self, urlImage ) ).start()

	## Methode qui gere l'icone d'un fichier dans la liste des telechargements
	# Il y a 3 icones possible :
	#  - C'est un fichier
	#  - C'est un fichier present dans l'historique (donc deja telecharge)
	#  - C'est un fichier present dans la liste des telechargements
	# @param fichier Fichier a gerer
	def gererIconeListeFichier( self, fichier ):
		if( fichier in self.listeFichiers ):
			ligneFichier = self.listeFichiers.index( fichier )
			# On cherche quel icone mettre en place
			if( fichier in self.listeFichiersATelecharger ):
				icone = self.iconeAjoute
			elif( self.historique.comparerHistorique( fichier ) ):
				icone = self.iconeTelecharge
			else:
				icone = self.iconeFichier
			# On met en place l'icone
			self.tableWidgetFichier.item( ligneFichier, 0 ).setIcon( icone )	

	######################################################
	# Methodes pour remplir la liste des telechargements #
	######################################################
	
	## Methode qui gere la liste des telechargements
	# @param ligne   Numero de la ligne (dans la liste des fichiers) de l'element a ajouter
	# @param colonne Numero de colonne (inutile, juste pour le slot)
	def gererTelechargement( self, ligne, colonne = 0 ):
		fichier = self.listeFichiers[ ligne ]
		# Si le fichier est deja dans la liste des telechargements
		if( fichier in self.listeFichiersATelecharger ):
			ligneTelechargement = self.listeFichiersATelecharger.index( fichier )
			self.supprimerTelechargement( ligneTelechargement )
		else: # S'il n'y est pas, on l'ajoute
			self.listeFichiersATelecharger.append( fichier )
			numLigne = self.tableWidgetTelechargement.rowCount()
			# On insere une nouvelle ligne dans la liste des telechargements
			self.tableWidgetTelechargement.insertRow( numLigne )
			# On y insere les elements qui vont biens
			self.tableWidgetTelechargement.setLigne( numLigne, 
													 [ self.tableWidgetTelechargement.creerItem( getattr( fichier, "date" ) ),
													   self.tableWidgetTelechargement.creerItem( getattr( fichier, "nom" ) ),
													   self.tableWidgetTelechargement.creerItem( u"En attente de téléchargement" )
													 ]
												   )
			# On adapte la taille des colonnes
			self.tableWidgetTelechargement.adapterColonnes()
			# On modifie l'icone dans la liste des fichiers
			self.gererIconeListeFichier( fichier )
	
	## Methode qui ajoute tous les fichiers a la liste des telechargements
	def ajouterTousLesFichiers( self ):
		for i in range( self.tableWidgetFichier.rowCount() ):
			self.gererTelechargement( i )
	
	## Methode qui supprime un fichier de la liste des telechargements
	# @param ligne   Numero de la ligne a supprimer
	# @param colonne Numero de colonne (inutile, juste pour le slot)	
	def supprimerTelechargement(  self, ligne, colonne = 0 ):
		fichier = self.listeFichiersATelecharger[ ligne ]
		# On supprime l'element du tableWidgetTelechargement
		self.tableWidgetTelechargement.removeRow( ligne )
		# On supprime l'element de la liste des fichiers a telecharger
		self.listeFichiersATelecharger.remove( fichier )
		# On modifie l'icone dans la liste des fichiers
		self.gererIconeListeFichier( fichier )
	
	## Methode qui supprime tous les telechargement de la liste des telechargements
	def supprimerTousLesTelechargements( self ):
		for i in range( self.tableWidgetTelechargement.rowCount() -1, -1, -1 ):
			self.supprimerTelechargement( i )
		
	## Methode qui lance le telechargement des fichiers	
	def lancerTelechargement( self ):	
		# On liste les emissions a telecharger avec leurs numeros de ligne
		listeFichiers = []
		for i in range( self.tableWidgetTelechargement.rowCount() ): # Pour chaque ligne
			fichier = self.listeFichiersATelecharger[ i ]
			listeFichiers.append( [ i,
									getattr( fichier, "lien" ),
									getattr( fichier, "nomFichierSortie" ) ] )
				
		nbATelecharger = len( listeFichiers )
		# Si on a des elements a charger
		if( nbATelecharger > 0 ):
			# On met en place la valeur du progressBar
			self.progressBarTelechargement.setMaximum( nbATelecharger )
			self.progressBarTelechargement.setValue( 0 )
			# On lance le telechargement
			threading.Thread( target = self.downloader.lancerTelechargement, args = ( listeFichiers, ) ).start()
			# On active/desactive ce qui va bien sur l'interface
			self.activerDesactiverInterface( True )
			
	## Methode qui stoppe le telechargement
	def stopperTelechargement( self ):
		# On stoppe le telechargement
		self.downloader.stopperTelechargement()

	############################################
	# Methodes pour ouvrir les autres fenetres #
	############################################
	
	#
	# Fenetre About
	#
	
	## Methode pour afficher la fenetre About
	def ouvrirFenetreAPropos( self ):
		if( self.aProposDialog == None ):
			self.aProposDialog = AProposDialog()
		self.aProposDialog.show()
		
	#
	# Fenetre de preference du logiciel
	#
	
	## Methode pour ouvrir les preferences du logiciel
	def ouvrirPreferencesLogiciel( self ):
		if( self.preferencesDialog == None ):
			self.preferencesDialog = PreferencesDialog( self, self.signaux )
		self.preferencesDialog.afficher()
	
	#
	# Fenetre de mise a jour des plugins
	#
	
	## Methode pour ouvrir la fenetre de mise a jour des plugins
	def ouvrirFenetreMiseAJour( self ):
		if( self.updateManagerDialog == None ):
			self.updateManagerDialog = UpdateManagerDialog( self )
		self.updateManagerDialog.afficher()	
	
	#
	# Fenetre de preference des plugins
	# 
	
	## Methode pour ouvrir les preferences du plugin courant	
	def ouvrirPreferencesPlugin( self ):
		listeOptions = self.api.getPluginListeOptions( self.nomPluginCourant )
		self.preferencesPluginDialog.ouvrirDialogPreferences( self.nomPluginCourant, listeOptions )
			
	#########
	# Slots #
	#########
	
	## Methode qui ouvre le repertoire de telechargement
	def ouvrirRepertoireTelechargement( self ):
		QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile( self.preferences.getPreference( "repertoireTelechargement" ) ) )
	
	## Methode qui rafraichit le plugin courant
	def rafraichirPlugin( self ):
		def threadRafraichirPlugin( self, nomPlugin ):
			self.signaux.signal( "debutActualisation", nomPlugin )
			self.api.pluginRafraichir( nomPlugin )
			self.signaux.signal( "finActualisation" )
			
		threading.Thread( target = threadRafraichirPlugin, args = ( self, self.nomPluginCourant ) ).start()		
	
	## Methode qui rafraichit tous les plugins
	# A utiliser au lancement du programme
	def rafraichirTousLesPlugins( self ):
		def threadRafraichirTousLesPlugins( self ):
			self.signaux.signal( "debutActualisation", "TVDownloader" )
			self.api.pluginRafraichirAuto()
			self.signaux.signal( "finActualisation" )
			self.signaux.signal( "actualiserListesDeroulantes" )
			
		threading.Thread( target = threadRafraichirTousLesPlugins, args = ( self, ) ).start()
	
	## Slot qui active/desactive des elements de l'interface pendant un telechargement
	# @param telechargementEnCours Indique si on telecharge ou pas
	def activerDesactiverInterface( self, telechargementEnCours = False ):
		# Les boutons
		self.pushButtonLancer.setEnabled( not telechargementEnCours )
		self.pushButtonStop.setEnabled( telechargementEnCours )
		self.pushButtonExtremiteMonter.setEnabled( not telechargementEnCours )
		self.pushButtonMonter.setEnabled( not telechargementEnCours )
		self.pushButtonDescendre.setEnabled( not telechargementEnCours )
		self.pushButtonExtremiteDescendre.setEnabled( not telechargementEnCours )
		self.pushButtonToutSupprimer.setEnabled( not telechargementEnCours )
		self.pushButtonNettoyer.setEnabled( not telechargementEnCours )
		
		# Le table widget
		self.tableWidgetTelechargement.setEnabled( not telechargementEnCours )

	## Slot appele lors ce qu'un le debut d'un telechargement commence
	# @param numero Position dans la liste des telechargement du telechargement qui commence
	def debutTelechargement( self, numero ):
		self.tableWidgetTelechargement.item( numero, 2 ).setText( stringToQstring( u"Téléchargement en cours..." ) )
		self.tableWidgetTelechargement.adapterColonnes()
		self.progressBarTelechargementFichier.setValue( 0 )

	## Slot appele lorsqu'un telechargement se finit
	# @param numero Position dans la liste des telechargement du telechargement qui se finit	
	def finTelechargement( self, numero ):
		fichier = self.listeFichiersATelecharger[ numero ]
		# On ajoute le fichier a l'historique
		self.historique.ajouterHistorique( fichier )
		# On modifie l'icone dans la liste des fichiers
		self.gererIconeListeFichier( fichier )	
		# On modifie l'interface
		self.tableWidgetTelechargement.item( numero, 2 ).setText( stringToQstring( u"Fini !" ) )
		self.progressBarTelechargement.setValue( self.progressBarTelechargement.value() + 1 )
		self.tableWidgetTelechargement.adapterColonnes()
		self.progressBarTelechargementFichier.setValue( 100 )
	
	## Slot qui nettoie la liste des telechargements de tous les telechargements finis
	def nettoyer( self ):
		for i in range( self.tableWidgetTelechargement.rowCount() - 1, -1, -1 ): # [ nbLignes - 1, nbLignes - 2, ..., 1, 0 ]
			if( self.tableWidgetTelechargement.item( i, 2 ).text() == u"Fini !" ): # Si c'est telecharge
				self.supprimerTelechargement( i )
コード例 #22
0
 def setUp(self):
     self.historique = Historique()
コード例 #23
0
	def __init__( self ):
		# Appel au constructeur de la classe mere
		QtGui.QMainWindow.__init__( self )
		
		###########
		# Fenetre #
		###########
		
		###
		# Reglages de la fenetre principale
		###
		
		# Nom de la fenetre
		self.setWindowTitle( "TVDownloader" )
		# Mise en place de son icone
		self.setWindowIcon( QtGui.QIcon( "ico/TVDownloader.png" ) )
		
		###
		# Mise en place des widgets dans la fenetre
		###
		
		# Widget central qui contiendra tout
		self.centralWidget = QtGui.QWidget( self )
		
		#
		# Barre du haut
		#
		
		# Layout horizontal qui contiendra les listes deroulantes
		self.horizontalLayoutBarreHaut = QtGui.QHBoxLayout()
		
		# Liste deroulante pour choisir le site (plugin)
		self.comboBoxSite = QtGui.QComboBox( self.centralWidget )
		self.horizontalLayoutBarreHaut.addWidget( self.comboBoxSite )
		
		# Liste deroulante pour choisir une chaine du site courant
		self.comboBoxChaine = QtGui.QComboBox( self.centralWidget)
		self.horizontalLayoutBarreHaut.addWidget( self.comboBoxChaine )
		
		# Liste deroulante pour choisir une emission de la chaine courante
		self.comboBoxEmission = QtGui.QComboBox( self.centralWidget )
		self.horizontalLayoutBarreHaut.addWidget( self.comboBoxEmission )
		
		#
		# Onglets
		#
		
		# Gestionnaire onglets
		self.tabWidget = QtGui.QTabWidget( self.centralWidget )
		
		# Onglet Fichiers
		self.tabFichiers = QtGui.QSplitter( self.centralWidget ) # L'onglet Fichier contient un splitter
		self.tabWidget.addTab( self.tabFichiers, u"Choix des fichiers" )
		
		# Onglet Telechargements
		self.tabTelechargements = QtGui.QWidget( self.centralWidget )
		self.tabWidget.addTab( self.tabTelechargements, u"Téléchargements" )
		
		#
		# Liste des fichiers
		#
		
		# Layout de grille qui contient le tableau qui liste les fichiers + boutons
		self.gridLayoutFichiers = QtGui.QGridLayout( self.tabFichiers )
		
		# Tableau qui contient la liste des fichiers disponibles pour l'emission courante
		self.tableWidgetFichier = MyQTableWidget( self.tabFichiers )
		# Il a 4 colonnes et 0 ligne (pour l'instant)
		self.tableWidgetFichier.setColumnCount( 3 )
		self.tableWidgetFichier.setRowCount( 0 )
		# On ajoute les titres
		self.tableWidgetFichier.setHorizontalHeaderItem( 0,
														 self.tableWidgetFichier.creerItem( "" ) )
		self.tableWidgetFichier.setHorizontalHeaderItem( 1,
														 self.tableWidgetFichier.creerItem( "Date" ) )
		self.tableWidgetFichier.setHorizontalHeaderItem( 2,
														 self.tableWidgetFichier.creerItem( "Emission" ) )
		# On l'ajoute au layout
		self.gridLayoutFichiers.addWidget( self.tableWidgetFichier, 0, 1, 6, 1 )
		
		# Icones du tableWidget
		self.iconeFichier     = QtGui.QIcon( "ico/gtk-file.svg" )
		self.iconeAjoute      = QtGui.QIcon( "ico/gtk-add.svg" )
		self.iconeTelecharge  = QtGui.QIcon( "ico/gtk-apply.svg" )
		
		# Bouton pour ajouter tous les fichiers a la liste des telechargements
		self.pushButtonToutAjouter = MyQPushButton( self.tabFichiers )
		self.pushButtonToutAjouter.setIcon( QtGui.QIcon( "ico/gtk-add.svg" ) )
		self.pushButtonToutAjouter.setToolTip( u"Ajouter tous les fichiers à la liste des téléchargements" )
		self.gridLayoutFichiers.addWidget( self.pushButtonToutAjouter, 0, 0, 2, 1 )
		
		# Bouton pour rafraichir le plugin courant
		self.pushButtonRafraichirPlugin = MyQPushButton( self.tabFichiers )
		self.pushButtonRafraichirPlugin.setIcon( QtGui.QIcon( "ico/gtk-refresh.svg" ) )
		self.pushButtonRafraichirPlugin.setToolTip( "Rafraichir le plugin" )
		self.gridLayoutFichiers.addWidget( self.pushButtonRafraichirPlugin, 2, 0, 2, 1 )

		# Bouton pour ouvrir la fenetre des preferences du plugin courant
		self.pushButtonPreferencesPlugin = MyQPushButton( self.tabFichiers )
		self.pushButtonPreferencesPlugin.setIcon( QtGui.QIcon( "ico/gtk-preferences.svg" ) )
		self.pushButtonPreferencesPlugin.setToolTip( u"Ouvrir les préférences du plugin" )
		self.gridLayoutFichiers.addWidget( self.pushButtonPreferencesPlugin, 4, 0, 2, 1 )
		
		# On met en place ce layout sur un widget (pour le splitter)
		self.widgetFichiers = QtGui.QWidget()
		self.widgetFichiers.setLayout( self.gridLayoutFichiers )
		
		#
		# Descriptif des fichiers
		#
		
		# Layout de grille
		self.gridLayoutDescriptif = QtGui.QGridLayout()
		
		# Label pour afficher un logo
		self.logoFichierDefaut = QtGui.QPixmap()
		self.logoFichierDefaut.load( "img/gtk-dialog-question.svg" )
		
		self.labelLogo = QtGui.QLabel( self.centralWidget )
		self.labelLogo.setPixmap( self.logoFichierDefaut.scaled( QtCore.QSize( 150, 150 ), QtCore.Qt.KeepAspectRatio ) )
		
		self.gridLayoutDescriptif.addWidget( self.labelLogo, 0, 0, 1, 1 )
		
		# Zone de texte pour afficher un descriptif
		self.plainTextEdit = QtGui.QPlainTextEdit( self.centralWidget )
		self.gridLayoutDescriptif.addWidget( self.plainTextEdit, 0, 1, 1, 2 )
		
		# On met en place ce layout sur un widget (pour le splitter)
		self.widgetDescriptif = QtGui.QWidget()
		self.widgetDescriptif.setLayout( self.gridLayoutDescriptif )
		

		# Onrientation verticale du splitter
		self.tabFichiers.setOrientation( QtCore.Qt.Vertical )
		
		# On ajoute les 2 elements au splitter (qui est notre onglet)
		self.tabFichiers.addWidget( self.widgetFichiers )
		self.tabFichiers.addWidget( self.widgetDescriptif )
		
		#
		# Liste des telechargements
		#
		
		# Layout de grille qui contient le tableau qui liste les fichiers a telecharger + les boutons pour le controller
		self.gridLayoutTelechargement = QtGui.QGridLayout( self.tabTelechargements )
		
		# Tableau qui contient la liste des fichiers a telecharger
		self.tableWidgetTelechargement = MyQTableWidget( self.tabTelechargements )
		# Il a 5 colonnes et 0 ligne (pour l'instant)
		self.tableWidgetTelechargement.setColumnCount( 3 )
		self.tableWidgetTelechargement.setRowCount( 0 )
		# On ajoute le titre des 5 colonnes
		self.tableWidgetTelechargement.setHorizontalHeaderItem( 0,
																self.tableWidgetTelechargement.creerItem( "Date" ) )
		self.tableWidgetTelechargement.setHorizontalHeaderItem( 1,
																self.tableWidgetTelechargement.creerItem( "Emission" ) )
		self.tableWidgetTelechargement.setHorizontalHeaderItem( 2,
																self.tableWidgetTelechargement.creerItem( "Etat" ) )
		# On l'ajoute au layout
		self.gridLayoutTelechargement.addWidget( self.tableWidgetTelechargement, 0, 1, 4, 1 )
		
		# Bouton pour monter l'element selectionne tout en haut de la liste
		self.pushButtonExtremiteMonter = MyQPushButton( self.tabTelechargements )
		self.pushButtonExtremiteMonter.setIcon( QtGui.QIcon( "ico/gtk-jump-to-rtl.svg" ) )
		self.pushButtonExtremiteMonter.setToolTip( u"Placer l'élément sélectionné tout en haut" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonExtremiteMonter, 0, 0, 1, 1 )
		
		# Bouton pour monter l'element selectionne d'un cran dans la liste
		self.pushButtonMonter = MyQPushButton( self.tabTelechargements )
		self.pushButtonMonter.setIcon( QtGui.QIcon( "ico/gtk-go-up.svg" ) )
		self.pushButtonMonter.setToolTip( u"Monter l'élément sélectionné" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonMonter, 1, 0, 1, 1 )

		# Bouton pour descendre l'element selectionne d'un cran dans la liste
		self.pushButtonDescendre = MyQPushButton( self.tabTelechargements )
		self.pushButtonDescendre.setIcon( QtGui.QIcon( "ico/gtk-go-down.svg" ) )
		self.pushButtonDescendre.setToolTip( u"Descendre l'élément selectionné" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonDescendre, 2, 0, 1, 1 )
		
		# Bouton pour descendre l'element selectionne tout en bas de la liste
		self.pushButtonExtremiteDescendre = MyQPushButton( self.tabTelechargements )
		self.pushButtonExtremiteDescendre.setIcon( QtGui.QIcon( "ico/gtk-jump-to-ltr.svg" ) )
		self.pushButtonExtremiteDescendre.setToolTip( u"Placer l'élément sélectionné tout en bas" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonExtremiteDescendre, 3, 0, 1, 1 )
		
		# Bouton pour supprimer tous les elements de la liste
		self.pushButtonToutSupprimer = MyQPushButton( self.tabTelechargements )
		self.pushButtonToutSupprimer.setIcon( QtGui.QIcon( "ico/gtk-cancel.svg" ) )
		self.pushButtonToutSupprimer.setToolTip( u"Supprimer tous les téléchargements" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonToutSupprimer, 0, 2, 1, 1 )
		
		# Bouton pour supprimer de la liste les telechargements termines
		self.pushButtonNettoyer = MyQPushButton( self.tabTelechargements )
		self.pushButtonNettoyer.setIcon( QtGui.QIcon( "ico/gtk-delete-full.svg" ) )
		self.pushButtonNettoyer.setToolTip( u"Supprimer les téléchargement terminés" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonNettoyer, 1, 2, 1, 1 )
		
		# Bouton pour ouvrir le dossier des telechargements
		self.pushButtonOuvrirDossierTelechargement = MyQPushButton( self.tabTelechargements )
		self.pushButtonOuvrirDossierTelechargement.setIcon( QtGui.QIcon( "ico/gtk-folder.svg" ) )
		self.pushButtonOuvrirDossierTelechargement.setToolTip( u"Ouvrir le dossier des téléchargements" )
		self.gridLayoutTelechargement.addWidget( self.pushButtonOuvrirDossierTelechargement, 2, 2, 1, 1 )
		
		#
		# Barre progression de telechargement d'un fichier
		#
		self.progressBarTelechargementFichier = QtGui.QProgressBar( self.centralWidget )
		self.progressBarTelechargementFichier.setProperty( "value", 0 )
		
		#
		# Barre de progression de telechargement des fichiers
		#
		self.progressBarTelechargement = QtGui.QProgressBar( self.centralWidget )
		self.progressBarTelechargement.setProperty( "value", 0 )
		
		#
		# Boutons du bas pour gerer ajouter/supprimer/lancer telechargements
		#
		
		# Layout horizontal qui contiendra les boutons
		self.horizontalLayoutBarreBas = QtGui.QHBoxLayout()
		
		# Bouton pour lancer les telechargements
		self.pushButtonLancer = QtGui.QPushButton( QtGui.QIcon( "ico/gtk-media-play-ltr.svg" ), u"Lancer téléchargement", self.centralWidget )
		self.horizontalLayoutBarreBas.addWidget( self.pushButtonLancer )

		# Bouton pour stopper les telechargements
		self.pushButtonStop = QtGui.QPushButton( QtGui.QIcon( "ico/gtk-media-stop.svg" ), u"Stopper le téléchargement", self.centralWidget )
		self.pushButtonStop.setEnabled( False )
		self.horizontalLayoutBarreBas.addWidget( self.pushButtonStop )	
	
		###
		# Positionnement des differents widgets/layouts sur le layout de grille
		###
		
		# Layout de grille dans lequel on va placer nos widgets/layouts
		self.gridLayout = QtGui.QGridLayout( self.centralWidget )
		# On ajoute la barre du haut
		self.gridLayout.addLayout( self.horizontalLayoutBarreHaut, 0, 0, 1, 3 )
		# On ajoute le gestionnaire d'onglets
		self.gridLayout.addWidget( self.tabWidget, 1, 0, 1, 3 )
		# On ajoute la barre de progression de telechargement d'un fichier
		self.gridLayout.addWidget( self.progressBarTelechargementFichier, 2, 0, 1, 3 )
		# On ajoute la barre de progression de telechargement des fichiers
		self.gridLayout.addWidget( self.progressBarTelechargement, 3, 0, 1, 3 )
		# On ajoute les boutons ajouter/supprimer/lancer
		self.gridLayout.addLayout( self.horizontalLayoutBarreBas, 4, 0, 1, 3 )
		
		###
		# Mise en place le central widget dans la fenetre
		###
		self.setCentralWidget( self.centralWidget )

		###
		# Mise en place du menu
		###
		
		# Menu barre
		self.menubar = QtGui.QMenuBar( self )
		self.menubar.setGeometry( QtCore.QRect( 0, 0, 480, 25 ) )
		
		# Menu Fichier
		self.menuFichier = QtGui.QMenu( "&Fichier", self.menubar )
		self.menubar.addAction( self.menuFichier.menuAction() )
		
		# Action Fichier -> Quitter
		self.actionQuitter = QtGui.QAction( QtGui.QIcon( "ico/gtk-quit.svg" ), "&Quitter", self )
		self.actionQuitter.setIconVisibleInMenu( True )
		self.menuFichier.addAction( self.actionQuitter )
		
		# Menu Edition
		self.menuEdition = QtGui.QMenu( "&Edition", self.menubar )
		self.menubar.addAction( self.menuEdition.menuAction() )
		
		# Action Edition -> Mise a jour
		self.actionMAJ = QtGui.QAction( QtGui.QIcon( "ico/gtk-refresh.svg" ), u"&Mise à jour des plugins", self )
		self.actionMAJ.setIconVisibleInMenu( True )
		self.menuEdition.addAction( self.actionMAJ )
		
		# Action Edition -> Preferences
		self.actionPreferences = QtGui.QAction( QtGui.QIcon( "ico/gtk-preferences.svg" ), u"&Préférences", self )
		self.actionPreferences.setIconVisibleInMenu( True )
		self.menuEdition.addAction( self.actionPreferences )
		
		# Menu Aide
		self.menuAide = QtGui.QMenu( "&Aide", self.menubar )
		self.menubar.addAction( self.menuAide.menuAction() )
		
		# Action Aide -> A propos
		self.actionAPropos = QtGui.QAction( QtGui.QIcon( "ico/gtk-about.svg" ), u"À p&ropos", self )
		self.actionAPropos.setIconVisibleInMenu( True )
		self.menuAide.addAction( self.actionAPropos )
		
		# Ajout du menu a l'interface
		self.setMenuBar( self.menubar )

		###
		# Signaux provenants de l'interface
		###

		QtCore.QObject.connect( self.tableWidgetFichier,
								QtCore.SIGNAL( "cellClicked(int,int)" ),
								self.afficherInformationsFichier )	
		
		QtCore.QObject.connect( self.tableWidgetFichier,
								QtCore.SIGNAL( "cellDoubleClicked(int,int)" ),
								self.gererTelechargement )	
								
		QtCore.QObject.connect( self.pushButtonToutAjouter,
								QtCore.SIGNAL( "clicked()" ),
								self.ajouterTousLesFichiers )								

		QtCore.QObject.connect( self.pushButtonRafraichirPlugin,
								QtCore.SIGNAL( "clicked()" ),
								self.rafraichirPlugin )

		QtCore.QObject.connect( self.tableWidgetTelechargement,
								QtCore.SIGNAL( "cellDoubleClicked(int,int)" ),
								self.supprimerTelechargement )	
		
		QtCore.QObject.connect( self.pushButtonExtremiteMonter,
								QtCore.SIGNAL( "clicked()" ),
								lambda versLeHaut = True, extremite = True : self.tableWidgetTelechargement.deplacerLigne( versLeHaut, extremite ) )
		
		QtCore.QObject.connect( self.pushButtonMonter,
								QtCore.SIGNAL( "clicked()" ),
								lambda versLeHaut = True, extremite = False : self.tableWidgetTelechargement.deplacerLigne( versLeHaut, extremite ) )
		
		QtCore.QObject.connect( self.pushButtonDescendre,
								QtCore.SIGNAL( "clicked()" ),
								lambda versLeHaut = False, extremite = False : self.tableWidgetTelechargement.deplacerLigne( versLeHaut, extremite ) )
		
		QtCore.QObject.connect( self.pushButtonExtremiteDescendre,
								QtCore.SIGNAL( "clicked()" ),
								lambda versLeHaut = False, extremite = True : self.tableWidgetTelechargement.deplacerLigne( versLeHaut, extremite ) )
		
		QtCore.QObject.connect( self.pushButtonToutSupprimer,
								QtCore.SIGNAL( "clicked()" ),
								self.supprimerTousLesTelechargements )
		
		QtCore.QObject.connect( self.pushButtonNettoyer,
								QtCore.SIGNAL( "clicked()" ),
								self.nettoyer )
		
		QtCore.QObject.connect( self.pushButtonLancer,
								QtCore.SIGNAL( "clicked()" ),
								self.lancerTelechargement )

		QtCore.QObject.connect( self.pushButtonStop,
								QtCore.SIGNAL( "clicked()" ),
								self.stopperTelechargement )
		
		QtCore.QObject.connect( self.actionQuitter,
								QtCore.SIGNAL( "triggered()" ),
								self.close )						
	
		################################################
		# Instanciations + initialisation de variables #
		################################################
		
		# Fenetre About
		self.aProposDialog = None
		# Fenetre des preferences du logiciel
		self.preferencesDialog = None
		# Fenetre de mise a jour des plugins
		self.updateManagerDialog = None
		# Nom plugin courant
		self.nomPluginCourant = ""
		# Liste des fichiers
		self.listeFichiers = []
		# Liste des fichiers a telecharger
		self.listeFichiersATelecharger = []
		# Cache des images descriptive
		# Clef : urlImage Valeur : image (binaire)
		self.cacheImage = {}
		
		# On intancie le lanceur de signaux
		self.signaux = Signaux()
		# On instancie le gestionnaire de preferences
		self.preferences = Preferences()
		# On instancie le gestionnaire de preferences des plugins
		self.preferencesPluginDialog = PreferencePluginDialog( self )
		# On instancie le gestionnaire de download
		self.downloader = Downloader( self.signaux )	
		# On recupere l'instance de API
		self.api = API.getInstance()
		# On instancie le gestionnaire d'historique
		self.historique = Historique()
		# On instancie la fenetre d'attente
		self.fenetreAttenteProgressDialog = FenetreAttenteProgressDialog( self )
		# On instancie le gest								 
		
		#
		# Fenetre de confirmation pour quitter le logiciel
		#
		self.quitterMessageBox = QtGui.QMessageBox( self )
		self.quitterMessageBox.setWindowTitle( "Fermeture de TVDownloader" )
		self.quitterMessageBox.setText( u"Voulez-vous réellement quitter TVDownloader ?" )
		self.quitterMessageBox.setInformativeText( u"Votre liste de téléchargement sera perdue" )
		self.quitterMessageBox.addButton( "Oui", QtGui.QMessageBox.AcceptRole )
		self.quitterMessageBox.addButton( "Non", QtGui.QMessageBox.RejectRole )
		
		############################################################
		# On connecte les signaux des instances precedements crees #
		############################################################	

		QtCore.QObject.connect( self.pushButtonOuvrirDossierTelechargement,
								QtCore.SIGNAL( "clicked()" ),
								self.ouvrirRepertoireTelechargement )
		
		QtCore.QObject.connect( self.comboBoxSite,
								QtCore.SIGNAL( "activated(QString)" ),
								self.listerChaines )
		
		QtCore.QObject.connect( self.comboBoxChaine,
								QtCore.SIGNAL( "activated(QString)" ),
								self.listerEmissions )
		
		QtCore.QObject.connect( self.comboBoxEmission,
								QtCore.SIGNAL( "activated(QString)" ),
								self.listerFichiers )

		QtCore.QObject.connect( self.pushButtonPreferencesPlugin,
								QtCore.SIGNAL( "clicked()" ),
								self.ouvrirPreferencesPlugin )

		QtCore.QObject.connect( self.actionPreferences,
								QtCore.SIGNAL( "triggered()" ),
								self.ouvrirPreferencesLogiciel )	
								
		QtCore.QObject.connect( self.actionMAJ,
								QtCore.SIGNAL( "triggered()" ),
								self.ouvrirFenetreMiseAJour )	

		QtCore.QObject.connect( self.actionAPropos,
								QtCore.SIGNAL( "triggered()" ),
								self.ouvrirFenetreAPropos )
		
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "debutActualisation(PyQt_PyObject)" ) , self.fenetreAttenteProgressDialog.ouvrirFenetreAttente )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "finActualisation()" ) , self.fenetreAttenteProgressDialog.fermerFenetreAttente )		
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "actualiserListesDeroulantes()" ) , self.actualiserListesDeroulantes )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "listeChaines(PyQt_PyObject)" ) , self.ajouterChaines )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "listeEmissions(PyQt_PyObject)" ) , self.ajouterEmissions )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "listeFichiers(PyQt_PyObject)" ) , self.ajouterFichiers )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "nouvelleImage(PyQt_PyObject)" ) , self.mettreEnPlaceImage )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "debutTelechargement(int)" ) , self.debutTelechargement )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "finTelechargement(int)" ) , self.finTelechargement )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "finDesTelechargements()" ) , self.activerDesactiverInterface )
		QtCore.QObject.connect( self.signaux, QtCore.SIGNAL( "pourcentageFichier(int)" ) , self.progressBarTelechargementFichier.setValue )		

		#########
		# Début #
		#########			
		
		# La fenetre prend la dimension qu'elle avait a sa fermeture
		taille = self.preferences.getPreference( "tailleFenetre" )
		self.resize( taille[ 0 ], taille[ 1 ] )
		
		# Si aucun plugin n'est active, on ouvre la fenetre des preferences
		if( len( self.preferences.getPreference( "pluginsActifs" ) ) == 0 ):
			self.ouvrirPreferencesLogiciel()
		
		# On actualise tous les plugins
		self.rafraichirTousLesPlugins()
コード例 #24
0
 def testSingleton(self):
     """Test si le pattern singleton est bien en place"""
     self.assertEqual(id(self.historique), id(Historique()))
コード例 #25
0
ファイル: PluzzDL.py プロジェクト: BantouTV/Pluzzdl
	def __init__( self, url, useFragments = False, proxy = None, resume = False, progressFnct = lambda x : None, stopDownloadEvent = threading.Event(), outDir = ".", manifest = False, playlist = False ):
		self.url               = url
		self.useFragments      = useFragments
		self.proxy             = proxy
		self.resume            = resume
		self.progressFnct      = progressFnct
		self.stopDownloadEvent = stopDownloadEvent
		self.outDir            = outDir
		self.navigateur        = Navigateur( self.proxy )
		self.historique        = Historique()
		self.configuration     = Configuration()
		self.lienMMS           = None
		self.lienRTMP          = None
		self.manifestURL       = None
		self.drm               = None
		if playlist:
			self.mode = "playlist"
			self.ext  = "ts"
		else:
			self.mode = "manifest"
			self.ext  = "flv"

		self.hmacKey           = self.configuration[ "hmac_key" ].decode( "hex" )
		self.playerHash        = self.configuration[ "player_hash" ]

		if( re.match( "http://www.pluzz.fr/[^\.]+?\.html", self.url ) ):
			# Recupere l'ID de l'emission
			self.getID()
			# Recupere la page d'infos de l'emission
			self.pageInfos = self.navigateur.getFichier( "http://www.pluzz.fr/appftv/webservices/video/getInfosOeuvre.php?mode=zeri&id-diffusion=%s" %( self.id ) )
			# Parse la page d'infos
			self.parseInfos()
			# Petit message en cas de DRM
			if( self.drm == "oui" ):
				logger.warning( "La vidéo posséde un DRM ; elle sera sans doute illisible" )
			# Lien MMS trouve
			if( self.lienMMS is not None ):
				logger.info( "Lien MMS : %s\nUtiliser par exemple mimms ou msdl pour la recuperer directement ou l'option -f de pluzzdl pour essayer de la charger via ses fragments" %( self.lienMMS ) )
			# Lien RTMP trouve
			if( self.lienRTMP is not None ):
				logger.info( "Lien RTMP : %s\nUtiliser par exemple rtmpdump pour la recuperer directement ou l'option -f de pluzzdl pour essayer de la charger via ses fragments" %( self.lienRTMP ) )
			# N'utilise pas les fragments si cela n'a pas ete demande et que des liens directs ont ete trouves
			if( ( ( self.lienMMS is not None ) or ( self.lienRTMP is not None ) ) and not self.useFragments ):
				sys.exit( 0 )

			if self.mode == "manifest":
				# Lien du manifest non trouve
				if( self.manifestURL is None ):
					logger.critical( "Pas de lien vers le manifest" )
					sys.exit( -1 )

			if self.mode == "playlist":
				# Lien de la playlist M3U8 non trouve
				if( self.playlistM3U8 is None ):
					logger.critical( "Pas de lien vers la playlist" )
					sys.exit( -1 )

			self.nomFichier = os.path.join( self.outDir, "%s.%s" %( re.findall( "http://www.pluzz.fr/([^\.]+?)\.html", self.url )[ 0 ], self.ext ) )
		else:
			if self.mode == "manifest":
				page = self.navigateur.getFichier( self.url )
				try:
					self.manifestURL = re.findall( "(http://.+?manifest.f4m)", page )[ 0 ]
				except:
					logger.critical( "Pas de lien vers le manifest" )
					sys.exit( -1 )
				try:
					self.nomFichier = os.path.join( self.outDir, "%s.flv" %( self.url.split( "/" )[ -1 ] ) )
				except:
					self.nomFichier = os.path.join( self.outDir, "video.flv" )

		self.generateNomFichier()

		if self.mode == "manifest":
			self.getVideoViaManifest()

		if self.mode == "playlist":
			self.getVideoViaPlaylist()
コード例 #26
0
ファイル: DownloaderM3u8.py プロジェクト: pacomod/replaydlr
class DlM3u8(Downloader):
    """
    Téléchargement des liens m3u8
    """

    def __init__(self,
                 m3u8Url,
                 outDir,
                 codeProgramme,
                 timeStamp,
                 navigateur,
                 stopDownloadEvent,
                 progressFnct):
        self.m3u8Url = m3u8Url
        super(DlM3u8, self).__init__(outDir, codeProgramme, timeStamp, "ts",
                                     navigateur, stopDownloadEvent, progressFnct)
        self.historique = Historique()

    def telecharger(self):
        # Récupère le fichier master.m3u8
        self.m3u8 = self.navigateur.getFichier(self.m3u8Url)
        # Extrait l'URL de tous les fragments
        self.listeFragments = re.findall(".+?\.ts", self.m3u8)
        #
        # Création de la vidéo
        #
        self.premierFragment = 1
        self.telechargementFini = False
        video = self.historique.getVideo(self.m3u8Url)
        # Si la vidéo est dans l'historique
        if(video is not None):
            # Si la vidéo existe sur le disque
            if(os.path.exists(self.nomFichier)):
                if(video.finie):
                    logger.info("La vidéo a déjà été entièrement téléchargée")
                    return
                else:
                    self.ouvrirVideoExistante()
                    self.premierFragment = video.fragments
                    logger.info("Reprise du téléchargement de la vidéo au fragment %d" % (video.fragments))
            else:
                self.ouvrirNouvelleVideo()
                logger.info("Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % (self.nomFichier))
        else:  # Si la vidéo n'est pas dans l'historique
            self.ouvrirNouvelleVideo()
        # Nombre de fragments
        self.nbFragMax = float(len(self.listeFragments))
        logger.debug("Nombre de fragments: %d" % (self.nbFragMax))
        # Ajout des fragments
        logger.info("Début du téléchargement des fragments")
        try:
            i = self.premierFragment
            while(i <= self.nbFragMax and not self.stopDownloadEvent.isSet()):
                frag = self.navigateur.getFichier("%s" % (
                        self.listeFragments[i - 1]))
                self.fichierVideo.write(frag)
                # Affichage de la progression
                self.progressFnct(min(int((i / self.nbFragMax) * 100), 100))
                i += 1
            if(i == self.nbFragMax + 1):
                self.progressFnct(100)
                self.telechargementFini = True
                logger.info("Fin du téléchargement")
        except KeyboardInterrupt:
            logger.info("Interruption clavier")
        except Exception as inst:
            logger.critical("Erreur inconnue %s" % inst)
        finally:
            # Ajout dans l'historique
            self.historique.ajouter(Video(lien = self.m3u8Url, fragments = i,
                                          finie = self.telechargementFini))
            # Fermeture du fichier
            self.fichierVideo.close()
コード例 #27
0
ファイル: PluzzDL.py プロジェクト: gongzuoqu/dld-tv-rip
class PluzzDLM3U8(object):
    """
	Telechargement des liens m3u8
	"""

    def __init__(self, m3u8URL, nomFichier, navigateur, stopDownloadEvent, progressFnct):
        self.m3u8URL = m3u8URL
        self.nomFichier = nomFichier
        self.navigateur = navigateur
        self.stopDownloadEvent = stopDownloadEvent
        self.progressFnct = progressFnct

        self.historique = Historique()

        self.nomFichierFinal = "%s.mp4" % (self.nomFichier[:-3])

    def ouvrirNouvelleVideo(self):
        """
		Creer une nouvelle video
		"""
        try:
            # Ouverture du fichier
            print "Nom Fichier:", self.nomFichier
            #			fullPathFile = os.path.join(os.getcwd(), self.nomFichier)
            #			print "fullPathFile:", fullPathFile
            self.fichierVideo = open(self.nomFichier, "wb")
        #			self.fichierVideo = open( fullPathFile, "wb" )
        except:
            raise PluzzDLException("Impossible d'écrire dans le répertoire %s" % (os.getcwd()))
        # Ajout de l'en-tête
        #	Fait dans creerMKV

    def ouvrirVideoExistante(self):
        """
		Ouvre une video existante
		"""
        try:
            # Ouverture du fichier
            self.fichierVideo = open(self.nomFichier, "a+b")
        except:
            raise PluzzDLException("Impossible d'écrire dans le répertoire %s" % (os.getcwd()))

    def creerMKV(self):
        """
		Creer un mkv a partir de la video existante (cree l'en-tete de la video)
	"""
        logger.info("Création du fichier MKV (vidéo finale); veuillez attendre quelques instants")
        logger.info("Convert: %s -> %s" % (self.nomFichier, self.nomFichierFinal))
	commande = "ffmpeg -i %s -c:a aac -strict -2 -vcodec copy %s" % (self.nomFichier, self.nomFichierFinal)

       	try:
            if (os.system(commande) == 0):
                os.remove(self.nomFichier)
                logger.info("Fin !")
            else:
                logger.warning(
                    "Problème lors de la création du MKV avec FFmpeg ; le fichier %s est néanmoins disponible" % (
                    self.nomFichier))
        except:
            raise PluzzDLException("Impossible de créer la vidéo finale")


    def telecharger(self):
        # Recupere le fichier master.m3u8
        self.m3u8 = self.navigateur.getFichier(self.m3u8URL)
        # Extrait l'URL de tous les fragments
        self.listeFragments = re.findall(".+?\.ts", self.m3u8)
        if not self.listeFragments:
            self.listeFragments = []
            self.listeM3U8 = re.findall(".+?index_2_av\.m3u8", self.m3u8)
            for m3u8 in self.listeM3U8:
                m3u8data = self.navigateur.getFichier(m3u8)
                self.listeFragments.extend(re.findall(".+?\.ts", m3u8data))
        #
        # Creation de la video
        #
        self.premierFragment = 1
        self.telechargementFini = False
        video = self.historique.getVideo(self.m3u8URL)
        # Si la video est dans l'historique
        if (video is not None):
            # Si la video existe sur le disque
            if (os.path.exists(self.nomFichier) or os.path.exists(self.nomFichierFinal)):
                if (video.finie):
                    logger.info("La vidéo a déjà été entièrement téléchargée")
                    if (not os.path.exists(self.nomFichierFinal)):
                        self.creerMKV()
                    return
                else:
                    self.ouvrirVideoExistante()
                    self.premierFragment = video.fragments
                    logger.info("Reprise du téléchargement de la vidéo au fragment %d" % (video.fragments))
            else:
                self.ouvrirNouvelleVideo()
                logger.info(u"Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % (
                self.nomFichier))
        else:  # Si la video n'est pas dans l'historique
            self.ouvrirNouvelleVideo()
        # Nombre de fragments
        self.nbFragMax = float(len(self.listeFragments))
        logger.debug("Nombre de fragments : %d" % (self.nbFragMax))
        # Ajout des fragments
        logger.info("Début du téléchargement des fragments")
        try:
            i = self.premierFragment
            while (i <= self.nbFragMax and not self.stopDownloadEvent.isSet()):
                frag = self.navigateur.getFichier("%s" % (self.listeFragments[i - 1]))
                self.fichierVideo.write(frag)
                # Affichage de la progression
                self.progressFnct(min(int((i / self.nbFragMax) * 100), 100))
                i += 1
            if (i == self.nbFragMax + 1):
                self.progressFnct(100)
                self.telechargementFini = True
                logger.info("Fin du téléchargement")
                self.creerMKV()
        except KeyboardInterrupt:
            logger.info("Interruption clavier")
        except Exception as inst:
            logger.critical("Erreur inconnue %s" % inst)
        finally:
            # Ajout dans l'historique
            self.historique.ajouter(Video(lien=self.m3u8URL, fragments=i, finie=self.telechargementFini))
            # Fermeture du fichier
            self.fichierVideo.close()
コード例 #28
0
ファイル: PluzzDL.py プロジェクト: btuduri/tvdownloader
class PluzzDLM3U8( object ):
	"""
	Telechargement des liens m3u8
	"""

	def __init__( self, m3u8URL, nomFichier, navigateur, stopDownloadEvent, progressFnct ):
		self.m3u8URL = m3u8URL
		self.nomFichier = nomFichier
		self.navigateur = navigateur
		self.stopDownloadEvent = stopDownloadEvent
		self.progressFnct = progressFnct

		self.historique = Historique()

		self.nomFichierFinal = "%s.mkv" % ( self.nomFichier[ :-3 ] )

	def ouvrirNouvelleVideo( self ):
		"""
		Creer une nouvelle video
		"""
		try :
			# Ouverture du fichier
			self.fichierVideo = open( self.nomFichier, "wb" )
		except :
			raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) )
		# Ajout de l'en-tête
		# 	Fait dans creerMKV

	def ouvrirVideoExistante( self ):
		"""
		Ouvre une video existante
		"""
		try :
			# Ouverture du fichier
			self.fichierVideo = open( self.nomFichier, "a+b" )
		except :
			raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) )

	def creerMKV( self ):
		"""
		Creer un mkv a partir de la video existante (cree l'en-tete de la video)
		"""
		logger.info( "Création du fichier MKV (vidéo finale) ; veuillez attendre quelques instants" )
		try:
			if( os.name == "nt" ):
				commande = "ffmpeg.exe -i %s -vcodec copy -acodec copy %s 1>NUL 2>NUL" % ( self.nomFichier, self.nomFichierFinal )
			else:
				commande = "ffmpeg -i %s -vcodec copy -acodec copy %s 1>/dev/null 2>/dev/null" % ( self.nomFichier, self.nomFichierFinal )
			if( os.system( commande ) == 0 ):
				os.remove( self.nomFichier )
				logger.info( "Fin !" )
			else:
				logger.warning( "Problème lors de la création du MKV avec FFmpeg ; le fichier %s est néanmoins disponible" % ( self.nomFichier ) )
		except:
			raise PluzzDLException( "Impossible de créer la vidéo finale" )

	def telecharger( self ):
		# Recupere le fichier master.m3u8
		self.m3u8 = self.navigateur.getFichier( self.m3u8URL )
		# Extrait l'URL de base pour tous les fragments
		self.urlBase = "/".join( self.m3u8URL.split( "/" )[ :-1 ] )
		# Recupere le lien avec le plus gros bitrate
		try:
			self.listeFragmentsURL = "%s/%s" % ( self.urlBase, re.findall( ".+?\.m3u8.*", self.m3u8 )[ -1 ] )
		except:
			raise PluzzDLException( "Impossible de trouver le lien vers la liste des fragments" )
		# Recupere la liste des fragments
		self.listeFragmentsPage = self.navigateur.getFichier( self.listeFragmentsURL )
		# Extrait l'URL de tous les fragments
		self.listeFragments = re.findall( ".+?\.ts", self.listeFragmentsPage )
		#
		# Creation de la video
		#
		self.premierFragment = 1
		self.telechargementFini = False
		video = self.historique.getVideo( self.listeFragmentsURL )
		# Si la video est dans l'historique
		if( video is not None ):
			# Si la video existe sur le disque
			if( os.path.exists( self.nomFichier ) or os.path.exists( self.nomFichierFinal ) ):
				if( video.finie ):
					logger.info( "La vidéo a déjà été entièrement téléchargée" )
					if( not os.path.exists( self.nomFichierFinal ) ):
						self.creerMKV()
					return
				else:
					self.ouvrirVideoExistante()
					self.premierFragment = video.fragments
					logger.info( "Reprise du téléchargement de la vidéo au fragment %d" % ( video.fragments ) )
			else:
				self.ouvrirNouvelleVideo()
				logger.info( u"Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % ( self.nomFichier ) )
		else:  # Si la video n'est pas dans l'historique
			self.ouvrirNouvelleVideo()
		# Nombre de fragments
		self.nbFragMax = float( len( self.listeFragments ) )
		logger.debug( "Nombre de fragments : %d" % ( self.nbFragMax ) )
		# Ajout des fragments
		logger.info( "Début du téléchargement des fragments" )
		try :
			i = self.premierFragment
			while( i <= self.nbFragMax and not self.stopDownloadEvent.isSet() ):
				frag = self.navigateur.getFichier( "%s/%s" % ( self.urlBase, self.listeFragments[ i - 1 ] ) )
				self.fichierVideo.write( frag )
				# Affichage de la progression
				self.progressFnct( min( int( ( i / self.nbFragMax ) * 100 ), 100 ) )
				i += 1
			if( i == self.nbFragMax + 1 ):
				self.progressFnct( 100 )
				self.telechargementFini = True
				logger.info( "Fin du téléchargement" )
				self.creerMKV()
		except KeyboardInterrupt:
			logger.info( "Interruption clavier" )
		except:
			logger.critical( "Erreur inconnue" )
		finally :
			# Ajout dans l'historique
			self.historique.ajouter( Video( lien = self.listeFragmentsURL, fragments = i, finie = self.telechargementFini ) )
			# Fermeture du fichier
			self.fichierVideo.close()