main_windows.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import queue
  2. import re
  3. import sys
  4. import threading
  5. from PySide2.QtWidgets import QApplication, QMainWindow
  6. from PySide2.QtUiTools import QUiLoader
  7. from PySide2.QtWidgets import *
  8. from PySide2.QtCore import *
  9. from PySide2 import QtCore
  10. from PySide2.QtGui import *
  11. from ui.ui_MainWindows import Ui_MainWindow
  12. from ui.Analyze import AnalyzeWindow
  13. from sub_windows import SubWindows,LineEditWin,FormWindow, get_sub_win_list,get_sub_win
  14. from ui.About import AboutWindow
  15. import GuiType
  16. class Stream(QObject):
  17. """Redirects console output to text widget."""
  18. newText = Signal(str)
  19. def __init__(self):
  20. super().__init__()
  21. self.stdout_bak = sys.stdout
  22. self.buffer = self.stdout_bak.buffer
  23. self.close = self.stdout_bak.close
  24. self.closed = self.stdout_bak.closed
  25. self.detach = self.stdout_bak.detach
  26. self.encoding = self.stdout_bak.encoding
  27. self.errors = self.stdout_bak.errors
  28. self.fileno = self.stdout_bak.fileno
  29. self.flush = self.stdout_bak.flush
  30. self.isatty = self.stdout_bak.isatty
  31. self.line_buffering = self.stdout_bak.line_buffering
  32. self.mode = self.stdout_bak.mode
  33. self.name = self.stdout_bak.name
  34. self.newlines = self.stdout_bak.newlines
  35. self.read = self.stdout_bak.read
  36. self.readable = self.stdout_bak.readable
  37. self.readline = self.stdout_bak.readline
  38. self.readlines = self.stdout_bak.readlines
  39. self.reconfigure = self.stdout_bak.reconfigure
  40. self.seek = self.stdout_bak.seek
  41. self.seekable = self.stdout_bak.seekable
  42. self.tell = self.stdout_bak.tell
  43. self.truncate = self.stdout_bak.truncate
  44. self.writable = self.stdout_bak.writable
  45. self.write_through = self.stdout_bak.write_through
  46. self.writelines = self.stdout_bak.writelines
  47. def write(self, text:str):
  48. self.stdout_bak.write(str(text))
  49. self.stdout_bak.flush()
  50. if len(text) == 0:
  51. return
  52. if text.isspace():
  53. return
  54. self.newText.emit(str(text+'\n'))
  55. class MessageItem(QTreeWidgetItem):
  56. def __init__(self, parent, msg:GuiType._GuiMessage):
  57. super().__init__(parent)
  58. self.setText(0, msg.Text)
  59. self.msg = msg
  60. class MessagesWidgetItem(QTreeWidgetItem):
  61. def __init__(self, parent, messages:GuiType._GuiMessages, level):
  62. super().__init__(parent)
  63. summary = messages.GetSummary()
  64. self.setText(0, level + f"({messages.Size})")
  65. for id_, size, text in summary:
  66. sumary_item = QTreeWidgetItem(self)
  67. sumary_item.setText(0, f"{id_}({size}):{text}")
  68. for msg in messages.GetMsgByID(id_):
  69. msg:GuiType._GuiMessage
  70. MessageItem(sumary_item, msg)
  71. class MainWindow(Ui_MainWindow, QMainWindow):
  72. textEdit_sig = Signal(str)
  73. sig = Signal(object)
  74. def __init__(self, GUI) -> None:
  75. super().__init__()
  76. self.setupUi(self)
  77. # 这里显示一下是为了能获取到 mdiArea 的尺寸,给 sub_windows 使用
  78. self.show()
  79. self.btn_shell.setText(GUI.Prompt)
  80. self.btn_shell.clicked.connect(self.click_btn_sell)
  81. self.tabWidget.currentChanged.connect(self.table_widget_change)
  82. self.tableHistory.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
  83. self.tableHistory.customContextMenuRequested.connect(self.history_right_click_menu)
  84. self.MessageTreeView.customContextMenuRequested.connect(self.message_right_click_menu)
  85. self.loader = QUiLoader()
  86. self.actionReport_Virtual_Timing.triggered.connect(self.add_sub_win)
  87. self.actionAbout.triggered.connect(self.about)
  88. self.actionAnalyze.triggered.connect(self.show_analyze_window)
  89. self.textEdit.document().contentsChanged.connect(self.textEdit_change_size)
  90. self.textEdit.document().contentsChange.connect(self.textEdit_change_contents)
  91. sys.stdout = Stream()
  92. sys.stdout.newText.connect(self.outputWritten)
  93. sys.stderr = sys.stdout
  94. self.GUI = GUI
  95. self.setWindowTitle(GUI.Title)
  96. self.sub_win = SubWindows(self)
  97. self.sub_win.sig.connect(self.sub_win.add_windows)
  98. def table_widget_change(self, index):
  99. member = {
  100. 0: None,
  101. 1: self.show_history,
  102. 2: self.show_message
  103. }
  104. method = member.get(index)
  105. if method:
  106. method()
  107. def show_history(self):
  108. self.tableHistory.clear()
  109. self.tableHistory.setRowCount(0)
  110. for row_text in self.GUI.GetHistory():
  111. end_row = self.tableHistory.rowCount()
  112. self.tableHistory.insertRow(end_row)
  113. self.tableHistory.setItem(end_row, 0, QTableWidgetItem(row_text))
  114. def copy(self, text):
  115. clipboard = QApplication.clipboard()
  116. clipboard.setText(text)
  117. def history_right_click_menu(self):
  118. itemPos = self.tableHistory.mapFromGlobal(QCursor().pos())
  119. item = self.tableHistory.itemAt(itemPos)
  120. if type(item) != QTableWidgetItem:
  121. return
  122. pop_menu = QMenu()
  123. pop_menu.addAction(QAction('Copy', pop_menu))
  124. pop_menu.triggered.connect(lambda: self.copy(self.tableHistory.currentItem().text()))
  125. pop_menu.exec_(QCursor.pos())
  126. def message_right_click_menu(self):
  127. itemPos = self.MessageTreeView.mapFromGlobal(QCursor().pos())
  128. item:MessageItem = self.MessageTreeView.itemAt(itemPos)
  129. if type(item) != MessageItem:
  130. return
  131. pop_menu = QMenu()
  132. pop_menu.addAction(QAction('Crossprobe', pop_menu))
  133. pop_menu.addAction(QAction('Properties', pop_menu))
  134. pop_menu.triggered.connect(lambda action: self.message_popmenu_action(action, item))
  135. pop_menu.exec_(QCursor.pos())
  136. def message_popmenu_action(self, action, item):
  137. if action.text() == 'Crossprobe':
  138. win_line_text = item.msg.CrossProbe()
  139. win = get_sub_win(self.mdiArea, LineEditWin, win_line_text.Title)
  140. # 如果窗口已经存在,关闭窗口,以便重新更新数据
  141. if win:
  142. win.close()
  143. LineEditWin(self.mdiArea, win_line_text)
  144. elif action.text() == 'Properties':
  145. win_form = item.msg.Properties()
  146. # 如果窗口已经存在,关闭窗口,以便重新更新数据
  147. win = get_sub_win(self.mdiArea, FormWindow, win_form.Title)
  148. if win:
  149. win.close()
  150. FormWindow(self.mdiArea, win_form)
  151. def show_message(self):
  152. for _ in range(self.MessageTreeView.topLevelItemCount()):
  153. self.MessageTreeView.takeTopLevelItem(0)
  154. MessagesWidgetItem(self.MessageTreeView, self.GUI.GetErrors(), "Errors")
  155. MessagesWidgetItem(self.MessageTreeView, self.GUI.GetCriticalWarnings(), "CriticalWarnings")
  156. MessagesWidgetItem(self.MessageTreeView, self.GUI.GetWarnings(), "Warnings")
  157. MessagesWidgetItem(self.MessageTreeView, self.GUI.GetInfos(), "Infos")
  158. self.MessageTreeView.expandAll()
  159. def about(self):
  160. d = AboutWindow(self, self.GUI.About)
  161. d.exec_()
  162. def show_analyze_window(self):
  163. d = AnalyzeWindow(self, self.GUI.Shell_Execute)
  164. d.exec_()
  165. def outputWritten(self, text):
  166. cursor = self.LogText.textCursor()
  167. cursor.movePosition(QTextCursor.End)
  168. cursor.insertText(text)
  169. self.LogText.setTextCursor(cursor)
  170. self.LogText.ensureCursorVisible()
  171. def textEdit_change_size(self):
  172. height = self.textEdit.document().size().height()
  173. self.textEdit.setMinimumHeight(height)
  174. def click_btn_sell(self):
  175. self.textEdit.append('\n')
  176. def textEdit_change_contents(self, from_index, charsRemoved, charsAdded):
  177. if not charsAdded:
  178. return
  179. stdin = self.textEdit.toPlainText()
  180. if not stdin:
  181. return
  182. # 捕获回车键
  183. if stdin[from_index] != '\n':
  184. return
  185. # 回车时,判断字符串代码是否结束
  186. if self.GUI.Shell_IsCmdFinished(stdin):
  187. # 删除回车字符
  188. stdin = stdin[:from_index] + stdin[from_index+1:]
  189. print(stdin)
  190. thread = threading.Thread(target=self.GUI.Shell_Execute, args=(stdin,))
  191. thread.start()
  192. self.textEdit.setText('')
  193. self.textEdit_change_size()
  194. def add_sub_win(self):
  195. print('add sub')
  196. self.t = self.loader.load("ui/TimingAnalyze.ui")
  197. self.mdiArea.addSubWindow(self.t)
  198. self.t.show()