diff --git a/src/calibre/gui2/preferences/__init__.py b/src/calibre/gui2/preferences/__init__.py index 9308fd7166..c27c0922cc 100644 --- a/src/calibre/gui2/preferences/__init__.py +++ b/src/calibre/gui2/preferences/__init__.py @@ -5,6 +5,7 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __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): diff --git a/src/calibre/gui2/preferences/behavior.py b/src/calibre/gui2/preferences/behavior.py index ba758ca7d2..1007cbbf80 100644 --- a/src/calibre/gui2/preferences/behavior.py +++ b/src/calibre/gui2/preferences/behavior.py @@ -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() # }}} diff --git a/src/calibre/gui2/preferences/coloring.py b/src/calibre/gui2/preferences/coloring.py index f58e0cb66c..aadd56c549 100644 --- a/src/calibre/gui2/preferences/coloring.py +++ b/src/calibre/gui2/preferences/coloring.py @@ -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() diff --git a/src/calibre/gui2/preferences/columns.py b/src/calibre/gui2/preferences/columns.py index f7e2e7a830..83ac1caffb 100644 --- a/src/calibre/gui2/preferences/columns.py +++ b/src/calibre/gui2/preferences/columns.py @@ -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: diff --git a/src/calibre/gui2/preferences/look_feel_tabs/__init__.py b/src/calibre/gui2/preferences/look_feel_tabs/__init__.py index 5a26182ef8..b9d2a0342d 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/__init__.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/__init__.py @@ -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) diff --git a/src/calibre/gui2/preferences/look_feel_tabs/book_details.py b/src/calibre/gui2/preferences/look_feel_tabs/book_details.py index 5f2780d62f..81cc008980 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/book_details.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/book_details.py @@ -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) diff --git a/src/calibre/gui2/preferences/look_feel_tabs/edit_metadata.py b/src/calibre/gui2/preferences/look_feel_tabs/edit_metadata.py index dcf6b17742..e74c2dddce 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/edit_metadata.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/edit_metadata.py @@ -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)) diff --git a/src/calibre/gui2/preferences/look_feel_tabs/quickview.py b/src/calibre/gui2/preferences/look_feel_tabs/quickview.py index 5fafe4530d..1cd7142d8d 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/quickview.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/quickview.py @@ -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() diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_display.py b/src/calibre/gui2/preferences/look_feel_tabs/tb_display.py index a29b390d06..3bbd9c138d 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/tb_display.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_display.py @@ -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() diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_hierarchy.py b/src/calibre/gui2/preferences/look_feel_tabs/tb_hierarchy.py index d14ec2c63d..d52e304383 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/tb_hierarchy.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_hierarchy.py @@ -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