Outils pour utilisateurs

Outils du site


pyqt4_navigateur_web

En construction!

#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import division
#Python 2.7
 
__logiciel__ = u"navigweb"
__version__ = u"1.0.0"
__date__ = u"8/10/2012"
 
import os, sys
from functools import partial
 
from PyQt4 import QtCore, QtGui, QtNetwork, QtWebKit
from apropos import Apropos
 
#############################################################################
class Navigateurweb(QtGui.QMainWindow):
    """navigateur web: affichage des pages web et des fichiers html disque"""
 
    # =======================================================================
    def __init__(self, url=None, repdefaut=u"", imprimepdf=None, parent=None):
        """initialisation du navigateur"""
        super(Navigateurweb, self).__init__(parent)
 
        # met le titre de la fenêtre
        self.setWindowTitle(u"Navigateur web")
        # affiche l'icone de la fenêtre s'il n'y en pas déjà une par défaut
        if self.windowIcon().isNull():
            # mettre ici l'icone si elle n'est pas donnée par l'appelant
            #self.setWindowIcon(QtGui.QIcon(u"navigweb.png"))
            pass
        # stocke la page 'home' en la corrigeant si nécessaire
        self.urlblank = QtCore.QUrl(u"about:blank")
        if url==None:
            self.urlhome = self.urlblank
        else:
            self.urlhome = self.corrigeurl(url)
 
        # fichier pdf dans lequel l'impression demandée se fera
        if imprimepdf==None:
            home = os.path.expanduser("~").decode('latin1')
            fichier = u"imprimer_3FBH2XO1P8.pdf"
            self.imprimepdf = os.path.join(home, fichier)
        else:
            self.imprimepdf = os.path.abspath(os.path.expanduser(imprimepdf))
 
        # répertoire par défaut dans lequel on va chercher les fichiers html
        self.repdefaut = os.path.abspath(os.path.expanduser(repdefaut))
 
 
        # fabrique le menu principal de la fenêtre
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('Fichier')
 
        ouvrirAction = QtGui.QAction('&Ouvrir', self)
        ouvrirAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_O)
        ouvrirAction.setStatusTip(u"Ouvrir un fichier html")
        ouvrirAction.triggered.connect(self.ouvrir_m)
        fileMenu.addAction(ouvrirAction)
 
        imprimerAction = QtGui.QAction('&Imprimer', self)
        imprimerAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_I)
        imprimerAction.setStatusTip(u"Imprimer dans un fichier pdf")
        imprimerAction.triggered.connect(self.imprimer_m)
        fileMenu.addAction(imprimerAction)
 
        fileMenu.addSeparator()
 
        quitterAction = QtGui.QAction('&Quitter', self)        
        quitterAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Q)        
        quitterAction.setStatusTip(u"Quitter le programme")
        quitterAction.triggered.connect(lambda : self.close())
        fileMenu.addAction(quitterAction)
 
        aideMenu = menubar.addMenu('Aide')
 
        aproposAction = QtGui.QAction('&A propos', self)        
        aproposAction.setStatusTip(u"A propos du programme")
        aproposAction.triggered.connect(self.apropos_m)
        aideMenu.addAction(aproposAction)
 
        # crée le QWebView pour affichage des pages html
        self.vuehtml = QtWebKit.QWebView()
 
        # configure viewhtml (interdire 'JavaEnabled' => plante le programme!))
        reglage = self.vuehtml.settings() 
        # activer javascript
        reglage.setAttribute(QtWebKit.QWebSettings.JavascriptEnabled, True)
        reglage.setAttribute(QtWebKit.QWebSettings.JavascriptCanOpenWindows, True)
        reglage.setAttribute(QtWebKit.QWebSettings.JavascriptCanAccessClipboard, True)
 
        # activer les plugins
        reglage.setAttribute(QtWebKit.QWebSettings.PluginsEnabled, True)
 
        # fait que les couleurs et motifs de fond de page ne seront pas imprimés
        reglage.setAttribute(QtWebKit.QWebSettings.PrintElementBackgrounds, False)
 
        # connecte les évènements du QWebView avec les méthodes
        self.vuehtml.loadProgress.connect(self.loadProgress_m)
        self.vuehtml.loadFinished.connect(self.loadFinished_m)
        self.vuehtml.linkClicked.connect(self.linkClicked_m)
        self.vuehtml.urlChanged.connect(self.urlChanged_m)
 
        # crée la ligne de saisie des adresses des pages html (web ou disque)
        self.adresse = QtGui.QLineEdit()
        self.adresse.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                   self.adresse.sizePolicy().verticalPolicy())
        self.adresse.returnPressed.connect(self.returnPressed_m)
 
        # initialise la barre d'outils (pré-existe dans le QMainWindoww)
        self.toolBar = self.addToolBar("Navigation")
        self.toolBar.addAction(self.vuehtml.pageAction(QtWebKit.QWebPage.Back))
        self.toolBar.addAction(self.vuehtml.pageAction(QtWebKit.QWebPage.Forward))
        self.toolBar.addAction(self.vuehtml.pageAction(QtWebKit.QWebPage.Reload))
        self.toolBar.addAction(self.vuehtml.pageAction(QtWebKit.QWebPage.Stop))
        self.toolBar.addWidget(self.adresse)
 
        # initialisation de la barre de status (affiche le nom de page html)
        self.statusBar().showMessage(u'')
 
        # positionne le QWebView dans la partie centrale de la fenêtre
        self.setCentralWidget(QtGui.QFrame())
        posit = QtGui.QGridLayout()
        posit.addWidget(self.vuehtml, 0, 0)
        self.centralWidget().setLayout(posit)
 
        # permet les liens hypertexte
        self.vuehtml.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks)
 
        # met en place un nouveau menu popup du QWebView
        self.vuehtml.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.vuehtml.customContextMenuRequested.connect(self.popupmenuvuehtml)        
 
        # met en place un nouveau menu popup pour la barre d'outils
        self.toolBar.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.toolBar.customContextMenuRequested.connect(self.popupmenutoolbar)        
 
        # active la capacité de charger des pages https://
        # certif: https://certs.starfieldtech.com/anonymous/repository.seam
        config = QtNetwork.QSslConfiguration.defaultConfiguration()
        certs=config.caCertificates()
        certs.append(QtNetwork.QSslCertificate(QtCore.QFile("starfieldcert")))
        config.setCaCertificates(certs)
 
        # charge la page demandée au lancement
        self.adresse.setText(self.urlhome.toString())
        self.returnPressed_m()
 
        # met le focus sur la page affichée
        self.vuehtml.setFocus()
 
    # =======================================================================
    def ouvrir_m(self):
        """Sélectionner et charger un fichier html du disque"""
 
        fichier = QtGui.QFileDialog.getOpenFileName(self, 
                     u"Sélectionnez le fichier html", 
                     self.repdefaut, 
                     u"Fichier html (*.html;*.htm);;Tous (*.*)")
        fichier = unicode(fichier)
 
        if fichier==u"":
            return
 
        # charge la page demandée au lancement
        self.adresse.setText(fichier)
        self.returnPressed_m()
 
    # =======================================================================
    def bidon(self):
        pass
 
    # =======================================================================
    def popupmenutoolbar(self, position):
        """menu popup de la barre d'outils: remplace celui d'origine"""
 
        # récupération de la liste des pages de l'historique
        history = self.vuehtml.page().history()
        hitems = []
        for hitem in history.items():
            hitems.append(hitem)
        ihitem =  history.currentItemIndex()
        i1 = max(ihitem-10, 0)
        i2 = min(ihitem+10, len(hitems)-1)
 
        # création de l'objet "menu popup"
        popupmenu = QtGui.QMenu(self.toolBar)
 
        # retour à la page 'home'
        actionHome = popupmenu.addAction(u"Retour à la page Home")
        actionHome.triggered.connect(self.home_m)
 
        # ajout d'un séparateur des items du menu
        popupmenu.addSeparator()
 
        # création des items à ajouter au menu
        actions = []
        for i in xrange(i1, i2+1):
            hitem = hitems[i]
            url = unicode(hitem.url().toString())
            if len(url)>70:
                # l'adresse est trop longue: on ne prend que le début et la fin
                url = url[:33] + u"...." + url[-33:]
 
            # créaction d'une action
            act = QtGui.QAction(url, self)
            # mettre en gras l'adresse de la page déjà affichée
            if i==ihitem: 
                police = act.font()
                police.setBold(True)
                act.setFont(police)
            # connecter l'item avec la méthode à exécuter
            act.triggered.connect(partial(self.allera, hitem))
 
            # on ajoute l'action au menu
            action = popupmenu.addAction(act)
            actions.append(action)
 
        # exécution du menu popup
        popupmenu.exec_(self.toolBar.mapToGlobal(position))
 
    # =======================================================================
    def allera(self, hitem):
        """affiche la page 'hitem' de l'historique"""
        self.vuehtml.page().history().goToItem(hitem)
 
    # =======================================================================
    def popupmenuvuehtml(self, position):
        """menu popup spécifique au QWebView: remplace celui d'origine"""
 
        # crée l'objet "menu popup"
        popupmenu = QtGui.QMenu(self.vuehtml)
 
        # fait un "zoom plus" avec Alt-P
        actionZPlus = popupmenu.addAction(u"Zoom &Plus")
        actionZPlus.setShortcut(QtGui.QKeySequence(QtCore.Qt.AltModifier | QtCore.Qt.Key_P))
        actionZPlus.triggered.connect(partial(self.zoom, +0.1))
 
        # fait un "zoom moins" avec Alt-M
        actionZMoins = popupmenu.addAction(u"Zoom &Moins")
        actionZMoins.setShortcut(QtGui.QKeySequence(QtCore.Qt.AltModifier | QtCore.Qt.Key_M))
        actionZMoins.triggered.connect(partial(self.zoom, -0.1))
 
        # ajout d'un séparateur des items du menu
        popupmenu.addSeparator()
 
        # lance et affiche une impression en pdf avec Alt-I
        actionZMoins = popupmenu.addAction(u"&Imprimer")
        actionZMoins.setShortcut(QtGui.QKeySequence(QtCore.Qt.AltModifier | QtCore.Qt.Key_I))
        actionZMoins.triggered.connect(self.imprimer_m)
 
        # exécute le menu popup
        popupmenu.exec_(self.vuehtml.mapToGlobal(position))
 
    # =======================================================================
    def corrigeurl(self, url):
        """corrige l'adresse url (unicode) pour obtenir une adresse viable
           si adresse disque: l'adresse doit être absolue
           si adresse web: l'adresse peut être incomplète
        """
        # comme "ftp:" ne marche pas => remplacer par "http:"
        if url[:4]==u"ftp:":
            url = u"http:" + url[4:]
 
        if os.path.exists(url):
            # cas d'un fichier disque html:  met "file://" si nécessaire
            return QtCore.QUrl.fromLocalFile(url)
 
        # cas d'une adresse web:  met "http://" si nécessaire
        return QtCore.QUrl.fromUserInput(url)
 
    # =======================================================================
    def home_m(self):
        """affiche la page 'home' comme nouvelle page html"""
        self.vuehtml.setUrl(self.urlhome) #load(self.urlhome)
        self.vuehtml.setFocus()
 
    # =======================================================================
    def returnPressed_m(self):
        """affiche la page correspondant à la ligne d'adresse"""
 
        # compléte si nécessaire l'url de la ligne d'adresse
        url = unicode(self.adresse.text()).strip()
        if url==u"":
            url = self.urlblank # => "about:blank"
        else:
            url = self.corrigeurl(url)
 
        # affiche la page html demandée
        self.vuehtml.setUrl(url) #load(url)
        self.vuehtml.setFocus()
 
    # =======================================================================
    def loadProgress_m(self, progression):
        """progression du chargement: affiche le nom de page dans la fenêtre"""
        nompage = self.vuehtml.title()
        msg = "%s (%s %%)" % (nompage, progression)
        #self.setWindowTitle("%s (%s %%)" % (nompage, progression))
        self.statusBar().showMessage(msg)
 
    # =======================================================================
    def loadFinished_m(self, ok):
        """fin de chargement: affiche le nom de page dans la fenêtre"""
        nompage = self.vuehtml.title()
        if not ok:
           nompage = nompage + u" (erreur page)" 
        #self.setWindowTitle(nompage)
        self.statusBar().showMessage(nompage)    
 
    # =======================================================================
    def linkClicked_m(self, url):
        """charge la page correspondant à l'url du lien hypertexte cliqué"""
        self.vuehtml.setUrl(url) #load(url)
        self.vuehtml.setFocus()
 
    # =======================================================================
    def urlChanged_m(self, url):
        """met à jour la ligne d'addresse à chaque changement d'url"""
        self.adresse.setText(url.toString())
 
    #========================================================================
    def imprimer_m(self):
        """Imprimer le contenu de la page affichée"""
 
        # créer et configurer l'objet printer pour imprimer
        printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
        dest = self.imprimepdf
        printer.setOutputFileName(dest)
        printer.setOutputFormat(QtGui.QPrinter.PdfFormat)
        printer.setCreator(u"aidehtml.py")
        printer.setDocName(u"aidehtml")
        printer.setPageSize(QtGui.QPrinter.A4)
        printer.setOrientation(QtGui.QPrinter.Portrait) #QtGui.QPrinter.Landscape
        #ordre des valeurs float des marges: left, top, right, bottom
        printer.setPageMargins(20.0, 10.0, 10.0, 10.0, QtGui.QPrinter.Millimeter)
        #printer.setFullPage(True) # NB: neutralise les marges!
        printer.setColorMode(QtGui.QPrinter.Color)
 
        # imprimer la page affichée
        self.vuehtml.print_(printer)
 
        # afficher le fichier pdf avec le visualiseur pdf par défaut
        if os.path.exists(dest):
            try:
                # solution pour Windows
                os.startfile(dest)
            except:
                # solution pour les Linux récents
                os.system('xdg-open ' + dest)
 
    # =======================================================================
    def zoom(self, increment):
        """applique un zoom + ou - selon l'incrément passé en argument"""
        current = self.vuehtml.textSizeMultiplier()
        self.vuehtml.setTextSizeMultiplier(current + increment)
 
    # =======================================================================
    def keyPressEvent(self, event):
        """raccourcis clavier: zoom+ =Alt-P, zoom- =Alt-M, impression =Alt-I"""
        if self.vuehtml.hasFocus():
            # avec Alt-P => zoom+
            if event.key() == QtCore.Qt.Key_P and \
                                   (event.modifiers() & QtCore.Qt.AltModifier):
                self.zoom(0.1)
                event.accept()
            # avec Alt-M => zoom-
            elif event.key() == QtCore.Qt.Key_M and \
                                   (event.modifiers() & QtCore.Qt.AltModifier):
                self.zoom(-0.1)
                event.accept()
            # avec Alt-I => Imprime la page affichée
            elif event.key() == QtCore.Qt.Key_I and \
                                   (event.modifiers() & QtCore.Qt.AltModifier):
                self.imprimer_m()
                event.accept()
            else:
                event.ignore()
        else:
            event.ignore()
 
    #========================================================================
    @QtCore.pyqtSlot()
    def apropos_m(self):
        """Fenêtre 'à propos' """
        pass
 
#############################################################################
if __name__ == '__main__':
    # code non exécuté si appel en tant que module
 
    app = QtGui.QApplication(sys.argv)
 
    if len(sys.argv) > 1:
        url = sys.argv[1]
    else:
        url = None
 
    url = "http://www.google.fr"
 
    fen = Navigateurweb(url)
    fen.show()
    sys.exit(app.exec_())
pyqt4_navigateur_web.txt · Dernière modification: 2013/09/13 10:55 de tyrtamos

Outils de la page