controlwidget.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. """
  2. This module defines the Initial view of the gui
  3. """
  4. from PyQt4 import QtGui, QtCore
  5. import logging
  6. import kcgwidget as kcgw
  7. from kcgwidget import error
  8. from backend import board
  9. from backend.board import available_boards
  10. from groupedelements import Checkboxes, Buttons, Elements
  11. import backendinterface as bif
  12. from loghandler import LogArea
  13. import storage
  14. from .. import config
  15. tr = kcgw.tr
  16. class LED(QtGui.QWidget):
  17. """
  18. Produces a graphical LED
  19. """
  20. def __init__(self, parent=None, status=1, height=10, width=10):
  21. """
  22. Initialize a LED
  23. :param parent: (QWidget) parent of this widget
  24. :param status: (int) (0=out, 1=off, 2=orange, 3=on) initial status of this LED
  25. :param height: (int) height of the LED
  26. :param width: (int) width of the LED
  27. :return: -
  28. """
  29. QtGui.QWidget.__init__(self, parent)
  30. colorRGB=(255, 0, 0)
  31. self.width = width
  32. self.height = height
  33. self.color = QtGui.QColor(colorRGB[0], colorRGB[1], colorRGB[2])
  34. self.center = QtCore.QPoint(width, height)
  35. self.setMinimumSize(2 * width, 2 * height)
  36. self.setMaximumSize(2 * width, 2 * height)
  37. if status == 3:
  38. self.set_on()
  39. elif status == 1:
  40. self.set_off()
  41. elif status == 0:
  42. self.set_out()
  43. elif status == 2:
  44. self.set_tri()
  45. self.status = status
  46. def paintEvent(self, event):
  47. paint = QtGui.QPainter()
  48. paint.begin(self)
  49. paint.setRenderHint(QtGui.QPainter.Antialiasing)
  50. # draw a grey 'socket' for the LED
  51. paint.setPen(QtGui.QColor(160, 160, 160))
  52. paint.setBrush(QtGui.QColor(180, 180, 180))
  53. paint.drawEllipse(self.center, self.width, self.height)
  54. # draw the body of the LED
  55. paint.setBrush(self.color)
  56. paint.drawEllipse(self.center, self.width*0.85, self.height*0.85)
  57. def set_on(self):
  58. """
  59. Set the LED to "on" state
  60. :return: -
  61. """
  62. self.color = QtGui.QColor(0, 255, 0)
  63. self.update()
  64. self.status = 3
  65. def set_off(self):
  66. """
  67. Set the LED to "off" state
  68. :return: -
  69. """
  70. self.color = QtGui.QColor(255, 0, 0)
  71. self.update()
  72. self.status = 1
  73. def set_out(self):
  74. """
  75. Set the LED to "OUT" state (that is like an LED without power)
  76. :return: -
  77. """
  78. self.color = QtGui.QColor(150, 150, 150)
  79. self.update()
  80. self.status = 0
  81. def set_tri(self):
  82. """
  83. Set the LED to "TRI" state (that is led is orange)
  84. :return: -
  85. """
  86. self.color = QtGui.QColor(255, 255, 0)
  87. self.update()
  88. self.status = 2
  89. def set_status(self, status):
  90. """
  91. Set the status of the led
  92. :param status: status (in 0, 1, 2, 3)
  93. """
  94. if status == 0:
  95. self.set_out()
  96. elif status == 1:
  97. self.set_off()
  98. elif status == 2:
  99. self.set_tri()
  100. elif status == 3:
  101. self.set_on()
  102. class StatusLED(QtGui.QWidget):
  103. """
  104. Create a Status LED with Label next to it
  105. """
  106. def __init__(self, text, status=None):
  107. """
  108. Initialise StatusLED
  109. :param text: label text next to the LED
  110. :param status: initial status of the LED
  111. :return: -
  112. """
  113. super(StatusLED, self).__init__()
  114. self.layout = QtGui.QHBoxLayout()
  115. self.label = QtGui.QLabel(text)
  116. self.led = LED(status=status, width=9, height=9)
  117. self.layout.addWidget(self.led)
  118. self.layout.addWidget(self.label)
  119. self.setLayout(self.layout)
  120. def set_on(self):
  121. """ See set_on of LED Class """
  122. self.led.set_on()
  123. def set_off(self):
  124. """ See set_off of LED Class """
  125. self.led.set_off()
  126. def set_out(self):
  127. """ See set_out of LED Class """
  128. self.led.set_out()
  129. def set_tri(self):
  130. """ See set_tri of LED Class """
  131. self.led.set_tri()
  132. def set_status(self, status):
  133. """
  134. See set_status of LED Class
  135. :param status: the status to set the led to
  136. """
  137. self.led.set_status(status)
  138. class BoardControl(kcgw.KCGWidgets):
  139. def __init__(self, board_id, single=False):
  140. super(BoardControl, self).__init__()
  141. self.board_id = board_id
  142. self.layout = QtGui.QVBoxLayout()
  143. self.setLayout(self.layout)
  144. if not single:
  145. self.header_layout = QtGui.QHBoxLayout()
  146. left_line = QtGui.QFrame()
  147. left_line.setFrameShape(QtGui.QFrame.HLine)
  148. left_line.setFrameShadow(QtGui.QFrame.Sunken)
  149. right_line = QtGui.QFrame()
  150. right_line.setFrameShape(QtGui.QFrame.HLine)
  151. right_line.setFrameShadow(QtGui.QFrame.Sunken)
  152. self.header_layout.addWidget(left_line)
  153. header_label = self.createLabel("Board: {}".format(available_boards.get_board_name_from_id(board_id)))
  154. header_label.setFixedWidth(header_label.sizeHint().width())
  155. self.header_layout.addWidget(header_label)
  156. self.header_layout.addWidget(right_line)
  157. self.layout.addLayout(self.header_layout)
  158. self.mainControlLayout = QtGui.QHBoxLayout()
  159. self.subControlLayout = QtGui.QHBoxLayout()
  160. self.subControlWidget = QtGui.QWidget()
  161. self.subControlWidget.setLayout(self.subControlLayout)
  162. self.statusLayout = QtGui.QHBoxLayout()
  163. self.layout.addLayout(self.mainControlLayout)
  164. self.layout.addWidget(self.subControlWidget)
  165. self.layout.addLayout(self.statusLayout)
  166. # ----------[ LED Status ]---------------
  167. self.pipeline_led = StatusLED(tr("Label", "DataFlow Pipeline"))
  168. self.master_control_led = StatusLED(tr("Label", "Master Control"))
  169. self.data_check_led = StatusLED(tr("Label", "Data Check"))
  170. self.pll_ld_led = StatusLED(tr("Label", "PLL_LD"))
  171. self.statusLayout.addWidget(self.pipeline_led)
  172. self.statusLayout.addWidget(self.master_control_led)
  173. self.statusLayout.addWidget(self.data_check_led)
  174. self.statusLayout.addWidget(self.pll_ld_led)
  175. # -----------[ Buttons ]--------------
  176. self.all_in_one_button = self.createButton(text=tr("Button", "Prepare Board"), connect=self.all_in_one,
  177. tooltip=tr("Tooltip", "Start, Calibrate, Synchronize and set Defaults\nCtrl+A"))
  178. self.toggleButton = self.createButton(text="", connect=self.toggle_sub_control)
  179. self.toggleButton.setIcon(QtGui.QIcon(config.install_path+"icons/chevron-bottom.svg"))
  180. self.toggleButton.setFixedWidth(50)
  181. # self.all_in_one_button.setShortcut("Ctrl+A")
  182. # self.all_in_one_button.setObjectName("all_in_one")
  183. self.skip_init_button = self.createButton(text=tr("Button", "Skip Initialisation"), connect=self.skip_init,
  184. tooltip=tr("Tooltip", "Skip Initialisation and read values from board.\n"
  185. "NOTE: ONLY DO THIS IF BOARD WAS CALIBRATED AND SYNCHRONIZED BEFORE"))
  186. self.start_button = self.createButton(text=tr("Button", "Start Board"), connect=lambda x: bif.bk_start_board(board_id=board_id))
  187. self.calibrate_button = self.createButton(text=tr("Button", "Calibrate"), connect=lambda x: bif.bk_calibrate(board_id=board_id))
  188. self.syncronize_button = self.createButton(text=tr("Button", "Synchronize"), connect=lambda x: bif.bk_sync_board(board_id=board_id))
  189. self.set_default_button = self.createButton(text=tr("Button", "Set Defaults"), connect=lambda x: bif.bk_write_values(board_id=board_id, defaults=True))
  190. self.soft_reset_button = self.createButton(text=tr("Button", "Soft Reset"), connect=lambda x: bif.bk_soft_reset(board_id=board_id))
  191. self.off_button = self.createButton(text=tr("Button", "Board Off"), connect=lambda x: bif.bk_stop_board(board_id=board_id))
  192. self.off_button.setObjectName("off")
  193. self.check_status_button = self.createButton(text=tr("Button", "Check Status"), connect=lambda x: bif._bif_status_readout(board_id=board_id))
  194. Buttons.addButton('start_board_{}'.format(board_id), self.start_button)
  195. Buttons.addButton(['calibrate_{}'.format(board_id), 'after_start_{}'.format(board_id)], self.calibrate_button)
  196. Buttons.addButton(['synchronize_{}'.format(board_id), 'after_start_{}'.format(board_id)], self.syncronize_button)
  197. Buttons.addButton(['set_defaults_{}'.format(board_id), 'after_start_{}'.format(board_id)], self.set_default_button)
  198. Elements.addItem('no_board_{}'.format(board_id),
  199. [
  200. self.start_button,
  201. self.calibrate_button,
  202. self.syncronize_button,
  203. self.set_default_button,
  204. self.soft_reset_button,
  205. self.off_button,
  206. self.all_in_one_button
  207. ])
  208. self.mainControlLayout.addWidget(self.skip_init_button)
  209. self.mainControlLayout.addWidget(self.all_in_one_button)
  210. self.mainControlLayout.addWidget(self.toggleButton)
  211. self.mainControlLayout.addWidget(self.soft_reset_button)
  212. self.mainControlLayout.addWidget(self.off_button)
  213. self.statusLayout.addWidget(self.check_status_button)
  214. self.subControlLayout.addWidget(self.start_button)
  215. self.subControlLayout.addWidget(self.calibrate_button)
  216. self.subControlLayout.addWidget(self.syncronize_button)
  217. self.subControlLayout.addWidget(self.set_default_button)
  218. # register the led updater function (used in backendinterface.bk_status_readout)
  219. storage.get_board_specific_storage(board_id).update_LED = self.on_check
  220. self.geo = self.saveGeometry()
  221. self.subControlWidget.hide()
  222. def toggle_sub_control(self):
  223. self.subControlWidget.setHidden(not self.subControlWidget.isHidden())
  224. if self.subControlWidget.isHidden():
  225. self.toggleButton.setIcon(QtGui.QIcon(config.install_path+"icons/chevron-bottom.svg"))
  226. else:
  227. self.toggleButton.setIcon(QtGui.QIcon(config.install_path+"icons/chevron-top.svg"))
  228. self.parent().adjustSize()
  229. def all_in_one(self):
  230. """
  231. Function that gets called when the Prepare Board Button is pressed.
  232. It Starts the board, syncs it and sets defaults.
  233. This is accomplished via the backendinterface module
  234. :return: -
  235. """
  236. if bif.bk_start_board(self.board_id) is not False:
  237. def do_the_rest(board_id):
  238. bif.bk_sync_board(board_id)
  239. bif.bk_write_values(board_id, defaults=True)
  240. bif.bk_calibrate(self.board_id, do_the_rest)
  241. def skip_init(self):
  242. board.get_board_config(self.board_id).read_from_board()
  243. board.get_board_status(self.board_id).calibrated = True
  244. board.get_board_status(self.board_id).synced = True
  245. board.get_board_status(self.board_id).defaults_set = True
  246. bif.bk_status_readout()
  247. def on_check(self):
  248. """
  249. This function is the handler for the status leds on the ControlWidget View.
  250. Parses the registers and sets the colors of the leds according.
  251. :return: -
  252. """
  253. try:
  254. status = bif.bk_get_status(self.board_id)
  255. except IndexError:
  256. error(0x002, "Pci returned not enough registers to update LEDs.")
  257. return
  258. for led, st in status.items():
  259. getattr(self, led.lower()+"_led").set_status(st)
  260. class ControlWidget(kcgw.KCGWidgets):
  261. """
  262. Main Widget that is shown at start of gui.
  263. """
  264. def __init__(self):
  265. super(ControlWidget, self).__init__()
  266. self.overlayout = QtGui.QVBoxLayout()
  267. self.setLayout(self.overlayout)
  268. self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
  269. self.overlayout.addWidget(self.splitter)
  270. self.board_control_list = {i: BoardControl(i, not available_boards.multi_board) for i in available_boards}
  271. self.board_widget = QtGui.QWidget()
  272. self.board_widget_layout = QtGui.QVBoxLayout()
  273. self.board_widget.setLayout(self.board_widget_layout)
  274. for bc in self.board_control_list.values():
  275. self.board_widget_layout.addWidget(bc)
  276. self.board_widget_layout.addStretch(1)
  277. if available_boards.multi_board:
  278. self.scroll_widget = QtGui.QScrollArea()
  279. # self.scroll_widget.setMaximumWidth(1.1 * self.board_control_list.values()[0].minimumSizeHint().width())
  280. self.scroll_widget.setWidgetResizable(True)
  281. self.scroll_widget.setWidget(self.board_widget)
  282. self.scroll_widget_container = QtGui.QWidget()
  283. self.scroll_widget_layout = QtGui.QHBoxLayout()
  284. self.scroll_widget_layout.addWidget(self.scroll_widget)
  285. self.scroll_widget_layout.setAlignment(QtCore.Qt.AlignLeft)
  286. self.scroll_widget_container.setLayout(self.scroll_widget_layout)
  287. self.splitter.addWidget(self.scroll_widget_container)
  288. else:
  289. self.splitter.addWidget(self.board_widget)
  290. # self.log_area = QtGui.QTextEdit()
  291. self.log_area = LogArea()
  292. self.log_area.setReadOnly(True)
  293. self.splitter.addWidget(self.log_area)
  294. self.log_area.init_logging()
  295. self.log_area.setKeywords([
  296. "Activating Board",
  297. "Started Board Calibration",
  298. "Synchronize PLLs",
  299. "Setting default Values",
  300. "Updating Values"
  301. ])
  302. # self.setTabOrder(self.soft_reset_button, self.check_status_button)
  303. # self.setTabOrder(self.check_status_button, self.off_button)
  304. # ------------------[ Logging ]----------------------
  305. # log_handler = LogHandler(self.log_area)
  306. # self.logger = logging.getLogger()
  307. # self.logger.addHandler(log_handler)
  308. # self.logger.setLevel(config.log_level)
  309. # logging.logger = self.logger
  310. # logging.logger.addHandler(log_handler)