Last active
July 14, 2016 05:34
-
-
Save oglops/7fa0972e14871dce1174d8e2e0188ed6 to your computer and use it in GitHub Desktop.
test toggling comment in qtextedit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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