Created
February 22, 2010 08:23
-
-
Save md2/310927 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python | |
| # -*- coding: utf-8 -*- | |
| # vim: ts=4 sw=4 et tw=0 sts=4 ai si | |
| from __future__ import with_statement | |
| import os | |
| import sys | |
| import re | |
| import enchant | |
| from uuid import uuid4 | |
| from lxml import etree | |
| from StringIO import StringIO | |
| from PyQt4 import QtCore, QtGui, QtWebKit | |
| stylesheet = """ | |
| <style type="text/css"> | |
| body { | |
| width: 80%; | |
| margin: 0 auto; | |
| } | |
| .title-info > *, .src-title-info, .document-info, .publish-info, [src_tag="stylesheet"] { | |
| display: none; | |
| } | |
| .annotation, .coverpage { | |
| display: block !important; | |
| } | |
| .annotation { | |
| margin-left: 40%; | |
| font-size: smaller; | |
| margin-bottom: 2em; | |
| } | |
| .annotation > *:first-child { | |
| margin-top: 0; | |
| } | |
| p { | |
| margin: 0; | |
| text-indent: 3em; | |
| } | |
| .empty-line { | |
| height: 1em; | |
| margin: 0 0; | |
| } | |
| .body > .title { | |
| font-size: 300%; | |
| } | |
| .section > .title { | |
| font-size: 200%; | |
| } | |
| .section > .section > .title { | |
| font-size: 180%; | |
| } | |
| .section > .section > .section > .title { | |
| font-size: 160%; | |
| } | |
| .section > .section > .section > .section > .title { | |
| font-size: 140%; | |
| } | |
| .title { | |
| font-size: 120%; | |
| } | |
| .title p { | |
| margin: 0.5em 0; | |
| text-indent: 0; | |
| text-align: center; | |
| } | |
| .subtitle { | |
| font-weight: bold; | |
| text-indent: 0; | |
| text-align: center; | |
| } | |
| .cite { | |
| border-left: 5px solid silver; | |
| background: #eee; | |
| padding: 0.4em 1em; | |
| } | |
| .cite > p:first-child, .cite > p:last-child { | |
| margin: 0; | |
| } | |
| .epigraph { | |
| margin-left: 20%; | |
| } | |
| .text-author { | |
| margin-left: 5em; | |
| } | |
| .poem { | |
| margin-left: 4em; | |
| margin-top: 1em; | |
| margin-bottom: 1em; | |
| } | |
| .stanza { | |
| margin-bottom: 0.3em; | |
| } | |
| .coverpage img, .section > .image > img { | |
| display: block; | |
| width: auto; | |
| margin: 0.5em auto; | |
| } | |
| span.hunspell { | |
| background-image: url(qrc:/incorrect-spelling.png); | |
| background-repeat: repeat-x; | |
| background-position: bottom left; | |
| } | |
| </style> | |
| """ | |
| fb2_to_html = """ | |
| <xsl:stylesheet version="1.0" | |
| xmlns="http://www.w3.org/1999/xhtml" | |
| xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | |
| xmlns:f="http://www.gribuser.ru/xml/fictionbook/2.0" | |
| xmlns:l="http://www.w3.org/1999/xlink" | |
| exclude-result-prefixes="xsl f l" | |
| > | |
| <xsl:output method="html" encoding="utf-8" | |
| doctype-public="-//W3C//DTD XHTML 1.1//EN" | |
| doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/> | |
| <xsl:template match="f:FictionBook"> | |
| <html> | |
| <head> | |
| </head> | |
| <body> | |
| <xsl:apply-templates/> | |
| </body> | |
| </html> | |
| </xsl:template> | |
| <xsl:template match="f:p | f:v"> | |
| <p><xsl:copy-of select="@*"/><xsl:apply-templates/></p> | |
| </xsl:template> | |
| <xsl:template match="f:empty-line"> | |
| <div class="empty-line"/> | |
| </xsl:template> | |
| <xsl:template match="f:section | f:annotation | f:epigraph | f:cite | f:poem | f:stanza | f:title | f:body"> | |
| <div class="{local-name()}"> | |
| <xsl:copy-of select="@*"/> | |
| <xsl:apply-templates/> | |
| </div> | |
| </xsl:template> | |
| <xsl:template match="f:description | f:title-info | f:src-title-info | f:document-info | f:publish-info | f:author | f:translator | f:coverpage | f:history"> | |
| <div class="{local-name()}"> | |
| <xsl:apply-templates/> | |
| </div> | |
| </xsl:template> | |
| <xsl:template match="f:text-author | f:subtitle"> | |
| <p class="{local-name()}"> | |
| <xsl:copy-of select="@*"/> | |
| <xsl:apply-templates/> | |
| </p> | |
| </xsl:template> | |
| <xsl:template name="base64image"> | |
| <xsl:param name="id"/> | |
| <xsl:variable name="object" select="//f:binary[@id=$id]"/> | |
| <xsl:value-of select="concat('data:', $object/@content-type, ';base64,', $object/text())"/> | |
| </xsl:template> | |
| <xsl:template name="img"> | |
| <img> | |
| <xsl:if test="starts-with(@l:href, '#')"> | |
| <xsl:attribute name="src"> | |
| <xsl:call-template name="base64image"> | |
| <xsl:with-param name="id" select="substring(@l:href, 2)"/> | |
| </xsl:call-template> | |
| </xsl:attribute> | |
| </xsl:if> | |
| <xsl:attribute name="alt"> | |
| <xsl:if test="@alt"> | |
| <xsl:value-of select="@alt"/> | |
| </xsl:if> | |
| <xsl:if test="not(@alt)"> | |
| <xsl:value-of select="@l:href"/> | |
| </xsl:if> | |
| </xsl:attribute> | |
| </img> | |
| </xsl:template> | |
| <xsl:template match="f:coverpage/f:image | f:section/f:image"> | |
| <div class="image" href="{@l:href}"> | |
| <xsl:copy-of select="@alt"/> | |
| <xsl:call-template name="img"/> | |
| </div> | |
| </xsl:template> | |
| <xsl:template match="f:image"> | |
| <span class="image" href="{@l:href}"> | |
| <xsl:copy-of select="@alt"/> | |
| <xsl:call-template name="img"/> | |
| </span> | |
| </xsl:template> | |
| <xsl:template match="f:binary"> | |
| <div class="binary"> | |
| <xsl:copy-of select="@*"/> | |
| </div> | |
| </xsl:template> | |
| <xsl:template match="f:a"> | |
| <a href="{@l:href}"> | |
| <xsl:if test="@type"> | |
| <xsl:attribute name="class"> | |
| <xsl:value-of select="@type"/> | |
| </xsl:attribute> | |
| </xsl:if> | |
| <xsl:apply-templates/> | |
| </a> | |
| </xsl:template> | |
| <xsl:template match="f:emphasis"> | |
| <em><xsl:apply-templates/></em> | |
| </xsl:template> | |
| <xsl:template match="f:strong"> | |
| <strong><xsl:apply-templates/></strong> | |
| </xsl:template> | |
| <xsl:template match="f:strikethrough"> | |
| <strike><xsl:apply-templates/></strike> | |
| </xsl:template> | |
| <xsl:template match="f:sub"> | |
| <sub><xsl:apply-templates/></sub> | |
| </xsl:template> | |
| <xsl:template match="f:sup"> | |
| <sup><xsl:apply-templates/></sup> | |
| </xsl:template> | |
| <xsl:template match="*"> | |
| <span class="unknown_element" src_tag="{local-name()}"> | |
| <xsl:copy-of select="@*"/> | |
| <xsl:apply-templates/> | |
| </span> | |
| </xsl:template> | |
| </xsl:stylesheet> | |
| """ | |
| html_to_fb2 = """ | |
| <xsl:stylesheet version="1.0" | |
| xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | |
| xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" | |
| xmlns:l="http://www.w3.org/1999/xlink" | |
| exclude-result-prefixes="xsl" | |
| > | |
| <xsl:output method="xml" encoding="utf-8"/> | |
| <xsl:template match="html"> | |
| <FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" | |
| xmlns:l="http://www.w3.org/1999/xlink"> | |
| <xsl:apply-templates/> | |
| </FictionBook> | |
| </xsl:template> | |
| <xsl:template match="p[not(@class) and parent::div/@class != 'stanza']"> | |
| <p><xsl:call-template name="copy-attributes"/><xsl:apply-templates/></p> | |
| </xsl:template> | |
| <xsl:template match="div[@class='stanza']/p"> | |
| <v><xsl:call-template name="copy-attributes"/><xsl:apply-templates/></v> | |
| </xsl:template> | |
| <xsl:template match="p[@class='subtitle']"> | |
| <subtitle><xsl:call-template name="copy-attributes"/><xsl:apply-templates/></subtitle> | |
| </xsl:template> | |
| <xsl:template match="p[@class='text-author']"> | |
| <text-author><xsl:call-template name="copy-attributes"/><xsl:apply-templates/></text-author> | |
| </xsl:template> | |
| <xsl:template match="span[@class='unknown_element']"> | |
| <xsl:element name="{@src_tag}"> | |
| <xsl:call-template name="copy-attributes"/> | |
| <xsl:apply-templates/> | |
| </xsl:element> | |
| </xsl:template> | |
| <xsl:template match="div[@class]"> | |
| <xsl:element name="{@class}"> | |
| <xsl:call-template name="copy-attributes"/> | |
| <xsl:apply-templates/> | |
| </xsl:element> | |
| </xsl:template> | |
| <xsl:template match="body"> | |
| <xsl:apply-templates/> | |
| </xsl:template> | |
| <xsl:template match="head | img"/> | |
| <xsl:template match="div[@class='image'] | span[@class='image']"> | |
| <image l:href="{@href}"> | |
| <xsl:copy-of select="@alt"/> | |
| </image> | |
| </xsl:template> | |
| <xsl:template match="div[@class='binary']"> | |
| <binary> | |
| <xsl:call-template name="copy-attributes"/> | |
| <xsl:variable name="type" select="@content-type"/> | |
| <xsl:variable name="href" select="concat('#', @id)"/> | |
| <xsl:variable name="src" select="(//div|//span)[@class='image'][@href=$href][1]/img/@src"/> | |
| <xsl:value-of select="substring-after($src, concat('data:', $type, ';base64,'))"/> | |
| </binary> | |
| </xsl:template> | |
| <xsl:template match="em | i"> | |
| <emphasis><xsl:apply-templates/></emphasis> | |
| </xsl:template> | |
| <xsl:template match="strong | b"> | |
| <strong><xsl:apply-templates/></strong> | |
| </xsl:template> | |
| <xsl:template match="a"> | |
| <a l:href="{@href}"> | |
| <xsl:if test="@class"> | |
| <xsl:attribute name="type"> | |
| <xsl:value-of select="@class"/> | |
| </xsl:attribute> | |
| </xsl:if> | |
| <xsl:apply-templates/> | |
| </a> | |
| </xsl:template> | |
| <xsl:template match="strike | s"> | |
| <strikethrough><xsl:apply-templates/></strikethrough> | |
| </xsl:template> | |
| <xsl:template match="sub"> | |
| <sub><xsl:apply-templates/></sub> | |
| </xsl:template> | |
| <xsl:template match="sup"> | |
| <sup><xsl:apply-templates/></sup> | |
| </xsl:template> | |
| <xsl:template match="span[@class='Apple-style-span' or @class='hunspell']"> | |
| <xsl:apply-templates/> | |
| </xsl:template> | |
| <xsl:template match="*"> | |
| <unk><xsl:apply-templates/></unk> | |
| </xsl:template> | |
| <xsl:template name="copy-attributes"> | |
| <xsl:copy-of select="@*[name() != 'class' and name() != 'src_tag' and name() != 'uuid']"/> | |
| </xsl:template> | |
| </xsl:stylesheet> | |
| """ | |
| class SpellingThread(QtCore.QThread): | |
| waitingForXml = QtCore.pyqtSignal(str) | |
| processedXml = QtCore.pyqtSignal(str, unicode) | |
| def __init__(self, parent=None): | |
| super(SpellingThread, self).__init__(parent) | |
| self.mutex = QtCore.QMutex() | |
| self.condition = QtCore.QWaitCondition() | |
| self.abort = False | |
| self.dictionary = enchant.Dict("ru_RU") | |
| self.wordlike = re.compile(ur"\b[Р°-СЏС‘]+(?:-[Р°-СЏС‘]+)?\b", re.UNICODE | re.IGNORECASE) | |
| self.uuids = [] | |
| self.xml = None | |
| def addUUID(self, uuid): | |
| self.uuids.append(uuid) | |
| def process(self, uuid): | |
| self.mutex.lock() | |
| self.waitingForXml.emit(uuid) | |
| self.condition.wait(self.mutex) | |
| self.mutex.unlock() | |
| if not self.abort and self.xml: | |
| mis = {} | |
| for word in self.wordlike.findall(self.xml): | |
| if not self.dictionary.check(word): | |
| mis[word] = None | |
| if mis: | |
| def subfunc(match): | |
| if match.group(1): | |
| return match.group(1) | |
| elif match.group(3): | |
| return match.group(3) | |
| else: | |
| return u'<span class="hunspell">%s</span>' % (match.group(2)) | |
| regex = re.compile(ur"(<[^>]+>)|\b(%s)\b|(.)" % (u"|".join(mis.keys())), re.UNICODE) | |
| self.xml = regex.sub(subfunc, self.xml) | |
| self.processedXml.emit(uuid, self.xml) | |
| def quit(self): | |
| locker = QtCore.QMutexLocker(self.mutex) | |
| self.abort = True | |
| self.condition.wakeOne() | |
| def feedXml(self, xml): | |
| locker = QtCore.QMutexLocker(self.mutex) | |
| self.xml = unicode(xml) | |
| self.condition.wakeOne() | |
| def reset(self): | |
| self.quit() | |
| self.wait() | |
| self.abort = False | |
| self.uuids = [] | |
| def run(self): | |
| for uuid in self.uuids: | |
| if self.abort: | |
| break | |
| self.process(uuid) | |
| xhtml_NS = "http://www.w3.org/1999/xhtml" | |
| class MainWindow(QtGui.QMainWindow): | |
| def __init__(self, parent=None): | |
| QtGui.QMainWindow.__init__(self, parent) | |
| self.setupUi(self) | |
| self.splitter.setSizes([10,1280]) | |
| self.webView.contextMenuEvent = self.webView_contextMenuEvent | |
| self.addBasicActions(self.menuEdit) | |
| self.spellingThread = SpellingThread() | |
| self.spellingThread.waitingForXml.connect(self.giveXml) | |
| self.spellingThread.processedXml.connect(self.setInnerXml) | |
| def addBasicActions(self, menu): | |
| menu.addAction(self.webView.pageAction(QtWebKit.QWebPage.Cut)) | |
| menu.addAction(self.webView.pageAction(QtWebKit.QWebPage.Copy)) | |
| menu.addAction(self.webView.pageAction(QtWebKit.QWebPage.Paste)) | |
| menu.addSeparator() | |
| menu.addAction(self.webView.pageAction(QtWebKit.QWebPage.ToggleBold)) | |
| menu.addAction(self.webView.pageAction(QtWebKit.QWebPage.ToggleItalic)) | |
| menu.addAction(self.webView.pageAction(QtWebKit.QWebPage.ToggleStrikethrough)) | |
| menu.addSeparator() | |
| menu.addAction(self.webView.pageAction(QtWebKit.QWebPage.ToggleSubscript)) | |
| menu.addAction(self.webView.pageAction(QtWebKit.QWebPage.ToggleSuperscript)) | |
| def webView_contextMenuEvent(self, event): | |
| menu = QtGui.QMenu(self) | |
| self.addBasicActions(menu) | |
| menu.exec_(event.globalPos()) | |
| def closeEvent(self, event): | |
| event.accept() | |
| @QtCore.pyqtSlot(bool) | |
| def on_actionReadOnly_triggered(self, checked): | |
| self.webView.page().setContentEditable(not checked) | |
| @QtCore.pyqtSlot() | |
| def on_actionOpen_triggered(self): | |
| filename = QtGui.QFileDialog.getOpenFileName(self, "", "", "FB2 files (*.fb2)") | |
| if filename: | |
| fb2 = etree.parse(unicode(filename)) | |
| xslt = etree.XML(fb2_to_html) | |
| transform = etree.XSLT(xslt) | |
| html = transform(fb2) | |
| html.find("/{%s}head" % xhtml_NS).append(etree.XML(stylesheet)) | |
| self.webView.setHtml(etree.tostring(html, method="html", encoding=unicode), | |
| QtCore.QUrl("file://%s/" % (os.getcwd()))) | |
| self.listWidget.clear() | |
| self.comboBox.setCurrentIndex(-1) | |
| self.spellingThread.reset() | |
| for el in self.webView.page().currentFrame().findAllElements("p").toList(): | |
| if not el.hasAttribute("uuid"): | |
| el.setAttribute("uuid", str(uuid4())) | |
| self.spellingThread.addUUID(str(el.attribute("uuid"))) | |
| self.spellingThread.start() | |
| def getElementByUUID(self, uuid): | |
| return self.webView.page().currentFrame().findFirstElement("[uuid='%s']" % (uuid)) | |
| def giveXml(self, uuid): | |
| el = self.getElementByUUID(uuid) | |
| self.spellingThread.feedXml(el.toInnerXml()) | |
| def setInnerXml(self, uuid, xml): | |
| el = self.getElementByUUID(uuid) | |
| el.setInnerXml(xml) | |
| @QtCore.pyqtSlot() | |
| def on_actionSaveAs_triggered(self): | |
| filename = QtGui.QFileDialog.getSaveFileName(self, "", "", "FB2 files (*.fb2)") | |
| if filename: | |
| parser = etree.HTMLParser(recover=False) | |
| html = etree.parse(StringIO(unicode(self.webView.page().currentFrame().toHtml())), | |
| parser=parser) | |
| xslt = etree.XML(html_to_fb2) | |
| transform = etree.XSLT(xslt) | |
| fb2 = transform(html) | |
| with open(filename, "w") as fo: | |
| fo.write(etree.tostring(fb2, encoding="utf-8", xml_declaration=True)) | |
| @QtCore.pyqtSlot(int) | |
| def on_comboBox_currentIndexChanged(self, index): | |
| query = str(self.comboBox.itemText(index)) | |
| if query in ('section', 'annotation', 'epigraph', 'cite', 'poem', 'stanza', 'title', 'image', 'empty-line'): | |
| query = "div.%s" % (query) | |
| elif query in ('text-author', 'subtitle'): | |
| query = "p.%s" % (query) | |
| elif query == 'emphasis': | |
| query = "em,i" | |
| elif query == 'strong': | |
| query = "strong,b" | |
| elif query == 'strikethrough': | |
| query = "strike,s" | |
| self.listWidget.clear() | |
| for el in self.webView.page().currentFrame().findAllElements(query).toList(): | |
| if not el.hasAttribute("uuid"): | |
| el.setAttribute("uuid", str(uuid4())) | |
| if el.hasAttribute("class"): | |
| item = QtGui.QListWidgetItem(el.attribute("class")) | |
| else: | |
| item = QtGui.QListWidgetItem(el.localName()) | |
| item.uuid = str(el.attribute("uuid")) | |
| self.listWidget.addItem(item) | |
| def on_listWidget_currentItemChanged(self, current, previous): | |
| if current: | |
| el = self.getElementByUUID(current.uuid) | |
| el.evaluateJavaScript("this.scrollIntoView()") | |
| def setupUi(self, MainWindow): | |
| MainWindow.setObjectName("MainWindow") | |
| MainWindow.resize(662, 668) | |
| self.centralwidget = QtGui.QWidget(MainWindow) | |
| self.centralwidget.setObjectName("centralwidget") | |
| self.verticalLayout_2 = QtGui.QVBoxLayout(self.centralwidget) | |
| self.verticalLayout_2.setSpacing(0) | |
| self.verticalLayout_2.setContentsMargins(0, 5, 5, 5) | |
| self.verticalLayout_2.setObjectName("verticalLayout_2") | |
| self.splitter = QtGui.QSplitter(self.centralwidget) | |
| self.splitter.setOrientation(QtCore.Qt.Horizontal) | |
| self.splitter.setObjectName("splitter") | |
| self.verticalLayoutWidget = QtGui.QWidget(self.splitter) | |
| self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") | |
| self.verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget) | |
| self.verticalLayout.setObjectName("verticalLayout") | |
| self.comboBox = QtGui.QComboBox(self.verticalLayoutWidget) | |
| sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) | |
| sizePolicy.setHorizontalStretch(0) | |
| sizePolicy.setVerticalStretch(0) | |
| sizePolicy.setHeightForWidth(self.comboBox.sizePolicy().hasHeightForWidth()) | |
| self.comboBox.setSizePolicy(sizePolicy) | |
| self.comboBox.setEditable(True) | |
| self.comboBox.setObjectName("comboBox") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.comboBox.addItem("") | |
| self.verticalLayout.addWidget(self.comboBox) | |
| self.listWidget = QtGui.QListWidget(self.verticalLayoutWidget) | |
| sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) | |
| sizePolicy.setHorizontalStretch(0) | |
| sizePolicy.setVerticalStretch(0) | |
| sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth()) | |
| self.listWidget.setSizePolicy(sizePolicy) | |
| self.listWidget.setObjectName("listWidget") | |
| self.verticalLayout.addWidget(self.listWidget) | |
| self.webView = QtWebKit.QWebView(self.splitter) | |
| sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) | |
| sizePolicy.setHorizontalStretch(0) | |
| sizePolicy.setVerticalStretch(0) | |
| sizePolicy.setHeightForWidth(self.webView.sizePolicy().hasHeightForWidth()) | |
| self.webView.setSizePolicy(sizePolicy) | |
| self.webView.setUrl(QtCore.QUrl("about:blank")) | |
| self.webView.setObjectName("webView") | |
| self.verticalLayout_2.addWidget(self.splitter) | |
| MainWindow.setCentralWidget(self.centralwidget) | |
| self.menuBar = QtGui.QMenuBar(MainWindow) | |
| self.menuBar.setGeometry(QtCore.QRect(0, 0, 662, 20)) | |
| self.menuBar.setObjectName("menuBar") | |
| self.menuFile = QtGui.QMenu(self.menuBar) | |
| self.menuFile.setObjectName("menuFile") | |
| self.menuEdit = QtGui.QMenu(self.menuBar) | |
| self.menuEdit.setObjectName("menuEdit") | |
| self.menuView = QtGui.QMenu(self.menuBar) | |
| self.menuView.setObjectName("menuView") | |
| self.menuHelp = QtGui.QMenu(self.menuBar) | |
| self.menuHelp.setObjectName("menuHelp") | |
| MainWindow.setMenuBar(self.menuBar) | |
| self.actionOpen = QtGui.QAction(MainWindow) | |
| self.actionOpen.setObjectName("actionOpen") | |
| self.actionExit = QtGui.QAction(MainWindow) | |
| self.actionExit.setObjectName("actionExit") | |
| self.actionReadOnly = QtGui.QAction(MainWindow) | |
| self.actionReadOnly.setCheckable(True) | |
| self.actionReadOnly.setChecked(True) | |
| self.actionReadOnly.setObjectName("actionReadOnly") | |
| self.actionSaveAs = QtGui.QAction(MainWindow) | |
| self.actionSaveAs.setObjectName("actionSaveAs") | |
| self.menuFile.addAction(self.actionOpen) | |
| self.menuFile.addAction(self.actionSaveAs) | |
| self.menuFile.addSeparator() | |
| self.menuFile.addAction(self.actionExit) | |
| self.menuView.addAction(self.actionReadOnly) | |
| self.menuBar.addAction(self.menuFile.menuAction()) | |
| self.menuBar.addAction(self.menuEdit.menuAction()) | |
| self.menuBar.addAction(self.menuView.menuAction()) | |
| self.menuBar.addAction(self.menuHelp.menuAction()) | |
| self.retranslateUi(MainWindow) | |
| self.comboBox.setCurrentIndex(-1) | |
| QtCore.QObject.connect(self.actionExit, QtCore.SIGNAL("triggered()"), MainWindow.close) | |
| QtCore.QMetaObject.connectSlotsByName(MainWindow) | |
| def retranslateUi(self, MainWindow): | |
| MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(0, QtGui.QApplication.translate("MainWindow", "a", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(1, QtGui.QApplication.translate("MainWindow", "annotation", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(2, QtGui.QApplication.translate("MainWindow", "cite", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(3, QtGui.QApplication.translate("MainWindow", "emphasis", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(4, QtGui.QApplication.translate("MainWindow", "empty-line", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(5, QtGui.QApplication.translate("MainWindow", "epigraph", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(6, QtGui.QApplication.translate("MainWindow", "image", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(7, QtGui.QApplication.translate("MainWindow", "poem", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(8, QtGui.QApplication.translate("MainWindow", "section", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(9, QtGui.QApplication.translate("MainWindow", "stanza", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(10, QtGui.QApplication.translate("MainWindow", "strikethrough", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(11, QtGui.QApplication.translate("MainWindow", "strong", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(12, QtGui.QApplication.translate("MainWindow", "sub", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(13, QtGui.QApplication.translate("MainWindow", "subtitle", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(14, QtGui.QApplication.translate("MainWindow", "sup", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(15, QtGui.QApplication.translate("MainWindow", "text-author", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.comboBox.setItemText(16, QtGui.QApplication.translate("MainWindow", "title", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.menuFile.setTitle(QtGui.QApplication.translate("MainWindow", "File", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.menuEdit.setTitle(QtGui.QApplication.translate("MainWindow", "Edit", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.menuView.setTitle(QtGui.QApplication.translate("MainWindow", "View", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.menuHelp.setTitle(QtGui.QApplication.translate("MainWindow", "Help", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.actionOpen.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.actionExit.setText(QtGui.QApplication.translate("MainWindow", "Exit", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.actionReadOnly.setText(QtGui.QApplication.translate("MainWindow", "Read Only", None, QtGui.QApplication.UnicodeUTF8)) | |
| self.actionSaveAs.setText(QtGui.QApplication.translate("MainWindow", "Save As...", None, QtGui.QApplication.UnicodeUTF8)) | |
| qt_resource_data = "\ | |
| \x00\x00\x00\x5f\ | |
| \x89\ | |
| \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ | |
| \x00\x00\x05\x00\x00\x00\x05\x08\x06\x00\x00\x00\x8d\x6f\x26\xe5\ | |
| \x00\x00\x00\x26\x49\x44\x41\x54\x08\x99\x63\x60\xc0\x02\x18\x91\ | |
| \x39\xff\x19\x18\xfe\x33\x30\x30\x7c\x81\x31\x18\xfe\x33\x30\xfc\ | |
| \x87\xb1\x61\x2a\x3e\xa3\x08\x60\x03\x00\x8d\xef\x0c\xde\xe9\xcf\ | |
| \xf6\x9e\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ | |
| " | |
| qt_resource_name = "\ | |
| \x00\x16\ | |
| \x0f\x61\x9d\xe7\ | |
| \x00\x69\ | |
| \x00\x6e\x00\x63\x00\x6f\x00\x72\x00\x72\x00\x65\x00\x63\x00\x74\x00\x2d\x00\x73\x00\x70\x00\x65\x00\x6c\x00\x6c\x00\x69\x00\x6e\ | |
| \x00\x67\x00\x2e\x00\x70\x00\x6e\x00\x67\ | |
| " | |
| qt_resource_struct = "\ | |
| \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ | |
| \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ | |
| " | |
| def qInitResources(): | |
| QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) | |
| def qCleanupResources(): | |
| QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) | |
| qInitResources() | |
| app = QtGui.QApplication(sys.argv) | |
| window = MainWindow() | |
| window.show() | |
| sys.exit(app.exec_()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment