main_windows.py 11 KB

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