def createTabWidget(self, code, textLexer: QsciLexer): tabWidget = QWidget() # 垂直布局 layout = WidgetUtil.createVBoxLayout() # 设置布局方式 tabWidget.setLayout(layout) editor = QsciScintilla(tabWidget) editor.setLexer(textLexer) # 行号提示 editor.setMarginType(0, QsciScintilla.NumberMargin) # 设置编号为1的页边显示行号。 editor.setMarginLineNumbers(0, True) # 对该页边启用行号 editor.setMarginWidth(0, 30) # 设置页边宽度 editor.setText(code) editor.SendScintilla(QsciScintilla.SCI_SETCODEPAGE, QsciScintilla.SC_CP_UTF8) # 设置编码为UTF-8 editor.setReadOnly(True) # 添加控件到布局中 layout.addWidget(editor) return tabWidget
class CodeDialog(QDialog): codeChanged = pyqtSignal('QString') def __init__(self, code): super(QDialog, self).__init__() self.codeEdit = QsciScintilla() self.codeEdit.setText(code) fixedWidthFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) self.codeEdit.setFont(fixedWidthFont) fontmetrics = QFontMetrics(fixedWidthFont) self.codeEdit.setMarginWidth(0, fontmetrics.width("000")) self.codeEdit.setMarginLineNumbers(0, True) self.codeEdit.setMarginsBackgroundColor(QColor("#cccccc")) self.codeEdit.setBraceMatching(QsciScintilla.SloppyBraceMatch) self.codeEdit.setCaretLineVisible(True) self.codeEdit.setCaretLineBackgroundColor(QColor("#ffe4e4")) lexer = QsciLexerPython() lexer.setDefaultFont(fixedWidthFont) self.codeEdit.setLexer(lexer) self.codeEdit.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.codeEdit.setUtf8(True) self.codeEdit.setTabWidth(4) self.codeEdit.setIndentationsUseTabs(True) self.codeEdit.setIndentationGuides(True) self.codeEdit.setTabIndents(True) self.codeEdit.setAutoIndent(True) verticalLayout = QVBoxLayout() verticalLayout.addWidget(self.codeEdit) self.setLayout(verticalLayout) self.codeEdit.textChanged.connect(self.changeCode) def changeCode(self): self.codeChanged.emit(self.codeEdit.text())
def getEditor(): editor = QsciScintilla() lexer = QsciLexerYAML() editor.setLexer(lexer) font = getFont() # lexer.setDefaultFont(font) lexer.setFont(font) settings = QSettings() lexer.readSettings(settings) print(settings.allKeys()) lexer.setDefaultPaper(QColor('#252721')) for i in range(10): lexer.setPaper(QColor('#252721'), i) lexer.setColor(QColor('#f8f8f2'), i) print(lexer.color(i).name()) lexer.setColor(QColor('#e6db74'), 0) # foreground (yellow) lexer.setColor(QColor('#75715e'), 1) # comment (gray) lexer.setColor(QColor('#f92672'), 2) # identifier (red) lexer.setColor(QColor('#ae81ff'), 3) # keyword (purple) lexer.setColor(QColor('#ae81ff'), 4) # number (purple) lexer.setColor(QColor('#ae81ff'), 5) # reference (purple) lexer.setColor(QColor('#ae81ff'), 6) # documentdelimiter (purple) lexer.setColor(QColor('#ae81ff'), 7) # text block marker (purple) lexer.setColor(QColor('#f92672'), 8) # syntax error marker (red) lexer.setColor(QColor('#f92672'), 9) # operator (red) # editor.setFont(font) # editor.setMarginsFont(font) editor.setCaretForegroundColor(QColor('#f8f8f0')) editor.setMarginWidth(0, getMarginWidth(font)) editor.setMarginWidth(1, 0) editor.setMarginLineNumbers(0, True) editor.setMarginsBackgroundColor(QColor('#252721')) editor.setMarginsForegroundColor(QColor('#f8f8f2')) editor.setExtraAscent(3) editor.setTabWidth(4) editor.setMinimumSize(600, 450) return editor
class BrowserWindow(QWidget): launcherWindow = None logoPixmap = None def __init__(self, launcherWindow, app): super().__init__() self.app = app self.launcherWindow = launcherWindow self.fontSize = 14 self.fontSizeLarge = 24 self.fontSizeSmall = 10 self.setCursor(AppData.cursors['arrow']) self.initUI() def multiple_replace(self, string, rep_dict): pattern = re.compile("|".join([re.escape(k) for k in rep_dict.keys()]), re.M) return pattern.sub(lambda x: rep_dict[x.group(0)], string) def styleEsc(self, string): return self.multiple_replace(string, { '{': '{{', '}': '}}', '@<': '{', '>@': '}' }) def initUI(self): ## pal = QPalette(); ## pal.setColor(QPalette.Background, Qt.black); ## self.setPalette(pal); self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.styleTemplate = self.styleEsc(""" QWidget{ background-color: black; border-color: red; border-style: solid; border-width: 1px; border-radius: 0px; font: bold @<fontSize>@px; color: red; padding: 0px; font-family: "Candara"; font-size: @<fontSize:d>@px; } QLabel{ font-size: @<fontSizeLarge:d>@px; border-width: 0px; } QTreeView::item:hover { background: black; border: 1px solid red; } QTreeView::item:selected { border: 1px solid red; color: red; } QTreeView::item:selected:active{ background: black; border: 1px solid red; } QTreeView::item:selected:!active { border: 1px solid red; color: red; } QTreeView::branch:has-siblings:!adjoins-item { border-image: url(Gui/stylesheet-vline.png) 0; } QTreeView::branch:has-siblings:adjoins-item { border-image: url(Gui/stylesheet-branch-more.png) 0; } QTreeView::branch:!has-children:!has-siblings:adjoins-item { border-image: url(Gui/stylesheet-branch-end.png) 0; } QTreeView::branch:has-children:!has-siblings:closed, QTreeView::branch:closed:has-children:has-siblings { border-image: none; image: url(Gui/stylesheet-branch-closed.png); } QTreeView::branch:open:has-children:!has-siblings, QTreeView::branch:open:has-children:has-siblings { border-image: none; image: url(Gui/stylesheet-branch-open.png); } QScrollBar:vertical { border: 2px solid red; background: black; width: 40px; margin: 22px 0 22px 0; } QScrollBar::handle:vertical { background: red; min-height: 20px; } QScrollBar::add-line:vertical { border: 2px red; background: black; height: 20px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { border: 2px red; background: black; height: 20px; subcontrol-position: top; subcontrol-origin: margin; } QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { border: 2px solid black; width: 3px; height: 3px; background: red; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: none; } """) self.setStyleSheet( self.styleTemplate.format(fontSize=int(self.fontSize), fontSizeLarge=int(self.fontSizeLarge))) #gridWidget = QWidget(self) #self.gridWidget = gridWidget grid = QGridLayout() #treeMooker = QWidget(self) #treeMooker.setStyleSheet("background-color: transparent;") #treeMooker.setAttribute(Qt.WA_TransparentForMouseEvents) #treeMooker.installEventFilter(self) #treeMookerGrid = QGridLayout() #stack = QStackedLayout() #stack.setStackingMode(QStackedLayout.StackAll) logo = QLabel(self) self.logoPixmap = QPixmap("./Project/Media/Gears.png") logo.setPixmap(self.logoPixmap) logo.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) grid.addWidget(logo, 2, 3, 1, 1) self.titleTemplate = self.styleEsc(''' <p align="left"><strong> <span style='font-size:@<fontSizeLarge>@pt; font-weight:600; color:#ff0000;'>GPU Eye And Retina Stimulation </span></strong><span style='font-size:10pt; font-weight:600; color:#aa0000;'>beta test version 0.4</span></p> <table border="0" cellpadding="0" cellspacing="0"> <tbody> <tr> <td > <p align="left"><span style='font-size:@<fontSize>@pt; font-weight:600; color:#ff0000;'>László Szécsi</span></p> </td> <td > <p><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'>Budapest University of Technology and Economics</span></p> </td> </tr> <tr> <td > <p align="left"> <span style='font-size:@<fontSize>@pt; font-weight:600; color:#ff0000;'>Péter Hantz</span></p> </td> <td > <p><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'>University of Pécs, Medical School</span></p> </td> </tr> <tr> <td > <p align="left"> <span style='font-size:@<fontSize>@pt; font-weight:600; color:#ff0000;'>Ágota Kacsó</span></p> </td> <td > <p><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'>Budapest University of Technology and Economics</span></p> </td> </tr> <tr> <td > <p align="left"><span style='font-size:@<fontSize>@pt; font-weight:600; color:#ff0000;'>Günther Zeck</span></p> </td> <td > <p><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'>Natural and Medical Sciences Institute Reutlingen</span></p> </td> </tr> <tr> <td > <p align="left"><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'>http://www.gears.vision</span></p> </td> <td > <p><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'>[email protected]</span></p> </td> </tr> </tbody> </table> ''') self.titleLabel = QLabel( self.titleTemplate.format(fontSize=self.fontSize, fontSizeLarge=self.fontSizeLarge, fontSizeSmall=self.fontSizeSmall)) self.titleLabel.setTextFormat(Qt.RichText) self.titleLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) grid.addWidget(self.titleLabel, 1, 3, 1, 1) self.instructionsTemplate = self.styleEsc(''' <p align="left"><strong> <table border="0" cellpadding="0" cellspacing="0"> <tbody> <tr> <td > <p align="left"><span style='font-size:@<fontSize>@pt; font-weight:600; color:#ff0000;'>Reset tree</span></p> </td> <td > <p><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'>press space</span></p> </td> </tr> <tr> <td > <p align="left"><span style='font-size:@<fontSize>@pt; font-weight:600; color:#ff0000;'>Navigate</span></p> </td> <td > <p><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'>press key for first character</span></p> </td> </tr> <tr> <td > <p align="left"> <span style='font-size:@<fontSize>@pt; font-weight:600; color:#ff0000;'>Change font size</span></p> </td> <td > <p><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'>ctrl+mouse wheel</span></p> </td> </tr> <tr> <td > <p align="left"><span style='font-size:@<fontSize>@pt; font-weight:600; color:#ff0000;'>Edit or configure</span></p> </td> <td > <p><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'>right click tree item</span></p> </td> </tr> <tr> <td > <p align="left"><span style='font-size:@<fontSize>@pt; font-weight:600; color:#ff0000;'>/</span></p> </td> <td > <p><span style='font-size:@<fontSizeSmall>@pt; font-weight:600; color:#aa0000;'> @<emptyFolderOp>@ empty folders</span></p> </td> </tr> </tbody> </table> ''') self.instructionsLabel = QLabel( self.instructionsTemplate.format(fontSize=self.fontSize, fontSizeLarge=self.fontSizeLarge, fontSizeSmall=self.fontSizeSmall, emptyFolderOp='show')) self.instructionsLabel.setStyleSheet(''' QLabel{ border-width: 1px; } ''') self.instructionsLabel.setTextFormat(Qt.RichText) self.instructionsLabel.setAlignment(Qt.AlignHCenter) grid.addWidget(self.instructionsLabel, 3, 1, 1, 1) specs = QLabel(gears.getSpecs()) #self.titleLabel.setTextFormat( Qt.RichText ) self.titleLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) specs.setFocusPolicy(Qt.NoFocus) #specsButton.clicked.connect(self.onSpecs) grid.addWidget(specs, 4, 1, 1, 1) quitButton = QPushButton('Quit') quitButton.setFocusPolicy(Qt.NoFocus) quitButton.clicked.connect(self.onQuit) grid.addWidget(quitButton, 4, 3, 1, 1) #settingsButton = QPushButton('Measurement hardware') #settingsButton.setFocusPolicy(Qt.NoFocus) #settingsButton.clicked.connect(self.onSet) #grid.addWidget(settingsButton, 3, 3, 1, 1) tree = BrowserTree(self.launcherWindow, self) tree.setAttribute(Qt.WA_TransparentForMouseEvents, on=False) self.tree = tree tree.setFocusPolicy(Qt.NoFocus) tree.setHeaderHidden(True) tree.setStyleSheet("background-color: black;") item0 = QTreeWidgetItem(tree) item0.setText(0, 'Sequences') itemMap = dict() itemMap["./Project/Sequences"] = item0 rootPath = "./Project/Sequences" emptyDirs = find_empty_dirs(rootPath) for (path, dirs, files) in os.walk(rootPath): for subdir in dirs: if subdir != "__pycache__": fullPath = os.path.join(path, subdir) #if(rootPath == path): # item0 = QTreeWidgetItem(tree) # itemMap[fullPath] = item0 # item0.setText(0, subdir) #else: item1 = QTreeWidgetItem() itemMap[fullPath] = item1 item1.setText(0, subdir) itemMap[path].addChild(item1) if fullPath in emptyDirs: item1.setText( 1, "gears_folder_not_holding_any_sequence_scripts") item1.setHidden(True) for item in files: if item.endswith('.pyx'): #if(rootPath == path): # item0 = QTreeWidgetItem(tree) # itemMap[os.path.join(path, item)] = item0 # item0.setText(0, item) #else: item1 = QTreeWidgetItem() itemMap[os.path.join(path, item)] = item1 item1.setText(0, item) item1.setText(1, "tags spot spatial temporal") itemMap[path].addChild(item1) item0.setExpanded(True) grid.addWidget(tree, 1, 1, 4, 3, Qt.AlignLeft | Qt.AlignTop) #qbtn = QPushButton('Quit', self) #qbtn.clicked.connect(QCoreApplication.instance().quit) #qbtn.resize(qbtn.sizeHint()) #grid.addWidget(qbtn, 8, 9) #treeMooker.setLayout(treeMookerGrid) #gridWidget.setLayout(grid) #stack.addWidget(treeMooker) #stack.addWidget(gridWidget) self.setLayout(grid) self.setWindowTitle('O\u0398\u03a6O') # self.setWindowIcon(QIcon('web.png')) self.showFullScreen() self.setFixedSize(self.size()) self.tree.setCurrentIndex(self.tree.model().index(0, 0)) def keyPressEvent(self, e): if e.key() == Qt.Key_Escape or e.text() == 'q': box = QMessageBox(self) QGuiApplication.setOverrideCursor(AppData.cursors['arrow']) box.setText('Are you sure you want to quit?') box.setWindowTitle('Please confirm!') box.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog) box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) box.setDefaultButton(QMessageBox.No) if box.exec() == QMessageBox.Yes: self.close() QGuiApplication.restoreOverrideCursor() elif e.key() == Qt.Key_Space or e.key() == Qt.Key_Backspace: self.tree.setCurrentItem(self.tree.topLevelItem(0)) self.tree.collapseAll() self.tree.topLevelItem(0).setExpanded(True) elif e.key() == Qt.Key_Down: ni = self.tree.itemBelow(self.tree.currentItem()) if (ni != None): self.tree.setCurrentItem(ni) elif e.key() == Qt.Key_Up: ni = self.tree.itemAbove(self.tree.currentItem()) if (ni != None): self.tree.setCurrentItem(ni) elif e.key() == Qt.Key_Left: ni = self.tree.currentItem().parent() if (ni != None): self.tree.setCurrentItem(ni) elif e.key() == Qt.Key_Right or e.key() == Qt.Key_Return or e.key( ) == Qt.Key_Enter: ni = self.tree.currentItem().child(0) if (ni != None): self.tree.setCurrentItem(ni) else: self.tree.open(self.tree.currentItem(), False) elif e.key() == Qt.Key_Slash: self.tree.hideEmptyFolders(not self.tree.isHidingEmptyFolders) self.instructionsLabel.setText( self.instructionsTemplate.format( fontSize=int(self.fontSize), fontSizeLarge=int(self.fontSizeLarge), fontSizeSmall=int(self.fontSizeSmall), emptyFolderOp=('show' if self.tree.isHidingEmptyFolders else 'hide'))) #elif e.key()==Qt.Key_0 or e.key()==Qt.Key_1 or e.key()==Qt.Key_2 or e.key()==Qt.Key_3 or e.key()==Qt.Key_4 or e.key()==Qt.Key_5 or e.key()==Qt.Key_6 or e.key()==Qt.Key_7 or e.key()==Qt.Key_8 or e.key()==Qt.Key_9 : else: self.tree.clearSelection() self.tree.keyboardSearch(e.text()) sel = self.tree.selectedItems() if len(sel) > 0: self.tree.onClick(sel[0], 0) def onSpecs(self): box = QMessageBox(self) horizontalSpacer = QSpacerItem(1000, 0, QSizePolicy.Minimum, QSizePolicy.Expanding) box.setText(gears.getSpecs()) box.setWindowTitle('System specs') box.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog) box.setStandardButtons(QMessageBox.Ok) box.setDefaultButton(QMessageBox.Ok) layout = box.layout() layout.addItem(horizontalSpacer, layout.rowCount(), 0, 1, layout.columnCount()) box.exec() def onQuit(self): box = QMessageBox(self) #box.setCursor(AppData.cursors['arrow']) QGuiApplication.setOverrideCursor(AppData.cursors['arrow']) box.setText('Are you sure you want to quit?') box.setWindowTitle('Please confirm!') box.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog) box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) box.setDefaultButton(QMessageBox.No) if box.exec() == QMessageBox.Yes: self.close() QGuiApplication.restoreOverrideCursor() def onSet(self): #from subprocess import call #call("notepad ./Project/Sequences/DefaultSequence.py") self.editor = QsciScintilla() # define the font to use font = QFont() font.setFamily('Courier') font.setFixedPitch(True) font.setPointSize(10) # the font metrics here will help # building the margin width later fm = QFontMetrics(font) ## set the default font of the editor ## and take the same font for line numbers self.editor.setFont(font) self.editor.setMarginsFont(font) ## Line numbers # conventionnaly, margin 0 is for line numbers self.editor.setMarginWidth(0, fm.width("00000") + 5) self.editor.setMarginLineNumbers(0, True) ## Edge Mode shows a red vetical bar at 80 chars self.editor.setEdgeMode(QsciScintilla.EdgeLine) self.editor.setEdgeColumn(80) self.editor.setEdgeColor(QColor("#FF0000")) ## Folding visual : we will use boxes self.editor.setFolding(QsciScintilla.BoxedTreeFoldStyle) ## Braces matching self.editor.setBraceMatching(QsciScintilla.SloppyBraceMatch) ## Editing line color self.editor.setCaretLineVisible(True) self.editor.setCaretLineBackgroundColor(QColor("#CDA869")) ## Margins colors # line numbers margin self.editor.setMarginsBackgroundColor(QColor("#333333")) self.editor.setMarginsForegroundColor(QColor("#CCCCCC")) # folding margin colors (foreground,background) self.editor.setFoldMarginColors(QColor("#99CC66"), QColor("#333300")) ## Choose a lexer lexer = QsciLexerPython() lexer.setDefaultFont(font) api = QsciStrictAPIs(lexer) api.prepare() lexer.setDefaultFont(font) self.editor.setLexer(lexer) self.editor.setMinimumSize(1024, 768) self.editor.show() ## Show this file in the editor text = open("./Project/Sequences/DefaultSequence.py").read() self.editor.setText(text) def wheelEvent(self, event): if self.app.keyboardModifiers() & Qt.ControlModifier: self.fontSize += event.angleDelta().y() / 120 self.fontSizeLarge += event.angleDelta().y() / 120 self.fontSizeSmall += event.angleDelta().y() / 120 self.setStyleSheet( self.styleTemplate.format(fontSize=int(self.fontSize), fontSizeLarge=int( self.fontSizeLarge))) self.titleLabel.setText( self.titleTemplate.format( fontSize=int(self.fontSize), fontSizeLarge=int(self.fontSizeLarge), fontSizeSmall=int(self.fontSizeSmall))) self.instructionsLabel.setText( self.instructionsTemplate.format( fontSize=int(self.fontSize), fontSizeLarge=int(self.fontSizeLarge), fontSizeSmall=int(self.fontSizeSmall), emptyFolderOp=('show' if self.tree.isHidingEmptyFolders else 'hide'))) self.tree.resizeColumnToContents(0) self.updateGeometry() #def eventFilter(self, obj, event): # #if event.type() in [ QEvent.MouseMove, QEvent.MouseButtonPress, QEvent.MouseButtonRelease, QEvent.MouseButtonDblClick]: # self.app.sendEvent(self.gridWidget, event) # return super().eventFilter(obj, event) def sizeHint(self): return self.app.desktop().screenGeometry().size()
class ScriptTab(QWidget,): autocomplete_lst = [] def __init__(self, parent, name, script="", filemodified=0): QWidget.__init__(self) self.parent = parent self.tabWidget = self.parent.ui.tabWidget self.gridlayout = QGridLayout(self) self._dirty = False self.initialize_editor() self.gridlayout.addWidget(self.editor) self.setAcceptDrops(True) self.filename = name self.filemodified = filemodified if self.is_file(): self.title = os.path.basename(name) # if self.equals_saved(): # self.filemodified = os.path.getmtime(self.filename) else: self.filename = "" self.title = name # Show this file in the self.editor self.editor.setText(script) self.clean_txt = self.saved() self.update_dirty() self.editor.keyPressEvent = self.key_press_event @property def scriptRunner(self): return self.parent.controller.scriptRunner def wheelEvent(self, event): if event.modifiers() == Qt.ControlModifier: if event.delta() > 0: self.editor.zoomIn() else: self.editor.zoomOut() return QWidget.wheelEvent(self, event) def initialize_editor(self): self.editor = QsciScintilla() # self.editor.cursorPositionChanged.connect(self.e) # self.editor.copyAvailable.connect(self.e) # self.editor.indicatorClicked.connect(self.e) # self.editor.indicatorReleased.connect(self.e) # self.editor.linesChanged.connect(self.e) # self.editor.marginClicked.connect(self.e) # self.editor.modificationAttempted.connect(self.e) # self.editor.modificationChanged.connect(self.e) # self.editor.selectionChanged.connect(self.e) # self.editor.textChanged.connect(self.e) # self.editor.userListActivated.connect(self.e) if self.editor.__class__.__name__ == "LineTextWidget": return # When using PySide without QSciScintilla # define the font to use font = QFont() font.setFamily("Consolas") font.setFixedPitch(True) font.setPointSize(10) # the font metrics here will help # building the margin width later fm = QFontMetrics(font) # set the default font of the self.editor # and take the same font for line numbers self.editor.setFont(font) self.editor.setMarginsFont(font) # Line numbers # conventionnaly, margin 0 is for line numbers self.editor.setMarginWidth(0, fm.width("00000") + 5) self.editor.setMarginLineNumbers(0, True) self.editor.setTabWidth(4) # Folding visual : we will use boxes self.editor.setFolding(QsciScintilla.BoxedTreeFoldStyle) self.editor.setAutoIndent(True) # Braces matching self.editor.setBraceMatching(QsciScintilla.SloppyBraceMatch) # Editing line color self.editor.setCaretLineVisible(True) self.editor.setCaretLineBackgroundColor(QColor("#CDA869")) # Margins colors # line numbers margin self.editor.setMarginsBackgroundColor(QColor("#333333")) self.editor.setMarginsForegroundColor(QColor("#CCCCCC")) # folding margin colors (foreground,background) self.editor.setFoldMarginColors(QColor("#99CC66"), QColor("#333300")) # Choose a lexer self.lexer = QsciLexerPython() self.lexer.setDefaultFont(font) # Set the length of the string before the editor tries to autocomplete # In practise this would be higher than 1 # But its set lower here to make the autocompletion more obvious self.editor.setAutoCompletionThreshold(1) # Tell the editor we are using a QsciAPI for the autocompletion self.editor.setAutoCompletionSource(QsciScintilla.AcsAPIs) self.editor.setLexer(self.lexer) self.editor.setCallTipsStyle(QsciScintilla.CallTipsContext) # self.editor.setCallTipsVisible(0) # Create an API for us to populate with our autocomplete terms self.api = QsciAPIs(self.lexer) # Compile the api for use in the lexer self.api.prepare() # def tefocusInEvent(self, event): # self.parent.focusInEvent(event) # return QTextEdit.focusInEvent(self.textEditScript, event) def is_file(self): return os.path.isfile(self.filename) def is_modified(self): if self.is_file(): if self.equals_saved(): self.filemodified = os.path.getmtime(self.filename) return str(os.path.getmtime(self.filename)) != str(self.filemodified) else: return False def saved(self): if self.is_file(): f = open(self.filename) saved = f.read() f.close() return saved.strip() else: return "" def equals_saved(self): curr_lines = self.get_script().strip().splitlines() saved_lines = self.saved().strip().splitlines() if len(curr_lines) != len(saved_lines): return False for cl, sl in zip(curr_lines, saved_lines): if cl.strip() != sl.strip(): return False return True @property def dirty(self): if not self._dirty: self.dirty = self.clean_txt != self.get_script() return self._dirty @dirty.setter def dirty(self, dirty): if dirty is False: self.clean_txt = self.get_script() if self._dirty != dirty: self._dirty = dirty self.filename_changed() def update_dirty(self): return self.dirty def index(self): return self.tabWidget.indexOf(self) def filename_changed(self): index = self.parent.ui.tabWidget.indexOf(self) if self.dirty: self.tabWidget.setTabText(index, "%s*" % self.title) else: self.tabWidget.setTabText(index, self.title) def reload(self): self.set_script(self.parent._load_script(self.filename)) self.filemodified = os.path.getmtime(self.filename) def close(self): while self.dirty is True: # While avoids data loss, in case save operation is aborted if self.filename == "": text = "Save unsaved changes?" else: text = "Save %s?" % self.filename ans = QMessageBox.question(self, 'Save', text, QMessageBox.Yes, QMessageBox.Cancel, QMessageBox.No) if ans == QMessageBox.Cancel: return elif ans == QMessageBox.Yes: self.parent.actionSave(False) elif ans == QMessageBox.No: break self.tabWidget.removeTab(self.index()) def _save(self,): f = open(self.filename, 'w') f.write(self.get_script()) f.close() self.title = os.path.basename(self.filename) self.dirty = False def key_press_event(self, event): self.update_dirty() if self.editor.__class__.__name__ == "LineTextWidget": return self.editor.edit.keyReleaseEvent(event) # When using PySide without QSciScintilla QsciScintilla.keyPressEvent(self.editor, event) linenr, pos_in_line = self.editor.getCursorPosition() line = str(self.editor.text(linenr)[:pos_in_line]) if event.key() == Qt.Key_F1: try: self.parent.show_documentation(getattr(self.scriptRunner, str(self.editor.selectedText()))) except AttributeError: pass if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return: for tip in self.autocomplete_lst: try: if line.endswith(tip[:tip.index('(') ]): self.editor.insert(tip[tip.index('('):]) parent, residual = self.scriptRunner.split_line(line) self.parent.show_documentation(self.scriptRunner.get_function_dict(parent, residual)[residual]) return except ValueError: pass if event.key() < 100 or event.key() in [Qt.Key_Backspace, Qt.Key_Shift]: linenr, pos_in_line = self.editor.getCursorPosition() line = str(self.editor.text(linenr)[:pos_in_line]) lst = self.scriptRunner.get_autocomplete_list(line) if lst is not None: self.api.clear() list(map(self.api.add, lst)) self.api.prepare() if len(lst) > 0: self.autocomplete_lst = lst self.editor.autoCompleteFromAll() shift_event = QKeyEvent(QEvent.KeyPress, Qt.Key_Shift, Qt.NoModifier) QsciScintilla.keyPressEvent(self.editor, shift_event) # show autocomplete list def set_script(self, script): self.editor.setText(script) def get_script(self): return str(self.editor.text()).replace("\r", "").replace(">>> ", "").replace("\t", " ") def dropHandler(self, dataItemList, ctrl, shift, event): pass
class highlightEditor(QMainWindow): """ 语法高亮代码框 """ def __init__(self, parent=None, lineNumberOn=False): super(highlightEditor, self).__init__() self.editor = QsciScintilla(parent) font = QFont() font.setFamily("Consolas") font.setPointSize(12) font.setFixedPitch(True) self.editor.setFont(font) self.editor.setObjectName("editor") self.editor.setUtf8(True) self.editor.setMarginsFont(font) if lineNumberOn: self.editor.setMarginWidth( 0, len(str(len(self.editor.text().split('\n')))) * 20) self.editor.setMarginLineNumbers(0, lineNumberOn) self.editor.setBraceMatching(QsciScintilla.StrictBraceMatch) self.editor.setIndentationsUseTabs(True) self.editor.setIndentationWidth(4) self.editor.setTabIndents(True) self.editor.setAutoIndent(True) self.editor.setBackspaceUnindents(True) self.editor.setTabWidth(4) self.editor.setCaretLineVisible(True) self.editor.setCaretLineBackgroundColor(QColor('#DCDCDC')) self.editor.setIndentationGuides(True) self.editor.setFolding(QsciScintilla.PlainFoldStyle) self.editor.setMarginWidth(2, 12) self.editor.markerDefine(QsciScintilla.Minus, QsciScintilla.SC_MARKNUM_FOLDEROPEN) self.editor.markerDefine(QsciScintilla.Plus, QsciScintilla.SC_MARKNUM_FOLDER) self.editor.markerDefine(QsciScintilla.Minus, QsciScintilla.SC_MARKNUM_FOLDEROPENMID) self.editor.markerDefine(QsciScintilla.Plus, QsciScintilla.SC_MARKNUM_FOLDEREND) self.editor.setMarkerBackgroundColor( QColor("#FFFFFF"), QsciScintilla.SC_MARKNUM_FOLDEREND) self.editor.setMarkerForegroundColor( QColor("#272727"), QsciScintilla.SC_MARKNUM_FOLDEREND) self.editor.setMarkerBackgroundColor( QColor("#FFFFFF"), QsciScintilla.SC_MARKNUM_FOLDEROPENMID) self.editor.setMarkerForegroundColor( QColor("#272727"), QsciScintilla.SC_MARKNUM_FOLDEROPENMID) self.editor.setAutoCompletionSource(QsciScintilla.AcsAll) self.editor.setAutoCompletionCaseSensitivity(True) self.editor.setAutoCompletionReplaceWord(False) self.editor.setAutoCompletionThreshold(1) self.editor.setAutoCompletionUseSingle(QsciScintilla.AcusExplicit) self.lexer = highlight(self.editor) self.editor.setLexer(self.lexer) self.__api = QsciAPIs(self.lexer) autocompletions = keyword.kwlist + [] for ac in autocompletions: self.__api.add(ac) self.__api.prepare() self.editor.autoCompleteFromAll() self.editor.textChanged.connect(self.changed) def changed(self): self.editor.setMarginWidth( 0, len(str(len(self.editor.text().split('\n')))) * 20)
class CodeDialog(QDialog): codeChanged = pyqtSignal('QString') def __init__(self, name, currentValue): super(QDialog, self).__init__() self.setWindowTitle(name) self.resize(800, 600) self.codeEdit = QsciScintilla() self.codeEdit.setText(currentValue) fixedWidthFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) self.codeEdit.setFont(fixedWidthFont) fontmetrics = QFontMetrics(fixedWidthFont) self.codeEdit.setMarginWidth(0, fontmetrics.width("000")) self.codeEdit.setMarginLineNumbers(0, True) self.codeEdit.setMarginsBackgroundColor(QColor("#cccccc")) self.codeEdit.setBraceMatching(QsciScintilla.SloppyBraceMatch) self.codeEdit.setCaretLineVisible(True) self.codeEdit.setCaretLineBackgroundColor(QColor("#ffe4e4")) lexer = QsciLexerPython() lexer.setDefaultFont(fixedWidthFont) self.codeEdit.setLexer(lexer) self.codeEdit.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.codeEdit.setUtf8(True) self.codeEdit.setTabWidth(4) self.codeEdit.setIndentationsUseTabs(True) self.codeEdit.setIndentationGuides(True) self.codeEdit.setTabIndents(True) self.codeEdit.setAutoIndent(True) self.cancelButton = QPushButton('Cancel') self.cancelButton.clicked.connect(self.cancel) self.acceptButton = QPushButton('Accept') self.acceptButton.clicked.connect(self.accept) self.pythonButton = QRadioButton('Python') self.pythonButton.setChecked(True) self.pythonButton.clicked.connect(self.pythonClicked) self.cppButton = QRadioButton('C++') self.cppButton.clicked.connect(self.cppClicked) hLayout0 = QHBoxLayout() hLayout0.addWidget(self.pythonButton) hLayout0.addWidget(self.cppButton) container0 = QWidget() container0.setLayout(hLayout0) verticalLayout = QVBoxLayout() verticalLayout.addWidget(container0) verticalLayout.addWidget(self.codeEdit) container = QWidget() hLayout =QHBoxLayout() hLayout.addWidget(self.cancelButton) hLayout.addWidget(self.acceptButton) container.setLayout(hLayout) verticalLayout.addWidget(container) self.setLayout(verticalLayout) self.language = 'python' def cancel(self): self.close() def accept(self): self.codeChanged.emit(self.codeEdit.text()) self.close() def pythonClicked(self): fixedWidthFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) lexer = QsciLexerPython() lexer.setDefaultFont(fixedWidthFont) self.codeEdit.setLexer(lexer) self.language = 'python' def cppClicked(self): fixedWidthFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) lexer = QsciLexerCPP() lexer.setDefaultFont(fixedWidthFont) self.codeEdit.setLexer(lexer) self.language = 'cpp'
class TransitionCodeDialog(QDialog): codeChanged = pyqtSignal('int', 'QString', 'QString') def __init__(self, name, transition): super(QDialog, self).__init__() self.transition = transition self.setWindowTitle(name) self.resize(800, 600) self.codeEdit = QsciScintilla() self.codeEdit.setText(self.transition.getCode()) fixedWidthFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) self.codeEdit.setFont(fixedWidthFont) fontmetrics = QFontMetrics(fixedWidthFont) self.codeEdit.setMarginWidth(0, fontmetrics.width("000")) self.codeEdit.setMarginLineNumbers(0, True) self.codeEdit.setMarginsBackgroundColor(QColor("#cccccc")) self.codeEdit.setBraceMatching(QsciScintilla.SloppyBraceMatch) self.codeEdit.setCaretLineVisible(True) self.codeEdit.setCaretLineBackgroundColor(QColor("#ffe4e4")) lexer = QsciLexerPython() lexer.setDefaultFont(fixedWidthFont) self.codeEdit.setLexer(lexer) self.codeEdit.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.codeEdit.setUtf8(True) self.codeEdit.setTabWidth(4) self.codeEdit.setIndentationsUseTabs(True) self.codeEdit.setIndentationGuides(True) self.codeEdit.setTabIndents(True) self.codeEdit.setAutoIndent(True) self.cancelButton = QPushButton('Cancel') self.cancelButton.clicked.connect(self.cancel) self.acceptButton = QPushButton('Accept') self.acceptButton.clicked.connect(self.accept) self.language = 'python' self.pythonButton = QRadioButton('Python') self.pythonButton.setChecked(True) self.pythonButton.clicked.connect(self.pythonClicked) self.cppButton = QRadioButton('C++') self.cppButton.clicked.connect(self.cppClicked) codeLanguageContainer = QWidget() hLayout0 = QHBoxLayout() hLayout0.addWidget(self.pythonButton) hLayout0.addWidget(self.cppButton) codeLanguageContainer.setLayout(hLayout0) self.temporalButton = QRadioButton('Temporal', self) self.temporalButton.toggled.connect(self.temporalToggled) self.conditionalButton = QRadioButton('Conditional', self) self.conditionalButton.toggled.connect(self.conditionalToggled) radioButtonContainer = QGroupBox() radioButtonContainer.setTitle('Transition Type') vLayout = QVBoxLayout() vLayout.addWidget(self.temporalButton) vLayout.addWidget(self.conditionalButton) radioButtonContainer.setLayout(vLayout) self.transitionTypeCode = QTextEdit() self.transitionTypeCode.setFont(fixedWidthFont) self.transitionGroupBox = QGroupBox() self.transitionGroupBox.setTitle('Temporal (number in ms)') h3Layout = QHBoxLayout() h3Layout.addWidget(self.transitionTypeCode) self.transitionGroupBox.setLayout(h3Layout) typeContainer = QWidget() h2Layout = QHBoxLayout() h2Layout.addWidget(radioButtonContainer) h2Layout.addWidget(self.transitionGroupBox) typeContainer.setLayout(h2Layout) verticalLayout = QVBoxLayout() verticalLayout.addWidget(typeContainer) verticalLayout.addWidget(codeLanguageContainer) verticalLayout.addWidget(self.codeEdit) container = QWidget() hLayout =QHBoxLayout() hLayout.addWidget(self.cancelButton) hLayout.addWidget(self.acceptButton) container.setLayout(hLayout) verticalLayout.addWidget(container) self.setLayout(verticalLayout) if self.transition.getType() == TransitionType.CONDITIONAL: self.conditionalButton.setChecked(True) self.conditionalToggled() elif self.transition.getType() == TransitionType.TEMPORAL: self.temporalButton.setChecked(True) self.temporalToggled() def cancel(self): self.close() def accept(self): type = None typeValue = None if self.temporalButton.isChecked(): type = int(TransitionType.TEMPORAL) typeValue = self.transitionTypeCode.toPlainText() elif self.conditionalButton.isChecked(): type = int(TransitionType.CONDITIONAL) typeValue = self.transitionTypeCode.toPlainText() self.codeChanged.emit(type, typeValue, self.codeEdit.text()) self.close() def temporalToggled(self): if (self.temporalButton.isChecked()): self.transitionGroupBox.setTitle('Temporal (number in ms)') self.transitionTypeCode.setPlainText(str(self.transition.getTemporalTime())) # print('temporal toggled') def conditionalToggled(self): if (self.conditionalButton.isChecked()): self.transitionGroupBox.setTitle('Condition (evaluates to true or false)') self.transitionTypeCode.setPlainText(self.transition.getCondition()) # print('conditional toggled') def pythonClicked(self): fixedWidthFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) lexer = QsciLexerPython() lexer.setDefaultFont(fixedWidthFont) self.codeEdit.setLexer(lexer) self.language = 'python' def cppClicked(self): fixedWidthFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) lexer = QsciLexerCPP() lexer.setDefaultFont(fixedWidthFont) self.codeEdit.setLexer(lexer) self.language = 'cpp'
class MainWindow(QMainWindow): def __init__(self): super().__init__(flags=0) self.code = QsciScintilla() # self.code.setTabStopWidth(4) self.code.setTabWidth(4) self.code.setMarginWidth(1, 100) self.code.setMarginLineNumbers(1, True) self.code.setAutoIndent(True) self.font = QFont('Courier New', 18) self.code.setFont(self.font) self.code.setMinimumSize(1024, 768) self.locations = {} self.debug_mode = False self.setCentralWidget(self.code) self.pane_output = QDockWidget('Output', self) self.output = QTextEdit(self.pane_output) self.pane_memory = QDockWidget('Memory', self) self.memory_list = QListWidget(self.pane_memory) self.memory = [0] * 65536 self.setup_menu() self.setup_panes() self.cfg = Config() self.directory = self.cfg.get('directory') self.filename = self.cfg.get('filename') if self.filename: self.open_file(self.filename) self.mega = Mega() self.update_memory_list() self.load_settings() def load_settings(self): geom = self.cfg.get('geometry') if not isinstance(geom, str): self.restoreGeometry(geom) state = self.cfg.get('state') if not isinstance(state, str): self.restoreState(state) def closeEvent(self, e: QCloseEvent) -> None: self.cfg.set('geometry', self.saveGeometry()) self.cfg.set('state', self.saveState()) def setup_panes(self): self.pane_output.setObjectName('Output') self.pane_output.setAllowedAreas(Qt.BottomDockWidgetArea) self.output.setTextInteractionFlags(Qt.TextSelectableByMouse) self.output.setFont(self.font) self.pane_output.setWidget(self.output) self.addDockWidget(Qt.BottomDockWidgetArea, self.pane_output) self.pane_memory.setObjectName('Memory') self.pane_memory.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.pane_memory.setWidget(self.memory_list) self.memory_list.setFont(self.font) self.addDockWidget(Qt.RightDockWidgetArea, self.pane_memory) def setup_menu(self): mb = self.menuBar() m = mb.addMenu('&File') dir_open = QAction('Open &Dir', m) dir_open.triggered.connect(self.on_dir_open) m.addAction(dir_open) file_open = QAction('&Open', m) file_open.triggered.connect(self.on_file_open) file_open.setShortcut('Ctrl+O') m.addAction(file_open) file_save = QAction('&Save', m) file_save.triggered.connect(self.on_file_save) file_save.setShortcut('Ctrl+S') m.addAction(file_save) m = mb.addMenu('&Build') assemble = QAction('&Assemble', m) assemble.triggered.connect(self.on_assemble) assemble.setShortcut('F7') m.addAction(assemble) program = QAction('&Program', m) program.triggered.connect(self.on_program) program.setShortcut('F9') m.addAction(program) m = mb.addMenu('&Debug') start = QAction('&Mode', m) start.triggered.connect(self.on_toggle_debug) start.setShortcut('F5') m.addAction(start) clock = QAction('&Clock', m) clock.triggered.connect(self.on_clock) clock.setShortcut('F11') m.addAction(clock) clock = QAction('&AutoClock', m) clock.triggered.connect(self.on_auto_clock) m.addAction(clock) ram = QAction('&RAM Update', m) ram.triggered.connect(self.on_update_memory) ram.setShortcut('F6') m.addAction(ram) def on_dir_open(self): res = QFileDialog.getExistingDirectory(caption='Select Directory', directory=self.directory) print(res) def open_file(self, filename): try: self.code.setText(open(filename).read()) self.cfg.set('filename', filename) except IOError: QMessageBox.warning(self, title='Error', text=f'Cannot open {filename}') def on_file_open(self): res = QFileDialog.getOpenFileName(caption='Open', filter='*.asm') filename = res[0] if filename: self.open_file(filename) def on_file_save(self): if self.filename: code = self.code.text() with open(self.filename, 'w') as f: f.write(code) def set_output(self, text, default=''): if not text: text = default self.output.setText(text) def on_assemble(self): work_dir = os.path.dirname(self.filename) filename = os.path.basename(self.filename) try: res = subprocess.run(['zasm', filename, '0', '0'], capture_output=True, cwd=work_dir, check=True) self.set_output(res.stdout.decode('utf-8'), 'Done') except subprocess.CalledProcessError: self.set_output('Assembler failed') def on_program(self): bin_name = self.filename.replace('.asm', '.bin') try: data = open(bin_name, 'rb').read() self.mega.write_memory(0, data) except IOError: QMessageBox.warning(parent=self, title='Error', text='Failed to open binary') def on_toggle_debug(self): if self.debug_mode: self.on_stop_debug() else: self.on_start_debug() def on_stop_debug(self): self.debug_mode = False try: self.code.setText(open(self.filename).read()) self.code.setReadOnly(False) except IOError: QMessageBox.warning(parent=self, title="Error", text=f'File "{self.filename}" not found') def on_start_debug(self): self.debug_mode = True lst_name = self.filename.replace('.asm', '.lst') try: listing = open(lst_name).read() self.code.setText(listing) self.code.setReadOnly(True) i = 0 for line in listing.split('\n'): parts = line.split() if parts: address = int(parts[0], 0) self.addr2line[address] = i i += 1 except IOError: QMessageBox.warning(parent=self, title='Error', text='No listing found. Try assemble') def on_clock(self): count = 0 print("------------------------------------------------------") while True: address, data, flags = self.mega.clock_read_bus() print(f'{address:04x}:{data:02x} {flags:02x} {flag_text(flags)}') if (flags & 3) == 0: count += 1 if count >= 2: if address in self.addr2line: y = self.addr2line.get(address) self.code.setSelection(y, 0, y + 1, 0) break def on_auto_clock(self): self.mega.auto_clock() def update_memory_list(self): self.memory_list.clear() for address in range(0, 8192, 16): line = f'{address:04x}' for i in range(16): line = line + f' {self.memory[address + i]:02x}' self.memory_list.addItem(QListWidgetItem(line)) def update_memory(self, address: int, length: int): if address < 0 or (address + length) > len(self.memory): QMessageBox.warning(parent=self, title='Error', text='Invalid memory range') return data = self.mega.read_memory(address, length) self.memory[address:(address + length)] = data self.update_memory_list() def on_update_memory(self): self.update_memory(0, 8192)
class CodeDialog(QDialog): codeChanged = pyqtSignal('QString') def __init__(self, name, currentValue): super(QDialog, self).__init__() self.setWindowTitle(name) self.resize(800, 600) self.codeEdit = QsciScintilla() self.codeEdit.setText(currentValue) fixedWidthFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) self.codeEdit.setFont(fixedWidthFont) fontmetrics = QFontMetrics(fixedWidthFont) self.codeEdit.setMarginWidth(0, fontmetrics.width("000")) self.codeEdit.setMarginLineNumbers(0, True) self.codeEdit.setMarginsBackgroundColor(QColor("#cccccc")) self.codeEdit.setBraceMatching(QsciScintilla.SloppyBraceMatch) self.codeEdit.setCaretLineVisible(True) self.codeEdit.setCaretLineBackgroundColor(QColor("#ffe4e4")) lexer = QsciLexerPython() lexer.setDefaultFont(fixedWidthFont) self.codeEdit.setLexer(lexer) self.codeEdit.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.codeEdit.setUtf8(True) self.codeEdit.setTabWidth(4) self.codeEdit.setIndentationsUseTabs(True) self.codeEdit.setIndentationGuides(True) self.codeEdit.setTabIndents(True) self.codeEdit.setAutoIndent(True) self.cancelButton = QPushButton('Cancel') self.cancelButton.clicked.connect(self.cancel) self.acceptButton = QPushButton('Accept') self.acceptButton.clicked.connect(self.accept) self.pythonButton = QRadioButton('Python') self.pythonButton.setChecked(True) self.pythonButton.clicked.connect(self.pythonClicked) self.cppButton = QRadioButton('C++') self.cppButton.clicked.connect(self.cppClicked) hLayout0 = QHBoxLayout() hLayout0.addWidget(self.pythonButton) hLayout0.addWidget(self.cppButton) container0 = QWidget() container0.setLayout(hLayout0) verticalLayout = QVBoxLayout() verticalLayout.addWidget(container0) verticalLayout.addWidget(self.codeEdit) container = QWidget() hLayout = QHBoxLayout() hLayout.addWidget(self.cancelButton) hLayout.addWidget(self.acceptButton) container.setLayout(hLayout) verticalLayout.addWidget(container) self.setLayout(verticalLayout) self.language = 'python' def cancel(self): self.close() def accept(self): self.codeChanged.emit(self.codeEdit.text()) self.close() def pythonClicked(self): fixedWidthFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) lexer = QsciLexerPython() lexer.setDefaultFont(fixedWidthFont) self.codeEdit.setLexer(lexer) self.language = 'python' def cppClicked(self): fixedWidthFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) lexer = QsciLexerCPP() lexer.setDefaultFont(fixedWidthFont) self.codeEdit.setLexer(lexer) self.language = 'cpp'