mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
e009faf4b2
@ -53,21 +53,38 @@ class StateTableWidgetItem(QTableWidgetItem):
|
||||
|
||||
class CategoryTableWidgetItem(QTableWidgetItem):
|
||||
|
||||
def __init__(self, lookup_name, category_icons, display_name, field_metadata, table):
|
||||
if in_library := (lookup_name in field_metadata):
|
||||
txt = display_name + f' ({lookup_name})'
|
||||
else:
|
||||
txt = display_name + ' (' + _('Not in library') + ')'
|
||||
super().__init__(txt)
|
||||
self._lookup_name = lookup_name
|
||||
def __init__(self, lookup_name, category_icons, field_metadata, table):
|
||||
super().__init__('')
|
||||
self._table = table
|
||||
self._category_icons = category_icons
|
||||
self._field_metadata = field_metadata
|
||||
self._is_deleted = False
|
||||
if in_library:
|
||||
self.setIcon(category_icons.get(lookup_name) or QIcon.cached_icon('column.png'))
|
||||
self._is_editable = False
|
||||
self._is_modified = False
|
||||
self._original_lookup_name = lookup_name
|
||||
self._original_in_library = lookup_name in self._field_metadata
|
||||
self.setText(lookup_name)
|
||||
|
||||
def setText(self, lookup_name):
|
||||
self._lookup_name = lookup_name
|
||||
if in_library := (self._lookup_name in self._field_metadata):
|
||||
txt = f"{self._field_metadata[self.lookup_name]['name']} ({self._lookup_name})"
|
||||
else:
|
||||
txt = f"{lookup_name} ({_('Not in library')})"
|
||||
super().setText(txt)
|
||||
self.setToolTip(txt)
|
||||
print('aaa', self._original_lookup_name, lookup_name)
|
||||
if self._original_lookup_name != lookup_name:
|
||||
self.setIcon(QIcon.cached_icon('modified.png'))
|
||||
elif in_library:
|
||||
self.setIcon(self.category_icons.get(self._lookup_name) or QIcon.cached_icon('column.png'))
|
||||
else:
|
||||
self.setIcon(QIcon.cached_icon('dialog_error.png'))
|
||||
if self._original_in_library:
|
||||
self.setFlags(self.flags() & ~Qt.ItemFlag.ItemIsEditable)
|
||||
else:
|
||||
self._is_editable = True
|
||||
self._txt = txt
|
||||
self.setFlags(self.flags() & ~Qt.ItemFlag.ItemIsEditable)
|
||||
|
||||
@property
|
||||
def is_deleted(self):
|
||||
@ -83,28 +100,59 @@ class CategoryTableWidgetItem(QTableWidgetItem):
|
||||
def lookup_name(self):
|
||||
return self._lookup_name
|
||||
|
||||
@property
|
||||
def original_lookup_name(self):
|
||||
return self._original_lookup_name
|
||||
|
||||
def undo(self):
|
||||
self.is_deleted = False
|
||||
|
||||
@property
|
||||
def is_editable(self):
|
||||
return self._is_editable
|
||||
|
||||
@property
|
||||
def is_modified(self):
|
||||
# Don't allow undo if the user selects a new column lookup key
|
||||
return False
|
||||
|
||||
@property
|
||||
def category_icons(self):
|
||||
return self._category_icons
|
||||
|
||||
|
||||
class CategoryTableItemDelegate(QStyledItemDelegate):
|
||||
|
||||
def __init__(self, parent, table, changed_signal):
|
||||
super().__init__(parent)
|
||||
self._table = table
|
||||
self._parent = parent
|
||||
self._changed_signal = changed_signal
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
editor = DelegateCB(parent)
|
||||
items = sorted(self._parent.all_values.keys(), key=sort_key)
|
||||
for text in items:
|
||||
editor.addItem(text)
|
||||
return editor
|
||||
|
||||
def setModelData(self, editor, model, index):
|
||||
val = editor.currentText() # We know val is a valid lookup name
|
||||
item = self._table.item(index.row(), index.column())
|
||||
item.setText(val)
|
||||
self._changed_signal.emit()
|
||||
|
||||
|
||||
class ValueTableWidgetItem(QTableWidgetItem):
|
||||
|
||||
def __init__(self, txt, table, all_values):
|
||||
self._original_text = txt
|
||||
self._table = table
|
||||
self._all_values = all_values
|
||||
self._is_template = is_template = txt == TEMPLATE_ICON_INDICATOR
|
||||
self._is_modified = False
|
||||
self._is_editable = False
|
||||
self._all_values = all_values
|
||||
super().__init__(('{' + _('template') + '}') if is_template else txt)
|
||||
if not is_template and txt not in all_values:
|
||||
icon = 'dialog_error.png'
|
||||
self.setToolTip(_("The value {} doesn't exist in the library").format(txt))
|
||||
self._is_editable = True
|
||||
else:
|
||||
icon = 'debug.png' if is_template else 'icon_choose.png'
|
||||
self.setFlags(self.flags() & ~Qt.ItemFlag.ItemIsEditable)
|
||||
self.setIcon(QIcon.cached_icon(icon))
|
||||
self.set_icon(txt)
|
||||
|
||||
@property
|
||||
def original_text(self):
|
||||
@ -129,12 +177,21 @@ class ValueTableWidgetItem(QTableWidgetItem):
|
||||
|
||||
@property
|
||||
def is_editable(self):
|
||||
return self._is_editable
|
||||
return not self._is_template
|
||||
|
||||
def set_icon(self, txt):
|
||||
if not self._is_template and txt not in self._all_values:
|
||||
icon = 'dialog_error.png'
|
||||
self.setToolTip(_("The value {} doesn't exist in the library").format(txt))
|
||||
else:
|
||||
icon = 'debug.png' if self._is_template else 'icon_choose.png'
|
||||
self.setToolTip(txt)
|
||||
self.setIcon(QIcon.cached_icon(icon))
|
||||
|
||||
def undo(self):
|
||||
self.is_modified = False
|
||||
self.setText(self._original_text)
|
||||
self.setIcon(QIcon.cached_icon('dialog_error.png'))
|
||||
self.set_icon(self._original_text)
|
||||
|
||||
|
||||
class ValueTableItemDelegate(QStyledItemDelegate):
|
||||
@ -165,6 +222,7 @@ class ValueTableItemDelegate(QStyledItemDelegate):
|
||||
val = editor.currentText()
|
||||
item = self._table.item(index.row(), index.column())
|
||||
item.setText(val)
|
||||
item.setToolTip(val)
|
||||
item.is_modified = True
|
||||
self._changed_signal.emit()
|
||||
|
||||
@ -429,16 +487,20 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
||||
pass
|
||||
|
||||
def lazy_initialize(self):
|
||||
self.rules_table.setItemDelegateForColumn(ICON_COLUMN, IconColumnDelegate(self, self.rules_table, self.changed_signal))
|
||||
self.rules_table.setItemDelegateForColumn(CATEGORY_COLUMN,
|
||||
CategoryTableItemDelegate(self, self.rules_table, self.changed_signal))
|
||||
self.rules_table.setItemDelegateForColumn(ICON_COLUMN,
|
||||
IconColumnDelegate(self, self.rules_table, self.changed_signal))
|
||||
self.rules_table.setItemDelegateForColumn(FOR_CHILDREN_COLUMN,
|
||||
ChildrenColumnDelegate(self, self.rules_table, self.changed_signal))
|
||||
ChildrenColumnDelegate(self, self.rules_table, self.changed_signal))
|
||||
self.rules_table.setItemDelegateForColumn(VALUE_COLUMN,
|
||||
ValueTableItemDelegate(self, self.rules_table, self.changed_signal))
|
||||
ValueTableItemDelegate(self, self.rules_table, self.changed_signal))
|
||||
self.populate_content()
|
||||
self.section_order = [0, 1, 1, 0, 0, 0, 0]
|
||||
self.last_section_sorted = 0
|
||||
self.do_sort(VALUE_COLUMN)
|
||||
self.do_sort(CATEGORY_COLUMN)
|
||||
self.changed_signal.connect(self.something_changed)
|
||||
|
||||
def populate_content(self):
|
||||
field_metadata = self.gui.current_db.field_metadata
|
||||
@ -451,26 +513,21 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
||||
row = 0
|
||||
t = self.rules_table
|
||||
t.clearContents()
|
||||
all_values = {}
|
||||
all_field_keys = field_metadata.all_field_keys()
|
||||
cats = self.gui.current_db.new_api.get_categories()
|
||||
self.all_values = all_values = {cat: set(t.name for t in cats[cat]) for cat in cats.keys()}
|
||||
for category,vdict in v.items():
|
||||
if category in field_metadata:
|
||||
display_name = field_metadata[category]['name']
|
||||
try:
|
||||
all_values[category] = set(self.gui.current_db.new_api.all_field_names(category))
|
||||
except ValueError:
|
||||
if category not in all_values:
|
||||
all_values[category] = set()
|
||||
if is_hierarchical_category(category):
|
||||
for value in all_values:
|
||||
for value in set(all_values[category]):
|
||||
idx = 0
|
||||
while idx >= 0:
|
||||
all_values[category].add(value)
|
||||
idx = value.rfind('.')
|
||||
while (idx := value.rfind('.')) >= 0:
|
||||
value = value[:idx]
|
||||
all_values[category].add(value)
|
||||
elif only_current_library:
|
||||
continue
|
||||
else:
|
||||
display_name = category.removeprefix('#')
|
||||
all_values[category] = set()
|
||||
self.all_values = all_values
|
||||
|
||||
@ -483,7 +540,7 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
||||
d = v[category][item_value]
|
||||
t.setItem(row, DELETED_COLUMN, StateTableWidgetItem(''))
|
||||
t.setItem(row, CATEGORY_COLUMN,
|
||||
CategoryTableWidgetItem(category, category_icons, display_name, field_metadata, t))
|
||||
CategoryTableWidgetItem(category, category_icons, field_metadata, t))
|
||||
t.setItem(row, ICON_MODIFIED_COLUMN, StateTableWidgetItem(''))
|
||||
t.setItem(row, VALUE_COLUMN, ValueTableWidgetItem(item_value, t, all_values[category]))
|
||||
t.setItem(row, ICON_COLUMN, IconFileTableWidgetItem(d[0], item_value, t))
|
||||
@ -492,6 +549,9 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
||||
t.setItem(row, FOR_CHILDREN_COLUMN, item)
|
||||
row += 1
|
||||
|
||||
def something_changed(self):
|
||||
self.show_only_current_library.setEnabled(False)
|
||||
|
||||
def show_context_menu(self, point):
|
||||
item = self.rules_table.itemAt(point)
|
||||
if item is None:
|
||||
@ -501,6 +561,9 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
||||
return
|
||||
m = QMenu(self)
|
||||
if column == CATEGORY_COLUMN:
|
||||
if item.is_editable:
|
||||
ac = m.addAction(_('Modify this value'), partial(self.context_menu_handler, 'modify', item))
|
||||
m.addSeparator()
|
||||
ac = m.addAction(_('Delete this rule'), partial(self.context_menu_handler, 'delete', item))
|
||||
ac.setEnabled(not item.is_deleted)
|
||||
ac = m.addAction(_('Undo delete'), partial(self.context_menu_handler, 'undo_delete', item))
|
||||
@ -549,7 +612,7 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
||||
self.delete_button.setEnabled(column == CATEGORY_COLUMN)
|
||||
if column == CATEGORY_COLUMN and item.is_deleted:
|
||||
self.undo_button.setEnabled(True)
|
||||
if column in (VALUE_COLUMN, ICON_COLUMN, FOR_CHILDREN_COLUMN):
|
||||
if column in (CATEGORY_COLUMN, VALUE_COLUMN, ICON_COLUMN, FOR_CHILDREN_COLUMN):
|
||||
if item.is_modified:
|
||||
self.undo_button.setEnabled(True)
|
||||
if item.is_editable:
|
||||
@ -575,7 +638,7 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
||||
idx = self.rules_table.currentIndex()
|
||||
if idx.isValid():
|
||||
column = idx.column()
|
||||
if column in (VALUE_COLUMN, ICON_COLUMN, FOR_CHILDREN_COLUMN):
|
||||
if column in (CATEGORY_COLUMN, VALUE_COLUMN, ICON_COLUMN, FOR_CHILDREN_COLUMN):
|
||||
self.rules_table.edit(idx)
|
||||
self.check_button_state(None) # Here to make buttons enabled/disabled
|
||||
|
||||
@ -655,6 +718,9 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
||||
pass
|
||||
v[cat_item.lookup_name].pop(value_text, None)
|
||||
continue
|
||||
if cat_item.original_lookup_name != cat_item.lookup_name:
|
||||
v[cat_item.lookup_name] = v[cat_item.original_lookup_name]
|
||||
v.pop(cat_item.original_lookup_name, None)
|
||||
|
||||
d = list(v[cat_item.lookup_name][value_text])
|
||||
|
||||
|
@ -45,6 +45,10 @@ or the context menu. The value icon rules are defined per-user, not per-library.
|
||||
<property name="text">
|
||||
<string>Show only categories and values available in the current library</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>This check box cannot be changed after any other changes have been made.
|
||||
Otherwise all edits would be lost.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
|
Loading…
x
Reference in New Issue
Block a user