diff --git a/src/calibre/gui2/actions/sort.py b/src/calibre/gui2/actions/sort.py index 2159f9c0da..b587b7cb27 100644 --- a/src/calibre/gui2/actions/sort.py +++ b/src/calibre/gui2/actions/sort.py @@ -5,30 +5,19 @@ __license__ = 'GPL v3' __copyright__ = '2013, Kovid Goyal ' from contextlib import suppress -from functools import partial -from qt.core import QAction, QDialog, QIcon, QToolButton, pyqtSignal +from qt.core import ( + QAbstractItemView, QAction, QDialog, QDialogButtonBox, QIcon, QListWidget, + QListWidgetItem, QSize, Qt, QToolButton, QVBoxLayout, pyqtSignal, +) from calibre.gui2.actions import InterfaceAction -from calibre.utils.icu import primary_sort_key from calibre.library.field_metadata import category_icon_map +from calibre.utils.icu import primary_sort_key from polyglot.builtins import iteritems SORT_HIDDEN_PREF = 'sort-action-hidden-fields' -def change_hidden(key, visible): - from calibre.gui2.ui import get_gui - gui = get_gui() - if gui is not None: - db = gui.current_db.new_api - val = set(db.pref(SORT_HIDDEN_PREF) or ()) - if visible: - val.discard(key) - else: - val.add(key) - db.set_pref(SORT_HIDDEN_PREF, tuple(val)) - - class SortAction(QAction): sort_requested = pyqtSignal(object, object) @@ -100,17 +89,10 @@ class SortByAction(InterfaceAction): fm = db.field_metadata name_map = {v:k for k, v in iteritems(fm.ui_sortable_field_keys())} hidden = frozenset(db.new_api.pref(SORT_HIDDEN_PREF, default=()) or ()) - hidden_items_menu = menu.addMenu(_('Select sortable columns')) + menu.addAction(_('Select sortable columns')).triggered.connect(self.select_sortable_columns) menu.addAction(_('Sort on multiple columns'), self.choose_multisort) menu.addSeparator() all_names = sorted(name_map, key=primary_sort_key) - for name in all_names: - key = name_map[name] - ac = hidden_items_menu.addAction(name) - ac.setCheckable(True) - ac.setChecked(key not in hidden) - ac.setObjectName(key) - ac.toggled.connect(partial(change_hidden, key)) for name in all_names: key = name_map[name] @@ -133,6 +115,35 @@ class SortByAction(InterfaceAction): else: menu.addAction(sac) + def select_sortable_columns(self): + db = self.gui.current_db + fm = db.field_metadata + name_map = {v:k for k, v in iteritems(fm.ui_sortable_field_keys())} + hidden = frozenset(db.new_api.pref(SORT_HIDDEN_PREF, default=()) or ()) + all_names = sorted(name_map, key=primary_sort_key) + items = QListWidget() + items.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection) + for display_name in all_names: + key = name_map[display_name] + i = QListWidgetItem(display_name, items) + i.setData(Qt.ItemDataRole.UserRole, key) + i.setSelected(key not in hidden) + d = QDialog(self.gui) + l = QVBoxLayout(d) + l.addWidget(items) + d.setWindowTitle(_('Select sortable columns')) + d.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) + d.bb.accepted.connect(d.accept) + d.bb.rejected.connect(d.reject) + l.addWidget(d.bb) + d.resize(d.sizeHint() + QSize(50, 100)) + if d.exec() == QDialog.DialogCode.Accepted: + hidden = [] + for i in (items.item(x) for x in range(items.count())): + if not i.isSelected(): + hidden.append(i.data(Qt.ItemDataRole.UserRole)) + db.new_api.set_pref(SORT_HIDDEN_PREF, tuple(hidden)) + def choose_multisort(self): from calibre.gui2.dialogs.multisort import ChooseMultiSort d = ChooseMultiSort(self.gui.current_db, parent=self.gui, is_device_connected=self.gui.device_connected)