def load(self, highlights): s = self.style() icon_size = s.pixelMetric(s.PM_SmallIconSize, None, self) dpr = self.devicePixelRatioF() is_dark = is_dark_theme() self.clear() self.uuid_map = {} highlights = (h for h in highlights if not h.get('removed') and h.get('highlighted_text')) section_map = defaultdict(list) section_tt_map = {} for h in self.sorted_highlights(highlights): tfam = h.get('toc_family_titles') or () if tfam: tsec = tfam[0] lsec = tfam[-1] else: tsec = h.get('top_level_section_title') lsec = h.get('lowest_level_section_title') sec = lsec or tsec or _('Unknown') if len(tfam) > 1: lines = [] for i, node in enumerate(tfam): lines.append('\xa0\xa0' * i + '➤ ' + node) tt = ngettext('Table of Contents section:', 'Table of Contents sections:', len(lines)) tt += '\n' + '\n'.join(lines) section_tt_map[sec] = tt section_map[sec].append(h) for secnum, (sec, items) in enumerate(section_map.items()): section = QTreeWidgetItem([sec], 1) section.setFlags(Qt.ItemIsEnabled) section.setFont(0, self.section_font) tt = section_tt_map.get(sec) if tt: section.setToolTip(0, tt) self.addTopLevelItem(section) section.setExpanded(True) for itemnum, h in enumerate(items): txt = h.get('highlighted_text') txt = txt.replace('\n', ' ') if len(txt) > 100: txt = txt[:100] + '…' item = QTreeWidgetItem(section, [txt], 2) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemNeverHasChildren) item.setData(0, Qt.UserRole, h) try: dec = decoration_for_style(self.palette(), h.get('style') or {}, icon_size, dpr, is_dark) except Exception: import traceback traceback.print_exc() dec = None if dec is None: dec = self.default_decoration item.setData(0, Qt.DecorationRole, dec) self.uuid_map[h['uuid']] = secnum, itemnum self.num_of_items += 1
def add_result(self, result): section_title = _('Unknown') section_id = -1 toc_nodes = getattr(result, 'toc_nodes', ()) or () if toc_nodes: section_title = toc_nodes[-1].get('title') or _('Unknown') section_id = toc_nodes[-1].get('id') if section_id is None: section_id = -1 section_key = section_id section = self.section_map.get(section_key) if section is None: section = QTreeWidgetItem([section_title], 1) section.setFlags(Qt.ItemIsEnabled) section.setFont(0, self.section_font) lines = [] for i, node in enumerate(toc_nodes): lines.append('\xa0\xa0' * i + '➤ ' + (node.get('title') or _('Unknown'))) tt = ngettext('Table of Contents section:', 'Table of Contents sections:', len(lines)) tt += '\n' + '\n'.join(lines) section.setToolTip(0, tt) self.section_map[section_key] = section self.addTopLevelItem(section) section.setExpanded(True) item = QTreeWidgetItem(section, [' '], 2) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemNeverHasChildren) item.setData(0, Qt.UserRole, result) item.setData(0, Qt.UserRole + 1, len(self.search_results)) item.setIcon(0, self.blank_icon) self.item_map[len(self.search_results)] = item self.search_results.append(result) n = self.number_of_results self.count_changed.emit(n) return n
def create_item(self, f, parent): name = f.name ans = QTreeWidgetItem(parent, [name]) ans.setData(0, Qt.UserRole, '/'.join(f.full_path[1:])) ans.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) ans.setCheckState(0, Qt.Unchecked if self.dev.is_folder_ignored(f.storage_id, f.full_path[1:]) else Qt.Checked) ans.setData(0, Qt.DecorationRole, file_icon_provider().icon_from_ext('dir')) return ans
def create_item(name, linear=None): imt = container.mime_map.get(name, guess_type(name)) icat = get_category(name, imt) category = 'text' if linear is not None else ({'text':'misc'}.get(icat, icat)) item = QTreeWidgetItem(self.categories['text' if linear is not None else category], 1) flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable if category == 'text': flags |= Qt.ItemIsDragEnabled if name not in cannot_be_renamed: flags |= Qt.ItemIsEditable item.setFlags(flags) item.setStatusTip(0, _('Full path: ') + name) item.setData(0, NAME_ROLE, name) item.setData(0, CATEGORY_ROLE, category) item.setData(0, LINEAR_ROLE, bool(linear)) item.setData(0, MIME_ROLE, imt) set_display_name(name, item) tooltips = [] emblems = [] if name in {cover_page_name, cover_image_name}: emblems.append('default_cover.png') tooltips.append(_('This file is the cover %s for this book') % (_('image') if name == cover_image_name else _('page'))) if name in container.opf_name: emblems.append('metadata.png') tooltips.append(_('This file contains all the metadata and book structure information')) if imt == ncx_mime or name in nav_items: emblems.append('toc.png') tooltips.append(_('This file contains the metadata table of contents')) if name not in manifested_names and not container.ok_to_be_unmanifested(name): emblems.append('dialog_question.png') tooltips.append(_('This file is not listed in the book manifest')) if linear is False: emblems.append('arrow-down.png') tooltips.append(_('This file is marked as non-linear in the spine\nDrag it to the top to make it linear')) if linear is None and icat == 'text': # Text item outside spine emblems.append('dialog_warning.png') tooltips.append(_('This file is a text file that is not referenced in the spine')) if category == 'text' and name in processed: # Duplicate entry in spine emblems.append('dialog_error.png') tooltips.append(_('This file occurs more than once in the spine')) if category == 'fonts' and name.rpartition('.')[-1].lower() in ('ttf', 'otf'): fname = self.get_font_family_name(name) if fname: tooltips.append(fname) else: emblems.append('dialog_error.png') tooltips.append(_('Not a valid font')) render_emblems(item, emblems) if tooltips: item.setData(0, Qt.ToolTipRole, '\n'.join(tooltips)) return item
def unserialize_node(dict_node, parent): n = QTreeWidgetItem(parent) n.setData(0, Qt.DisplayRole, dict_node['title']) n.setData(0, Qt.UserRole, dict_node['toc_node']) n.setFlags(NODE_FLAGS) n.setData(0, Qt.DecorationRole, dict_node['icon']) n.setData(0, Qt.ToolTipRole, dict_node['tooltip']) self.update_status_tip(n) n.setExpanded(dict_node['is_expanded']) n.setSelected(dict_node['is_selected']) for c in dict_node['children']: unserialize_node(c, n)
def create_item(name, linear=None): imt = container.mime_map.get(name, guess_type(name)) icat = get_category(name, imt) category = "text" if linear is not None else ({"text": "misc"}.get(icat, icat)) item = QTreeWidgetItem(self.categories["text" if linear is not None else category], 1) flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable if category == "text": flags |= Qt.ItemIsDragEnabled if name not in cannot_be_renamed: flags |= Qt.ItemIsEditable item.setFlags(flags) item.setStatusTip(0, _("Full path: ") + name) item.setData(0, NAME_ROLE, name) item.setData(0, CATEGORY_ROLE, category) item.setData(0, LINEAR_ROLE, bool(linear)) item.setData(0, MIME_ROLE, imt) set_display_name(name, item) tooltips = [] emblems = [] if name in {cover_page_name, cover_image_name}: emblems.append("default_cover.png") tooltips.append( _("This file is the cover %s for this book") % (_("image") if name == cover_image_name else _("page")) ) if name in container.opf_name: emblems.append("metadata.png") tooltips.append(_("This file contains all the metadata and book structure information")) if imt == ncx_mime or name in nav_items: emblems.append("toc.png") tooltips.append(_("This file contains the metadata table of contents")) if name not in manifested_names and not container.ok_to_be_unmanifested(name): emblems.append("dialog_question.png") tooltips.append(_("This file is not listed in the book manifest")) if linear is False: emblems.append("arrow-down.png") tooltips.append( _("This file is marked as non-linear in the spine\nDrag it to the top to make it linear") ) if linear is None and icat == "text": # Text item outside spine emblems.append("dialog_warning.png") tooltips.append(_("This file is a text file that is not referenced in the spine")) if category == "text" and name in processed: # Duplicate entry in spine emblems.append("dialog_error.png") tooltips.append(_("This file occurs more than once in the spine")) render_emblems(item, emblems) if tooltips: item.setData(0, Qt.ToolTipRole, "\n".join(tooltips)) return item
def add_result(self, result): section_title = _('Unknown') section_id = -1 toc_nodes = getattr(result, 'toc_nodes', ()) or () if toc_nodes: section_title = toc_nodes[-1].get('title') or _('Unknown') section_id = toc_nodes[-1].get('id') if section_id is None: section_id = -1 section_key = section_id section = self.section_map.get(section_key) spine_idx = getattr(result, 'spine_idx', -1) if section is None: section = QTreeWidgetItem([section_title], 1) section.setFlags(Qt.ItemFlag.ItemIsEnabled) section.setFont(0, self.section_font) section.setData(0, SPINE_IDX_ROLE, spine_idx) lines = [] for i, node in enumerate(toc_nodes): lines.append('\xa0\xa0' * i + '➤ ' + (node.get('title') or _('Unknown'))) if lines: tt = ngettext('Table of Contents section:', 'Table of Contents sections:', len(lines)) tt += '\n' + '\n'.join(lines) section.setToolTip(0, tt) self.section_map[section_key] = section for s in range(self.topLevelItemCount()): ti = self.topLevelItem(s) if ti.data(0, SPINE_IDX_ROLE) > spine_idx: self.insertTopLevelItem(s, section) break else: self.addTopLevelItem(section) section.setExpanded(True) item = QTreeWidgetItem(section, [' '], 2) item.setFlags(Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemNeverHasChildren) item.setData(0, SEARCH_RESULT_ROLE, result) item.setData(0, RESULT_NUMBER_ROLE, len(self.search_results)) item.setData(0, SPINE_IDX_ROLE, spine_idx) if isinstance(result, SearchResult): tt = '<p>…' + escape(result.before, False) + '<b>' + escape( result.text, False) + '</b>' + escape(result.after, False) + '…' item.setData(0, Qt.ItemDataRole.ToolTipRole, tt) item.setIcon(0, self.blank_icon) self.item_map[len(self.search_results)] = item self.search_results.append(result) n = self.number_of_results self.count_changed.emit(n) return n
def setMeshGroups(self, groups): """ Sets the mesh group list Arguments: groups (dict[int, list[tuple[str, int]]]): Mesh groups info. """ self._list.clear() grp_types = sorted(groups.keys()) for typ in grp_types: names = groups[typ] if not names: continue title = MeshElemType.value2str(typ) item = QTreeWidgetItem(self._list, [title]) for name, size in names: sub_item = QTreeWidgetItem(item, [name, str(size)]) sub_item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) sub_item.setCheckState(0, Qt.Unchecked) sub_item.setTextAlignment(1, Qt.AlignRight) self._list.expandAll()
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.Checked) item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable) item.setData(0, Qt.FontRole, bf) item.setData(0, Qt.UserRole, (mi, cover, formats)) matching_books = db.books_with_same_title(mi) def add_child(text): c = QTreeWidgetItem([text], 1) c.setFlags(Qt.ItemIsEnabled) item.addChild(c) return c add_child(_('Already in calibre:')).setData(0, Qt.FontRole, itf) for book_id in matching_books: aut = [a.replace('|', ',') for a in (db.authors(book_id, index_is_id=True) or '').split(',')] add_child(ta%dict( title=db.title(book_id, index_is_id=True), author=authors_to_string(aut), formats=db.formats(book_id, index_is_id=True, verify_formats=False))) add_child('') yield item
def add_child(text): c = QTreeWidgetItem([text], 1) c.setFlags(Qt.ItemIsEnabled) item.addChild(c) return c