main_windows.py 10 KB

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