1 Star 15 Fork 15

阿德/代码编辑器

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
textedit.py 17.93 KB
一键复制 编辑 原始数据 按行查看 历史
#!/usr/bin/env python3
import sys
from PyQt5.QtCore import *
#from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import ( QAction, QApplication, QMessageBox, QTextEdit, QMenu, QFileDialog)
from PyQt5.QtGui import QCursor, QFont, QColor, QPixmap, QTextCursor, QPalette
from PyQt5.QtPrintSupport import *
from PyQt5.Qsci import QsciLexerCPP, QsciScintilla, QsciAPIs,QsciScintillaBase
#from PyQt5.Qsci import QsciDocument
from qrc_resources import *
from lexer_c_getfunc import g_allFuncList
import keyword
class MyLexerCPP(QsciLexerCPP):
def __init__(self,parent):
QsciLexerCPP.__init__(self,parent)
if parent == None:
return
self.setFont(self.parent().Font)
#颜色由主界面传入,存于《setting.ini》中
self.setColor(QColor(self.parent().win.colorDict[ 'Default' ])) #设置前景色
self.setPaper(QColor(self.parent().win.colorDict[ 'Background' ])) #设置底色
self.setColor(QColor(self.parent().win.colorDict['Default' ]), QsciLexerCPP.Default )
self.setColor(QColor(self.parent().win.colorDict['Keyword' ]), QsciLexerCPP.Keyword )
self.setColor(QColor(self.parent().win.colorDict['KeywordSet2' ]), QsciLexerCPP.KeywordSet2 )
self.setColor(QColor(self.parent().win.colorDict['CommentDoc' ]), QsciLexerCPP.CommentDoc )#文档注释 /**开头的颜色
self.setColor(QColor(self.parent().win.colorDict['Comment' ]), QsciLexerCPP.Comment )#块注释 的颜色
self.setColor(QColor(self.parent().win.colorDict['CommentLine' ]), QsciLexerCPP.CommentLine )#行注释的颜色
self.setColor(QColor(self.parent().win.colorDict['Number' ]), QsciLexerCPP.Number ) #数字 的颜色
self.setColor(QColor(self.parent().win.colorDict['DoubleQuotedString' ]), QsciLexerCPP.DoubleQuotedString)#双引号字符串的颜色
self.setColor(QColor(self.parent().win.colorDict['SingleQuotedString' ]), QsciLexerCPP.SingleQuotedString)#单引号字符的颜色
self.setColor(QColor(self.parent().win.colorDict['PreProcessor' ]), QsciLexerCPP.PreProcessor )#预编译语句的颜色
self.setColor(QColor(self.parent().win.colorDict['Operator' ]), QsciLexerCPP.Operator )
self.setColor(QColor(self.parent().win.colorDict['UnclosedString' ]), QsciLexerCPP.UnclosedString)#未完成输入的字符串的颜色
#self.setColor(QColor("#000000"), QsciLexerCPP.Identifier) #可识别字符的颜色,这个范围很广,包含了关键词,函数名;所以要取消这句
font = QFont(self.parent().Font)
font.setBold(True)
self.setFont(font,5) #默认的字体加粗。
font = QFont(self.parent().Font)
font.setItalic(True)
self.setFont(font,QsciLexerCPP.Comment) #注释的字体用斜体。
for i in range(0, QsciScintillaBase.STYLE_MAX):
desc = self.description(i)
if desc:
self.setEolFill(True, i) #将填充的底色延伸到屏幕的右端;否则默认只有文字的地方。
class SciTextEdit(QsciScintilla):
NextId = 1
def __init__(self, filename='', wins=None, parent=None):
global g_allFuncList
super(QsciScintilla, self).__init__(parent)
self.win=wins
self.jumpName=''
self.list_line=[]
self.Font = self.win.EditFont #采用主窗口传入的字体
self.Font.setFixedPitch(True)
self.setFont(self.Font)
#1.设置文档的编码格式为 “utf8” ,换行符为 windows 【可选linux,Mac】
self.setUtf8(True)
self.setEolMode(QsciScintilla.SC_EOL_CRLF)#文件中的每一行都以EOL字符结尾(换行符为 \r \n)
#2.设置括号匹配模式
self.setBraceMatching(QsciScintilla.StrictBraceMatch)#
#3.设置 Tab 键功能
self.setIndentationsUseTabs(True)#行首缩进采用Tab键,反向缩进是Shift +Tab
self.setIndentationWidth(4) #行首缩进宽度为4个空格
self.setIndentationGuides(True)# 显示虚线垂直线的方式来指示缩进
self.setTabIndents(True) #编辑器将行首第一个非空格字符推送到下一个缩进级别
self.setAutoIndent(True) #插入新行时,自动缩进将光标推送到与前一个相同的缩进级别
self.setBackspaceUnindents(True)
self.setTabWidth(4) # Tab 等于 4 个空格
#4.设置光标
self.setCaretWidth(2) #光标宽度(以像素为单位),0表示不显示光标
self.setCaretForegroundColor(QColor("darkCyan")) #光标颜色
self.setCaretLineVisible(True) #是否高亮显示光标所在行
self.setCaretLineBackgroundColor(QColor(self.win.colorDict[ 'CaretLine' ])) #光标所在行的底色
#5.设置页边特性。 这里有3种Margin:[0]行号 [1]改动标识 [2]代码折叠
#5.1 设置行号
self.setMarginsFont(self.Font) #行号字体
self.setMarginLineNumbers(0,True) #设置标号为0的页边显示行号
self.setMarginWidth(0,'00000') #行号宽度
self.setMarkerForegroundColor(QColor("#FFFFFF"),0)
self.setMarginsBackgroundColor(QColor(self.win.colorDict[ 'Background' ]))
#self.setMarkerBackgroundColor(QColor(self.win.colorDict[ 'Background' ]),0)
#self.setMarkerBackgroundColor(QColor(self.win.colorDict[ 'Background' ]),1)
#self.setMarkerBackgroundColor(QColor(self.win.colorDict[ 'Background' ]),2)
#5.2 设置改动标记
self.setMarginType(1, QsciScintilla.SymbolMargin) # 设置标号为1的页边用于显示改动标记
self.setMarginWidth(1, "0000") #改动标记占用的宽度
#img = QPixmap(":/leftside.png") #改动标记图标,大小是48 x 48
#sym_1 = img.scaled(QSize(16, 16)) #图标缩小为 16 x 16 #
sym_1 = QsciScintilla.LeftRectangle
self.markerDefine(sym_1, 0)
self.setMarginMarkerMask(1, 0b1111)
self.setMarkerForegroundColor(QColor("#ff0000"),0)
self.setMarkerBackgroundColor(QColor("#00ff00"),0) #00ff00
#5.3 设置代码自动折叠区域
self.setFolding(QsciScintilla.PlainFoldStyle)
self.setMarginWidth(2,12)
#5.3.1 设置代码折叠和展开时的页边标记 - +
self.markerDefine(QsciScintilla.Minus, QsciScintilla.SC_MARKNUM_FOLDEROPEN)
self.markerDefine(QsciScintilla.Plus, QsciScintilla.SC_MARKNUM_FOLDER)
self.markerDefine(QsciScintilla.Minus, QsciScintilla.SC_MARKNUM_FOLDEROPENMID)
self.markerDefine(QsciScintilla.Plus, QsciScintilla.SC_MARKNUM_FOLDEREND)
#5.3.2 设置代码折叠后,+ 的颜色FFFFFF
self.setMarkerBackgroundColor(QColor("#FFBCBC"), QsciScintilla.SC_MARKNUM_FOLDEREND)
self.setMarkerForegroundColor(QColor("red"), QsciScintilla.SC_MARKNUM_FOLDEREND)
#6.语法高亮显示
#6.1语法高亮的设置见 MyLexerCPP类 源码
self.lexer=MyLexerCPP(self)
self.setLexer(self.lexer)
#6.2设置自动补全
self.mod=False
self.__api = QsciAPIs(self.lexer)
# SDCC编译器的关键字 列表
sdcc_kwlist=['__data','__idata','__pdata','__xdata','__code','__bit','__sbit',
'__sfr' , 'u8', 'u16' , 'WORD', 'BYTE','define' , 'include','__interrupt',
'__critical', '__using','double' , 'int' , 'struct' , 'break' , 'else' ,
'auto' ,'switch' , 'case','enum' , 'register' , 'typedef' , 'default' ,
'char' , 'extern' , 'return' , 'union' , 'const' , 'float','long' ,
'short' , 'unsigned' , 'continue' , 'for' , 'signed' , 'void' ,
'goto','sizeof' , 'volatile' , 'do' , 'while' , 'static' , 'if',
'endif', 'ifndef', 'ifdef']
autocompletions = keyword.kwlist+sdcc_kwlist
for ac in autocompletions:
self.__api.add(ac)
self.__api.prepare()
self.autoCompleteFromAll()
self.setAutoCompletionSource(QsciScintilla.AcsAll) #自动补全所以地方出现的
self.setAutoCompletionCaseSensitivity(True) #设置自动补全大小写敏感
self.setAutoCompletionThreshold(1); #输入1个字符,就出现自动补全 提示
self.setAutoCompletionReplaceWord(False)
self.setAutoCompletionUseSingle(QsciScintilla.AcusExplicit)
self.setAttribute(Qt.WA_DeleteOnClose)
#设置函数名为关键字2 KeyWord = sdcc_kwlistcc ;KeywordSet2 = 函数名
self.SendScintilla(QsciScintilla.SCI_SETKEYWORDS, 0," ".join(sdcc_kwlist).encode(encoding='utf-8'))
#self.SendScintilla(QsciScintilla.SCI_STYLESETFORE, QsciLexerCPP.KeywordSet2, 0x7f0000)
self.SendScintilla(QsciScintilla.SCI_SETKEYWORDS, 1," ".join(g_allFuncList).encode(encoding='utf-8'))
self.filename = filename
if self.filename=='':
self.filename = str("未命名-{0}".format(SciTextEdit.NextId))
SciTextEdit.NextId += 1
self.setModified(False)
#设置文档窗口的标题
self.setWindowTitle(QFileInfo(self.filename).fileName())
#将槽函数链接到文本改动的信号
self.textChanged.connect(self.textChangedAction)
#给文档窗口添加右键菜单
self.setContextMenuPolicy(Qt.CustomContextMenu)#
self.customContextMenuRequested.connect(self.RightMenu)
def getIncludeFile(self, linestr):
start=0
end=0
for i in range(7, len(linestr)):
if start !=0 and linestr[i] in ' >"':
end = i+1
return linestr[start: end]
elif start ==0 and linestr[i] in '<"':
start = i
return None
def getFuncNameInLine(self, linestr): #在行中查找函数名
start=0
end=linestr.find('(')
if end == 0:
return None
for i in range(end-1, -1, -1): #从 左括号字符 “(” 往回查询到空格、= 、制表符 就停止
if start !=0 and linestr[i] in " =\t":
end = start
start = i+1
break
# 左括号 和 函数名 之间有可能包含空格
elif start ==0 and linestr[i] != ' ' : #非空格,就是函数名最后一个字符,把位置保存在start
start = i+1
else:
end=0
return linestr[start: end]
def RightMenu(self):
line_num, index=self.getCursorPosition()
text=self.text()
#0.获取光标所在行的全部字符
str1=text.splitlines(False)[line_num]
if len(str1) != 0:
#0.1 如果字符串有 ‘#in’ ,那么应该包含文件名
if '#in' in str1:
self.jumpName = self.getIncludeFile(str1)
#0.2 如果含有 字符 ( ,那么应该有函数名
elif '(' in str1:
self.jumpName= self.getFuncNameInLine(str1)
#1.Jump to
self.popMenu = QMenu()
Jump2Function=QAction('Jump to '+self.jumpName, self)
self.popMenu.addAction(Jump2Function)
Jump2Function.triggered.connect(self.do_Jump2Function)
#setEnabled isRedoAvailable isUndoAvailable
#2.undo
undoAction =QAction('Undo', self)
undoAction.triggered.connect(self.undo)
undoAction.setEnabled(self.isUndoAvailable())
self.popMenu.addAction(undoAction)
#3.redo
redoAction =QAction('Redo', self)
redoAction.triggered.connect(self.redo)
redoAction.setEnabled(self.isRedoAvailable())
self.popMenu.addAction(redoAction)
#4.copy
copyAction =QAction('Copy', self)
copyAction.triggered.connect(self.copy)
self.popMenu.addAction(copyAction)
#5.cut
cutAction =QAction('Cut', self)
cutAction.triggered.connect(self.cut)
self.popMenu.addAction(cutAction)
#6.paste
pasteAction =QAction('Paste', self)
pasteAction.triggered.connect(self.paste)
self.popMenu.addAction(pasteAction)
#7.在鼠标位置显示右菜单
self.popMenu.exec_(QCursor.pos())
def do_Jump2Function(self): # 跳转到函数 ;跳转到包含文件
if self.jumpName[0] in '"<' :
self.win.Jump2IncludeFile_Signal.emit(self.jumpName)
else:
self.win.Jump2Func_Signal.emit(self.jumpName)
def closeEvent(self, event):
if (self.isModified() and
QMessageBox.question(self,
"文本编辑器 - 未保存的更改",
"保存在 {0} 文件中所做出的更改?".format(self.filename),
QMessageBox.Yes|QMessageBox.No) ==
QMessageBox.Yes):
try:
self.save()
except EnvironmentError as e:
QMessageBox.warning(self,
"文本编辑器 - 保存错误",
"保存失败 {0}: {1}".format(self.filename, e))
def textChangedAction(self):
line, index=self.getCursorPosition() #获取当前光标所在行
handle_01 = self.markerAdd(line, 0) # 添加改动标记
self.list_line.append(handle_01) #保存改动标记所在的地方,给后面保存文档时消除标记提供信息
def save(self):
if self.filename[:3]=='未命名':
if self.filename[-4:]==".txt":
self.filename=self.filename[:-4]
filename = QFileDialog.getSaveFileName(self, "文本编辑器 - 另存为", self.filename,
"c files (*.c *.*)")
if filename[0]=='':
return
self.filename = filename[0]
self.setWindowTitle(QFileInfo(self.filename).fileName())
exception = None
fh = None
try:
fh = QFile(self.filename)
if not fh.open(QIODevice.WriteOnly):
raise IOError(str(fh.errorString()))
stream = QTextStream(fh)
stream.setCodec("UTF-8")
stream << self.text()
#self.document().setModified(False)
self.setModified(False)
except EnvironmentError as e:
exception = e
finally:
if fh is not None:
fh.close()
if exception is not None:
raise exception
#将保存过的文件消除改动标识,清空记录改动的列表
for line in self.list_line:
self.markerDeleteHandle(line)
self.list_line.clear()
def load(self):
exception = None
fh = None
try:
fh = QFile(self.filename)
if not fh.open(QIODevice.ReadOnly):
raise IOError(str(fh.errorString()))
stream = QTextStream(fh)
stream.setCodec("UTF-8")
self.setText(stream.readAll())
#self.document().setModified(False)
self.setModified(False)
except EnvironmentError as e:
exception = e
finally:
if fh is not None:
fh.close()
if exception is not None:
raise exception
'''
if __name__=="__main__":
app=QApplication(sys.argv)
form=TextEdit()
form.show()
app.exec_()
def mousePressEvent(self, event):
"""Overloaded mouse click event"""
#Execute the superclass mouse click event
super().mousePressEvent(event)
#Set focus to the clicked editor
self.setFocus()
# Hide the function wheel if it is shown
key1=event.button()
#模拟鼠标左键单击 QMouseEvent(QEvent::Type type, const QPointF &localPos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
#event.button()=QtCore.Qt.LeftButton
if key1 == QtCore.Qt.RightButton:
print("right mouse")
def keyPressEvent(self, QKeyEvent):#重写按键事件
super().keyPressEvent(QKeyEvent)
key = QKeyEvent.key()
if key == Qt.Key_ParenLeft:
#print("( press down")
pos = self.SendScintilla(QsciScintilla.SCI_GETCURRENTPOS) #取得当前位置,注释掉的代码在包含中文代码中出错。
start = self.SendScintilla(QsciScintilla.SCI_WORDSTARTPOSITION, pos-2) # 纯英文下,运行正常
end = self.SendScintilla(QsciScintilla.SCI_WORDENDPOSITION, pos-2)
self.SendScintilla(QsciScintilla.SCI_CALLTIPSHOW, pos, self.text()[start:end] )
#self.CallTipShow(pos, self.text()[start:end] )
elif key == Qt.Key_ParenRight:
self.SendScintilla(QsciScintilla.SCI_CALLTIPCANCEL)
'''
class QtextEditClick(QTextEdit):
TextEdit2Click_Signal = pyqtSignal()
def __init__(self, parent=None):
super(QtextEditClick, self).__init__(parent)
self.textChanged.connect(self.textChangedAction)#将槽函数链接到文本改动的信号
def mouseDoubleClickEvent(self, e):
self.TextEdit2Click_Signal.emit() #产生一个文本双击信号
def textChangedAction(self):
cursor=self.textCursor()
cursor.movePosition(QTextCursor.End)#移动鼠标至文档最后
self.setTextCursor(cursor)
QApplication.processEvents()
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/huangweide001/code4STC51.git
git@gitee.com:huangweide001/code4STC51.git
huangweide001
code4STC51
代码编辑器
master

搜索帮助

Cb406eda 1850385 E526c682 1850385