Show completions when editing tags/authors/series etc in the Tag browser and Manage tags dialog. Fixes #1878302 [[Enhancement] Tag Manager Edit Enhancements](https://bugs.launchpad.net/calibre/+bug/1878302)

Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
Kovid Goyal 2020-05-13 21:30:07 +05:30
commit a4bb2b93f0
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 71 additions and 11 deletions

View File

@ -7,7 +7,7 @@ __license__ = 'GPL v3'
from PyQt5.Qt import (Qt, QDialog, QTableWidgetItem, QAbstractItemView, QIcon, from PyQt5.Qt import (Qt, QDialog, QTableWidgetItem, QAbstractItemView, QIcon,
QDialogButtonBox, QFrame, QLabel, QTimer, QMenu, QApplication, QDialogButtonBox, QFrame, QLabel, QTimer, QMenu, QApplication,
QByteArray) QByteArray, QItemDelegate)
from calibre.ebooks.metadata import author_to_author_sort, string_to_authors from calibre.ebooks.metadata import author_to_author_sort, string_to_authors
from calibre.gui2 import error_dialog, gprefs from calibre.gui2 import error_dialog, gprefs
@ -24,6 +24,24 @@ class tableItem(QTableWidgetItem):
def __lt__(self, other): def __lt__(self, other):
return sort_key(unicode_type(self.text())) < sort_key(unicode_type(other.text())) return sort_key(unicode_type(self.text())) < sort_key(unicode_type(other.text()))
class EditColumnDelegate(QItemDelegate):
def __init__(self, completion_data):
QItemDelegate.__init__(self)
self.completion_data = completion_data
def createEditor(self, parent, option, index):
if index.column() == 0:
if self.completion_data:
from calibre.gui2.complete2 import EditWithComplete
editor = EditWithComplete(parent)
editor.set_separator(None)
editor.update_items_cache(self.completion_data)
else:
from calibre.gui2.widgets import EnLineEdit
editor = EnLineEdit(parent)
return editor
return QItemDelegate.createEditor(self, parent, option, index)
class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog): class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
@ -70,23 +88,27 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
auts = db.get_authors_with_ids() auts = db.get_authors_with_ids()
self.table.setRowCount(len(auts)) self.table.setRowCount(len(auts))
select_item = None select_item = None
for row, (id, author, sort, link) in enumerate(auts): completion_data = []
for row, (_id, author, sort, link) in enumerate(auts):
author = author.replace('|', ',') author = author.replace('|', ',')
self.authors[id] = (author, sort, link) self.authors[_id] = (author, sort, link)
completion_data.append(author)
aut = tableItem(author) aut = tableItem(author)
aut.setData(Qt.UserRole, id) aut.setData(Qt.UserRole, _id)
sort = tableItem(sort) sort = tableItem(sort)
link = tableItem(link) link = tableItem(link)
self.table.setItem(row, 0, aut) self.table.setItem(row, 0, aut)
self.table.setItem(row, 1, sort) self.table.setItem(row, 1, sort)
self.table.setItem(row, 2, link) self.table.setItem(row, 2, link)
if id_to_select in (id, author): if id_to_select in (_id, author):
if select_sort: if select_sort:
select_item = sort select_item = sort
elif select_link: elif select_link:
select_item = link select_item = link
else: else:
select_item = aut select_item = aut
self.table.setItemDelegate(EditColumnDelegate(completion_data))
self.table.resizeColumnsToContents() self.table.resizeColumnsToContents()
if self.table.columnWidth(2) < 200: if self.table.columnWidth(2) < 200:
self.table.setColumnWidth(2, 200) self.table.setColumnWidth(2, 200)

View File

@ -82,15 +82,26 @@ class EditColumnDelegate(QItemDelegate):
def __init__(self, table): def __init__(self, table):
QItemDelegate.__init__(self) QItemDelegate.__init__(self)
self.table = table self.table = table
self.completion_data = None
def set_completion_data(self, data):
self.completion_data = data
def createEditor(self, parent, option, index): def createEditor(self, parent, option, index):
item = self.table.item(index.row(), 0)
if index.column() == 0: if index.column() == 0:
item = self.table.item(index.row(), 0) item = self.table.item(index.row(), 0)
if item.is_deleted: if item.is_deleted:
return None return None
return QItemDelegate.createEditor(self, parent, option, index) if self.completion_data:
from calibre.gui2.complete2 import EditWithComplete
editor = EditWithComplete(parent)
editor.set_separator(None)
editor.update_items_cache(self.completion_data)
else:
from calibre.gui2.widgets import EnLineEdit
editor = EnLineEdit(parent)
return editor
return None
class TagListEditor(QDialog, Ui_TagListEditor): class TagListEditor(QDialog, Ui_TagListEditor):
@ -139,7 +150,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)) self.edit_delegate = EditColumnDelegate(self.table)
self.table.setItemDelegateForColumn(0, self.edit_delegate)
# Add the data # Add the data
select_item = self.fill_in_table(None, tag_to_match) select_item = self.fill_in_table(None, tag_to_match)
@ -185,6 +197,8 @@ class TagListEditor(QDialog, Ui_TagListEditor):
self.all_tags[v] = {'key': k, 'count': count, 'cur_name': v, self.all_tags[v] = {'key': k, 'count': count, 'cur_name': v,
'is_deleted': k in self.to_delete} 'is_deleted': k in self.to_delete}
self.original_names[k] = v self.original_names[k] = v
self.edit_delegate.set_completion_data(self.original_names.values())
self.ordered_tags = sorted(self.all_tags.keys(), key=self.sorter) self.ordered_tags = sorted(self.all_tags.keys(), key=self.sorter)
if tags is None: if tags is None:
tags = self.ordered_tags tags = self.ordered_tags

View File

@ -18,8 +18,10 @@ from PyQt5.Qt import (
from calibre import sanitize_file_name from calibre import sanitize_file_name
from calibre.constants import config_dir from calibre.constants import config_dir
from calibre.ebooks.metadata import rating_to_stars from calibre.ebooks.metadata import rating_to_stars
from calibre.gui2.complete2 import EditWithComplete
from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES, from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES,
TagsModel, DRAG_IMAGE_ROLE, COUNT_ROLE) TagsModel, DRAG_IMAGE_ROLE, COUNT_ROLE)
from calibre.gui2.widgets import EnLineEdit
from calibre.gui2 import config, gprefs, choose_files, pixmap_to_data, rating_font, empty_index from calibre.gui2 import config, gprefs, choose_files, pixmap_to_data, rating_font, empty_index
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
from calibre.utils.serialize import json_loads from calibre.utils.serialize import json_loads
@ -33,6 +35,7 @@ class TagDelegate(QStyledItemDelegate): # {{{
self.old_look = False self.old_look = False
self.rating_pat = re.compile(r'[%s]' % rating_to_stars(3, True)) self.rating_pat = re.compile(r'[%s]' % rating_to_stars(3, True))
self.rating_font = QFont(rating_font()) self.rating_font = QFont(rating_font())
self.completion_data = None
def draw_average_rating(self, item, style, painter, option, widget): def draw_average_rating(self, item, style, painter, option, widget):
rating = item.average_rating rating = item.average_rating
@ -118,6 +121,18 @@ class TagDelegate(QStyledItemDelegate): # {{{
if item.type == TagTreeItem.TAG and item.tag.state == 0 and config['show_avg_rating']: if item.type == TagTreeItem.TAG and item.tag.state == 0 and config['show_avg_rating']:
self.draw_average_rating(item, style, painter, option, widget) self.draw_average_rating(item, style, painter, option, widget)
def set_completion_data(self, data):
self.completion_data = data
def createEditor(self, parent, option, index):
if self.completion_data:
editor = EditWithComplete(parent)
editor.set_separator(None)
editor.update_items_cache(self.completion_data)
else:
editor = EnLineEdit(parent)
return editor
# }}} # }}}
@ -403,14 +418,23 @@ class TagsView(QTreeView): # {{{
self.recount() self.recount()
return return
def set_completion_data(category):
try:
completion_data = self.db.new_api.all_field_names(category)
except:
completion_data = None
self.itemDelegate().set_completion_data(completion_data)
if action == 'edit_item_no_vl': if action == 'edit_item_no_vl':
item = self.model().get_node(index) item = self.model().get_node(index)
item.use_vl = False item.use_vl = False
set_completion_data(category)
self.edit(index) self.edit(index)
return return
if action == 'edit_item_in_vl': if action == 'edit_item_in_vl':
item = self.model().get_node(index) item = self.model().get_node(index)
item.use_vl = True item.use_vl = True
set_completion_data(category)
self.edit(index) self.edit(index)
return return
if action == 'delete_item_in_vl': if action == 'delete_item_in_vl':
@ -538,11 +562,11 @@ class TagsView(QTreeView): # {{{
self.context_menu.addAction(self.rename_icon, self.context_menu.addAction(self.rename_icon,
_('Rename %s in Virtual library')%display_name(tag), _('Rename %s in Virtual library')%display_name(tag),
partial(self.context_menu_handler, action='edit_item_in_vl', partial(self.context_menu_handler, action='edit_item_in_vl',
index=index)) index=index, category=key))
self.context_menu.addAction(self.rename_icon, self.context_menu.addAction(self.rename_icon,
_('Rename %s')%display_name(tag), _('Rename %s')%display_name(tag),
partial(self.context_menu_handler, action='edit_item_no_vl', partial(self.context_menu_handler, action='edit_item_no_vl',
index=index)) index=index, category=key))
if key in ('tags', 'series', 'publisher') or \ if key in ('tags', 'series', 'publisher') or \
self._model.db.field_metadata.is_custom_field(key): self._model.db.field_metadata.is_custom_field(key):
if self.model().get_in_vl(): if self.model().get_in_vl():