main_windows.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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.GUI = GUI
  83. self.setWindowTitle(GUI.Title)
  84. self.btn_shell.setText(GUI.Prompt)
  85. self.btn_shell.clicked.connect(self.click_btn_sell)
  86. self.tabWidget.currentChanged.connect(self.table_widget_change)
  87. self.tableHistory.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
  88. self.tableHistory.customContextMenuRequested.connect(self.history_right_click_menu)
  89. self.MessageTreeView.customContextMenuRequested.connect(self.message_right_click_menu)
  90. self.status_label = QLabel("Ready")
  91. self.statusbar.addWidget(self.status_label)
  92. self.loader = QUiLoader()
  93. self.actionCopy.triggered.connect(self.action_copy)
  94. self.actionPast.triggered.connect(self.action_paste)
  95. self.actionSelect_all.triggered.connect(self.action_select_all)
  96. self.actionAnalyze.triggered.connect(self.show_analyze_window)
  97. self.actionRead_Timing_Constraint.triggered.connect(self.read_timing_constraint)
  98. self.actionRead_Power_Intent
  99. self.actionElaborate.triggered.connect(self.elaborate_window)
  100. self.actionReload_Design.triggered.connect(self.reload_design)
  101. # MENUE
  102. # file
  103. self.actionStop_GUI.triggered.connect(GUI.Stop)
  104. self.actionExit.triggered.connect(GUI.Exit)
  105. # View
  106. self.actionIncr_Font
  107. self.actionDecr_Font
  108. self.actionToolbar.triggered.connect(lambda: self.toolBar.setHidden(not self.actionToolbar.isChecked()))
  109. self.actionSidebar.triggered.connect(lambda: self.sub_win.side_bar.mdisubwin.setHidden(not self.actionSidebar.isChecked()))
  110. self.actionConsole.triggered.connect(lambda: self.tabWidget.setHidden(not self.actionConsole.isChecked()))
  111. self.actionStatusBar.triggered.connect(lambda: self.statusbar.setHidden(not self.actionStatusBar.isChecked()))
  112. self.actionSave_as_Default
  113. self.actionPreferences
  114. # Design
  115. self.actionReport_Exceptions.triggered.connect(self.about)
  116. self.actionReport_Virtual_Timing.triggered.connect(self.add_sub_win)
  117. # Windows
  118. self.action_win_group = QActionGroup(self)
  119. self.action_Hierarchy.setActionGroup(self.action_win_group)
  120. action_tabgroup = QActionGroup(self)
  121. self.actionLog.setActionGroup(action_tabgroup)
  122. self.actionHistory.setActionGroup(action_tabgroup)
  123. self.actionMessages.setActionGroup(action_tabgroup)
  124. self.actionLog.triggered.connect(self.action_tab_widget)
  125. self.actionHistory.triggered.connect(self.action_tab_widget)
  126. self.actionMessages.triggered.connect(self.action_tab_widget)
  127. self.actionAbout.triggered.connect(self.about)
  128. self.textEdit.document().contentsChanged.connect(self.textEdit_change_size)
  129. self.textEdit.document().contentsChange.connect(self.textEdit_change_contents)
  130. sys.stdout = Stream()
  131. sys.stdout.newText.connect(self.outputWritten)
  132. sys.stderr = sys.stdout
  133. self.sub_win = SubWindows(self)
  134. self.sub_win.sig.connect(self.sub_win.add_windows)
  135. def action_copy(self):
  136. # 获得文本光标所在控件
  137. widget:QTextBrowser = self.focusWidget()
  138. if type(widget) not in (QTextBrowser, QTextEdit):
  139. return
  140. cur:QTextCursor = widget.textCursor()
  141. self.copy(cur.selectedText())
  142. def action_paste(self):
  143. clipboard = QApplication.clipboard()
  144. # 获得文本光标所在控件
  145. widget:QTextBrowser = self.focusWidget()
  146. if type(widget) not in (QTextBrowser, QTextEdit):
  147. return
  148. widget.textCursor().insertText(clipboard.text())
  149. def action_select_all(self):
  150. # 获得文本光标所在控件
  151. widget:QTextBrowser = self.focusWidget()
  152. if type(widget) not in (QTextBrowser, QTextEdit):
  153. return
  154. widget.selectAll()
  155. def action_tab_widget(self):
  156. action_sender = self.sender()
  157. action = {
  158. self.actionLog: 0,
  159. self.actionHistory: 1,
  160. self.actionMessages: 2,
  161. }
  162. index = action.get(action_sender)
  163. if index != None:
  164. self.tabWidget.setCurrentIndex(index)
  165. def read_timing_constraint(self):
  166. ReadTimeWindow(self, os.getcwd())
  167. def table_widget_change(self, index):
  168. member = {
  169. 0: None,
  170. 1: self.show_history,
  171. 2: self.show_message
  172. }
  173. method = member.get(index)
  174. if method:
  175. method()
  176. def show_history(self):
  177. self.tableHistory.clear()
  178. blank_row = self.tableHistory.height() / self.tableHistory.verticalHeader().height() + 2
  179. self.tableHistory.setRowCount(blank_row)
  180. for row_text in self.GUI.GetHistory():
  181. end_row = self.tableHistory.rowCount()
  182. self.tableHistory.insertRow(end_row)
  183. self.tableHistory.setItem(end_row, 0, QTableWidgetItem(row_text))
  184. self.tableHistory.scrollToBottom()
  185. def copy(self, text):
  186. clipboard = QApplication.clipboard()
  187. clipboard.setText(text)
  188. def history_right_click_menu(self):
  189. itemPos = self.tableHistory.mapFromGlobal(QCursor().pos())
  190. item = self.tableHistory.itemAt(itemPos)
  191. if type(item) != QTableWidgetItem:
  192. return
  193. pop_menu = QMenu()
  194. pop_menu.addAction(QAction('Copy', pop_menu))
  195. pop_menu.triggered.connect(lambda: self.copy(self.tableHistory.currentItem().text()))
  196. pop_menu.exec_(QCursor.pos())
  197. def message_right_click_menu(self):
  198. itemPos = self.MessageTreeView.mapFromGlobal(QCursor().pos())
  199. item:MessageItem = self.MessageTreeView.itemAt(itemPos)
  200. if type(item) != MessageItem:
  201. return
  202. pop_menu = QMenu()
  203. pop_menu.addAction(QAction('Crossprobe', pop_menu))
  204. pop_menu.addAction(QAction('Properties', pop_menu))
  205. pop_menu.triggered.connect(lambda action: self.message_popmenu_action(action, item))
  206. pop_menu.exec_(QCursor.pos())
  207. def message_popmenu_action(self, action, item):
  208. if action.text() == 'Crossprobe':
  209. win_line_text = item.msg.CrossProbe()
  210. win = get_sub_win(self.mdiArea, LineEditWin, win_line_text.Title)
  211. # 如果窗口已经存在,关闭窗口,以便重新更新数据
  212. if win:
  213. win.close()
  214. LineEditWin(self.mdiArea, win_line_text)
  215. elif action.text() == 'Properties':
  216. win_form = item.msg.Properties()
  217. # 如果窗口已经存在,关闭窗口,以便重新更新数据
  218. win = get_sub_win(self.mdiArea, FormWindow, win_form.Title)
  219. if win:
  220. win.close()
  221. FormWindow(self.mdiArea, win_form)
  222. def show_message(self):
  223. for _ in range(self.MessageTreeView.topLevelItemCount()):
  224. self.MessageTreeView.takeTopLevelItem(0)
  225. MessagesWidgetItem(self.MessageTreeView, self.GUI.GetErrors(), "Errors")
  226. MessagesWidgetItem(self.MessageTreeView, self.GUI.GetCriticalWarnings(), "CriticalWarnings")
  227. MessagesWidgetItem(self.MessageTreeView, self.GUI.GetWarnings(), "Warnings")
  228. MessagesWidgetItem(self.MessageTreeView, self.GUI.GetInfos(), "Infos")
  229. def about(self):
  230. d = AboutWindow(self, self.GUI.About)
  231. d.exec_()
  232. def show_analyze_window(self):
  233. d = AnalyzeWindow(self, self.GUI.Shell_Execute)
  234. d.exec_()
  235. def elaborate_window(self):
  236. d = Elaborate(self)
  237. d.exec_()
  238. def outputWritten(self, text):
  239. cursor = self.LogText.textCursor()
  240. cursor.movePosition(QTextCursor.End)
  241. cursor.insertText(text)
  242. self.LogText.setTextCursor(cursor)
  243. self.LogText.ensureCursorVisible()
  244. def textEdit_change_size(self):
  245. height = self.textEdit.document().size().height()
  246. self.textEdit.setMinimumHeight(height)
  247. def click_btn_sell(self):
  248. self.textEdit.append('\n')
  249. def textEdit_change_contents(self, from_index, charsRemoved, charsAdded):
  250. if not charsAdded:
  251. return
  252. stdin = self.textEdit.toPlainText()
  253. if not stdin:
  254. return
  255. # 捕获回车键
  256. if stdin[from_index] != '\n':
  257. return
  258. # 回车时,判断字符串代码是否结束
  259. if self.GUI.Shell_IsCmdFinished(stdin):
  260. # 删除回车字符
  261. stdin = stdin[:from_index] + stdin[from_index+1:]
  262. print(stdin)
  263. thread = threading.Thread(target=self.GUI.Shell_Execute, args=(stdin,))
  264. thread.start()
  265. self.textEdit.setText('')
  266. self.textEdit_change_size()
  267. def reload_design(self):
  268. thread = threading.Thread(target=self.GUI.ReloadDesign)
  269. thread.start()
  270. def add_sub_win(self):
  271. print('add sub')
  272. self.t = self.loader.load("ui/TimingAnalyze.ui")
  273. self.mdiArea.addSubWindow(self.t)
  274. self.t.show()