Allow comparing the ORIGINAL_EPUB version of a book to the EPUB version by right clicking on the ORIGINAL_EPUB format in the book details panel.

This commit is contained in:
Kovid Goyal 2014-01-29 14:34:35 +05:30
parent 4fadc7dacc
commit 0d5cf9d78c
4 changed files with 53 additions and 9 deletions

View File

@ -671,8 +671,9 @@ class Cache(object):
''' '''
Return absolute path to the ebook file of format `format` Return absolute path to the ebook file of format `format`
Currently used only in calibredb list, the viewer, edit book and the Currently used only in calibredb list, the viewer, edit book,
catalogs (via get_data_as_dict()). compare_format to original format and the catalogs (via
get_data_as_dict()).
Apart from the viewer, I don't believe any of the others do any file Apart from the viewer, I don't believe any of the others do any file
I/O with the results of this call. I/O with the results of this call.

View File

@ -413,6 +413,7 @@ class BookInfo(QWebView):
remove_format = pyqtSignal(int, object) remove_format = pyqtSignal(int, object)
save_format = pyqtSignal(int, object) save_format = pyqtSignal(int, object)
restore_format = pyqtSignal(int, object) restore_format = pyqtSignal(int, object)
compare_format = pyqtSignal(int, object)
copy_link = pyqtSignal(object) copy_link = pyqtSignal(object)
manage_author = pyqtSignal(object) manage_author = pyqtSignal(object)
@ -433,7 +434,7 @@ class BookInfo(QWebView):
for x, icon in [ for x, icon in [
('remove_format', 'trash.png'), ('save_format', 'save.png'), ('remove_format', 'trash.png'), ('save_format', 'save.png'),
('restore_format', 'edit-undo.png'), ('copy_link','edit-copy.png'), ('restore_format', 'edit-undo.png'), ('copy_link','edit-copy.png'),
('manage_author', 'user_profile.png')]: ('manage_author', 'user_profile.png'), ('compare_format', 'diff.png')]:
ac = QAction(QIcon(I(icon)), '', self) ac = QAction(QIcon(I(icon)), '', self)
ac.current_fmt = None ac.current_fmt = None
ac.current_url = None ac.current_url = None
@ -458,6 +459,9 @@ class BookInfo(QWebView):
def restore_format_triggerred(self): def restore_format_triggerred(self):
self.context_action_triggered('restore_format') self.context_action_triggered('restore_format')
def compare_format_triggerred(self):
self.context_action_triggered('compare_format')
def copy_link_triggerred(self): def copy_link_triggerred(self):
self.context_action_triggered('copy_link') self.context_action_triggered('copy_link')
@ -517,20 +521,31 @@ class BookInfo(QWebView):
if url.startswith('format:'): if url.startswith('format:'):
parts = url.split(':') parts = url.split(':')
try: try:
book_id, fmt = int(parts[1]), parts[2] book_id, fmt = int(parts[1]), parts[2].upper()
except: except:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
else: else:
from calibre.gui2.ui import get_gui
db = get_gui().current_db.new_api
ofmt = fmt.upper() if fmt.startswith('ORIGINAL_') else 'ORIGINAL_' + fmt
fmts = {x.upper() for x in db.formats(book_id)}
for a, t in [('remove', _('Delete the %s format')), for a, t in [('remove', _('Delete the %s format')),
('save', _('Save the %s format to disk')), ('save', _('Save the %s format to disk')),
('restore', _('Restore the %s format')), ('restore', _('Restore the %s format')),
('compare', ''),
]: ]:
if a == 'restore' and not fmt.upper().startswith('ORIGINAL_'): if a == 'restore' and not fmt.startswith('ORIGINAL_'):
continue continue
if a == 'compare':
if ofmt not in fmts:
continue
t = _('Compare to the %s format') % (fmt[9:] if fmt.startswith('ORIGINAL_') else ofmt)
else:
t = t % fmt
ac = getattr(self, '%s_format_action'%a) ac = getattr(self, '%s_format_action'%a)
ac.current_fmt = (book_id, fmt) ac.current_fmt = (book_id, fmt)
ac.setText(t%parts[2]) ac.setText(t)
menu.addAction(ac) menu.addAction(ac)
if len(menu.actions()) > 0: if len(menu.actions()) > 0:
menu.exec_(ev.globalPos()) menu.exec_(ev.globalPos())
@ -635,6 +650,7 @@ class BookDetails(QWidget): # {{{
remove_specific_format = pyqtSignal(int, object) remove_specific_format = pyqtSignal(int, object)
save_specific_format = pyqtSignal(int, object) save_specific_format = pyqtSignal(int, object)
restore_specific_format = pyqtSignal(int, object) restore_specific_format = pyqtSignal(int, object)
compare_specific_format = pyqtSignal(int, object)
copy_link = pyqtSignal(object) copy_link = pyqtSignal(object)
remote_file_dropped = pyqtSignal(object, object) remote_file_dropped = pyqtSignal(object, object)
files_dropped = pyqtSignal(object, object) files_dropped = pyqtSignal(object, object)
@ -706,6 +722,7 @@ class BookDetails(QWidget): # {{{
self.book_info.remove_format.connect(self.remove_specific_format) self.book_info.remove_format.connect(self.remove_specific_format)
self.book_info.save_format.connect(self.save_specific_format) self.book_info.save_format.connect(self.save_specific_format)
self.book_info.restore_format.connect(self.restore_specific_format) self.book_info.restore_format.connect(self.restore_specific_format)
self.book_info.compare_format.connect(self.compare_specific_format)
self.book_info.copy_link.connect(self.copy_link) self.book_info.copy_link.connect(self.copy_link)
self.book_info.manage_author.connect(self.manage_author) self.book_info.manage_author.connect(self.manage_author)
self.setCursor(Qt.PointingHandCursor) self.setCursor(Qt.PointingHandCursor)

View File

@ -449,6 +449,7 @@ class LayoutMixin(object): # {{{
self.book_details.view_device_book.connect( self.book_details.view_device_book.connect(
self.iactions['View'].view_device_book) self.iactions['View'].view_device_book)
self.book_details.manage_author.connect(lambda author:self.do_author_sort_edit(self, author, select_sort=False, select_link=False)) self.book_details.manage_author.connect(lambda author:self.do_author_sort_edit(self, author, select_sort=False, select_link=False))
self.book_details.compare_specific_format.connect(self.compare_format)
m = self.library_view.model() m = self.library_view.model()
if m.rowCount(None) > 0: if m.rowCount(None) > 0:
@ -475,6 +476,18 @@ class LayoutMixin(object): # {{{
if url: if url:
QApplication.clipboard().setText(url) QApplication.clipboard().setText(url)
def compare_format(self, book_id, fmt):
db = self.current_db.new_api
ofmt = fmt
if fmt.startswith('ORIGINAL_'):
fmt = fmt.partition('_')[-1]
else:
ofmt = 'ORIGINAL_' + fmt
path1, path2 = db.format_abspath(book_id, ofmt), db.format_abspath(book_id, fmt)
from calibre.gui2.tweak_book.diff.main import compare_books
compare_books(path1, path2, parent=self, revert_msg=_('Restore %s') % ofmt, revert_callback=partial(
self.iactions['Remove Books'].restore_format, book_id, ofmt))
def save_layout_state(self): def save_layout_state(self):
for x in ('library', 'memory', 'card_a', 'card_b'): for x in ('library', 'memory', 'card_a', 'card_b'):
getattr(self, x+'_view').save_state() getattr(self, x+'_view').save_state()

View File

@ -11,7 +11,7 @@ from functools import partial
from PyQt4.Qt import ( from PyQt4.Qt import (
QGridLayout, QToolButton, QIcon, QRadioButton, QMenu, QApplication, Qt, QGridLayout, QToolButton, QIcon, QRadioButton, QMenu, QApplication, Qt,
QSize, QWidget, QLabel, QStackedLayout, QPainter, QRect, QVBoxLayout, QSize, QWidget, QLabel, QStackedLayout, QPainter, QRect, QVBoxLayout,
QCursor, QEventLoop, QKeySequence, pyqtSignal) QCursor, QEventLoop, QKeySequence, pyqtSignal, QTimer)
from calibre.ebooks.oeb.polish.container import Container from calibre.ebooks.oeb.polish.container import Container
from calibre.gui2 import info_dialog from calibre.gui2 import info_dialog
@ -107,8 +107,8 @@ def container_diff(left, right):
left_names -= samefile_names left_names -= samefile_names
right_names -= samefile_names right_names -= samefile_names
cache, changed_names, renamed_names, removed_names, added_names = changed_files( cache, changed_names, renamed_names, removed_names, added_names = changed_files(
left_names, right_names, left.raw_data, right.raw_data) left_names, right_names, left.raw_data, right.raw_data)
def syntax(container, name): def syntax(container, name):
mt = container.mime_map[name] mt = container.mime_map[name]
@ -141,6 +141,7 @@ class Diff(Dialog):
return QSize(int(0.9 * geom.width()), int(0.8 * geom.height())) return QSize(int(0.9 * geom.width()), int(0.8 * geom.height()))
def setup_ui(self): def setup_ui(self):
self.setWindowIcon(QIcon(I('diff.png')))
self.stacks = st = QStackedLayout(self) self.stacks = st = QStackedLayout(self)
self.busy = BusyWidget(self) self.busy = BusyWidget(self)
self.w = QWidget(self) self.w = QWidget(self)
@ -300,6 +301,18 @@ class Diff(Dialog):
return return
return Dialog.keyPressEvent(self, ev) return Dialog.keyPressEvent(self, ev)
def compare_books(path1, path2, revert_msg=None, revert_callback=None, parent=None):
d = Diff(parent=parent, revert_button_msg=revert_msg)
if revert_msg is not None:
d.revert_requested.connect(revert_callback)
QTimer.singleShot(0, partial(d.ebook_diff, path1, path2))
d.exec_()
try:
d.revert_requested.disconnect()
except:
pass
d.break_cycles()
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
app = QApplication([]) app = QApplication([])