mirror of
https://github.com/kovidgoyal/calibre.git
synced 2026-01-04 03:00:20 -05:00
Enhancement 2120768: up/down arrows for setting metadata edit order
I changed all the row move buttons in Preferences to use the Shift (move 5), Ctrl (move 10), and Ctrl-Shirt (move to end). This involved a fair bit of refactoring. It is possible that I missed the buttons somewhere.
This commit is contained in:
parent
4d0bee8870
commit
bdaa04430f
@ -5,6 +5,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from functools import partial
|
||||
import textwrap
|
||||
|
||||
from qt.core import (
|
||||
@ -480,8 +481,8 @@ def show_config_widget(category, name, gui=None, show_restart_msg=False,
|
||||
class ListViewWithMoveByKeyPress(QListView):
|
||||
|
||||
def set_movement_functions(self, up_function, down_function):
|
||||
self.up_function = up_function
|
||||
self.down_function = down_function
|
||||
self.up_function = partial(up_function, use_kbd_modifiers=False)
|
||||
self.down_function = partial(down_function, use_kbd_modifiers=False)
|
||||
|
||||
def event(self, event):
|
||||
if (event.type() == QEvent.KeyPress and
|
||||
@ -497,8 +498,8 @@ class ListViewWithMoveByKeyPress(QListView):
|
||||
class ListWidgetWithMoveByKeyPress(QListWidget):
|
||||
|
||||
def set_movement_functions(self, up_function, down_function):
|
||||
self.up_function = up_function
|
||||
self.down_function = down_function
|
||||
self.up_function = partial(up_function, use_kbd_modifiers=False)
|
||||
self.down_function = partial(down_function, use_kbd_modifiers=False)
|
||||
|
||||
def event(self, event):
|
||||
if (event.type() == QEvent.KeyPress and
|
||||
@ -514,8 +515,8 @@ class ListWidgetWithMoveByKeyPress(QListWidget):
|
||||
class TableWidgetWithMoveByKeyPress(QTableWidget):
|
||||
|
||||
def set_movement_functions(self, up_function, down_function):
|
||||
self.up_function = up_function
|
||||
self.down_function = down_function
|
||||
self.up_function = partial(up_function, use_kbd_modifiers=False)
|
||||
self.down_function = partial(down_function, use_kbd_modifiers=False)
|
||||
|
||||
def event(self, event):
|
||||
if (event.type() == QEvent.KeyPress and
|
||||
@ -528,6 +529,19 @@ class TableWidgetWithMoveByKeyPress(QTableWidget):
|
||||
return QTableWidget.event(self, event)
|
||||
|
||||
|
||||
def get_move_count(row_count):
|
||||
mods = QApplication.keyboardModifiers()
|
||||
if mods == Qt.KeyboardModifier.ShiftModifier:
|
||||
count = 5
|
||||
elif mods == Qt.KeyboardModifier.ControlModifier:
|
||||
count = 10
|
||||
elif mods == (Qt.KeyboardModifier.ShiftModifier | Qt.KeyboardModifier.ControlModifier):
|
||||
count = row_count
|
||||
else:
|
||||
count = 1
|
||||
return count
|
||||
|
||||
|
||||
# Testing {{{
|
||||
|
||||
def test_widget(category, name, gui=None, callback=None):
|
||||
|
||||
@ -16,7 +16,7 @@ from calibre.ebooks import BOOK_EXTENSIONS
|
||||
from calibre.ebooks.oeb.iterator import is_supported
|
||||
from calibre.gui2 import config, dynamic, gprefs, info_dialog
|
||||
from calibre.gui2.actions.choose_library import get_change_library_action_plugin
|
||||
from calibre.gui2.preferences import ConfigWidgetBase, Setting, test_widget
|
||||
from calibre.gui2.preferences import ConfigWidgetBase, get_move_count, Setting, test_widget
|
||||
from calibre.gui2.preferences.behavior_ui import Ui_Form
|
||||
from calibre.utils.config import prefs
|
||||
from calibre.utils.icu import sort_key
|
||||
@ -67,9 +67,10 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
r('virtual_lib_on_startup', db.prefs, choices=choices)
|
||||
self.reset_confirmation_button.clicked.connect(self.reset_confirmation_dialogs)
|
||||
|
||||
self.input_up_button.clicked.connect(self.up_input)
|
||||
self.input_down_button.clicked.connect(self.down_input)
|
||||
self.opt_input_order.set_movement_functions(self.up_input, self.down_input)
|
||||
self.input_up_button.clicked.connect(partial(self.up_input, use_kbd_modifiers=True))
|
||||
self.input_down_button.clicked.connect(partial(self.down_input, use_kbd_modifiers=True))
|
||||
self.opt_input_order.set_movement_functions(partial(self.up_input, use_kbd_modifiers=False),
|
||||
partial(self.down_input, use_kbd_modifiers=False))
|
||||
self.opt_input_order.dropEvent = partial(input_order_drop_event, self)
|
||||
for signal in ('Activated', 'Changed', 'DoubleClicked', 'Clicked'):
|
||||
signal = getattr(self.opt_internally_viewed_formats, 'item'+signal)
|
||||
@ -158,19 +159,23 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
item.setData(Qt.ItemDataRole.UserRole, (format))
|
||||
item.setFlags(Qt.ItemFlag.ItemIsEnabled|Qt.ItemFlag.ItemIsSelectable|Qt.ItemFlag.ItemIsDragEnabled)
|
||||
|
||||
def up_input(self, *args):
|
||||
idx = self.opt_input_order.currentRow()
|
||||
if idx > 0:
|
||||
self.opt_input_order.insertItem(idx-1, self.opt_input_order.takeItem(idx))
|
||||
self.opt_input_order.setCurrentRow(idx-1)
|
||||
self.changed_signal.emit()
|
||||
def up_input(self, use_kbd_modifiers, *args):
|
||||
count = get_move_count(self.opt_input_order.count()) if use_kbd_modifiers else 1
|
||||
for _ in range(count):
|
||||
idx = self.opt_input_order.currentRow()
|
||||
if idx > 0:
|
||||
self.opt_input_order.insertItem(idx-1, self.opt_input_order.takeItem(idx))
|
||||
self.opt_input_order.setCurrentRow(idx-1)
|
||||
self.changed_signal.emit()
|
||||
|
||||
def down_input(self, *args):
|
||||
idx = self.opt_input_order.currentRow()
|
||||
if idx < self.opt_input_order.count()-1:
|
||||
self.opt_input_order.insertItem(idx+1, self.opt_input_order.takeItem(idx))
|
||||
self.opt_input_order.setCurrentRow(idx+1)
|
||||
self.changed_signal.emit()
|
||||
def down_input(self, use_kbd_modifiers, *args):
|
||||
count = get_move_count(self.opt_input_order.count()) if use_kbd_modifiers else 1
|
||||
for _ in range(count):
|
||||
idx = self.opt_input_order.currentRow()
|
||||
if idx < self.opt_input_order.count()-1:
|
||||
self.opt_input_order.insertItem(idx+1, self.opt_input_order.takeItem(idx))
|
||||
self.opt_input_order.setCurrentRow(idx+1)
|
||||
self.changed_signal.emit()
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ from calibre.constants import config_dir
|
||||
from calibre.gui2 import choose_files, choose_save_file, error_dialog, gprefs, info_dialog, open_local_file, pixmap_to_data, question_dialog
|
||||
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
||||
from calibre.gui2.metadata.single_download import RichTextDelegate
|
||||
from calibre.gui2.preferences import ListViewWithMoveByKeyPress
|
||||
from calibre.gui2.preferences import get_move_count, ListViewWithMoveByKeyPress
|
||||
from calibre.gui2.widgets2 import ColorButton, FlowLayout, Separator
|
||||
from calibre.library.coloring import Rule, color_row_key, conditionable_columns, displayable_columns, rule_from_template
|
||||
from calibre.utils.icu import lower, sort_key
|
||||
@ -1275,27 +1275,29 @@ class EditRules(QWidget): # {{{
|
||||
self.model.remove_rule(row)
|
||||
self.changed.emit()
|
||||
|
||||
def move_rows(self, moving_up=True):
|
||||
sm = self.rules_view.selectionModel()
|
||||
rows = sorted(sm.selectedRows(), reverse=not moving_up)
|
||||
if rows:
|
||||
if rows[0].row() == (0 if moving_up else self.model.rowCount() - 1):
|
||||
return
|
||||
sm.clear()
|
||||
indices_to_select = []
|
||||
for idx in rows:
|
||||
if idx.isValid():
|
||||
idx = self.model.move(idx, -1 if moving_up else 1)
|
||||
if idx is not None:
|
||||
indices_to_select.append(idx)
|
||||
if indices_to_select:
|
||||
new_selections = QItemSelection()
|
||||
for idx in indices_to_select:
|
||||
new_selections.merge(QItemSelection(idx, idx),
|
||||
QItemSelectionModel.SelectionFlag.Select)
|
||||
sm.select(new_selections, QItemSelectionModel.SelectionFlag.Select)
|
||||
self.rules_view.scrollTo(indices_to_select[0])
|
||||
self.changed.emit()
|
||||
def move_rows(self, moving_up=True, use_kbd_modifiers=True):
|
||||
count = get_move_count(self.rules_view.model().rowCount()) if use_kbd_modifiers else 1
|
||||
for _ in range(count):
|
||||
sm = self.rules_view.selectionModel()
|
||||
rows = sorted(sm.selectedRows(), reverse=not moving_up)
|
||||
if rows:
|
||||
if rows[0].row() == (0 if moving_up else self.model.rowCount() - 1):
|
||||
return
|
||||
sm.clear()
|
||||
indices_to_select = []
|
||||
for idx in rows:
|
||||
if idx.isValid():
|
||||
idx = self.model.move(idx, -1 if moving_up else 1)
|
||||
if idx is not None:
|
||||
indices_to_select.append(idx)
|
||||
if indices_to_select:
|
||||
new_selections = QItemSelection()
|
||||
for idx in indices_to_select:
|
||||
new_selections.merge(QItemSelection(idx, idx),
|
||||
QItemSelectionModel.SelectionFlag.Select)
|
||||
sm.select(new_selections, QItemSelectionModel.SelectionFlag.Select)
|
||||
self.rules_view.scrollTo(indices_to_select[0])
|
||||
self.changed.emit()
|
||||
|
||||
def clear(self):
|
||||
self.model.clear()
|
||||
|
||||
@ -7,12 +7,13 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
import copy
|
||||
import sys
|
||||
from functools import partial
|
||||
from contextlib import suppress
|
||||
|
||||
from qt.core import QAbstractItemView, QApplication, QIcon, Qt, QTableWidgetItem
|
||||
from qt.core import QAbstractItemView, QIcon, Qt, QTableWidgetItem
|
||||
|
||||
from calibre.gui2 import Application, error_dialog, gprefs, question_dialog
|
||||
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
|
||||
from calibre.gui2.preferences import ConfigWidgetBase, get_move_count, test_widget
|
||||
from calibre.gui2.preferences.columns_ui import Ui_Form
|
||||
from calibre.gui2.preferences.create_custom_column import CreateCustomColumn
|
||||
|
||||
@ -42,8 +43,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
default=0) + 1
|
||||
self.created_count = self.initial_created_count
|
||||
|
||||
self.column_up.clicked.connect(self.up_column)
|
||||
self.column_down.clicked.connect(self.down_column)
|
||||
self.column_up.clicked.connect(partial(self.up_column, use_kbd_modifiers=True))
|
||||
self.column_down.clicked.connect(partial(self.down_column, use_kbd_modifiers=True))
|
||||
self.opt_columns.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
self.opt_columns.set_movement_functions(self.up_column, self.down_column)
|
||||
self.del_custcol_button.clicked.connect(self.del_custcol)
|
||||
@ -278,20 +279,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
key = self.opt_columns.item(row, self.KEY_COLUMN).text()
|
||||
self.setup_row(row, key, row, force_checked_to=checked)
|
||||
|
||||
def get_move_count(self):
|
||||
mods = QApplication.keyboardModifiers()
|
||||
if mods == Qt.KeyboardModifier.ShiftModifier:
|
||||
count = 5
|
||||
elif mods == Qt.KeyboardModifier.ControlModifier:
|
||||
count = 10
|
||||
elif mods == (Qt.KeyboardModifier.ShiftModifier | Qt.KeyboardModifier.ControlModifier):
|
||||
count = self.opt_columns.rowCount()
|
||||
else:
|
||||
count = 1
|
||||
return count
|
||||
|
||||
def up_column(self):
|
||||
count = self.get_move_count()
|
||||
def up_column(self, use_kbd_modifiers):
|
||||
count = get_move_count(self.opt_columns.rowCount()) if use_kbd_modifiers else 1
|
||||
for _ in range(count):
|
||||
row = self.opt_columns.currentRow()
|
||||
if row > 0:
|
||||
@ -307,8 +296,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
self.changed_signal.emit()
|
||||
self.opt_columns.setSortingEnabled(True)
|
||||
|
||||
def down_column(self):
|
||||
count = self.get_move_count()
|
||||
def down_column(self, use_kbd_modifiers):
|
||||
count = get_move_count(self.opt_columns.rowCount()) if use_kbd_modifiers else 1
|
||||
for _ in range(count):
|
||||
row = self.opt_columns.currentRow()
|
||||
if row < self.opt_columns.rowCount()-1:
|
||||
|
||||
@ -29,7 +29,7 @@ from calibre.ebooks.metadata.search_internet import qquote
|
||||
from calibre.gui2 import choose_files, choose_save_file, error_dialog
|
||||
from calibre.gui2.book_details import get_field_list
|
||||
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
||||
from calibre.gui2.preferences import LazyConfigWidgetBase
|
||||
from calibre.gui2.preferences import get_move_count, LazyConfigWidgetBase
|
||||
from calibre.gui2.preferences.coloring import EditRules
|
||||
from calibre.gui2.ui import get_gui
|
||||
from calibre.utils.formatter import EvalFormatter
|
||||
@ -204,6 +204,11 @@ class DisplayedFields(QAbstractListModel):
|
||||
self.db.new_api.set_pref(self.pref_name, self.fields)
|
||||
|
||||
def move(self, idx, delta):
|
||||
row = idx.row()
|
||||
if delta > 0:
|
||||
delta = delta if row + delta < self.rowCount() else self.rowCount() - row - 1
|
||||
else:
|
||||
delta = -row if row + delta < 0 else delta
|
||||
row = idx.row() + delta
|
||||
if row >= 0 and row < len(self.fields):
|
||||
t = self.fields[row]
|
||||
@ -294,20 +299,22 @@ def reset_layout(in_widget, model=None):
|
||||
in_widget.changed_signal.emit()
|
||||
|
||||
|
||||
def move_field_up(widget, model):
|
||||
def move_field_up(widget, model, *args, use_kbd_modifiers=True):
|
||||
count = get_move_count(model.rowCount()) if use_kbd_modifiers else 1
|
||||
idx = widget.currentIndex()
|
||||
if idx.isValid():
|
||||
idx = model.move(idx, -1)
|
||||
idx = model.move(idx, -count)
|
||||
if idx is not None:
|
||||
sm = widget.selectionModel()
|
||||
sm.select(idx, QItemSelectionModel.SelectionFlag.ClearAndSelect)
|
||||
widget.setCurrentIndex(idx)
|
||||
|
||||
|
||||
def move_field_down(widget, model):
|
||||
def move_field_down(widget, model, *args, use_kbd_modifiers=True):
|
||||
count = get_move_count(model.rowCount()) if use_kbd_modifiers else 1
|
||||
idx = widget.currentIndex()
|
||||
if idx.isValid():
|
||||
idx = model.move(idx, 1)
|
||||
idx = model.move(idx, count)
|
||||
if idx is not None:
|
||||
sm = widget.selectionModel()
|
||||
sm.select(idx, QItemSelectionModel.SelectionFlag.ClearAndSelect)
|
||||
|
||||
@ -208,8 +208,8 @@ class BookDetailsTab(LazyConfigWidgetBase, Ui_Form):
|
||||
self.field_display_order.setModel(self.display_model)
|
||||
mu = partial(move_field_up, self.field_display_order, self.display_model)
|
||||
md = partial(move_field_down, self.field_display_order, self.display_model)
|
||||
self.df_up_button.clicked.connect(mu)
|
||||
self.df_down_button.clicked.connect(md)
|
||||
self.df_up_button.clicked.connect(partial(mu, use_kbd_modifiers=True))
|
||||
self.df_down_button.clicked.connect(partial(md, use_kbd_modifiers=True))
|
||||
self.field_display_order.set_movement_functions(mu, md)
|
||||
|
||||
self.opt_book_details_css.textChanged.connect(self.changed_signal)
|
||||
|
||||
@ -57,8 +57,8 @@ class EditMetadataTab(LazyConfigWidgetBase, Ui_Form):
|
||||
mu = partial(move_field_up, self.em_display_order, self.em_display_model)
|
||||
md = partial(move_field_down, self.em_display_order, self.em_display_model)
|
||||
self.em_display_order.set_movement_functions(mu, md)
|
||||
self.em_up_button.clicked.connect(mu)
|
||||
self.em_down_button.clicked.connect(md)
|
||||
self.em_up_button.clicked.connect(partial(mu, use_kbd_modifiers=True))
|
||||
self.em_down_button.clicked.connect(partial(md, use_kbd_modifiers=True))
|
||||
self.em_export_layout_button.clicked.connect(partial(export_layout, self, model=self.em_display_model))
|
||||
self.em_import_layout_button.clicked.connect(partial(import_layout, self, model=self.em_display_model))
|
||||
self.em_reset_layout_button.clicked.connect(partial(reset_layout, model=self.em_display_model))
|
||||
|
||||
@ -50,8 +50,8 @@ class QuickviewTab(LazyConfigWidgetBase, Ui_Form):
|
||||
mu = partial(move_field_up, self.qv_display_order, self.qv_display_model)
|
||||
md = partial(move_field_down, self.qv_display_order, self.qv_display_model)
|
||||
self.qv_display_order.set_movement_functions(mu, md)
|
||||
self.qv_up_button.clicked.connect(mu)
|
||||
self.qv_down_button.clicked.connect(md)
|
||||
self.qv_up_button.clicked.connect(partial(mu, use_kbd_modifiers=True))
|
||||
self.qv_down_button.clicked.connect(partial(md, use_kbd_modifiers=True))
|
||||
|
||||
def lazy_initialize(self):
|
||||
self.qv_display_model.initialize()
|
||||
|
||||
@ -71,37 +71,17 @@ class TbDisplayTab(LazyConfigWidgetBase, Ui_Form):
|
||||
self.tb_reset_layout_button.clicked.connect(partial(reset_layout, self, model=self.tb_display_model))
|
||||
self.tb_export_layout_button.clicked.connect(partial(export_layout, self, model=self.tb_display_model))
|
||||
self.tb_import_layout_button.clicked.connect(partial(import_layout, self, model=self.tb_display_model))
|
||||
self.tb_up_button.clicked.connect(self.tb_up_button_clicked)
|
||||
self.tb_down_button.clicked.connect(self.tb_down_button_clicked)
|
||||
self.tb_display_order.set_movement_functions(self.tb_up_button_clicked, self.tb_down_button_clicked)
|
||||
|
||||
mu = partial(move_field_up, self.tb_display_order, self.tb_display_model)
|
||||
md = partial(move_field_down, self.tb_display_order, self.tb_display_model)
|
||||
self.tb_up_button.clicked.connect(partial(mu, use_kbd_modifiers=True))
|
||||
self.tb_down_button.clicked.connect(partial(md, use_kbd_modifiers=True))
|
||||
self.tb_display_order.set_movement_functions(mu, md)
|
||||
|
||||
def lazy_initialize(self):
|
||||
self.tb_display_model.initialize()
|
||||
self.tb_focus_label.setVisible(self.opt_tag_browser_allow_keyboard_focus.isChecked())
|
||||
|
||||
def tb_down_button_clicked(self):
|
||||
idx = self.tb_display_order.currentIndex()
|
||||
if idx.isValid():
|
||||
row = idx.row()
|
||||
model = self.tb_display_model
|
||||
fields = model.fields
|
||||
key = fields[row][0]
|
||||
if not is_standard_category(key):
|
||||
return
|
||||
if row < len(fields) and is_standard_category(fields[row+1][0]):
|
||||
move_field_down(self.tb_display_order, model)
|
||||
|
||||
def tb_up_button_clicked(self):
|
||||
idx = self.tb_display_order.currentIndex()
|
||||
if idx.isValid():
|
||||
row = idx.row()
|
||||
model = self.tb_display_model
|
||||
fields = model.fields
|
||||
key = fields[row][0]
|
||||
if not is_standard_category(key):
|
||||
return
|
||||
move_field_up(self.tb_display_order, model)
|
||||
|
||||
def restore_defaults(self):
|
||||
LazyConfigWidgetBase.restore_defaults(self)
|
||||
self.tb_display_model.restore_defaults()
|
||||
|
||||
@ -100,7 +100,7 @@ class TbHierarchyTab(LazyConfigWidgetBase, Ui_Form):
|
||||
self.tb_search_order.addItem(item)
|
||||
node = v
|
||||
|
||||
def move_tb_search_up(self):
|
||||
def move_tb_search_up(self, *args, **kwargs):
|
||||
idx = self.tb_search_order.currentRow()
|
||||
if idx <= 0:
|
||||
return
|
||||
@ -109,7 +109,7 @@ class TbHierarchyTab(LazyConfigWidgetBase, Ui_Form):
|
||||
self.tb_search_order.setCurrentRow(idx-1)
|
||||
self.changed_signal.emit()
|
||||
|
||||
def move_tb_search_down(self):
|
||||
def move_tb_search_down(self, *args, **kwargs):
|
||||
idx = self.tb_search_order.currentRow()
|
||||
if idx < 0 or idx == 3:
|
||||
return
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user