mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk and fix for bug #5414
This commit is contained in:
commit
c79091e71b
@ -9,8 +9,9 @@ __description__ = 'PCMag (www.pcmag.com) delivers authoritative, labs-based comp
|
|||||||
'''
|
'''
|
||||||
http://www.pcmag.com/
|
http://www.pcmag.com/
|
||||||
'''
|
'''
|
||||||
|
import re
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
from calibre.ebooks.BeautifulSoup import Comment
|
||||||
|
|
||||||
class pcMag(BasicNewsRecipe):
|
class pcMag(BasicNewsRecipe):
|
||||||
__author__ = 'Lorenzo Vigentini'
|
__author__ = 'Lorenzo Vigentini'
|
||||||
@ -33,9 +34,6 @@ class pcMag(BasicNewsRecipe):
|
|||||||
remove_javascript = True
|
remove_javascript = True
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
|
|
||||||
keep_only_tags = [
|
|
||||||
dict(name='div', attrs={'id':'articleContent'})
|
|
||||||
]
|
|
||||||
|
|
||||||
feeds = [
|
feeds = [
|
||||||
(u'Tech Commentary from the Editors of PC Magazine', u'http://rssnewsapps.ziffdavis.com/PCMAG_commentary.xml'),
|
(u'Tech Commentary from the Editors of PC Magazine', u'http://rssnewsapps.ziffdavis.com/PCMAG_commentary.xml'),
|
||||||
@ -49,8 +47,13 @@ class pcMag(BasicNewsRecipe):
|
|||||||
(u'Technology News from Ziff Davis', u'http://rssnewsapps.ziffdavis.com/pcmagbreakingnews.xml')
|
(u'Technology News from Ziff Davis', u'http://rssnewsapps.ziffdavis.com/pcmagbreakingnews.xml')
|
||||||
]
|
]
|
||||||
|
|
||||||
|
keep_only_tags = [dict(attrs={'class':'content-page'})]
|
||||||
remove_tags = [
|
remove_tags = [
|
||||||
dict(name='div', attrs={'id':['microAd','intellitxt','articleDeckTalkback','inlineDigg','underArticleLinks','w_talkback']}),
|
dict(attrs={'class':['control-side','comment','highlights_content','btn-holder','subscribe-panel',
|
||||||
dict(name='span', attrs={'id':['highlights_content','yahooBuzzBadge-48558872521263350499378']})
|
'grey-box comments-box']}),
|
||||||
]
|
dict(id=['inlineDigg']),
|
||||||
|
dict(text=lambda text:isinstance(text, Comment)),
|
||||||
|
dict(name='img', width='1'),
|
||||||
|
]
|
||||||
|
preprocess_regexps = [(re.compile(r"<img '[^']+?'"), lambda m : '<img ')]
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import os
|
|||||||
import glob
|
import glob
|
||||||
from calibre.customize import FileTypePlugin, MetadataReaderPlugin, MetadataWriterPlugin
|
from calibre.customize import FileTypePlugin, MetadataReaderPlugin, MetadataWriterPlugin
|
||||||
from calibre.constants import numeric_version
|
from calibre.constants import numeric_version
|
||||||
from calibre.ebooks.metadata.archive import ArchiveExtract
|
from calibre.ebooks.metadata.archive import ArchiveExtract, get_cbz_metadata
|
||||||
|
|
||||||
class HTML2ZIP(FileTypePlugin):
|
class HTML2ZIP(FileTypePlugin):
|
||||||
name = 'HTML to ZIP'
|
name = 'HTML to ZIP'
|
||||||
@ -97,6 +97,12 @@ class ComicMetadataReader(MetadataReaderPlugin):
|
|||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
ret = extract_first(stream)
|
ret = extract_first(stream)
|
||||||
mi = MetaInformation(None, None)
|
mi = MetaInformation(None, None)
|
||||||
|
stream.seek(0)
|
||||||
|
if ftype == 'cbz':
|
||||||
|
try:
|
||||||
|
mi.smart_update(get_cbz_metadata(stream))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
if ret is not None:
|
if ret is not None:
|
||||||
path, data = ret
|
path, data = ret
|
||||||
ext = os.path.splitext(path)[1][1:]
|
ext = os.path.splitext(path)[1][1:]
|
||||||
|
@ -202,9 +202,11 @@ class PRS505(CLI, Device):
|
|||||||
|
|
||||||
def write_card_prefix(prefix, listid):
|
def write_card_prefix(prefix, listid):
|
||||||
if prefix is not None and hasattr(booklists[listid], 'write'):
|
if prefix is not None and hasattr(booklists[listid], 'write'):
|
||||||
if not os.path.exists(prefix):
|
tgt = os.path.join(prefix, *(self.CACHE_XML.split('/')))
|
||||||
os.makedirs(prefix)
|
base = os.path.dirname(tgt)
|
||||||
with open(prefix + self.__class__.CACHE_XML, 'wb') as f:
|
if not os.path.exists(base):
|
||||||
|
os.makedirs(base)
|
||||||
|
with open(tgt, 'wb') as f:
|
||||||
booklists[listid].write(f)
|
booklists[listid].write(f)
|
||||||
write_card_prefix(self._card_a_prefix, 1)
|
write_card_prefix(self._card_a_prefix, 1)
|
||||||
write_card_prefix(self._card_b_prefix, 2)
|
write_card_prefix(self._card_b_prefix, 2)
|
||||||
|
@ -81,12 +81,40 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
OptionRecommendation(name='no_default_epub_cover', recommended_value=False,
|
OptionRecommendation(name='no_default_epub_cover', recommended_value=False,
|
||||||
help=_('Normally, if the input file has no cover and you don\'t'
|
help=_('Normally, if the input file has no cover and you don\'t'
|
||||||
' specify one, a default cover is generated with the title, '
|
' specify one, a default cover is generated with the title, '
|
||||||
'authors, etc. This option disables the generation of this cover.')),
|
'authors, etc. This option disables the generation of this cover.')
|
||||||
|
),
|
||||||
|
|
||||||
|
OptionRecommendation(name='no_svg_cover', recommended_value=False,
|
||||||
|
help=_('Do not use SVG for the book cover. Use this option if '
|
||||||
|
'your EPUB is going to be used ona device that does not '
|
||||||
|
'support SVG, like the iPhone or the JetBook Lite. '
|
||||||
|
'Without this option, such devices will display the cover '
|
||||||
|
'as a blank page.')
|
||||||
|
),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
recommendations = set([('pretty_print', True, OptionRecommendation.HIGH)])
|
recommendations = set([('pretty_print', True, OptionRecommendation.HIGH)])
|
||||||
|
|
||||||
|
NONSVG_TITLEPAGE_COVER = '''\
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="calibre:cover" content="true" />
|
||||||
|
<title>Cover</title>
|
||||||
|
<style type="text/css" title="override_css">
|
||||||
|
@page {padding: 0pt; margin:0pt}
|
||||||
|
body { text-align: center; padding:0pt; margin: 0pt; }
|
||||||
|
div { padding:0pt; margin: 0pt; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<img src="%s" alt="cover" style="height: 100%%" />
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'''
|
||||||
|
|
||||||
TITLEPAGE_COVER = '''\
|
TITLEPAGE_COVER = '''\
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||||
@ -301,7 +329,9 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
else:
|
else:
|
||||||
href = self.default_cover()
|
href = self.default_cover()
|
||||||
if href is not None:
|
if href is not None:
|
||||||
tp = self.TITLEPAGE_COVER%unquote(href)
|
templ = self.NONSVG_TITLEPAGE_COVER if self.opts.no_svg_cover \
|
||||||
|
else self.TITLEPAGE_COVER
|
||||||
|
tp = templ%unquote(href)
|
||||||
id, href = m.generate('titlepage', 'titlepage.xhtml')
|
id, href = m.generate('titlepage', 'titlepage.xhtml')
|
||||||
item = m.add(id, href, guess_type('t.xhtml')[0],
|
item = m.add(id, href, guess_type('t.xhtml')[0],
|
||||||
data=etree.fromstring(tp))
|
data=etree.fromstring(tp))
|
||||||
|
@ -64,3 +64,45 @@ class ArchiveExtract(FileTypePlugin):
|
|||||||
of.write(zf.read(fname))
|
of.write(zf.read(fname))
|
||||||
return of.name
|
return of.name
|
||||||
|
|
||||||
|
def get_comic_book_info(d, mi):
|
||||||
|
series = d.get('series', '')
|
||||||
|
if series.strip():
|
||||||
|
mi.series = series
|
||||||
|
if d.get('volume', -1) > -1:
|
||||||
|
mi.series_index = float(d['volume'])
|
||||||
|
if d.get('rating', -1) > -1:
|
||||||
|
mi.rating = d['rating']
|
||||||
|
for x in ('title', 'publisher'):
|
||||||
|
y = d.get(x, '').strip()
|
||||||
|
if y:
|
||||||
|
setattr(mi, x, y)
|
||||||
|
tags = d.get('tags', [])
|
||||||
|
if tags:
|
||||||
|
mi.tags = tags
|
||||||
|
authors = []
|
||||||
|
for credit in d.get('credits', []):
|
||||||
|
if credit.get('role', '') in ('Writer', 'Artist', 'Cartoonist',
|
||||||
|
'Creator'):
|
||||||
|
x = credit.get('person', '')
|
||||||
|
if x:
|
||||||
|
x = ' '.join((reversed(x.split(', '))))
|
||||||
|
authors.append(x)
|
||||||
|
if authors:
|
||||||
|
mi.authors = authors
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_cbz_metadata(stream):
|
||||||
|
from calibre.utils.zipfile import ZipFile
|
||||||
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
|
import json
|
||||||
|
|
||||||
|
zf = ZipFile(stream)
|
||||||
|
mi = MetaInformation(None, None)
|
||||||
|
if zf.comment:
|
||||||
|
m = json.loads(zf.comment)
|
||||||
|
if hasattr(m, 'keys'):
|
||||||
|
for cat in m.keys():
|
||||||
|
if cat.startswith('ComicBookInfo'):
|
||||||
|
get_comic_book_info(m[cat], mi)
|
||||||
|
return mi
|
||||||
|
@ -96,6 +96,8 @@ class CSSSelector(etree.XPath):
|
|||||||
path = css_to_xpath(css)
|
path = css_to_xpath(css)
|
||||||
except UnicodeEncodeError: # Bug in css_to_xpath
|
except UnicodeEncodeError: # Bug in css_to_xpath
|
||||||
path = '/'
|
path = '/'
|
||||||
|
except NotImplementedError: # Probably a subselect like :hover
|
||||||
|
path = '/'
|
||||||
path = self.LOCAL_NAME_RE.sub(r"local-name() = '", path)
|
path = self.LOCAL_NAME_RE.sub(r"local-name() = '", path)
|
||||||
etree.XPath.__init__(self, path, namespaces=namespaces)
|
etree.XPath.__init__(self, path, namespaces=namespaces)
|
||||||
self.css = css
|
self.css = css
|
||||||
@ -534,6 +536,8 @@ class Style(object):
|
|||||||
result = base
|
result = base
|
||||||
else:
|
else:
|
||||||
result = self._unit_convert(width, base=base)
|
result = self._unit_convert(width, base=base)
|
||||||
|
if isinstance(result, (unicode, str, bytes)):
|
||||||
|
result = self._profile.width
|
||||||
self._width = result
|
self._width = result
|
||||||
return self._width
|
return self._width
|
||||||
|
|
||||||
@ -555,6 +559,8 @@ class Style(object):
|
|||||||
result = base
|
result = base
|
||||||
else:
|
else:
|
||||||
result = self._unit_convert(height, base=base)
|
result = self._unit_convert(height, base=base)
|
||||||
|
if isinstance(result, (unicode, str, bytes)):
|
||||||
|
result = self._profile.height
|
||||||
self._height = result
|
self._height = result
|
||||||
return self._height
|
return self._height
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@ class PluginWidget(Widget, Ui_Form):
|
|||||||
|
|
||||||
def __init__(self, parent, get_option, get_help, db=None, book_id=None):
|
def __init__(self, parent, get_option, get_help, db=None, book_id=None):
|
||||||
Widget.__init__(self, parent, 'epub_output',
|
Widget.__init__(self, parent, 'epub_output',
|
||||||
['dont_split_on_page_breaks', 'flow_size', 'no_default_epub_cover']
|
['dont_split_on_page_breaks', 'flow_size',
|
||||||
|
'no_default_epub_cover', 'no_svg_cover']
|
||||||
)
|
)
|
||||||
self.db, self.book_id = db, book_id
|
self.db, self.book_id = db, book_id
|
||||||
self.initialize_options(get_option, get_help, db, book_id)
|
self.initialize_options(get_option, get_help, db, book_id)
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Split files &larger than:</string>
|
<string>Split files &larger than:</string>
|
||||||
@ -31,7 +31,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QSpinBox" name="opt_flow_size">
|
<widget class="QSpinBox" name="opt_flow_size">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> KB</string>
|
<string> KB</string>
|
||||||
@ -47,7 +47,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="4" column="0">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -67,6 +67,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="opt_no_svg_cover">
|
||||||
|
<property name="text">
|
||||||
|
<string>No &SVG cover</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -8,7 +8,7 @@ import re
|
|||||||
|
|
||||||
from PyQt4.QtCore import SIGNAL, Qt
|
from PyQt4.QtCore import SIGNAL, Qt
|
||||||
from PyQt4.QtGui import QDialog, QWidget, QDialogButtonBox, QFileDialog, \
|
from PyQt4.QtGui import QDialog, QWidget, QDialogButtonBox, QFileDialog, \
|
||||||
QBrush, QSyntaxHighlighter, QTextCharFormat
|
QBrush, QTextCursor, QTextEdit
|
||||||
|
|
||||||
from calibre.gui2.convert.regex_builder_ui import Ui_RegexBuilder
|
from calibre.gui2.convert.regex_builder_ui import Ui_RegexBuilder
|
||||||
from calibre.gui2.convert.xexp_edit_ui import Ui_Form as Ui_Edit
|
from calibre.gui2.convert.xexp_edit_ui import Ui_Form as Ui_Edit
|
||||||
@ -17,31 +17,6 @@ from calibre.gui2 import error_dialog
|
|||||||
from calibre.ebooks.oeb.iterator import EbookIterator
|
from calibre.ebooks.oeb.iterator import EbookIterator
|
||||||
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
||||||
|
|
||||||
class RegexHighlighter(QSyntaxHighlighter):
|
|
||||||
|
|
||||||
def __init__(self, *args):
|
|
||||||
QSyntaxHighlighter.__init__(self, *args)
|
|
||||||
|
|
||||||
self.regex = u''
|
|
||||||
|
|
||||||
def update_regex(self, regex):
|
|
||||||
self.regex = regex
|
|
||||||
self.rehighlight()
|
|
||||||
|
|
||||||
def highlightBlock(self, text):
|
|
||||||
valid_regex = True
|
|
||||||
text = qstring_to_unicode(text)
|
|
||||||
format = QTextCharFormat()
|
|
||||||
format.setBackground(QBrush(Qt.yellow))
|
|
||||||
|
|
||||||
if self.regex:
|
|
||||||
try:
|
|
||||||
for mo in re.finditer(self.regex, text):
|
|
||||||
self.setFormat(mo.start(), mo.end() - mo.start(), format)
|
|
||||||
except:
|
|
||||||
valid_regex = False
|
|
||||||
self.emit(SIGNAL('regex_valid(PyQt_PyObject)'), valid_regex)
|
|
||||||
|
|
||||||
class RegexBuilder(QDialog, Ui_RegexBuilder):
|
class RegexBuilder(QDialog, Ui_RegexBuilder):
|
||||||
|
|
||||||
def __init__(self, db, book_id, regex, *args):
|
def __init__(self, db, book_id, regex, *args):
|
||||||
@ -49,9 +24,7 @@ class RegexBuilder(QDialog, Ui_RegexBuilder):
|
|||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.regex.setText(regex)
|
self.regex.setText(regex)
|
||||||
self.regex_valid(True)
|
self.regex_valid()
|
||||||
self.highlighter = RegexHighlighter(self.preview.document())
|
|
||||||
self.highlighter.update_regex(regex)
|
|
||||||
|
|
||||||
if not db or not book_id:
|
if not db or not book_id:
|
||||||
self.button_box.addButton(QDialogButtonBox.Open)
|
self.button_box.addButton(QDialogButtonBox.Open)
|
||||||
@ -62,7 +35,7 @@ class RegexBuilder(QDialog, Ui_RegexBuilder):
|
|||||||
self.connect(self.regex, SIGNAL('textChanged(QString)'), self.regex_valid)
|
self.connect(self.regex, SIGNAL('textChanged(QString)'), self.regex_valid)
|
||||||
self.connect(self.test, SIGNAL('clicked()'), self.do_test)
|
self.connect(self.test, SIGNAL('clicked()'), self.do_test)
|
||||||
|
|
||||||
def regex_valid(self, valid):
|
def regex_valid(self):
|
||||||
regex = qstring_to_unicode(self.regex.text())
|
regex = qstring_to_unicode(self.regex.text())
|
||||||
if regex:
|
if regex:
|
||||||
try:
|
try:
|
||||||
@ -70,11 +43,29 @@ class RegexBuilder(QDialog, Ui_RegexBuilder):
|
|||||||
self.regex.setStyleSheet('QLineEdit { color: black; background-color: rgba(0,255,0,20%); }')
|
self.regex.setStyleSheet('QLineEdit { color: black; background-color: rgba(0,255,0,20%); }')
|
||||||
except:
|
except:
|
||||||
self.regex.setStyleSheet('QLineEdit { color: black; background-color: rgb(255,0,0,20%); }')
|
self.regex.setStyleSheet('QLineEdit { color: black; background-color: rgb(255,0,0,20%); }')
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
self.regex.setStyleSheet('QLineEdit { color: black; background-color: white; }')
|
self.regex.setStyleSheet('QLineEdit { color: black; background-color: white; }')
|
||||||
|
return True
|
||||||
|
|
||||||
def do_test(self):
|
def do_test(self):
|
||||||
self.highlighter.update_regex(qstring_to_unicode(self.regex.text()))
|
selections = []
|
||||||
|
if self.regex_valid():
|
||||||
|
text = qstring_to_unicode(self.preview.toPlainText())
|
||||||
|
regex = qstring_to_unicode(self.regex.text())
|
||||||
|
|
||||||
|
try:
|
||||||
|
for match in re.finditer(regex, text):
|
||||||
|
cursor = QTextCursor(self.preview.document())
|
||||||
|
cursor.setPosition(match.start(), QTextCursor.MoveAnchor)
|
||||||
|
cursor.setPosition(match.end(), QTextCursor.KeepAnchor)
|
||||||
|
sel = QTextEdit.ExtraSelection()
|
||||||
|
sel.cursor = cursor
|
||||||
|
sel.format.setBackground(QBrush(Qt.yellow))
|
||||||
|
selections.append(sel)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.preview.setExtraSelections(selections)
|
||||||
|
|
||||||
def select_format(self, db, book_id):
|
def select_format(self, db, book_id):
|
||||||
format = None
|
format = None
|
||||||
|
@ -350,7 +350,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
|
|
||||||
self.view_menu = QMenu()
|
self.view_menu = QMenu()
|
||||||
self.view_menu.addAction(_('View'))
|
self.view_menu.addAction(_('View'))
|
||||||
self.view_menu.addAction(_('View specific format'))
|
ac = self.view_menu.addAction(_('View specific format'))
|
||||||
|
ac.setShortcut(Qt.AltModifier+Qt.Key_V)
|
||||||
self.action_view.setMenu(self.view_menu)
|
self.action_view.setMenu(self.view_menu)
|
||||||
|
|
||||||
self.delete_menu = QMenu()
|
self.delete_menu = QMenu()
|
||||||
|
@ -394,13 +394,14 @@ class Document(QWebPage):
|
|||||||
return self.mainFrame().contentsSize().width() # offsetWidth gives inaccurate results
|
return self.mainFrame().contentsSize().width() # offsetWidth gives inaccurate results
|
||||||
|
|
||||||
def set_bottom_padding(self, amount):
|
def set_bottom_padding(self, amount):
|
||||||
padding = '%dpx'%amount
|
body = self.mainFrame().documentElement().findFirst('body')
|
||||||
try:
|
if body.isNull():
|
||||||
old_padding = unicode(self.javascript('$("body").css("padding-bottom")').toString())
|
return
|
||||||
except:
|
old_padding = unicode(body.styleProperty('padding-bottom',
|
||||||
old_padding = ''
|
body.ComputedStyle)).strip()
|
||||||
|
padding = u'%dpx'%amount
|
||||||
if old_padding != padding:
|
if old_padding != padding:
|
||||||
self.javascript('$("body").css("padding-bottom", "%s")' % padding)
|
body.setStyleProperty('padding-bottom', padding + ' !important')
|
||||||
|
|
||||||
|
|
||||||
class EntityDeclarationProcessor(object):
|
class EntityDeclarationProcessor(object):
|
||||||
@ -423,7 +424,7 @@ class DocumentView(QWebView):
|
|||||||
QWebView.__init__(self, *args)
|
QWebView.__init__(self, *args)
|
||||||
self.debug_javascript = False
|
self.debug_javascript = False
|
||||||
self.shortcuts = Shortcuts(SHORTCUTS, 'shortcuts/viewer')
|
self.shortcuts = Shortcuts(SHORTCUTS, 'shortcuts/viewer')
|
||||||
self.self_closing_pat = re.compile(r'<([a-z]+)\s+([^>]+)/>',
|
self.self_closing_pat = re.compile(r'<([a-z1-6]+)\s+([^>]+)/>',
|
||||||
re.IGNORECASE)
|
re.IGNORECASE)
|
||||||
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
||||||
self._size_hint = QSize(510, 680)
|
self._size_hint = QSize(510, 680)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user