Beispiel #1
0
class plotScroller:
    def update_val(self, proc):
        d=str(self.scl.value())
        self.v.setText(d)
        if proc != None:
            proc(self.scl.value())
        
    def __init__(self, master, text, geo, proc=None, lim=(0,100,1)):
        self.scl=QScrollBar(Qt.Horizontal, master)
        self.scl.resize(geo[2]-50,geo[3])
        self.scl.move(geo[0]+50,geo[1])
        self.scl.setMinimum(lim[0])
        self.scl.setMaximum(lim[1])
        self.scl.setSingleStep(lim[2])
        self.scl.valueChanged.connect(lambda: self.update_val(proc))
        
        q=QLabel(master)
        q.move(geo[0],geo[1]+10)
        q.resize(50,20)
        q.setText(text)
        
        self.v=QLabel(master)
        self.v.move(geo[2]+10,geo[1]+10)
        self.v.resize(50,20)
        self.v.setText(str(self.scl.value()))
    
    def setValue(self, v):
        self.scl.setValue(v)
Beispiel #2
0
class SlidersGroup(QGroupBox):

    valueChanged = pyqtSignal(int)

    def __init__(self, orientation, title, parent=None):
        super(SlidersGroup, self).__init__(title, parent)

        self.slider = QSlider(orientation)
        self.slider.setFocusPolicy(Qt.StrongFocus)
        self.slider.setTickPosition(QSlider.TicksBothSides)
        self.slider.setTickInterval(10)
        self.slider.setSingleStep(1)

        self.scrollBar = QScrollBar(orientation)
        self.scrollBar.setFocusPolicy(Qt.StrongFocus)

        self.dial = QDial()
        self.dial.setFocusPolicy(Qt.StrongFocus)

        self.slider.valueChanged.connect(self.scrollBar.setValue)
        self.scrollBar.valueChanged.connect(self.dial.setValue)
        self.dial.valueChanged.connect(self.slider.setValue)
        self.dial.valueChanged.connect(self.valueChanged)

        if orientation == Qt.Horizontal:
            direction = QBoxLayout.TopToBottom
        else:
            direction = QBoxLayout.LeftToRight

        slidersLayout = QBoxLayout(direction)
        slidersLayout.addWidget(self.slider)
        slidersLayout.addWidget(self.scrollBar)
        slidersLayout.addWidget(self.dial)
        self.setLayout(slidersLayout)    

    def setValue(self, value):    
        self.slider.setValue(value)    

    def setMinimum(self, value):    
        self.slider.setMinimum(value)
        self.scrollBar.setMinimum(value)
        self.dial.setMinimum(value)    

    def setMaximum(self, value):    
        self.slider.setMaximum(value)
        self.scrollBar.setMaximum(value)
        self.dial.setMaximum(value)    

    def invertAppearance(self, invert):
        self.slider.setInvertedAppearance(invert)
        self.scrollBar.setInvertedAppearance(invert)
        self.dial.setInvertedAppearance(invert)    

    def invertKeyBindings(self, invert):
        self.slider.setInvertedControls(invert)
        self.scrollBar.setInvertedControls(invert)
        self.dial.setInvertedControls(invert)
class SlidersGroup(QGroupBox):

    valueChanged = pyqtSignal(int)

    def __init__(self, orientation, title, parent=None):
        super(SlidersGroup, self).__init__(title, parent)

        self.slider = QSlider(orientation)
        self.slider.setFocusPolicy(Qt.StrongFocus)
        self.slider.setTickPosition(QSlider.TicksBothSides)
        self.slider.setTickInterval(10)
        self.slider.setSingleStep(1)

        self.scrollBar = QScrollBar(orientation)
        self.scrollBar.setFocusPolicy(Qt.StrongFocus)

        self.dial = QDial()
        self.dial.setFocusPolicy(Qt.StrongFocus)

        self.slider.valueChanged.connect(self.scrollBar.setValue)
        self.scrollBar.valueChanged.connect(self.dial.setValue)
        self.dial.valueChanged.connect(self.slider.setValue)
        self.dial.valueChanged.connect(self.valueChanged)

        if orientation == Qt.Horizontal:
            direction = QBoxLayout.TopToBottom
        else:
            direction = QBoxLayout.LeftToRight

        slidersLayout = QBoxLayout(direction)
        slidersLayout.addWidget(self.slider)
        slidersLayout.addWidget(self.scrollBar)
        slidersLayout.addWidget(self.dial)
        self.setLayout(slidersLayout)

    def setValue(self, value):
        self.slider.setValue(value)

    def setMinimum(self, value):
        self.slider.setMinimum(value)
        self.scrollBar.setMinimum(value)
        self.dial.setMinimum(value)

    def setMaximum(self, value):
        self.slider.setMaximum(value)
        self.scrollBar.setMaximum(value)
        self.dial.setMaximum(value)

    def invertAppearance(self, invert):
        self.slider.setInvertedAppearance(invert)
        self.scrollBar.setInvertedAppearance(invert)
        self.dial.setInvertedAppearance(invert)

    def invertKeyBindings(self, invert):
        self.slider.setInvertedControls(invert)
        self.scrollBar.setInvertedControls(invert)
        self.dial.setInvertedControls(invert)
Beispiel #4
0
class ObjMotorWidgetUI(QWidget):
    
#    waveforms_generated = pyqtSignal(object, object, list, int)
#    SignalForContourScanning = pyqtSignal(int, int, int, np.ndarray, np.ndarray)
#    MessageBack = pyqtSignal(str)
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
#        os.chdir('./')# Set directory to current folder.
        self.setFont(QFont("Arial"))
        
#        self.setMinimumSize(1350,900)
        self.setWindowTitle("ObjMotorWidget")
        self.layout = QGridLayout(self)
        self.connect_status = False
        #**************************************************************************************************************************************
        #--------------------------------------------------------------------------------------------------------------------------------------
        #-----------------------------------------------------------GUI for Objective Motor----------------------------------------------------
        #--------------------------------------------------------------------------------------------------------------------------------------          
        #**************************************************************************************************************************************
        
        # Movement based on relative positions.
        self.ObjMotorcontrolContainer = QGroupBox("Objective motor control")
        self.ObjMotorcontrolContainer.setStyleSheet("QGroupBox {\
                                font: bold;\
                                border: 1px solid silver;\
                                border-radius: 6px;\
                                margin-top: 12px;\
                                color:Navy; \
                                background-color: #FFFAFA}\
                                QGroupBox::title{subcontrol-origin: margin;\
                                                 left: 7px;\
                                                 padding: 5px 5px 5px 5px;}")
        self.ObjMotorcontrolLayout = QGridLayout()
        
        self.ObjMotor_connect = StylishQT.connectButton()
        self.ObjMotor_connect.setFixedWidth(70)
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_connect, 0, 0)
        self.ObjMotor_connect.clicked.connect(lambda: self.ConnectMotor())     
        self.ObjMotor_connect.setGraphicsEffect(QGraphicsDropShadowEffect(blurRadius=3, xOffset=2, yOffset=2))
        
        self.ObjMotor_disconnect = StylishQT.disconnectButton()
        self.ObjMotor_disconnect.setFixedWidth(70)
        self.ObjMotor_disconnect.setGraphicsEffect(QGraphicsDropShadowEffect(blurRadius=3, xOffset=2, yOffset=2))
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_disconnect, 0, 1)
        
        self.ObjMotor_disconnect.clicked.connect(lambda: self.DisconnectMotor()) 
        self.ObjMotor_disconnect.setEnabled(False)
        
        self.ObjMotor_upwards = QPushButton("↑")
        self.ObjMotor_upwards.setStyleSheet("QPushButton {color:white;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}"
                                            "QPushButton:pressed {color:red;background-color: white; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}"
                                            "QPushButton:hover:!pressed {color:gray;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}")        
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_upwards, 2, 2)
        self.ObjMotor_upwards.clicked.connect(lambda: self.MovingMotorThread("Motor_move_upwards"))
#        self.ObjMotor_upwards.setShortcut('w')
        
        self.ObjMotor_down = QPushButton("↓")
        self.ObjMotor_down.setStyleSheet("QPushButton {color:white;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}"
                                            "QPushButton:pressed {color:red;background-color: white; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}"
                                            "QPushButton:hover:!pressed {color:gray;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}")        
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_down, 3, 2)
        self.ObjMotor_down.clicked.connect(lambda: self.MovingMotorThread("Motor_move_downwards"))
#        self.stage_down.setShortcut('s')
        
        self.ObjMotor_target = QDoubleSpinBox(self)
        self.ObjMotor_target.setMinimum(-10000)
        self.ObjMotor_target.setMaximum(10000)
        self.ObjMotor_target.setDecimals(6)
#        self.ObjMotor_target.setValue(3.45)
        self.ObjMotor_target.setSingleStep(0.001)        
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_target, 1, 1)
        self.ObjMotorcontrolLayout.addWidget(QLabel("Target:"), 1, 0)
        
        self.ObjMotor_current_pos_Label = QLabel("Current position: ")
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_current_pos_Label, 2, 0, 1, 2)
        
        self.ObjMotor_goto = QPushButton()
        self.ObjMotor_goto.setIcon(QIcon('./Icons/move_coord.png')) 
        self.ObjMotor_goto.setToolTip("Move to absolute position")
        self.ObjMotor_goto.setStyleSheet("QPushButton {color:white;background-color: #CCFFFF;}"
                                      "QPushButton:hover:!pressed {color:white;background-color: #FFE5CC;}")
        self.ObjMotor_goto.setFixedWidth(35)
        self.ObjMotor_goto.setFixedHeight(35)
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_goto, 1, 2)
        self.ObjMotor_goto.clicked.connect(lambda: self.MovingMotorThread("Motor_move_target"))
        
        self.ObjMotor_step = QDoubleSpinBox(self)
        self.ObjMotor_step.setMinimum(-10000)
        self.ObjMotor_step.setMaximum(10000)
        self.ObjMotor_step.setDecimals(6)
        self.ObjMotor_step.setValue(0.003)
        self.ObjMotor_step.setSingleStep(0.001)        
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_step, 3, 1)
        self.ObjMotorcontrolLayout.addWidget(QLabel("Step: "), 3, 0)  
        
        self.FocusSlider = QScrollBar(Qt.Horizontal)
        self.FocusSlider.setMinimum(2500000)
        self.FocusSlider.setMaximum(4500000)
#        self.FocusSlider.setTickPosition(QSlider.TicksBothSides)
#        self.FocusSlider.setTickInterval(1000000)
        self.FocusSlider.setStyleSheet('color:white; background: lightblue')
        self.FocusSlider.setSingleStep(10000)
#        self.line640 = QLineEdit(self)
#        self.line640.setFixedWidth(60)
#        self.FocusSlider.sliderReleased.connect(lambda:self.updatelinevalue(640))
        self.FocusSlider.valueChanged.connect(lambda:self.MovingMotorThread("Motor_move_slider"))
        self.FocusSlider.setTracking(False)
#        self.line640.returnPressed.connect(lambda:self.updatesider(640))
        self.ObjMotorcontrolLayout.addWidget(self.FocusSlider, 4, 0, 1, 3)
        
        self.ObjMotorcontrolContainer.setLayout(self.ObjMotorcontrolLayout)
        self.ObjMotorcontrolContainer.setMaximumHeight(300)
        self.layout.addWidget(self.ObjMotorcontrolContainer, 4, 0)          
        
        #**************************************************************************************************************************************
        #--------------------------------------------------------------------------------------------------------------------------------------
        #-----------------------------------------------------------Fucs for Motor movement----------------------------------------------------
        #--------------------------------------------------------------------------------------------------------------------------------------          
        #**************************************************************************************************************************************         
    def ConnectMotor(self):
        self.ObjMotorcontrolContainer.setEnabled(False)
        self.ObjMotor_disconnect.setEnabled(True)
        self.ObjMotor_connect.setEnabled(False)
        
        self.device_instance = ConnectObj_Thread()
        self.device_instance.start()
        self.device_instance.finished.connect(self.getmotorhandle)

    def getmotorhandle(self):
        self.pi_device_instance = self.device_instance.getInstance()
        print('Objective motor connected.')
        self.connect_status = True
#        self.normalOutputWritten('Objective motor connected.'+'\n')
        
        self.ObjCurrentPos = self.pi_device_instance.pidevice.qPOS(self.pi_device_instance.pidevice.axes)
        self.ObjMotor_current_pos_Label.setText("Current position: {:.4f}".format(self.ObjCurrentPos['1'])) # Axis here is a string.
        self.ObjMotor_target.setValue(self.ObjCurrentPos['1'])
        
        decimal_places = len(str(self.ObjCurrentPos['1']).split('.')[1])
        print(int(self.ObjCurrentPos['1']*(10**decimal_places)))
        self.FocusSlider.setValue(int(self.ObjCurrentPos['1']*(10**6)))
        self.ObjMotorcontrolContainer.setEnabled(True)
        
    def MovingMotorThread(self, target):
        if target == "Motor_move_target":
            MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('Target',))
            MoveMotorThread.start()
        elif target == "Motor_move_upwards":
            MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('UP',))
            MoveMotorThread.start()            
        elif target == "Motor_move_downwards":
            MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('DOWN',))
            MoveMotorThread.start()  
        elif target == "Motor_move_slider":
            MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('Slider',))
            MoveMotorThread.start()          
        
    def MoveMotor(self, direction):
        if direction == "Target":
            pos = PIMotor.move(self.pi_device_instance.pidevice, self.ObjMotor_target.value())
        elif direction == "UP":
            self.MotorStep = self.ObjMotor_step.value()
            pos = PIMotor.move(self.pi_device_instance.pidevice, (self.ObjCurrentPos['1'] + self.MotorStep))
        elif direction == "DOWN":
            self.MotorStep = self.ObjMotor_step.value()
            pos = PIMotor.move(self.pi_device_instance.pidevice, (self.ObjCurrentPos['1'] - self.MotorStep))
        elif direction == "Slider":
            pos = PIMotor.move(self.pi_device_instance.pidevice, self.FocusSlider.value()/1000000)
            
        self.ObjCurrentPos = self.pi_device_instance.pidevice.qPOS(self.pi_device_instance.pidevice.axes)
        self.ObjMotor_current_pos_Label.setText("Current position: {:.4f}".format(self.ObjCurrentPos['1'])) # Axis here is a string.
        self.ObjMotor_target.setValue(self.ObjCurrentPos['1'])  
        
        # decimal_places = len(str(self.ObjCurrentPos['1']).split('.')[1])
        self.FocusSlider.setValue(int(self.ObjCurrentPos['1']*(10**6)))
      
    def DisconnectMotor(self):
        self.ObjMotor_connect.setEnabled(True)
        self.ObjMotor_disconnect.setEnabled(False)
        
        PIMotor.CloseMotorConnection(self.pi_device_instance.pidevice)
        print('Disconnected')
        self.connect_status = False
#        self.normalOutputWritten('Objective motor disconnected.'+'\n')
        
    def closeEvent(self, event):
        # ## Because the software combines both PyQt and PyQtGraph, using the
        # ## closeEvent() from PyQt will cause a segmentation fault. Calling 
        # ## also the exit() from PyQtGraph solves this problem. 
        # pg.exit()
        if self.connect_status == True:
            self.DisconnectMotor()
            
        QtWidgets.QApplication.quit()
        event.accept()
Beispiel #5
0
class VanillaWindow(QMainWindow):

    SHIFT = 100
    MAX_BRUSH_SIZE = 500
    TOOLBAR_HEIGHT = 791
    TOOLBAR_WIDTH = 389
    BUTTON_SIZE = 64
    MENU_BAR_HEIGHT = 30
    BUTTON_SHIFT = 20
    MINIMUM_CANVAS_LEFT_SHIFT = 250

    def __init__(self):
        super().__init__()
        self.to_draw_canvas = False
        self.to_draw_line = False
        self.to_draw_rectangle = False
        self.to_draw_triangle = False
        self.to_draw_ellipse = False
        self.to_draw_selection = False
        self.cursor_on_canvas = False
        self.shape_start = None
        self.selection_left = 0
        self.selection_right = 0
        self.selection_up = 0
        self.selection_down = 0
        self.selection_width = 0
        self.selection_height = 0
        self.mouse_pressed = False
        self.picture_name = None
        self.canvas = Canvas()
        self.button_images = {}
        self.buttons = {}
        self.layer_tables = []
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle('Vanilla')
        self.setWindowIcon(QIcon('images/icon.png'))
        self.showMaximized()
        self.setStyleSheet('QMainWindow{background: Gray;}'
                           'QMenuBar::item:selected{background: #202020;}'
                           'QMenu::item:disabled{color: #505050;}'
                           'QToolTip{background : black; font-size: 16px; color: white; '
                           'border: black solid 1px}')
        self.setMouseTracking(True)
        self.create_menu_bar()

        self.color_picker = QPushButton('', self)
        color_picker_height = 100
        self.color_picker.setGeometry(50, self.TOOLBAR_HEIGHT + self.MENU_BAR_HEIGHT - color_picker_height - 50,
                                      100, color_picker_height)
        red = Canvas().current_color.r
        green = Canvas().current_color.g
        blue = Canvas().current_color.b
        self.color_picker.setStyleSheet(f'background: Color({red}, {green}, {blue})')
        self.color_picker.clicked.connect(self.pick_color)
        self.color_picker.show()

        self.size_slider = QSlider(Qt.Horizontal, self)
        slider_height = 20
        self.size_slider.setGeometry(10, self.color_picker.y() - slider_height - 60, 145, slider_height)
        self.size_slider.setMinimum(1)
        self.size_slider.setMaximum(self.MAX_BRUSH_SIZE)
        self.size_slider.valueChanged[int].connect(self.size_changed)
        self.size_slider.show()

        validator = QIntValidator(1, self.MAX_BRUSH_SIZE)
        self.size_edit = QLineEdit('1', self)
        self.size_edit.setGeometry(self.size_slider.x() + self.size_slider.width() + 5, self.size_slider.y(), 35, 20)
        self.size_edit.setFont(QFont('Arial', 10))
        self.size_edit.setAlignment(Qt.AlignCenter)
        self.size_edit.setValidator(validator)
        self.size_edit.textChanged[str].connect(self.size_edited)
        self.size_edit.show()

        self.size_label = QLabel('Brush Size:', self)
        self.size_label.setFont(QFont('Arial', 16))
        self.size_label.setStyleSheet('color: lightGray;')
        self.size_label.setGeometry(self.size_slider.x(), self.size_slider.y() - self.size_slider.height() - 10,
                                    self.size_slider.width() + self.size_edit.width() + 5, 30)
        self.size_label.show()

        self.create_buttons()

        width = QDesktopWidget().width()
        height = QDesktopWidget().height() - 64
        size = 20

        self.layer_button_left = width - 220

        self.add_layer_button = QPushButton('Add Layer', self)
        self.add_layer_button.setGeometry(self.layer_button_left + 24, self.TOOLBAR_HEIGHT - 15, 150, 30)
        self.add_layer_button.clicked.connect(self.add_layer)
        self.add_layer_button.setFont(QFont('Arial', 14))
        self.add_layer_button.show()

        self.layers_label = QLabel('Layers', self)
        self.layers_label.setFont(QFont('Arial', 20))
        self.layers_label.setStyleSheet('color: lightGray;')
        self.layers_label.setGeometry(self.layer_button_left, 25, 197, 60)
        self.layers_label.setAlignment(Qt.AlignCenter)
        self.layers_label.show()

        self.vertical_scrollbar = QScrollBar(self)
        self.vertical_scrollbar.setGeometry(width - size, 0, size, height - size)
        self.vertical_scrollbar.valueChanged[int].connect(self.vertical_scrollbar_value_changed)

        self.horizontal_scrollbar = QScrollBar(Qt.Horizontal, self)
        self.horizontal_scrollbar.setGeometry(0, height - size, width - size, size)
        self.horizontal_scrollbar.valueChanged[int].connect(self.horizontal_scrollbar_value_changed)

        self.show()

    def create_buttons(self):
        left = 25

        brush_button = self.create_button(left, self.MENU_BAR_HEIGHT + 20, 'Brush', 'B', self.brush_button_clicked)
        self.buttons[Tools.BRUSH] = brush_button

        right = brush_button.x() + brush_button.width() + self.BUTTON_SHIFT

        eraser_button = self.create_button(right, brush_button.y(), 'Eraser', 'E', self.eraser_button_clicked)
        self.buttons[Tools.ERASER] = eraser_button

        fill_button = self.create_button(left, self.get_button_shift(brush_button), 'Fill', 'F',
                                         self.fill_button_pressed)
        self.buttons[Tools.FILL] = fill_button

        selection_button = self.create_button(right, fill_button.y(), 'Selection', 'S', self.selection_button_clicked)
        self.buttons[Tools.SELECTION] = selection_button

        line_button = self.create_button(left, self.get_button_shift(fill_button), 'Line', 'L',
                                         self.line_button_clicked)
        self.buttons[Tools.LINE] = line_button

        rectangle_button = self.create_button(right, line_button.y(), 'Rectangle', 'R', self.rectangle_button_clicked)
        self.buttons[Tools.SQUARE] = rectangle_button

        ellipse_button = self.create_button(left, self.get_button_shift(line_button), 'Ellipse', 'C',
                                            self.ellipse_button_clicked)
        self.buttons[Tools.CIRCLE] = ellipse_button

        triangle_button = self.create_button(right, ellipse_button.y(), 'Triangle', 'T', self.triangle_button_clicked)
        self.buttons[Tools.TRIANGLE] = triangle_button

        right_turn_button = self.create_button(left, self.get_button_shift(ellipse_button), 'Turn Right', 'Ctrl+R',
                                               self.turn_selection_right)
        left_turn_button = self.create_button(right, right_turn_button.y(), 'Turn Left', 'Ctrl+L',
                                              self.turn_selection_left)

        flip_horizontally_button =  self.create_button(left, self.get_button_shift(right_turn_button),
                                                       'Flip Horizontally', 'Ctrl+H', self.flip_horizontally)

        flip_vertically_button = self.create_button(right, flip_horizontally_button.y(), 'Flip Vertically', 'Ctrl+F',
                                                    self.flip_vertically)

    def create_menu_bar(self):
        self.menu_bar = self.menuBar()
        self.menu_bar.setStyleSheet('selection-background-color: #202020; background: #393939; color: lightGray;')

        file_menu = self.menu_bar.addMenu('&File')

        new_action = QAction('&New', self)
        new_action.setShortcut('Ctrl+N')
        new_action.triggered.connect(self.ask_size)
        file_menu.addAction(new_action)

        open_action = QAction('&Open', self)
        open_action.setShortcut('Ctrl+O')
        open_action.triggered.connect(self.open)
        file_menu.addAction(open_action)

        file_menu.addSeparator()

        self.save_action = QAction('&Save', self)
        self.save_action.setShortcut('Ctrl+S')
        self.save_action.triggered.connect(self.save)
        self.save_action.setDisabled(True)
        file_menu.addAction(self.save_action)

        self.save_as_action = QAction('Save as', self)
        self.save_as_action.setShortcut('Ctrl+Shift+S')
        self.save_as_action.triggered.connect(self.save_as)
        self.save_as_action.setDisabled(True)
        file_menu.addAction(self.save_as_action)

        image_menu = self.menu_bar.addMenu('&Image')

        self.greyscale_action = QAction('Greyscale', self)
        self.greyscale_action.setShortcut('Ctrl+G')
        self.greyscale_action.triggered.connect(self.change_greyscale)
        self.greyscale_action.setDisabled(True)
        image_menu.addAction(self.greyscale_action)

        self.brightness_action = QAction('Brightness', self)
        self.brightness_action.setShortcut('Ctrl+B')
        self.brightness_action.triggered.connect(self.brightness)
        self.brightness_action.setDisabled(True)
        image_menu.addAction(self.brightness_action)

        selection_menu = self.menu_bar.addMenu('&Selection')

        self.deselect_action = QAction('Deselect', self)
        self.deselect_action.setShortcut('Ctrl+D')
        self.deselect_action.triggered.connect(self.deselect)
        self.deselect_action.setDisabled(True)
        selection_menu.addAction(self.deselect_action)

        self.select_all_action = QAction('Select All', self)
        self.select_all_action.setShortcut('Ctrl+A')
        self.select_all_action.triggered.connect(self.select_all)
        self.select_all_action.setDisabled(True)
        selection_menu.addAction(self.select_all_action)

        selection_menu.addSeparator()

        self.delete_selection_action = QAction('Delete', self)
        self.delete_selection_action.setShortcut('Delete')
        self.delete_selection_action.triggered.connect(self.delete_in_selection)
        self.delete_selection_action.setDisabled(True)
        selection_menu.addAction(self.delete_selection_action)

    def create_button(self, x, y, image, shortcut='', action=lambda: None):
        button = QPushButton('', self)
        button.setGeometry(x, y, self.BUTTON_SIZE, self.BUTTON_SIZE)
        button.setStyleSheet('background: transparent;')
        button.setShortcut(shortcut)
        button.setToolTip(f'{image} ({shortcut})')
        button.clicked.connect(action)
        self.button_images[button] = QImage(f'images/{image}.png')
        button.show()
        return button

    def flip(self, flip_function):
        if not self.canvas.selection_is_on:
            return
        flip_function()
        self.to_draw_selection = False
        self.update_canvas()
        self.update()

    def flip_horizontally(self):
        self.flip(self.canvas.flip_horizontally)

    def flip_vertically(self):
        self.flip(self.canvas.flip_vertically)

    def get_button_shift(self, upper_button):
        return upper_button.y() + upper_button.height() + self.BUTTON_SHIFT

    def turn_selection_right(self):
        self.turn_selection(self.canvas.turn_selection_right)

    def turn_selection_left(self):
        self.turn_selection(self.canvas.turn_selection_left)

    def turn_selection(self, turn_function):
        if not self.canvas.selection_is_on:
            return
        turn_function()
        self.to_draw_selection = False
        self.update_canvas()
        self.update()

    def create_layer_button(self, x, y, layer_number):
        button = QPushButton('', self)
        button.setGeometry(x, y, 187, 100)
        button.setStyleSheet('background: transparent;')
        button.clicked.connect(lambda: self.change_layer(layer_number))
        button.show()
        return button

    def change_layer(self, number):
        self.canvas.change_layer(number)
        self.update_color_button()
        self.update()

    def delete_layer(self, layer_table):
        self.canvas.delete_layer(layer_table.layer)
        self.layer_tables.remove(layer_table)
        self.update_canvas()
        self.update_layers_buttons()
        if len(self.canvas.layers) == 5:
            self.add_layer_button.setDisabled(False)
        self.update()

    def update_layers_buttons(self):
        for table in self.layer_tables:
            table.close()
        self.layer_tables = []
        x = self.layer_button_left + 5
        for i in range(len(self.canvas.layers)):
            layer = self.canvas.layers[i]
            btn = self.create_layer_button(x, 90 + i * 105, i)
            self.layer_tables.append(LayerTable(x, 90 + i * 105, layer, btn, self))

    def add_layer(self):
        self.canvas.add_layer()
        if len(self.canvas.layers) == 6:
            self.add_layer_button.setDisabled(True)
        self.update_layers_buttons()
        self.update()

    def eraser_button_clicked(self):
        self.canvas.choose_eraser()
        self.update()

    def brush_button_clicked(self):
        self.canvas.choose_brush()
        self.update()

    def line_button_clicked(self):
        self.canvas.choose_line()
        self.update()

    def rectangle_button_clicked(self):
        self.canvas.choose_rectangle()
        self.update()

    def triangle_button_clicked(self):
        self.canvas.choose_triangle()
        self.update()

    def ellipse_button_clicked(self):
        self.canvas.choose_ellipse()
        self.update()

    def fill_button_pressed(self):
        self.canvas.choose_fill()
        self.update()

    def selection_button_clicked(self):
        self.canvas.choose_selection()
        self.update()

    def horizontal_scrollbar_value_changed(self, value):
        self.update()

    def vertical_scrollbar_value_changed(self, value):
        self.update()

    def change_greyscale(self):
        if self.canvas.active_layer.greyscale:
            self.canvas.turn_greyscale_off()
        else:
            self.canvas.turn_greyscale_on()
        self.update_canvas()
        self.update_color_button()
        self.update()

    def deselect(self):
        self.canvas.deselect()
        self.deselect_action.setDisabled(True)
        self.delete_selection_action.setDisabled(True)
        self.to_draw_selection = False
        self.update()

    def select_all(self):
        self.canvas.deselect()
        self.shape_start = 0, 0
        self.cursor_position = self.canvas.width - 1, self.canvas.height - 1
        self.update_selection_position()
        self.canvas.select(*self.shape_start, *self.cursor_position)
        self.to_draw_selection = True
        self.deselect_action.setDisabled(False)
        self.delete_selection_action.setDisabled(False)
        self.update()

    def change_brightness(self, brightness):
        self.canvas.change_brightness(brightness)
        self.update_canvas()
        self.update()

    def brightness(self):
        success, brightness = BrightnessDialog.get_brightness(self, self.canvas.active_layer.brightness)
        if success:
            self.change_brightness(brightness)

    def delete_in_selection(self):
        if not self.canvas.selection_is_on:
            return
        self.canvas.delete_selection()
        self.update_canvas()
        self.update()

    @property
    def canvas_left_side(self):
        return self.canvas_left_edge - self.horizontal_scrollbar.value()

    @property
    def canvas_upper_side(self):
        return self.canvas_upper_edge - self.vertical_scrollbar.value()

    def size_edited(self, size):
        if size == '':
            value = 1
        else:
            value = int(size)
        if value == 0:
            self.size_edit.setText('1')
        else:
            self.size_slider.setValue(value)

    def size_changed(self, value):
        if value == 0:
            self.canvas.brush_size = 1
        else:
            self.canvas.brush_size = value
        if self.to_draw_canvas:
            self.change_cursor()
        self.size_edit.setText(f'{self.canvas.brush_size}')

    def pick_color(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.canvas.change_color(color.red(), color.green(), color.blue(), color.alpha())
            self.update_color_button()

    def update_color_button(self):
        cur_color = self.canvas.current_color
        color = QColor(cur_color.r, cur_color.g, cur_color.b)
        self.color_picker.setStyleSheet(f'background: {color.name()}')

    def ask_size(self):
        success, width, height = SizeDialog.get_size(self)
        if success:
            self.create_canvas(width, height)

    def create_canvas(self, width, height):
        old_canvas = self.canvas
        self.canvas = Canvas(width, height)
        self.canvas.current_color_rgb = old_canvas.current_color_rgb
        self.canvas.brush_size = old_canvas.brush_size
        self.canvas.current_tool = old_canvas.current_tool
        max_size = self.height() - self.SHIFT * 2
        proportion = width / height
        if proportion > 1:
            self.canvas_width = max_size
            self.canvas_height = max_size / proportion
        else:
            self.canvas_width = max_size * proportion
            self.canvas_height = max_size
        self.pixel_size = self.canvas_width / self.canvas.width
        self.canvas_left_edge = (self.width() - self.canvas_width) / 2
        self.canvas_upper_edge = (self.height() - self.canvas_height) / 2
        self.canvas_as_image = self.convert_to_image()
        self.to_draw_canvas = True
        self.enable_actions()
        self.update_layers_buttons()

    def enable_actions(self):
        self.save_action.setDisabled(False)
        self.save_as_action.setDisabled(False)
        self.greyscale_action.setDisabled(False)
        self.brightness_action.setDisabled(False)
        self.select_all_action.setDisabled(False)

    def convert_to_image(self):
        image = QImage(self.canvas.width, self.canvas.height, QImage.Format_ARGB32)
        x = 0
        y = 0
        for layer in self.canvas.layers:
            for column in layer.pixels:
                for pixel in column:
                    image.setPixelColor(x, y, QColor(pixel.r, pixel.g, pixel.b, pixel.a))
                    y += 1
                x += 1
                y = 0
        return image

    def open(self):
        load_file_name = QFileDialog.getOpenFileName(self, 'Chose Image File', '',
                                                     'PNG Files (*.png);;JPG Files (*.jpg);;BMP Files (*.bmp)')[0]
        if load_file_name == '':
            return False
        self.picture_name = load_file_name
        image = QImage(load_file_name)
        self.create_canvas(image.width(), image.height())
        for x in range(self.canvas.width):
            for y in range(self.canvas.height):
                color = image.pixelColor(x, y)
                self.canvas.pixels[x][y] = Color(color.red(), color.green(), color.blue(), color.alpha())
        self.update_canvas()
        self.to_draw_canvas = True
        self.update()

    def save(self):
        if self.picture_name is None:
            self.save_as()
        else:
            self.canvas_as_image.save(self.picture_name)

    def save_as(self):
        name = QFileDialog.getSaveFileName(self, 'Save', '',
                                           'PNG Files (*.png);;JPG Files (*.jpg);;BMP Files (*.bmp)')[0]
        if name == '':
            return False
        self.picture_name = name
        self.save()

    def change_cursor(self):
        if self.canvas.current_tool == Tools.BRUSH:
            self.setCursor(self.get_brush_cursor())
        elif self.canvas.current_tool == Tools.ERASER:
            self.setCursor(self.get_eraser_cursor())
        elif self.canvas.current_tool == Tools.FILL:
            self.setCursor(self.get_fill_cursor())

    def get_brush_cursor(self):
        size = (2 * self.canvas.brush_size - 1) * self.pixel_size
        cursor = QPixmap(size, size)
        cursor.fill(Qt.transparent)
        painter = QPainter()
        painter.begin(cursor)
        painter.setPen(QColor(self.canvas.current_color.r, self.canvas.current_color.g, self.canvas.current_color.b))
        painter.drawEllipse(0, 0, size - 1, size - 1)
        painter.drawLine(size / 2, size / 4, size / 2, size / 4 * 3)
        painter.drawLine(size / 4, size / 2, size / 4 * 3, size / 2)
        painter.end()
        return QCursor(cursor)

    def get_eraser_cursor(self):
        size = (2 * self.canvas.brush_size - 1) * self.pixel_size
        cursor = QPixmap(size, size)
        cursor.fill(Qt.transparent)
        painter = QPainter()
        painter.begin(cursor)
        painter.setBrush(QBrush(QColor(255, 255, 255)))
        painter.drawEllipse(0, 0, size - 1, size - 1)
        painter.end()
        return QCursor(cursor)

    def get_fill_cursor(self):
        fill = QImage('images/FillCursor.png')
        cursor = QPixmap(fill.width(), fill.height())
        cursor.fill(Qt.transparent)
        painter = QPainter()
        painter.begin(cursor)
        painter.setBrush(QColor(self.canvas.current_color.r, self.canvas.current_color.g, self.canvas.current_color.b))
        painter.drawRect(10, 10, 10, 4)
        painter.drawImage(0, 0, fill)
        painter.end()
        return QCursor(cursor)

    def mouseMoveEvent(self, event):
        if not self.to_draw_canvas:
            return
        x = math.floor((event.pos().x() - self.canvas_left_side) / self.pixel_size)
        y = math.floor((event.pos().y() - self.canvas_upper_side) / self.pixel_size)
        if 0 <= x < self.canvas.width and 0 <= y < self.canvas.height:
            self.cursor_position = (x, y)
            self.change_cursor()
            self.cursor_on_canvas = True
        else:
            if not self.mouse_pressed:
                self.shape_start = None
            self.cursor_on_canvas = False
            self.setCursor(Qt.ArrowCursor)
        if self.mouse_pressed:
            self.move_tools()
            self.update_canvas()
            self.update()

    def move_tools(self):
        if self.canvas.current_tool in [Tools.BRUSH, Tools.ERASER]:
            self.canvas.paint(*self.cursor_position)
        if self.cursor_on_canvas and self.canvas.current_tool == Tools.SELECTION:
            self.update_selection_position()

    def update_canvas(self):
        if not self.to_draw_canvas:
            return
        while len(self.canvas.changed_pixels) > 0:
            x, y = self.canvas.changed_pixels.pop()
            layer = len(self.canvas.layers) - 1
            pixel = self.canvas.get_pixel(x, y, layer)
            while layer > 0 and pixel.a == 0:
                layer -= 1
                pixel = self.canvas.get_pixel(x, y, layer)
            self.canvas_as_image.setPixelColor(x, y, QColor(pixel.r, pixel.g, pixel.b, pixel.a))

    def mousePressEvent(self, event):
        if self.cursor_on_canvas and event.button() == Qt.LeftButton:
            self.mouse_pressed = True
            self.press_tools()

    def press_tools(self):
        if self.canvas.current_tool in [Tools.LINE, Tools.SQUARE, Tools.TRIANGLE, Tools.CIRCLE, Tools.SELECTION]:
            self.shape_start = self.cursor_position
        if self.canvas.current_tool in [Tools.BRUSH, Tools.ERASER]:
            self.canvas.paint(*self.cursor_position)
        elif self.canvas.current_tool == Tools.LINE:
            self.to_draw_line = True
        elif self.canvas.current_tool == Tools.SQUARE:
            self.to_draw_rectangle = True
        elif self.canvas.current_tool == Tools.TRIANGLE:
            self.to_draw_triangle = True
        elif self.canvas.current_tool == Tools.CIRCLE:
            self.to_draw_ellipse = True
        elif self.canvas.current_tool == Tools.FILL:
            self.canvas.fill(*self.cursor_position)
        elif self.canvas.current_tool == Tools.SELECTION:
            self.deselect()
            self.deselect_action.setDisabled(False)
            self.delete_selection_action.setDisabled(False)
            self.to_draw_selection = True

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton and self.to_draw_canvas:
            self.release_tools()
            self.update_canvas()
            self.update()
            self.mouse_pressed = False

    def release_tools(self):
        if self.shape_start is None:
            return
        if self.canvas.current_tool == Tools.SELECTION:
            self.canvas.select(*self.shape_start, *self.cursor_position)
        if self.canvas.current_tool == Tools.LINE:
            self.to_draw_line = False
            self.canvas.draw_line(*self.shape_start, *self.cursor_position)
        elif self.canvas.current_tool == Tools.SQUARE:
            self.to_draw_rectangle = False
            self.canvas.draw_rectangle(*self.shape_start, *self.cursor_position)
        elif self.canvas.current_tool == Tools.TRIANGLE:
            self.to_draw_triangle = False
            self.canvas.draw_triangle(*self.shape_start, *self.cursor_position)
        elif self.canvas.current_tool == Tools.CIRCLE:
            self.to_draw_ellipse = False
            self.canvas.draw_ellipse(*self.shape_start, *self.cursor_position)

    def wheelEvent(self, event):
        if not self.to_draw_canvas:
            return
        delta = event.angleDelta().y() / 120
        old_width = self.canvas_width
        old_height = self.canvas_height
        if self.canvas.width * (self.pixel_size + delta) > 0 and self.canvas.height * (self.pixel_size + delta) > 0:
            self.pixel_size += delta
            self.canvas_width = self.canvas.width * self.pixel_size
            self.canvas_height = self.canvas.height * self.pixel_size
            self.canvas_left_edge += (old_width - self.canvas_width) / 2
            self.canvas_upper_edge += (old_height - self.canvas_height) / 2
            self.change_cursor()
            self.update()
        if self.canvas_left_edge < self.MINIMUM_CANVAS_LEFT_SHIFT:
            max = self.MINIMUM_CANVAS_LEFT_SHIFT - self.canvas_left_edge
            self.horizontal_scrollbar.setMaximum(max)
            self.horizontal_scrollbar.setMinimum(-max)
            self.horizontal_scrollbar.show()
        else:
            self.horizontal_scrollbar.hide()
        if self.canvas_upper_edge < self.MENU_BAR_HEIGHT:
            max = self.MENU_BAR_HEIGHT - self.canvas_upper_edge
            self.vertical_scrollbar.setMinimum(-max)
            self.vertical_scrollbar.setMaximum(max)
            self.vertical_scrollbar.show()
        else:
            self.vertical_scrollbar.hide()

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        if self.to_draw_canvas:
            self.draw_pixels(painter)
        painter.setPen(QColor(self.canvas.current_color.r, self.canvas.current_color.g, self.canvas.current_color.b))
        if self.to_draw_line:
            self.draw_line(painter)
        if self.to_draw_rectangle:
            self.draw_rectangle(painter)
        if self.to_draw_triangle:
            self.draw_triangle(painter)
        if self.to_draw_ellipse:
            self.draw_ellipse(painter)
        if self.to_draw_selection:
            self.draw_selection(painter)
        self.draw_edges(painter)
        self.draw_layers(painter)
        painter.drawImage(0, self.menu_bar.height(), QImage('images/ToolBar.png'))
        self.highlight_current_button(painter)
        self.draw_buttons(painter)
        painter.end()

    def draw_layers(self, painter):
        painter.drawImage(self.width() - self.TOOLBAR_WIDTH, self.menu_bar.height(), QImage('images/LayersBar.png'))
        self.draw_current_layer(painter)
        for table in self.layer_tables:
            table.draw(painter)

    def highlight_current_button(self, painter):
        painter.setBrush(QColor(255, 255, 255))
        painter.setPen(Qt.transparent)
        button = self.buttons[self.canvas.current_tool]
        painter.drawRect(button.x(), button.y(), self.BUTTON_SIZE, self.BUTTON_SIZE)

    def get_start_end_position(self):
        start_x, start_y = self.shape_start
        end_x, end_y = self.cursor_position
        start_x = start_x * self.pixel_size + self.canvas_left_side + self.pixel_size / 2
        start_y = start_y * self.pixel_size + self.canvas_upper_side + self.pixel_size / 2
        end_x = end_x * self.pixel_size + self.canvas_left_side + self.pixel_size / 2
        end_y = end_y * self.pixel_size + self.canvas_upper_side + self.pixel_size / 2
        return start_x, start_y, end_x, end_y

    def draw_line(self, painter):
        start_x, start_y, end_x, end_y = self.get_start_end_position()
        painter.drawLine(start_x, start_y, end_x, end_y)

    def draw_rectangle(self, painter):
        start_x, start_y, end_x, end_y = self.get_start_end_position()
        left = min(start_x, end_x)
        up = min(start_y, end_y)
        painter.drawRect(left, up, abs(end_x - start_x), abs(end_y - start_y))

    def draw_triangle(self, painter):
        start_x, start_y, end_x, end_y = self.get_start_end_position()
        left = min(start_x, end_x)
        right = max(start_x, end_x)
        up = min(start_y, end_y)
        down = max(start_y, end_y)
        width = right - left
        left_up = left + width // 2
        right_up = left_up + (width % 2)
        painter.drawLine(left_up, up, left, down)
        painter.drawLine(right_up, up, right, down)
        painter.drawLine(left, down, right, down)

    def draw_ellipse(self, painter):
        start_x, start_y, end_x, end_y = self.get_start_end_position()
        left = min(start_x, end_x)
        up = min(start_y, end_y)
        painter.drawEllipse(left, up, abs(end_x - start_x), abs(end_y - start_y))

    def update_selection_position(self):
        start_x = self.shape_start[0] * self.pixel_size + self.canvas_left_side
        start_y = self.shape_start[1] * self.pixel_size + self.canvas_upper_side
        end_x = self.cursor_position[0] * self.pixel_size + self.canvas_left_side
        end_y = self.cursor_position[1] * self.pixel_size + self.canvas_upper_side
        self.selection_left = min(start_x, end_x)
        self.selection_right = max(start_x, end_x) + self.pixel_size
        self.selection_up = min(start_y, end_y)
        self.selection_down = max(start_y, end_y) + self.pixel_size
        self.selection_width = abs(self.cursor_position[0] - self.shape_start[0]) + 1
        self.selection_height = abs(self.cursor_position[1] - self.shape_start[1]) + 1

    def draw_selection(self, painter):
        width = self.pixel_size / 4
        black_pen = QPen(QColor(0, 0, 0))
        black_pen.setWidth(3)
        white_pen = QPen(QColor(255, 255, 255))
        white_pen.setWidth(3)
        painter.setPen(black_pen)
        for x in range(self.selection_width):
            painter.drawLine(self.selection_left + x * self.pixel_size,
                             self.selection_up, self.selection_left + x * self.pixel_size + width, self.selection_up)
            painter.drawLine(self.selection_left + x * self.pixel_size,
                             self.selection_down, self.selection_left + x * self.pixel_size + width, self.selection_down)
            painter.setPen(white_pen)
            painter.drawLine(self.selection_left + x * self.pixel_size + width,
                             self.selection_up, self.selection_left + x * self.pixel_size + width * 3, self.selection_up)
            painter.drawLine(self.selection_left + x * self.pixel_size + width,
                             self.selection_down, self.selection_left + x * self.pixel_size + width * 3, self.selection_down)
            painter.setPen(black_pen)
            painter.drawLine(self.selection_left + x * self.pixel_size + width * 3,
                             self.selection_up, self.selection_left + x * self.pixel_size + width * 4, self.selection_up)
            painter.drawLine(self.selection_left + x * self.pixel_size + width * 3,
                             self.selection_down, self.selection_left + x * self.pixel_size + width * 4, self.selection_down)
        for y in range(self.selection_height):
            painter.drawLine(self.selection_left, self.selection_up + y * self.pixel_size,
                             self.selection_left, self.selection_up + y * self.pixel_size + width)
            painter.drawLine(self.selection_right, self.selection_up + y * self.pixel_size,
                             self.selection_right, self.selection_up + y * self.pixel_size + width)
            painter.setPen(white_pen)
            painter.drawLine(self.selection_left, self.selection_up + y * self.pixel_size + width,
                             self.selection_left, self.selection_up + y * self.pixel_size + width * 3)
            painter.drawLine(self.selection_right, self.selection_up + y * self.pixel_size + width,
                             self.selection_right, self.selection_up + y * self.pixel_size + width * 3)
            painter.setPen(black_pen)
            painter.drawLine(self.selection_left, self.selection_up + y * self.pixel_size + width * 3,
                             self.selection_left, self.selection_up + y * self.pixel_size + width * 4)
            painter.drawLine(self.selection_right, self.selection_up + y * self.pixel_size + width * 3,
                             self.selection_right, self.selection_up + y * self.pixel_size + width * 4)

    def draw_pixels(self, painter):
        painter.drawImage(self.canvas_left_side, self.canvas_upper_side,
                          self.canvas_as_image.scaled(self.canvas_width, self.canvas_height))
        painter.setBrush(Qt.transparent)
        black_pen = QPen(QColor(0, 0, 0))
        black_pen.setWidth(3)
        painter.setPen(black_pen)
        painter.drawRect(self.canvas_left_side, self.canvas_upper_side, self.canvas_width, self.canvas_height)
        painter.setPen(Qt.black)
        self.draw_grid(painter)

    def draw_grid(self, painter):
        if self.pixel_size > 10:
            for i in range(self.canvas.width + 1):
                x = self.canvas_left_side + i * self.pixel_size
                painter.drawLine(x, self.canvas_upper_side,
                                 x, self.canvas_upper_side + self.canvas_height)
            for i in range(self.canvas.height + 1):
                y = self.canvas_upper_side + i * self.pixel_size
                painter.drawLine(self.canvas_left_side, y,
                                 self.canvas_left_side + self.canvas_width, y)

    def draw_edges(self, painter):
        painter.setPen(Qt.transparent)
        painter.setBrush(QColor('#393939'))
        painter.drawRect(self.vertical_scrollbar.x(), self.vertical_scrollbar.y(),
                         self.vertical_scrollbar.width(),
                         self.vertical_scrollbar.height() + self.horizontal_scrollbar.height() + 1)
        painter.drawRect(self.horizontal_scrollbar.x(), self.horizontal_scrollbar.y(),
                         self.horizontal_scrollbar.width(), self.horizontal_scrollbar.height() + 1)

    def draw_current_layer(self, painter):
        if not self.to_draw_canvas:
            return
        painter.setBrush(Qt.white)
        table = self.layer_tables[self.canvas.current_layer]
        painter.drawRect(table.x - 1, table.y - 1, LayerTable.WIDTH + 2, LayerTable.HEIGHT + 2)

    def draw_buttons(self, painter):
        painter.setPen(Qt.transparent)
        painter.setBrush(QColor(self.canvas.current_color.r, self.canvas.current_color.g,
                                self.canvas.current_color.b))
        for button, image in self.button_images.items():
            painter.drawRect(button.x() + 3, button.y() + 3, self.BUTTON_SIZE - 6, self.BUTTON_SIZE - 6)
            painter.drawImage(button.x(), button.y(), image.scaled(self.BUTTON_SIZE, self.BUTTON_SIZE))
Beispiel #6
0
class DollWidget(QWidget):
    def __init__(self, usbcom=None, target='0.0.0.0', port=0, name='Uno_Doll'):
        super(DollWidget, self).__init__()
        self.name = name
        self.usbcom = usbcom
        self.target = target
        self.port = port
        self.initUI()

    def setName(self, name):
        self.name = name

    def setValue(self, value):
        self.timeline.setValue(value)
        self.eyebrowLine.setValue(value)
        self.eyeLine.setValue(value)
        self.earLine.setValue(value)
        self.mouseLine.setValue(value)

    def setSlider(self, value):
        if value > 0.8 * self.relativeMaximum:
            self.relativeMaximum = 1.2 * self.relativeMaximum
        self.slider.setValue(int(100 * value / self.relativeMaximum))

    def initUI(self):
        self.mode = 0
        self.time = 0
        self.eyebrowEmotion = open('eyebrow.dqbe', 'w+')
        self.eyebrowEmotion.seek(0)
        self.eyeEmotion = open('eye.dqbe', 'w+')
        self.eyeEmotion.seek(0)
        self.earEmotion = open('ear.dqbe', 'w+')
        self.earEmotion.seek(0)
        self.mouseEmotion = open('mouse.dqbe', 'w+')
        self.mouseEmotion.seek(0)
        self.file = open('emoji.dqpe', 'a+')
        self.file.seek(0)
        '''mode 1 as play. mode 2 as record. mode 3 as stop. mode 4 as save.'''
        self.thisDoll = QCheckBox(self.name, self)
        self.eyebrow = QCheckBox('eyebrow', self)
        self.eye = QCheckBox('eye', self)
        self.ear = QCheckBox('ear', self)
        self.mouse = QCheckBox('mouse', self)
        self.playBtn = QPushButton('Play', self)
        self.recordBtn = QPushButton('Record', self)
        self.stopBtn = QPushButton('Stop', self)
        self.saveBtn = QPushButton('Save', self)
        self.timeline = TimeLine(scale=True)
        self.eyebrowLine = TimeLine(scale=False,
                                    emotionPool=self.eyebrowEmotion,
                                    types='eyebrow')
        self.eyeLine = TimeLine(scale=False,
                                emotionPool=self.eyeEmotion,
                                types='eye')
        self.earLine = TimeLine(scale=False,
                                emotionPool=self.earEmotion,
                                types='ear')
        self.mouseLine = TimeLine(scale=False,
                                  emotionPool=self.mouseEmotion,
                                  types='mouse')
        self.slider = QScrollBar(Qt.Horizontal)
        self.slider.setMinimum(0)
        self.slider.setMaximum(100)
        self.relativeMaximum = 15
        self.slider.setValue(0)
        self.slider.valueChanged.connect(self.valueChange)

        self.playBtn.clicked.connect(self.handlePlayBtn)
        self.stopBtn.clicked.connect(self.handleStopBtn)
        self.recordBtn.clicked.connect(self.handleRecordBtn)
        self.saveBtn.clicked.connect(self.handleSaveBtn)
        self.thisDoll.stateChanged.connect(
            lambda: self.handleCheck(self.thisDoll))

        dollcmd.setComPort(self.usbcom)

        #UI
        layout = QGridLayout(self)
        layout.addWidget(self.playBtn, 0, 0, 1, 1)
        layout.addWidget(self.recordBtn, 0, 1, 1, 1)
        layout.addWidget(self.stopBtn, 0, 2, 1, 1)
        layout.addWidget(self.saveBtn, 0, 3, 1, 1)

        layout.addWidget(self.thisDoll, 1, 0, 1, 1)
        layout.addWidget(self.eyebrow, 2, 1, 1, 1)
        layout.addWidget(self.eye, 3, 1, 1, 1)
        layout.addWidget(self.ear, 4, 1, 1, 1)
        layout.addWidget(self.mouse, 5, 1, 1, 1)

        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        self.scrollContent = QWidget(scroll)

        scrollLayout = QVBoxLayout(self.scrollContent)
        self.scrollContent.setLayout(scrollLayout)
        scrollLayout.addWidget(self.timeline)
        scrollLayout.addWidget(self.eyebrowLine)
        scrollLayout.addWidget(self.eyeLine)
        scrollLayout.addWidget(self.earLine)
        scrollLayout.addWidget(self.mouseLine)
        scroll.setWidget(self.scrollContent)
        layout.addWidget(self.slider, 0, 4, 1, 7)
        layout.addWidget(self.scrollContent, 1, 4, 5, 7)
        self.show()

    def valueChange(self):
        s = self.slider.value()
        value = (s * self.relativeMaximum * 0.01)
        self.setValue(value)
        if self.mode != 1 and self.mode != 2 and self.mode != 4:
            self.time = value * 20

    def handleCheck(self, this):
        if this.isChecked():
            state = Qt.Checked
        else:
            state = Qt.Unchecked
        self.eye.setCheckState(state)
        self.eyebrow.setCheckState(state)
        self.ear.setCheckState(state)
        self.mouse.setCheckState(state)

    def handlePlayBtn(self):
        self.mode = 1
        self.handleIO()

    def handleStopBtn(self):
        self.mode = 3

    def handleRecordBtn(self):
        self.mode = 2
        self.handleIO()

    def handleSaveBtn(self):
        self.mode = 4
        self.handleIO()
        '''
        eyebrow and eye 
        jd1[0] 1023 = left, 0 = right
        jd1[1] 1023 = up. , 0 = down

        ear
        1023. = up, 0 = down

        '''

    def handleIO(self):
        if self.mode == 1:
            data = self.file.readline()
            #dollcmd.sendUDP()
            self.time += 1
            self.setValue(self.time * 0.05)
            self.setSlider(self.time * 0.05)
            QTimer.singleShot(50, self.handleIO)
        if self.mode == 2:
            data = dollcmd.handleIOData()
            self.file.write(data)
            #dollcmd.sendUDP(data)
            if '\n' in data:
                self.eyebrowEmotion.seek(self.time * 12)
                self.eyeEmotion.seek(self.time * 12)
                self.earEmotion.seek(self.time * 12)
                self.mouseEmotion.seek(self.time * 12)
                lists = data.replace('\n', '').split(',')
                #ear
                if int(lists[0]) > 512: i = 0
                else: i = 1
                i *= 3
                if int(lists[1]) > 512: i += 0
                else: i += 1
                self.earEmotion.write('{}@{}\n'.format(
                    str(self.time).zfill(8), str(i)))
                #ear
                #eyebrow
                if int(lists[2]) > 682: i = 0
                elif int(lists[2]) > 341: i = 1
                else: i = 2
                i *= 3
                if int(lists[3]) > 682: i += 0
                elif int(lists[3]) > 341: i += 1
                else: i += 2
                self.eyebrowEmotion.write('{}@{}\n'.format(
                    str(self.time).zfill(8), str(i)))
                #eyebrow
                #eye
                if int(lists[6]) > 682: i = 0
                elif int(lists[6]) > 341: i = 1
                else: i = 2
                i *= 3
                if int(lists[7]) > 682: i += 0
                elif int(lists[7]) > 341: i += 1
                else: i += 2
                self.eyeEmotion.write('{}@{}\n'.format(
                    str(self.time).zfill(8), str(i)))
                #eye
                #mouse
                if int(lists[10]) > 682: i = 0
                elif int(lists[10]) > 341: i = 1
                else: i = 2
                i *= 3
                if int(lists[11]) > 682: i += 0
                elif int(lists[11]) > 341: i += 1
                else: i += 2
                self.mouseEmotion.write('{}@{}\n'.format(
                    str(self.time).zfill(8), str(i)))
                #mouse
            self.time += 1
            self.setValue(self.time * 0.05)
            self.setSlider(self.time * 0.05)
            QTimer.singleShot(50, self.handleIO)
        if self.mode == 3:
            pass
        if self.mode == 4:
            pass

    def mousePressEvent(self, event):
        pass

    def mouseMoveEvent(self, event):
        pass
class dicomImage2DdisplayWidget(QWidget):
    addSeedsSignal = pyqtSignal(bool)
    def __init__(self, **kwargs):
        super(dicomImage2DdisplayWidget, self).__init__()
        self._face = kwargs.get('face', 0)
        self._datas = kwargs.get('datas', 0)
        self._Spacing = kwargs.get('spacing', None)
        self._low_hu = kwargs.get("low_hu", -1150)
        self._high_hu = kwargs.get("high_hu", 3250)
        self._axis = 0
        #===============Seeds information============================
        self.seedsColors = []
        self.baseImageSize = 512
        self.regionDrawMod = 0
        self.drawLayer = []

        #===============Regioin draw tool parmeter===================
        self.drawPanterbegin = QPoint()
        self.drawPanterEnd = QPoint()
        self.posX = 0
        self.posY = 0

        #===============Init UI======================================
        self.initUI()


    def initUI(self):
        self.setGeometry(0, 0, self.baseImageSize, self.baseImageSize)

        self.viewLayout = None
        self.imLable = QLabel(self)
        self.imLable.setScaledContents(True)
        self.imData = None

        self.topLable = QLabel(self)
        self.downLable = QLabel(self)
        self.imLable.resize(self.width(), self.height())

        self.initDicomParameter()
        pass

    def initDicomParameter(self):
        #============================SetDataParameter===========================
        self._color_table = [qRgb(i, i, i) for i in range(64)]
        self.datas = self._datas.copy()
        self.faceWindowV = self.faceWindowH = max(self.datas.shape)

        #============================ChangeFaceSize=============================
        self.xSpacing, self.ySpacing, self.zSpacing = self._Spacing

        #============================OperationMod===============================
        self.OperationMod = 0
        self.facePlane = ['mainFaceplane', 'leftFaceplane', 'frontFaceplane']
        self.idxSlice = 100

        self.currentFace = self.facePlane[self._face]
        #============================RegionGrowingParameter=====================
        self.PosXY = [150, 75]
        # self.seedList = [(self.PosXY[0], self.PosXY[1])]
        self.seedList = []

        self.seedSelectNum = 0

        self.LowAndUpper = [10, 3000]
        self.regionArea = []
        self.regionDrawSize = 5

        self.idxSlicelimt = self.datas.shape[0]
        # print(self.datas.shape[0])
        #=======================================================================
        self.initOperationButton()
        self.initDisplayfacePlane()
        self.choiceOpreationMod()

        pass

    def initOperationButton(self):
        self.facePlanes = QComboBox(self)
        self.facePlanes.addItem(self.facePlane[0])
        self.facePlanes.addItem(self.facePlane[1])
        self.facePlanes.addItem(self.facePlane[2])
        self.facePlanes.setCurrentIndex(self._face)
        # self.facePlanes.activated[str].connect(self.faceItem_Choice)
        self.facePlanes.currentTextChanged.connect(self.faceItem_Choice)
        self.facePlanes.keyPressEvent = self.customComboxKeyEvent
        self.facePlanes.move((self.width() - self.facePlanes.width()), 0)

        #==================================Active keyBoard event without combobox=======================
        # shorcut = QShortcut(QKeySequence(Qt.Key_F), self.facePlanes, activated=self.useforTestKeyEvent)
        #===============================================================================================

        #================================== Contrul region seed up and low range =======================
        regionWide = QRangeSlider(self)
        regionWide.setMax(255)
        regionWide.setMin(0)
        regionWide.setStart(150)
        regionWide.setEnd(255)
        regionWide.setRange(0, 255)
        regionWide.setDrawValues(True)
        regionWide.setBackgroundStyle('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #222, stop:1 #333);')
        regionWide.handle.setStyleSheet('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #8EE5EE, stop:1 #393);')
        regionWide.startValueChanged.connect(self.rangeSliderStartVolue)
        regionWide.endValueChanged.connect(self.rangeSliderEndVolue)
        #===============================================================================================

        self.modCombox = QComboBox(self)
        self.modCombox.addItem('Normal')
        self.modCombox.addItem('Region')
        self.modCombox.setCurrentIndex(self.OperationMod)
        # self.modCombox.activated[str].connect(self.mod_Choice)
        self.modCombox.currentTextChanged.connect(self.mod_Choice)
        self.modCombox.keyPressEvent = self.customComboxKeyEvent
        self.modCombox.move((self.width() - self.facePlanes.width() - self.modCombox.width()), 0)

        self.layerScrollBar = QScrollBar(Qt.Horizontal, self)
        self.layerScrollBar.setGeometry(0, 0, 128, 5)
        self.layerScrollBar.setMinimum(0)
        self.layerScrollBar.setMaximum(min(self.datas.shape))
        self.layerScrollBar.setValue(0)
        self.layerScrollBar.sliderMoved.connect(self.selectLayer)

        self.BaseBoxLayout = QBoxLayout(QBoxLayout.TopToBottom)
        self.BaseBoxLayout.addWidget(self.layerScrollBar, 0)
        self.BaseBoxLayout.addWidget(regionWide, 1)
        self.BaseBoxLayout.setAlignment(Qt.AlignTop)


        self.secondBoxLayout = QBoxLayout(QBoxLayout.LeftToRight)
        self.secondBoxLayout.addLayout(self.BaseBoxLayout)
        self.secondBoxLayout.addWidget(self.modCombox)
        self.secondBoxLayout.addWidget(self.facePlanes)
        self.secondBoxLayout.setAlignment(Qt.AlignTop)

        self.groupbox = QGroupBox(self)
        self.groupbox.setGeometry(28, -64, 512, 64)
        self.groupbox.setLayout(self.secondBoxLayout)

        self.showButton = QPushButton(self)
        self.showButton.setGeometry(0, 0, 16, 16)
        self.showButton.clicked.connect(self.playAnimation)


        self.initAnimation()
        pass

    def setGroup_pos(self, apos):
        self.groupbox.move(apos.x(), apos.y())
        pass

    def setSeedsColor(self, lists):

        # self.seedList.clear()
        # self.seedsColors.clear()
        # for i in range(0, len(colorList)):
        #     self.seedsColors.append(colorList[i][0])
        #     self.seedList.append(colorList[i][1])
        self.seedsColors.append(lists[0])
        self.seedList.append(lists[1])
        print('seedList:', self.seedList)

        pass

    def selectSeedinList(self, num):
        # tmpS = self.seedList[num]
        # tmpC = self.seedsColors[num]
        self.seedSelectNum = num
        # print(self.seedsColors)
        # print(self.seedList)
        # print('number is :', num)
        # print(tmpC, tmpS)
        pass

    def removeSeedinList(self, num):
        self.seedList.remove(self.seedList[num])
        self.choiceDisplayMod()
        pass

    def rangeSliderStartVolue(self, event):
        self.LowAndUpper[0] = event
        self.choiceDisplayMod()
        pass

    def rangeSliderEndVolue(self, event):
        self.LowAndUpper[1] = event
        self.choiceDisplayMod()
        pass

    def viewSeedinList(self, event):
        if event[0] == True:
            print('Open eye is:', event[1])
        elif event[0] == False:
            print('Close eye is:', event[1])
        else:
            print('viewSeedinList error.....')

        pass

    def initAnimation(self):
        self.isBoardshow = False
        xAxis = self.groupbox.pos().x()
        yAxis = self.groupbox.height()

        self.groupBoxAnim = QPropertyAnimation(self, b'pos')
        self.groupBoxAnim.setDuration(200)
        self.groupBoxAnim.setStartValue(QPointF(xAxis, -yAxis))
        # self.anim.setKeyValueAt(0.5, QPointF(0, 10))
        # self.anim.setKeyValueAt(0.8, QPointF(0, 80))
        self.groupBoxAnim.setEndValue(QPointF(xAxis, 0))

        self.reverGroupBoxAnim = QPropertyAnimation(self, b'pos')
        self.reverGroupBoxAnim.setDuration(200)
        self.reverGroupBoxAnim.setStartValue(QPointF(xAxis, 0))
        self.reverGroupBoxAnim.setEndValue(QPointF(xAxis, -yAxis))

        pass

    def playAnimation(self):
        print('-----PlayAnimation-----')
        if self.isBoardshow == False:
            self.reverGroupBoxAnim.stop()
            self.groupBoxAnim.start()
            self.isBoardshow = True
        elif self.isBoardshow == True:
            self.groupBoxAnim.stop()
            self.reverGroupBoxAnim.start()
            self.isBoardshow = False
        pass
    pos = pyqtProperty(QPointF, fset=setGroup_pos)

    def selectLayer(self, event):
        self.idxSlice = self.layerScrollBar.value()
        self.choiceDisplayMod()
        pass

    def sliderval(self):
        self._low_hu = self.lowHusBar.value()
        self._high_hu = self.heighHusBar.value()
        self.choiceDisplayMod()
        pass

    def mod_Choice(self, event):
        if event == 'Normal':
            self.OperationMod = 0
        elif event == 'Region':
            self.OperationMod = 1
        self.choiceOpreationMod()
        pass

    def initDisplayfacePlane(self):
        if self._face == 0:
            self.topfaceView()
        elif self._face == 1:
            self.leftfaceView()
        elif self._face == 2:
            self.frontfaceView()
        pass


    def faceItem_Choice(self, faceEvent):

        if faceEvent == self.facePlane[0]:
            self.topfaceView()
            self.currentFace = self.facePlane[0]
            print('main view')
        elif faceEvent == self.facePlane[1]:
            self.leftfaceView()
            self.currentFace = self.facePlane[1]
            print('left view')
        elif faceEvent == self.facePlane[2]:
            self.frontfaceView()
            self.currentFace = self.facePlane[2]
            print('front view')

        self.choiceOpreationMod()
        self.getResizeEvent(self.width(), self.height())
        pass

    #==========================MakeSureDisplayMod=============================
    def choiceDisplayMod(self):
        if self.OperationMod == 0:
            self.drawNomralArea()
        elif self.OperationMod == 1:
            self.drawGrowingArea()
        pass
    #=========================================================================

    def choiceOpreationMod(self):
        if self.OperationMod == 0:
            self.imLable.mouseMoveEvent = self.normalModMouseMoveEvent
        elif self.OperationMod == 1:
            self.imLable.mouseMoveEvent = self.regionModMouseMoveEvent
            self.imLable.mousePressEvent = self.regionModMousePressEvent
            self.imLable.mouseReleaseEvent = self.regionModMouseReleasedEvent

            self.imLable.wheelEvent = self.regionGrowingWheelEvent
        self.choiceDisplayMod()
        pass



    def topfaceView(self):
        self.datas = self._datas.copy()
        self.idxSlicelimt = self.datas.shape[0]
        self.faceWindowH = self.faceWindowV = self.width()
        tmpPalete = QPalette()
        tmpPalete.setColor(QPalette.Background, QColor(0, 0, 0))
        self.setPalette(tmpPalete)
        #=======================Init drawLayer===================
        self.drawLayer = np.full(self.datas.shape, 0)
        print('topfaceView:', self.drawLayer.shape)

        pass

    def leftfaceView(self):

        self.datas = self._datas.copy()
        self.datas = np.rot90(self.datas, -1)
        self.datas = np.rot90(self.datas,  axes=(0, 2))
        self.idxSlicelimt = self.datas.shape[0]

        self.setScaleSize(max(self.datas.shape), min(self.datas.shape))

        tmpPalete = QPalette()
        tmpPalete.setColor(QPalette.Background, QColor(0, 0, 0))
        self.setPalette(tmpPalete)

        #=======================Init drawLayer===================
        self.drawLayer = np.full(self.datas.shape, 0)
        print('leftfaceView:', self.drawLayer.shape)

        pass


    def frontfaceView(self):
        self.datas = self._datas.copy()
        self.datas = np.rot90(self.datas, -1)
        self.idxSlicelimt = self.datas.shape[0]

        width = self.datas.shape[0]
        height = self.datas.shape[1]
        depth = self.datas.shape[2]
        self.setScaleSize(max(width, height, depth), min(width, height, depth))

        tmpPalete = QPalette()
        tmpPalete.setColor(QPalette.Background, QColor(0, 0, 0))
        self.setPalette(tmpPalete)

        #=======================Init drawLayer===================
        self.drawLayer = np.full(self.datas.shape, 0)
        print('frontfaceView:', self.drawLayer.shape)

        pass

    def drawNomralArea(self):
        self.idxSlice = np.clip(self.idxSlice, 0, self.idxSlicelimt -1)
        self.imData = self.datas[self.idxSlice]
        self.displayDicomImage()
        pass

    def drawGrowingArea(self):
        self.imgOriginal = SimpleITK.GetImageFromArray(self.datas[self.idxSlice])
        self.imgWhiteMatter = SimpleITK.ConnectedThreshold(image1=self.imgOriginal,
                                                           seedList=self.seedList,
                                                           lower=self.LowAndUpper[0],
                                                           upper=self.LowAndUpper[1],
                                                           replaceValue=1,
                                                           )
        self.regionArea = SimpleITK.GetArrayFromImage(self.imgWhiteMatter)

        #================if use draw or eraser====================
        if np.sum(self.drawLayer[self.idxSlice] != 0) != 0:
            self.regionDrawLayerCombinEvent()

        self.drawGrowingAreaContour()
        pass

    def drawGrowingAreaContour(self):
        foreColorvalue = 1
        self.imgWhiteMatter = SimpleITK.GetImageFromArray(self.regionArea)
        self.imgWhiteMatterNoHoles = SimpleITK.VotingBinaryHoleFilling(image1=self.imgWhiteMatter,
                                                                       radius=[2] * 3,
                                                                       majorityThreshold=50,
                                                                       backgroundValue=0,
                                                                       foregroundValue=foreColorvalue)
        regionContour = SimpleITK.LabelContour(self.imgWhiteMatterNoHoles)
        # tmpWmatter = self.imgWhiteMatter
        # regionContour = tmpWmatter | regionContour
        tmpImage = SimpleITK.LabelOverlay(self.imgOriginal, regionContour)
        regionContourArray = SimpleITK.GetArrayFromImage(tmpImage)
        self.imData = regionContourArray
        self.displayDicomImage()

        pass

    #==============================Key board event ============================================
    def customComboxKeyEvent(self, event):
        print('ComboxKeyEvent')
        pass

    def useforTestKeyEvent(self):
        print('just test combobox key event')
        # self.displayDicomImage()
        pass


    #==============================Use for display dicom image=================================
    def displayDicomImage(self):
        if self.imData is not None:
            raw_data = self.imData
            shape = self.imData.shape
            # maxNum = max(shape)
            # minNum = min(shape)
            raw_data[raw_data < 0] = 0
            raw_data[raw_data > 255] = 255
            if len(shape) >= 3:
                data = raw_data
                #=================用于调节对比度的方法=======================
                # data = (raw_data - self._low_hu) / self.window_width * 256
                # print('---------Update3d--------')
                #===========================================================
                data = data.astype(np.int8)
                tmpImage = QImage(data, shape[1], shape[0], shape[1] * shape[2], QImage.Format_RGB888)
                pixmap = QPixmap.fromImage(tmpImage)
                # pixmap = pixmap.scaled(self.faceWindowH , self.faceWindowV )
                # pixmap = pixmap.scaled(self.xSpacing, self.zSpacing)
                # pixmap = pixmap.scaled(1024, 128)
                self.imLable.setPixmap(pixmap)
            elif len(shape) < 3:
                data = raw_data
                # data = (raw_data - self._low_hu) / self.window_width * 256
                # print('---------Update2d---------')
                data = data.astype(np.int8)
                tmpImage = QImage(data, shape[1], shape[0],  QImage.Format_Grayscale8)
                tmpImage.setColorTable(self._color_table)
                pixmap = QPixmap.fromImage(tmpImage)
                # pixmap = pixmap.scaled(self.faceWindowH, self.faceWindowV)
                # pixmap = pixmap.scaled(self.xSpacing, self.zSpacing)
                # pixmap = pixmap.scaled(1024, 128)
                self.imLable.setPixmap(pixmap)
        pass

    def normalModMouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            xAxis = event.pos().x()
            yAxis = event.pos().y()
        self.choiceDisplayMod()
        pass

#=============================Region draw layer operation==========================================
    def regionDrawLayerEvent(self, x, y, value):
        self.regionArea[y - self.regionDrawSize:y + self.regionDrawSize, x - self.regionDrawSize:x + self.regionDrawSize] = value
        self.drawLayer[self.idxSlice] = self.regionArea
        pass

    def regionDrawLayerCombinEvent(self):
        self.regionArea = self.drawLayer[self.idxSlice].astype(np.uint8)
        pass

#=============================Region mod mouse Press and released event============================
    def regionModMousePressEvent(self, event):

        if event.buttons() == Qt.LeftButton and self.regionDrawMod != 0:
            xAxis = event.pos().x()
            yAxis = event.pos().y()
            if xAxis >= 0 and yAxis >= 0:
                tmpX = math.floor(xAxis * (self.baseImageSize / self.imLable.width()))
                tmpY = math.floor(yAxis * (self.baseImageSize / self.imLable.height()))
                if self.regionDrawMod == 1:
                    self.regionDrawLayerEvent(tmpX, tmpY, 1)
                elif self.regionDrawMod == 2:
                    self.regionDrawLayerEvent(tmpX, tmpY, 0)
            self.drawGrowingAreaContour()

        pass

    def regionModMouseReleasedEvent(self, Event):
        if Event.buttons() == Qt.RightButton:
            print('Right button released')
        pass
#==================================================================================================

#=====================================Region mod mouse move event==================================
    def regionModMouseMoveEvent(self, event):
        self.posX = event.pos().x()
        self.posY = event.pos().y()
        if event.buttons() == Qt.LeftButton and self.regionDrawMod == 0:
            if self.regionDrawMod == 0:
                xAxis = event.pos().x()
                yAxis = event.pos().y()
                if xAxis >= 0 and yAxis >= 0:
                    self.PosXY[0] = math.floor(xAxis * (self.baseImageSize / self.imLable.width()))
                    self.PosXY[1] = math.floor(yAxis * (self.baseImageSize / self.imLable.height()))
                    self.seedList[self.seedSelectNum] = (self.PosXY[0], self.PosXY[1])
                else:
                    print('Region Mod has Nagtive number')
        elif event.buttons() == Qt.LeftButton and self.regionDrawMod != 0:
            xAxis = event.pos().x()
            yAxis = event.pos().y()
            if xAxis >= 0 and yAxis >= 0:
                tmpX = math.floor(xAxis * (self.baseImageSize / self.imLable.width()))
                tmpY = math.floor(yAxis * (self.baseImageSize / self.imLable.height()))
                if self.regionDrawMod == 1:
                    self.regionDrawLayerEvent(tmpX, tmpY, 1)
                elif self.regionDrawMod == 2:
                    self.regionDrawLayerEvent(tmpX, tmpY, 0)
                else:
                    print('regionModMouseMoveEvent regionDrawMod error......')
                    return
            self.drawGrowingAreaContour()
            return
        else:
            print('regionModMouseMoveEvent error......')
        self.choiceDisplayMod()
        pass

#=================================SetWindowSizeEvent==========================================
    def setScaleSize(self, maxnum, minnum):
        self.faceWindowH = maxnum
        self.faceWindowV = minnum * (max(self.xSpacing, self.ySpacing, self.zSpacing) / min(self.xSpacing, self.ySpacing, self.zSpacing))
        pass

    def getResizeEvent(self, sizeX, sizeY):
        if self.currentFace == self.facePlane[0]:
            tmpSize = min(sizeX, sizeY)
            self.imLable.resize(tmpSize, tmpSize)

        elif self.currentFace == self.facePlane[1]:
            #==================Resize Lable===================
            self.setScaleSize(min(sizeX, sizeY), min(sizeX, sizeY) * (min(self.datas.shape)/max(self.datas.shape)))
            self.imLable.resize(self.faceWindowH, self.faceWindowV)

        elif self.currentFace == self.facePlane[2]:
            self.setScaleSize(min(sizeX, sizeY), min(sizeX, sizeY) * (min(self.datas.shape) / max(self.datas.shape)))
            self.imLable.resize(self.faceWindowH, self.faceWindowV)

        #==================Move Lable=====================
        maxPosY = max(sizeY, self.imLable.height())
        minPoxY = min(sizeY, self.imLable.height())
        tmpPosX = np.clip((sizeX - sizeY), 0, max(sizeX, sizeY)) / 2
        tmpPosY = (maxPosY - minPoxY) / 2
        self.imLable.move(tmpPosX, tmpPosY)
        pass


#===========================mousewheelEvent==================================
    def regionGrowingWheelEvent(self, event):
        angle = event.angleDelta() / 8
        angleX = angle.x()
        angleY = angle.y()

        if angleY > 0:
            self.regionDrawSize -= 1
        elif angleY < 0:
            self.regionDrawSize += 1
        pass

#==========================RegionDrawMod=====================
    def setRegionDrawMod(self, event):
        if event == 0:
            self.regionDrawMod = 0
        elif event == 1:
            self.regionDrawMod = 1
        elif event == 2:
            self.regionDrawMod = 2
        else:
            print('setRegionDrawMod error....')
        pass

#====================Use for paint or eraser====================
    def paintEvent(self, QPaintEvent):
        pen1 = QPen(Qt.blue, 1)
        q = QPainter(self)
        q.setPen(pen1)
        q.drawRect(self.posX - 25, self.posY - 25, 50, 50)
        # print('paintEvent')
        pass


    @property
    def window_width(self):
        return self._high_hu - self._low_hu





#=======================================================================================================================
# pathDicom = "D:/Dicomfile/MT_07/"
# idxSlice = 50
# reader = SimpleITK.ImageSeriesReader()
# filenamesDICOM = reader.GetGDCMSeriesFileNames(pathDicom)
#
# reader.SetFileNames(filenamesDICOM)
# imgOriginals = reader.Execute()
# datas = SimpleITK.GetArrayFromImage(imgOriginals)
# Spacing = imgOriginals.GetSpacing()
#
# if __name__ == '__main__':
#     app = QApplication(sys.argv)
#     win = dicomImage2DdisplayWidget(face=0, datas= datas, spacing=Spacing)
#     win.show()
#     sys.exit(app.exec_())
class MainUi(QMainWindow):
    obj_num = 0
    container = {}
    
    def __init__(self, info):
        super(MainUi, self).__init__()
        self.icon = [ico for ico in info]
        self.column = len(self.icon)
        self.num = 10  # 界面头部展示模块数量
        self.init_ui()
    
    def init_ui(self):
        self.setWindowIcon(QIcon('index.ico'))
        self.setWindowTitle("工具")
        self.resize(960, 600)
        self.statusBar().show()
        self._center()
        self.main_widget = QWidget()  # 创建窗口主部件
        self.main_layout = QGridLayout()  # 创建主部件的网格布局
        self.main_widget.setLayout(self.main_layout)  # 设置窗口主部件布局为网格布局
        
        # 创建上侧部件
        self.up_widget = QWidget()
        self.up_widget.setObjectName('up_widget')
        self.up_widget.setFixedHeight(80)
        self.up_layout = QGridLayout()
        self.up_widget.setLayout(self.up_layout)
        
        # 创建滚动条
        self.slide = QScrollBar(True)
        self.slide.setObjectName('slide_roll_bar')
        self.slide.setFixedHeight(const.SLIDE_HEIGHT)
        self.slide.setMaximum(self.column)
        self.slide.setMinimum(self.num)
        self.slide.valueChanged.connect(self._value_change)
        
        # 创建日志记录
        # ************************************************##
        name = "Analysis"
        self.notice_btn = QPushButton(name)
        self.notice_btn.setObjectName(name)
        self.container["selectedNoticeName"] = name
        self.notice_btn.setFixedSize(const.NOTICE_WIDTH, const.BTN_HEIGHT)
        self.notice_btn.clicked.connect(self._clicked)
        
        self.notice_close_btn = QPushButton("✘")
        self.notice_close_btn.setObjectName("close_btn")
        self.notice_close_btn.setFixedSize(30, 30)
        self.notice_close_btn.setStyleSheet(
            """#close_btn{
                    background:red;
                    border:none;
                    margin-bottom: 20px;
                    margin-left: 20px;
                }
                #close_btn:hover{
                background:white;
            }
            """
        )
        self.notice_btn.setStyleSheet("""
            #Analysis:hover#close_btn {
                background:red;
            }
        """)
        self.close_layout = QGridLayout()
        self.close_layout.addWidget(self.notice_close_btn)
        self.close_layout.setAlignment(Qt.AlignAbsolute|Qt.AlignRight)
        self.close_layout.setSpacing(0)
        self.notice_btn.setLayout(self.close_layout)
        # self.notice_btn.set(self.notice_close_btn)
        # ************************************************##
        # 创建中侧部件
        self.mid_widget = QWidget()
        self.mid_widget.setObjectName('mid_widget')
        # self.mid_widget.setFixedHeight(400)
        self.mid_layout = QGridLayout()
        self.mid_widget.setLayout(self.mid_layout)
        
        # 创建下侧部件
        self.down_widget = QWidget()
        self.down_widget.setObjectName('down_widget')
        self.down_widget.setFixedHeight(60)
        self.down_layout = QGridLayout()
        self.down_widget.setLayout(self.down_layout)
        
        self.main_layout.addWidget(self.up_widget, 0, 0, 1, self.column)
        self.main_layout.addWidget(self.slide, 1, 0, 1, self.column)
        self.main_layout.addWidget(self.notice_btn, 2, 0, 1, 1)
        self.main_layout.addWidget(self.mid_widget, 3, 1, 1, self.column - 1)
        self.main_layout.addWidget(self.down_widget, 4, self.column - 1, 1, 1)
        self.setCentralWidget(self.main_widget)
        
        # 生成analysis
        analysis = Analysis(self, name)
        self.container[name] = {"noticeName": name, "modelObj": analysis, "index": self.obj_num}
        self.container["selectedModelName"] = name
        
        # 创建头部(head)
        self.head_widget = QWidget()
        self.head_layout = QGridLayout()
        self.head_widget.setLayout(self.head_layout)
        
        self.load_model_ico(0, self.num) if self.num < self.column else self.load_model_ico(0, self.column)
        self.up_layout.addWidget(self.head_widget, 0, 0, 0, 0)
        # 创建中部
        
        # 创建尾部 按钮
        self.tail_btn = QPushButton("Execute")
        self.tail_btn.setObjectName('execute')
        self.tail_btn.setFixedSize(const.TAIL_HEIGHT, const.BTN_HEIGHT)
        self.tail_btn.clicked.connect(self.run)
        
        self.down_layout.addWidget(self.tail_btn, 0, 0, 0, 0)
        self.down_layout.setAlignment(Qt.AlignRight)
        # 展示进度条
        self.progressBar = QProgressBar()
        self.progressBar.setFixedHeight(10)
        self.progressBar.setMaximum(const.HUNDRED)
        
        label = QLabel()
        label.setText("运行进度:")
        self.statusBar().addPermanentWidget(label)
        self.statusBar().addPermanentWidget(self.progressBar)
        self.main_layout.setSpacing(const.ZERO)
        
        set_style(self)
        # self.setWindowFlag(Qt.FramelessWindowHint)  # 隐藏边框
        # self.setWindowOpacity(0.9)  # 设置窗口透明度
        # self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明
    
    def run(self):
        mode_name = self.container.get("selectedModelName", "")
        mode_info = self.container.get(mode_name, {})
        mode = mode_info.get("modelObj")
        if not mode:
            print("error %s" % mode)
            return
        try:
            mode.run()
        except:
            self.set_progress()
            traceback.print_exc()
    
    def set_progress(self):
        self.tail_btn.setEnabled(True)
    
    def load_model_ico(self, start, end):
        for i in range(start, end):
            self.tool_btn = QToolButton()
            self.tool_btn.setText(f"{self.icon[i]}")  # 设置按钮文本
            self.tool_btn.setObjectName(f"{self.icon[i]}")  # 设置按钮文本
            self.tool_btn.setFixedSize(85, 52)
            # self.tool_btn.setFixedHeight(85)
            self.tool_btn.setIcon(qtawesome.icon(f'fa.{self.icon[i]}', color='white'))  # 设置按钮图标
            self.tool_btn.setIconSize(QSize(const.ICO_SIZE, const.ICO_SIZE))  # 设置图标大小
            self.tool_btn.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
            self.tool_btn.clicked.connect(self._clicked)
            
            self.head_layout.addWidget(self.tool_btn, 0, i, 1, 1)
    
    def info_btn(self, name):
        notice_btn = QPushButton(name)
        notice_btn.setObjectName(f"{name}_{self.obj_num}")
        notice_btn.setFixedSize(const.NOTICE_WIDTH, const.BTN_HEIGHT)
        self.container[name]["noticeName"] = f"{name}_{self.obj_num}"
        notice_btn.clicked.connect(self._clicked)
        
        self.main_layout.addWidget(notice_btn, 2, self.obj_num, 1, 1)
    
    def _clicked(self):
        model_name = self.sender().text()
        if model_name == self.container.get("selectedModelName"):
            self.show_widget(model_name)
            return  # message.info()
        self.statusBar().showMessage(f'Current Value is {model_name}')
        model_info = self.container.get(model_name, {})
        if not model_info:
            mode = None
            try:
                mode = ObjFactory.create(self, model_name)
            except:
                traceback.print_exc()
                # return  # message.info()
            if mode is None:
                set_mid_widget_background_style(self.mid_widget, False)
                self.show_widget(model_name)
                print("failed")
                return  # message.info()
            model_info["modelObj"] = mode
            self.obj_num += 1
            model_info["index"] = self.obj_num
            self.container[model_name] = model_info
            self.info_btn(model_name)
        self.show_widget(model_name)
        self.show()
    
    @staticmethod
    def del_layout(layout):
        for i in range(layout.count()):
            layout.itemAt(i).widget().deleteLater()
    
    def show_widget(self, curr_mode_name):
        previous_name = self.container.get("selectedModelName")
        if previous_name is not None:
            index = self.container.get(previous_name).get("index")
            if index is not None:
                self.mid_layout.itemAt(index).widget().close()
        index = self.container.get(curr_mode_name, {}).get("index")
        if index is None:
            set_ico_style(self.head_widget, curr_mode_name)
            self.show_notice_widget(curr_mode_name)
            return
        self.mid_layout.itemAt(index).widget().show()
        self.show_notice_widget(curr_mode_name)
        set_mid_widget_background_style(self.mid_widget)
        set_ico_style(self.head_widget, curr_mode_name)
        self.container["selectedModelName"] = curr_mode_name
        print(f"当前Container:{self.container}")
        print(f"当前选中模块:{curr_mode_name}")
    
    def show_notice_widget(self, model_name):
        curr_notice_name = self.container.get(model_name, {}).get("noticeName", "failed-model")
        args = []
        for key, item in self.container.items():
            if not isinstance(item, dict):
                continue
            elif key == model_name:
                continue
            else:
                args.append(item.get("noticeName"))
        args.append(curr_notice_name)
        set_notice_style(self.main_widget, tuple(args))
        
        self.container["selectedNoticeName"] = curr_notice_name
    
    def _value_change(self):
        value = self.slide.value()
        start = value - self.num
        self.statusBar().showMessage(f'Current Value is {value}')
        self.del_layout(self.head_layout)
        self.load_model_ico(start, value)
    
    def paintEvent(self, event):
        # 设置背景颜色
        painter = QPainter(self)
        background_color = QColor()
        background_color.setNamedColor('#006CAB')
        painter.setBrush(background_color)
        painter.drawRect(self.rect())
    
    def _center(self):
        # 窗口居中
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 2)
Beispiel #9
0
class MainUi(QMainWindow):
    def __init__(self):
        super(MainUi, self).__init__()
        self.icon = [
            'forward', 'sellsy', 'film', 'home', 'download', 'heart',
            'comment', 'star', 'question', 'music', 'pause', 'backward'
        ]
        self.column = len(self.icon)
        self.num = 10  # 界面头部展示模块数量
        self.row = 5
        self.init_ui()

    def init_ui(self):
        self.setWindowIcon(QIcon('./img/index.ico'))
        self.setWindowTitle("工具")
        # self.setFixedSize(960, 700)
        self.resize(960, 700)
        # self._center()
        self.main_widget = QWidget()  # 创建窗口主部件
        self.main_layout = QGridLayout()  # 创建主部件的网格布局
        self.main_widget.setLayout(self.main_layout)  # 设置窗口主部件布局为网格布局

        # 创建上侧部件
        self.up_widget = QWidget()
        self.up_widget.setObjectName('up_widget')
        self.up_widget.setFixedHeight(80)
        self.up_layout = QGridLayout()
        self.up_widget.setLayout(self.up_layout)
        # 创建滚动条
        self.slide = QScrollBar(True)
        self.slide.setObjectName('slide_roll_bar')
        self.slide.setMaximum(self.column)
        self.slide.setMinimum(self.num)
        self.slide.valueChanged.connect(self._value_change)

        # 创建中侧部件
        self.mid_widget = QWidget()
        self.mid_widget.setObjectName('mid_widget')
        self.mid_layout = QGridLayout()
        self.mid_widget.setLayout(self.mid_layout)

        # 创建下侧部件
        self.down_widget = QWidget()
        self.down_widget.setObjectName('down_widget')
        self.down_layout = QGridLayout()
        self.down_widget.setLayout(self.down_layout)

        self.main_layout.addWidget(self.up_widget, 0, 0, 1, self.column)
        self.main_layout.addWidget(self.slide, 1, 0, 1, self.column)
        self.main_layout.addWidget(self.mid_widget, 2, 2, 1, self.column - 2)
        self.main_layout.addWidget(self.down_widget, 3, self.column - 1,
                                   self.row, 1)
        self.setCentralWidget(self.main_widget)

        # 创建头部(head)
        self.head_widget = QWidget()
        self.head_layout = QGridLayout()
        self.head_widget.setLayout(self.head_layout)

        self.load_model_ico(
            0, self.num) if self.num < self.column else self.load_model_ico(
                0, self.column)

        self.up_layout.addWidget(self.head_widget, 0, 0, 0, 0)

        # 创建中部(middle)
        self.middle_widget = QWidget()
        self.middle_layout = QGridLayout()
        self.middle_widget.setLayout(self.middle_layout)

        for i in range(self.row):
            self.middle_icon = QLabel(chr(0xf002) + f'目录_{i}:')
            self.middle_icon.setFont(qtawesome.font('fa', 12))
            self.middle_input = QLineEdit()
            # self.middle_input.setPlaceholderText("请选择文件...")
            self.middle_input.setObjectName(f'middle_input_{i}')
            self.middle_btn = QPushButton(
                qtawesome.icon('fa.film', color='green'), "选择文件")
            self.middle_btn.setObjectName(f'middle_btn_{i}')
            self.middle_btn.clicked.connect(self.open_dir)

            self.middle_layout.addWidget(self.middle_icon, i, 0, 1, 1)
            self.middle_layout.addWidget(self.middle_input, i, 1, 1,
                                         self.row - 1)
            self.middle_layout.addWidget(self.middle_btn, i, self.row, 1, 1)

        self.mid_layout.addWidget(self.middle_widget, 0, 0, 1, 1)

        # 创建尾部
        self.tail_widget = QWidget()
        self.tail_layout = QGridLayout()
        self.tail_widget.setLayout(self.tail_layout)

        self.tail_btn = QPushButton(
            qtawesome.icon('fa.download', color='green'), "运行")
        self.tail_layout.addWidget(self.tail_btn, 0, 9, 1, 1)
        self.down_layout.addWidget(self.tail_widget, 0, 0, 0, 0)
        self.set_style()

        self.main_layout.setSpacing(0)
        # self.setWindowFlag(Qt.FramelessWindowHint)  # 隐藏边框

        # self.setWindowOpacity(0.9)  # 设置窗口透明度
        # self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明

    def open_dir(self):
        response = QFileDialog.getOpenFileName()
        if isinstance(response, tuple):
            file_path = response[0]
            if not os.path.exists(file_path):
                return
            self.middle_widget.sender().previousInFocusChain().setText(
                file_path)

    def _value_change(self):
        value = self.slide.value()
        start = value - self.num
        self.statusBar().showMessage(f'Current Value is {value}')
        for i in range(self.head_layout.count()):
            self.head_layout.itemAt(i).widget().deleteLater()
        self.load_model_ico(start, value)

    def load_model_ico(self, start, end):
        for i in range(start, end):
            self.tool_btn = QToolButton()
            self.tool_btn.setText(f"{self.icon[i]}")  # 设置按钮文本
            self.tool_btn.setObjectName(f"{self.icon[i]}")  # 设置按钮文本
            self.tool_btn.setFixedSize(80, 50)
            self.tool_btn.setIcon(
                qtawesome.icon(f'fa.{self.icon[i]}', color='white'))  # 设置按钮图标
            self.tool_btn.setIconSize(QSize(30, 30))  # 设置图标大小
            self.tool_btn.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
            self.tool_btn.clicked.connect(self._clicked)

            self.head_layout.addWidget(self.tool_btn, 0, i)

    def _clicked(self):
        text = self.sender().text()
        self.statusBar().showMessage(f'Current Value is {text}')
        self.change_style(text)

    def change_style(self, text):
        self.head_widget.setStyleSheet("""
            QToolButton{border:none;}
            QToolButton:hover{border-bottom:2px solid #F76677;}
            #%s{border:2px dotted black;}
        """ % text)

    def set_style(self):
        self.up_widget.setStyleSheet("""
            #up_widget{background:gray;}
        """)
        self.mid_widget.setStyleSheet("""
            #mid_widget{
                background:white;
                border-top-left-radius: 5px;
                border-bottom-left-radius: 5px;
            }
        """)
        self.down_widget.setStyleSheet("""
            #down_widget{background:darkGray;}
        """)
        self.head_widget.setStyleSheet("""
            QToolButton{
                border:none;
            }
            QToolButton:hover{border-bottom:2px solid #F76677;}
        """)
        self.middle_widget.setStyleSheet("""
            QLineEdit{
                border:1px solid gray;
                /*border-radius:10px;*/
                padding:5px 2px;
            }
            QPushButton{
                border:none;
                border-right:1px gray;
                border-radius:10px;
                width:40%;
                padding:5px 2px;
            }
            QPushButton:hover{
                color:red;font-weight: bold;
            }
            QLabel{
                padding:0 0 0 100%;
            }
        """)
        self.tail_widget.setStyleSheet("""
            QPushButton{
                border:none;
                border-right:1px gray;
                border-radius:10px;
                padding:5px 2px;
            }
            QPushButton:hover{
                color:red;font-weight: bold;
            }
        """)

    def paintEvent(self, event):
        # 设置背景颜色
        painter = QPainter(self)
        background_color = QColor()
        background_color.setNamedColor('darkGray')
        painter.setBrush(background_color)
        painter.drawRect(self.rect())
Beispiel #10
0
class BitsWidget(QWidget):
    def __init__(self, offset, bit_size, row_width, grid_width, grid_height,
                 bit_border_threshold) -> None:
        super().__init__()
        self._app = App()
        self._offset = offset
        self._bit_size = bit_size
        self._row_width = row_width
        self._grid_width = grid_width
        self._grid_h_offset = 0
        self._grid_height = grid_height
        self._grid_v_offset = 0
        self._one_color = Qt.blue
        self._zero_color = Qt.white
        self._color_table = [
            QColor(self._zero_color).rgb(),
            QColor(self._one_color).rgb(),
        ]
        self._bit_border_threshold = bit_border_threshold
        self._easter_egg = 0
        self._painting = False

        self._bits_area = QWidget()

        self._h_scrollbar = QScrollBar(orientation=Qt.Horizontal)
        self._h_scrollbar.setMinimum(0)
        self._h_scrollbar.valueChanged.connect(self._on_scrollbar_change)
        self._h_scrollbar.hide()
        self._v_scrollbar = QScrollBar(orientation=Qt.Vertical)
        self._v_scrollbar.setMinimum(0)
        self._v_scrollbar.valueChanged.connect(self._on_scrollbar_change)
        self._v_scrollbar.hide()

        inner_layout = QVBoxLayout()
        inner_layout.setContentsMargins(0, 0, 0, 0)
        inner_layout.setSpacing(0)
        inner_layout.addWidget(self._bits_area, stretch=1)
        inner_layout.addWidget(self._h_scrollbar)
        inner_widget = QWidget()
        inner_widget.setLayout(inner_layout)

        outer_layout = QHBoxLayout()
        outer_layout.setContentsMargins(0, 0, 0, 0)
        outer_layout.setSpacing(0)
        outer_layout.addWidget(inner_widget, stretch=1)
        outer_layout.addWidget(self._v_scrollbar)
        self.setLayout(outer_layout)

    @property
    def offset(self) -> int:
        return self._offset

    @offset.setter
    def offset(self, new_offset):
        self._offset = new_offset

    @property
    def bit_size(self) -> int:
        return self._bit_size

    @bit_size.setter
    def bit_size(self, size: int):
        self._bit_size = size

    @property
    def row_width(self) -> int:
        return self._row_width

    @row_width.setter
    def row_width(self, width: int):
        self._row_width = width

    @property
    def grid_width(self) -> int:
        return self._grid_width

    @grid_width.setter
    def grid_width(self, size: int):
        self._grid_width = size

    @property
    def grid_h_offset(self) -> int:
        return self._grid_h_offset

    @grid_h_offset.setter
    def grid_h_offset(self, offset: int):
        self._grid_h_offset = offset

    @property
    def grid_height(self) -> int:
        return self._grid_height

    @grid_height.setter
    def grid_height(self, size: int):
        self._grid_height = size

    @property
    def grid_v_offset(self) -> int:
        return self._grid_v_offset

    @grid_v_offset.setter
    def grid_v_offset(self, offset: int):
        self._grid_v_offset = offset

    @property
    def _bits_area_width(self):
        return self._bits_area.width()

    @property
    def _bits_area_height(self):
        return self._bits_area.height()

    @property
    def _num_rows(self):
        return ceil((self._app.num_bits - self._offset) / self._row_width)

    def set_bit_border_threshold(self, threshold):
        self._bit_border_threshold = threshold

    def load_file(self, filename, max_bytes):
        self._app.load_file(filename, max_bytes)

    def paintEvent(self, a0: QPaintEvent) -> None:
        super().paintEvent(a0)
        if not self._app.num_bits:
            return

        self._painting = True
        self._set_scrollbars()
        self._paint_bits()

        self._draw_grid()
        self._painting = False

    def _paint_bits(self):
        visible_columns = self._bits_area_width // self._bit_size
        visible_rows = self._bits_area_height // self._bit_size
        bitmap = self._app.create_bitmap(
            self._offset,
            self._row_width,
            self._h_scrollbar.value(),
            self._v_scrollbar.value(),
            visible_rows,
            visible_columns,
        )
        pixmap = self._create_pixmap(bitmap.data, bitmap.width,
                                     bitmap.bytes_per_row)
        painter = QPainter(self)
        painter.drawPixmap(0, 0, pixmap)
        self._draw_bit_separators(painter, pixmap.width(), pixmap.height())
        self._draw_last_row_of_bits(painter, bitmap.remainder, pixmap)
        painter.end()

    def _draw_bit_separators(self, painter: QPainter, right, bottom):
        if self._bit_size <= self._bit_border_threshold:
            return

        painter.setPen(QPen(Qt.black, 1))
        self._draw_h_grid(painter, right, bottom, 1, 0)
        self._draw_v_grid(painter, right, bottom, 1, 0)

    def _draw_last_row_of_bits(self, painter, last_row_of_bits, pixmap):
        painter.setPen(
            QPen(
                Qt.black if self._bit_size > self._bit_border_threshold else
                Qt.transparent,
                1,
                Qt.SolidLine,
            ))
        for i, b in enumerate(last_row_of_bits):
            self._draw_bit(painter, i, pixmap.height() // self._bit_size, b)

    def _draw_bit(self, painter: QPainter, x, y, bit):
        painter.setBrush(
            QBrush(self._one_color if bit else self._zero_color,
                   Qt.SolidPattern))
        painter.drawRect(x * self._bit_size, y * self._bit_size,
                         self._bit_size, self._bit_size)

    def _draw_grid(self):
        if not self._grid_width and not self._grid_height:
            return
        if not self._num_rows:
            return

        painter = QPainter(self)
        painter.setPen(QPen(Qt.red, 1, Qt.SolidLine))

        right = min(
            (self._row_width - self._h_scrollbar.value()) * self._bit_size,
            self._bits_area_width,
        )
        bottom = min(
            (self._num_rows - self._v_scrollbar.value()) * self._bit_size,
            self._bits_area_height,
        )
        self._draw_h_grid(
            painter,
            right,
            bottom,
            self._grid_width,
            self._grid_h_offset - self._h_scrollbar.value(),
        )
        self._draw_v_grid(
            painter,
            right,
            bottom,
            self._grid_height,
            self._grid_v_offset - self._v_scrollbar.value(),
        )

    def _create_pixmap(self, data: bytes, width, bytes_per_row: int):
        height = len(data) // bytes_per_row
        image = QImage(data, width, height, bytes_per_row, QImage.Format_Mono)
        image.setColorTable(self._color_table)
        return QPixmap.fromImage(image).scaled(width * self._bit_size,
                                               height * self._bit_size)

    def _draw_h_grid(self, painter, right, bottom, grid_width, grid_offset):
        if not grid_width:
            return

        start_offset = grid_offset % grid_width
        start = start_offset * self._bit_size
        for x in range(start, right + 1, grid_width * self._bit_size):
            painter.drawLine(x, 0, x, bottom)

    def _draw_v_grid(self, painter, right, bottom, grid_height, grid_offset):
        if not grid_height:
            return

        start_offset = grid_offset % grid_height
        start = start_offset * self._bit_size
        for y in range(start, bottom + 1, grid_height * self._bit_size):
            painter.drawLine(0, y, right, y)

    def _set_scrollbars(self):
        self._set_h_scrollbar()
        v_visibility_changed = self._set_v_scrollbar()
        if v_visibility_changed:
            h_visibility_changed = self._set_h_scrollbar()
            if h_visibility_changed:
                self._set_v_scrollbar()

    def _set_h_scrollbar(self):
        h_scroll_max = self._calc_h_scrollbar_max()
        was_visible = self._h_scrollbar.isVisible()
        if h_scroll_max > 0:
            self._h_scrollbar.setMaximum(h_scroll_max)
            self._h_scrollbar.show()
            return not was_visible
        else:
            self._h_scrollbar.setValue(0)
            self._h_scrollbar.hide()
            return was_visible

    def _set_v_scrollbar(self):
        v_scroll_max = self._calc_v_scrollbar_max()
        was_visible = self._v_scrollbar.isVisible()
        if v_scroll_max > 0:
            self._v_scrollbar.setMaximum(v_scroll_max)
            self._v_scrollbar.show()
            return not was_visible
        else:
            self._v_scrollbar.setValue(0)
            self._v_scrollbar.hide()
            return was_visible

    def _calc_h_scrollbar_max(self):
        return self._row_width - (self._bits_area_width // self.bit_size)

    def _calc_v_scrollbar_max(self):
        visible_rows = self._bits_area_height // self.bit_size
        return self._num_rows - visible_rows

    def wheelEvent(self, event: QWheelEvent) -> None:
        y_delta = event.angleDelta().y()
        if y_delta:
            notches = ceil(y_delta / 120)
            self._v_scrollbar.setValue(self._v_scrollbar.value() - notches)

        x_delta = event.angleDelta().x()
        if x_delta:
            notches = ceil(x_delta / 120)
            self._h_scrollbar.setValue(self._h_scrollbar.value() - notches)

    def mousePressEvent(self, a0: QMouseEvent) -> None:
        if (a0.x() <= self._bit_size and a0.y() <= self._bit_size
                and self._easter_egg < 9):
            self._easter_egg += 1
        elif (self._bit_size <= a0.x() <= self._bit_size * 2
              and self._bit_size <= a0.y() <= self._bit_size * 2
              and 9 <= self._easter_egg < 12):
            self._easter_egg += 1
        elif (self._bit_size * 2 <= a0.x() <= self._bit_size * 3
              and self._bit_size * 2 <= a0.y() <= self._bit_size * 3
              and self._easter_egg == 12):
            tmp = self._one_color
            self._one_color = self._zero_color
            self._zero_color = tmp
            self._color_table = [self._color_table[1], self._color_table[0]]
            self._easter_egg = 0
        else:
            self._easter_egg = 0

    def _on_scrollbar_change(self):
        if not self._painting:
            self.repaint()
Beispiel #11
0
class App(QWidget):
    def __init__(self):
        super().__init__()
        self.title = 'Tomo Control'
        self.left = 400
        self.top = 400
        self.width = 1000
        self.height = 600
        self.initUI()
        self.img_bkg = np.array([])
        self.img_tomo = np.array([])
        self.img_align = np.array([])
        self.img_recon = np.array([])

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.font1 = QtGui.QFont('Arial', 11, QtGui.QFont.Bold)
        self.font2 = QtGui.QFont('Arial', 11, QtGui.QFont.Normal)
        self.fpath = os.getcwd()

        #        lb_empty = QLabel()
        grid = QGridLayout()
        gpbox_prep = self.GP_prepare()
        gpbox_recon = self.recon()

        grid.addWidget(gpbox_prep, 0, 1)
        grid.addWidget(gpbox_recon, 1, 1)

        layout = QVBoxLayout()

        layout.addLayout(grid)
        layout.addWidget(QLabel())

        self.setLayout(layout)
#        self.resize(640,200)

    def GP_prepare(self):
        lb_empty = QLabel()
        lb_empty2 = QLabel()
        lb_empty2.setFixedWidth(30)

        gpbox = QGroupBox('Load image')
        gpbox.setFont(self.font1)

        lb_ld = QLabel()
        lb_ld.setFont(self.font2)
        lb_ld.setText('Image type:')
        lb_ld.setFixedWidth(100)

        self.pb_ld = QPushButton('Load image stack')
        self.pb_ld.setToolTip('image type: .hdf, .tiff')
        self.pb_ld.setFont(self.font2)
        self.pb_ld.clicked.connect(self.load_image)
        self.pb_ld.setFixedWidth(150)

        lb_mod = QLabel()
        lb_mod.setFont(self.font2)
        lb_mod.setText('Image mode:')
        lb_mod.setFixedWidth(100)

        file_group = QButtonGroup()
        file_group.setExclusive(True)
        self.rd_hdf = QRadioButton('hdf')
        self.rd_hdf.setChecked(True)
        self.rd_tif = QRadioButton('tif')
        file_group.addButton(self.rd_hdf)
        file_group.addButton(self.rd_tif)

        type_group = QButtonGroup()
        type_group.setExclusive(True)
        self.rd_absp = QRadioButton('Absorption')
        self.rd_absp.setFont(self.font2)
        self.rd_absp.setChecked(True)
        self.rd_flrc = QRadioButton('Fluorescence')
        self.rd_flrc.setFont(self.font2)
        type_group.addButton(self.rd_absp)
        type_group.addButton(self.rd_flrc)

        lb_fp = QLabel()
        lb_fp.setFont(self.font2)
        lb_fp.setText('Image loaded: ')
        lb_fp.setFixedWidth(100)

        self.lb_ip = QLabel()
        self.lb_ip.setFont(self.font2)

        hbox1 = QHBoxLayout()
        hbox1.addWidget(lb_ld)
        hbox1.addWidget(self.rd_hdf)
        hbox1.addWidget(self.rd_tif)
        hbox1.addWidget(lb_empty2)
        hbox1.addWidget(self.pb_ld)
        hbox1.addWidget(lb_empty2)
        hbox1.addWidget(self.lb_ip)
        hbox1.setAlignment(QtCore.Qt.AlignLeft)

        hbox2 = QHBoxLayout()
        hbox2.addWidget(lb_mod)
        hbox2.addWidget(self.rd_absp)
        hbox2.addWidget(self.rd_flrc)
        hbox2.addWidget(lb_empty)
        hbox2.setAlignment(QtCore.Qt.AlignLeft)

        vbox = QVBoxLayout()
        vbox.addLayout(hbox1)
        vbox.addLayout(hbox2)
        vbox.setAlignment(QtCore.Qt.AlignLeft)

        gpbox.setLayout(vbox)

        return gpbox

    def recon(self):
        lb_empty = QLabel()
        lb_empty2 = QLabel()
        lb_empty2.setFixedWidth(30)

        gpbox = QGroupBox('Tomo reconstruction')
        gpbox.setFont(self.font1)

        self.canvas1 = MyCanvas()
        self.canvas2 = MyCanvas()

        pb_rmbg = QPushButton('Remove Bkg')
        pb_rmbg.setFont(self.font2)
        pb_rmbg.clicked.connect(self.rm_bkg)
        pb_rmbg.setFixedWidth(150)

        pb_align = QPushButton('Align image')
        pb_align.setFont(self.font2)
        pb_align.clicked.connect(self.align_img)
        pb_align.setFixedWidth(150)

        self.sl1 = QScrollBar(QtCore.Qt.Horizontal)
        self.sl1.setMaximum(0)
        self.sl1.setMinimum(0)
        #        self.sl1.hide()
        self.sl1.valueChanged.connect(lambda: self.sliderval('left'))

        self.sl2 = QScrollBar(QtCore.Qt.Horizontal)
        self.sl2.setMaximum(0)
        self.sl2.setMinimum(0)
        #        self.sl2.hide()
        self.sl2.valueChanged.connect(lambda: self.sliderval('right'))

        self.cb1 = QComboBox()
        self.cb1.setFont(self.font2)
        self.cb1.addItem('Raw image')
        self.cb1.addItem('Background')
        self.cb1.addItem('Aligned')
        self.cb1.addItem('Reconstructed')

        self.cb2 = QComboBox()
        self.cb2.setFont(self.font2)
        self.cb2.addItem('Raw image')
        self.cb2.addItem('Background')
        self.cb2.addItem('Aligned')
        self.cb2.addItem('Reconstructed')

        pb_sh1 = QPushButton('Update')
        pb_sh1.setToolTip('update left image')
        pb_sh1.setFont(self.font2)
        pb_sh1.clicked.connect(lambda: self.update_canvas_img('left'))
        pb_sh1.setFixedWidth(150)

        pb_sh2 = QPushButton('Update')
        pb_sh2.setToolTip('update right image')
        pb_sh2.setFont(self.font2)
        pb_sh2.clicked.connect(lambda: self.update_canvas_img('right'))
        pb_sh2.setFixedWidth(150)

        hbox = QHBoxLayout()

        vbox_pb = QVBoxLayout()
        vbox_pb.addWidget(pb_rmbg)
        vbox_pb.addWidget(pb_align)
        vbox_pb.addWidget(lb_empty)
        vbox_pb.setAlignment(QtCore.Qt.AlignTop)

        hbox_can_l = QHBoxLayout()
        hbox_can_l.addWidget(self.cb1)
        hbox_can_l.addWidget(pb_sh1)

        hbox_can_r = QHBoxLayout()
        hbox_can_r.addWidget(self.cb2)
        hbox_can_r.addWidget(pb_sh2)

        vbox_can1 = QVBoxLayout()
        vbox_can1.addWidget(self.canvas1)
        vbox_can1.addWidget(self.sl1)
        vbox_can1.addLayout(hbox_can_l)
        vbox_can1.setAlignment(QtCore.Qt.AlignLeft)

        vbox_can2 = QVBoxLayout()
        vbox_can2.addWidget(self.canvas2)
        vbox_can2.addWidget(self.sl2)
        vbox_can2.addLayout(hbox_can_r)
        vbox_can2.setAlignment(QtCore.Qt.AlignLeft)

        hbox.addLayout(vbox_pb)
        hbox.addLayout(vbox_can1)
        hbox.addWidget(lb_empty2)
        hbox.addLayout(vbox_can2)
        hbox.setAlignment(QtCore.Qt.AlignLeft)

        gpbox.setLayout(hbox)
        return gpbox

    def load_image(self):
        options = QFileDialog.Option()
        options |= QFileDialog.DontUseNativeDialog
        if self.rd_hdf.isChecked() == True: file_type = 'hdf files (*.h5)'
        else: file_type = 'tiff files (*.tif)'

        fn, _ = QFileDialog.getOpenFileName(tomo,
                                            "QFileDialog.getOpenFileName()",
                                            "",
                                            file_type,
                                            options=options)
        self.img_bkg = np.array([])
        self.img_tomo = np.array([])
        self.img_align = np.array([])
        self.img_recon = np.array([])
        if fn:
            print(fn)
            fn_relative = fn.split('/')[-1]
            self.lb_ip.setText('{} loaded'.format(fn_relative))
            if self.rd_hdf.isChecked() == True:  # read hdf file
                f = h5py.File(fn, 'r')
                try:
                    self.img_tomo = np.array(f['img_tomo'])
                except:
                    self.img_tomo = np.zeros([1, 100, 100])
                    print('bkg image not exist')
                try:
                    self.img_bkg = np.array(f['img_bkg_raw'])
                except:
                    self.img_bkg = np.zeros([self.img_tomo.shape])
                    print('tomo image not exist')

                f.close()
            else:  # read tiff file
                self.img_tomo = np.array(io.imread(fn))

            if self.img_tomo.shape[0] > 0:
                print('total images: ' + str(self.img_tomo.shape[0]))
#                self.sl1.show()

#            test_img = self.img_tomo[0]
#            self.canvas1.update_img_one(test_img)
#            self.show_image(test_img)

#    def show_image(self, test_img):
#        ax = self.figure.add_subplot(111)
#        ax.clear()
#        ax.imshow(test_img)
#        self.canvas.draw()

#    def show_image(self, test_img):
#        colormap = []
##        for i in range(255):
##            colormap.append(QtGui.qRgb(i,i,i))
#        w, h = test_img.shape
#
#        pp = QtGui.QImage(test_img.data, h,w, QtGui.QImage.Format_RGB32)
##        if (max(pp.width(), pp.height()) > 600)
##        pixmap = QtGui.QPixmap(pp.scaled(pp.width()/2, pp.height()/2))
##        else:
#        pixmap = QtGui.QPixmap(pp)
#        self.lb_pic.setPixmap(pixmap)

    def sliderval(self, slide_type):

        if slide_type == 'left':
            canvas = self.canvas1
            img_index = self.sl1.value()

        else:
            canvas = self.canvas2
            img_index = self.sl2.value()

        img = canvas.img_stack[img_index]
        img = np.array(img)
        #        self.show_image(img)
        canvas.update_img_one(img)

    def rm_bkg(self):
        pass

    def align_img(self):
        pass

    def update_canvas_img(self, canv):

        if canv == 'left':
            canvas = self.canvas1
            slide = self.sl1
            index = self.cb1.currentIndex()
            print(str(1) + ' ' + str(index))
        else:
            canvas = self.canvas2
            slide = self.sl2
            index = self.cb2.currentIndex()
            print(str(2) + ' ' + str(index))

        if index == 0:
            canvas.img_stack = self.img_tomo
            canvas.update_img_stack()
            slide.setMaximum(max(self.img_tomo.shape[0] - 1, 0))
        elif index == 1:
            canvas.img_stack = self.img_bkg
            canvas.update_img_stack()
            slide.setMaximum(max(self.img_bkg.shape[0] - 1, 0))
        elif index == 2:
            canvas.img_stack = self.img_align
            canvas.update_img_stack()
            slide.setMaximum(max(self.img_align.shape[0] - 1, 0))
        else:
            canvas.img_stack = self.img_recon
            canvas.update_img_stack()
            slide.setMaximum(max(self.img_recon.shape[0] - 1, 0))
Beispiel #12
0
class CarlaRackW(QFrame, HostWidgetMeta):
#class CarlaRackW(QFrame, HostWidgetMeta, metaclass=PyQtMetaClass):
    def __init__(self, parent, host, doSetup = True):
        QFrame.__init__(self, parent)
        self.host = host

        if False:
            # kdevelop likes this :)
            host = CarlaHostMeta()
            self.host = host

        # -------------------------------------------------------------

        self.fLayout = QHBoxLayout(self)
        self.fLayout.setContentsMargins(0, 0, 0, 0)
        self.fLayout.setSpacing(0)
        self.setLayout(self.fLayout)

        self.fPadLeft  = QLabel(self)
        self.fPadLeft.setFixedWidth(25)
        self.fPadLeft.setObjectName("PadLeft")
        self.fPadLeft.setText("")

        self.fPadRight = QLabel(self)
        self.fPadRight.setFixedWidth(25)
        self.fPadRight.setObjectName("PadRight")
        self.fPadRight.setText("")

        self.fRack = CarlaRackList(self, host)
        self.fRack.setObjectName("CarlaRackList")
        self.fRack.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.fRack.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.fRack.currentRowChanged.connect(self.slot_currentRowChanged)

        sb = self.fRack.verticalScrollBar()
        self.fScrollBar = QScrollBar(Qt.Vertical, self)
        self.fScrollBar.setMinimum(sb.minimum())
        self.fScrollBar.setMaximum(sb.maximum())
        self.fScrollBar.setValue(sb.value())

        #sb.actionTriggered.connect(self.fScrollBar.triggerAction)
        #sb.sliderMoved.connect(self.fScrollBar.)
        #sb.sliderPressed.connect(self.fScrollBar.)
        #sb.sliderReleased.connect(self.fScrollBar.)
        sb.rangeChanged.connect(self.fScrollBar.setRange)
        sb.valueChanged.connect(self.fScrollBar.setValue)
        self.fScrollBar.rangeChanged.connect(sb.setRange)
        self.fScrollBar.valueChanged.connect(sb.setValue)

        self.fLayout.addWidget(self.fPadLeft)
        self.fLayout.addWidget(self.fRack)
        self.fLayout.addWidget(self.fPadRight)
        self.fLayout.addWidget(self.fScrollBar)

        # -------------------------------------------------------------
        # Internal stuff

        self.fParent      = parent
        self.fPluginCount = 0
        self.fPluginList  = []

        self.fCurrentRow = -1
        self.fLastSelectedItem = None

        # -------------------------------------------------------------
        # Set-up GUI stuff

        #app  = QApplication.instance()
        #pal1 = app.palette().base().color()
        #pal2 = app.palette().button().color()
        #col1 = "stop:0 rgb(%i, %i, %i)" % (pal1.red(), pal1.green(), pal1.blue())
        #col2 = "stop:1 rgb(%i, %i, %i)" % (pal2.red(), pal2.green(), pal2.blue())

        self.setStyleSheet("""
          QLabel#PadLeft {
            background-image: url(:/bitmaps/rack_padding_left.png);
            background-repeat: repeat-y;
          }
          QLabel#PadRight {
            background-image: url(:/bitmaps/rack_padding_right.png);
            background-repeat: repeat-y;
          }
          CarlaRackList#CarlaRackList {
            background-color: black;
          }
        """)

        # -------------------------------------------------------------
        # Connect actions to functions

        host.PluginAddedCallback.connect(self.slot_handlePluginAddedCallback)
        host.PluginRemovedCallback.connect(self.slot_handlePluginRemovedCallback)
        host.ReloadAllCallback.connect(self.slot_handleReloadAllCallback)

        if not doSetup: return

        parent.ui.menu_Canvas.hide()

        parent.ui.act_plugins_enable.triggered.connect(self.slot_pluginsEnable)
        parent.ui.act_plugins_disable.triggered.connect(self.slot_pluginsDisable)
        parent.ui.act_plugins_volume100.triggered.connect(self.slot_pluginsVolume100)
        parent.ui.act_plugins_mute.triggered.connect(self.slot_pluginsMute)
        parent.ui.act_plugins_wet100.triggered.connect(self.slot_pluginsWet100)
        parent.ui.act_plugins_bypass.triggered.connect(self.slot_pluginsBypass)
        parent.ui.act_plugins_center.triggered.connect(self.slot_pluginsCenter)
        parent.ui.act_plugins_panic.triggered.connect(self.slot_pluginsDisable)

        parent.ui.act_settings_configure.triggered.connect(self.slot_configureCarla)

    # -----------------------------------------------------------------

    @pyqtSlot(int, str)
    def slot_handlePluginAddedCallback(self, pluginId, pluginName):
        pitem = CarlaRackItem(self.fRack, pluginId, self.fParent.getSavedSettings()[CARLA_KEY_MAIN_USE_CUSTOM_SKINS])

        self.fPluginList.append(pitem)
        self.fPluginCount += 1

        if not self.fParent.isProjectLoading():
            pitem.getWidget().setActive(True, True, True)

    @pyqtSlot(int)
    def slot_handlePluginRemovedCallback(self, pluginId):
        pitem = self.getPluginItem(pluginId)

        self.fPluginCount -= 1
        self.fPluginList.pop(pluginId)
        self.fRack.takeItem(pluginId)

        if pitem is not None:
            pitem.closeEditDialog()
            del pitem

        # push all plugins 1 slot back
        for i in range(pluginId, self.fPluginCount):
            pitem = self.fPluginList[i]
            pitem.setPluginId(i)

    # -----------------------------------------------------------------
    # HostWidgetMeta methods

    def removeAllPlugins(self):
        while self.fRack.takeItem(0):
            pass

        for pitem in self.fPluginList:
            if pitem is None:
                break

            pitem.closeEditDialog()
            del pitem

        self.fPluginCount = 0
        self.fPluginList  = []

    def engineStarted(self):
        pass

    def engineStopped(self):
        pass

    def idleFast(self):
        for pitem in self.fPluginList:
            if pitem is None:
                break

            pitem.getWidget().idleFast()

    def idleSlow(self):
        for pitem in self.fPluginList:
            if pitem is None:
                break

            pitem.getWidget().idleSlow()

    def projectLoadingStarted(self):
        self.fRack.setEnabled(False)

    def projectLoadingFinished(self):
        self.fRack.setEnabled(True)

    def saveSettings(self, settings):
        pass

    def showEditDialog(self, pluginId):
        dialog = self.getPluginEditDialog(pluginId)

        if dialog is None:
            return

        dialog.show()

    # -----------------------------------------------------------------

    @pyqtSlot()
    def slot_pluginsEnable(self):
        if not self.host.is_engine_running():
            return

        for pitem in self.fPluginList:
            if pitem is None:
                break

            pitem.getWidget().setActive(True, True, True)

    @pyqtSlot()
    def slot_pluginsDisable(self):
        if not self.host.is_engine_running():
            return

        for pitem in self.fPluginList:
            if pitem is None:
                break

            pitem.getWidget().setActive(False, True, True)

    @pyqtSlot()
    def slot_pluginsVolume100(self):
        if not self.host.is_engine_running():
            return

        for pitem in self.fPluginList:
            if pitem is None:
                break

            pitem.getWidget().setInternalParameter(PLUGIN_CAN_VOLUME, 1.0)

    @pyqtSlot()
    def slot_pluginsMute(self):
        if not self.host.is_engine_running():
            return

        for pitem in self.fPluginList:
            if pitem is None:
                break

            pitem.getWidget().setInternalParameter(PLUGIN_CAN_VOLUME, 0.0)

    @pyqtSlot()
    def slot_pluginsWet100(self):
        if not self.host.is_engine_running():
            return

        for pitem in self.fPluginList:
            if pitem is None:
                break

            pitem.getWidget().setInternalParameter(PLUGIN_CAN_DRYWET, 1.0)

    @pyqtSlot()
    def slot_pluginsBypass(self):
        if not self.host.is_engine_running():
            return

        for pitem in self.fPluginList:
            if pitem is None:
                break

            pitem.getWidget().setInternalParameter(PLUGIN_CAN_DRYWET, 0.0)

    @pyqtSlot()
    def slot_pluginsCenter(self):
        if not self.host.is_engine_running():
            return

        for pitem in self.fPluginList:
            if pitem is None:
                break

            pitem.getWidget().setInternalParameter(PARAMETER_BALANCE_LEFT, -1.0)
            pitem.getWidget().setInternalParameter(PARAMETER_BALANCE_RIGHT, 1.0)
            pitem.getWidget().setInternalParameter(PARAMETER_PANNING, 0.0)

    # -----------------------------------------------------------------

    @pyqtSlot()
    def slot_configureCarla(self):
        dialog = CarlaSettingsW(self, self.host, False, False)
        if not dialog.exec_():
            return

        self.fParent.loadSettings(False)

    # -----------------------------------------------------------------

    @pyqtSlot(int)
    def slot_handleReloadAllCallback(self, pluginId):
        if pluginId >= self.fPluginCount:
            return

        pitem = self.fPluginList[pluginId]
        if pitem is None:
            return

        self.fRack.setCurrentRow(-1)
        self.fCurrentRow = -1
        self.fLastSelectedItem = None

        pitem.recreateWidget()

    # -----------------------------------------------------------------

    @pyqtSlot(int)
    def slot_currentRowChanged(self, row):
        self.fCurrentRow = row

        if self.fLastSelectedItem is not None:
            self.fLastSelectedItem.setSelected(False)

        if row < 0 or row >= self.fPluginCount or self.fPluginList[row] is None:
            self.fLastSelectedItem = None
            return

        pitem = self.fPluginList[row]
        pitem.getWidget().setSelected(True)
        self.fLastSelectedItem = pitem.getWidget()

    # -----------------------------------------------------------------

    def getPluginItem(self, pluginId):
        if pluginId >= self.fPluginCount:
            return None

        pitem = self.fPluginList[pluginId]
        if pitem is None:
            return None
        if False:
            pitem = CarlaRackItem(self, 0, False)

        return pitem

    def getPluginEditDialog(self, pluginId):
        if pluginId >= self.fPluginCount:
            return None

        pitem = self.fPluginList[pluginId]
        if pitem is None:
            return None
        if False:
            pitem = CarlaRackItem(self, 0, False)

        return pitem.getEditDialog()

    def getPluginSlotWidget(self, pluginId):
        if pluginId >= self.fPluginCount:
            return None

        pitem = self.fPluginList[pluginId]
        if pitem is None:
            return None
        if False:
            pitem = CarlaRackItem(self, 0, False)

        return pitem.getWidget()
Beispiel #13
0
class MainWindow(MainWindowBase, MainWindowUI):

    VIDEOS = ('front_video_file', 'eyes_video_file')

    def __init__(self, manager, parent=None):
        MainWindowBase.__init__(self, parent)

        self.manager = manager
        self.current_segment = None
        self.current_video = 0
        self.nav_hide_empty = True

        self.setupUi(self)
        self.setupConnections()

    def setupUi(self, parent):
        MainWindowUI.setupUi(self, parent)

        # content area
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.content.setLayout(layout)

        # add video widget
        self.contentWidget = VideoWidget()
        self.content.layout().addWidget(self.contentWidget)

        self.prev_code = 'def f(img):\n    return img'
        self.te_code = PyCodeEdit()
        self.te_code.setPlainText(self.prev_code)
        self.content.layout().addWidget(self.te_code)

        # footer area
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.footer.setLayout(layout)

        self.bar_index = QScrollBar(Qt.Horizontal)
        self.bar_index.setFocusPolicy(Qt.WheelFocus)
        self.bar_index.setMinimum(0)
        self.bar_index.setSingleStep(1)
        self.bar_index.valueChanged.connect(self.indexChanged)
        layout.addWidget(self.bar_index)

        self.info = QLabel()
        layout.addWidget(self.info)

        # construct navigation tree
        self.refreshNavigation()

        # design the view
        self.treeView.header().hide()  # hide header
        self.treeView.expandToDepth(0)  # expand first level

    def setupConnections(self):

        # shortcuts
        self.sc_next = QShortcut(QKeySequence("Right"), self)
        self.sc_next.activated.connect(self.nextImage)

        self.sc_prev = QShortcut(QKeySequence("Left"), self)
        self.sc_prev.activated.connect(self.prevImage)

        self.treeView.doubleClicked.connect(self.navigation_doubleClicked)

        self.pb_video_toggle.clicked.connect(self.toggleVideo)
        self.pb_hide_toggle.clicked.connect(self.toggleHideEmpty)

    def toggleVideo(self):
        self.current_video = (self.current_video + 1) % len(MainWindow.VIDEOS)
        self.setSegment(self.current_segment)

    def toggleHideEmpty(self):
        self.nav_hide_empty = not self.nav_hide_empty
        self.refreshNavigation()

    def refreshNavigation(self):
        items = []
        for project_id in self.manager.getProjectNames():
            project = self.manager.getProject(project_id)
            p_node = NavigationNode(project.info['Name'])
            p_node.obj_data = project
            items.append(p_node)

            for r_id in sorted(p_node.obj_data.getRecordingNames()):
                print(r_id)
                recording = p_node.obj_data.getRecording(r_id)
                print(recording)

                if recording:
                    r_node = NavigationNode(r_id)
                    r_node.obj_data = recording

                    p_node.addChild(r_node)
                    for segment_id in r_node.obj_data.getSegmentIDs():
                        s_node = NavigationNode(segment_id)
                        s_node.obj_data = r_node.obj_data.getSegment(
                            segment_id)
                        r_node.addChild(s_node)

        self.treeView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.treeView.setUniformRowHeights(True)
        self.treeView.setModel(NavigationModel(items))

    def navigation_doubleClicked(self, _):
        item = self.treeView.selectedIndexes()[0]
        obj = item.internalPointer().obj_data

        if hasattr(obj, 'segments') and obj.segments_data:
            obj = obj.segments_data[0]

        if hasattr(obj, 'eyes_video_file'):
            self.setSegment(obj)

    def applyCode(self):
        code = self.te_code.toPlainText()
        if self.prev_code != code:
            try:
                exec(code, globals(), locals())
                self.contentWidget.onImage = locals()['f']
            except Exception as e:
                print(e)

    def prevImage(self):
        self.bar_index.setValue(self.bar_index.value() - 1)

    def nextImage(self):
        self.bar_index.setValue(self.bar_index.value() + 1)

    def setVideo(self, path):
        self.contentWidget.openVideo(path)
        self.bar_index.setMaximum(self.contentWidget.video.length)

    def indexChanged(self, value):
        self.applyCode()
        video = self.contentWidget.video
        video.pos_frame = value
        self.contentWidget.updateImage()

        info_msg = []
        info_msg.append('FPS:   %s' % video.fps)
        info_msg.append('Frame: %d / %d (%.4f)' %
                        (video.pos_frame + 1, video.length, video.pos_msec))

        self.info.setText('\n'.join(info_msg))

    def setSegment(self, segment):
        try:
            self.current_segment = segment
            self.setVideo(
                getattr(self.current_segment,
                        MainWindow.VIDEOS[self.current_video]))
            self.bar_index.setValue(0)
            self.indexChanged(0)
        except:
            pass
Beispiel #14
0
class EditorMapComponent:

    current = None

    def __init__(self, tabbed=True, parent=None):
        EditorMapComponent.current = self

        self.workspace = Workspace()
        self.gc_state = GraphicContextState()

        if tabbed:
            self.tab_widget = QTabWidget(parent)
            self.widget = QWidget(self.tab_widget)
            self.tab_widget.addTab(self.widget, "A Label")
        else:
            self.tab_widget = None
            self.widget = QWidget(parent)

        self.layout = QGridLayout(self.widget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setHorizontalSpacing(0)
        self.layout.setVerticalSpacing(0)

        self.scroll_horz = QScrollBar(Qt.Horizontal)
        self.scroll_vert = QScrollBar(Qt.Vertical)
        self.editormap_widget = EditorMapWidget(self, None)

        self.scroll_horz.valueChanged.connect(self.move_to_x)
        self.scroll_vert.valueChanged.connect(self.move_to_y)

        self.layout.addWidget(self.editormap_widget, 0, 0)
        self.layout.addWidget(self.scroll_horz, 1, 0)
        self.layout.addWidget(self.scroll_vert, 0, 1)

        self.sig_drop = Signal()
        self.editormap_widget.sig_drop.connect(self.on_drop)

    def on_drop(self, data, pos):
        """sends (brush, pos)"""
        brush_id = pickle.loads(data)
        brush = ObjectSelector.current.get_brush(brush_id)
        return self.sig_drop(brush, pos)

    def get_workspace(self):
        return self.workspace

    def grab_mouse(self):
        self.editormap_widget.grabMouse()

    def release_mouse(self):
        self.editormap_widget.releaseMouse()

    # ifdef GRUMBEL
    # void
    # EditorMapComponentImpl::on_key_down(const CL_InputEvent& event)
    # {
    #   if (event.id >= 0 && event.id < 256)
    #   {
    #     Rect rect = parent.get_position()
    #     key_bindings[event.id](CL_Mouse::get_x() - rect.left,
    #                            CL_Mouse::get_y() - rect.top)
    #   }

    #   if (event.repeat_count == 0)
    #   {
    #     Rect rect = parent.get_position()
    #     CL_InputEvent ev2 = event
    #     ev2.mouse_pos = Point(CL_Mouse::get_x() - rect.left,
    #                           CL_Mouse::get_y() - rect.top)
    #     workspace.key_down(InputEvent(ev2))
    #   }
    # }

    # void
    # EditorMapComponentImpl::on_key_up(const CL_InputEvent& event)
    # {
    #   Rect rect = parent.get_position()
    #   CL_InputEvent ev2 = event
    #   ev2.mouse_pos = Point(CL_Mouse::get_x() - rect.left,
    #                         CL_Mouse::get_y() - rect.top)
    #   workspace.key_up(InputEvent(ev2))
    # }

    # void
    # EditorMapComponentImpl::draw ()
    # {
    #   if (workspace.get_map().is_null()) return

    #   Display::push_cliprect(parent.get_screen_rect())

    #   Display::push_modelview()
    #   Display::add_translate(parent.get_screen_x(), parent.get_screen_y())

    #   // Update scrollbars (FIXME: move me to function)
    #   scrollbar_v.set_range(0, workspace.get_map().get_bounding_rect().height)
    #   scrollbar_v.set_pagesize(parent.height/gc_state.get_zoom())
    #   scrollbar_v.set_pos(gc_state.get_pos().y)

    #   scrollbar_h.set_range(0, workspace.get_map().get_bounding_rect().width)
    #   scrollbar_h.set_pagesize(parent.width/gc_state.get_zoom())
    #   scrollbar_h.set_pos(gc_state.get_pos().x)

    #   gc_state.push()
    #   {
    #     GraphicContext gc(gc_state, CL_Display::get_current_window().get_gc())
    #     workspace.draw(gc)
    #   }
    #   gc_state.pop()

    #   Display::pop_modelview()
    #   Display::pop_cliprect()
    # }
    # endif

    def screen2world(self, pos):
        return self.gc_state.screen2world(pos)

    def set_zoom(self, z):
        self.gc_state.set_zoom(z)

        self.editormap_widget.repaint()
        self.update_scrollbars()

    def zoom_out(self, pos):
        self.gc_state.set_zoom(self.gc_state.get_zoom() / 1.25,
                               Pointf(pos.x, pos.y))

        self.editormap_widget.repaint()
        self.update_scrollbars()

    def zoom_in(self, pos):
        self.gc_state.set_zoom(self.gc_state.get_zoom() * 1.25,
                               Pointf(pos.x, pos.y))

        self.editormap_widget.repaint()
        self.update_scrollbars()

    def zoom_to(self, rect):
        self.gc_state.zoom_to(rect)

        self.editormap_widget.repaint()
        self.update_scrollbars()

    def get_clip_rect(self):
        return self.gc_state.get_clip_rect()

    def move_to(self, x, y):
        self.gc_state.set_pos(Pointf(x, y))

        self.editormap_widget.repaint()
        self.update_scrollbars()

    def move_to_x(self, x):

        self.gc_state.set_pos(Pointf(x, self.gc_state.get_pos().y))

        self.editormap_widget.repaint()
        self.update_scrollbars()

    def move_to_y(self, y):
        self.gc_state.set_pos(Pointf(self.gc_state.get_pos().x, y))

        self.editormap_widget.repaint()
        self.update_scrollbars()

    def sig_on_key(self, keyseq_str):
        key_sequence = QKeySequence(keyseq_str)
        if key_sequence.isEmpty():
            raise RuntimeError("invalid key binding: '%s'" % keyseq_str)

        shortcut = QShortcut(key_sequence, self.editormap_widget)
        signal = Signal()

        def on_key(*args):
            pos = self.editormap_widget.mapFromGlobal(QCursor.pos())
            # pos = self.gc_state.screen2world(Point.from_qt(pos))
            signal(pos.x(), pos.y())

        shortcut.activated.connect(on_key)

        return signal

    def get_gc_state(self):
        return self.gc_state

    def get_widget(self):
        return self.tab_widget or self.widget

    def update_scrollbars(self):
        rect = self.workspace.get_map().get_bounding_rect()
        border = 128

        self.scroll_horz.setMinimum(rect.left - border)
        self.scroll_horz.setMaximum(rect.right + border)
        self.scroll_horz.setPageStep(self.editormap_widget.width())
        self.scroll_horz.setSliderPosition(int(self.gc_state.get_pos().x))

        self.scroll_vert.setMinimum(rect.top - border)
        self.scroll_vert.setMaximum(rect.bottom + border)
        self.scroll_vert.setPageStep(self.editormap_widget.height())
        self.scroll_vert.setSliderPosition(int(self.gc_state.get_pos().y))

    def set_sector_tab_label(self, index, text):
        self.tab_widget.setTabText(index, "Sector \"%s\"" % text)