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
dce5f748ed
@ -14,11 +14,13 @@ from qt.core import QAbstractItemView, QApplication, QDialog, QIcon, QMenu, QSiz
|
|||||||
from calibre.constants import config_dir
|
from calibre.constants import config_dir
|
||||||
from calibre.db.constants import TEMPLATE_ICON_INDICATOR
|
from calibre.db.constants import TEMPLATE_ICON_INDICATOR
|
||||||
from calibre.gui2 import choose_files, gprefs, pixmap_to_data
|
from calibre.gui2 import choose_files, gprefs, pixmap_to_data
|
||||||
|
from calibre.gui2.dialogs.tag_list_editor import block_signals
|
||||||
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
||||||
from calibre.gui2.library.delegates import DelegateCB
|
from calibre.gui2.library.delegates import DelegateCB
|
||||||
from calibre.gui2.preferences import LazyConfigWidgetBase
|
from calibre.gui2.preferences import LazyConfigWidgetBase
|
||||||
from calibre.gui2.preferences.look_feel_tabs.tb_icon_rules_ui import Ui_Form
|
from calibre.gui2.preferences.look_feel_tabs.tb_icon_rules_ui import Ui_Form
|
||||||
from calibre.utils.formatter import EvalFormatter
|
from calibre.utils.formatter import EvalFormatter
|
||||||
|
from calibre.utils.icu import sort_key
|
||||||
|
|
||||||
DELETED_COLUMN = 0
|
DELETED_COLUMN = 0
|
||||||
CATEGORY_COLUMN = 1
|
CATEGORY_COLUMN = 1
|
||||||
@ -35,7 +37,7 @@ class StateTableWidgetItem(QTableWidgetItem):
|
|||||||
def __init__(self, txt):
|
def __init__(self, txt):
|
||||||
super().__init__(txt)
|
super().__init__(txt)
|
||||||
self.setIcon(QIcon.cached_icon('blank.png'))
|
self.setIcon(QIcon.cached_icon('blank.png'))
|
||||||
self.setFlags(Qt.ItemFlag.NoItemFlags)
|
self.setFlags(Qt.ItemFlag.ItemIsEnabled)
|
||||||
|
|
||||||
def setText(self, txt):
|
def setText(self, txt):
|
||||||
if txt:
|
if txt:
|
||||||
@ -56,18 +58,18 @@ class CategoryTableWidgetItem(QTableWidgetItem):
|
|||||||
super().__init__(txt)
|
super().__init__(txt)
|
||||||
self._lookup_name = lookup_name
|
self._lookup_name = lookup_name
|
||||||
self._table = table
|
self._table = table
|
||||||
self._is_modified = False
|
self._is_deleted = False
|
||||||
self.setIcon(category_icons.get(lookup_name) or QIcon.cached_icon('column.png'))
|
self.setIcon(category_icons.get(lookup_name) or QIcon.cached_icon('column.png'))
|
||||||
self._txt = txt
|
self._txt = txt
|
||||||
self.setFlags(self.flags() & ~Qt.ItemFlag.ItemIsEditable)
|
self.setFlags(self.flags() & ~Qt.ItemFlag.ItemIsEditable)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_modified(self):
|
def is_deleted(self):
|
||||||
return self._is_modified
|
return self._is_deleted
|
||||||
|
|
||||||
@is_modified.setter
|
@is_deleted.setter
|
||||||
def is_modified(self, to_what):
|
def is_deleted(self, to_what):
|
||||||
self._is_modified = to_what
|
self._is_deleted = to_what
|
||||||
deleted_item = self._table.item(self.row(), DELETED_COLUMN)
|
deleted_item = self._table.item(self.row(), DELETED_COLUMN)
|
||||||
deleted_item.setText(to_what)
|
deleted_item.setText(to_what)
|
||||||
|
|
||||||
@ -76,18 +78,27 @@ class CategoryTableWidgetItem(QTableWidgetItem):
|
|||||||
return self._lookup_name
|
return self._lookup_name
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self.is_modified = False
|
self.is_deleted = False
|
||||||
|
|
||||||
|
|
||||||
class ValueTableWidgetItem(QTableWidgetItem):
|
class ValueTableWidgetItem(QTableWidgetItem):
|
||||||
|
|
||||||
def __init__(self, txt, table):
|
def __init__(self, txt, table, all_values):
|
||||||
self._original_text = txt
|
self._original_text = txt
|
||||||
self._table = table
|
self._table = table
|
||||||
|
self._all_values = all_values
|
||||||
self._is_template = is_template = txt == TEMPLATE_ICON_INDICATOR
|
self._is_template = is_template = txt == TEMPLATE_ICON_INDICATOR
|
||||||
|
self._is_modified = False
|
||||||
|
self._is_editable = False
|
||||||
super().__init__(('{' + _('template') + '}') if is_template else txt)
|
super().__init__(('{' + _('template') + '}') if is_template else txt)
|
||||||
self.setIcon(QIcon.cached_icon('debug.png' if is_template else 'icon_choose.png'))
|
if not is_template and txt not in all_values:
|
||||||
self.setFlags(self.flags() & ~Qt.ItemFlag.ItemIsEditable)
|
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))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def original_text(self):
|
def original_text(self):
|
||||||
@ -97,9 +108,59 @@ class ValueTableWidgetItem(QTableWidgetItem):
|
|||||||
def is_template(self):
|
def is_template(self):
|
||||||
return self._is_template
|
return self._is_template
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_deleted(self):
|
||||||
|
return self._table.item(self.row(), CATEGORY_COLUMN).is_deleted
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_modified(self):
|
def is_modified(self):
|
||||||
return self._table.item(self.row(), CATEGORY_COLUMN).is_modified
|
return self._is_modified
|
||||||
|
|
||||||
|
@is_modified.setter
|
||||||
|
def is_modified(self, to_what):
|
||||||
|
self._is_modified = to_what
|
||||||
|
self.setIcon(QIcon.cached_icon('modified.png'))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_editable(self):
|
||||||
|
return self._is_editable
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self.is_modified = False
|
||||||
|
self.setText(self._original_text)
|
||||||
|
self.setIcon(QIcon.cached_icon('dialog_error.png'))
|
||||||
|
|
||||||
|
|
||||||
|
class ValueTableItemDelegate(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):
|
||||||
|
row = index.row()
|
||||||
|
item = self._table.item(row, VALUE_COLUMN)
|
||||||
|
if item.is_template:
|
||||||
|
return None
|
||||||
|
editor = DelegateCB(parent)
|
||||||
|
items = sorted(self._parent.all_values[self._table.item(row, CATEGORY_COLUMN).lookup_name], key=sort_key)
|
||||||
|
for text in items:
|
||||||
|
editor.addItem(text)
|
||||||
|
items_lower = [item.lower() for item in items]
|
||||||
|
try:
|
||||||
|
editor.setCurrentIndex(items_lower.index(item.original_text.lower()))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return editor
|
||||||
|
|
||||||
|
def setModelData(self, editor, model, index):
|
||||||
|
val = editor.currentText()
|
||||||
|
item = self._table.item(index.row(), index.column())
|
||||||
|
item.setText(val)
|
||||||
|
item.is_modified = True
|
||||||
|
self._changed_signal.emit()
|
||||||
|
|
||||||
|
|
||||||
class IconFileTableWidgetItem(QTableWidgetItem):
|
class IconFileTableWidgetItem(QTableWidgetItem):
|
||||||
@ -155,11 +216,16 @@ class IconFileTableWidgetItem(QTableWidgetItem):
|
|||||||
self.set_text(self._original_text)
|
self.set_text(self._original_text)
|
||||||
self.setIcon(self._original_icon)
|
self.setIcon(self._original_icon)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_editable(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class IconColumnDelegate(QStyledItemDelegate):
|
class IconColumnDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
def __init__(self, parent, table, changed_signal):
|
def __init__(self, parent, table, changed_signal):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
self._parent = parent
|
||||||
self._table = table
|
self._table = table
|
||||||
self._changed_signal = changed_signal
|
self._changed_signal = changed_signal
|
||||||
|
|
||||||
@ -189,6 +255,7 @@ class IconColumnDelegate(QStyledItemDelegate):
|
|||||||
icon_item.setIcon(new_icon)
|
icon_item.setIcon(new_icon)
|
||||||
icon_item.is_modified = True
|
icon_item.is_modified = True
|
||||||
self._changed_signal.emit()
|
self._changed_signal.emit()
|
||||||
|
self._parent.check_button_state(icon_item)
|
||||||
|
|
||||||
|
|
||||||
class ChildrenTableWidgetItem(QTableWidgetItem):
|
class ChildrenTableWidgetItem(QTableWidgetItem):
|
||||||
@ -246,11 +313,16 @@ class ChildrenTableWidgetItem(QTableWidgetItem):
|
|||||||
self.is_modified = False
|
self.is_modified = False
|
||||||
self._set_text_and_icon(self._original_value)
|
self._set_text_and_icon(self._original_value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_editable(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class ChildrenColumnDelegate(QStyledItemDelegate):
|
class ChildrenColumnDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
def __init__(self, parent, table, changed_signal):
|
def __init__(self, parent, table, changed_signal):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
self._parent = parent
|
||||||
self._table = table
|
self._table = table
|
||||||
self._changed_signal = changed_signal
|
self._changed_signal = changed_signal
|
||||||
|
|
||||||
@ -264,13 +336,13 @@ class ChildrenColumnDelegate(QStyledItemDelegate):
|
|||||||
self.longest_text = ''
|
self.longest_text = ''
|
||||||
for icon, text in zip(icons, items):
|
for icon, text in zip(icons, items):
|
||||||
editor.addItem(QIcon.cached_icon(icon), text)
|
editor.addItem(QIcon.cached_icon(icon), text)
|
||||||
if len(text) > len(self.longest_text):
|
|
||||||
self.longest_text = text
|
|
||||||
return editor
|
return editor
|
||||||
|
|
||||||
def setModelData(self, editor, model, index):
|
def setModelData(self, editor, model, index):
|
||||||
val = {0:True, 1:False}[editor.currentIndex()]
|
val = {0:True, 1:False}[editor.currentIndex()]
|
||||||
self._table.item(index.row(), index.column()).set_value(val)
|
item = self._table.item(index.row(), index.column())
|
||||||
|
item.set_value(val)
|
||||||
|
self._parent.check_button_state(item)
|
||||||
self._changed_signal.emit()
|
self._changed_signal.emit()
|
||||||
|
|
||||||
def setEditorData(self, editor, index):
|
def setEditorData(self, editor, index):
|
||||||
@ -298,6 +370,9 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
self.rules_table.customContextMenuRequested.connect(self.show_context_menu)
|
self.rules_table.customContextMenuRequested.connect(self.show_context_menu)
|
||||||
self.rules_table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
self.rules_table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
||||||
|
|
||||||
|
self.rules_table.itemClicked.connect(self.check_button_state)
|
||||||
|
self.rules_table.itemChanged.connect(self.check_button_state)
|
||||||
|
|
||||||
# Make the minimum section size smaller so the icon column icons don't
|
# Make the minimum section size smaller so the icon column icons don't
|
||||||
# have a lot of space on the right
|
# have a lot of space on the right
|
||||||
self.rules_table.horizontalHeader().setMinimumSectionSize(20)
|
self.rules_table.horizontalHeader().setMinimumSectionSize(20)
|
||||||
@ -308,19 +383,23 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
item.setIcon(QIcon.cached_icon('trash.png'))
|
item.setIcon(QIcon.cached_icon('trash.png'))
|
||||||
item.setToolTip(_('This icon shows in the row if the rule is deleted'))
|
item.setToolTip(_('This icon shows in the row if the rule is deleted'))
|
||||||
elif i == CATEGORY_COLUMN:
|
elif i == CATEGORY_COLUMN:
|
||||||
item.setToolTip(_('The name of the category'))
|
item.setToolTip(_('The name of the category. Select a cell in this column to delete a row.'))
|
||||||
elif i == VALUE_COLUMN:
|
elif i == VALUE_COLUMN:
|
||||||
item.setToolTip(_('The value in the category the rule is applied to'))
|
item.setToolTip('<p>' +
|
||||||
|
_('The value in the category the rule is applied to. '
|
||||||
|
"If the value doesn't exist in the library then an "
|
||||||
|
"error icon is shown, in which case you can edit the "
|
||||||
|
"cell to pick the correct value."))
|
||||||
elif i == ICON_MODIFIED_COLUMN:
|
elif i == ICON_MODIFIED_COLUMN:
|
||||||
item.setIcon(QIcon.cached_icon('modified.png'))
|
item.setIcon(QIcon.cached_icon('modified.png'))
|
||||||
item.setToolTip(_('This icon shows in the row if the icon or template is modified'))
|
item.setToolTip(_('This icon shows in the row if the icon or template is modified.'))
|
||||||
elif i == ICON_COLUMN:
|
elif i == ICON_COLUMN:
|
||||||
item.setToolTip(_('The file name of the icon or the text of the template'))
|
item.setToolTip(_('The file name of the icon or the text of the template.'))
|
||||||
elif i == FOR_CHILDREN_MODIFIED_COLUMN:
|
elif i == FOR_CHILDREN_MODIFIED_COLUMN:
|
||||||
item.setIcon(QIcon.cached_icon('modified.png'))
|
item.setIcon(QIcon.cached_icon('modified.png'))
|
||||||
item.setToolTip(_('This icon shows in the row if the "for children" setting is modified'))
|
item.setToolTip(_('This icon shows in the row if the "for children" setting is modified.'))
|
||||||
elif i == FOR_CHILDREN_COLUMN:
|
elif i == FOR_CHILDREN_COLUMN:
|
||||||
item.setToolTip(_('Indicates whether the rule applies to child values'))
|
item.setToolTip(_('Indicates whether the rule applies to child values.'))
|
||||||
|
|
||||||
# Capture clicks on the horizontal header to sort the table columns
|
# Capture clicks on the horizontal header to sort the table columns
|
||||||
hh = self.rules_table.horizontalHeader()
|
hh = self.rules_table.horizontalHeader()
|
||||||
@ -330,6 +409,7 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
hh.setSortIndicatorShown(True)
|
hh.setSortIndicatorShown(True)
|
||||||
|
|
||||||
self.delete_button.clicked.connect(self.delete_rule)
|
self.delete_button.clicked.connect(self.delete_rule)
|
||||||
|
self.delete_button.setEnabled(False)
|
||||||
self.edit_button.clicked.connect(self.edit_column)
|
self.edit_button.clicked.connect(self.edit_column)
|
||||||
self.undo_button.clicked.connect(self.undo_changes)
|
self.undo_button.clicked.connect(self.undo_changes)
|
||||||
self.show_only_current_library.stateChanged.connect(self.change_filter_library)
|
self.show_only_current_library.stateChanged.connect(self.change_filter_library)
|
||||||
@ -346,6 +426,8 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
self.rules_table.setItemDelegateForColumn(ICON_COLUMN, IconColumnDelegate(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,
|
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))
|
||||||
self.populate_content()
|
self.populate_content()
|
||||||
self.section_order = [0, 1, 1, 0, 0, 0, 0]
|
self.section_order = [0, 1, 1, 0, 0, 0, 0]
|
||||||
self.last_section_sorted = 0
|
self.last_section_sorted = 0
|
||||||
@ -363,39 +445,42 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
t = self.rules_table
|
t = self.rules_table
|
||||||
t.clearContents()
|
t.clearContents()
|
||||||
|
|
||||||
|
all_values = {}
|
||||||
for category,vdict in v.items():
|
for category,vdict in v.items():
|
||||||
if category in field_metadata:
|
if category in field_metadata:
|
||||||
display_name = field_metadata[category]['name']
|
display_name = field_metadata[category]['name']
|
||||||
all_values = self.gui.current_db.new_api.all_field_names(category)
|
all_values[category] = set(self.gui.current_db.new_api.all_field_names(category))
|
||||||
if is_hierarchical_category(category):
|
if is_hierarchical_category(category):
|
||||||
rslt = set()
|
|
||||||
for value in all_values:
|
for value in all_values:
|
||||||
idx = 0
|
idx = 0
|
||||||
while idx >= 0:
|
while idx >= 0:
|
||||||
rslt.add(value)
|
all_values[category].add(value)
|
||||||
idx = value.rfind('.')
|
idx = value.rfind('.')
|
||||||
value = value[:idx]
|
value = value[:idx]
|
||||||
all_values = rslt
|
|
||||||
elif only_current_library:
|
elif only_current_library:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
display_name = category.removeprefix('#')
|
display_name = category.removeprefix('#')
|
||||||
all_values = ()
|
all_values = {category: set()}
|
||||||
for item_value in vdict:
|
self.all_values = all_values
|
||||||
if only_current_library and item_value != TEMPLATE_ICON_INDICATOR and item_value not in all_values:
|
|
||||||
continue
|
with block_signals(self.rules_table):
|
||||||
t.setRowCount(row + 1)
|
for item_value in vdict:
|
||||||
d = v[category][item_value]
|
if (only_current_library and item_value != TEMPLATE_ICON_INDICATOR and
|
||||||
t.setItem(row, DELETED_COLUMN, StateTableWidgetItem(''))
|
item_value not in all_values[category]):
|
||||||
t.setItem(row, CATEGORY_COLUMN,
|
continue
|
||||||
CategoryTableWidgetItem(category, category_icons, display_name, t))
|
t.setRowCount(row + 1)
|
||||||
t.setItem(row, ICON_MODIFIED_COLUMN, StateTableWidgetItem(''))
|
d = v[category][item_value]
|
||||||
t.setItem(row, VALUE_COLUMN, ValueTableWidgetItem(item_value, t))
|
t.setItem(row, DELETED_COLUMN, StateTableWidgetItem(''))
|
||||||
t.setItem(row, ICON_COLUMN, IconFileTableWidgetItem(d[0], item_value, t))
|
t.setItem(row, CATEGORY_COLUMN,
|
||||||
t.setItem(row, FOR_CHILDREN_MODIFIED_COLUMN, StateTableWidgetItem(''))
|
CategoryTableWidgetItem(category, category_icons, display_name, t))
|
||||||
item = ChildrenTableWidgetItem(d[1], item_value, t)
|
t.setItem(row, ICON_MODIFIED_COLUMN, StateTableWidgetItem(''))
|
||||||
t.setItem(row, FOR_CHILDREN_COLUMN, item)
|
t.setItem(row, VALUE_COLUMN, ValueTableWidgetItem(item_value, t, all_values[category]))
|
||||||
row += 1
|
t.setItem(row, ICON_COLUMN, IconFileTableWidgetItem(d[0], item_value, t))
|
||||||
|
t.setItem(row, FOR_CHILDREN_MODIFIED_COLUMN, StateTableWidgetItem(''))
|
||||||
|
item = ChildrenTableWidgetItem(d[1], item_value, t)
|
||||||
|
t.setItem(row, FOR_CHILDREN_COLUMN, item)
|
||||||
|
row += 1
|
||||||
|
|
||||||
def show_context_menu(self, point):
|
def show_context_menu(self, point):
|
||||||
item = self.rules_table.itemAt(point)
|
item = self.rules_table.itemAt(point)
|
||||||
@ -405,10 +490,14 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
if column in (DELETED_COLUMN, ICON_MODIFIED_COLUMN, FOR_CHILDREN_MODIFIED_COLUMN):
|
if column in (DELETED_COLUMN, ICON_MODIFIED_COLUMN, FOR_CHILDREN_MODIFIED_COLUMN):
|
||||||
return
|
return
|
||||||
m = QMenu(self)
|
m = QMenu(self)
|
||||||
if column in (CATEGORY_COLUMN, VALUE_COLUMN):
|
if column == CATEGORY_COLUMN:
|
||||||
ac = m.addAction(_('Delete this rule'), partial(self.context_menu_handler, 'delete', item))
|
ac = m.addAction(_('Delete this rule'), partial(self.context_menu_handler, 'delete', item))
|
||||||
ac.setEnabled(not item.is_modified)
|
ac.setEnabled(not item.is_deleted)
|
||||||
ac = m.addAction(_('Undo delete'), partial(self.context_menu_handler, 'undo_delete', item))
|
ac = m.addAction(_('Undo delete'), partial(self.context_menu_handler, 'undo_delete', item))
|
||||||
|
ac.setEnabled(item.is_deleted)
|
||||||
|
elif column == VALUE_COLUMN and item.is_editable:
|
||||||
|
ac = m.addAction(_('Modify this value'), partial(self.context_menu_handler, 'modify', item))
|
||||||
|
ac = m.addAction(_('Undo modification'), partial(self.context_menu_handler, 'undo_modification', item))
|
||||||
ac.setEnabled(item.is_modified)
|
ac.setEnabled(item.is_modified)
|
||||||
elif column in (ICON_COLUMN, FOR_CHILDREN_COLUMN):
|
elif column in (ICON_COLUMN, FOR_CHILDREN_COLUMN):
|
||||||
ac = m.addAction(_('Modify this value'), partial(self.context_menu_handler, 'modify', item))
|
ac = m.addAction(_('Modify this value'), partial(self.context_menu_handler, 'modify', item))
|
||||||
@ -440,6 +529,22 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
return
|
return
|
||||||
return super().keyPressEvent(ev)
|
return super().keyPressEvent(ev)
|
||||||
|
|
||||||
|
def check_button_state(self, item):
|
||||||
|
if item is None:
|
||||||
|
item = self.rules_table.currentItem()
|
||||||
|
self.delete_button.setEnabled(False)
|
||||||
|
self.edit_button.setEnabled(False)
|
||||||
|
self.undo_button.setEnabled(False)
|
||||||
|
column = item.column()
|
||||||
|
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 item.is_modified:
|
||||||
|
self.undo_button.setEnabled(True)
|
||||||
|
if item.is_editable:
|
||||||
|
self.edit_button.setEnabled(True)
|
||||||
|
|
||||||
def change_filter_library(self, state):
|
def change_filter_library(self, state):
|
||||||
gprefs['tag_browser_rules_show_only_current_library'] = self.show_only_current_library.isChecked()
|
gprefs['tag_browser_rules_show_only_current_library'] = self.show_only_current_library.isChecked()
|
||||||
self.populate_content()
|
self.populate_content()
|
||||||
@ -449,14 +554,9 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
idx = self.rules_table.currentIndex()
|
idx = self.rules_table.currentIndex()
|
||||||
if idx.isValid():
|
if idx.isValid():
|
||||||
column = idx.column()
|
column = idx.column()
|
||||||
if column == DELETED_COLUMN:
|
if column == VALUE_COLUMN and self.rules_table.item(idx.row(), column).is_modified:
|
||||||
column = CATEGORY_COLUMN
|
self.undo_modification()
|
||||||
elif column == ICON_MODIFIED_COLUMN:
|
elif column == CATEGORY_COLUMN:
|
||||||
column = ICON_COLUMN
|
|
||||||
elif column == FOR_CHILDREN_MODIFIED_COLUMN:
|
|
||||||
column = FOR_CHILDREN_COLUMN
|
|
||||||
|
|
||||||
if column in (CATEGORY_COLUMN, VALUE_COLUMN):
|
|
||||||
self.undo_delete()
|
self.undo_delete()
|
||||||
elif column in (ICON_COLUMN, FOR_CHILDREN_COLUMN):
|
elif column in (ICON_COLUMN, FOR_CHILDREN_COLUMN):
|
||||||
self.undo_modification()
|
self.undo_modification()
|
||||||
@ -465,21 +565,25 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
idx = self.rules_table.currentIndex()
|
idx = self.rules_table.currentIndex()
|
||||||
if idx.isValid():
|
if idx.isValid():
|
||||||
column = idx.column()
|
column = idx.column()
|
||||||
if column in (ICON_COLUMN, FOR_CHILDREN_COLUMN):
|
if column in (VALUE_COLUMN, ICON_COLUMN, FOR_CHILDREN_COLUMN):
|
||||||
self.rules_table.edit(idx)
|
self.rules_table.edit(idx)
|
||||||
|
self.check_button_state(None) # Here to make buttons enabled/disabled
|
||||||
|
|
||||||
def delete_rule(self):
|
def delete_rule(self):
|
||||||
idx = self.rules_table.currentIndex()
|
idx = self.rules_table.currentIndex()
|
||||||
if idx.isValid():
|
if idx.isValid() and idx.column() == CATEGORY_COLUMN:
|
||||||
item = self.rules_table.item(idx.row(), CATEGORY_COLUMN)
|
item = self.rules_table.item(idx.row(), idx.column())
|
||||||
item.is_modified = True
|
item.is_deleted = True
|
||||||
self.changed_signal.emit()
|
self.changed_signal.emit()
|
||||||
|
self.check_button_state(item)
|
||||||
|
|
||||||
def undo_delete(self):
|
def undo_delete(self):
|
||||||
idx = self.rules_table.currentIndex()
|
idx = self.rules_table.currentIndex()
|
||||||
if idx.isValid():
|
if idx.isValid():
|
||||||
self.rules_table.item(idx.row(), CATEGORY_COLUMN).undo()
|
item = self.rules_table.item(idx.row(), CATEGORY_COLUMN)
|
||||||
|
item.undo()
|
||||||
self.changed_signal.emit()
|
self.changed_signal.emit()
|
||||||
|
self.check_button_state(item)
|
||||||
|
|
||||||
def undo_modification(self):
|
def undo_modification(self):
|
||||||
idx = self.rules_table.currentIndex()
|
idx = self.rules_table.currentIndex()
|
||||||
@ -487,6 +591,7 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
item = self.rules_table.item(idx.row(), idx.column())
|
item = self.rules_table.item(idx.row(), idx.column())
|
||||||
item.undo()
|
item.undo()
|
||||||
self.changed_signal.emit()
|
self.changed_signal.emit()
|
||||||
|
self.check_button_state(item)
|
||||||
|
|
||||||
def table_column_resized(self, col, old, new):
|
def table_column_resized(self, col, old, new):
|
||||||
self.table_column_widths = []
|
self.table_column_widths = []
|
||||||
@ -529,7 +634,7 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
value_item = self.rules_table.item(r, VALUE_COLUMN)
|
value_item = self.rules_table.item(r, VALUE_COLUMN)
|
||||||
value_text = value_item._original_text
|
value_text = value_item._original_text
|
||||||
|
|
||||||
if cat_item.is_modified: # deleted
|
if cat_item.is_deleted:
|
||||||
if not value_item.is_template:
|
if not value_item.is_template:
|
||||||
# Need to delete the icon file to clean up
|
# Need to delete the icon file to clean up
|
||||||
icon_file = self.rules_table.item(r, ICON_COLUMN).text()
|
icon_file = self.rules_table.item(r, ICON_COLUMN).text()
|
||||||
@ -541,9 +646,13 @@ class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form):
|
|||||||
v[cat_item.lookup_name].pop(value_text, None)
|
v[cat_item.lookup_name].pop(value_text, None)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
icon_item = self.rules_table.item(r, ICON_COLUMN)
|
|
||||||
d = list(v[cat_item.lookup_name][value_text])
|
d = list(v[cat_item.lookup_name][value_text])
|
||||||
|
|
||||||
|
if value_item.is_modified:
|
||||||
|
v[cat_item.lookup_name].pop(value_text)
|
||||||
|
v[cat_item.lookup_name][value_item.text()] = d
|
||||||
|
|
||||||
|
icon_item = self.rules_table.item(r, ICON_COLUMN)
|
||||||
if icon_item.is_modified:
|
if icon_item.is_modified:
|
||||||
if value_item.is_template:
|
if value_item.is_template:
|
||||||
d[0] = icon_item.text()
|
d[0] = icon_item.text()
|
||||||
|
@ -43,8 +43,8 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string><p>View all the defined value icon rules, including template rules.
|
<string><p>View all the defined value icon rules, including template rules.
|
||||||
Rules are defined and edited in the Tag browser context menus. Rules can be deleted in
|
Rules are defined and edited in the Tag browser context menus. Rules can be deleted in
|
||||||
this dialog using the button, the delete key, or the context menu. The value icon rules
|
this dialog by selecting the Category cell then using the button, the delete key,
|
||||||
are defined per-user, not per-library.</p></string>
|
or the context menu. The value icon rules are defined per-user, not per-library.</p></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -70,7 +70,7 @@ are defined per-user, not per-library.</p></string>
|
|||||||
<normaloff>:/images/trash.png</normaloff>:/images/trash.png</iconset>
|
<normaloff>:/images/trash.png</normaloff>:/images/trash.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Delete the selected rule</string>
|
<string>Delete the selected rule. The Category cell for the rule must be selected</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -81,7 +81,7 @@ are defined per-user, not per-library.</p></string>
|
|||||||
<normaloff>:/images/edit_input.png</normaloff>:/images/edit_input.png</iconset>
|
<normaloff>:/images/edit_input.png</normaloff>:/images/edit_input.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Edit the selected column</string>
|
<string>Edit the selected cell</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -92,7 +92,7 @@ are defined per-user, not per-library.</p></string>
|
|||||||
<normaloff>:/images/edit-undo.png</normaloff>:/images/edit-undo.png</iconset>
|
<normaloff>:/images/edit-undo.png</normaloff>:/images/edit-undo.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Undelete the selected rule if it is deleted</string>
|
<string>Undo changes in the selected cell, if any.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -1611,6 +1611,11 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
self.db.new_api.rename_items(lookup_key, {an_item.tag.id: new_name},
|
self.db.new_api.rename_items(lookup_key, {an_item.tag.id: new_name},
|
||||||
restrict_to_book_ids=restrict_to_books)
|
restrict_to_book_ids=restrict_to_books)
|
||||||
self.tag_item_renamed.emit()
|
self.tag_item_renamed.emit()
|
||||||
|
val_icon_data = self.value_icons.get(an_item.tag.category, {}).get(an_item.tag.original_name)
|
||||||
|
if val_icon_data:
|
||||||
|
# There is an icon for the old value. Rename it
|
||||||
|
self.value_icons[an_item.tag.category].pop(an_item.tag.original_name, None)
|
||||||
|
self.value_icons[an_item.tag.category][new_name] = val_icon_data
|
||||||
an_item.tag.name = new_name
|
an_item.tag.name = new_name
|
||||||
an_item.tag.state = TAG_SEARCH_STATES['clear']
|
an_item.tag.state = TAG_SEARCH_STATES['clear']
|
||||||
self.use_position_based_index_on_next_recount = True
|
self.use_position_based_index_on_next_recount = True
|
||||||
|
Loading…
x
Reference in New Issue
Block a user