Edit book: Nicer UI for changing the entries in the insert tag menu

This commit is contained in:
copilot-swe-agent[bot] 2026-02-25 09:53:57 +00:00 committed by Kovid Goyal
parent e579327c22
commit 748368eda2
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 131 additions and 22 deletions

View File

@ -12,9 +12,9 @@ from qt.core import (
QAction,
QApplication,
QColor,
QDialog,
QIcon,
QImage,
QInputDialog,
QMainWindow,
QMenu,
QPainter,
@ -263,11 +263,7 @@ class Editor(QMainWindow):
for name in names:
m.addAction(name, partial(self.insert_tag, name))
m.addSeparator()
m.addAction(_('Add a tag to this menu'), self.add_insert_tag)
if names:
m = m.addMenu(_('Remove from this menu'))
for name in names:
m.addAction(name, partial(self.remove_insert_tag, name))
m.addAction(_('Manage the entries in this menu'), self.manage_insert_tags)
def insert_tag(self, name):
self.editor.insert_tag(name)
@ -280,24 +276,12 @@ class Editor(QMainWindow):
tprefs['insert_tag_mru'] = mru
self._build_insert_tag_button_menu()
def add_insert_tag(self):
name, ok = QInputDialog.getText(self, _('Name of tag to add'), _(
'Enter the name of the tag'))
if ok:
mru = tprefs['insert_tag_mru']
mru.insert(0, name)
tprefs['insert_tag_mru'] = mru
def manage_insert_tags(self):
from calibre.gui2.tweak_book.widgets import ManageTagList
d = ManageTagList(self)
if d.exec() == QDialog.DialogCode.Accepted:
self._build_insert_tag_button_menu()
def remove_insert_tag(self, name):
mru = tprefs['insert_tag_mru']
try:
mru.remove(name)
except ValueError:
pass
tprefs['insert_tag_mru'] = mru
self._build_insert_tag_button_menu()
def set_request_completion(self, callback=None, doc_name=None):
self.editor.request_completion = callback
self.editor.completion_doc_name = doc_name

View File

@ -5,12 +5,14 @@ __license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
import os
import re
import textwrap
import unicodedata
from collections import OrderedDict
from math import ceil
from qt.core import (
QAbstractItemView,
QAbstractListModel,
QApplication,
QCheckBox,
@ -24,6 +26,7 @@ from qt.core import (
QGroupBox,
QHBoxLayout,
QIcon,
QInputDialog,
QItemSelectionModel,
QLabel,
QLineEdit,
@ -34,6 +37,7 @@ from qt.core import (
QPixmap,
QPlainTextEdit,
QPoint,
QPushButton,
QRect,
QSize,
QSizePolicy,
@ -46,6 +50,8 @@ from qt.core import (
QTextDocument,
QTextOption,
QToolButton,
QTreeWidget,
QTreeWidgetItem,
QVBoxLayout,
QWidget,
pyqtSignal,
@ -109,6 +115,125 @@ class InsertTag(Dialog): # {{{
# }}}
class ManageTagList(Dialog): # {{{
_tag_re = re.compile(r'[a-zA-Z0-9:-]+')
def __init__(self, parent=None):
self._entries = list(tprefs['insert_tag_mru'])
Dialog.__init__(self, _('Manage tag list'), 'manage-insert-tag-list', parent=parent)
def setup_ui(self):
self.l = l = QVBoxLayout(self)
self.tree = t = QTreeWidget(self)
t.setHeaderHidden(True)
t.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
l.addWidget(t)
bh = QHBoxLayout()
self.add_button = ab = QPushButton(_('&Add'))
ab.clicked.connect(self._add_entry)
bh.addWidget(ab)
self.edit_button = eb = QPushButton(_('&Edit'))
eb.clicked.connect(self._edit_entry)
bh.addWidget(eb)
self.remove_button = rb = QPushButton(_('&Remove'))
rb.clicked.connect(self._remove_entry)
bh.addWidget(rb)
bh.addStretch()
l.addLayout(bh)
l.addWidget(self.bb)
t.itemSelectionChanged.connect(self._update_button_states)
self._populate_tree()
self._update_button_states()
def _tag_name(self, entry):
m = self._tag_re.match(entry)
return m.group() if m else entry
def _populate_tree(self):
self.tree.clear()
groups = {}
for entry in self._entries:
tag_name = self._tag_name(entry)
groups.setdefault(tag_name, []).append(entry)
for tag_name in sorted(groups, key=primary_sort_key):
parent_item = QTreeWidgetItem([tag_name])
parent_item.setFlags(parent_item.flags() & ~Qt.ItemFlag.ItemIsSelectable)
for entry in sorted(groups[tag_name], key=primary_sort_key):
child = QTreeWidgetItem([entry])
child.setData(0, Qt.ItemDataRole.UserRole, entry)
parent_item.addChild(child)
self.tree.addTopLevelItem(parent_item)
parent_item.setExpanded(True)
self._update_button_states()
def _current_entry(self):
item = self.tree.currentItem()
if item is None:
return None
return item.data(0, Qt.ItemDataRole.UserRole)
def _update_button_states(self):
has_entry = self._current_entry() is not None
self.edit_button.setEnabled(has_entry)
self.remove_button.setEnabled(has_entry)
def _add_entry(self):
name, ok = QInputDialog.getText(
self, _('Add tag'),
_('Enter the tag to add (may include attributes, for example: div class="chapter"):'))
if ok:
name = name.strip()
if not name:
return
if name in self._entries:
error_dialog(self, _('Already exists'),
_('The entry {!r} already exists in the list.').format(name), show=True)
return
self._entries.insert(0, name)
self._populate_tree()
def _edit_entry(self):
old_entry = self._current_entry()
if old_entry is None:
return
name, ok = QInputDialog.getText(
self, _('Edit tag'), _('Edit the tag:'), text=old_entry)
if ok:
name = name.strip()
if not name or name == old_entry:
return
if name in self._entries:
error_dialog(self, _('Already exists'),
_('The entry {!r} already exists in the list.').format(name), show=True)
return
idx = self._entries.index(old_entry)
self._entries[idx] = name
self._populate_tree()
def _remove_entry(self):
entry = self._current_entry()
if entry is None:
return
try:
self._entries.remove(entry)
except ValueError:
pass
self._populate_tree()
def accept(self):
tprefs['insert_tag_mru'] = self._entries
Dialog.accept(self)
# }}}
class RationalizeFolders(Dialog): # {{{
TYPE_MAP = (