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     

 

 

##

posted @ 2024-11-24 20:19  陳亞林  阅读(31)  评论(0)    收藏  举报