mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-08-11 09:13:57 -04:00
Wire up open annotations button and add button to select book in calibre
This commit is contained in:
parent
b958361a18
commit
1f253580b5
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from PyQt5.Qt import Qt
|
||||||
|
|
||||||
from calibre.gui2.actions import InterfaceAction
|
from calibre.gui2.actions import InterfaceAction
|
||||||
|
|
||||||
@ -25,7 +26,19 @@ class BrowseAnnotationsAction(InterfaceAction):
|
|||||||
if self._browser is None:
|
if self._browser is None:
|
||||||
from calibre.gui2.library.annotations import AnnotationsBrowser
|
from calibre.gui2.library.annotations import AnnotationsBrowser
|
||||||
self._browser = AnnotationsBrowser(self.gui)
|
self._browser = AnnotationsBrowser(self.gui)
|
||||||
|
self._browser.show_book.connect(self.open_book, type=Qt.QueuedConnection)
|
||||||
|
self._browser.open_annotation.connect(self.open_annotation, type=Qt.QueuedConnection)
|
||||||
return self._browser
|
return self._browser
|
||||||
|
|
||||||
def show_browser(self):
|
def show_browser(self):
|
||||||
self.browser.show_dialog()
|
self.browser.show_dialog()
|
||||||
|
|
||||||
|
def library_changed(self, db):
|
||||||
|
if self._browser is not None:
|
||||||
|
self._browser.reinitialize()
|
||||||
|
|
||||||
|
def open_book(self, book_id, fmt):
|
||||||
|
self.gui.library_view.select_rows({book_id})
|
||||||
|
|
||||||
|
def open_annotation(self, book_id, fmt, cfi):
|
||||||
|
self.gui.iactions['View'].view_format_by_id(book_id, fmt, open_at=cfi)
|
||||||
|
@ -107,13 +107,13 @@ class ViewAction(InterfaceAction):
|
|||||||
'annotations_map': annotations_map,
|
'annotations_map': annotations_map,
|
||||||
}
|
}
|
||||||
|
|
||||||
def view_format_by_id(self, id_, format):
|
def view_format_by_id(self, id_, format, open_at=None):
|
||||||
db = self.gui.current_db
|
db = self.gui.current_db
|
||||||
fmt_path = db.format_abspath(id_, format,
|
fmt_path = db.format_abspath(id_, format,
|
||||||
index_is_id=True)
|
index_is_id=True)
|
||||||
if fmt_path:
|
if fmt_path:
|
||||||
title = db.title(id_, index_is_id=True)
|
title = db.title(id_, index_is_id=True)
|
||||||
self._view_file(fmt_path, calibre_book_data=self.calibre_book_data(id_, format))
|
self._view_file(fmt_path, calibre_book_data=self.calibre_book_data(id_, format), open_at=open_at)
|
||||||
self.update_history([(id_, title)])
|
self.update_history([(id_, title)])
|
||||||
|
|
||||||
def book_downloaded_for_viewing(self, job):
|
def book_downloaded_for_viewing(self, job):
|
||||||
@ -122,7 +122,7 @@ class ViewAction(InterfaceAction):
|
|||||||
return
|
return
|
||||||
self._view_file(job.result)
|
self._view_file(job.result)
|
||||||
|
|
||||||
def _launch_viewer(self, name=None, viewer='ebook-viewer', internal=True, calibre_book_data=None):
|
def _launch_viewer(self, name=None, viewer='ebook-viewer', internal=True, calibre_book_data=None, open_at=None):
|
||||||
self.gui.setCursor(Qt.BusyCursor)
|
self.gui.setCursor(Qt.BusyCursor)
|
||||||
try:
|
try:
|
||||||
if internal:
|
if internal:
|
||||||
@ -132,6 +132,8 @@ class ViewAction(InterfaceAction):
|
|||||||
|
|
||||||
if name is not None:
|
if name is not None:
|
||||||
args.append(name)
|
args.append(name)
|
||||||
|
if open_at is not None:
|
||||||
|
args.append('--open-at=' + open_at)
|
||||||
if calibre_book_data is not None:
|
if calibre_book_data is not None:
|
||||||
with PersistentTemporaryFile('.json') as ptf:
|
with PersistentTemporaryFile('.json') as ptf:
|
||||||
ptf.write(as_bytes(json.dumps(calibre_book_data)))
|
ptf.write(as_bytes(json.dumps(calibre_book_data)))
|
||||||
@ -162,12 +164,12 @@ class ViewAction(InterfaceAction):
|
|||||||
finally:
|
finally:
|
||||||
self.gui.unsetCursor()
|
self.gui.unsetCursor()
|
||||||
|
|
||||||
def _view_file(self, name, calibre_book_data=None):
|
def _view_file(self, name, calibre_book_data=None, open_at=None):
|
||||||
ext = os.path.splitext(name)[1].upper().replace('.',
|
ext = os.path.splitext(name)[1].upper().replace('.',
|
||||||
'').replace('ORIGINAL_', '')
|
'').replace('ORIGINAL_', '')
|
||||||
viewer = 'lrfviewer' if ext == 'LRF' else 'ebook-viewer'
|
viewer = 'lrfviewer' if ext == 'LRF' else 'ebook-viewer'
|
||||||
internal = self.force_internal_viewer or ext in config['internally_viewed_formats']
|
internal = self.force_internal_viewer or ext in config['internally_viewed_formats'] or open_at is not None
|
||||||
self._launch_viewer(name, viewer, internal, calibre_book_data=calibre_book_data)
|
self._launch_viewer(name, viewer, internal, calibre_book_data=calibre_book_data, open_at=open_at)
|
||||||
|
|
||||||
def view_specific_format(self, triggered):
|
def view_specific_format(self, triggered):
|
||||||
rows = list(self.gui.library_view.selectionModel().selectedRows())
|
rows = list(self.gui.library_view.selectionModel().selectedRows())
|
||||||
|
@ -63,7 +63,7 @@ class AnnotsResultsDelegate(ResultsDelegate):
|
|||||||
class ResultsList(QTreeWidget):
|
class ResultsList(QTreeWidget):
|
||||||
|
|
||||||
current_result_changed = pyqtSignal(object)
|
current_result_changed = pyqtSignal(object)
|
||||||
open_annotation = pyqtSignal(object)
|
open_annotation = pyqtSignal(object, object, object)
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QTreeWidget.__init__(self, parent)
|
QTreeWidget.__init__(self, parent)
|
||||||
@ -80,7 +80,7 @@ class ResultsList(QTreeWidget):
|
|||||||
def item_activated(self, item):
|
def item_activated(self, item):
|
||||||
r = item.data(0, Qt.UserRole)
|
r = item.data(0, Qt.UserRole)
|
||||||
if isinstance(r, dict):
|
if isinstance(r, dict):
|
||||||
self.open_annotation.emit(r['annotation'])
|
self.open_annotation.emit(r['book_id'], r['format'], r['annotation'])
|
||||||
|
|
||||||
def set_results(self, results):
|
def set_results(self, results):
|
||||||
self.clear()
|
self.clear()
|
||||||
@ -206,7 +206,7 @@ class Restrictions(QWidget):
|
|||||||
class BrowsePanel(QWidget):
|
class BrowsePanel(QWidget):
|
||||||
|
|
||||||
current_result_changed = pyqtSignal(object)
|
current_result_changed = pyqtSignal(object)
|
||||||
open_annotation = pyqtSignal(object)
|
open_annotation = pyqtSignal(object, object, object)
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
@ -251,6 +251,7 @@ class BrowsePanel(QWidget):
|
|||||||
db = current_db()
|
db = current_db()
|
||||||
self.search_box.setFocus(Qt.OtherFocusReason)
|
self.search_box.setFocus(Qt.OtherFocusReason)
|
||||||
self.restrictions.re_initialize(db)
|
self.restrictions.re_initialize(db)
|
||||||
|
self.cleared()
|
||||||
|
|
||||||
def sizeHint(self):
|
def sizeHint(self):
|
||||||
return QSize(450, 600)
|
return QSize(450, 600)
|
||||||
@ -316,7 +317,8 @@ class Details(QTextBrowser):
|
|||||||
|
|
||||||
class DetailsPanel(QWidget):
|
class DetailsPanel(QWidget):
|
||||||
|
|
||||||
open_annotation = pyqtSignal(object)
|
open_annotation = pyqtSignal(object, object, object)
|
||||||
|
show_book = pyqtSignal(object, object)
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
@ -324,14 +326,29 @@ class DetailsPanel(QWidget):
|
|||||||
l = QVBoxLayout(self)
|
l = QVBoxLayout(self)
|
||||||
self.text_browser = tb = Details(self)
|
self.text_browser = tb = Details(self)
|
||||||
l.addWidget(tb)
|
l.addWidget(tb)
|
||||||
|
|
||||||
|
h = QHBoxLayout()
|
||||||
|
l.addLayout(h)
|
||||||
self.open_button = ob = QPushButton(QIcon(I('viewer.png')), _('Open in viewer'), self)
|
self.open_button = ob = QPushButton(QIcon(I('viewer.png')), _('Open in viewer'), self)
|
||||||
|
ob.setToolTip(_('Open the book at this annotation in the calibre viewer'))
|
||||||
ob.clicked.connect(self.open_result)
|
ob.clicked.connect(self.open_result)
|
||||||
l.addWidget(ob)
|
h.addWidget(ob)
|
||||||
|
|
||||||
|
self.library_button = lb = QPushButton(QIcon(I('lt.png')), _('Show in calibre'), self)
|
||||||
|
lb.setToolTip(_('Show this book in the main calibre book list'))
|
||||||
|
lb.clicked.connect(self.show_in_library)
|
||||||
|
h.addWidget(lb)
|
||||||
|
|
||||||
self.show_result(None)
|
self.show_result(None)
|
||||||
|
|
||||||
def open_result(self):
|
def open_result(self):
|
||||||
if self.current_result is not None:
|
if self.current_result is not None:
|
||||||
self.open_annotation.emit(self.current_result['annotation'])
|
r = self.current_result
|
||||||
|
self.open_annotation.emit(r['book_id'], r['format'], r['annotation'])
|
||||||
|
|
||||||
|
def show_in_library(self):
|
||||||
|
if self.current_result is not None:
|
||||||
|
self.show_book.emit(self.current_result['book_id'], self.current_result['format'])
|
||||||
|
|
||||||
def sizeHint(self):
|
def sizeHint(self):
|
||||||
return QSize(450, 600)
|
return QSize(450, 600)
|
||||||
@ -341,9 +358,11 @@ class DetailsPanel(QWidget):
|
|||||||
if r is None:
|
if r is None:
|
||||||
self.text_browser.setVisible(False)
|
self.text_browser.setVisible(False)
|
||||||
self.open_button.setVisible(False)
|
self.open_button.setVisible(False)
|
||||||
|
self.library_button.setVisible(False)
|
||||||
return
|
return
|
||||||
self.text_browser.setVisible(True)
|
self.text_browser.setVisible(True)
|
||||||
self.open_button.setVisible(True)
|
self.open_button.setVisible(True)
|
||||||
|
self.library_button.setVisible(True)
|
||||||
db = current_db()
|
db = current_db()
|
||||||
book_id = r['book_id']
|
book_id = r['book_id']
|
||||||
title, authors = db.field_for('title', book_id), db.field_for('authors', book_id)
|
title, authors = db.field_for('title', book_id), db.field_for('authors', book_id)
|
||||||
@ -385,20 +404,21 @@ class DetailsPanel(QWidget):
|
|||||||
|
|
||||||
class AnnotationsBrowser(Dialog):
|
class AnnotationsBrowser(Dialog):
|
||||||
|
|
||||||
open_annotation = pyqtSignal(object)
|
open_annotation = pyqtSignal(object, object, object)
|
||||||
|
show_book = pyqtSignal(object, object)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
Dialog.__init__(self, _('Annotations browser'), 'library-annotations-browser-1', parent=parent)
|
Dialog.__init__(self, _('Annotations browser'), 'library-annotations-browser-1', parent=parent)
|
||||||
self.setAttribute(Qt.WA_DeleteOnClose, False)
|
self.setAttribute(Qt.WA_DeleteOnClose, False)
|
||||||
|
|
||||||
def do_open_annotation(self, annot):
|
def do_open_annotation(self, book_id, fmt, annot):
|
||||||
atype = annot['type']
|
atype = annot['type']
|
||||||
if atype == 'bookmark':
|
if atype == 'bookmark':
|
||||||
if annot['pos_type'] == 'epubcfi':
|
if annot['pos_type'] == 'epubcfi':
|
||||||
self.open_annotation.emit(annot['pos'])
|
self.open_annotation.emit(book_id, fmt, annot['pos'])
|
||||||
elif atype == 'highlight':
|
elif atype == 'highlight':
|
||||||
x = 2 * (annot['spine_index'] + 1)
|
x = 2 * (annot['spine_index'] + 1)
|
||||||
self.open_annotation.emit('epubcfi(/{}{})'.format(x, annot['start_cfi']))
|
self.open_annotation.emit(book_id, fmt, 'epubcfi(/{}{})'.format(x, annot['start_cfi']))
|
||||||
|
|
||||||
def keyPressEvent(self, ev):
|
def keyPressEvent(self, ev):
|
||||||
if ev.key() not in (Qt.Key_Enter, Qt.Key_Return):
|
if ev.key() not in (Qt.Key_Enter, Qt.Key_Return):
|
||||||
@ -425,6 +445,7 @@ class AnnotationsBrowser(Dialog):
|
|||||||
self.details_panel = dp = DetailsPanel(self)
|
self.details_panel = dp = DetailsPanel(self)
|
||||||
s.addWidget(dp)
|
s.addWidget(dp)
|
||||||
dp.open_annotation.connect(self.do_open_annotation)
|
dp.open_annotation.connect(self.do_open_annotation)
|
||||||
|
dp.show_book.connect(self.show_book)
|
||||||
bp.current_result_changed.connect(dp.show_result)
|
bp.current_result_changed.connect(dp.show_result)
|
||||||
|
|
||||||
h = QHBoxLayout()
|
h = QHBoxLayout()
|
||||||
@ -432,19 +453,22 @@ class AnnotationsBrowser(Dialog):
|
|||||||
h.addWidget(us), h.addStretch(10), h.addWidget(self.bb)
|
h.addWidget(us), h.addStretch(10), h.addWidget(self.bb)
|
||||||
|
|
||||||
def show_dialog(self):
|
def show_dialog(self):
|
||||||
self.browse_panel.re_initialize()
|
|
||||||
if self.parent() is None:
|
if self.parent() is None:
|
||||||
self.exec_()
|
self.exec_()
|
||||||
else:
|
else:
|
||||||
self.show()
|
self.show()
|
||||||
self.raise_()
|
self.raise_()
|
||||||
|
|
||||||
|
def reinitialize(self):
|
||||||
|
self.browse_panel.re_initialize()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from calibre.library import db
|
from calibre.library import db
|
||||||
app = Application([])
|
app = Application([])
|
||||||
current_db.ans = db(os.path.expanduser('~/test library'))
|
current_db.ans = db(os.path.expanduser('~/test library'))
|
||||||
br = AnnotationsBrowser()
|
br = AnnotationsBrowser()
|
||||||
|
br.reinitialize()
|
||||||
br.show_dialog()
|
br.show_dialog()
|
||||||
del br
|
del br
|
||||||
del app
|
del app
|
||||||
|
Loading…
x
Reference in New Issue
Block a user