mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
Allow opening the full Tag Editor dialog directly from the book list by holding down the Shift key while starting an edit of a tag-like field. For example, click on the tags field for a book and press Shift-F2
Tag Browser: Allow undoing the deletion of items in the Manage categories window Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
d821086eeb
@ -317,8 +317,10 @@ class Text(Base):
|
||||
if self.sep['ui_to_list'] == '&':
|
||||
w.set_space_before_sep(True)
|
||||
w.set_add_separator(tweaks['authors_completer_append_separator'])
|
||||
w.get_editor_button().setVisible(False)
|
||||
else:
|
||||
w.get_editor_button().clicked.connect(self.edit)
|
||||
w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
||||
w.get_editor_button().clicked.connect(self.edit)
|
||||
else:
|
||||
w = EditWithComplete(parent)
|
||||
w.set_separator(None)
|
||||
|
@ -2,9 +2,11 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
from PyQt5.Qt import (Qt, QDialog, QTableWidgetItem, QIcon, QByteArray, QSize,
|
||||
QDialogButtonBox)
|
||||
QDialogButtonBox, QTableWidget, QObject, pyqtSignal,
|
||||
QEvent, QItemDelegate)
|
||||
|
||||
from calibre.gui2.dialogs.tag_list_editor_ui import Ui_TagListEditor
|
||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||
from calibre.gui2 import question_dialog, error_dialog, info_dialog, gprefs
|
||||
from calibre.utils.icu import sort_key
|
||||
|
||||
@ -15,15 +17,26 @@ class NameTableWidgetItem(QTableWidgetItem):
|
||||
self.initial_value = txt
|
||||
self.current_value = txt
|
||||
self.previous_value = txt
|
||||
self.is_deleted = False
|
||||
|
||||
def data(self, role):
|
||||
if role == Qt.DisplayRole:
|
||||
if self.is_deleted:
|
||||
return ''
|
||||
return self.current_value
|
||||
elif role == Qt.EditRole:
|
||||
return self.current_value
|
||||
else:
|
||||
return QTableWidgetItem.data(self, role)
|
||||
|
||||
def set_is_deleted(self, to_what):
|
||||
if to_what:
|
||||
self.setIcon(QIcon(I('trash.png')))
|
||||
else:
|
||||
self.setIcon(QIcon(None))
|
||||
self.current_value = self.previous_value = self.initial_value
|
||||
self.is_deleted = to_what
|
||||
|
||||
def setData(self, role, data):
|
||||
if role == Qt.EditRole:
|
||||
self.previous_value = self.current_value
|
||||
@ -61,6 +74,27 @@ class CountTableWidgetItem(QTableWidgetItem):
|
||||
def __lt__(self, other):
|
||||
return self._count < other._count
|
||||
|
||||
class EditColumnDelegate(QItemDelegate):
|
||||
|
||||
def __init__(self, table):
|
||||
QItemDelegate.__init__(self)
|
||||
self.table = table
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
item = self.table.item(index.row(), 0)
|
||||
if index.column() == 0:
|
||||
item = self.table.item(index.row(), 0)
|
||||
if item.is_deleted:
|
||||
return None
|
||||
return QItemDelegate.createEditor(self, parent, option, index)
|
||||
if not confirm(
|
||||
_('Do you want to undo your changes?'),
|
||||
'tag_list_editor_undo'):
|
||||
return
|
||||
item.setText(item.initial_text())
|
||||
self.table.blockSignals(True)
|
||||
self.table.item(index.row(), 2).setData(Qt.DisplayRole, '')
|
||||
self.table.blockSignals(False)
|
||||
|
||||
class TagListEditor(QDialog, Ui_TagListEditor):
|
||||
|
||||
@ -122,6 +156,8 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
||||
self.count_order = 1
|
||||
self.was_order = 1
|
||||
|
||||
self.table.setItemDelegate(EditColumnDelegate(self.table))
|
||||
|
||||
# Add the data
|
||||
select_item = None
|
||||
self.table.setRowCount(len(self.all_tags))
|
||||
@ -136,8 +172,9 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
||||
# only the name column can be selected
|
||||
item.setFlags(item.flags() & ~(Qt.ItemIsSelectable|Qt.ItemIsEditable))
|
||||
self.table.setItem(row, 1, item)
|
||||
item = QTableWidgetItem('')
|
||||
item.setFlags(item.flags() & ~(Qt.ItemIsSelectable|Qt.ItemIsEditable))
|
||||
item = QTableWidgetItem()
|
||||
# item.setFlags(item.flags() & ~(Qt.ItemIsSelectable|Qt.ItemIsEditable))
|
||||
item.setFlags((item.flags() | Qt.ItemIsEditable) & ~Qt.ItemIsSelectable)
|
||||
self.table.setItem(row, 2, item)
|
||||
|
||||
# Scroll to the selected item if there is one
|
||||
@ -158,6 +195,8 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
||||
self.search_button.clicked.connect(self.search_clicked)
|
||||
self.search_button.setDefault(True)
|
||||
|
||||
self.table.setEditTriggers(QTableWidget.EditKeyPressed)
|
||||
|
||||
self.start_find_pos = -1
|
||||
|
||||
try:
|
||||
@ -216,7 +255,7 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
||||
if not item.text():
|
||||
error_dialog(self, _('Item is blank'),
|
||||
_('An item cannot be set to nothing. Delete it instead.')).exec_()
|
||||
item.setText(item.previous_text())
|
||||
item.setText(item.initial_text())
|
||||
return
|
||||
if item.text() != item.initial_text():
|
||||
id_ = int(item.data(Qt.UserRole))
|
||||
@ -235,7 +274,19 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
||||
error_dialog(self, _('No item selected'),
|
||||
_('You must select one item from the list of Available items.')).exec_()
|
||||
return
|
||||
self.table.editItem(item)
|
||||
col_zero_item = self.table.item(item.row(), 0);
|
||||
if col_zero_item.is_deleted:
|
||||
if not question_dialog(self, _('Undelete item?'),
|
||||
'<p>'+_('That item is deleted. Do you want to undelete it?')+'<br>'):
|
||||
return
|
||||
col_zero_item.set_is_deleted(False)
|
||||
self.to_delete.discard(int(col_zero_item.data(Qt.UserRole)))
|
||||
orig = self.table.item(col_zero_item.row(), 2)
|
||||
self.table.blockSignals(True)
|
||||
orig.setData(Qt.DisplayRole, '')
|
||||
self.table.blockSignals(False)
|
||||
else:
|
||||
self.table.editItem(item)
|
||||
|
||||
def delete_tags(self):
|
||||
deletes = self.table.selectedItems()
|
||||
@ -243,16 +294,43 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
||||
error_dialog(self, _('No items selected'),
|
||||
_('You must select at least one item from the list.')).exec_()
|
||||
return
|
||||
ct = ', '.join([unicode(item.text()) for item in deletes])
|
||||
if not question_dialog(self, _('Are you sure?'),
|
||||
'<p>'+_('Are you sure you want to delete the following items?')+'<br>'+ct):
|
||||
return
|
||||
|
||||
to_del = []
|
||||
to_undel = []
|
||||
for item in deletes:
|
||||
if item.is_deleted:
|
||||
to_undel.append(item)
|
||||
else:
|
||||
to_del.append(item)
|
||||
if to_del:
|
||||
ct = ', '.join([unicode(item.text()) for item in to_del])
|
||||
if not confirm(
|
||||
'<p>'+_('Are you sure you want to delete the following items?')+'<br>'+ct,
|
||||
'tag_list_editor_delete'):
|
||||
return
|
||||
if to_undel:
|
||||
ct = ', '.join([unicode(item.text()) for item in to_undel])
|
||||
if not confirm(
|
||||
'<p>'+_('Are you sure you want to undelete the following items?')+'<br>'+ct,
|
||||
'tag_list_editor_undelete'):
|
||||
return
|
||||
row = self.table.row(deletes[0])
|
||||
for item in deletes:
|
||||
id = int(item.data(Qt.UserRole))
|
||||
self.to_delete.add(id)
|
||||
self.table.removeRow(self.table.row(item))
|
||||
|
||||
if item.is_deleted:
|
||||
item.set_is_deleted(False)
|
||||
self.to_delete.discard(int(item.data(Qt.UserRole)))
|
||||
orig = self.table.item(item.row(), 2)
|
||||
self.table.blockSignals(True)
|
||||
orig.setData(Qt.DisplayRole, '')
|
||||
self.table.blockSignals(False)
|
||||
else:
|
||||
id = int(item.data(Qt.UserRole))
|
||||
self.to_delete.add(id)
|
||||
item.set_is_deleted(True)
|
||||
orig = self.table.item(item.row(), 2)
|
||||
self.table.blockSignals(True)
|
||||
orig.setData(Qt.DisplayRole, item.initial_text())
|
||||
self.table.blockSignals(False)
|
||||
if row >= self.table.rowCount():
|
||||
row = self.table.rowCount() - 1
|
||||
if row >= 0:
|
||||
|
@ -23,6 +23,7 @@ from calibre.utils.formatter import validation_formatter
|
||||
from calibre.utils.icu import sort_key
|
||||
from calibre.gui2.dialogs.comments_dialog import CommentsDialog
|
||||
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
||||
from calibre.gui2.dialogs.tag_editor import TagEditor
|
||||
from calibre.gui2.languages import LanguagesEdit
|
||||
|
||||
class UpdateEditorGeometry(object):
|
||||
@ -307,13 +308,22 @@ class CompleteDelegate(QStyledItemDelegate, UpdateEditorGeometry): # {{{
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
if self.db and hasattr(self.db, self.items_func_name):
|
||||
col = index.model().column_map[index.column()]
|
||||
m = index.model()
|
||||
col = m.column_map[index.column()]
|
||||
# If shifted, bring up the tag editor instead of the line editor.
|
||||
# Don't do this for people-name columns because order will be lost
|
||||
if QApplication.keyboardModifiers() == Qt.ShiftModifier and self.sep == ',':
|
||||
key = col if m.is_custom_column(col) else None
|
||||
d = TagEditor(parent, self.db, m.id(index.row()), key=key)
|
||||
if d.exec_() == TagEditor.Accepted:
|
||||
m.setData(index, self.sep.join(d.tags), Qt.EditRole)
|
||||
return None
|
||||
editor = EditWithComplete(parent)
|
||||
editor.set_separator(self.sep)
|
||||
editor.set_space_before_sep(self.space_before_sep)
|
||||
if self.sep == '&':
|
||||
editor.set_add_separator(tweaks['authors_completer_append_separator'])
|
||||
if not index.model().is_custom_column(col):
|
||||
if not m.is_custom_column(col):
|
||||
all_items = getattr(self.db, self.items_func_name)()
|
||||
else:
|
||||
all_items = list(self.db.all_custom(
|
||||
|
Loading…
x
Reference in New Issue
Block a user