Skip to content

Instantly share code, notes, and snippets.

@oglops
Last active July 14, 2016 05:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oglops/7fa0972e14871dce1174d8e2e0188ed6 to your computer and use it in GitHub Desktop.
Save oglops/7fa0972e14871dce1174d8e2e0188ed6 to your computer and use it in GitHub Desktop.
test toggling comment in qtextedit
import os
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import uic
import textwrap
from functools import partial
class MyWindow(QDialog):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
layout = QVBoxLayout()
textedit = QTextEdit()
code = '''
def myFunc(x):
print 'x=%s' % x
if 3>2:
print 'yeah!'
myFunc(1)
'''
code = textwrap.dedent(code).strip()
textedit.insertPlainText(code)
font = QFont('Monospace')
textedit.setFont(font)
buttons_to_create = [
('Current Pos', partial(self.test, 'current_pos')),
('Add Single Line Comment', partial(self.test, 'single_line_comment')),
('Get Range', partial(self.test, 'get_range')),
('Load Range', partial(self.test, 'load_range')),
('Toggle Multi Line Comment', self.toggle_comment),
('Get char at current pos',
partial(self.test, 'get_text_cur_pos')),
# ('Tab', partial(self.test, 'tab')),
# ('Shift + Tab', partial(self.test, 'shift_tab')),
('Tab', partial(self.tab, 'tab')),
('Shift + Tab', partial(self.tab, 'shift_tab')),
('Undo', partial(self.test, 'undo')),
]
buttons = []
for label, cmd in buttons_to_create:
btn = QPushButton(label)
btn.clicked.connect(cmd)
buttons.append(btn)
layout.addWidget(textedit)
for btn in buttons:
layout.addWidget(btn)
self.setLayout(layout)
self.textedit = textedit
self.init()
self.comment_string = '#'
# self.last_change=None
textedit.setLineWrapMode(QTextEdit.FixedPixelWidth)
textedit.setLineWrapColumnOrWidth(600)
def init(self):
# self.moveToPosition(25)
start_pos, end_pos = 21, 59
cursor = self.textedit.textCursor()
self.moveToPosition(start_pos)
# self.textedit.setTextCursor(cursor)
cursor = self.textedit.textCursor()
cursor.movePosition(
QTextCursor.Right, QTextCursor.KeepAnchor, end_pos-start_pos)
self.textedit.setTextCursor(cursor)
# test single text delete
# self.moveToPosition(start_pos)
# cursor = self.textedit.textCursor()
# cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor, 20)
# self.textedit.setTextCursor(cursor)
def moveToPosition(self, pos):
cursor = self.textedit.textCursor()
cursor.movePosition(QTextCursor.Start, QTextCursor.MoveAnchor)
cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor, pos)
self.textedit.setTextCursor(cursor)
def restore_selection(fn):
from functools import wraps
@wraps(fn)
def wrapper(self,*args, **kw):
print 'before'
self.test('get_range')
fn(self,*args, **kw)
print 'after'
self.test('load_range')
return wrapper
@restore_selection
def toggle_comment(self,*args):
self.last_change='toggle_comment'
self.test('multi_line_comment')
@restore_selection
def tab(self,mode='tab',*args):
self.test(mode)
def position_in_block(self,cursor):
# this can be replaced with cursor.positionInBlock after qt 4.7
pos = cursor.position()-cursor.block().position()
return pos
def get_line_range(self,cursor,start_pos,end_pos):
# if start_pos!=end_pos:
# find which line is left most
cursor.setPosition(end_pos)
last_line = cursor.block().blockNumber()
if cursor.atBlockStart() and start_pos != end_pos:
last_line -= 1
cursor.setPosition(start_pos)
first_line = cursor.block().blockNumber()
return (first_line,last_line)
def get_min_indent(self,cursor,start_pos,first_line,last_line):
# find the leftmost line and get its position
cursor.setPosition(start_pos)
indents = []
for _line_nb in range(first_line, last_line+1):
text = str(cursor.block().text())
indent = len(text)-len(text.lstrip())
# print 'line:',_line_nb,'indent:',indent
indents.append(indent)
cursor.movePosition(QTextCursor.NextBlock)
min_indent = min(indents)
print 'min_indent:', min_indent
return min_indent
def test(self, mode='current_pos'):
cursor = self.textedit.textCursor()
if mode == 'current_pos':
print 'current pos:', cursor.position()
elif mode == 'single_line_comment':
cursor.movePosition(
QTextCursor.StartOfBlock, QTextCursor.MoveAnchor)
self.textedit.setTextCursor(cursor)
cursor.insertText('# ')
elif mode == 'get_range':
start_pos, end_pos = [cursor.selectionStart(),
cursor.selectionEnd()]
print 'range:', start_pos, end_pos
self.sel_range = (start_pos, end_pos)
elif mode == 'load_range':
start_pos, end_pos = self.sel_range
print 'load range:', start_pos, end_pos
self.moveToPosition(start_pos)
cursor = self.textedit.textCursor()
cursor.movePosition(
QTextCursor.Right, QTextCursor.KeepAnchor, end_pos - start_pos)
self.textedit.setTextCursor(cursor)
elif mode == 'multi_line_comment':
# find selected lines
start_pos, end_pos = [cursor.selectionStart(),
cursor.selectionEnd()]
first_line,last_line = self.get_line_range(cursor,start_pos, end_pos)
# If the selection contains only commented lines and surrounding
# whitespace, uncomment. Otherwise, comment.
is_comment_or_whitespace = True
at_least_one_comment = False
for _line_nb in range(first_line, last_line+1):
text = str(cursor.block().text()).lstrip()
print 'dealing text:', text
is_comment = text.startswith(self.comment_string)
is_whitespace = (text == '')
is_comment_or_whitespace *= (is_comment or is_whitespace)
if is_comment:
at_least_one_comment = True
cursor.movePosition(QTextCursor.NextBlock)
min_indent = self.get_min_indent(cursor,start_pos,first_line,last_line)
cursor.beginEditBlock()
if is_comment_or_whitespace and at_least_one_comment:
print 'need to uncomment'
cursor.setPosition(start_pos)
for _line_nb in range(first_line, last_line+1):
if _line_nb==first_line:
self.moveToPosition(start_pos)
if self.position_in_block(cursor)>min_indent:
start_pos-=2
cursor.movePosition(QTextCursor.StartOfLine)
cursor.movePosition(
QTextCursor.Right, QTextCursor.MoveAnchor, min_indent)
self.textedit.setTextCursor(cursor)
cursor.deleteChar()
end_pos-=1
next_char = cursor.block().text()[self.position_in_block(cursor)]
print 'next char:', next_char
if next_char == ' ':
cursor.deleteChar()
end_pos-=1
cursor.movePosition(QTextCursor.NextBlock)
self.sel_range=(start_pos,end_pos)
else:
print 'need to comment'
cursor.setPosition(start_pos)
for _line_nb in range(first_line, last_line+1):
if _line_nb==first_line:
self.moveToPosition(start_pos)
if self.position_in_block(cursor)>min_indent:
start_pos+=2
cursor.movePosition(QTextCursor.StartOfLine)
cursor.movePosition(
QTextCursor.Right, QTextCursor.MoveAnchor, min_indent)
self.textedit.setTextCursor(cursor)
cursor.insertText('%s ' % self.comment_string)
end_pos+=2
cursor.movePosition(QTextCursor.NextBlock)
self.sel_range=(start_pos,end_pos)
cursor.endEditBlock()
elif mode == 'get_text_cur_pos':
print 'get cur pos text'
cursor = self.textedit.textCursor()
positionInBlock = self.position_in_block(cursor)
print 'block pos:', positionInBlock
print 'block text:', cursor.block().text()
print cursor.block().text()[positionInBlock]
elif mode == 'tab':
print 'tab'
start_pos, end_pos = [cursor.selectionStart(),
cursor.selectionEnd()]
start_pos+=4
# get last first line
first_line,last_line = self.get_line_range(cursor,start_pos, end_pos)
# indent 4 spaces
for _line_nb in range(first_line, last_line+1):
cursor.movePosition(QTextCursor.StartOfLine)
self.textedit.setTextCursor(cursor)
cursor.insertText(' '*4)
end_pos+=4
cursor.movePosition(QTextCursor.NextBlock)
self.sel_range=(start_pos,end_pos)
elif mode == 'shift_tab':
print 'shift_tab'
start_pos, end_pos = [cursor.selectionStart(),
cursor.selectionEnd()]
# get last first line
first_line,last_line = self.get_line_range(cursor,start_pos, end_pos)
for _line_nb in range(first_line, last_line+1):
cursor.movePosition(QTextCursor.StartOfLine)
if _line_nb==first_line:
for i in range(4):
next_char = cursor.block().text()[self.position_in_block(cursor)]
if next_char == ' ':
cursor.deleteChar()
start_pos-=1
end_pos-=1
else:
for i in range(4):
next_char = cursor.block().text()[self.position_in_block(cursor)]
if next_char == ' ':
cursor.deleteChar()
end_pos-=1
self.textedit.setTextCursor(cursor)
cursor.movePosition(QTextCursor.NextBlock)
self.sel_range=(start_pos,end_pos)
elif mode == 'undo':
print 'undo'
# if self.last_change=='toggle_comment':
# self.toggle_comment()
self.textedit.undo()
def main():
if qApp.applicationName().startsWith('Maya'):
global win
try:
win.close()
except:
pass
win = MyWindow(getMayaWindow())
else:
app = QApplication(sys.argv)
win = MyWindow()
win.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment