Skip to content

Instantly share code, notes, and snippets.

@LegoStormtroopr
Last active June 13, 2019 14:37
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LegoStormtroopr/6146161 to your computer and use it in GitHub Desktop.
Save LegoStormtroopr/6146161 to your computer and use it in GitHub Desktop.
A BackTab Friendly QTextEdit for PyQt. Allows a user to use Tab/Shift-Tab to indent and un-indent text in a QTextEdit - it also works in QPlaintextEdit A workable solution to this StackOverflow question: http://stackoverflow.com/questions/13579116/qtextedit-shift-tab-wrong-behaviour/18032320#18032320
import sys
from PyQt4 import QtCore, QtGui
class TabPlainTextEdit(QtGui.QTextEdit):
def __init__(self,parent):
QtGui.QTextEdit.__init__(self, parent)
def keyPressEvent(self, event):
# Shift + Tab is not the same as trying to catch a Shift modifier and a tab Key.
# Shift + Tab is a Backtab!!
if event.key() == QtCore.Qt.Key_Backtab:
cur = self.textCursor()
# Copy the current selection
pos = cur.position() # Where a selection ends
anchor = cur.anchor() # Where a selection starts (can be the same as above)
# Can put QtGui.QTextCursor.MoveAnchor as the 2nd arg, but this is the default
cur.setPosition(pos)
# Move the position back one, selection the character prior to the original position
cur.setPosition(pos-1,QtGui.QTextCursor.KeepAnchor)
if str(cur.selectedText()) == "\t":
# The prior character is a tab, so delete the selection
cur.removeSelectedText()
# Reposition the cursor with the one character offset
cur.setPosition(anchor-1)
cur.setPosition(pos-1,QtGui.QTextCursor.KeepAnchor)
else:
# Try all of the above, looking before the anchor (This helps if the achor is before a tab)
cur.setPosition(anchor)
cur.setPosition(anchor-1,QtGui.QTextCursor.KeepAnchor)
if str(cur.selectedText()) == "\t":
cur.removeSelectedText()
cur.setPosition(anchor-1)
cur.setPosition(pos-1,QtGui.QTextCursor.KeepAnchor)
else:
# Its not a tab, so reset the selection to what it was
cur.setPosition(anchor)
cur.setPosition(pos,QtGui.QTextCursor.KeepAnchor)
else:
return QtGui.QTextEdit.keyPressEvent(self, event)
def main():
app = QtGui.QApplication(sys.argv)
w = TabPlainTextEdit(None)
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
@onlyjus
Copy link

onlyjus commented Jun 13, 2019

I found a better way to do this (handles spaces as too):

        tab_char = '\t' # could be anything including spaces
        if event.key() == QtCore.Qt.Key_Backtab:
            # get current cursor
            cur = self.textCursor()
            cur.clearSelection()
 
            # move to begining of line and select text to first word
            cur.movePosition(QtGui.QTextCursor.StartOfLine)
            cur.movePosition(QtGui.QTextCursor.NextWord, QtGui.QTextCursor.KeepAnchor)
            sel_text = cur.selectedText()

            # if the text starts with the tab_char, replace it
            if sel_text.startswith(tab_char):
                text = sel_text.replace(tab_char, '', 1)
                cur.insertText(text)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment