diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_icon_rules.py b/src/calibre/gui2/preferences/look_feel_tabs/tb_icon_rules.py index ec35da6d8a..7c5f6f2296 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/tb_icon_rules.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_icon_rules.py @@ -17,18 +17,24 @@ from calibre.gui2 import gprefs from calibre.gui2.preferences import ConfigTabWidget, ConfigWidgetBase from calibre.gui2.preferences.look_feel_tabs.tb_icon_rules_ui import Ui_Form -CATEGORY_COLUMN = 0 -VALUE_COLUMN = 1 -ICON_COLUMN = 2 -FOR_CHILDREN_COLUMN = 3 -DELECTED_COLUMN = 4 +DELETED_COLUMN = 0 +CATEGORY_COLUMN = 1 +VALUE_COLUMN = 2 +ICON_COLUMN = 3 +FOR_CHILDREN_COLUMN = 4 +HEADER_SECTION_COUNT = 5 class CategoryTableWidgetItem(QTableWidgetItem): - def __init__(self, txt): + def __init__(self, lookup_name, category_icons, deleted_item, field_metadata): + self._lookup_name = lookup_name + txt = field_metadata[lookup_name]['name'] + f' ({lookup_name})' super().__init__(txt) self._is_deleted = False + self.setIcon(category_icons[lookup_name]) + self._txt = txt + self._deleted_item = deleted_item @property def is_deleted(self): @@ -37,6 +43,59 @@ class CategoryTableWidgetItem(QTableWidgetItem): @is_deleted.setter def is_deleted(self, to_what): self._is_deleted = to_what + if to_what: + self._deleted_item.setIcon(QIcon.cached_icon('trash.png')) + else: + self._deleted_item.setIcon(QIcon()) + + @property + def lookup_name(self): + return self._lookup_name + + +class ValueTableWidgetItem(QTableWidgetItem): + + def __init__(self, txt): + self._key = txt + is_template = txt == TEMPLATE_ICON_INDICATOR + super().__init__(_('{template}') if is_template else txt) + self.setIcon(QIcon.cached_icon('debug.png' if is_template else 'icon_choose.png')) + + @property + def real_value(self): + return self._key + + +class IconFileTableWidgetItem(QTableWidgetItem): + + def __init__(self, icon_file, value): + self._key = icon_file + is_template = value == TEMPLATE_ICON_INDICATOR + super().__init__(icon_file) + self.setToolTip(icon_file) + if is_template: + self.setIcon(QIcon.cached_icon('blank.png')) + else: + p = os.path.join(config_dir, 'tb_icons', icon_file) + if os.path.exists(p): + icon = QIcon.ic(p) + self.setIcon(icon) + else: + self.setIcon(QIcon.cached_icon('dialog_error.png')) + self.setToolTip(icon_file + '\n' + _("This icon file doesn't exist")) + + +class ChildrenTableWidgetItem(QTableWidgetItem): + + def __init__(self, txt, for_child): + super().__init__(txt) + if for_child is None: + icon = QIcon() + elif for_child: + icon = QIcon.cached_icon('ok.png') + else: + icon = QIcon.cached_icon('list_remove.png') + self.setIcon(QIcon.cached_icon(icon)) class TbIconRulesTab(ConfigTabWidget, Ui_Form): @@ -49,12 +108,26 @@ class TbIconRulesTab(ConfigTabWidget, Ui_Form): self.rules_table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) self.rules_table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) - self.rules_table.setColumnCount(4) - self.rules_table.setHorizontalHeaderLabels((_('Category'), _('Value'), _('Icon file or template'), - _('Use for children'))) + self.rules_table.setColumnCount(HEADER_SECTION_COUNT) + self.rules_table.setHorizontalHeaderLabels( + ('', _('Category'), _('Value'), _('Icon file or template'),_('For children'))) self.rules_table.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.rules_table.customContextMenuRequested.connect(self.show_context_menu) + for i in range(0, HEADER_SECTION_COUNT): + item = self.rules_table.horizontalHeaderItem(i) + if i == DELETED_COLUMN: + item.setIcon(QIcon.cached_icon('trash.png')) + item.setToolTip(_('Show this icon if the rule is deleted')) + elif i == CATEGORY_COLUMN: + item.setToolTip(_('The name of the category')) + elif i == VALUE_COLUMN: + item.setToolTip(_('The value in the category the rule is applied to')) + elif i == ICON_COLUMN: + item.setToolTip(_('The file name of the icon or the text of the template')) + elif i == FOR_CHILDREN_COLUMN: + item.setToolTip(_('Indicates whether the rule apples to child values')) + # Capture clicks on the horizontal header to sort the table columns hh = self.rules_table.horizontalHeader() hh.sectionResized.connect(self.table_column_resized) @@ -68,22 +141,26 @@ class TbIconRulesTab(ConfigTabWidget, Ui_Form): self.tb_icon_rules_groupbox.setContentsMargins(0, 0, 0, 0) self.tb_icon_rules_gridlayout.setContentsMargins(2, 2, 2, 2) + field_metadata = gui.current_db.field_metadata + category_icons = gui.tags_view.model().category_custom_icons v = gprefs['tags_browser_value_icons'] row = 0 for category,vdict in v.items(): for value in vdict: self.rules_table.setRowCount(row + 1) d = v[category][value] - self.rules_table.setItem(row, 0, CategoryTableWidgetItem(category)) - self.rules_table.setItem(row, 1, QTableWidgetItem(value)) - self.rules_table.setItem(row, 2, QTableWidgetItem(d[0])) + deleted_item = QTableWidgetItem(None) + self.rules_table.setItem(row, DELETED_COLUMN, deleted_item) + self.rules_table.setItem(row, CATEGORY_COLUMN, + CategoryTableWidgetItem(category, category_icons, deleted_item, field_metadata)) + self.rules_table.setItem(row, VALUE_COLUMN, ValueTableWidgetItem(value)) + self.rules_table.setItem(row, ICON_COLUMN, IconFileTableWidgetItem(d[0], value)) if value == TEMPLATE_ICON_INDICATOR: txt = '' else: txt = _('Yes') if d[1] else _('No') - item = QTableWidgetItem(txt) - item.setTextAlignment(Qt.AlignmentFlag.AlignCenter|Qt.AlignmentFlag.AlignVCenter) - self.rules_table.setItem(row, 3, item) + item = ChildrenTableWidgetItem(txt, None if value == TEMPLATE_ICON_INDICATOR else d[1]) + self.rules_table.setItem(row, FOR_CHILDREN_COLUMN, item) row += 1 self.category_order = 1 @@ -132,7 +209,6 @@ class TbIconRulesTab(ConfigTabWidget, Ui_Form): if idx.isValid(): item = self.rules_table.item(idx.row(), CATEGORY_COLUMN) item.is_deleted = True - item.setIcon(QIcon.ic('trash.png')) self.changed_signal.emit() def undo_delete(self): @@ -140,7 +216,6 @@ class TbIconRulesTab(ConfigTabWidget, Ui_Form): if idx.isValid(): item = self.rules_table.item(idx.row(), CATEGORY_COLUMN) item.is_deleted = False - item.setIcon(QIcon()) def table_column_resized(self, col, old, new): self.table_column_widths = [] @@ -184,7 +259,7 @@ class TbIconRulesTab(ConfigTabWidget, Ui_Form): for r in range(0, self.rules_table.rowCount()): cat_item = self.rules_table.item(r, CATEGORY_COLUMN) if cat_item.is_deleted: - val = self.rules_table.item(r, VALUE_COLUMN).text() + val = self.rules_table.item(r, VALUE_COLUMN).real_value if val != TEMPLATE_ICON_INDICATOR: icon_file = self.rules_table.item(r, ICON_COLUMN).text() path = os.path.join(config_dir, 'tb_icons', icon_file) @@ -192,7 +267,7 @@ class TbIconRulesTab(ConfigTabWidget, Ui_Form): os.remove(path) except: pass - v[cat_item.text()].pop(val, None) + v[cat_item.lookup_name].pop(val, None) # Remove categories with no rules for category in list(v.keys()): if len(v[category]) == 0: