diff options
author | David Boddie <dboddie@trolltech.com> | 2009-04-06 16:53:34 +0200 |
---|---|---|
committer | David Boddie <dboddie@trolltech.com> | 2009-04-06 16:53:34 +0200 |
commit | d1c73c0d21f752110e95dcb6275386acf1ac6172 (patch) | |
tree | 7e629737054f5fd594bf394a1318735c08a0cb18 | |
parent | a37422434e2140ccb606f166238f75a5a741ec03 (diff) |
Ported the Web Monster example to Python.
-rw-r--r-- | webmonster/webmonster.py | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/webmonster/webmonster.py b/webmonster/webmonster.py new file mode 100644 index 0000000..98819ba --- /dev/null +++ b/webmonster/webmonster.py @@ -0,0 +1,198 @@ +############################################################################# +## +## Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +## Contact: Qt Software Information (qt-info@nokia.com) +## +## This file is part of the Graphics Dojo project on Qt Labs. +## +## This file may be used under the terms of the GNU General Public +## License version 2.0 or 3.0 as published by the Free Software Foundation +## and appearing in the file LICENSE.GPL included in the packaging of +## this file. Please review the following information to ensure GNU +## General Public Licensing requirements will be met: +## http://www.fsf.org/licensing/licenses/info/GPLv2.html and +## http://www.gnu.org/copyleft/gpl.html. +## +## If you are unsure which license is appropriate for your use, please +## contact the sales department at qt-sales@nokia.com. +## +## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +## +############################################################################# + +import sys +from PyQt4.QtCore import * +from PyQt4.QtGui import * +from PyQt4.QtNetwork import * +from PyQt4.QtWebKit import * + +try: + import webmonster_rc +except ImportError: + sys.stderr.write( + "Please process the webmonster.qrc file before running this program. " + "For example with:\n\n" + "pyrcc4 -o webmonster_rc.py webmonster.qrc\n\n" + ) + sys.exit(1) + +MONSTER_JS_URL = "http://deanm.github.com/pre3d/monster.js" + +class PaintCommand: + def __init__(self, opacity = 0.0, stroke = QPen(), + fill = QBrush(), polygon = QPolygonF()): + self.opacity = opacity + self.stroke = stroke + self.fill = fill + self.polygon = polygon + + +def parseColor(name): + + if name == "none": + return QColor() + + name = str(name) + if name.startswith("rgba("): + start = name.find('(') + end = name.rfind(')') + if end != -1: + substr = name[start+1:-1] + colors = map(float, substr.split(',')) + if len(colors) == 4: + colors[3] = max(0, colors[3] * 255) + return QColor(*colors) + + return QColor(name) + + +class WebMonster(QWidget): + + def __init__(self, parent = None): + + QWidget.__init__(self, parent) + self.commandBuffer = [] + self.fps = 0 + self.frameTick = QTime() + self.totalFrame = 0 + + self.page = QWebPage(self) + self.page.settings().setAttribute(QWebSettings.JavascriptEnabled, True) + self.page.mainFrame().addToJavaScriptWindowObject("webmonster", self) + + self.manager = QNetworkAccessManager(self) + self.connect(self.manager, SIGNAL("finished(QNetworkReply*)"), + self.start) + + url = QUrl(MONSTER_JS_URL) + reply = self.manager.get(QNetworkRequest(url)) + self.connect(reply, SIGNAL("downloadProgress(qint64, qint64)"), + self.progress) + + self.setWindowTitle(self.tr("About to download %1").arg(MONSTER_JS_URL)) + + def progress(self, received, total): + + percent = received * 100 / total + self.setWindowTitle(self.tr("Downloading %1: %2%").arg(MONSTER_JS_URL).arg(percent)) + + def start(self, networkReply): + + url = networkReply.url() + if networkReply.error(): + self.setWindowTitle(self.tr("Can't download %1: %2").arg( + url.toString()).arg(networkReply.errorString())) + else: + self.setWindowTitle(self.tr("Monster Evolution in Qt")) + self.setAttribute(Qt.WA_OpaquePaintEvent, True) + + file = QFile() + file.setFileName(":/magic.js") + file.open(QIODevice.ReadOnly) + magicCode = QString(file.readAll()) + file.close() + self.page.mainFrame().evaluateJavaScript(magicCode) + + scriptCode = QString(networkReply.readAll()) + self.page.mainFrame().evaluateJavaScript(scriptCode) + self.page.mainFrame().evaluateJavaScript("window.onLoad()") + + networkReply.deleteLater() + + @pyqtSignature("drawPolygons(int, QVariantList)") + def drawPolygons(self, polygonCount, polygonArray): + + extra = polygonCount - len(self.commandBuffer) + if extra > 0: + self.commandBuffer += [None] * extra + elif extra < 0: + self.commandBuffer = self.commandBuffer[:polygonCount] + + i = 0 + while i < polygonCount: + + cmd = polygonArray[i].toList() + alpha = cmd[0].toDouble()[0] + strokeColor = cmd[1].toString() + fillColor = cmd[2].toString() + pointCount = cmd[3].toInt()[0] + pointArray = cmd[4].toList() + + polygon = QPolygonF(pointCount / 2) + p = 0 + while p < pointCount / 2: + polygon[p] = QPointF(pointArray[2 * p].toDouble()[0], + pointArray[2 * p + 1].toDouble()[0]) + p += 1 + + paint = self.commandBuffer[i] + if not paint: + paint = self.commandBuffer[i] = PaintCommand() + + paint.opacity = alpha + if strokeColor != "none": + paint.stroke.setStyle(Qt.SolidLine) + paint.stroke.setColor(parseColor(strokeColor)) + else: + paint.stroke = QPen(Qt.NoPen) + + if fillColor != "none": + paint.fill = QBrush(parseColor(fillColor)) + else: + paint.fill = QBrush(Qt.NoBrush) + paint.polygon = polygon + i += 1 + + self.update() + + if self.totalFrame % 15 == 0: + elapsed = self.frameTick.elapsed() + self.frameTick.start() + self.fps = 16 * 1000 / (1 + elapsed) + + self.totalFrame += 1 + + def paintEvent(self, event): + + p = QPainter(self) + p.setRenderHint(QPainter.Antialiasing, True) + for cmd in self.commandBuffer: + p.setPen(cmd.stroke) + p.setOpacity(cmd.opacity) + p.setBrush(cmd.fill) + p.drawPolygon(cmd.polygon) + + p.setPen(Qt.white) + p.drawText(10, 600 - 20, QString("%1 FPS").arg(self.fps)) + + +if __name__ == "__main__": + + app = QApplication(sys.argv) + + webmonster = WebMonster() + webmonster.setFixedSize(800, 600) + webmonster.show() + + sys.exit(app.exec_()) |