Просмотр исходного кода

解决 Crossprobe 窗口出现了行号和文本不对齐的情况

mrh 3 лет назад
Родитель
Сommit
50122bb044
6 измененных файлов с 116 добавлено и 245 удалено
  1. 8 8
      GuiShell.py
  2. 5 28
      sub_windows.py
  3. 1 15
      ui/LineEdit.ui
  4. 102 96
      ui/lineNumberWidget.py
  5. 0 8
      ui/ui_LineEdit.py
  6. 0 90
      ui/ui_TimingAnalyze.py

+ 8 - 8
GuiShell.py

@@ -18,10 +18,10 @@ class _GuiMain():
     History = []
     History = []
     SideBar = None
     SideBar = None
     Messages = None
     Messages = None
-    TextFont = "Monospace"
-    TextFontSize = 13
-    SysFont = "FreeMono"
-    SysFontSize = 15
+    TextFont = "Cantarell"
+    TextFontSize = 11
+    SysFont = "Cantarell"
+    SysFontSize = 12
     About = "NeoConstraint(R) 2023.03-Alpha\nChipara, Inc. Ltd"     # Help-About
     About = "NeoConstraint(R) 2023.03-Alpha\nChipara, Inc. Ltd"     # Help-About
     Prompt = "nc_shell-t>"        # Console-Shell
     Prompt = "nc_shell-t>"        # Console-Shell
  
  
@@ -60,10 +60,10 @@ class _GuiMain():
 
 
     def ViewGetDefault(self):
     def ViewGetDefault(self):
         # Read from disk, blah blah
         # Read from disk, blah blah
-        self.TextFont = "Monospace"
-        self.TextFontSize = 10
-        self.SysFont = "FreeMono"
-        self.SysFontSize = 9
+        self.TextFont = "Cantorall"
+        self.TextFontSize = 11
+        self.SysFont = "Cantorall"
+        self.SysFontSize = 12
 
 
     def ViewSet(self, text_font_size, text_font, sys_font_size, sys_font):
     def ViewSet(self, text_font_size, text_font, sys_font_size, sys_font):
         self.TextFont = text_font
         self.TextFont = text_font

+ 5 - 28
sub_windows.py

@@ -7,7 +7,7 @@ from PySide2.QtGui import *
 from PySide2.QtUiTools import QUiLoader
 from PySide2.QtUiTools import QUiLoader
 from ui.ui_Form import Ui_Form
 from ui.ui_Form import Ui_Form
 from ui.ui_SideBar import Ui_SideBar
 from ui.ui_SideBar import Ui_SideBar
-from ui.lineNumberWidget import LineNumberWidget
+from ui.lineNumberWidget import Editor
 from ui.ui_LineEdit import Ui_LineEdit
 from ui.ui_LineEdit import Ui_LineEdit
 from ui.Analyze import AnalyzeWindow
 from ui.Analyze import AnalyzeWindow
 import GuiType as GuiType
 import GuiType as GuiType
@@ -246,9 +246,8 @@ class LineEditWin(Ui_LineEdit, MdiActionWindow):
         super().__init__(mainWindow)
         super().__init__(mainWindow)
         self.setupUi(self)
         self.setupUi(self)
         self.setWindowTitle(instance.Title)
         self.setWindowTitle(instance.Title)
-        self.textBrowser.textChanged.connect(self.__line_widget_line_count_changed)
-        self.lineWidget = LineNumberWidget(self.textBrowser)
-        self.horizontalLayout.insertWidget(0,self.lineWidget)
+        self.editor = Editor(mainWindow)
+        self.horizontalLayout.addWidget(self.editor)
         self.instance = instance
         self.instance = instance
         self.set_text(instance)
         self.set_text(instance)
 
 
@@ -259,34 +258,12 @@ class LineEditWin(Ui_LineEdit, MdiActionWindow):
         self.mdisubwin.resize(self.width(), mdiArea.height())
         self.mdisubwin.resize(self.width(), mdiArea.height())
         self.mdisubwin.show()
         self.mdisubwin.show()
 
 
-        self.go_to_line(self.instance.GotoLine)
+        self.editor.goToLine(self.instance.GotoLine)
         
         
     def set_text(self, instance:GuiType._GuiWinLinedText):
     def set_text(self, instance:GuiType._GuiWinLinedText):
         for text in instance.LinedText:
         for text in instance.LinedText:
-            self.textBrowser.append(text)
+            self.editor.appendPlainText(text)
     
     
-    def go_to_line(self, line):
-        if line > self.lineWidget.line_count():
-            line = self.lineWidget.line_count()
-        cur = self.textBrowser.textCursor()
-        cur.movePosition(QTextCursor.Start)
-        self.textBrowser.setTextCursor(cur)
-        position = self.textBrowser.document().findBlockByLineNumber(line-1).position()
-        if position < self.textBrowser.height()/2:
-            position = 0
-        elif position < self.textBrowser.document().lastBlock().position() - self.textBrowser.height()/2:
-            position += self.textBrowser.height()/2
-        else:
-            position = self.textBrowser.document().lastBlock().position()
-        cur.setPosition(position, QTextCursor.MoveAnchor)
-        self.textBrowser.setTextCursor(cur)
-        
-        self.lineWidget.highlightLineNumber(line)
-    
-    def __line_widget_line_count_changed(self):
-            if self.lineWidget:
-                n = int(self.textBrowser.document().lineCount())
-                self.lineWidget.changeLineCount(n)
          
          
                 
                 
 class SideBarWin(Ui_SideBar, MdiActionWindow):
 class SideBarWin(Ui_SideBar, MdiActionWindow):

+ 1 - 15
ui/LineEdit.ui

@@ -20,21 +20,7 @@
   <widget class="QWidget" name="centralwidget">
   <widget class="QWidget" name="centralwidget">
    <layout class="QGridLayout" name="gridLayout">
    <layout class="QGridLayout" name="gridLayout">
     <item row="0" column="0">
     <item row="0" column="0">
-     <layout class="QHBoxLayout" name="horizontalLayout" stretch="0">
-      <item>
-       <widget class="QTextBrowser" name="textBrowser">
-        <property name="contextMenuPolicy">
-         <enum>Qt::NoContextMenu</enum>
-        </property>
-        <property name="lineWrapMode">
-         <enum>QTextEdit::NoWrap</enum>
-        </property>
-        <property name="textInteractionFlags">
-         <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
-        </property>
-       </widget>
-      </item>
-     </layout>
+     <layout class="QHBoxLayout" name="horizontalLayout" stretch=""/>
     </item>
     </item>
    </layout>
    </layout>
   </widget>
   </widget>

+ 102 - 96
ui/lineNumberWidget.py

@@ -1,103 +1,109 @@
 from PySide2.QtGui import *
 from PySide2.QtGui import *
-from PySide2.QtWidgets import QTextBrowser,QTextEdit
+from PySide2 import QtCore, QtGui, QtWidgets
 from PySide2.QtCore import Qt
 from PySide2.QtCore import Qt
 
 
 
 
-class LineNumberWidget(QTextBrowser):
-    def __init__(self, widget):
-        super().__init__()
-        self.__initUi(widget)
-
-    def __initUi(self, widget):
-        self.__lineCount = widget.document().lineCount()
-        self.__size = int(widget.font().pointSizeF())
-        self.__styleInit()
-        # 尝试解决行号换行问题
-        self.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap)
-        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
-        self.setTextInteractionFlags(Qt.NoTextInteraction)
-
-        self.verticalScrollBar().setEnabled(False)
-
-        widget.verticalScrollBar().valueChanged.connect(self.__changeLineWidgetScrollAsTargetedWidgetScrollChanged)
-
-        self.__initLineCount()
-        self.befor_hightlight_line = None
-
-    def __changeLineWidgetScrollAsTargetedWidgetScrollChanged(self, v):
-        self.verticalScrollBar().setValue(v)
-        self.setWidthByStr()
-
-    def __initLineCount(self):
-        for n in range(1, self.__lineCount+1):
-            self.append(str(n))
-
-    def changeLineCount(self, n):
-        max_one = max(self.__lineCount, n)
-        diff = n-self.__lineCount
-        if max_one == self.__lineCount:
-            first_v = self.verticalScrollBar().value()
-            for i in range(self.__lineCount, self.__lineCount + diff, -1):
-                self.moveCursor(QTextCursor.End, QTextCursor.MoveAnchor)
-                self.moveCursor(QTextCursor.StartOfLine, QTextCursor.MoveAnchor)
-                self.moveCursor(QTextCursor.End, QTextCursor.KeepAnchor)
-                self.textCursor().removeSelectedText()
-                self.textCursor().deletePreviousChar()
-            last_v = self.verticalScrollBar().value()
-            if abs(first_v-last_v) != 2:
-                self.verticalScrollBar().setValue(first_v)
-        else:
-            for i in range(self.__lineCount, self.__lineCount + diff, 1):
-                self.append(str(i + 1))
-
-        self.__lineCount = n
-
-    def selectLine(self, line):
-        position = self.document().findBlockByLineNumber(line-1).position()
-        tc = self.textCursor()
-        tc.setPosition(position, QTextCursor.MoveAnchor) # 直接跳转到start_pos
-        tc.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)
-        return tc
-    
-    def highlightLineNumber(self, line):
-        if self.befor_hightlight_line:
-            self.clearHighlightLineNumber(self.befor_hightlight_line)
-        fmt = QTextCharFormat()
-        fmt.setFontWeight(QFont.Bold)
-        fmt.setForeground(QBrush(QColor(0,0,0)))
-        tc = self.selectLine(line)
-        tc.mergeCharFormat(fmt) # 格式化选中文本
-        tc.clearSelection() # 取消选中
-        self.befor_hightlight_line = line
-    
-    def clearHighlightLineNumber(self, line):
-        tc = self.selectLine(line)
-        tc.setCharFormat(QTextCharFormat())
-    
-    def setValue(self, v):
-        self.verticalScrollBar().setValue(v)
+class Editor(QtWidgets.QPlainTextEdit):
+    def __init__(self, parent=None):
+        super().__init__(parent)
+        self.lineNumberArea = LineNumberArea(self)
+
+        self.blockCountChanged.connect(self.updateLineNumberAreaWidth)
+        self.updateRequest.connect(self.updateLineNumberArea)
+        self.cursorPositionChanged.connect(self.highlightCurrentLine)
+
+        self.updateLineNumberAreaWidth(0)
+        self.setLineWrapMode(QtWidgets.QPlainTextEdit.LineWrapMode.NoWrap)
+        self.setReadOnly(True)
         
         
-    def setFontSize(self, s: float):
-        self.__size = int(s)
-        self.__styleInit()
-    
-    def setWidthByStr(self):
-        withd = (len(str(self.__lineCount)) + 2) * self.__size*0.7
-        self.setFixedWidth(withd)
-    
-    def line_count(self):
-        return self.__lineCount
+    def goToLine(self, center_line):
+        total_num_of_lines = self.document().lineCount()
+        # 计算每行的高度
+        line_height = self.fontMetrics().lineSpacing()
+        # 获取文本控件可视窗口的高度
+        viewport_height = self.viewport().height()
+        # 每行所需滚动条的值
+        scroll_per_line = (self.verticalScrollBar().pageStep() + self.verticalScrollBar().maximum())/total_num_of_lines
         
         
-    def __styleInit(self):
-        self.__style = f'''
-                       QTextBrowser 
-                       {{ 
-                       background: transparent; 
-                       border: none; 
-                       color: #AAA; 
-                       font: {self.__size}pt;
-                       }}
-                       '''
+        scroll_value = (center_line - viewport_height/2/line_height) * scroll_per_line
         
         
-        self.setStyleSheet(self.__style)
-        self.setWidthByStr()
+        # 移动光标
+        cursor = self.textCursor()
+        cursor.movePosition(QtGui.QTextCursor.Start)
+        for i in range(center_line - 1):
+            cursor.movePosition(QtGui.QTextCursor.Down, QtGui.QTextCursor.MoveAnchor)
+        self.setTextCursor(cursor)
+        self.verticalScrollBar().setValue(0) 
+        self.verticalScrollBar().setValue(scroll_value)  
+
+                                                            
+    def lineNumberAreaWidth(self):
+        digits = 1
+        count = max(1, self.blockCount())
+        while count >= 10:
+            count /= 10
+            digits += 1
+        space = 3 + self.fontMetrics().horizontalAdvance('9') * digits
+        return space
+
+    def updateLineNumberAreaWidth(self, newBlockCount):
+        self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)
+
+    def updateLineNumberArea(self, rect, dy):
+        if dy:
+            self.lineNumberArea.scroll(0, dy)
+        else:
+            self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height())
+
+        if rect.contains(self.viewport().rect()):
+            self.updateLineNumberAreaWidth(0)
+
+    def resizeEvent(self, event):
+        super().resizeEvent(event)
+        cr = self.contentsRect()
+        self.lineNumberArea.setGeometry(QtCore.QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height()))
+
+    def highlightCurrentLine(self):
+        extraSelections = []
+
+        selection = QtWidgets.QTextEdit.ExtraSelection()
+
+        lineColor = QtGui.QColor(232,232,255)
+
+        selection.format.setBackground(lineColor)
+        selection.format.setProperty(QtGui.QTextFormat.FullWidthSelection, True)
+        selection.cursor = self.textCursor()
+        selection.cursor.clearSelection()
+        extraSelections.append(selection)
+
+        self.setExtraSelections(extraSelections)
+
+
+class LineNumberArea(QtWidgets.QWidget):
+    def __init__(self, editor):
+        super().__init__(editor)
+        self.editor = editor
+
+    def sizeHint(self):
+        return QtCore.QSize(self.editor.lineNumberAreaWidth(), 0)
+
+    def paintEvent(self, event):
+        painter = QtGui.QPainter(self)
+        painter.fillRect(event.rect(), QtCore.Qt.lightGray)
+
+        block = self.editor.firstVisibleBlock()
+        blockNumber = block.blockNumber()
+        top = self.editor.blockBoundingGeometry(block).translated(self.editor.contentOffset()).top()
+        bottom = top + self.editor.blockBoundingRect(block).height()
+
+        height = self.editor.fontMetrics().height()
+        while block.isValid() and top <= event.rect().bottom():
+            if block.isVisible() and bottom >= event.rect().top():
+                number = str(blockNumber + 1)
+                painter.setPen(QtCore.Qt.black)
+                painter.drawText(0, top, self.width(), height, QtCore.Qt.AlignRight, number)
+
+            block = block.next()
+            top = bottom
+            bottom = top + self.editor.blockBoundingRect(block).height()
+            blockNumber += 1

+ 0 - 8
ui/ui_LineEdit.py

@@ -31,14 +31,6 @@ class Ui_LineEdit(object):
         self.gridLayout.setObjectName(u"gridLayout")
         self.gridLayout.setObjectName(u"gridLayout")
         self.horizontalLayout = QHBoxLayout()
         self.horizontalLayout = QHBoxLayout()
         self.horizontalLayout.setObjectName(u"horizontalLayout")
         self.horizontalLayout.setObjectName(u"horizontalLayout")
-        self.textBrowser = QTextBrowser(self.centralwidget)
-        self.textBrowser.setObjectName(u"textBrowser")
-        self.textBrowser.setContextMenuPolicy(Qt.NoContextMenu)
-        self.textBrowser.setLineWrapMode(QTextEdit.NoWrap)
-        self.textBrowser.setTextInteractionFlags(Qt.LinksAccessibleByKeyboard|Qt.LinksAccessibleByMouse|Qt.TextBrowserInteraction|Qt.TextSelectableByKeyboard|Qt.TextSelectableByMouse)
-
-        self.horizontalLayout.addWidget(self.textBrowser)
-
 
 
         self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
         self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
 
 

+ 0 - 90
ui/ui_TimingAnalyze.py

@@ -1,90 +0,0 @@
-# -*- coding: utf-8 -*-
-
-################################################################################
-## Form generated from reading UI file 'TimingAnalyze.ui'
-##
-## Created by: Qt User Interface Compiler version 5.15.0
-##
-## WARNING! All changes made in this file will be lost when recompiling UI file!
-################################################################################
-
-from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
-    QObject, QPoint, QRect, QSize, QTime, QUrl, Qt)
-from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
-    QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter,
-    QPixmap, QRadialGradient)
-from PySide2.QtWidgets import *
-
-
-class Ui_TimingWindow(object):
-    def setupUi(self, TimingWindow):
-        if not TimingWindow.objectName():
-            TimingWindow.setObjectName(u"TimingWindow")
-        TimingWindow.resize(534, 461)
-        self.centralwidget = QWidget(TimingWindow)
-        self.centralwidget.setObjectName(u"centralwidget")
-        self.gridLayout = QGridLayout(self.centralwidget)
-        self.gridLayout.setObjectName(u"gridLayout")
-        self.verticalLayout = QVBoxLayout()
-        self.verticalLayout.setObjectName(u"verticalLayout")
-        self.tableView = QTableView(self.centralwidget)
-        self.tableView.setObjectName(u"tableView")
-
-        self.verticalLayout.addWidget(self.tableView)
-
-        self.horizontalLayout = QHBoxLayout()
-        self.horizontalLayout.setObjectName(u"horizontalLayout")
-        self.pushButton = QPushButton(self.centralwidget)
-        self.pushButton.setObjectName(u"pushButton")
-
-        self.horizontalLayout.addWidget(self.pushButton)
-
-        self.pushButton_2 = QPushButton(self.centralwidget)
-        self.pushButton_2.setObjectName(u"pushButton_2")
-
-        self.horizontalLayout.addWidget(self.pushButton_2)
-
-        self.pushButton_4 = QPushButton(self.centralwidget)
-        self.pushButton_4.setObjectName(u"pushButton_4")
-
-        self.horizontalLayout.addWidget(self.pushButton_4)
-
-        self.pushButton_3 = QPushButton(self.centralwidget)
-        self.pushButton_3.setObjectName(u"pushButton_3")
-
-        self.horizontalLayout.addWidget(self.pushButton_3)
-
-
-        self.verticalLayout.addLayout(self.horizontalLayout)
-
-        self.label = QLabel(self.centralwidget)
-        self.label.setObjectName(u"label")
-
-        self.verticalLayout.addWidget(self.label)
-
-
-        self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
-
-        TimingWindow.setCentralWidget(self.centralwidget)
-        self.menubar = QMenuBar(TimingWindow)
-        self.menubar.setObjectName(u"menubar")
-        self.menubar.setGeometry(QRect(0, 0, 534, 23))
-        TimingWindow.setMenuBar(self.menubar)
-        self.statusbar = QStatusBar(TimingWindow)
-        self.statusbar.setObjectName(u"statusbar")
-        TimingWindow.setStatusBar(self.statusbar)
-
-        self.retranslateUi(TimingWindow)
-
-        QMetaObject.connectSlotsByName(TimingWindow)
-    # setupUi
-
-    def retranslateUi(self, TimingWindow):
-        TimingWindow.setWindowTitle(QCoreApplication.translate("TimingWindow", u"MainWindow", None))
-        self.pushButton.setText(QCoreApplication.translate("TimingWindow", u"Report", None))
-        self.pushButton_2.setText(QCoreApplication.translate("TimingWindow", u"Export", None))
-        self.pushButton_4.setText(QCoreApplication.translate("TimingWindow", u"Reload", None))
-        self.pushButton_3.setText(QCoreApplication.translate("TimingWindow", u"Columns", None))
-        self.label.setText(QCoreApplication.translate("TimingWindow", u"TextLabel", None))
-    # retranslateUi
-