Edit book: When text is selected allow changing the indentation of all lines in the selection by pressing Tab to increase one level or Shift+Tab to decrease one level. Fixes #2076251 [[Edit Book][Enhancement] Allow to indent all selected lines at once](https://bugs.launchpad.net/calibre/+bug/2076251)

This commit is contained in:
Kovid Goyal 2024-08-14 21:42:00 +05:30
parent 3d477b904c
commit 5fc10a7af1
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 62 additions and 8 deletions

View File

@ -72,7 +72,7 @@ class Smarts(NullSmarts):
if key == Qt.Key.Key_Home and smart_home(editor, ev):
return True
if key == Qt.Key.Key_Tab:
if key in (Qt.Key.Key_Tab, Qt.Key.Key_Backtab):
mods = ev.modifiers()
if not mods & Qt.KeyboardModifier.ControlModifier and smart_tab(editor, ev):
return True

View File

@ -732,7 +732,7 @@ class Smarts(NullSmarts):
if key == Qt.Key.Key_Home and smart_home(editor, ev):
return True
if key == Qt.Key.Key_Tab:
if key in (Qt.Key.Key_Tab, Qt.Key.Key_Backtab):
if not mods & Qt.KeyboardModifier.ControlModifier and smart_tab(editor, ev):
return True

View File

@ -36,7 +36,7 @@ class Smarts(NullSmarts):
def handle_key_press(self, ev, editor):
key = ev.key()
if key == Qt.Key.Key_Tab:
if key in (Qt.Key.Key_Tab, Qt.Key.Key_Backtab):
mods = ev.modifiers()
if not mods & Qt.KeyboardModifier.ControlModifier and smart_tab(editor, ev):
return True

View File

@ -74,19 +74,73 @@ def expand_tabs(text, tw):
return text.replace('\t', ' ' * tw)
def smart_tab(editor, ev):
def smart_tab_if_whitespace_only_before_cursor(editor, backwards):
cursor, text = get_text_before_cursor(editor)
if not text.lstrip():
# cursor is preceded by only whitespace
tw = editor.tw
text = expand_tabs(text, tw)
spclen = len(text) - (len(text) % tw) + tw
cursor.insertText(' ' * spclen)
editor.setTextCursor(cursor)
return True
if backwards:
if leading := len(text):
new_leading = max(0, leading - tw)
extra = new_leading % tw
if extra:
new_leading += tw - extra
cursor.insertText(' ' * new_leading)
return True
else:
spclen = len(text) - (len(text) % tw) + tw
cursor.insertText(' ' * spclen)
editor.setTextCursor(cursor)
return True
return False
def smart_tab_all_blocks_in_selection(editor, backwards):
cursor = editor.textCursor()
c = QTextCursor(cursor)
c.clearSelection()
c.setPosition(cursor.selectionStart())
tab_width = editor.tw
changed = False
while not c.atEnd() and c.position() <= cursor.selectionEnd():
c.clearSelection()
c.movePosition(QTextCursor.MoveOperation.EndOfBlock)
c.movePosition(QTextCursor.MoveOperation.StartOfBlock, QTextCursor.MoveMode.KeepAnchor)
c.movePosition(QTextCursor.MoveOperation.StartOfBlock)
# select leading whitespace
while not c.atEnd() and c.document().characterAt(c.position()).isspace():
c.movePosition(QTextCursor.MoveOperation.NextCharacter, QTextCursor.MoveMode.KeepAnchor)
text = expand_tabs(editor.selected_text_from_cursor(c), tab_width)
leading = len(text)
replaced = False
if backwards:
if leading:
new_leading = max(0, leading - tab_width)
extra = new_leading % tab_width
if extra:
new_leading += tab_width - extra
replaced = True
else:
new_leading = leading + tab_width
new_leading -= new_leading % tab_width
replaced = True
if replaced:
c.insertText(' ' * new_leading)
changed = True
c.movePosition(QTextCursor.MoveOperation.NextBlock)
c.movePosition(QTextCursor.MoveOperation.StartOfBlock)
return changed
def smart_tab(editor, ev):
cursor = editor.textCursor()
backwards = ev.key() == Qt.Key.Key_Backtab or (ev.key() == Qt.Key.Key_Tab and bool(ev.modifiers() & Qt.KeyboardModifier.ShiftModifier))
if cursor.hasSelection():
return smart_tab_all_blocks_in_selection(editor, backwards)
return smart_tab_if_whitespace_only_before_cursor(editor, backwards)
def smart_backspace(editor, ev):
if editor.textCursor().hasSelection():
return False