Port use of QVariant in the viewer, the viewer now basically works

This commit is contained in:
Kovid Goyal 2014-04-22 14:44:47 +05:30
parent f6bdc450a8
commit b052f6ed68
8 changed files with 58 additions and 52 deletions

View File

@ -34,7 +34,9 @@ def all_py_files():
def detect_qvariant(): def detect_qvariant():
count = 0 count = 0
pat = re.compile(b'|'.join(br'QVariant NONE toInt toBool toString\(\) toPyObject canConvert toBitArray toByteArray toHash toFloat toMap toLine toPoint toReal toRect toTime toUInt toUrl'.split())) # noqa pat = re.compile(b'|'.join(br'QVariant NONE toInt toBool toString\(\) toPyObject canConvert toBitArray toByteArray toHash toFloat toMap toLine toPoint toReal toRect toTime toUInt toUrl'.split())) # noqa
exclusions = {} exclusions = {
'src/calibre/gui2/viewer/gestures.py': {'toPoint'},
}
for path in all_py_files(): for path in all_py_files():
if os.path.basename(path) in { if os.path.basename(path) in {
'BeautifulSoup.py', 'icu.py', 'smtp.py', 'Zeroconf.py', 'date.py', 'apsw_shell.py', } or 'pylrs' in path: 'BeautifulSoup.py', 'icu.py', 'smtp.py', 'Zeroconf.py', 'date.py', 'apsw_shell.py', } or 'pylrs' in path:

View File

@ -10,9 +10,9 @@ from functools import partial
from PyQt5.Qt import QAbstractListModel, Qt, QKeySequence, QListView, \ from PyQt5.Qt import QAbstractListModel, Qt, QKeySequence, QListView, \
QHBoxLayout, QWidget, QApplication, QStyledItemDelegate, QStyle, \ QHBoxLayout, QWidget, QApplication, QStyledItemDelegate, QStyle, \
QVariant, QTextDocument, QRectF, QFrame, QSize, QFont, QKeyEvent QTextDocument, QRectF, QFrame, QSize, QFont, QKeyEvent
from calibre.gui2 import NONE, error_dialog from calibre.gui2 import error_dialog
from calibre.utils.config import XMLConfig from calibre.utils.config import XMLConfig
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
from calibre.gui2.shortcuts_ui import Ui_Frame from calibre.gui2.shortcuts_ui import Ui_Frame
@ -72,13 +72,13 @@ class Customize(QFrame, Ui_Frame):
font = QFont() font = QFont()
button.setFont(font) button.setFont(font)
sequence = QKeySequence(code|(int(ev.modifiers())&~Qt.KeypadModifier)) sequence = QKeySequence(code|(int(ev.modifiers())&~Qt.KeypadModifier))
button.setText(sequence.toString()) button.setText(sequence.toString(QKeySequence.NativeText))
self.capture = 0 self.capture = 0
setattr(self, 'shortcut%d'%which, sequence) setattr(self, 'shortcut%d'%which, sequence)
dup_desc = self.dup_check(sequence, self.key) dup_desc = self.dup_check(sequence, self.key)
if dup_desc is not None: if dup_desc is not None:
error_dialog(self, _('Already assigned'), error_dialog(self, _('Already assigned'),
unicode(sequence.toString()) + ' ' + unicode(sequence.toString(QKeySequence.NativeText)) + ' ' +
_('already assigned to') + ' ' + dup_desc, show=True) _('already assigned to') + ' ' + dup_desc, show=True)
self.clear_clicked(which=which) self.clear_clicked(which=which)
@ -92,7 +92,7 @@ class Delegate(QStyledItemDelegate):
def to_doc(self, index): def to_doc(self, index):
doc = QTextDocument() doc = QTextDocument()
doc.setHtml(index.data().toString()) doc.setHtml(index.data())
return doc return doc
def editing_done(self, editor, hint): def editing_done(self, editor, hint):
@ -128,14 +128,14 @@ class Delegate(QStyledItemDelegate):
return w return w
def setEditorData(self, editor, index): def setEditorData(self, editor, index):
defs = index.data(DEFAULTS).toPyObject() defs = index.data(DEFAULTS)
defs = _(' or ').join([unicode(x.toString(x.NativeText)) for x in defs]) defs = _(' or ').join([unicode(x.toString(x.NativeText)) for x in defs])
editor.key = unicode(index.data(KEY).toString()) editor.key = unicode(index.data(KEY))
editor.default_shortcuts.setText(_('&Default') + ': %s' % defs) editor.default_shortcuts.setText(_('&Default') + ': %s' % defs)
editor.default_shortcuts.setChecked(True) editor.default_shortcuts.setChecked(True)
editor.header.setText('<b>%s: %s</b>'%(_('Customize shortcuts for'), editor.header.setText('<b>%s: %s</b>'%(_('Customize shortcuts for'),
unicode(index.data(DESCRIPTION).toString()))) unicode(index.data(DESCRIPTION))))
custom = index.data(CUSTOM).toPyObject() custom = index.data(CUSTOM)
if custom: if custom:
editor.custom.setChecked(True) editor.custom.setChecked(True)
for x in (0, 1): for x in (0, 1):
@ -212,38 +212,36 @@ class Shortcuts(QAbstractListModel):
return [unicode(x.toString(x.NativeText)) for x in return [unicode(x.toString(x.NativeText)) for x in
self.get_sequences(key)] self.get_sequences(key)]
def data(self, index, role): def data(self, index, role):
row = index.row() row = index.row()
if row < 0 or row >= len(self.order): if row < 0 or row >= len(self.order):
return NONE return None
key = self.order[row] key = self.order[row]
if role == Qt.DisplayRole: if role == Qt.DisplayRole:
return QVariant(self.TEMPLATE.format(self.descriptions[key], return self.TEMPLATE.format(self.descriptions[key],
_(' or ').join(self.get_shortcuts(key)), _('Keys'))) _(' or ').join(self.get_shortcuts(key)), _('Keys'))
if role == Qt.ToolTipRole: if role == Qt.ToolTipRole:
return QVariant(_('Double click to change')) return _('Double click to change')
if role == DEFAULTS: if role == DEFAULTS:
return QVariant(self.sequences[key]) return self.sequences[key]
if role == DESCRIPTION: if role == DESCRIPTION:
return QVariant(self.descriptions[key]) return self.descriptions[key]
if role == CUSTOM: if role == CUSTOM:
if key in self.custom: if key in self.custom:
return QVariant(self.custom[key]) return self.custom[key]
else: else:
return QVariant([]) return []
if role == KEY: if role == KEY:
return QVariant(key) return key
return NONE return None
def set_data(self, index, custom): def set_data(self, index, custom):
key = self.order[index.row()] key = self.order[index.row()]
if custom: if custom:
self.custom[key] = [unicode(x.toString()) for x in custom] self.custom[key] = [unicode(x.toString(QKeySequence.PortableText)) for x in custom]
elif key in self.custom: elif key in self.custom:
del self.custom[key] del self.custom[key]
def flags(self, index): def flags(self, index):
if not index.isValid(): if not index.isValid():
return Qt.ItemIsEnabled return Qt.ItemIsEnabled

View File

@ -145,7 +145,7 @@ class BookmarkManager(QWidget):
def item_changed(self, item): def item_changed(self, item):
self.bookmarks_list.blockSignals(True) self.bookmarks_list.blockSignals(True)
title = unicode(item.data(Qt.DisplayRole).toString()) title = unicode(item.data(Qt.DisplayRole))
if not title: if not title:
title = _('Unknown') title = _('Unknown')
item.setData(Qt.DisplayRole, title) item.setData(Qt.DisplayRole, title)
@ -186,7 +186,7 @@ class BookmarkManager(QWidget):
return bytearray(cPickle.dumps(bm, -1)) return bytearray(cPickle.dumps(bm, -1))
def item_to_bm(self, item): def item_to_bm(self, item):
return cPickle.loads(bytes(item.data(Qt.UserRole).toPyObject())) return cPickle.loads(bytes(item.data(Qt.UserRole)))
def get_bookmarks(self): def get_bookmarks(self):
return list(self) return list(self)

View File

@ -10,7 +10,7 @@ __docformat__ = 'restructuredtext en'
import zipfile import zipfile
from functools import partial from functools import partial
from PyQt5.Qt import (QFont, QVariant, QDialog, Qt, QColor, QColorDialog, from PyQt5.Qt import (QFont, QDialog, Qt, QColor, QColorDialog,
QMenu, QInputDialog) QMenu, QInputDialog)
from calibre.constants import iswindows, isxp from calibre.constants import iswindows, isxp
@ -120,7 +120,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
for i in range(len(pats)): for i in range(len(pats)):
pmap[names[i]] = pats[i] pmap[names[i]] = pats[i]
for x in sorted(names): for x in sorted(names):
self.hyphenate_default_lang.addItem(x, QVariant(pmap[x])) self.hyphenate_default_lang.addItem(x, pmap[x])
self.hyphenate_pats = pats self.hyphenate_pats = pats
self.hyphenate_names = names self.hyphenate_names = names
p = self.tabs.widget(1) p = self.tabs.widget(1)
@ -304,7 +304,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
float(self.opt_font_mag_step.value())/100.) float(self.opt_font_mag_step.value())/100.)
idx = self.hyphenate_default_lang.currentIndex() idx = self.hyphenate_default_lang.currentIndex()
c.set('hyphenate_default_lang', c.set('hyphenate_default_lang',
str(self.hyphenate_default_lang.itemData(idx).toString())) self.hyphenate_default_lang.itemData(idx))
c.set('line_scrolling_stops_on_pagebreaks', c.set('line_scrolling_stops_on_pagebreaks',
self.opt_line_scrolling_stops_on_pagebreaks.isChecked()) self.opt_line_scrolling_stops_on_pagebreaks.isChecked())
c.set('fullscreen_clock', self.opt_fullscreen_clock.isChecked()) c.set('fullscreen_clock', self.opt_fullscreen_clock.isChecked())

View File

@ -145,7 +145,7 @@ class Document(QWebPage): # {{{
q = unicode(q) q = unicode(q)
hyphenated_q = self.javascript( hyphenated_q = self.javascript(
'hyphenate_text(%s, "%s")' % (json.dumps(q, ensure_ascii=False), self.loaded_lang), typ='string') 'hyphenate_text(%s, "%s")' % (json.dumps(q, ensure_ascii=False), self.loaded_lang), typ='string')
if QWebPage.findText(self, hyphenated_q, flags): if hyphenated_q and QWebPage.findText(self, hyphenated_q, flags):
return True return True
return QWebPage.findText(self, q, flags) return QWebPage.findText(self, q, flags)
@ -351,17 +351,19 @@ class Document(QWebPage): # {{{
def javascript(self, string, typ=None): def javascript(self, string, typ=None):
ans = self.mainFrame().evaluateJavaScript(string) ans = self.mainFrame().evaluateJavaScript(string)
if typ in {'int', int}: if typ in {'int', int}:
ans = ans.toInt() try:
if ans[1]: return int(ans)
return ans[0] except (TypeError, ValueError):
return 0 return 0
if typ in {'float', float}: if typ in {'float', float}:
ans = ans.toReal() try:
return ans[0] if ans[1] else 0.0 return float(ans)
except (TypeError, ValueError):
return 0.0
if typ == 'string': if typ == 'string':
return unicode(ans.toString()) return ans or u''
if typ in {bool, 'bool'}: if typ in {bool, 'bool'}:
return ans.toBool() return bool(ans)
return ans return ans
def javaScriptConsoleMessage(self, msg, lineno, msgid): def javaScriptConsoleMessage(self, msg, lineno, msgid):
@ -386,8 +388,9 @@ class Document(QWebPage): # {{{
self.javascript('window.paged_display.jump_to_anchor("%s")'%anchor) self.javascript('window.paged_display.jump_to_anchor("%s")'%anchor)
def element_ypos(self, elem): def element_ypos(self, elem):
ans, ok = elem.evaluateJavaScript('$(this).offset().top').toInt() try:
if not ok: ans = int(elem.evaluateJavaScript('$(this).offset().top'))
except (TypeError, ValueError):
raise ValueError('No ypos found') raise ValueError('No ypos found')
return ans return ans
@ -482,7 +485,7 @@ class Document(QWebPage): # {{{
def extract_node(self): def extract_node(self):
return unicode(self.mainFrame().evaluateJavaScript( return unicode(self.mainFrame().evaluateJavaScript(
'window.calibre_extract.extract()').toString()) 'window.calibre_extract.extract()'))
# }}} # }}}

View File

@ -98,7 +98,7 @@ class ImageView(QDialog):
if geom is not None: if geom is not None:
self.restoreGeometry(geom) self.restoreGeometry(geom)
try: try:
self.current_image_name = unicode(self.current_url.toString()).rpartition('/')[-1] self.current_image_name = unicode(self.current_url.toString(QUrl.None)).rpartition('/')[-1]
except AttributeError: except AttributeError:
self.current_image_name = self.current_url self.current_image_name = self.current_url
title = _('View Image: %s')%self.current_image_name title = _('View Image: %s')%self.current_image_name

View File

@ -16,8 +16,7 @@ class PagePosition(object):
@property @property
def viewport_cfi(self): def viewport_cfi(self):
ans = None ans = self.document.mainFrame().evaluateJavaScript('''
res = self.document.mainFrame().evaluateJavaScript('''
ans = 'undefined'; ans = 'undefined';
if (window.paged_display) { if (window.paged_display) {
ans = window.paged_display.current_cfi(); ans = window.paged_display.current_cfi();
@ -25,10 +24,8 @@ class PagePosition(object):
} }
ans; ans;
''') ''')
if res.isValid() and not res.isNull() and res.type() == res.String: if ans in {'', 'undefined'}:
c = unicode(res.toString()) ans = None
if c != 'undefined':
ans = c
return ans return ans
def scroll_to_cfi(self, cfi): def scroll_to_cfi(self, cfi):
@ -51,11 +48,13 @@ class PagePosition(object):
self.restore() self.restore()
def save(self, overwrite=True): def save(self, overwrite=True):
if not overwrite and self._cpos is not None: return if not overwrite and self._cpos is not None:
return
self._cpos = self.current_pos self._cpos = self.current_pos
def restore(self): def restore(self):
if self._cpos is None: return if self._cpos is None:
return
self.to_pos(self._cpos) self.to_pos(self._cpos)
self._cpos = None self._cpos = None

View File

@ -82,9 +82,13 @@ class Printing(QObject):
printer.newPage() printer.newPage()
first = False first = False
self.mf.render(painter) self.mf.render(painter)
nsl = evaljs('paged_display.next_screen_location()').toInt() try:
if not nsl[1] or nsl[0] <= 0: break nsl = int(evaljs('paged_display.next_screen_location()'))
evaljs('window.scrollTo(%d, 0)'%nsl[0]) except (TypeError, ValueError):
break
if nsl <= 0:
break
evaljs('window.scrollTo(%d, 0)'%nsl)
painter.end() painter.end()