Exemple #1
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.l = l = QGridLayout(self)
        self.setLayout(l)
        l.setContentsMargins(0, 0, 0, 0)

        self.is_visible = False
        self.view = QTreeWidget(self)
        self.delegate = Delegate(self.view)
        self.view.setItemDelegate(self.delegate)
        self.view.setHeaderHidden(True)
        self.view.setAnimated(True)
        self.view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.view.customContextMenuRequested.connect(self.show_context_menu,
                                                     type=Qt.QueuedConnection)
        self.view.itemActivated.connect(self.emit_navigate)
        self.view.itemPressed.connect(self.item_pressed)
        pi = plugins['progress_indicator'][0]
        if hasattr(pi, 'set_no_activate_on_click'):
            pi.set_no_activate_on_click(self.view)
        self.view.itemDoubleClicked.connect(self.emit_navigate)
        l.addWidget(self.view)

        self.refresh_action = QAction(QIcon(I('view-refresh.png')),
                                      _('&Refresh'), self)
        self.refresh_action.triggered.connect(self.build)
Exemple #2
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.l = l = QGridLayout(self)
        self.setLayout(l)
        l.setContentsMargins(0, 0, 0, 0)

        self.view = QTreeWidget(self)
        self.delegate = Delegate(self.view)
        self.view.setItemDelegate(self.delegate)
        self.view.setHeaderHidden(True)
        self.view.setAnimated(True)
        self.view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.view.customContextMenuRequested.connect(self.show_context_menu,
                                                     type=Qt.QueuedConnection)
        self.view.itemActivated.connect(self.emit_navigate)
        self.view.itemPressed.connect(self.item_pressed)
        pi = plugins['progress_indicator'][0]
        if hasattr(pi, 'set_no_activate_on_click'):
            pi.set_no_activate_on_click(self.view)
        self.view.itemDoubleClicked.connect(self.emit_navigate)
        l.addWidget(self.view)

        self.refresh_action = QAction(QIcon(I('view-refresh.png')),
                                      _('&Refresh'), self)
        self.refresh_action.triggered.connect(self.refresh)
        self.refresh_timer = t = QTimer(self)
        t.setInterval(1000), t.setSingleShot(True)
        t.timeout.connect(self.auto_refresh)
        self.toc_name = None
        self.currently_editing = None
Exemple #3
0
    def setup_ui(self):
        self.l = l = QVBoxLayout(self)
        self.setLayout(l)

        self.msg = m = QLabel(
            self.msg
            or _('Choose the folder into which the files will be placed'))
        l.addWidget(m)
        m.setWordWrap(True)

        self.folders = f = QTreeWidget(self)
        f.setHeaderHidden(True)
        f.itemDoubleClicked.connect(self.accept)
        l.addWidget(f)
        f.setContextMenuPolicy(Qt.CustomContextMenu)
        f.customContextMenuRequested.connect(self.show_context_menu)
        self.root = QTreeWidgetItem(f, ('/', ))

        def process(node, parent):
            parent.setIcon(0, QIcon(I('mimetypes/dir.png')))
            for child in sorted(node, key=sort_key):
                c = QTreeWidgetItem(parent, (child, ))
                process(node[child], c)

        process(create_folder_tree(current_container()), self.root)
        self.root.setSelected(True)
        f.expandAll()

        l.addWidget(self.bb)
Exemple #4
0
    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.Ok
                                        | QDialogButtonBox.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'), bb.ActionRole)
        ab.clicked.connect(self.select_all), ab.setIcon(QIcon(I('plus.png')))
        self.nb = ab = bb.addButton(_('Select &none'), bb.ActionRole)
        ab.clicked.connect(self.select_none), ab.setIcon(QIcon(I('minus.png')))
        self.cb = cb = bb.addButton(_('&Copy to clipboard'), bb.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:
            self.restoreGeometry(geom)
        self.exec_()
Exemple #5
0
    def __init__(self, db, duplicates, parent=None):
        QDialog.__init__(self, parent)
        self.l = l = QGridLayout()
        self.setLayout(l)
        self.setWindowTitle(_('Duplicates found!'))
        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.Ok
                                        | QDialogButtonBox.Cancel)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)
        l.addWidget(bb, 2, 0, 1, 2)
        self.ab = ab = bb.addButton(_('Select &all'), bb.ActionRole)
        ab.clicked.connect(self.select_all)
        self.nb = ab = bb.addButton(_('Select &none'), bb.ActionRole)
        ab.clicked.connect(self.select_none)

        self.resize(self.sizeHint())
        self.exec_()
    def __init__(self, parent, db):
        QDialog.__init__(self, parent)
        self.db = db

        self.setWindowTitle(_('Check Library -- Problems Found'))
        self.setWindowIcon(QIcon(I('debug.png')))

        self._tl = QHBoxLayout()
        self.setLayout(self._tl)
        self.splitter = QSplitter(self)
        self.left = QWidget(self)
        self.splitter.addWidget(self.left)
        self.helpw = QTextEdit(self)
        self.splitter.addWidget(self.helpw)
        self._tl.addWidget(self.splitter)
        self._layout = QVBoxLayout()
        self.left.setLayout(self._layout)
        self.helpw.setReadOnly(True)
        self.helpw.setText(
            _('''\
        <h1>Help</h1>

        <p>calibre stores the list of your books and their metadata in a
        database. The actual book files and covers are stored as normal
        files in the calibre library folder. The database contains a list of the files
        and covers belonging to each book entry. This tool checks that the
        actual files in the library folder on your computer match the
        information in the database.</p>

        <p>The result of each type of check is shown to the left. The various
        checks are:
        </p>
        <ul>
        <li><b>Invalid titles</b>: These are files and folders appearing
        in the library where books titles should, but that do not have the
        correct form to be a book title.</li>
        <li><b>Extra titles</b>: These are extra files in your calibre
        library that appear to be correctly-formed titles, but have no corresponding
        entries in the database</li>
        <li><b>Invalid authors</b>: These are files appearing
        in the library where only author folders should be.</li>
        <li><b>Extra authors</b>: These are folders in the
        calibre library that appear to be authors but that do not have entries
        in the database</li>
        <li><b>Missing book formats</b>: These are book formats that are in
        the database but have no corresponding format file in the book's folder.
        <li><b>Extra book formats</b>: These are book format files found in
        the book's folder but not in the database.
        <li><b>Unknown files in books</b>: These are extra files in the
        folder of each book that do not correspond to a known format or cover
        file.</li>
        <li><b>Missing cover files</b>: These represent books that are marked
        in the database as having covers but the actual cover files are
        missing.</li>
        <li><b>Cover files not in database</b>: These are books that have
        cover files but are marked as not having covers in the database.</li>
        <li><b>Folder raising exception</b>: These represent folders in the
        calibre library that could not be processed/understood by this
        tool.</li>
        </ul>

        <p>There are two kinds of automatic fixes possible: <i>Delete
        marked</i> and <i>Fix marked</i>.</p>
        <p><i>Delete marked</i> is used to remove extra files/folders/covers that
        have no entries in the database. Check the box next to the item you want
        to delete. Use with caution.</p>

        <p><i>Fix marked</i> is applicable only to covers and missing formats
        (the three lines marked 'fixable'). In the case of missing cover files,
        checking the fixable box and pushing this button will tell calibre that
        there is no cover for all of the books listed. Use this option if you
        are not going to restore the covers from a backup. In the case of extra
        cover files, checking the fixable box and pushing this button will tell
        calibre that the cover files it found are correct for all the books
        listed. Use this when you are not going to delete the file(s). In the
        case of missing formats, checking the fixable box and pushing this
        button will tell calibre that the formats are really gone. Use this if
        you are not going to restore the formats from a backup.</p>

        '''))

        self.log = QTreeWidget(self)
        self.log.itemChanged.connect(self.item_changed)
        self.log.itemExpanded.connect(self.item_expanded_or_collapsed)
        self.log.itemCollapsed.connect(self.item_expanded_or_collapsed)
        self._layout.addWidget(self.log)

        self.check_button = QPushButton(_('&Run the check again'))
        self.check_button.setDefault(False)
        self.check_button.clicked.connect(self.run_the_check)
        self.copy_button = QPushButton(_('Copy &to clipboard'))
        self.copy_button.setDefault(False)
        self.copy_button.clicked.connect(self.copy_to_clipboard)
        self.ok_button = QPushButton(_('&Done'))
        self.ok_button.setDefault(True)
        self.ok_button.clicked.connect(self.accept)
        self.delete_button = QPushButton(_('Delete &marked'))
        self.delete_button.setToolTip(
            _('Delete marked files (checked subitems)'))
        self.delete_button.setDefault(False)
        self.delete_button.clicked.connect(self.delete_marked)
        self.fix_button = QPushButton(_('&Fix marked'))
        self.fix_button.setDefault(False)
        self.fix_button.setEnabled(False)
        self.fix_button.setToolTip(
            _('Fix marked sections (checked fixable items)'))
        self.fix_button.clicked.connect(self.fix_items)
        self.bbox = QDialogButtonBox(self)
        self.bbox.addButton(self.check_button, QDialogButtonBox.ActionRole)
        self.bbox.addButton(self.delete_button, QDialogButtonBox.ActionRole)
        self.bbox.addButton(self.fix_button, QDialogButtonBox.ActionRole)
        self.bbox.addButton(self.copy_button, QDialogButtonBox.ActionRole)
        self.bbox.addButton(self.ok_button, QDialogButtonBox.AcceptRole)

        h = QHBoxLayout()
        ln = QLabel(_('Names to ignore:'))
        h.addWidget(ln)
        self.name_ignores = QLineEdit()
        self.name_ignores.setText(
            db.prefs.get('check_library_ignore_names', ''))
        self.name_ignores.setToolTip(
            _('Enter comma-separated standard file name wildcards, such as synctoy*.dat'
              ))
        ln.setBuddy(self.name_ignores)
        h.addWidget(self.name_ignores)
        le = QLabel(_('Extensions to ignore'))
        h.addWidget(le)
        self.ext_ignores = QLineEdit()
        self.ext_ignores.setText(
            db.prefs.get('check_library_ignore_extensions', ''))
        self.ext_ignores.setToolTip(
            _('Enter comma-separated extensions without a leading dot. Used only in book folders'
              ))
        le.setBuddy(self.ext_ignores)
        h.addWidget(self.ext_ignores)
        self._layout.addLayout(h)

        self._layout.addWidget(self.bbox)
        self.resize(950, 500)
        self.bbox.setEnabled(True)