mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 07:20:44 -04:00
Port use of QVariant in the viewer, the viewer now basically works
This commit is contained in:
parent
f6bdc450a8
commit
b052f6ed68
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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())
|
||||||
|
@ -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()'))
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user