Attachment 'augmented.py'

Download

   1 #!/usr/bin/env python
   2 
   3 """
   4 augmented.py - Demonstrates how to call WebKit's JavaScript objects from Python
   5                and call Python objects from JavaScript.
   6 
   7 This file is part of the PyQt for Desktop and Embedded Devices package.
   8 
   9 Copyright (C) 2009 David Boddie <david.boddie@nokia.com>
  10 Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
  11 All rights reserved.
  12 
  13 Contact: Nokia Corporation (qt-info@nokia.com)
  14 
  15 You may use this file under the terms of the BSD license as follows:
  16 
  17 "Redistribution and use in source and binary forms, with or without
  18  modification, are permitted provided that the following conditions are met:
  19 
  20  * Redistributions of source code must retain the above copyright notice, this
  21    list of conditions and the following disclaimer.
  22  * Redistributions in binary form must reproduce the above copyright notice,
  23    this list of conditions and the following disclaimer in the documentation
  24    and/or other materials provided with the distribution.
  25  * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the names
  26    of its contributors may be used to endorse or promote products derived from
  27    this software without specific prior written permission.
  28 
  29  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  30  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  32  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  33  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  35  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  36  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  37  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  38  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  39 """
  40 
  41 import sys
  42 from PyQt4.QtCore import *
  43 from PyQt4.QtGui import *
  44 from PyQt4.QtWebKit import *
  45 
  46 
  47 js = \
  48 """findAnchors = function()
  49 {
  50     findAnchorsInNode(document, 0);
  51 }
  52 
  53 findAnchorsInNode = function(parent)
  54 {
  55     var children = parent.childNodes;
  56     
  57     for (var i = 0; i < children.length; i++) {
  58         var child = children[i];
  59         if (child.nodeName == "A") {
  60             if (child.hasAttributes()) {
  61                 var attributes = child.attributes;
  62                 for (var j = 0; j < attributes.length; j++) {
  63                     if (attributes[j].nodeName == "name") {
  64                         var following = findFollowing(child);
  65                         anchorList.addHeading(following.nodeName, attributes[j].nodeValue, getAnchorText(following));
  66                     }
  67                 }
  68             }
  69         } else if (child.hasChildNodes()) {
  70             findAnchorsInNode(child);
  71         }
  72     }
  73 }
  74 
  75 findFollowing = function(anchor)
  76 {
  77     var next = anchor.nextSibling;
  78     while (next && next.nodeType != Node.ELEMENT_NODE)
  79         next = next.nextSibling;
  80     
  81     return next;
  82 }
  83 
  84 getAnchorText = function(parent)
  85 {
  86     var children = parent.childNodes;
  87     var text = "";
  88     
  89     for (var i = 0; i < children.length; i++) {
  90         var child = children[i];
  91         if (child.nodeType == Node.TEXT_NODE)
  92             text = text + child.nodeValue;
  93         else if (child.hasChildNodes())
  94             text = text + findAnchorText(child);
  95     }
  96     
  97     return text;
  98 }
  99 """
 100 
 101 class Browser(QMainWindow):
 102 
 103     default_url = QUrl("http://doc.qt.nokia.com/4.5/qt4-5-intro.html")
 104     
 105     def __init__(self, parent = None):
 106     
 107         QMainWindow.__init__(self, parent)
 108         
 109         fileMenu = QMenu(self.tr("&File"), self)
 110         newAction = fileMenu.addAction(self.tr("&New Document"))
 111         newAction.setShortcut(QKeySequence(QKeySequence.New))
 112         self.connect(newAction, SIGNAL("triggered()"), self.newDocument)
 113         exitAction = fileMenu.addAction(self.tr("E&xit"))
 114         exitAction.setShortcut(QKeySequence(self.tr("Ctrl+Q")))
 115         self.connect(exitAction, SIGNAL("triggered()"), self.close)
 116         self.menuBar().addMenu(fileMenu)
 117         
 118         toolbar = QToolBar(self.tr("Document"), self)
 119         self.documentCombo = QComboBox()
 120         self.documentCombo.currentIndexChanged.connect(self.openDocument)
 121         self.addressEdit = QLineEdit()
 122         self.addressEdit.returnPressed.connect(self.openUrl)
 123         toolbar.addWidget(QLabel(self.tr("Document:")))
 124         toolbar.addWidget(self.documentCombo)
 125         toolbar.addWidget(QLabel(self.tr("Address:")))
 126         toolbar.addWidget(self.addressEdit)
 127         self.addToolBar(toolbar)
 128         
 129         headingsDockWindow = QDockWidget(self.tr("Headings"), self)
 130         headingsDockWindow.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
 131         self.headingsList = QTreeView()
 132         self.headingsList.setHeaderHidden(True)
 133         self.headingsModel = QStandardItemModel()
 134         self.headingsList.setModel(self.headingsModel)
 135         headingsDockWindow.setWidget(self.headingsList)
 136         self.addDockWidget(Qt.LeftDockWidgetArea, headingsDockWindow)
 137         
 138         self.headingsList.clicked.connect(self.goToAnchor)
 139         
 140         self.stackedWidget = QStackedWidget()
 141         self.setCentralWidget(self.stackedWidget)
 142         self.newDocument()
 143     
 144     def newDocument(self, url = default_url):
 145     
 146         self.documentCombo.addItem(url.toString())
 147         webview = QWebView()
 148         webview.setUrl(url)
 149         webview.titleChanged.connect(self.updateDocumentTitle)
 150         webview.loadFinished.connect(self.prepareJavaScript)
 151         
 152         index = self.stackedWidget.addWidget(webview)
 153         self.documentCombo.setCurrentIndex(index)
 154         self.updateAddress()
 155     
 156     def updateAddress(self):
 157     
 158         url = self.stackedWidget.currentWidget().url()
 159         self.addressEdit.setText(url.toString())
 160     
 161     def openDocument(self, index):
 162     
 163         self.stackedWidget.setCurrentIndex(index)
 164         widget = self.stackedWidget.currentWidget()
 165         if widget:
 166             self.updateAddress()
 167             self.listHeadings(widget)
 168     
 169     def openUrl(self):
 170     
 171         text = self.addressEdit.text()
 172         self.stackedWidget.currentWidget().setUrl(QUrl(text))
 173     
 174     def updateDocumentTitle(self, title):
 175     
 176         index = self.stackedWidget.indexOf(self.sender())
 177         self.documentCombo.setItemText(index, title)
 178         self.updateAddress()
 179     
 180     def prepareJavaScript(self, success):
 181     
 182         if not success:
 183             return
 184         
 185         if self.sender() != self.stackedWidget.currentWidget():
 186             return
 187         
 188         webview = self.sender()
 189         webview.page().mainFrame().addToJavaScriptWindowObject("anchorList", self)
 190         webview.page().mainFrame().evaluateJavaScript(js)
 191         self.listHeadings(webview)
 192     
 193     def listHeadings(self, webview):
 194     
 195         self.headingsModel.clear()
 196         webview.page().mainFrame().evaluateJavaScript("findAnchors();")
 197     
 198     @pyqtSignature("addHeading(QString, QString, QString)")
 199     def addHeading(self, nodeName, name, title):
 200     
 201         if str(nodeName) not in ("H1", "H2", "H3", "H4", "H5", "H6"):
 202             return
 203         
 204         webview = self.stackedWidget.currentWidget()
 205         url = webview.page().mainFrame().url()
 206         url.setFragment(name)
 207         
 208         level = int(str(nodeName)[1])
 209         newItem = QStandardItem(title)
 210         newItem.setData(QVariant(url), Qt.UserRole)
 211         newItem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
 212         
 213         parent = self.headingsModel
 214         i = 1
 215         while i < level:
 216             if parent.rowCount() == 0:
 217                 item = QStandardItem("[%i]" % i)
 218                 item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
 219                 parent.appendRow(item)
 220             elif parent == self.headingsModel:
 221                 item = parent.item(parent.rowCount() - 1, 0)
 222             else:
 223                 item = parent.child(parent.rowCount() - 1, 0)
 224             parent = item
 225             self.headingsList.setExpanded(parent.index(), True)
 226             i += 1
 227         
 228         parent.appendRow(newItem)
 229     
 230     def goToAnchor(self, index):
 231     
 232         url = index.data(Qt.UserRole).toUrl()
 233         if url.isValid():
 234             webview = self.stackedWidget.currentWidget()
 235             webview.load(url)
 236 
 237 
 238 if __name__ == "__main__":
 239 
 240     app = QApplication(sys.argv)
 241     browser = Browser()
 242     browser.show()
 243     sys.exit(app.exec_())

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2014-06-07 22:36:21, 8.4 KB) [[attachment:augmented.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.

Unable to edit the page? See the FrontPage for instructions.