コード例 #1
0
class ColorChoiceWidget(ColorWidget):
	def __init__(self):
		super(ColorChoiceWidget, self).__init__()

		self.buttons = []

		self.buttonGroup = QButtonGroup()
		self.buttonGroup.setExclusive(True)
		self.buttonGroup.buttonClicked.connect(self.selectColor)

	def setColors(self, colors):
		layout = self.buttonWidget.layout()
		id = 0
		for color in colors:
			button = ColorButton()
			button.setColor(color)
			button.setCheckable(True)
			layout.addWidget(button)
			self.buttonGroup.addButton(button)
			self.buttonGroup.setId(button, id)
			id += 1
		layout.addStretch(10)

	def setColor(self, color):
		self.color = color
		for button in self.buttonGroup.buttons():
			diffs = map(lambda x, y: abs(x - y), button.color, color)
			if sum(diffs) < 0.0001:
				button.setChecked(True)
				break

	def selectColor(self, button):
		self.color = button.color
		self.valueChanged.emit(self.color)
コード例 #2
0
class ColorChoiceWidget(ColorWidget):
    def __init__(self):
        super(ColorChoiceWidget, self).__init__()

        self.buttons = []

        self.buttonGroup = QButtonGroup()
        self.buttonGroup.setExclusive(True)
        self.buttonGroup.buttonClicked.connect(self.selectColor)

    def setColors(self, colors):
        layout = self.buttonWidget.layout()
        id = 0
        for color in colors:
            button = ColorButton()
            button.setColor(color)
            button.setCheckable(True)
            layout.addWidget(button)
            self.buttonGroup.addButton(button)
            self.buttonGroup.setId(button, id)
            id += 1
        layout.addStretch(10)

    def setColor(self, color):
        self.color = color
        for button in self.buttonGroup.buttons():
            diffs = map(lambda x, y: abs(x - y), button.color, color)
            if sum(diffs) < 0.0001:
                button.setChecked(True)
                break

    def selectColor(self, button):
        self.color = button.color
        self.valueChanged.emit(self.color)
コード例 #3
0
ファイル: bridge.py プロジェクト: JanDeVisser/Grumble
class RadioButtons(WidgetBridge, Choices):
    _qttype = QGroupBox

    def customize(self, widget):
        assert self.choices, "RadioButtons: Cannot build widget bridge without choices"
        # We give the GroupBox a container so we can add stretch at the end.
        self.container = QWidget(self.parent)
        hbox = QHBoxLayout(self.container)
        self.buttongroup = QButtonGroup(self.parent)
        if "direction" in self.config and \
                self.config["direction"].lower() == "vertical":
            box = QVBoxLayout()
        else:
            box = QHBoxLayout()
        ix = 1
        for text in self.choicesdict().values():
            rb = QRadioButton(text, self.parent)
            box.addWidget(rb)
            self.buttongroup.addButton(rb, ix)
            ix += 1
        widget.setLayout(box)
        hbox.addWidget(widget)
        hbox.addStretch(1)
        hbox.setContentsMargins(QMargins(0, 0, 0, 0))

    def apply(self, value):
        for b in self.buttongroup.buttons():
            b.setChecked(False)
        b = self.buttongroup.button(self.index(value) + 1)
        if b:
            b.setChecked(True)

    def retrieve(self):
        ix = self.buttongroup.checkedId()
        return self.at(ix - 1) if ix > 0 else None
コード例 #4
0
class PeriodicTableWidget(QWidget):

    selectionChanged = Signal()

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        # Widgets, layouts and signals
        self._group = QButtonGroup()

        layout = QGridLayout()
        layout.setSpacing(0)

        for i in range(18):
            layout.setColumnMinimumWidth(i, 40)
            layout.setColumnStretch(i, 0)
        for i in list(range(7)) + [8, 9]:
            layout.setRowMinimumHeight(i, 40)
            layout.setRowStretch(i, 0)

        ## Element
        for z, position in _ELEMENT_POSITIONS.items():
            widget = ElementPushButton(z)
            widget.setCheckable(True)
            layout.addWidget(widget, *position)
            self._group.addButton(widget, z)

        ## Labels
        layout.addWidget(QLabel(''), 7, 0) # Dummy
        layout.addWidget(QLabel('*'), 5, 2, Qt.AlignCenter)
        layout.addWidget(QLabel('*'), 8, 2, Qt.AlignCenter)
        layout.addWidget(QLabel('**'), 6, 2, Qt.AlignCenter)
        layout.addWidget(QLabel('**'), 9, 2, Qt.AlignCenter)

        for row in [0, 1, 2, 3, 4, 5, 6, 8, 9]:
            layout.setRowStretch(row, 1)

        self.setLayout(layout)

        # Signals
        self._group.buttonClicked.connect(self.selectionChanged)

        # Default
        self.setColorFunction(_category_color_function)

    def setColorFunction(self, func):
        if not callable(func):
            raise ValueError('Not a function')
        self._color_function = func

        # Redraw
        for widget in self._group.buttons():
            z = self._group.id(widget)
            bcolor = func(z)
            fcolor = 'white' if _calculate_brightness(bcolor) < 128 else 'black'
            sheet = 'background-color: %s; color: %s' % (bcolor.name(), fcolor)
            widget.setStyleSheet(sheet)

    def colorFunction(self):
        return self._color_function

    def setMultipleSelection(self, multiple):
        self._group.setExclusive(not multiple)

    def isMultipleSelection(self):
        return not self._group.exclusive()

    def setSelection(self, selection):
        def _uncheckedAll():
            for widget in self._group.buttons():
                widget.setChecked(False)

        if selection is None:
            _uncheckedAll()
            self.selectionChanged.emit()
            return

        if isinstance(selection, (int, six.string_types)):
            selection = [selection]

        if not self.isMultipleSelection() and len(selection) > 1:
            raise ValueError('Multiple selection mode is off. Cannot select more than one element')

        _uncheckedAll()

        for z in selection:
            if isinstance(z, six.string_types):
                z = ep.atomic_number(z.strip())
            self._group.button(z).setChecked(True)

        self.selectionChanged.emit()
#
    def selection(self):
        selection = set()
        for widget in self._group.buttons():
            if widget.isChecked():
                selection.add(self._group.id(widget))

        if self.isMultipleSelection():
            return frozenset(selection)
        else:
            if len(selection) > 0:
                return list(selection)[0]
            else:
                return None

    def selectionSymbol(self):
        selection = self.selection()
        if self.isMultipleSelection():
            return frozenset(map(ep.symbol, selection))
        else:
            if selection is None:
                return None
            else:
                return ep.symbol(selection)
コード例 #5
0
class VideoSwitcher(QWidget):

    def __init__(self, controller, mainWindow):
        super(VideoSwitcher, self).__init__()
        self.controller = controller
        self.mainWindow = mainWindow
        self.setupUi()

    def setupUi(self):

        gridlayout = QGridLayout()
        self.setLayout(gridlayout)

        ''' Buttons added to inputs should have a numeric ID set equal to their input number on the Aldates main switcher. '''
        self.inputs = QButtonGroup()

        inputsGrid = QHBoxLayout()

        self.btnCamera1 = CameraSelectionButton(1)
        self.btnCamera1.setText("Camera 1")
        self.btnCamera1.setInput(VisualsSystem.camera1)
        inputsGrid.addWidget(self.btnCamera1)
        self.inputs.addButton(self.btnCamera1, 1)
        self.btnCamera1.setIcon(QIcon(":icons/camera-video"))

        self.btnCamera2 = CameraSelectionButton(2)
        self.btnCamera2.setText("Camera 2")
        self.btnCamera2.setInput(VisualsSystem.camera2)
        inputsGrid.addWidget(self.btnCamera2)
        self.inputs.addButton(self.btnCamera2, 2)
        self.btnCamera2.setIcon(QIcon(":icons/camera-video"))

        self.btnCamera3 = CameraSelectionButton(3)
        self.btnCamera3.setText("Camera 3")
        self.btnCamera3.setInput(VisualsSystem.camera3)
        inputsGrid.addWidget(self.btnCamera3)
        self.inputs.addButton(self.btnCamera3, 3)
        self.btnCamera3.setIcon(QIcon(":icons/camera-video"))

        self.btnDVD = InputButton()
        self.btnDVD.setText("DVD")
        self.btnDVD.setInput(VisualsSystem.dvd)
        inputsGrid.addWidget(self.btnDVD)
        self.inputs.addButton(self.btnDVD, 4)
        self.btnDVD.setIcon(QIcon(":icons/media-optical"))

        self.btnExtras = InputButton()
        self.btnExtras.setText("Extras")
        inputsGrid.addWidget(self.btnExtras)
        self.btnExtras.setIcon(QIcon(":icons/video-display"))
        self.inputs.addButton(self.btnExtras, 5)

        self.btnVisualsPC = InputButton()
        self.btnVisualsPC.setText("Visuals PC")
        self.btnVisualsPC.setInput(VisualsSystem.visualsPC)
        inputsGrid.addWidget(self.btnVisualsPC)
        self.inputs.addButton(self.btnVisualsPC, 6)
        self.btnVisualsPC.setIcon(QIcon(":icons/computer"))

        self.btnBlank = InputButton()
        self.btnBlank.setText("Blank")
        self.btnBlank.setInput(VisualsSystem.blank)
        inputsGrid.addWidget(self.btnBlank)
        self.inputs.addButton(self.btnBlank, 0)

        gridlayout.addLayout(inputsGrid, 0, 0, 1, 7)

        self.extrasSwitcher = ExtrasSwitcher(self.controller)
        self.extrasSwitcher.inputSelected.connect(self.handleExtrasSelect)
        self.btnExtras.setInput(ProxyInput(self.extrasSwitcher))
        self.blank = QWidget(self)
        gridlayout.addWidget(self.blank, 1, 0, 1, 5)

        self.outputsGrid = OutputsGrid()

        gridlayout.addWidget(self.outputsGrid, 1, 5, 1, 2)

        gridlayout.setRowStretch(0, 1)
        gridlayout.setRowStretch(1, 5)
        QMetaObject.connectSlotsByName(self)
        self.setInputClickHandlers()
        self.setOutputClickHandlers(self.outputsGrid)
        self.configureInnerControlPanels()
        self.gridlayout = gridlayout

    def configureInnerControlPanels(self):
        self.panels = [
            QWidget(),  # Blank
            CameraControl(self.controller["Camera 1"]) if self.controller.hasDevice("Camera 1") else QLabel(StringConstants.noDevice),
            CameraControl(self.controller["Camera 2"]) if self.controller.hasDevice("Camera 2") else QLabel(StringConstants.noDevice),
            CameraControl(self.controller["Camera 3"]) if self.controller.hasDevice("Camera 3") else QLabel(StringConstants.noDevice),
            QLabel(StringConstants.noDevice),  # DVD - no controls
            self.extrasSwitcher if self.controller.hasDevice("Extras") else QLabel(StringConstants.noDevice),  # Extras
            EclipseControls(self.controller["Main Scan Converter"]) if self.controller.hasDevice("Main Scan Converter") else QLabel(StringConstants.noDevice),  # Visuals PC
        ]
        self.advPanels = [
            None,
            AdvancedCameraControl("Camera 1", self.controller["Camera 1"], self.mainWindow) if self.controller.hasDevice("Camera 1") else None,
            AdvancedCameraControl("Camera 2", self.controller["Camera 2"], self.mainWindow) if self.controller.hasDevice("Camera 1") else None,
            AdvancedCameraControl("Camera 3", self.controller["Camera 3"], self.mainWindow) if self.controller.hasDevice("Camera 1") else None,
            None,
            None,
            None
        ]

    def setInputClickHandlers(self):
        for btn in self.inputs.buttons():
            btn.clicked.connect(self.handleInputSelect)
            btn.longpress.connect(self.showAdvPanel)

    def setOutputClickHandlers(self, outputsGrid):
        outputsGrid.connectMainOutputs(self.handleOutputSelect)
        ''' btnPCMix is a special case since that's on a different switcher '''
        outputsGrid.connectPreviewOutputs(self.handlePCMixSelect)

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_0:
            self.btnBlank.click()
        elif e.key() == Qt.Key_1:
            self.btnCamera1.click()
        elif e.key() == Qt.Key_2:
            self.btnCamera2.click()
        elif e.key() == Qt.Key_3:
            self.btnCamera3.click()
        elif e.key() == Qt.Key_4:
            self.btnDVD.click()
        elif e.key() == Qt.Key_5:
            self.btnExtras.click()
        elif e.key() == Qt.Key_6:
            self.btnVisualsPC.click()
        elif e.key() == Qt.Key_Space:
            self.outputsGrid.btnAll.click()
        else:
            self.panels[self.inputs.checkedId()].keyPressEvent(e)

    def keyReleaseEvent(self, e):
        self.panels[self.inputs.checkedId()].keyReleaseEvent(e)

    def handleInputSelect(self):
        inputID = self.inputs.checkedId()
        logging.debug("Input selected: " + str(inputID))
        if inputID >= 0:
            myInput = self.inputs.checkedButton().input
            if myInput:
                myInput.preview(self.controller)
        self.gridlayout.removeWidget(self.gridlayout.itemAtPosition(1, 0).widget())
        for p in self.panels:
            p.hide()
        chosenPanel = self.panels[inputID]
        self.gridlayout.addWidget(chosenPanel, 1, 0, 1, 5)
        chosenPanel.show()

        # Prevent certain options from being selectable
        if inputID == 6 or inputID == 0:
            self.outputsGrid.setEnabled(True)
            self.outputsGrid.btnPCMix.setEnabled(False)
        elif inputID == 5 and self.extrasSwitcher.currentInput() is None:
            self.outputsGrid.setEnabled(False)
            self.outputsGrid.btnPCMix.setEnabled(True)
        else:
            self.outputsGrid.setEnabled(True)
            self.outputsGrid.btnPCMix.setEnabled(True)

    def handleOutputSelect(self):
        outputChannel = self.sender().ID
        inputID = self.inputs.checkedId()
        checkedExtrasButton = self.extrasSwitcher.inputs.checkedButton()
        inputChannel = checkedExtrasButton.input if (inputID == 5 and checkedExtrasButton) else self.inputs.checkedButton().input
        if inputChannel:
            inputChannel.toMain(self.controller, outputChannel)

    def handlePCMixSelect(self):
        inputID = self.inputs.checkedId()
        checkedExtrasButton = self.extrasSwitcher.inputs.checkedButton()
        inputChannel = checkedExtrasButton.input if (inputID == 5 and checkedExtrasButton) else self.inputs.checkedButton().input
        if inputChannel:
            inputChannel.toPCMix(self.controller)

    @Slot(VisualsSystem.Input)
    def handleExtrasSelect(self, extrasInput):
        if extrasInput is not None:
            self.btnExtras.setText(extrasInput.name)
            self.outputsGrid.inputNames[5] = extrasInput.name
            self.outputsGrid.setEnabled(True)
        else:
            # Not sure under what circumstances, if any, this will arise
            self.btnExtras.setText("Extras")
            self.outputsGrid.inputNames[5] = "Extras"
            self.outputsGrid.setEnabled(False)

    def showAdvPanel(self):
        sender = self.sender()
        inputID = self.sender().ID if hasattr(sender, "ID") else None
        if inputID is not None and self.advPanels[inputID] is not None:
            self.mainWindow.showScreen(self.advPanels[inputID])

    def updateOutputMappings(self, mapping):
        print mapping
        self.outputsGrid.updateOutputMappings(mapping)
コード例 #6
0
class AllInputsPanel(QWidget):

    inputSelected = Signal(Input)

    def __init__(self, switcherState, parent=None):
        super(AllInputsPanel, self).__init__(parent)

        self.switcherState = switcherState
        self.selectedInput = None
        self.page = 0
        self.sources = []

        self.layout = QGridLayout()
        self.input_buttons = QButtonGroup()

        self.btnPageUp = ExpandingButton()
        self.btnPageUp.setIcon(QIcon(":icons/go-up"))
        self.btnPageUp.clicked.connect(lambda: self.setPage(self.page - 1))
        self.layout.addWidget(self.btnPageUp, 0, 5, 3, 1)

        self.btnPageDown = ExpandingButton()
        self.btnPageDown.setIcon(QIcon(":icons/go-down"))
        self.btnPageDown.clicked.connect(lambda: self.setPage(self.page + 1))
        self.layout.addWidget(self.btnPageDown, 3, 5, 3, 1)

        for col in range(5):
            self.layout.setColumnStretch(col, 1)
            for row in range(3):
                btn = InputButton(None)
                self.layout.addWidget(btn, row * 2, col, 2, 1)
                self.input_buttons.addButton(btn)
                btn.clicked.connect(self.selectInput)
                btn.setFixedWidth(120)

        self.setLayout(self.layout)

        self.switcherState.inputsChanged.connect(self.setSources)
        self.setSources()
        self.displayInputs()

    def setSources(self):
        self.sources = [
            vs for vs in VideoSource if vs in self.switcherState.inputs.keys()
        ]

    def displayInputs(self):

        idx = 0
        start = self.page * 15
        end = start + 15

        self.input_buttons.setExclusive(False)
        for btn in self.input_buttons.buttons():
            btn.hide()
            btn.setChecked(False)
        self.input_buttons.setExclusive(True)

        for vs in self.sources[start:end]:
            inp = self.switcherState.inputs[vs]
            row = (idx / 5) * 2
            col = idx % 5

            btn = self.layout.itemAtPosition(row, col).widget()
            btn.setInput(inp)
            btn.setChecked(inp == self.selectedInput)
            btn.show()

            idx += 1

        self.btnPageUp.setEnabled(self.page > 0)
        self.btnPageDown.setEnabled(end < len(self.switcherState.inputs))

    def setPage(self, page):
        self.page = page
        self.displayInputs()

    def selectInput(self):
        inputBtn = self.sender()
        self.selectedInput = inputBtn.input
        self.inputSelected.emit(inputBtn.input)
コード例 #7
0
class CameraControl(QWidget):
    '''
    GUI to control a camera.
    '''

    def __init__(self, camera):
        super(CameraControl, self).__init__()
        self.camera = camera
        self.initUI()
        self.panSpeed = 12
        self.tiltSpeed = 12
        self.zoomSpeed = 6

    def initUI(self):
        layout = QGridLayout()
        self.setLayout(layout)

        self.btnUp = CameraButton()
        layout.addWidget(self.btnUp, 0, 1, 2, 1)
        _safelyConnect(self.btnUp.pressed, lambda: self.camera.moveUp(self.panSpeed, self.tiltSpeed))
        _safelyConnect(self.btnUp.released, self.camera.stop)
        _safelyConnect(self.btnUp.clicked, self.deselectPreset)
        self.btnUp.setIcon(QIcon(":icons/go-up"))

        self.btnLeft = CameraButton()
        layout.addWidget(self.btnLeft, 1, 0, 2, 1)
        _safelyConnect(self.btnLeft.pressed, lambda: self.camera.moveLeft(self.panSpeed, self.tiltSpeed))
        _safelyConnect(self.btnLeft.released, self.camera.stop)
        _safelyConnect(self.btnLeft.clicked, self.deselectPreset)
        self.btnLeft.setIcon(QIcon(":icons/go-previous"))

        self.btnDown = CameraButton()
        layout.addWidget(self.btnDown, 2, 1, 2, 1)
        _safelyConnect(self.btnDown.pressed, lambda: self.camera.moveDown(self.panSpeed, self.tiltSpeed))
        _safelyConnect(self.btnDown.released, self.camera.stop)
        _safelyConnect(self.btnDown.clicked, self.deselectPreset)
        self.btnDown.setIcon(QIcon(":icons/go-down"))

        self.btnRight = CameraButton()
        layout.addWidget(self.btnRight, 1, 2, 2, 1)
        _safelyConnect(self.btnRight.pressed, lambda: self.camera.moveRight(self.panSpeed, self.tiltSpeed))
        _safelyConnect(self.btnRight.released, self.camera.stop)
        _safelyConnect(self.btnRight.clicked, self.deselectPreset)
        self.btnRight.setIcon(QIcon(":icons/go-next"))

        zoomInOut = PlusMinusButtons("Zoom")
        _safelyConnect(zoomInOut.upButton.pressed, lambda: self.camera.zoomIn(self.zoomSpeed))
        _safelyConnect(zoomInOut.upButton.released, self.camera.zoomStop)
        _safelyConnect(zoomInOut.upButton.clicked, self.deselectPreset)
        _safelyConnect(zoomInOut.downButton.pressed, lambda: self.camera.zoomOut(self.zoomSpeed))
        _safelyConnect(zoomInOut.downButton.released, self.camera.zoomStop)
        _safelyConnect(zoomInOut.downButton.clicked, self.deselectPreset)

        layout.addWidget(zoomInOut, 0, 3, 4, 1)

        focus = PlusMinusAutoButtons("Focus")
        _safelyConnect(focus.upButton.pressed, self.camera.focusFar)
        _safelyConnect(focus.upButton.released, self.camera.focusStop)
        _safelyConnect(focus.upButton.clicked, self.deselectPreset)
        _safelyConnect(focus.downButton.pressed, self.camera.focusNear)
        _safelyConnect(focus.downButton.released, self.camera.focusStop)
        _safelyConnect(focus.downButton.clicked, self.deselectPreset)

        def autoFocusAndDeselect():
            self.camera.focusAuto()
            self.deselectPreset()
        _safelyConnect(focus.autoButton.clicked, autoFocusAndDeselect)
        layout.addWidget(focus, 0, 4, 4, 1)

        brightness = PlusMinusAutoButtons("Bright")
        _safelyConnect(brightness.upButton.clicked, self.camera.brighter)
        _safelyConnect(brightness.downButton.clicked, self.camera.darker)
        _safelyConnect(brightness.autoButton.clicked, self.camera.setAutoExposure)
        layout.addWidget(brightness, 0, 5, 4, 1)

        presets = QGridLayout()
        presets.setRowStretch(0, 2)
        presets.setRowStretch(1, 1)

        self.presetGroup = QButtonGroup()

        for i in range(1, 7):
            btnPresetRecall = CameraButton()
            presets.addWidget(btnPresetRecall, 0, i, 1, 1)
            btnPresetRecall.setText(str(i))
            _safelyConnect(btnPresetRecall.clicked, lambda i=i: self.recallPreset(i))
            btnPresetRecall.setCheckable(True)
            self.presetGroup.addButton(btnPresetRecall, i)

            btnPresetSet = CameraButton()
            presets.addWidget(btnPresetSet, 1, i, 1, 1)
            btnPresetSet.setText("Set")
            _safelyConnect(btnPresetSet.clicked, lambda i=i: self.storePreset(i))

        layout.addLayout(presets, 4, 0, 3, 6)

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Left:
            self.btnLeft.pressed.emit()
        elif e.key() == Qt.Key_Right:
            self.btnRight.pressed.emit()
        elif e.key() == Qt.Key_Up:
            self.btnUp.pressed.emit()
        elif e.key() == Qt.Key_Down:
            self.btnDown.pressed.emit()

    def keyReleaseEvent(self, e):
        if e.key() == Qt.Key_Left:
            self.btnLeft.released.emit()
        elif e.key() == Qt.Key_Right:
            self.btnRight.released.emit()
        elif e.key() == Qt.Key_Up:
            self.btnUp.released.emit()
        elif e.key() == Qt.Key_Down:
            self.btnDown.released.emit()

    @handlePyroErrors
    def storePreset(self, index):
        print "Storing preset " + str(index)
        result = self.camera.storePreset(index)
        self.presetGroup.buttons()[index - 1].setChecked(True)
        return result

    @handlePyroErrors
    def recallPreset(self, index):
        print "Recalling preset " + str(index)
        return self.camera.recallPreset(index)

    def deselectPreset(self):
        if self.presetGroup.checkedId() >= 0:
            # Yuck.
            self.presetGroup.setExclusive(False)
            while (self.presetGroup.checkedId() >= 0):
                self.presetGroup.checkedButton().setChecked(False)
            self.presetGroup.setExclusive(True)
コード例 #8
0
ファイル: CameraControls.py プロジェクト: staldates/aldatesx
class CameraControl(QWidget):
    '''
    GUI to control a camera.
    '''

    def __init__(self, controller, cameraID):
        super(CameraControl, self).__init__()
        self.controller = controller
        self.cameraID = cameraID
        self.initUI()

    def initUI(self):
        layout = QGridLayout()
        self.setLayout(layout)

        self.btnUp = CameraButton(CameraMove.Up)
        layout.addWidget(self.btnUp, 0, 1, 2, 1)
        self.btnUp.pressed.connect(self.move)
        self.btnUp.released.connect(self.stop)
        self.btnUp.setIcon(QIcon("icons/go-up.svg"))

        self.btnLeft = CameraButton(CameraMove.Left)
        layout.addWidget(self.btnLeft, 1, 0, 2, 1)
        self.btnLeft.pressed.connect(self.move)
        self.btnLeft.released.connect(self.stop)
        self.btnLeft.setIcon(QIcon("icons/go-previous.svg"))

        self.btnDown = CameraButton(CameraMove.Down)
        layout.addWidget(self.btnDown, 2, 1, 2, 1)
        self.btnDown.pressed.connect(self.move)
        self.btnDown.released.connect(self.stop)
        self.btnDown.setIcon(QIcon("icons/go-down.svg"))

        self.btnRight = CameraButton(CameraMove.Right)
        layout.addWidget(self.btnRight, 1, 2, 2, 1)
        self.btnRight.pressed.connect(self.move)
        self.btnRight.released.connect(self.stop)
        self.btnRight.setIcon(QIcon("icons/go-next.svg"))

        zoomInOut = PlusMinusButtons("Zoom", CameraZoom.Tele, CameraZoom.Wide)
        zoomInOut.connectPressed(self.zoom)
        zoomInOut.connectReleased(self.stopZoom)
        layout.addWidget(zoomInOut, 0, 3, 4, 1)

        focus = PlusMinusAutoButtons("Focus", CameraFocus.Far, CameraFocus.Near, CameraFocus.Auto)
        focus.connectPressed(self.focus)
        focus.connectReleased(self.stopFocus)
        focus.autoButton.clicked.connect(self.focus)
        layout.addWidget(focus, 0, 4, 4, 1)

        brightness = PlusMinusButtons("Brightness", True, False)
        brightness.connectClicked(self.exposure)
        layout.addWidget(brightness, 0, 5, 4, 1)

        presets = QGridLayout()
        presets.setRowStretch(0, 2)
        presets.setRowStretch(1, 1)

        self.presetGroup = QButtonGroup()

        for i in range(0, 6):
            btnPresetRecall = CameraButton(i)
            presets.addWidget(btnPresetRecall, 0, i, 1, 1)
            btnPresetRecall.setText(str(i + 1))
            btnPresetRecall.clicked.connect(self.recallPreset)
            btnPresetRecall.setCheckable(True)
            self.presetGroup.addButton(btnPresetRecall, i)

            btnPresetSet = CameraButton(i)
            presets.addWidget(btnPresetSet, 1, i, 1, 1)
            btnPresetSet.setText("Set")
            btnPresetSet.clicked.connect(self.storePreset)

        layout.addLayout(presets, 4, 0, 3, 6)

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Left:
            self.btnLeft.pressed.emit()
        elif e.key() == Qt.Key_Right:
            self.btnRight.pressed.emit()
        elif e.key() == Qt.Key_Up:
            self.btnUp.pressed.emit()
        elif e.key() == Qt.Key_Down:
            self.btnDown.pressed.emit()

    def keyReleaseEvent(self, e):
        if e.key() == Qt.Key_Left:
            self.btnLeft.released.emit()
        elif e.key() == Qt.Key_Right:
            self.btnRight.released.emit()
        elif e.key() == Qt.Key_Up:
            self.btnUp.released.emit()
        elif e.key() == Qt.Key_Down:
            self.btnDown.released.emit()

    def move(self):
        sender = self.sender()
        try:
            result = self.controller.move(self.cameraID, sender.cameraBinding)
            self.deselectPreset()
            return result
        except NamingError:
            self.errorBox(StringConstants.nameErrorText)
        except ProtocolError:
            self.errorBox(StringConstants.protocolErrorText)

    def stop(self):
        try:
            self.controller.move(self.cameraID, CameraMove.Stop)
        except NamingError:
            self.errorBox(StringConstants.nameErrorText)
        except ProtocolError:
            self.errorBox(StringConstants.protocolErrorText)

    def focus(self):
        sender = self.sender()
        try:
            result = self.controller.focus(self.cameraID, sender.cameraBinding)
            self.deselectPreset()
            return result
        except NamingError:
            self.errorBox(StringConstants.nameErrorText)
        except ProtocolError:
            self.errorBox(StringConstants.protocolErrorText)

    def stopFocus(self):
        try:
            self.controller.focus(self.cameraID, CameraFocus.Stop)
        except NamingError:
            self.errorBox(StringConstants.nameErrorText)
        except ProtocolError:
            self.errorBox(StringConstants.protocolErrorText)

    def zoom(self):
        sender = self.sender()
        try:
            result = self.controller.zoom(self.cameraID, sender.cameraBinding)
            self.deselectPreset()
            return result
        except NamingError:
            self.errorBox(StringConstants.nameErrorText)
        except ProtocolError:
            self.errorBox(StringConstants.protocolErrorText)

    def stopZoom(self):
        try:
            self.controller.zoom(self.cameraID, CameraZoom.Stop)
        except NamingError:
            self.errorBox(StringConstants.nameErrorText)
        except ProtocolError:
            self.errorBox(StringConstants.protocolErrorText)

    def exposure(self):
        sender = self.sender()
        try:
            result = self.controller.backlightComp(self.cameraID, sender.cameraBinding)
            self.deselectPreset()
            return result
        except NamingError:
            self.errorBox(StringConstants.nameErrorText)
        except ProtocolError:
            self.errorBox(StringConstants.protocolErrorText)

    def storePreset(self):
        sender = self.sender()
        try:
            result = self.controller.savePreset(self.cameraID, sender.cameraBinding)
            self.presetGroup.buttons()[sender.cameraBinding].setChecked(True)
            return result
        except NamingError:
            self.errorBox(StringConstants.nameErrorText)
        except ProtocolError:
            self.errorBox(StringConstants.protocolErrorText)

    def recallPreset(self):
        sender = self.sender()
        try:
            return self.controller.recallPreset(self.cameraID, sender.cameraBinding)
        except NamingError:
            self.errorBox(StringConstants.nameErrorText)
        except ProtocolError:
            self.errorBox(StringConstants.protocolErrorText)

    def deselectPreset(self):
        # Yuck.
        self.presetGroup.setExclusive(False)
        while (self.presetGroup.checkedId() >= 0):
            self.presetGroup.checkedButton().setChecked(False)
        self.presetGroup.setExclusive(True)

    def errorBox(self, text):
        msgBox = QMessageBox()
        msgBox.setText(text)
        msgBox.setIcon(QMessageBox.Critical)
        msgBox.exec_()