%PDF- %PDF-
Direktori : /lib/calibre/calibre/gui2/dialogs/ |
Current File : //lib/calibre/calibre/gui2/dialogs/duplicates.py |
#!/usr/bin/env python3 __license__ = 'GPL v3' __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>' __docformat__ = 'restructuredtext en' import os.path from qt.core import ( QDialog, QGridLayout, QIcon, QLabel, QTreeWidget, QTreeWidgetItem, Qt, QFont, QDialogButtonBox, QApplication) from calibre.gui2 import gprefs from calibre.ebooks.metadata import authors_to_string from calibre.utils.icu import primary_sort_key class DuplicatesQuestion(QDialog): def __init__(self, db, duplicates, parent=None): QDialog.__init__(self, parent) self.l = l = QGridLayout() self.setLayout(l) t = ngettext('Duplicate found', 'duplicates found', len(duplicates)) if len(duplicates) > 1: t = '%d %s' % (len(duplicates), t) self.setWindowTitle(t) self.i = i = QIcon(I('dialog_question.png')) self.setWindowIcon(i) self.l1 = l1 = QLabel() self.l2 = l2 = QLabel(_( 'Books with the same titles as the following already ' 'exist in calibre. Select which books you want added anyway.')) l2.setWordWrap(True) l1.setPixmap(i.pixmap(128, 128)) l.addWidget(l1, 0, 0) l.addWidget(l2, 0, 1) self.dup_list = dl = QTreeWidget(self) l.addWidget(dl, 1, 0, 1, 2) dl.setHeaderHidden(True) dl.addTopLevelItems(list(self.process_duplicates(db, duplicates))) dl.expandAll() dl.setIndentation(30) self.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok|QDialogButtonBox.StandardButton.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb, 2, 0, 1, 2) l.setColumnStretch(1, 10) self.ab = ab = bb.addButton(_('Select &all'), QDialogButtonBox.ButtonRole.ActionRole) ab.clicked.connect(self.select_all), ab.setIcon(QIcon(I('plus.png'))) self.nb = ab = bb.addButton(_('Select &none'), QDialogButtonBox.ButtonRole.ActionRole) ab.clicked.connect(self.select_none), ab.setIcon(QIcon(I('minus.png'))) self.cb = cb = bb.addButton(_('&Copy to clipboard'), QDialogButtonBox.ButtonRole.ActionRole) cb.setIcon(QIcon(I('edit-copy.png'))) cb.clicked.connect(self.copy_to_clipboard) self.resize(self.sizeHint()) geom = gprefs.get('duplicates-question-dialog-geometry', None) if geom is not None: QApplication.instance().safe_restore_geometry(self, geom) self.exec() def copy_to_clipboard(self): QApplication.clipboard().setText(self.as_text) def select_all(self): for i in range(self.dup_list.topLevelItemCount()): x = self.dup_list.topLevelItem(i) x.setCheckState(0, Qt.CheckState.Checked) def select_none(self): for i in range(self.dup_list.topLevelItemCount()): x = self.dup_list.topLevelItem(i) x.setCheckState(0, Qt.CheckState.Unchecked) def reject(self): self.save_geometry() self.select_none() QDialog.reject(self) def accept(self): self.save_geometry() QDialog.accept(self) def save_geometry(self): gprefs.set('duplicates-question-dialog-geometry', bytearray(self.saveGeometry())) def process_duplicates(self, db, duplicates): ta = _('%(title)s by %(author)s [%(formats)s]') bf = QFont(self.dup_list.font()) bf.setBold(True) itf = QFont(self.dup_list.font()) itf.setItalic(True) for mi, cover, formats in duplicates: # formats is a list of file paths # Grab just the extension and display to the user # Based only off the file name, no file type tests are done. incoming_formats = ', '.join(os.path.splitext(path)[-1].replace('.', '').upper() for path in formats) item = QTreeWidgetItem([ta%dict( title=mi.title, author=mi.format_field('authors')[1], formats=incoming_formats)] , 0) item.setCheckState(0, Qt.CheckState.Checked) item.setFlags(Qt.ItemFlag.ItemIsEnabled|Qt.ItemFlag.ItemIsUserCheckable) item.setData(0, Qt.ItemDataRole.FontRole, bf) item.setData(0, Qt.ItemDataRole.UserRole, (mi, cover, formats)) matching_books = db.books_with_same_title(mi) def add_child(text): c = QTreeWidgetItem([text], 1) c.setFlags(Qt.ItemFlag.ItemIsEnabled) item.addChild(c) return c add_child(_('Already in calibre:')).setData(0, Qt.ItemDataRole.FontRole, itf) author_text = {} for book_id in matching_books: author_text[book_id] = authors_to_string([a.replace('|', ',') for a in (db.authors(book_id, index_is_id=True) or '').split(',')]) def key(x): return primary_sort_key(str(author_text[x])) for book_id in sorted(matching_books, key=key): add_child(ta%dict( title=db.title(book_id, index_is_id=True), author=author_text[book_id], formats=db.formats(book_id, index_is_id=True, verify_formats=False))) add_child('') yield item @property def duplicates(self): for i in range(self.dup_list.topLevelItemCount()): x = self.dup_list.topLevelItem(i) if x.checkState(0) == Qt.CheckState.Checked: yield x.data(0, Qt.ItemDataRole.UserRole) @property def as_text(self): entries = [] for i in range(self.dup_list.topLevelItemCount()): x = self.dup_list.topLevelItem(i) check = '✓' if x.checkState(0) == Qt.CheckState.Checked else '✗' title = f'{check} {str(x.text(0))}' dups = [] for child in (x.child(j) for j in range(x.childCount())): dups.append('\t' + str(child.text(0))) entries.append(title + '\n' + '\n'.join(dups)) return '\n\n'.join(entries) if __name__ == '__main__': from calibre.ebooks.metadata.book.base import Metadata as M from calibre.library import db app = QApplication([]) db = db() d = DuplicatesQuestion(db, [(M('Life of Pi', ['Yann Martel']), None, None), (M('Heirs of the blade', ['Adrian Tchaikovsky']), None, None)]) print(tuple(d.duplicates))