Last active
September 5, 2016 20:19
-
-
Save oglops/868582a8847cc2244331e3642f527329 to your computer and use it in GitHub Desktop.
hack script editor wip, 测试 lineedit 按到rect范围内就setfocus
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
#!/usr/bin/env python2 | |
import os | |
import sys | |
from PyQt4.QtCore import * | |
from PyQt4.QtGui import * | |
from PyQt4 import uic | |
import signal | |
signal.signal(signal.SIGINT, signal.SIG_DFL) | |
import re | |
CODE='''class A(object): | |
def __init__(self,*args): | |
pass | |
def method1_A(self): | |
pass | |
class B(object): | |
def __init__(self,*args): | |
pass | |
def method1_B(self): | |
pass | |
def main(): | |
pass | |
''' | |
EVENT_TABLE= {v: k for k, v in QEvent.__dict__.items()} | |
class MyTextEdit(QTextEdit): | |
def mousePressEvent(self,event): | |
pass | |
print 'my own click event' | |
if self.lineedit.rect().contains( event.pos()): | |
print 'click inside lineedit' | |
self.lineedit.setFocus() | |
QTextEdit.mousePressEvent(self,event) | |
class MyWindow(QDialog): | |
def __init__(self, parent=None): | |
super(MyWindow, self).__init__(parent) | |
layout = QVBoxLayout() | |
textedit = QTextEdit() | |
# textedit = MyTextEdit() | |
def mousePressEvent(event): | |
pass | |
print 'my own click event' | |
if self.lineedit.rect().contains( event.pos()): | |
print 'click inside lineedit' | |
self.lineedit.setFocus() | |
self.lineedit.completer().complete() | |
QTextEdit.mousePressEvent(textedit,event) | |
textedit.mousePressEvent=mousePressEvent | |
textedit.setPlainText(CODE) | |
button = QPushButton('pop up completer') | |
layout.addWidget(textedit) | |
layout.addWidget(button) | |
self.setLayout(layout) | |
self.resize(640,280) | |
self.textedit=textedit | |
self.layout=layout | |
parent_widget= textedit.parent() | |
# parent_rect = textedit.childrenRect() | |
# _, _, w, h = parent_rect.getCoords() | |
_, _, w, h = textedit.rect().getCoords() | |
# print 'w,h',w,h | |
lineedit = QLineEdit(textedit) | |
textedit.lineedit=lineedit | |
lineedit.setGeometry(w/2-w*0.6/2, 0, w*0.6, 32) | |
symbols = get_symbols(CODE) | |
# completer = QCompleter(self) | |
completer = MyCompleter(self) | |
lineedit.setCompleter(completer) | |
model = QStringListModel(self) | |
completer.setModel(model) | |
print 'list:',[x for _,_,x in symbols] | |
model.setStringList([x for _,_,x in symbols]) | |
completer.setCaseSensitivity(Qt.CaseInsensitive) | |
completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) | |
def focusOutEvent(self,event): | |
print 'my focusout' | |
QListView.focusOutEvent(self,event) | |
completer.popup().focusOutEvent=focusOutEvent | |
self.completer=completer | |
self.lineedit = lineedit | |
lineedit.setAttribute(Qt.WA_TransparentForMouseEvents) | |
self.lineedit.setFocus() | |
button.clicked.connect(self._test) | |
# self.completer.complete() | |
QTimer.singleShot(0,self.completer.complete) | |
self.setAttribute(Qt.WA_DeleteOnClose) | |
def _test(self): | |
# print self.textedit.parent() | |
self.lineedit.setFocus() | |
self.completer.complete() | |
class MyCompleter(QCompleter): | |
def __init__(self,parent=None): | |
super(MyCompleter,self).__init__(parent) | |
# self.popupView = QListWidget() | |
# self.popupView.setAlternatingRowColors(True) | |
# self.popupView.setWordWrap(False) | |
# self.setPopup(self.popupView) | |
# self.setCompletionMode(QCompleter.PopupCompletion) | |
# self.setCaseSensitivity(Qt.CaseInsensitive) | |
def eventFilter(self,obj,event): | |
etype=event.type() | |
exclude = [1,12] | |
if etype not in exclude: | |
print 'event.type:',EVENT_TABLE[event.type()],obj | |
if event.type() == QEvent.Hide: | |
print 'hide! ',obj | |
# obj.show() | |
# return True | |
if event.type() == QEvent.FocusOut: | |
print 'yeah focus out on',obj | |
if event.type() == QEvent.MouseButtonRelease: | |
print 'yeah mouse release on',obj | |
super(MyCompleter,self).eventFilter(obj,event) | |
return False | |
def get_symbols(code): | |
symbols = [] | |
symbol_regex = re.compile('^(\s*)(class|def)\s*([^\(\s]+\([^\(]*\))') | |
for n, line in enumerate(code.split('\n')): | |
if symbol_regex.search(line): | |
groups = symbol_regex.search(line).groups() | |
symbols.append((n+1, groups[1], groups[0]+groups[2])) | |
# print n+1,[str(x) for x in groups] | |
return symbols | |
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() |
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
# todo | |
# ctrl+d remove multiple line | |
# double click go to line | |
# ctrl+g go to line | |
# ctrl+r sublime style | |
try: | |
qApp.removeEventFilter(myFilter) | |
print 'removed filter' | |
except: | |
print 'first run' | |
from PyQt4 import QtCore, QtGui | |
from PyQt4.QtCore import * | |
from PyQt4.QtGui import * | |
from PyQt4.QtCore import Qt, QObject, QEvent, QChar, QModelIndex | |
from PyQt4.QtGui import QTextCursor, qApp | |
import maya.cmds as mc | |
import maya.mel as mel | |
import maya.OpenMayaUI as apiUI | |
import sip | |
import sys | |
import os | |
import re | |
import logging | |
_logger = logging.getLogger('hackScriptEditor') | |
for handler in _logger.handlers: | |
_logger.removeHandler(handler) | |
# _logger.setLevel(logging.INFO) | |
ch = logging.StreamHandler(sys.stdout) | |
ch.setLevel(logging.INFO) | |
formatter = logging.Formatter('%(name)s:%(levelname)s: %(message)s') | |
ch.setFormatter(formatter) | |
_logger.addHandler(ch) | |
_logger.propagate = 0 | |
class CustomFilter(QObject): | |
def __init__(self, parent=None): | |
super(CustomFilter, self).__init__(parent) | |
self.textedit = None | |
self.lineedit = None | |
def get_exec_type(self): | |
gCommandExecuterTabs = get_mel_global('$gCommandExecuterTabs') | |
tabIdx = mc.tabLayout(gCommandExecuterTabs, q=1, st=1) | |
cmd_executer = mc.layout(tabIdx, q=1, ca=1)[0] | |
return mc.cmdScrollFieldExecuter(cmd_executer, q=1, st=1) | |
def eventFilter(self, obj, event): | |
if event.type() == QEvent.KeyPress: | |
if 'scriptEditorPanel' in mc.getPanel(up=1): | |
self.get_text_edit() | |
self.exec_type = self.get_exec_type() | |
if self.exec_type == 'python': | |
self.comment_str = '#' | |
elif self.exec_type == 'mel': | |
self.comment_str = '//' | |
# print event.key(),event.modifiers() | |
if event.key() == Qt.Key_Slash and event.modifiers() == Qt.ControlModifier: | |
_logger.debug('ctrl+/ pressed') | |
self.toggle_comment() | |
return True | |
elif event.key() == Qt.Key_Tab and event.modifiers() == Qt.NoModifier: | |
_logger.debug('tab pressed') | |
self.tab('tab') | |
return True | |
elif event.key() == Qt.Key_Backtab and event.modifiers() == Qt.ShiftModifier: | |
_logger.debug('shift+tab pressed') | |
self.tab('shift_tab') | |
return True | |
elif event.key() == Qt.Key_D and event.modifiers() == Qt.ControlModifier: | |
_logger.debug('ctrl+d pressed') | |
self.test('delete_line') | |
return True | |
elif event.key() == Qt.Key_E and event.modifiers() == Qt.ControlModifier: | |
_logger.debug('ctrl+e pressed') | |
self.test('execute') | |
return True | |
elif event.key() == Qt.Key_Z and event.modifiers() == Qt.ControlModifier: | |
_logger.debug('ctrl+z pressed') | |
self.test('undo') | |
return True | |
elif event.key() == Qt.Key_R and event.modifiers() == Qt.ControlModifier: | |
_logger.debug('ctrl+r pressed') | |
self.test('goto_symbol') | |
return True | |
elif event.key() == Qt.Key_Escape: | |
_logger.debug('escape pressed') | |
self.test('cancel_completer') | |
return True | |
return False | |
def get_text_edit(self): | |
'get current qtextedit from script editor' | |
tabIdx = mc.tabLayout(gCommandExecuterTabs, q=1, st=1) | |
_logger.debug('current tab: %s', tabIdx) | |
cmd_executer = mc.layout(tabIdx, q=1, ca=1)[0] | |
ptr = apiUI.MQtUtil.findControl(cmd_executer) | |
self.textedit = sip.wrapinstance(long(ptr), QObject) | |
def moveToPosition(self, pos): | |
'move cursor actual position to 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): | |
_logger.debug('before') | |
self.test('get_range') | |
fn(self, *args, **kw) | |
_logger.debug('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): | |
# find left most line | |
cursor.setPosition(end_pos) | |
last_line = cursor.block().blockNumber() | |
if cursor.atBlockStart() and start_pos != end_pos: | |
_logger.debug('start_pos: %s end_pos: %s', 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()) | |
indents.append(indent) | |
cursor.movePosition(QTextCursor.NextBlock) | |
min_indent = min(indents) | |
_logger.debug('min_indent: %s', min_indent) | |
return min_indent | |
def is_empty_line(self, cursor): | |
empty = False | |
if len(str(cursor.block().text()).strip(' ')) == 0: | |
empty = True | |
_logger.debug('empty line [%s]', cursor.block().text()) | |
return empty | |
def test(self, mode='current_pos'): | |
cursor = self.textedit.textCursor() | |
if mode == 'current_pos': | |
_logger.debug('current pos: %s', cursor.position()) | |
elif mode == 'single_line_comment': | |
cursor.movePosition( | |
QTextCursor.StartOfBlock, QTextCursor.MoveAnchor) | |
self.textedit.setTextCursor(cursor) | |
cursor.insertText(self.comment_str+' ') | |
elif mode == 'get_range': | |
start_pos, end_pos = [cursor.selectionStart(), | |
cursor.selectionEnd()] | |
_logger.debug('range: %s %s', start_pos, end_pos) | |
self.sel_range = (start_pos, end_pos) | |
elif mode == 'load_range': | |
start_pos, end_pos = self.sel_range | |
_logger.debug('load range: %s %s', 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() | |
_logger.debug('dealing text: %s', text) | |
is_comment = text.startswith(self.comment_str) | |
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: | |
_logger.debug('need to uncomment') | |
cursor.setPosition(start_pos) | |
for _line_nb in range(first_line, last_line+1): | |
if self.is_empty_line(cursor): | |
cursor.movePosition(QTextCursor.NextBlock) | |
continue | |
if _line_nb == first_line: | |
self.moveToPosition(start_pos) | |
if self.position_in_block(cursor) > min_indent: | |
start_pos -= len(self.comment_str)+1 | |
cursor.movePosition(QTextCursor.StartOfLine) | |
cursor.movePosition( | |
QTextCursor.Right, QTextCursor.MoveAnchor, min_indent) | |
self.textedit.setTextCursor(cursor) | |
for i in range(len(self.comment_str)): | |
cursor.deleteChar() | |
end_pos -= 1 | |
next_char = cursor.block().text()[ | |
self.position_in_block(cursor)] | |
_logger.debug('next char: %s', next_char) | |
if next_char == ' ': | |
cursor.deleteChar() | |
end_pos -= 1 | |
cursor.movePosition(QTextCursor.NextBlock) | |
self.sel_range = (start_pos, end_pos) | |
else: | |
_logger.debug('need to comment') | |
cursor.setPosition(start_pos) | |
for _line_nb in range(first_line, last_line+1): | |
if self.is_empty_line(cursor): | |
cursor.movePosition(QTextCursor.NextBlock) | |
continue | |
if _line_nb == first_line: | |
self.moveToPosition(start_pos) | |
if self.position_in_block(cursor) >= min_indent: | |
start_pos += len(self.comment_str)+1 | |
cursor.movePosition(QTextCursor.StartOfLine) | |
cursor.movePosition( | |
QTextCursor.Right, QTextCursor.MoveAnchor, min_indent) | |
self.textedit.setTextCursor(cursor) | |
cursor.insertText('%s ' % self.comment_str) | |
end_pos += len(self.comment_str)+1 | |
cursor.movePosition(QTextCursor.NextBlock) | |
self.sel_range = (start_pos, end_pos) | |
cursor.endEditBlock() | |
elif mode == 'get_text_cur_pos': | |
_logger.debug('get cur pos text') | |
cursor = self.textedit.textCursor() | |
positionInBlock = self.position_in_block(cursor) | |
_logger.debug('block pos: %s', positionInBlock) | |
_logger.debug('block text: %s', cursor.block().text()) | |
_logger.debug(cursor.block().text()[positionInBlock]) | |
elif mode == 'tab': | |
print 'tab' | |
cursor.beginEditBlock() | |
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) | |
# range(first_line, last_line+1) | |
_logger.debug('tab key: %s %s', first_line, last_line) | |
start_pos += 4 | |
# indent 4 spaces | |
for _line_nb in range(first_line, last_line+1): | |
cursor.movePosition(QTextCursor.StartOfLine) | |
self.textedit.setTextCursor(cursor) | |
# skip empty line | |
if len(str(cursor.block().text()).strip(' ')) or first_line == last_line: | |
cursor.insertText(' '*4) | |
end_pos += 4 | |
cursor.movePosition(QTextCursor.NextBlock) | |
self.sel_range = (start_pos, end_pos) | |
cursor.endEditBlock() | |
elif mode == 'shift_tab': | |
_logger.debug('shift_tab') | |
cursor.beginEditBlock() | |
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() | |
if next_char: | |
next_char = next_char[ | |
self.position_in_block(cursor)] | |
else: | |
break | |
if next_char == ' ': | |
cursor.deleteChar() | |
end_pos -= 1 | |
self.textedit.setTextCursor(cursor) | |
cursor.movePosition(QTextCursor.NextBlock) | |
self.sel_range = (start_pos, end_pos) | |
cursor.endEditBlock() | |
elif mode == 'undo': | |
_logger.debug('undo') # self.sel_range | |
# if self.last_change=='toggle_comment': | |
# self.toggle_comment() | |
self.textedit.undo() | |
if getattr(self, 'sel_range', None): | |
self.test('load_range') | |
self.sel_range = None | |
elif mode == 'delete_line': | |
_logger.debug('delete_line') | |
cursor.beginEditBlock() | |
start_pos, end_pos = [cursor.selectionStart(), | |
cursor.selectionEnd()] | |
# get last first line | |
first_line, last_line = sorted( | |
self.get_line_range(cursor, start_pos, end_pos)) | |
for _line_nb in reversed(range(first_line, last_line+1)): | |
text_block = self.textedit.document().findBlockByLineNumber( | |
_line_nb) | |
cursor.setPosition(text_block.position()) | |
self.textedit.setTextCursor(cursor) | |
cursor.select(QTextCursor.LineUnderCursor) | |
cursor.removeSelectedText() | |
cursor.deleteChar() | |
cursor.endEditBlock() | |
elif mode == 'execute': | |
_logger.debug('execute') | |
# if self.lastnge=='toggle_comment': | |
# self.toggle_comment() | |
# if something selected, run it | |
start_pos, end_pos = [cursor.selectionStart(), | |
cursor.selectionEnd()] | |
run_all = 0 | |
if start_pos == end_pos: | |
# run all | |
cmd = self.textedit.toPlainText() | |
run_all = 1 | |
else: | |
cmd = cursor.selectedText() | |
# get first line content | |
cursor.movePosition(QTextCursor.Start, QTextCursor.MoveAnchor) | |
cursor.movePosition( | |
QTextCursor.Right, QTextCursor.MoveAnchor, start_pos) | |
first_line = str(cursor.block().text()) | |
spaces = len(first_line)-len(first_line.lstrip(' ')) | |
start_pos_in_block = self.position_in_block(cursor) | |
if not run_all: | |
if start_pos_in_block < spaces: | |
# f ill spaces | |
cmd = ' '*start_pos_in_block+cmd | |
else: | |
cmd = ' '*spaces + cmd | |
cmd = str(cmd.replace(QChar(0x2029), QChar('\n'))) | |
cmd = self.dedent_code(cmd) | |
print 'will run cmd:\n', cmd | |
# exec(cmd) | |
elif mode == 'goto_symbol': | |
print self.textedit.parent() | |
print self.textedit.parent().__class__ | |
print dir(self.textedit.parent()) | |
parent_widget = self.textedit.parent() | |
parent_rect = parent_widget.childrenRect() | |
_, _, w, h = parent_rect.getCoords() | |
# btn =QtGui.QPushButton('yeah',parent=parent_widget) | |
if len(parent_widget.children()) == 3: | |
lineedit = parent_widget.children()[2] | |
# lineedit.deleteLater() | |
else: | |
# lineedit = MyLineEdit(parent_widget) | |
lineedit = QLineEdit(parent_widget) | |
completer = CustomQCompleter() | |
current_tab_text = self.get_current_tab_text() | |
print 'current tab:', current_tab_text | |
symbols = get_symbols(current_tab_text) | |
self.symbols = symbols | |
model = MyModel() | |
model.setup(symbols) | |
completer.setModel(model) | |
completer.linedit=lineedit | |
completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) | |
completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) | |
completer.setWrapAround(False) | |
lineedit.setCompleter(completer) | |
completer.highlighted[QModelIndex].connect(self.goto_line) | |
lineedit.textChanged[QString].connect(self.pop) | |
lineedit.editingFinished.connect(self.repop) | |
lineedit.setFocus() | |
# lineedit.setFocusPolicy(Qt.NoFocus) | |
# lineedit.focusOutEvent=focusOutEvent | |
self.completer = completer | |
self.lineedit = lineedit | |
QTimer.singleShot(0, self.completer.complete) | |
lineedit.setGeometry(w/2-w*0.6/2, 0, w*0.6, 32) | |
lineedit.show() | |
print parent_widget.children() | |
QTimer.singleShot(0, self.scroll_to_nearest) | |
# button = parent_widget.children()[2] | |
# button.raise_() | |
# button.setGeometry(QtCore.QRect(100,100,80,20)) | |
# button.raise_() | |
# parent_widget.children()[1].deleteLater() | |
# button.setMaximumSize(QtCore.QSize(32767, 32767)) | |
# print self.textedit. | |
# button.activateWindow() | |
# self.textedit.stackUnder(button) | |
# parent_widget.children()[2].raise_() | |
# del parent_widget.children()[1] | |
# layout = parent_widget.children()[0] | |
# layout.addWidget(parent_widget.children()[2]) | |
# layout.removeWidget(parent_widget.children()[2]) | |
pass | |
elif mode == 'cancel_completer': | |
# check to see if complete is visible | |
pass | |
if self.lineedit is not None: | |
self.completer.deleteLater() | |
self.lineedit.deleteLater() | |
self.lineedit = None | |
def scroll_to_nearest(self): | |
# find current cursor line | |
cursor = self.textedit.textCursor() | |
line = cursor.blockNumber()+1 | |
print 'current line:',line | |
# get all lines | |
all_lines= [ x for x,_,_ in self.symbols] | |
# print 'all_lines:',all_lines | |
# find nearest line | |
line_distance = [ abs(line-x) for x in all_lines] | |
sorted_lines=sorted(zip(all_lines,line_distance),key=lambda x:x[1]) | |
nearest_line = sorted_lines[0][0] | |
print 'nearest line:',nearest_line | |
# find the nearest index | |
row= all_lines.index(nearest_line) | |
index = self.completer.model().index(row,0) | |
self.completer.popup().setCurrentIndex(index) | |
# self.completer.popup().scrollTo(index) | |
# QTimer.singleShot(0,lambda: self.completer.popup().scrollTo(index,QAbstractItemView.PositionAtCenter)) | |
self.scroll_to_current_line(index) | |
def scroll_to_current_line(self,index): | |
self.completer.popup().scrollTo(index,QAbstractItemView.PositionAtCenter) | |
# self.first_down=False | |
# self.completer.popup().setCurrentIndex(index) | |
self.completer.popup().setFocus() | |
def repop(self): | |
print 'yeah repop' | |
# self.test('cancel_completer') | |
def pop(self, symbol): | |
print 'symbol:', symbol | |
if isinstance(symbol, bool) or str(symbol) == u'@': | |
print 'is @' | |
text = '' | |
else: | |
text = symbol | |
self.completer.splitPath(text) | |
self.lineedit.setFocus() | |
# self.completer.complete() | |
# QTimer.singleShot(0,self.completer.complete) | |
def goto_line(self, index): | |
# print self.completer.model().sourceModel().symbol_data[x[0].row()][0] | |
line = index.data(Qt.UserRole).toPyObject() | |
print 'goto_line:', line | |
block = self.textedit.document().findBlockByLineNumber(line-1) | |
# make the line appear in middle | |
# get first line visible | |
cursor = self.textedit.cursorForPosition(QPoint(2,2)) | |
first_line = cursor.blockNumber()+1 | |
# print 'first line:',first_line | |
# get last line visible | |
bottom_right=QPoint(self.textedit.viewport().width()-1,self.textedit.viewport().height()-1) | |
end_pos= self.textedit.cursorForPosition(bottom_right).position() | |
cursor.setPosition(end_pos) | |
last_line = cursor.blockNumber()+1 | |
# print 'last line:',last_line | |
if first_line<=line<=last_line: | |
new_line=line | |
else: | |
mid = (last_line-first_line)/2 | |
if line<first_line: | |
new_line = line -mid | |
elif line > last_line: | |
new_line = line +mid | |
dummy_block = self.textedit.document().findBlockByLineNumber(new_line-1) | |
cursor.setPosition(dummy_block.position()) | |
self.textedit.setTextCursor(cursor) | |
# highlight | |
cursor.setPosition(block.position()) | |
self.textedit.setTextCursor(cursor) | |
cursor.movePosition(QTextCursor.StartOfBlock) | |
cursor.select(QTextCursor.LineUnderCursor) | |
self.textedit.setTextCursor(cursor) | |
def dedent_code(self, code): | |
indents = [] | |
for line in code.splitlines(): | |
_logger.debug('---> %s', line) | |
spaces = len(line)-len(line.lstrip(' ')) | |
if len(line.strip(' ')) > 0: | |
indents.append(spaces) | |
indent = min(indents) | |
_logger.debug('min indents: %s', indent) | |
new_code = '' | |
for line in code.splitlines(): | |
if len(line) > indent: | |
_logger.debug('working on: %s', line) | |
new_code += line[indent:]+'\n' | |
else: | |
new_code += line+'\n' | |
return new_code | |
def get_current_tab_text(self): | |
text = self.textedit.toPlainText() | |
return text | |
class MyModel(QStandardItemModel): | |
def __init__(self, parent=None): | |
super(MyModel, self).__init__(parent) | |
def data(self, index, role): | |
symbol = self.symbol_data[index.row()] | |
if role == Qt.DisplayRole: | |
if symbol[1] == 'class': | |
return symbol[2] | |
elif symbol[1] == 'def': | |
return re.search('[^\()]*', symbol[2]).group()+'(...)' | |
elif role == Qt.UserRole: | |
return symbol[0] | |
def setup(self, data): | |
self.symbol_data = data | |
for n, type_, name in data: | |
item = QStandardItem(name) | |
self.appendRow(item) | |
class MyLineEdit(QLineEdit): | |
def focusOutEvent(self,event): | |
print 'yeah focus out!' | |
pass | |
def focusInEvent(self,event): | |
print 'yeah focus in!' | |
# self.completer().popup().show() | |
super(MyLineEdit,self).focusInEvent(event) | |
# def keyPressEvent(self, event): | |
# if event.key() == Qt.Key_Backspace: | |
# event.accept() | |
# super(MyLineEdit, self).keyPressEvent(event) | |
# if self.text() == '': | |
# self.completer().splitPath('') | |
# self.completer().complete() | |
class CustomQCompleter3(QCompleter): | |
def __init__(self, parent=None): | |
super(CustomQCompleter, self).__init__(parent) | |
self.local_completion_prefix = "" | |
self.source_model = None | |
def setModel(self, model): | |
self.source_model = model | |
self._proxy = QSortFilterProxyModel( | |
self) | |
self._proxy.setFilterCaseSensitivity(Qt.CaseInsensitive) | |
self._proxy.setSourceModel(model) | |
super(CustomQCompleter, self).setModel(self._proxy) | |
def splitPath(self, path): | |
self.local_completion_prefix = str(path) | |
self._proxy.setFilterFixedString(path) | |
return "" | |
class CustomQCompleter(QCompleter): | |
def __init__(self, parent=None): | |
super(CustomQCompleter, self).__init__(parent) | |
self.source_model = None | |
self.first_down = True | |
self.local_completion_prefix = "" | |
def setModel(self, model): | |
self.source_model = model | |
# self._proxy = QSortFilterProxyModel(self, filterCaseSensitivity=Qt.CaseInsensitive) | |
self._proxy = QSortFilterProxyModel( | |
self) | |
self._proxy.setFilterCaseSensitivity(Qt.CaseInsensitive) | |
self._proxy.setSourceModel(model) | |
super(CustomQCompleter, self).setModel(self._proxy) | |
def splitPath(self, path): | |
# print 'splitPath=[%s]' % path | |
# if str(path).startswith('@'): | |
# path=path[1:] | |
self.local_completion_prefix = str(path) | |
self._proxy.setFilterFixedString(path) | |
# self.complete() | |
return "" | |
def eventFilter(self, obj, event): | |
if event.type() == QEvent.KeyPress: | |
'This is used to mute the connection to clear lineedit' | |
if event.key() in (Qt.Key_Down, Qt.Key_Up): | |
# print 'yeah', self.popup() | |
curIndex = self.popup().currentIndex() | |
# print self.popup().selectionModel().selectedIndexes() | |
# selList = self.popup().selectionModel().selectedIndexes() | |
# print 'selList:',selList | |
if event.key() == Qt.Key_Down: | |
# curIndex = self.popup().selectionModel().createIndex( curIndex.row()+1,curIndex.column()) | |
# print 'row count:', self._proxy.rowCount() | |
# the_index =self.popup().selectionModel().currentIndex() | |
# src_index = self._proxy.mapToSource(curIndex) | |
# print 'current source row:', src_index.row() | |
# print 'line proxy:', self._proxy.data(curIndex).toPyObject()[0] | |
# print 'line :', self._proxy.data(curIndex,Qt.DisplayRole) | |
# .toPyObject()[0] | |
if curIndex.row() == self._proxy.rowCount()-1: | |
print 'already last row' | |
if self._proxy.rowCount() == 1: | |
# return False | |
pass | |
# go to that line | |
else: | |
self.popup().setCurrentIndex(curIndex) | |
return True | |
else: | |
if not self.local_completion_prefix: | |
print ' manual add 1' | |
nextIndex = self._proxy.index(curIndex.row() + 1, curIndex.column()); | |
next_nextIndex = self._proxy.index(nextIndex.row() + 1, curIndex.column()); | |
# if not next_nextIndex.isValid(): | |
# next_nextIndex=nextIndex | |
self.popup().setCurrentIndex(nextIndex) | |
first_visible_row = self.popup().indexAt(QPoint(0,0)).row() | |
# print first_visible_row,self.maxVisibleItems(),nextIndex.row() | |
# if we have not reached last visible row | |
if first_visible_row+self.maxVisibleItems()-1<=nextIndex.row(): | |
# if we are at last row | |
if next_nextIndex.isValid(): | |
self.popup().scrollTo(next_nextIndex,QAbstractItemView.PositionAtBottom) | |
else: | |
self.popup().scrollToBottom() | |
else: | |
# if current index is the 7th index | |
self.popup().scrollTo(next_nextIndex) | |
if self._proxy.rowCount() == curIndex.row() + 1: | |
print 'last row' | |
# | |
return True | |
else: | |
print 'pass' | |
pass | |
# qApp.processEvents() | |
# QTimer.singleShot(0,lambda:self.popup().scrollTo(nextIndex,QAbstractItemView.EnsureVisible)) | |
# super(CustomQCompleter, self).eventFilter(obj, event) | |
pass | |
# return True | |
else: | |
if curIndex.row() == 0: | |
print 'already first row' | |
return True | |
else: | |
if not self.local_completion_prefix: | |
lastIndex = self._proxy.index(curIndex.row() - 1, curIndex.column()); | |
self.popup().setCurrentIndex(lastIndex) | |
first_visible_row = self.popup().indexAt(QPoint(0,0)).row() | |
if lastIndex.row()>=first_visible_row: | |
self.popup().scrollTo(lastIndex) | |
else: | |
self.popup().scrollTo(lastIndex,QAbstractItemView.PositionAtTop) | |
return True | |
else: | |
pass | |
print 'current row:', curIndex.row() | |
# print 'line original:', curIndex.data(Qt.UserRole).toPyObject() | |
# self.popup().setCurrentIndex(curIndex) | |
# if selList==[]: | |
# print 'selList empty:',curIndex | |
# self.popup().setCurrentIndex(curIndex) | |
# return True | |
if curIndex.row() == 0 and self.first_down: | |
print 'already row 0 first' | |
self.popup().setCurrentIndex(curIndex) | |
self.first_down = False | |
return True | |
# QTimer.singleShot(0,lambda :self.popup().setCurrentIndex(curIndex)) | |
# else: | |
# print 'selList has something:',curIndex.row() | |
# return True | |
super(CustomQCompleter, self).eventFilter( obj,event) | |
# print 'after super' | |
return False | |
def get_symbols(file_content=open('/home/oglop/tmp/enhancedScriptEditor.py').read()): | |
# if not os.path.isfile(file): | |
# print 'get symbols from file' | |
# f = open(file) | |
# elif isinstance(file,str): | |
# print 'get symbols from string' | |
# import StringIO | |
# f = StringIO.StringIO(file) | |
symbols = [] | |
symbol_regex = re.compile('^(\s*)(class|def)\s*([^\(\s]+\([^\(]*\))') | |
# with open(file) as f: | |
# try: | |
for n, line in enumerate(file_content.split('\n')): | |
if symbol_regex.search(line): | |
groups = symbol_regex.search(line).groups() | |
symbols.append((n+1, groups[1], groups[0]+groups[2])) | |
print n+1,[str(x) for x in groups] | |
# finally: | |
# f.close() | |
return symbols | |
def get_mel_global(var): | |
try: | |
return mel.eval('$tmp_var1=%s' % var) | |
except: | |
return mel.eval('$tmp_var2=%s' % var) | |
# This can remove the filter we installed | |
# qApp.removeEventFilter(filter) | |
myFilter = None | |
gCommandExecuterTabs = None | |
def main(): | |
global myFilter | |
global gCommandExecuterTabs | |
gCommandExecuterTabs = get_mel_global('$gCommandExecuterTabs') | |
myFilter = CustomFilter() | |
# qApp.removeEventFilter(filter) | |
qApp.installEventFilter(myFilter) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment