Exemple #1
1
 def build_connection_group (self):
     
     self.connect_group = QGroupBox(parent =  self.main_widget)
     self.connect_group.setTitle('Connection')
     self.connect_group.setStyleSheet("QGroupBox { border: 1px solid gray; border-radius: 3px;  margin-top: 0.5em; } QGroupBox::title {  subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;}")
     
     self.connect_label = QLabel("IP Address")
     self.connect_line = QLineEdit("10.0.6.65")
     self.connect_line.setFixedWidth(100)
     
     self.connect_button = QPushButton("Connect")
     self.connect_button.clicked.connect(self.connection_handler)
     
     self.port_label = QLabel("Port")
     self.port_line = QLineEdit("4000")
     self.port_line.setFixedWidth(50)
     self.led_connected = QLed(parent = self.main_widget)
     self.led_connected.turnOff()
     
     self.connect_layout = QHBoxLayout()
     
     self.connect_layout.addWidget(self.connect_label)
     self.connect_layout.addWidget(self.connect_line)
     self.connect_layout.addWidget(self.port_label)
     self.connect_layout.addWidget(self.port_line)
     self.connect_layout.addWidget(self.led_connected)
     self.connect_layout.addWidget(self.connect_button)
     
     self.connect_group.setLayout(self.connect_layout)
Exemple #2
0
class CommandWindow (QMainWindow):
    
    # Constructs a new CommandWindow
    def __init__(self, parent = None):
        
        QMainWindow.__init__(self, parent)
        self.main_widget = QWidget()
        
        # Builds all groups
        self.build_connection_group()        
        self.build_source_windows()
        self.build_buttons_group()
        self.build_commands_group()
        self.build_log_group()
        
        # Initially the client is disconnected. Consequently, no boards
        # are available
        self.sources_group.setVisible(False)
        
        self.main_layout = QGridLayout()
        self.main_layout.setSpacing(10)
        
        # Groups all components in the main widget
        self.main_layout.addWidget(self.connect_group, 0, 0, 1, 3)
        self.main_layout.addWidget(self.commands_group, 1, 0, 1, 5)
        self.main_layout.addWidget(self.sources_group, 2, 0, 1, 5)
        self.main_layout.addWidget(self.log_group, 3, 0, 1, 5)
        
        self.main_widget.setLayout(self.main_layout)
        
        self.statusBar().showMessage("Client started.")
        self.setCentralWidget(self.main_widget)
        self.setWindowTitle('Commands Window')
        self.setFixedSize(QSize(720, 330))
        
        # Constructs the objects responsible to send and receive packets 
        # from PROSAC
        self.requester_controller = Requester(self)
        
        self.is_closed = 0
    
    # Sets a requester in the case it was not instantiated 
    def setRequester(self, r):
        self.requester_controller = r
        self.requester_controller.window_controller = self
    
    # Builds text boxes, labels and buttons required to establish a connection with PROSAC 
    def build_connection_group (self):
        
        self.connect_group = QGroupBox(parent =  self.main_widget)
        self.connect_group.setTitle('Connection')
        self.connect_group.setStyleSheet("QGroupBox { border: 1px solid gray; border-radius: 3px;  margin-top: 0.5em; } QGroupBox::title {  subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;}")
        
        self.connect_label = QLabel("IP Address")
        self.connect_line = QLineEdit("10.0.6.65")
        self.connect_line.setFixedWidth(100)
        
        self.connect_button = QPushButton("Connect")
        self.connect_button.clicked.connect(self.connection_handler)
        
        self.port_label = QLabel("Port")
        self.port_line = QLineEdit("4000")
        self.port_line.setFixedWidth(50)
        self.led_connected = QLed(parent = self.main_widget)
        self.led_connected.turnOff()
        
        self.connect_layout = QHBoxLayout()
        
        self.connect_layout.addWidget(self.connect_label)
        self.connect_layout.addWidget(self.connect_line)
        self.connect_layout.addWidget(self.port_label)
        self.connect_layout.addWidget(self.port_line)
        self.connect_layout.addWidget(self.led_connected)
        self.connect_layout.addWidget(self.connect_button)
        
        self.connect_group.setLayout(self.connect_layout)
    
    # Builds components to show last received and sent messages
    def build_log_group (self): 
        
        self.log_group = QGroupBox(parent =  self.main_widget)
        self.log_group.setTitle('Messages')
        self.log_group.setStyleSheet("QGroupBox { border: 1px solid gray; border-radius: 3px;  margin-top: 0.5em; } QGroupBox::title {  subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;}")
        
        self.label_sent = QLabel("Last packet sent: ")
        self.label_received = QLabel("Last packet received: ")
        
        self.log_layout = QVBoxLayout()
        self.log_layout.addWidget(self.label_received)
        self.log_layout.addWidget(self.label_sent)
        
        self.log_group.setLayout(self.log_layout)
    
    # Adds as many buttons as the number of connected power supplies.
    def build_buttons_group (self):
        
        self.sources_group = QGroupBox(parent =  self.main_widget)
        self.sources_group.setTitle('Power supply')
        self.sources_group.setStyleSheet("QGroupBox { border: 1px solid gray; border-radius: 3px;  margin-top: 0.5em; } QGroupBox::title {  subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;}")
    
        self.sources_layout = QHBoxLayout()
    
        for button in self.board_buttons_list:
            self.sources_layout.addWidget(button)
            
        self.sources_group.setLayout(self.sources_layout)
        
    # Builds all command buttons.
    # 0x00 stands for a normal reading command, 0x01, a ADJUST command, 0x05, a acknowledge message,
    # 0xE0 is used to ENABLE CYCLE and 0xE1, to abort it.
    def build_commands_group (self):
        
        self.commands_group = QGroupBox(parent =  self.main_widget)
        self.commands_group.setTitle('Commands')
        self.commands_group.setStyleSheet("QGroupBox { border: 1px solid gray; border-radius: 3px;  margin-top: 0.5em; } QGroupBox::title {  subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;}")
    
        self.commands_layout = QHBoxLayout()
    
        self.button_normal = QPushButton("0x00")
        self.commands_layout.addWidget(self.button_normal)
        self.button_normal.setEnabled(False)
        # Connects clicked signal to the handler
        self.button_normal.clicked.connect(self.normal_handler)
        
        self.button_adjust = QPushButton("0x01")
        self.commands_layout.addWidget(self.button_adjust)
        self.button_adjust.setEnabled(False)
        self.button_adjust.clicked.connect(self.adjust_handler)
        
        self.button_confirm = QPushButton("0x05")
        self.commands_layout.addWidget(self.button_confirm)
        self.button_confirm.setEnabled(False)
        self.button_confirm.clicked.connect(self.confirm_handler)
        
        self.button_cycle_enable = QPushButton("0xE0")
        self.commands_layout.addWidget(self.button_cycle_enable)
        self.button_cycle_enable.setEnabled(False)
        self.button_cycle_enable.clicked.connect(self.cycle_enable_handler)
        
        self.button_cycle_abort = QPushButton("0xE1")
        self.commands_layout.addWidget(self.button_cycle_abort)
        self.button_cycle_abort.setEnabled(False)
        self.button_cycle_abort.clicked.connect(self.cycle_abort_handler)
        
        self.commands_group.setLayout(self.commands_layout)
    
    # Returns how many power suppliers are connected
    def get_boards_count(self):
        
        return len(self.board_source_windows_list)
    
    # Returns how many power suppliers are connected
    def get_boards_list(self):
        
        return self.board_source_windows_list
    
    # Resets lists
    def build_source_windows(self):
        
        # board_source_windows_list is a list object which contains all references
        # to the SourceWindow objects. board_buttons_list contains the references to
        # the buttons which open the respective window 
        
        self.board_source_windows_list = list()
        self.board_buttons_list = list()
        
        # Support for a pre-built configuration (command IDENT not necessary)
        #for i in board_list:
        #    self.board_source_windows_list.append(SourceWindow(parent = self, board = i))
        #    button = QPushButton(i.getTitle())
        #    button.clicked.connect (self.source_handler)
        #    self.board_buttons_list.append(button)

    # Adds a button to the board_buttons_list and associates it to a SourceWindow object
    def add_board_source_group(self, id):
               
        self.board_source_windows_list.append(SourceWindow(parent = self, board = Board(title='Board #%d' % id, color = QColor(randint(0, 255), randint(0, 255), randint(0, 255) ), order = id)))
        button = QPushButton('Board #%d' % id)
        button.clicked.connect (self.source_handler)
        self.board_buttons_list.append(button)
        
        self.sources_layout.addWidget(button)
    
    # Resets and deletes board_source_windows_list and board_buttons_list
    def clear_source_group (self):
        
        # Resets entire source group. Clears buttons and layout
        for b in self.board_buttons_list:
            b.deleteLater()
            #self.sources_layout.removeWidget(b)
            
        self.board_buttons_list = []  # Clears button list
        
        for b in self.board_source_windows_list:
            
            # if useCanvas is True, close canvas. Such operation must be made explicitly,
            # considering that matplotlib does not handle it.
            if b.useCanvas:
                b.canvas.close()
                     
            b.close()
        
        self.board_source_windows_list = []
        
    # Updates buttons in the case of a disconnection
    def set_disconnected_state (self):
               
        self.sources_group.setVisible(False)
        
        self.button_normal.setEnabled(False)
        self.button_adjust.setEnabled(False)
        self.button_cycle_enable.setEnabled(False)
        self.button_cycle_abort.setEnabled(False)
        self.button_confirm.setEnabled(False)
        
        self.led_connected.turnOff()
                
        self.connect_button.setText("Connect")
    
    # Updates buttons in the case of a connection    
    def set_connected_state (self):
        
        self.sources_group.setVisible(True)
        
        self.button_normal.setEnabled(True)
        self.button_adjust.setEnabled(True)
        self.button_cycle_enable.setEnabled(True)
        self.button_cycle_abort.setEnabled(False)
        self.button_confirm.setEnabled(True)
        
        self.led_connected.turnOn()
        
        self.connect_button.setText("Disconnect")
        
    def set_requester_controller(self, requester):
        
        self.requester_controller = requester

    ####### HANDLERS section #######
    
    # Handles a connection / disconnection request
    def connection_handler(self):
        
        if not self.requester_controller.isConnected :
        
            port_n = int(self.port_line.text())
            
            self.led_connected.turnAlmostOn()
            
            self.statusBar().clearMessage()
            
            self.statusBar().showMessage('Trying to connect to %s through port %d' % (self.connect_line.text(), port_n))
            
            self.update()
            
            # Tries to connect to the PROSAC
            connected, message = self.requester_controller.connect(ip_address = self.connect_line.text(), port = port_n)
            
            self.statusBar().showMessage('%s' % message)
                    
            if connected:
                
                self.set_connected_state()
                                            
                # Request information about how many boards are connected (IDENT command)
                self.requester_controller.execute_command(0x02)
                self.requester_controller.execute_command(0x03)
                
                
                self.requester_controller.can_ask = True
            
            # If connection request was not successful, reset all lists 
            # and boards
            else: 
                
                self.requester_controller.isConnected = False
                self.clear_source_group()
                self.set_disconnected_state()
        
        # Disconnection request: reset all lists and updates buttons
        else :
            
            self.requester_controller.disconnect()
            
            self.clear_source_group()
            
            self.set_disconnected_state()
                        
            self.statusBar().showMessage('Client disconnected.')            
            
    # Sends a 0x00 command
    def normal_handler (self):
    
        self.requester_controller.execute_command(0x00)
    
    # Sends a 0x01 command
    def adjust_handler(self):
        
        self.requester_controller.execute_command(0x01)
    
    # Sends a 0x05 command
    def confirm_handler(self):
        
        self.requester_controller.execute_command(0x05)

    # Sends a 0xE0 command and updates states of buttons
    def cycle_enable_handler(self):
        
        self.requester_controller.execute_command(0xE0)
        
        self.button_normal.setEnabled(False)
        self.button_adjust.setEnabled(False)
        self.button_cycle_enable.setEnabled(False)
        self.button_cycle_abort.setEnabled(True)
        self.button_confirm.setEnabled(False)
    
    # Sends a 0xE1 command and updates states of buttons
    def cycle_abort_handler(self):
        
        self.requester_controller.execute_command(0xE1)
        
        self.button_normal.setEnabled(True)
        self.button_adjust.setEnabled(True)
        self.button_cycle_enable.setEnabled(True)
        self.button_cycle_abort.setEnabled(False)
        self.button_confirm.setEnabled(True)
        
    # Handles push-button event and shows the associated SourceWindow object 
    def source_handler(self):
        
        sender = self.sender()
        j = 0
        
        for i in self.board_buttons_list:
            
            if sender == i:
                break
            
            j = j + 1
            
        self.board_source_windows_list[j].show()
        
        self.statusBar().showMessage(sender.text() + ' was pressed')
    
    # Update flag in order to reader thread to acknowledge it 
    def closeEvent(self, *args, **kwargs):
        
        self.is_closed = 1
        
        return QMainWindow.closeEvent(self, *args, **kwargs)
    
    # Updates all SourceWindow objects 
    def paintEvent(self, *args, **kwargs):
        
        for b in self.board_source_windows_list:
            b.update()
        
        return QMainWindow.paintEvent(self, *args, **kwargs)