|
@@ -1,455 +1,455 @@
|
|
|
-"""
|
|
|
-This module defines the Initial view of the gui
|
|
|
-"""
|
|
|
-
|
|
|
-from PyQt4 import QtGui, QtCore
|
|
|
-import logging
|
|
|
-
|
|
|
-from . import kcgwidget as kcgw
|
|
|
-from .kcgwidget import error
|
|
|
-from .backend import board
|
|
|
-from .backend.board import available_boards
|
|
|
-from .groupedelements import Checkboxes, Buttons, Elements
|
|
|
-from . import backendinterface as bif
|
|
|
-from .loghandler import LogArea
|
|
|
-from . import storage
|
|
|
-from .. import config
|
|
|
-
|
|
|
-import traceback
|
|
|
-tr = kcgw.tr
|
|
|
-
|
|
|
-
|
|
|
-# 888 88888888888888888b.
|
|
|
-# 888 888 888 "Y88b
|
|
|
-# 888 888 888 888
|
|
|
-# 888 8888888 888 888
|
|
|
-# 888 888 888 888
|
|
|
-# 888 888 888 888
|
|
|
-# 888 888 888 .d88P
|
|
|
-# 8888888888888888888888888P"
|
|
|
-
|
|
|
-class LED(QtGui.QWidget):
|
|
|
- """
|
|
|
- Produces a graphical LED
|
|
|
- """
|
|
|
- def __init__(self, parent=None, status=1, height=10, width=10):
|
|
|
- """
|
|
|
- Initialize a LED
|
|
|
- :param parent: (QWidget) parent of this widget
|
|
|
- :param status: (int) (0=out, 1=off, 2=orange, 3=on) initial status of this LED
|
|
|
- :param height: (int) height of the LED
|
|
|
- :param width: (int) width of the LED
|
|
|
- :return: -
|
|
|
- """
|
|
|
- QtGui.QWidget.__init__(self, parent)
|
|
|
- colorRGB=(255, 0, 0)
|
|
|
- self.width = width
|
|
|
- self.height = height
|
|
|
- self.color = QtGui.QColor(colorRGB[0], colorRGB[1], colorRGB[2])
|
|
|
- self.center = QtCore.QPoint(width, height)
|
|
|
- self.setMinimumSize(2 * width, 2 * height)
|
|
|
- self.setMaximumSize(2 * width, 2 * height)
|
|
|
- if status == 3:
|
|
|
- self.set_on()
|
|
|
- elif status == 1:
|
|
|
- self.set_off()
|
|
|
- elif status == 0:
|
|
|
- self.set_out()
|
|
|
- elif status == 2:
|
|
|
- self.set_tri()
|
|
|
- self.status = status
|
|
|
-
|
|
|
- def paintEvent(self, event):
|
|
|
- paint = QtGui.QPainter()
|
|
|
- paint.begin(self)
|
|
|
- paint.setRenderHint(QtGui.QPainter.Antialiasing)
|
|
|
-
|
|
|
- # draw a grey 'socket' for the LED
|
|
|
- paint.setPen(QtGui.QColor(160, 160, 160))
|
|
|
- paint.setBrush(QtGui.QColor(180, 180, 180))
|
|
|
- paint.drawEllipse(self.center, self.width, self.height)
|
|
|
-
|
|
|
- # draw the body of the LED
|
|
|
- paint.setBrush(self.color)
|
|
|
- paint.drawEllipse(self.center, self.width*0.85, self.height*0.85)
|
|
|
-
|
|
|
- def set_on(self):
|
|
|
- """
|
|
|
- Set the LED to "on" state
|
|
|
- :return: -
|
|
|
- """
|
|
|
- self.color = QtGui.QColor(0, 255, 0)
|
|
|
- self.update()
|
|
|
- self.status = 3
|
|
|
-
|
|
|
- def set_off(self):
|
|
|
- """
|
|
|
- Set the LED to "off" state
|
|
|
- :return: -
|
|
|
- """
|
|
|
- self.color = QtGui.QColor(255, 0, 0)
|
|
|
- self.update()
|
|
|
- self.status = 1
|
|
|
-
|
|
|
- def set_out(self):
|
|
|
- """
|
|
|
- Set the LED to "OUT" state (that is like an LED without power)
|
|
|
- :return: -
|
|
|
- """
|
|
|
- self.color = QtGui.QColor(150, 150, 150)
|
|
|
- self.update()
|
|
|
- self.status = 0
|
|
|
-
|
|
|
- def set_tri(self):
|
|
|
- """
|
|
|
- Set the LED to "TRI" state (that is led is orange)
|
|
|
- :return: -
|
|
|
- """
|
|
|
- self.color = QtGui.QColor(255, 255, 0)
|
|
|
- self.update()
|
|
|
- self.status = 2
|
|
|
-
|
|
|
- def set_status(self, status):
|
|
|
- """
|
|
|
- Set the status of the led
|
|
|
- :param status: status (in 0, 1, 2, 3)
|
|
|
- """
|
|
|
- if status == 0:
|
|
|
- self.set_out()
|
|
|
- elif status == 1:
|
|
|
- self.set_off()
|
|
|
- elif status == 2:
|
|
|
- self.set_tri()
|
|
|
- elif status == 3:
|
|
|
- self.set_on()
|
|
|
-
|
|
|
-
|
|
|
-# .d8888b. 888 888 888 88888888888888888b.
|
|
|
-# d88P Y88b888 888 888 888 888 "Y88b
|
|
|
-# Y88b. 888 888 888 888 888 888
|
|
|
-# "Y888b. 888888 8888b. 888888888 888.d8888b 888 8888888 888 888
|
|
|
-# "Y88b.888 "88b888 888 88888K 888 888 888 888
|
|
|
-# "888888 .d888888888 888 888"Y8888b.888 888 888 888
|
|
|
-# Y88b d88PY88b. 888 888Y88b. Y88b 888 X88888 888 888 .d88P
|
|
|
-# "Y8888P" "Y888"Y888888 "Y888 "Y88888 88888P'8888888888888888888888888P"
|
|
|
-
|
|
|
-class StatusLED(QtGui.QWidget):
|
|
|
- """
|
|
|
- Create a Status LED with Label next to it
|
|
|
- """
|
|
|
- def __init__(self, text, status=None):
|
|
|
- """
|
|
|
- Initialise StatusLED
|
|
|
- :param text: label text next to the LED
|
|
|
- :param status: initial status of the LED
|
|
|
- :return: -
|
|
|
- """
|
|
|
- super(StatusLED, self).__init__()
|
|
|
- self.layout = QtGui.QHBoxLayout()
|
|
|
- self.label = QtGui.QLabel(text)
|
|
|
- self.led = LED(status=status, width=9, height=9)
|
|
|
- self.layout.addWidget(self.led)
|
|
|
- self.layout.addWidget(self.label)
|
|
|
- self.setLayout(self.layout)
|
|
|
-
|
|
|
- def set_on(self):
|
|
|
- """
|
|
|
- See set_on of LED Class
|
|
|
- """
|
|
|
- self.led.set_on()
|
|
|
-
|
|
|
- def set_off(self):
|
|
|
- """
|
|
|
- See set_off of LED Class
|
|
|
- """
|
|
|
- self.led.set_off()
|
|
|
-
|
|
|
- def set_out(self):
|
|
|
- """
|
|
|
- See set_out of LED Class
|
|
|
- """
|
|
|
- self.led.set_out()
|
|
|
-
|
|
|
- def set_tri(self):
|
|
|
- """
|
|
|
- See set_tri of LED Class
|
|
|
- """
|
|
|
- self.led.set_tri()
|
|
|
-
|
|
|
- def set_status(self, status):
|
|
|
- """
|
|
|
- See set_status of LED Class
|
|
|
- :param status: the status to set the led to
|
|
|
- """
|
|
|
- self.led.set_status(status)
|
|
|
-
|
|
|
-
|
|
|
-# 888888b. 888 .d8888b. 888 888
|
|
|
-# 888 "88b 888d88P Y88b 888 888
|
|
|
-# 888 .88P 888888 888 888 888
|
|
|
-# 8888888K. .d88b. 8888b. 888d888 .d88888888 .d88b. 88888b. 888888888d888 .d88b. 888
|
|
|
-# 888 "Y88bd88""88b "88b888P" d88" 888888 d88""88b888 "88b888 888P" d88""88b888
|
|
|
-# 888 888888 888.d888888888 888 888888 888888 888888 888888 888 888 888888
|
|
|
-# 888 d88PY88..88P888 888888 Y88b 888Y88b d88PY88..88P888 888Y88b. 888 Y88..88P888
|
|
|
-# 8888888P" "Y88P" "Y888888888 "Y88888 "Y8888P" "Y88P" 888 888 "Y888888 "Y88P" 888
|
|
|
-
|
|
|
-class BoardControl(kcgw.KCGWidgets):
|
|
|
- """
|
|
|
- The main view of the gui for each board at startup
|
|
|
- """
|
|
|
- def __init__(self, board_id, single=False):
|
|
|
- super(BoardControl, self).__init__()
|
|
|
- self.board_id = board_id
|
|
|
- self.layout = QtGui.QVBoxLayout()
|
|
|
- self.setLayout(self.layout)
|
|
|
-
|
|
|
- if not single:
|
|
|
- self.header_layout = QtGui.QHBoxLayout()
|
|
|
- left_line = QtGui.QFrame()
|
|
|
- left_line.setFrameShape(QtGui.QFrame.HLine)
|
|
|
- left_line.setFrameShadow(QtGui.QFrame.Sunken)
|
|
|
- right_line = QtGui.QFrame()
|
|
|
- right_line.setFrameShape(QtGui.QFrame.HLine)
|
|
|
- right_line.setFrameShadow(QtGui.QFrame.Sunken)
|
|
|
- self.header_layout.addWidget(left_line)
|
|
|
- header_label = self.createLabel("Board: {}".format(available_boards.get_board_name_from_id(board_id)))
|
|
|
- header_label.setFixedWidth(header_label.sizeHint().width())
|
|
|
- self.header_layout.addWidget(header_label)
|
|
|
- self.header_layout.addWidget(right_line)
|
|
|
-
|
|
|
- self.layout.addLayout(self.header_layout)
|
|
|
-
|
|
|
- self.mainControlLayout = QtGui.QHBoxLayout()
|
|
|
- self.subControlLayout = QtGui.QGridLayout()#QtGui.QHBoxLayout()
|
|
|
- self.subControlWidget = QtGui.QWidget()
|
|
|
- self.subControlWidget.setLayout(self.subControlLayout)
|
|
|
- self.statusLayout = QtGui.QHBoxLayout()
|
|
|
- self.layout.addLayout(self.mainControlLayout)
|
|
|
- self.layout.addWidget(self.subControlWidget)
|
|
|
- self.layout.addLayout(self.statusLayout)
|
|
|
-
|
|
|
- # ----------[ LED Status ]---------------
|
|
|
- self.pipeline_led = StatusLED(tr("Label", "DataFlow Pipeline"))
|
|
|
- self.master_control_led = StatusLED(tr("Label", "Master Control"))
|
|
|
- #self.data_check_led = StatusLED(tr("Label", "Data Check"))
|
|
|
- #self.pll_ld_led = StatusLED(tr("Label", "PLL_LD"))
|
|
|
- self.statusLayout.addWidget(self.pipeline_led)
|
|
|
- self.statusLayout.addWidget(self.master_control_led)
|
|
|
- #self.statusLayout.addWidget(self.data_check_led)
|
|
|
- #self.statusLayout.addWidget(self.pll_ld_led)
|
|
|
-
|
|
|
- # -----------[ Buttons ]--------------
|
|
|
- from functools import partial
|
|
|
- conf = board.get_board_config(board_id)
|
|
|
- if conf.get('board_version') > 10:
|
|
|
- logging.critical('Board Offline - GUI not working! - restart with active board')
|
|
|
- self.mainControlLayout.addWidget(self.createLabel('Board Offline - GUI not working! - restart with active board'))
|
|
|
- else:
|
|
|
- self.all_in_one_button = self.createButton(text=tr("Button", "Prepare Board"), connect=self.all_in_one,
|
|
|
- tooltip=tr("Tooltip", "Start, Calibrate, Synchronize and set Defaults\nCtrl+A"))
|
|
|
-
|
|
|
- self.toggleButton = self.createButton(text="", connect=self.toggle_sub_control)
|
|
|
- self.toggleButton.setIcon(QtGui.QIcon(config.icon_path("chevron-bottom.svg")))
|
|
|
- self.toggleButton.setFixedWidth(50)
|
|
|
- # self.all_in_one_button.setShortcut("Ctrl+A")
|
|
|
- # self.all_in_one_button.setObjectName("all_in_one")
|
|
|
-
|
|
|
-
|
|
|
- self.skip_init_button = self.createButton(text=tr("Button", "Skip Initialisation"), connect=self.skip_init,
|
|
|
- tooltip=tr("Tooltip", "Skip Initialisation and read values from board.\n"
|
|
|
- "NOTE: ONLY DO THIS IF BOARD WAS CALIBRATED AND SYNCHRONIZED BEFORE"))
|
|
|
-
|
|
|
- self.set_default_button = self.createButton(text=tr("Button", "Set Defaults"), connect=lambda x: bif.bk_write_values(board_id=board_id, defaults=True))
|
|
|
- self.soft_reset_button = self.createButton(text=tr("Button", "Soft Reset"), connect=lambda x: bif.bk_soft_reset(board_id=board_id))
|
|
|
- #self.off_button = self.createButton(text=tr("Button", "Board Off"), connect=lambda x: bif.bk_stop_board(board_id=board_id))
|
|
|
- #self.off_button.setObjectName("off")
|
|
|
- self.check_status_button = self.createButton(text=tr("Button", "Check Status"), connect=lambda x: bif._bif_status_readout(board_id=board_id))
|
|
|
-
|
|
|
-
|
|
|
- seqlist = conf.get_sequence_list()
|
|
|
- columnctr=0
|
|
|
- linectr = 0
|
|
|
- seqcolum = -1
|
|
|
- try:
|
|
|
- for item in seqlist:
|
|
|
- buttontemp = self.createButton(text=tr("Button", conf.get_sequence_comment(item)), connect=partial(bif.bk_run_sequence, board_id=board_id, name=item))
|
|
|
- Buttons.addButton(item, buttontemp)
|
|
|
- Elements.addItem('no_board_{}'.format(board_id),[buttontemp])
|
|
|
- #self.subControlLayout.addWidget(buttontemp)
|
|
|
- if 'PLL_sequence' in item:
|
|
|
- if seqcolum == -1:
|
|
|
- seqcolum = columnctr
|
|
|
- columnctr += 1
|
|
|
- self.subControlLayout.addWidget(buttontemp, linectr, seqcolum)
|
|
|
- linectr += 1
|
|
|
-
|
|
|
- else:
|
|
|
- self.subControlLayout.addWidget(buttontemp, 0,columnctr)
|
|
|
- columnctr += 1
|
|
|
-
|
|
|
-
|
|
|
- self.subControlLayout.addWidget(self.set_default_button, 0, columnctr)
|
|
|
- except Exception as e:
|
|
|
- traceback.print_exc()
|
|
|
-
|
|
|
- Buttons.addButton(['set_defaults_{}'.format(board_id), 'after_start_{}'.format(board_id)], self.set_default_button)
|
|
|
- Elements.addItem('no_board_{}'.format(board_id),
|
|
|
- [
|
|
|
- self.set_default_button,
|
|
|
- self.soft_reset_button,
|
|
|
- #self.off_button,
|
|
|
- self.all_in_one_button
|
|
|
- ])
|
|
|
-
|
|
|
- self.mainControlLayout.addWidget(self.all_in_one_button)
|
|
|
- self.mainControlLayout.addWidget(self.toggleButton)
|
|
|
- self.mainControlLayout.addWidget(self.skip_init_button)
|
|
|
-
|
|
|
- self.mainControlLayout.addWidget(self.soft_reset_button)
|
|
|
- #self.mainControlLayout.addWidget(self.off_button)
|
|
|
-
|
|
|
- self.statusLayout.addWidget(self.check_status_button)
|
|
|
-
|
|
|
-
|
|
|
- # register the led updater function (used in backendinterface.bk_status_readout)
|
|
|
- storage.get_board_specific_storage(board_id).update_LED = self.on_check
|
|
|
- self.geo = self.saveGeometry()
|
|
|
- self.subControlWidget.hide()
|
|
|
-
|
|
|
- def toggle_sub_control(self):
|
|
|
- """
|
|
|
- Show or hide the subcontrol buttons
|
|
|
- """
|
|
|
- self.subControlWidget.setHidden(not self.subControlWidget.isHidden())
|
|
|
- if self.subControlWidget.isHidden():
|
|
|
- self.toggleButton.setIcon(QtGui.QIcon(config.icon_path("chevron-bottom.svg")))
|
|
|
- else:
|
|
|
- self.toggleButton.setIcon(QtGui.QIcon(config.icon_path("chevron-top.svg")))
|
|
|
- self.parent().adjustSize()
|
|
|
-
|
|
|
- def all_in_one(self):
|
|
|
- """
|
|
|
- Function that gets called when the Prepare Board Button is pressed.
|
|
|
- It Starts the board, syncs it and sets defaults.
|
|
|
- This is accomplished via the Sequences module
|
|
|
- :return: -
|
|
|
- """
|
|
|
- seq = board.get_board_config(self.board_id).get_init_order()
|
|
|
- for item in seq:
|
|
|
- if item == 'startup_sequence':
|
|
|
- if board.is_active(board_id):
|
|
|
- logging.info('Board already powered on - skip startup_sequence')
|
|
|
- continue
|
|
|
-
|
|
|
- bif.bk_run_sequence(self.board_id, item)
|
|
|
-
|
|
|
- popup = kcgw.PopupDialog("Do not forget to turn on the T/H switches!",
|
|
|
- title='Reminder', okonly=True)
|
|
|
- popup.exec_()
|
|
|
- popup.deleteLater()
|
|
|
- popup.get_return_value()
|
|
|
- board.get_board_config(self.board_id).set_startup()
|
|
|
-
|
|
|
- def skip_init(self):
|
|
|
- """
|
|
|
- Skip board initialisation progress and read data from board. This will adjust the values in the gui to those
|
|
|
- on the board (for every value that is stored on the board)
|
|
|
- """
|
|
|
- board.get_board_config(self.board_id).read_from_board()
|
|
|
- board.get_board_status(self.board_id).calibrated = True
|
|
|
- board.get_board_status(self.board_id).synced = True
|
|
|
- board.get_board_status(self.board_id).defaults_set = True
|
|
|
- bif.bk_status_readout()
|
|
|
- logging.info("Initialisation skipped, configuration and status was read from KAPTURE.")
|
|
|
-
|
|
|
- def on_check(self):
|
|
|
- """
|
|
|
- This function is the handler for the status leds on the ControlWidget View.
|
|
|
- Parses the registers and sets the colors of the leds according.
|
|
|
- :return: -
|
|
|
- """
|
|
|
- try:
|
|
|
- status = bif.bk_get_status(self.board_id)
|
|
|
- except IndexError:
|
|
|
- error(0x002, "Pci returned not enough registers to update LEDs.")
|
|
|
- return
|
|
|
-
|
|
|
- for led, st in list(status.items()):
|
|
|
- try:
|
|
|
- getattr(self, led.lower()+"_led").set_status(st)
|
|
|
- except:
|
|
|
- pass
|
|
|
-
|
|
|
-
|
|
|
-# .d8888b. 888 888888 888d8b 888 888
|
|
|
-# d88P Y88b 888 888888 o 888Y8P 888 888
|
|
|
-# 888 888 888 888888 d8b 888 888 888
|
|
|
-# 888 .d88b. 88888b. 888888888d888 .d88b. 888888 d888b 888888 .d88888 .d88b. .d88b. 888888
|
|
|
-# 888 d88""88b888 "88b888 888P" d88""88b888888d88888b888888d88" 888d88P"88bd8P Y8b888
|
|
|
-# 888 888888 888888 888888 888 888 88888888888P Y88888888888 888888 88888888888888
|
|
|
-# Y88b d88PY88..88P888 888Y88b. 888 Y88..88P8888888P Y8888888Y88b 888Y88b 888Y8b. Y88b.
|
|
|
-# "Y8888P" "Y88P" 888 888 "Y888888 "Y88P" 888888P Y888888 "Y88888 "Y88888 "Y8888 "Y888
|
|
|
-# 888
|
|
|
-# Y8b d88P
|
|
|
-# "Y88P"
|
|
|
-
|
|
|
-class ControlWidget(kcgw.KCGWidgets):
|
|
|
- """
|
|
|
- Main Widget that is shown at start of gui.
|
|
|
- """
|
|
|
- def __init__(self):
|
|
|
- super(ControlWidget, self).__init__()
|
|
|
-
|
|
|
- self.overlayout = QtGui.QVBoxLayout()
|
|
|
- self.setLayout(self.overlayout)
|
|
|
-
|
|
|
- self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
|
|
|
- self.overlayout.addWidget(self.splitter)
|
|
|
-
|
|
|
- self.log_area = LogArea()
|
|
|
- self.log_area.setReadOnly(True)
|
|
|
- self.log_area.init_logging()
|
|
|
- self.log_area.setKeywords([
|
|
|
- "Activating Board",
|
|
|
- "Started Board Calibration",
|
|
|
- "Synchronize PLLs",
|
|
|
- "Setting default Values",
|
|
|
- "Updating Values"
|
|
|
- ])
|
|
|
-
|
|
|
- self.board_control_list = {i: BoardControl(i, not available_boards.multi_board) for i in available_boards}
|
|
|
- self.board_widget = QtGui.QWidget()
|
|
|
- self.board_widget_layout = QtGui.QVBoxLayout()
|
|
|
- self.board_widget.setLayout(self.board_widget_layout)
|
|
|
- for bc in list(self.board_control_list.values()):
|
|
|
- self.board_widget_layout.addWidget(bc)
|
|
|
- self.board_widget_layout.addStretch(1)
|
|
|
-
|
|
|
- if available_boards.multi_board:
|
|
|
- self.scroll_widget = QtGui.QScrollArea()
|
|
|
- # self.scroll_widget.setMaximumWidth(1.1 * self.board_control_list.values()[0].minimumSizeHint().width())
|
|
|
- self.scroll_widget.setWidgetResizable(True)
|
|
|
- self.scroll_widget.setWidget(self.board_widget)
|
|
|
- self.scroll_widget_container = QtGui.QWidget()
|
|
|
- self.scroll_widget_layout = QtGui.QHBoxLayout()
|
|
|
- self.scroll_widget_layout.addWidget(self.scroll_widget)
|
|
|
- self.scroll_widget_layout.setAlignment(QtCore.Qt.AlignLeft)
|
|
|
- self.scroll_widget_container.setLayout(self.scroll_widget_layout)
|
|
|
- self.splitter.addWidget(self.scroll_widget_container)
|
|
|
- else:
|
|
|
- self.splitter.addWidget(self.board_widget)
|
|
|
-
|
|
|
- # self.log_area = QtGui.QTextEdit()
|
|
|
-
|
|
|
- self.splitter.addWidget(self.log_area)
|
|
|
-
|
|
|
- # self.setTabOrder(self.soft_reset_button, self.check_status_button)
|
|
|
- # self.setTabOrder(self.check_status_button, self.off_button)
|
|
|
-
|
|
|
- # ------------------[ Logging ]----------------------
|
|
|
- # log_handler = LogHandler(self.log_area)
|
|
|
- # self.logger = logging.getLogger()
|
|
|
- # self.logger.addHandler(log_handler)
|
|
|
- # self.logger.setLevel(config.log_level)
|
|
|
- # logging.logger = self.logger
|
|
|
- # logging.logger.addHandler(log_handler)
|
|
|
+"""
|
|
|
+This module defines the Initial view of the gui
|
|
|
+"""
|
|
|
+
|
|
|
+from PyQt4 import QtGui, QtCore
|
|
|
+import logging
|
|
|
+
|
|
|
+from . import kcgwidget as kcgw
|
|
|
+from .kcgwidget import error
|
|
|
+from .backend import board
|
|
|
+from .backend.board import available_boards
|
|
|
+from .groupedelements import Checkboxes, Buttons, Elements
|
|
|
+from . import backendinterface as bif
|
|
|
+from .loghandler import LogArea
|
|
|
+from . import storage
|
|
|
+from .. import config
|
|
|
+
|
|
|
+import traceback
|
|
|
+tr = kcgw.tr
|
|
|
+
|
|
|
+
|
|
|
+# 888 88888888888888888b.
|
|
|
+# 888 888 888 "Y88b
|
|
|
+# 888 888 888 888
|
|
|
+# 888 8888888 888 888
|
|
|
+# 888 888 888 888
|
|
|
+# 888 888 888 888
|
|
|
+# 888 888 888 .d88P
|
|
|
+# 8888888888888888888888888P"
|
|
|
+
|
|
|
+class LED(QtGui.QWidget):
|
|
|
+ """
|
|
|
+ Produces a graphical LED
|
|
|
+ """
|
|
|
+ def __init__(self, parent=None, status=1, height=10, width=10):
|
|
|
+ """
|
|
|
+ Initialize a LED
|
|
|
+ :param parent: (QWidget) parent of this widget
|
|
|
+ :param status: (int) (0=out, 1=off, 2=orange, 3=on) initial status of this LED
|
|
|
+ :param height: (int) height of the LED
|
|
|
+ :param width: (int) width of the LED
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ QtGui.QWidget.__init__(self, parent)
|
|
|
+ colorRGB=(255, 0, 0)
|
|
|
+ self.width = width
|
|
|
+ self.height = height
|
|
|
+ self.color = QtGui.QColor(colorRGB[0], colorRGB[1], colorRGB[2])
|
|
|
+ self.center = QtCore.QPoint(width, height)
|
|
|
+ self.setMinimumSize(2 * width, 2 * height)
|
|
|
+ self.setMaximumSize(2 * width, 2 * height)
|
|
|
+ if status == 3:
|
|
|
+ self.set_on()
|
|
|
+ elif status == 1:
|
|
|
+ self.set_off()
|
|
|
+ elif status == 0:
|
|
|
+ self.set_out()
|
|
|
+ elif status == 2:
|
|
|
+ self.set_tri()
|
|
|
+ self.status = status
|
|
|
+
|
|
|
+ def paintEvent(self, event):
|
|
|
+ paint = QtGui.QPainter()
|
|
|
+ paint.begin(self)
|
|
|
+ paint.setRenderHint(QtGui.QPainter.Antialiasing)
|
|
|
+
|
|
|
+ # draw a grey 'socket' for the LED
|
|
|
+ paint.setPen(QtGui.QColor(160, 160, 160))
|
|
|
+ paint.setBrush(QtGui.QColor(180, 180, 180))
|
|
|
+ paint.drawEllipse(self.center, self.width, self.height)
|
|
|
+
|
|
|
+ # draw the body of the LED
|
|
|
+ paint.setBrush(self.color)
|
|
|
+ paint.drawEllipse(self.center, self.width*0.85, self.height*0.85)
|
|
|
+
|
|
|
+ def set_on(self):
|
|
|
+ """
|
|
|
+ Set the LED to "on" state
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ self.color = QtGui.QColor(0, 255, 0)
|
|
|
+ self.update()
|
|
|
+ self.status = 3
|
|
|
+
|
|
|
+ def set_off(self):
|
|
|
+ """
|
|
|
+ Set the LED to "off" state
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ self.color = QtGui.QColor(255, 0, 0)
|
|
|
+ self.update()
|
|
|
+ self.status = 1
|
|
|
+
|
|
|
+ def set_out(self):
|
|
|
+ """
|
|
|
+ Set the LED to "OUT" state (that is like an LED without power)
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ self.color = QtGui.QColor(150, 150, 150)
|
|
|
+ self.update()
|
|
|
+ self.status = 0
|
|
|
+
|
|
|
+ def set_tri(self):
|
|
|
+ """
|
|
|
+ Set the LED to "TRI" state (that is led is orange)
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ self.color = QtGui.QColor(255, 255, 0)
|
|
|
+ self.update()
|
|
|
+ self.status = 2
|
|
|
+
|
|
|
+ def set_status(self, status):
|
|
|
+ """
|
|
|
+ Set the status of the led
|
|
|
+ :param status: status (in 0, 1, 2, 3)
|
|
|
+ """
|
|
|
+ if status == 0:
|
|
|
+ self.set_out()
|
|
|
+ elif status == 1:
|
|
|
+ self.set_off()
|
|
|
+ elif status == 2:
|
|
|
+ self.set_tri()
|
|
|
+ elif status == 3:
|
|
|
+ self.set_on()
|
|
|
+
|
|
|
+
|
|
|
+# .d8888b. 888 888 888 88888888888888888b.
|
|
|
+# d88P Y88b888 888 888 888 888 "Y88b
|
|
|
+# Y88b. 888 888 888 888 888 888
|
|
|
+# "Y888b. 888888 8888b. 888888888 888.d8888b 888 8888888 888 888
|
|
|
+# "Y88b.888 "88b888 888 88888K 888 888 888 888
|
|
|
+# "888888 .d888888888 888 888"Y8888b.888 888 888 888
|
|
|
+# Y88b d88PY88b. 888 888Y88b. Y88b 888 X88888 888 888 .d88P
|
|
|
+# "Y8888P" "Y888"Y888888 "Y888 "Y88888 88888P'8888888888888888888888888P"
|
|
|
+
|
|
|
+class StatusLED(QtGui.QWidget):
|
|
|
+ """
|
|
|
+ Create a Status LED with Label next to it
|
|
|
+ """
|
|
|
+ def __init__(self, text, status=None):
|
|
|
+ """
|
|
|
+ Initialise StatusLED
|
|
|
+ :param text: label text next to the LED
|
|
|
+ :param status: initial status of the LED
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ super(StatusLED, self).__init__()
|
|
|
+ self.layout = QtGui.QHBoxLayout()
|
|
|
+ self.label = QtGui.QLabel(text)
|
|
|
+ self.led = LED(status=status, width=9, height=9)
|
|
|
+ self.layout.addWidget(self.led)
|
|
|
+ self.layout.addWidget(self.label)
|
|
|
+ self.setLayout(self.layout)
|
|
|
+
|
|
|
+ def set_on(self):
|
|
|
+ """
|
|
|
+ See set_on of LED Class
|
|
|
+ """
|
|
|
+ self.led.set_on()
|
|
|
+
|
|
|
+ def set_off(self):
|
|
|
+ """
|
|
|
+ See set_off of LED Class
|
|
|
+ """
|
|
|
+ self.led.set_off()
|
|
|
+
|
|
|
+ def set_out(self):
|
|
|
+ """
|
|
|
+ See set_out of LED Class
|
|
|
+ """
|
|
|
+ self.led.set_out()
|
|
|
+
|
|
|
+ def set_tri(self):
|
|
|
+ """
|
|
|
+ See set_tri of LED Class
|
|
|
+ """
|
|
|
+ self.led.set_tri()
|
|
|
+
|
|
|
+ def set_status(self, status):
|
|
|
+ """
|
|
|
+ See set_status of LED Class
|
|
|
+ :param status: the status to set the led to
|
|
|
+ """
|
|
|
+ self.led.set_status(status)
|
|
|
+
|
|
|
+
|
|
|
+# 888888b. 888 .d8888b. 888 888
|
|
|
+# 888 "88b 888d88P Y88b 888 888
|
|
|
+# 888 .88P 888888 888 888 888
|
|
|
+# 8888888K. .d88b. 8888b. 888d888 .d88888888 .d88b. 88888b. 888888888d888 .d88b. 888
|
|
|
+# 888 "Y88bd88""88b "88b888P" d88" 888888 d88""88b888 "88b888 888P" d88""88b888
|
|
|
+# 888 888888 888.d888888888 888 888888 888888 888888 888888 888 888 888888
|
|
|
+# 888 d88PY88..88P888 888888 Y88b 888Y88b d88PY88..88P888 888Y88b. 888 Y88..88P888
|
|
|
+# 8888888P" "Y88P" "Y888888888 "Y88888 "Y8888P" "Y88P" 888 888 "Y888888 "Y88P" 888
|
|
|
+
|
|
|
+class BoardControl(kcgw.KCGWidgets):
|
|
|
+ """
|
|
|
+ The main view of the gui for each board at startup
|
|
|
+ """
|
|
|
+ def __init__(self, board_id, single=False):
|
|
|
+ super(BoardControl, self).__init__()
|
|
|
+ self.board_id = board_id
|
|
|
+ self.layout = QtGui.QVBoxLayout()
|
|
|
+ self.setLayout(self.layout)
|
|
|
+
|
|
|
+ if not single:
|
|
|
+ self.header_layout = QtGui.QHBoxLayout()
|
|
|
+ left_line = QtGui.QFrame()
|
|
|
+ left_line.setFrameShape(QtGui.QFrame.HLine)
|
|
|
+ left_line.setFrameShadow(QtGui.QFrame.Sunken)
|
|
|
+ right_line = QtGui.QFrame()
|
|
|
+ right_line.setFrameShape(QtGui.QFrame.HLine)
|
|
|
+ right_line.setFrameShadow(QtGui.QFrame.Sunken)
|
|
|
+ self.header_layout.addWidget(left_line)
|
|
|
+ header_label = self.createLabel("Board: {}".format(available_boards.get_board_name_from_id(board_id)))
|
|
|
+ header_label.setFixedWidth(header_label.sizeHint().width())
|
|
|
+ self.header_layout.addWidget(header_label)
|
|
|
+ self.header_layout.addWidget(right_line)
|
|
|
+
|
|
|
+ self.layout.addLayout(self.header_layout)
|
|
|
+
|
|
|
+ self.mainControlLayout = QtGui.QHBoxLayout()
|
|
|
+ self.subControlLayout = QtGui.QGridLayout()#QtGui.QHBoxLayout()
|
|
|
+ self.subControlWidget = QtGui.QWidget()
|
|
|
+ self.subControlWidget.setLayout(self.subControlLayout)
|
|
|
+ self.statusLayout = QtGui.QHBoxLayout()
|
|
|
+ self.layout.addLayout(self.mainControlLayout)
|
|
|
+ self.layout.addWidget(self.subControlWidget)
|
|
|
+ self.layout.addLayout(self.statusLayout)
|
|
|
+
|
|
|
+ # ----------[ LED Status ]---------------
|
|
|
+ self.pipeline_led = StatusLED(tr("Label", "DataFlow Pipeline"))
|
|
|
+ self.master_control_led = StatusLED(tr("Label", "Master Control"))
|
|
|
+ #self.data_check_led = StatusLED(tr("Label", "Data Check"))
|
|
|
+ self.pll_ld_led = StatusLED(tr("Label", "PLL Lock"))
|
|
|
+ self.statusLayout.addWidget(self.pipeline_led)
|
|
|
+ self.statusLayout.addWidget(self.master_control_led)
|
|
|
+ #self.statusLayout.addWidget(self.data_check_led)
|
|
|
+ self.statusLayout.addWidget(self.pll_ld_led)
|
|
|
+
|
|
|
+ # -----------[ Buttons ]--------------
|
|
|
+ from functools import partial
|
|
|
+ conf = board.get_board_config(board_id)
|
|
|
+ if conf.get('board_version') > 10:
|
|
|
+ logging.critical('Board Offline - GUI not working! - restart with active board')
|
|
|
+ self.mainControlLayout.addWidget(self.createLabel('Board Offline - GUI not working! - restart with active board'))
|
|
|
+ else:
|
|
|
+ self.all_in_one_button = self.createButton(text=tr("Button", "Prepare Board"), connect=self.all_in_one,
|
|
|
+ tooltip=tr("Tooltip", "Start, Calibrate, Synchronize and set Defaults\nCtrl+A"))
|
|
|
+
|
|
|
+ self.toggleButton = self.createButton(text="", connect=self.toggle_sub_control)
|
|
|
+ self.toggleButton.setIcon(QtGui.QIcon(config.icon_path("chevron-bottom.svg")))
|
|
|
+ self.toggleButton.setFixedWidth(50)
|
|
|
+ # self.all_in_one_button.setShortcut("Ctrl+A")
|
|
|
+ # self.all_in_one_button.setObjectName("all_in_one")
|
|
|
+
|
|
|
+
|
|
|
+ self.skip_init_button = self.createButton(text=tr("Button", "Skip Initialisation"), connect=self.skip_init,
|
|
|
+ tooltip=tr("Tooltip", "Skip Initialisation and read values from board.\n"
|
|
|
+ "NOTE: ONLY DO THIS IF BOARD WAS CALIBRATED AND SYNCHRONIZED BEFORE"))
|
|
|
+
|
|
|
+ self.set_default_button = self.createButton(text=tr("Button", "Set Defaults"), connect=lambda x: bif.bk_write_values(board_id=board_id, defaults=True))
|
|
|
+ self.soft_reset_button = self.createButton(text=tr("Button", "Soft Reset"), connect=lambda x: bif.bk_soft_reset(board_id=board_id))
|
|
|
+ #self.off_button = self.createButton(text=tr("Button", "Board Off"), connect=lambda x: bif.bk_stop_board(board_id=board_id))
|
|
|
+ #self.off_button.setObjectName("off")
|
|
|
+ self.check_status_button = self.createButton(text=tr("Button", "Check Status"), connect=lambda x: bif._bif_status_readout(board_id=board_id))
|
|
|
+
|
|
|
+
|
|
|
+ seqlist = conf.get_sequence_list()
|
|
|
+ columnctr=0
|
|
|
+ linectr = 0
|
|
|
+ seqcolum = -1
|
|
|
+ try:
|
|
|
+ for item in seqlist:
|
|
|
+ buttontemp = self.createButton(text=tr("Button", conf.get_sequence_comment(item)), connect=partial(bif.bk_run_sequence, board_id=board_id, name=item))
|
|
|
+ Buttons.addButton(item, buttontemp)
|
|
|
+ Elements.addItem('no_board_{}'.format(board_id),[buttontemp])
|
|
|
+ #self.subControlLayout.addWidget(buttontemp)
|
|
|
+ if 'PLL_sequence' in item:
|
|
|
+ if seqcolum == -1:
|
|
|
+ seqcolum = columnctr
|
|
|
+ columnctr += 1
|
|
|
+ self.subControlLayout.addWidget(buttontemp, linectr, seqcolum)
|
|
|
+ linectr += 1
|
|
|
+
|
|
|
+ else:
|
|
|
+ self.subControlLayout.addWidget(buttontemp, 0,columnctr)
|
|
|
+ columnctr += 1
|
|
|
+
|
|
|
+
|
|
|
+ self.subControlLayout.addWidget(self.set_default_button, 0, columnctr)
|
|
|
+ except Exception as e:
|
|
|
+ traceback.print_exc()
|
|
|
+
|
|
|
+ Buttons.addButton(['set_defaults_{}'.format(board_id), 'after_start_{}'.format(board_id)], self.set_default_button)
|
|
|
+ Elements.addItem('no_board_{}'.format(board_id),
|
|
|
+ [
|
|
|
+ self.set_default_button,
|
|
|
+ self.soft_reset_button,
|
|
|
+ #self.off_button,
|
|
|
+ self.all_in_one_button
|
|
|
+ ])
|
|
|
+
|
|
|
+ self.mainControlLayout.addWidget(self.all_in_one_button)
|
|
|
+ self.mainControlLayout.addWidget(self.toggleButton)
|
|
|
+ self.mainControlLayout.addWidget(self.skip_init_button)
|
|
|
+
|
|
|
+ self.mainControlLayout.addWidget(self.soft_reset_button)
|
|
|
+ #self.mainControlLayout.addWidget(self.off_button)
|
|
|
+
|
|
|
+ self.statusLayout.addWidget(self.check_status_button)
|
|
|
+
|
|
|
+
|
|
|
+ # register the led updater function (used in backendinterface.bk_status_readout)
|
|
|
+ storage.get_board_specific_storage(board_id).update_LED = self.on_check
|
|
|
+ self.geo = self.saveGeometry()
|
|
|
+ self.subControlWidget.hide()
|
|
|
+
|
|
|
+ def toggle_sub_control(self):
|
|
|
+ """
|
|
|
+ Show or hide the subcontrol buttons
|
|
|
+ """
|
|
|
+ self.subControlWidget.setHidden(not self.subControlWidget.isHidden())
|
|
|
+ if self.subControlWidget.isHidden():
|
|
|
+ self.toggleButton.setIcon(QtGui.QIcon(config.icon_path("chevron-bottom.svg")))
|
|
|
+ else:
|
|
|
+ self.toggleButton.setIcon(QtGui.QIcon(config.icon_path("chevron-top.svg")))
|
|
|
+ self.parent().adjustSize()
|
|
|
+
|
|
|
+ def all_in_one(self):
|
|
|
+ """
|
|
|
+ Function that gets called when the Prepare Board Button is pressed.
|
|
|
+ It Starts the board, syncs it and sets defaults.
|
|
|
+ This is accomplished via the Sequences module
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ seq = board.get_board_config(self.board_id).get_init_order()
|
|
|
+ for item in seq:
|
|
|
+ if item == 'startup_sequence':
|
|
|
+ if board.is_active(board_id):
|
|
|
+ logging.info('Board already powered on - skip startup_sequence')
|
|
|
+ continue
|
|
|
+
|
|
|
+ bif.bk_run_sequence(self.board_id, item)
|
|
|
+
|
|
|
+ popup = kcgw.PopupDialog("Do not forget to turn on the T/H switches!",
|
|
|
+ title='Reminder', okonly=True)
|
|
|
+ popup.exec_()
|
|
|
+ popup.deleteLater()
|
|
|
+ popup.get_return_value()
|
|
|
+ board.get_board_config(self.board_id).set_startup()
|
|
|
+
|
|
|
+ def skip_init(self):
|
|
|
+ """
|
|
|
+ Skip board initialisation progress and read data from board. This will adjust the values in the gui to those
|
|
|
+ on the board (for every value that is stored on the board)
|
|
|
+ """
|
|
|
+ board.get_board_config(self.board_id).read_from_board()
|
|
|
+ board.get_board_status(self.board_id).calibrated = True
|
|
|
+ board.get_board_status(self.board_id).synced = True
|
|
|
+ board.get_board_status(self.board_id).defaults_set = True
|
|
|
+ bif.bk_status_readout()
|
|
|
+ logging.info("Initialisation skipped, configuration and status was read from KAPTURE.")
|
|
|
+
|
|
|
+ def on_check(self):
|
|
|
+ """
|
|
|
+ This function is the handler for the status leds on the ControlWidget View.
|
|
|
+ Parses the registers and sets the colors of the leds according.
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ status = bif.bk_get_status(self.board_id)
|
|
|
+ except IndexError:
|
|
|
+ error(0x002, "Pci returned not enough registers to update LEDs.")
|
|
|
+ return
|
|
|
+
|
|
|
+ for led, st in list(status.items()):
|
|
|
+ try:
|
|
|
+ getattr(self, led.lower()+"_led").set_status(st)
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+# .d8888b. 888 888888 888d8b 888 888
|
|
|
+# d88P Y88b 888 888888 o 888Y8P 888 888
|
|
|
+# 888 888 888 888888 d8b 888 888 888
|
|
|
+# 888 .d88b. 88888b. 888888888d888 .d88b. 888888 d888b 888888 .d88888 .d88b. .d88b. 888888
|
|
|
+# 888 d88""88b888 "88b888 888P" d88""88b888888d88888b888888d88" 888d88P"88bd8P Y8b888
|
|
|
+# 888 888888 888888 888888 888 888 88888888888P Y88888888888 888888 88888888888888
|
|
|
+# Y88b d88PY88..88P888 888Y88b. 888 Y88..88P8888888P Y8888888Y88b 888Y88b 888Y8b. Y88b.
|
|
|
+# "Y8888P" "Y88P" 888 888 "Y888888 "Y88P" 888888P Y888888 "Y88888 "Y88888 "Y8888 "Y888
|
|
|
+# 888
|
|
|
+# Y8b d88P
|
|
|
+# "Y88P"
|
|
|
+
|
|
|
+class ControlWidget(kcgw.KCGWidgets):
|
|
|
+ """
|
|
|
+ Main Widget that is shown at start of gui.
|
|
|
+ """
|
|
|
+ def __init__(self):
|
|
|
+ super(ControlWidget, self).__init__()
|
|
|
+
|
|
|
+ self.overlayout = QtGui.QVBoxLayout()
|
|
|
+ self.setLayout(self.overlayout)
|
|
|
+
|
|
|
+ self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
|
|
|
+ self.overlayout.addWidget(self.splitter)
|
|
|
+
|
|
|
+ self.log_area = LogArea()
|
|
|
+ self.log_area.setReadOnly(True)
|
|
|
+ self.log_area.init_logging()
|
|
|
+ self.log_area.setKeywords([
|
|
|
+ "Activating Board",
|
|
|
+ "Started Board Calibration",
|
|
|
+ "Synchronize PLLs",
|
|
|
+ "Setting default Values",
|
|
|
+ "Updating Values"
|
|
|
+ ])
|
|
|
+
|
|
|
+ self.board_control_list = {i: BoardControl(i, not available_boards.multi_board) for i in available_boards}
|
|
|
+ self.board_widget = QtGui.QWidget()
|
|
|
+ self.board_widget_layout = QtGui.QVBoxLayout()
|
|
|
+ self.board_widget.setLayout(self.board_widget_layout)
|
|
|
+ for bc in list(self.board_control_list.values()):
|
|
|
+ self.board_widget_layout.addWidget(bc)
|
|
|
+ self.board_widget_layout.addStretch(1)
|
|
|
+
|
|
|
+ if available_boards.multi_board:
|
|
|
+ self.scroll_widget = QtGui.QScrollArea()
|
|
|
+ # self.scroll_widget.setMaximumWidth(1.1 * self.board_control_list.values()[0].minimumSizeHint().width())
|
|
|
+ self.scroll_widget.setWidgetResizable(True)
|
|
|
+ self.scroll_widget.setWidget(self.board_widget)
|
|
|
+ self.scroll_widget_container = QtGui.QWidget()
|
|
|
+ self.scroll_widget_layout = QtGui.QHBoxLayout()
|
|
|
+ self.scroll_widget_layout.addWidget(self.scroll_widget)
|
|
|
+ self.scroll_widget_layout.setAlignment(QtCore.Qt.AlignLeft)
|
|
|
+ self.scroll_widget_container.setLayout(self.scroll_widget_layout)
|
|
|
+ self.splitter.addWidget(self.scroll_widget_container)
|
|
|
+ else:
|
|
|
+ self.splitter.addWidget(self.board_widget)
|
|
|
+
|
|
|
+ # self.log_area = QtGui.QTextEdit()
|
|
|
+
|
|
|
+ self.splitter.addWidget(self.log_area)
|
|
|
+
|
|
|
+ # self.setTabOrder(self.soft_reset_button, self.check_status_button)
|
|
|
+ # self.setTabOrder(self.check_status_button, self.off_button)
|
|
|
+
|
|
|
+ # ------------------[ Logging ]----------------------
|
|
|
+ # log_handler = LogHandler(self.log_area)
|
|
|
+ # self.logger = logging.getLogger()
|
|
|
+ # self.logger.addHandler(log_handler)
|
|
|
+ # self.logger.setLevel(config.log_level)
|
|
|
+ # logging.logger = self.logger
|
|
|
+ # logging.logger.addHandler(log_handler)
|