pyqt qscintill PyEditor
##
1 # encoding: utf-8 2 import PyQt5.Qsci as sci 3 # import PyQt5.QtWidgets as wgt 4 import os 5 from PyQt5.QtWidgets import * 6 from PyQt5.QtCore import * 7 from PyQt5.QtGui import * 8 from PyQt5.Qsci import * 9 import textwrap 10 11 import jedi 12 # jedi.settings.case_insensitive_completion=True 13 # jedi.settings.add_bracket_after_function= True 14 # jedi.settings.fast_parser= False 15 16 17 src='''import matplotlib.pyplot as plt 18 import numpy as np 19 x0=np.linspace( 0 , 30 , 600 );y0=x0*np.sin(x0 ) 20 plt.plot(x0 , y0 );plt.show() 21 ''' 22 app=QApplication( [] ) 23 mn=QMainWindow( ) 24 25 class scintillaEditor( sci.QsciScintilla): 26 def __init__(self , parent=None ): 27 super( ) . __init__( parent) 28 self.SendScintilla(self.SCI_STYLESETFONT, 1, b'Courier') 29 # self.SendScintilla(self.sci_gettext, 1, b'Courier') 30 31 self._editorFont=QFont("宋体",16,QFont.Normal) 32 self.setMarginLineNumbers(0, True) 33 self.setMarginSensitivity(0, True) 34 self.setMarginWidth( 0 , 32) 35 self.append( src) 36 # txt.changeEvent( ) 37 self.setFont( self._editorFont ) 38 self.zoomTo( 4 ) 39 40 41 """ 42 Setup the call tip options 43 """ 44 # Select the context at which the call tips are displayed. 45 # This selects when call tips are active, depending of the 46 # scope like a C++ namespace or Python module. 47 self.setCallTipsStyle(QsciScintilla.CallTipsNoContext) 48 # Set the number of calltips that will be displayed at one time. 49 # 0 shows all applicable call tips. 50 self.setCallTipsVisible(0) 51 # This selects the position at which the call tip rectangle will appear. 52 # If it is not possible to show the call tip rectangle at the selected position 53 # because it would be displayed outside the bounds of the document, it will be 54 # displayed where it is possible. 55 self.setCallTipsPosition(QsciScintilla.CallTipsAboveText) 56 # Select the various highlight colors 57 # Background 58 self.setCallTipsBackgroundColor(QColor(0xff, 0xff, 0xff, 0xff)) 59 # Text 60 self.setCallTipsForegroundColor(QColor(0x50, 0x50, 0x50, 0xff)) 61 # Current argument text 62 self.setCallTipsHighlightColor(QColor(0xff, 0x00, 0x00, 0xff)) 63 64 """ 65 Autocompletion options - Basic 66 """ 67 # Set the autocompletion to be case IN-sensitive 68 self.setAutoCompletionCaseSensitivity(False) 69 # Set the threshold at which the autocompletion window appears 70 self.setAutoCompletionThreshold(1) 71 # Set the source from which the autocompletions will be pulled from 72 self.setAutoCompletionSource(QsciScintilla.AcsAll) 73 # Sets whether the characters to the right of the autocompletion 74 # will be overwritten when an autocompletion is selected. 75 self.setAutoCompletionReplaceWord(True) 76 # Select the behaviour of autocompletions when there is only a single 77 # entry in the autocompletion list. The selection below sets that 78 # when the autocompletion window will always be displayed. 79 self.setAutoCompletionUseSingle(QsciScintilla.AcusNever) 80 81 self.lexer_instance=sci.QsciLexerPython( ) 82 self.setLexer( self.lexer_instance ) 83 self.api_instance=sci.QsciAPIs(self.lexer_instance) 84 85 class frameToolBarMnu( QFrame ): 86 ''' 87 action_out=.toolbar.addAction( "caption" , action_out_CallBackFunc) 88 @pyqtSlot() 89 def def toolBar_open_Func(): 90 ... 91 92 menu_out=.menu.addAction( "title" , menu_out_CallBackFunc) 93 @pyqtSlot() 94 def def toolBar_open_Func(): 95 ... 96 ''' 97 def __init__ (self , parent=None): 98 super( ) .__init__( parent) 99 100 fontMn=QFont("黑体",16,QFont.Bold) 101 102 self._vbox_=QVBoxLayout( self ) 103 self.splitter =QSplitter( self ) 104 self.splitter.setOrientation( 0 ) 105 self.toolbar=QToolBar(self) 106 self.toolbar.setFont( fontMn) 107 108 action_open=self.toolbar.addAction( "open" , self.toolBar_open_Func ) 109 action_save=self.toolbar.addAction( "save" , self.toolBar_save_Func) 110 action_new=self.toolbar.addAction( "new" , self.toolBar_new_Func) 111 action_execl=self.toolbar.addAction( "execl" , self.toolBar_Exec_Func ) 112 # action_execl=self.toolbar.addAction( "jedi" , toolBar_Jedi_Func ) 113 self.jediBtn=QPushButton( 'jedi' ,self) 114 self.jediBtn.setCheckable( True) 115 self.toolbar.addWidget( self.jediBtn ) 116 117 118 self.menu=QMenuBar(self) 119 self.menu.setFont( fontMn) 120 121 self._vbox_.addWidget( self.menu ) 122 self._vbox_.addWidget( self.toolbar ) 123 self._vbox_.addWidget( self.splitter ) 124 125 self.editorMain=scintillaEditor( self ) 126 self.editorMain.textChanged.connect( self.editorMain_onTextChanged ) 127 self.__filePath__='' 128 129 self.statusbarMain=QStatusBar( self ) 130 self.label_ssbar01=QLabel( 'label01', self) 131 self.statusbarMain.addWidget( self.label_ssbar01 ) 132 self._vbox_.addWidget( self.statusbarMain ) 133 134 135 def test(self): 136 self.menu.addMenu("file") 137 self.menu.addMenu("view") 138 self.menu.addMenu("edit") 139 140 @pyqtSlot() 141 def toolBar_Exec_Func( self ): 142 try: 143 exec( self.editorMain.text() ) 144 except Exception as e: 145 print(e) 146 @pyqtSlot() 147 def toolBar_open_Func(self): 148 filename=QFileDialog.getOpenFileName( fm ,'open file','/home/jm/study') 149 print( filename ) 150 if os.path.exists( filename[0] )==False: 151 return 152 if filename[0] in [ "" , " " , None] : 153 return 154 self.__filePath__=filename[0] 155 156 with open(filename[0],'r') as f: 157 my_txt=f.read() 158 self.editorMain.setText(my_txt) 159 @pyqtSlot() 160 def toolBar_save_Func( self ): 161 if self.__filePath__=="" or self.__filePath__ is None : 162 filename=QFileDialog.getSaveFileName(fm,'save file','/home/jm/study') 163 else: 164 filename=[self.__filePath__] 165 with open(filename[0],'w') as f: 166 my_text=editor.text( ) 167 f.write(my_text) 168 169 @pyqtSlot() 170 def toolBar_new_Func(self): 171 self.editorMain.setText( "#encoding: utf-8\n") 172 self.__filePath__= "" 173 174 # @pyqtSlot() 175 # def toolBar_Jedi_Func(): 176 # return 177 178 179 def editorMain_onTextChanged (self ): 180 pos=self.editorMain.SendScintilla( self.editorMain.SCI_GETCURRENTPOS, 0 , 0) 181 sp=self.editorMain.SendScintilla( self.editorMain.SCI_WORDSTARTPOSITION , pos , True ) 182 ep=self.editorMain.SendScintilla( self.editorMain.SCI_WORDENDPOSITION, pos , True ) 183 184 print( self.editorMain.text( ) [ sp:ep] ) 185 186 # self.editorMain.SendScintilla( self.editorMain.SCI_SETSEL , sp , ep) 187 188 189 190 api=self.editorMain.api_instance 191 mtxt= self.editorMain.text( ) 192 api.clear( ) 193 if self.jediBtn.isChecked( )==False: 194 for i in buildFuncs : 195 api.add( i) 196 api.prepare() 197 return 198 pos=editor.getCursorPosition( ) 199 x,y=pos 200 if(len(mtxt)==0 ):return 201 JdSrc=jedi.Script( mtxt , path='tmp.py') 202 try: 203 completes=JdSrc.complete( x+1 , y) # 注意 line坐标从1开始 204 except Exception as e: 205 print( e) 206 else: 207 for i in completes: 208 api.add( i.name) 209 # docstr=textwrap.shorten( i.docstring() , width=256, placeholder="...") 210 # api.add( i.docstring() ) 211 api.prepare( ) 212 return 213 214 fm=frameToolBarMnu(mn ) 215 editor02=QsciScintilla( mn ) 216 editor=fm.editorMain # fm.test() 217 218 fm.splitter.addWidget( editor) 219 fm.splitter.addWidget( editor02) 220 mn.setCentralWidget( fm ) 221 toolbar01=fm.toolbar 222 223 # lx=sci.QsciLexerPython( ) 224 # editor.setLexer( lx ) 225 # api=sci.QsciAPIs(lx) 226 227 # api.add("for while import return ") 228 229 funcs = [ 230 "test_autocompletion", 231 "add(int arg_1, float arg_2) Add two integers together", # This call tip has a description 232 "subtract(int arg_1, test arg_2)", 233 "subtract(float arg_1, float arg_2)", 234 "subtract(test arg_1, test arg_2)", 235 "divide(float div_1, float div_2)", 236 "some_func(arg_3)" 237 ] 238 # Add the functions to the api 239 for s in funcs: 240 fm.editorMain.api_instance.add(s) 241 242 243 # Create a list of autocompletions 244 test_autocompletions = [ 245 "test_autocompletion", 246 "autocompletion_with_image?1", 247 "another_autocompletion?2", 248 "subtract?1(int arg_1, float arg_2) Subtract function", # This call tip has a description and an image 249 "entry_that_will_be_removed_later" 250 ] 251 252 buildFuncs=['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 253 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 254 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 255 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 256 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 257 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 258 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 259 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 260 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 261 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 262 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 263 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 264 'WindowsError', 'ZeroDivisionError', '__IPYTHON__', '__build_class__', '__debug__', '__doc__', 265 '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 266 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'cell_count', 'chr', 'classmethod', 'compile', 'complex', 267 'copyright', 'credits', 'debugcell', 'debugfile', 'delattr', 'dict', 'dir', 'display', 'divmod', 'enumerate', 'eval', 268 'exec', 'execfile', 'filter', 'float', 'format', 'frozenset', 'get_ipython', 'getattr', 'globals', 'hasattr', 'hash', 'help', 269 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 270 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'range', 'repr', 'reversed', 'round', 'runcell', 271 'runfile', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip'] 272 273 274 import keyword 275 buildFuncs=buildFuncs+keyword.kwlist 276 277 # Add the functions to the api 278 for ac in test_autocompletions: 279 fm.editorMain.api_instance.add(ac) 280 # Example of removing an entry 281 fm.editorMain.api_instance.remove("entry_that_will_be_removed_later") 282 # Prepare the QsciAPIs instance information 283 fm.editorMain.api_instance.prepare() 284 285 286 if __name__ == '__main__': 287 scn=fm.editorMain 288 xx=b' ' 289 fm.editorMain.SendScintilla( scn.SCI_GETLINE, 1 , xx) 290 print( xx ) 291 mn.show( ) 292 app.exec( ) 293
##
浙公网安备 33010602011771号