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`
Currently used only in calibredb list, the viewer, edit book and the
catalogs (via get_data_as_dict()).
Currently used only in calibredb list, the viewer, edit book,
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
I/O with the results of this call.

View File

@ -413,6 +413,7 @@ class BookInfo(QWebView):
remove_format = pyqtSignal(int, object)
save_format = pyqtSignal(int, object)
restore_format = pyqtSignal(int, object)
compare_format = pyqtSignal(int, object)
copy_link = pyqtSignal(object)
manage_author = pyqtSignal(object)
@ -433,7 +434,7 @@ class BookInfo(QWebView):
for x, icon in [
('remove_format', 'trash.png'), ('save_format', 'save.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.current_fmt = None
ac.current_url = None
@ -458,6 +459,9 @@ class BookInfo(QWebView):
def restore_format_triggerred(self):
self.context_action_triggered('restore_format')
def compare_format_triggerred(self):
self.context_action_triggered('compare_format')
def copy_link_triggerred(self):
self.context_action_triggered('copy_link')
@ -517,20 +521,31 @@ class BookInfo(QWebView):
if url.startswith('format:'):
parts = url.split(':')
try:
book_id, fmt = int(parts[1]), parts[2]
book_id, fmt = int(parts[1]), parts[2].upper()
except:
import traceback
traceback.print_exc()
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')),
('save', _('Save the %s format to disk')),
('restore', _('Restore the %s format')),
('compare', ''),
]:
if a == 'restore' and not fmt.upper().startswith('ORIGINAL_'):
if a == 'restore' and not fmt.startswith('ORIGINAL_'):
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.current_fmt = (book_id, fmt)
ac.setText(t%parts[2])
ac.setText(t)
menu.addAction(ac)
if len(menu.actions()) > 0:
menu.exec_(ev.globalPos())
@ -635,6 +650,7 @@ class BookDetails(QWidget): # {{{
remove_specific_format = pyqtSignal(int, object)
save_specific_format = pyqtSignal(int, object)
restore_specific_format = pyqtSignal(int, object)
compare_specific_format = pyqtSignal(int, object)
copy_link = pyqtSignal(object)
remote_file_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.save_format.connect(self.save_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.manage_author.connect(self.manage_author)
self.setCursor(Qt.PointingHandCursor)

View File

@ -449,6 +449,7 @@ class LayoutMixin(object): # {{{
self.book_details.view_device_book.connect(
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.compare_specific_format.connect(self.compare_format)
m = self.library_view.model()
if m.rowCount(None) > 0:
@ -475,6 +476,18 @@ class LayoutMixin(object): # {{{
if 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):
for x in ('library', 'memory', 'card_a', 'card_b'):
getattr(self, x+'_view').save_state()

View File

@ -11,7 +11,7 @@ from functools import partial
from PyQt4.Qt import (
QGridLayout, QToolButton, QIcon, QRadioButton, QMenu, QApplication, Qt,
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.gui2 import info_dialog
@ -107,8 +107,8 @@ def container_diff(left, right):
left_names -= samefile_names
right_names -= samefile_names
cache, changed_names, renamed_names, removed_names, added_names = changed_files(
left_names, right_names, left.raw_data, right.raw_data)
cache, changed_names, renamed_names, removed_names, added_names = changed_files(
left_names, right_names, left.raw_data, right.raw_data)
def syntax(container, 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()))
def setup_ui(self):
self.setWindowIcon(QIcon(I('diff.png')))
self.stacks = st = QStackedLayout(self)
self.busy = BusyWidget(self)
self.w = QWidget(self)
@ -300,6 +301,18 @@ class Diff(Dialog):
return
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__':
import sys
app = QApplication([])