mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -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'] == '&':
|
if self.sep['ui_to_list'] == '&':
|
||||||
w.set_space_before_sep(True)
|
w.set_space_before_sep(True)
|
||||||
w.set_add_separator(tweaks['authors_completer_append_separator'])
|
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.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
||||||
w.get_editor_button().clicked.connect(self.edit)
|
|
||||||
else:
|
else:
|
||||||
w = EditWithComplete(parent)
|
w = EditWithComplete(parent)
|
||||||
w.set_separator(None)
|
w.set_separator(None)
|
||||||
|
@ -2,9 +2,11 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
from PyQt5.Qt import (Qt, QDialog, QTableWidgetItem, QIcon, QByteArray, QSize,
|
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.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.gui2 import question_dialog, error_dialog, info_dialog, gprefs
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
|
|
||||||
@ -15,15 +17,26 @@ class NameTableWidgetItem(QTableWidgetItem):
|
|||||||
self.initial_value = txt
|
self.initial_value = txt
|
||||||
self.current_value = txt
|
self.current_value = txt
|
||||||
self.previous_value = txt
|
self.previous_value = txt
|
||||||
|
self.is_deleted = False
|
||||||
|
|
||||||
def data(self, role):
|
def data(self, role):
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
|
if self.is_deleted:
|
||||||
|
return ''
|
||||||
return self.current_value
|
return self.current_value
|
||||||
elif role == Qt.EditRole:
|
elif role == Qt.EditRole:
|
||||||
return self.current_value
|
return self.current_value
|
||||||
else:
|
else:
|
||||||
return QTableWidgetItem.data(self, role)
|
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):
|
def setData(self, role, data):
|
||||||
if role == Qt.EditRole:
|
if role == Qt.EditRole:
|
||||||
self.previous_value = self.current_value
|
self.previous_value = self.current_value
|
||||||
@ -61,6 +74,27 @@ class CountTableWidgetItem(QTableWidgetItem):
|
|||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
return self._count < other._count
|
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):
|
class TagListEditor(QDialog, Ui_TagListEditor):
|
||||||
|
|
||||||
@ -122,6 +156,8 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
|||||||
self.count_order = 1
|
self.count_order = 1
|
||||||
self.was_order = 1
|
self.was_order = 1
|
||||||
|
|
||||||
|
self.table.setItemDelegate(EditColumnDelegate(self.table))
|
||||||
|
|
||||||
# Add the data
|
# Add the data
|
||||||
select_item = None
|
select_item = None
|
||||||
self.table.setRowCount(len(self.all_tags))
|
self.table.setRowCount(len(self.all_tags))
|
||||||
@ -136,8 +172,9 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
|||||||
# only the name column can be selected
|
# only the name column can be selected
|
||||||
item.setFlags(item.flags() & ~(Qt.ItemIsSelectable|Qt.ItemIsEditable))
|
item.setFlags(item.flags() & ~(Qt.ItemIsSelectable|Qt.ItemIsEditable))
|
||||||
self.table.setItem(row, 1, item)
|
self.table.setItem(row, 1, item)
|
||||||
item = QTableWidgetItem('')
|
item = QTableWidgetItem()
|
||||||
item.setFlags(item.flags() & ~(Qt.ItemIsSelectable|Qt.ItemIsEditable))
|
# item.setFlags(item.flags() & ~(Qt.ItemIsSelectable|Qt.ItemIsEditable))
|
||||||
|
item.setFlags((item.flags() | Qt.ItemIsEditable) & ~Qt.ItemIsSelectable)
|
||||||
self.table.setItem(row, 2, item)
|
self.table.setItem(row, 2, item)
|
||||||
|
|
||||||
# Scroll to the selected item if there is one
|
# 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.clicked.connect(self.search_clicked)
|
||||||
self.search_button.setDefault(True)
|
self.search_button.setDefault(True)
|
||||||
|
|
||||||
|
self.table.setEditTriggers(QTableWidget.EditKeyPressed)
|
||||||
|
|
||||||
self.start_find_pos = -1
|
self.start_find_pos = -1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -216,7 +255,7 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
|||||||
if not item.text():
|
if not item.text():
|
||||||
error_dialog(self, _('Item is blank'),
|
error_dialog(self, _('Item is blank'),
|
||||||
_('An item cannot be set to nothing. Delete it instead.')).exec_()
|
_('An item cannot be set to nothing. Delete it instead.')).exec_()
|
||||||
item.setText(item.previous_text())
|
item.setText(item.initial_text())
|
||||||
return
|
return
|
||||||
if item.text() != item.initial_text():
|
if item.text() != item.initial_text():
|
||||||
id_ = int(item.data(Qt.UserRole))
|
id_ = int(item.data(Qt.UserRole))
|
||||||
@ -235,7 +274,19 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
|||||||
error_dialog(self, _('No item selected'),
|
error_dialog(self, _('No item selected'),
|
||||||
_('You must select one item from the list of Available items.')).exec_()
|
_('You must select one item from the list of Available items.')).exec_()
|
||||||
return
|
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):
|
def delete_tags(self):
|
||||||
deletes = self.table.selectedItems()
|
deletes = self.table.selectedItems()
|
||||||
@ -243,16 +294,43 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
|||||||
error_dialog(self, _('No items selected'),
|
error_dialog(self, _('No items selected'),
|
||||||
_('You must select at least one item from the list.')).exec_()
|
_('You must select at least one item from the list.')).exec_()
|
||||||
return
|
return
|
||||||
ct = ', '.join([unicode(item.text()) for item in deletes])
|
|
||||||
if not question_dialog(self, _('Are you sure?'),
|
to_del = []
|
||||||
'<p>'+_('Are you sure you want to delete the following items?')+'<br>'+ct):
|
to_undel = []
|
||||||
return
|
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])
|
row = self.table.row(deletes[0])
|
||||||
for item in deletes:
|
for item in deletes:
|
||||||
id = int(item.data(Qt.UserRole))
|
if item.is_deleted:
|
||||||
self.to_delete.add(id)
|
item.set_is_deleted(False)
|
||||||
self.table.removeRow(self.table.row(item))
|
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():
|
if row >= self.table.rowCount():
|
||||||
row = self.table.rowCount() - 1
|
row = self.table.rowCount() - 1
|
||||||
if row >= 0:
|
if row >= 0:
|
||||||
|
@ -23,6 +23,7 @@ from calibre.utils.formatter import validation_formatter
|
|||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
from calibre.gui2.dialogs.comments_dialog import CommentsDialog
|
from calibre.gui2.dialogs.comments_dialog import CommentsDialog
|
||||||
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
||||||
|
from calibre.gui2.dialogs.tag_editor import TagEditor
|
||||||
from calibre.gui2.languages import LanguagesEdit
|
from calibre.gui2.languages import LanguagesEdit
|
||||||
|
|
||||||
class UpdateEditorGeometry(object):
|
class UpdateEditorGeometry(object):
|
||||||
@ -307,13 +308,22 @@ class CompleteDelegate(QStyledItemDelegate, UpdateEditorGeometry): # {{{
|
|||||||
|
|
||||||
def createEditor(self, parent, option, index):
|
def createEditor(self, parent, option, index):
|
||||||
if self.db and hasattr(self.db, self.items_func_name):
|
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 = EditWithComplete(parent)
|
||||||
editor.set_separator(self.sep)
|
editor.set_separator(self.sep)
|
||||||
editor.set_space_before_sep(self.space_before_sep)
|
editor.set_space_before_sep(self.space_before_sep)
|
||||||
if self.sep == '&':
|
if self.sep == '&':
|
||||||
editor.set_add_separator(tweaks['authors_completer_append_separator'])
|
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)()
|
all_items = getattr(self.db, self.items_func_name)()
|
||||||
else:
|
else:
|
||||||
all_items = list(self.db.all_custom(
|
all_items = list(self.db.all_custom(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user