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_())