Пример #1
0
class DelayWidget(StepBaseWidget):
    def __init__(self, step: Steps.Delay):
        super(DelayWidget, self).__init__(step)

        detail_layout = self.ui.detailFrame.layout()
        self.delay_time = QSpinBox()
        detail_layout.addRow("Delay: ", self.delay_time)

        self.delay_time.valueChanged.connect(self.update_delay)

    def update_delay(self):
        self.step.delay = self.delay_time.value()
Пример #2
0
class IntSlider(QWidget):
    """THe IntSlider class provides controller with a handle which can be pulled back
    and forth to change the **integer**.
    """
    def __init__(self):
        super().__init__()
        self._slider = QSlider(Qt.Horizontal)
        self._spinbox = QSpinBox()

        # setup signal
        self._slider.valueChanged.connect(self._value_changed)  # type: ignore
        self._spinbox.valueChanged.connect(self._value_changed)  # type: ignore

        # setup layout
        h_layout = AHBoxLayout(self)
        h_layout.addWidget(self._slider)
        h_layout.addWidget(self._spinbox)

    @property
    def current_value(self) -> int:
        return self._spinbox.value()

    @property
    def range(self) -> tuple[int, int]:
        return (self._slider.minimum(), self._slider.maximum())

    @range.setter
    def range(self, range: tuple[int, int]) -> None:
        self._slider.setRange(*range)
        self._spinbox.setRange(*range)

    @Slot(int)  # type: ignore
    def _value_changed(self, value: int) -> None:
        sender = self.sender()
        if sender is self._slider:
            self._spinbox.blockSignals(True)
            self._spinbox.setValue(value)
            self._spinbox.blockSignals(False)
        elif sender is self._spinbox:
            self._slider.blockSignals(True)
            self._slider.setValue(value)
            self._slider.blockSignals(False)

    def update_current_value(self, num: int) -> None:
        """Update current number of this widget. This method changes the display of the gui.

        Parameters
        ----------
        num : int
            Integer.
        """
        self._spinbox.setValue(num)
Пример #3
0
class WaitForImageWidget(StepBaseWidget):
    def __init__(self, step: Steps.WaitForImage):
        super(WaitForImageWidget, self).__init__(step)

        detail_layout: QFormLayout = self.ui.detailFrame.layout()

        # Image selection
        self.image_label = QLabel()
        self.image_button = QPushButton("Select Image")

        # Timeout Input
        self.timeout_spin = QSpinBox()

        # Signal/Slots
        self.timeout_spin.valueChanged.connect(self.update_timeout)
        self.image_button.clicked.connect(self.update_image)

        # Widget insert
        detail_layout.addRow("Image: ", self.image_label)
        detail_layout.addRow("", self.image_button)
        detail_layout.addRow("Timeout: ", self.timeout_spin)

        # Init
        self.image_label.setText(self.step.image)
        self.timeout_spin.setValue(self.step.timeout)

        if not self.image_label.text():
            self.image_label.setText("No image selected")

    def update_image(self):
        file_name = QFileDialog.getOpenFileName(
            parent=None,
            caption="Choose Image to Find",
            dir=self.timeline.manager.resource_pool.as_posix(),
            filter="Images (*.png *.jpg)",
        )

        if not file_name:
            print("Canceled selection")
            return

        self.step.image = file_name[0]
        self.image_label.setText(self.step.image)

        if not self.image_label.text():
            self.image_label.setText("No image selected")

    def update_timeout(self):
        self.step.timeout = self.timeout_spin.value()
Пример #4
0
class Form(QDialog):

    def __init__(self, parent=None):
        super(Form, self).__init__(parent)
        self.title = "Emoji Splitter"
        self.setWindowTitle(self.title)

        # preview_split widget
        self.preview_widget = QLabel()
        # media_preview = QPixmap('C:/Users/roela/PycharmProjects/Emojisplitter/bolkvis.png')
        # media_preview = QMovie('Naamloos.gif')  # QPixmap('Naamloos.gif')
        self.media_preview('Naamloos.gif')

        # embed preview_split in a scrollable window
        self.preview_scroll_area = QScrollArea()
        self.preview_scroll_area.setWidget(self.preview_widget)
        self.preview_scroll_area.setBackgroundRole(QPalette.Dark)
        self.preview_scroll_area.setWidgetResizable(True)

        # Create button widgets
        self.open_file_button = QPushButton("Select &File")
        self.filename = QLineEdit("C:/Users/roela/PycharmProjects/Emojisplitter/Naamloos.gif")
        self.preview_button = QPushButton("&Preview Split")
        self.fit_to_window_checkbox = QCheckBox("Fit Preview Image to &Window")
        self.horizontal_emojis_spinbox = QSpinBox()
        self.horizontal_emojis_spinbox.setMinimum(1)
        self.horizontal_emojis_label = QLabel("Number of &horizontal emojis:")
        self.horizontal_emojis_label.setBuddy(self.horizontal_emojis_spinbox)
        self.vertical_emojis_spinbox = QSpinBox()
        self.vertical_emojis_spinbox.setMinimum(1)
        self.vertical_emojis_label = QLabel("Number of &vertical emojis:")
        self.vertical_emojis_label.setBuddy(self.vertical_emojis_spinbox)
        self.split_emojis_button = QPushButton("&Split Emoji")
        self.results_folder_button = QPushButton("Open folder with &results")

        # give the button_layout a fixed width
        button_container = QWidget()
        button_container.setFixedWidth(256)

        # Create layout and add widgets
        button_layout = QVBoxLayout(button_container)
        button_layout.addWidget(self.open_file_button)
        button_layout.addWidget(self.filename)

        # Put labels next to spinboxes
        horizontal_emojis_layout = QHBoxLayout()
        horizontal_emojis_layout.addWidget(self.horizontal_emojis_label)
        horizontal_emojis_layout.addWidget(self.horizontal_emojis_spinbox)

        vertical_emojis_layout = QHBoxLayout()
        vertical_emojis_layout.addWidget(self.vertical_emojis_label)
        vertical_emojis_layout.addWidget(self.vertical_emojis_spinbox)

        button_layout.addLayout(horizontal_emojis_layout)
        button_layout.addLayout(vertical_emojis_layout)

        button_layout.addWidget(self.preview_button)
        button_layout.addWidget(self.fit_to_window_checkbox)
        button_layout.addWidget(self.split_emojis_button)
        button_layout.addWidget(self.results_folder_button)

        preview_layout = QVBoxLayout()
        # preview_layout.addWidget(self.preview_widget)
        preview_layout.addWidget(self.preview_scroll_area)

        # combine button and preview_split layout
        nested_layout = QHBoxLayout()
        nested_layout.addWidget(button_container)
        nested_layout.addLayout(preview_layout)
        # Set dialog layout
        self.setLayout(nested_layout)

        # Add button functions
        self.open_file_button.clicked.connect(self.open_file)
        self.preview_button.clicked.connect(self.preview_split)
        self.fit_to_window_checkbox.clicked.connect(self.fit_to_window)
        self.split_emojis_button.clicked.connect(self.split)
        self.results_folder_button.clicked.connect(self.open_folder_with_results)

        # update preview_split on changing value of a spinbox
        self.horizontal_emojis_spinbox.valueChanged.connect(self.preview_split)
        self.vertical_emojis_spinbox.valueChanged.connect(self.preview_split)

    # Preview the image.
    def preview_split(self):
        preview_image = emojisplitter.emojisplitter(self.filename.text(),
                                                    self.horizontal_emojis_spinbox.value(),
                                                    self.vertical_emojis_spinbox.value(),
                                                    False)
        self.preview_widget.setPixmap(preview_image)
        if self.fit_to_window_checkbox.checkState():
            self.fit_to_window()

    # Fit the image to the current window
    def fit_to_window(self):
        self.preview_widget.setPixmap(
            self.preview_widget.pixmap().scaled(self.preview_scroll_area.width(),
                                                self.preview_scroll_area.height(),
                                                aspectMode=Qt.KeepAspectRatio))

    # open file
    def open_file(self):
        self.filename.setText(QFileDialog.getOpenFileName(self, "Open Image")[0])
        self.media_preview(self.filename.text())

    def media_preview(self, filename):
        media_preview = QMovie(filename)
        self.preview_widget.setMovie(media_preview)
        self.preview_widget.movie().start()
        self.preview_widget.resize(media_preview.currentPixmap().width(), media_preview.currentPixmap().height())
        # self.preview_split()  # This immediately show where the split would be

    def split(self):
        emojisplitter.emojisplitter(self.filename.text(),
                                    self.horizontal_emojis_spinbox.value(),
                                    self.vertical_emojis_spinbox.value(),
                                    True)

    def open_folder_with_results(self):
        path = Path(self.filename.text()).parent
        webbrowser.open('file:///' + str(path))
Пример #5
0
class DeviceItem(QWidget):
    numberChanged = Signal()

    def __init__(self, device: RigDevice):
        super().__init__()

        self.device = device

        self._nameLabel = QLabel(device.serialNumber)
        self._statusLabel = QLabel("")
        self._startNumberDial = QSpinBox()
        self._startNumberDial.setMinimum(0)
        self._startNumberDial.setMaximum(9999)
        self._startNumberDial.setValue(device.startNumber)
        self._startNumberDial.valueChanged.connect(self.SetStartNumber)

        self._enableToggle = QToolButton()
        self._enableToggle.clicked.connect(self.ToggleEnable)
        self._enableToggle.setText("Disable")

        self._layout = QHBoxLayout()
        self.setLayout(self._layout)

        self._layout.addWidget(self._nameLabel, stretch=1)
        self._layout.addWidget(self._statusLabel, stretch=1)
        self._layout.addWidget(self._enableToggle)
        self._layout.addWidget(self._startNumberDial)
        self._layout.addStretch(1)

        solenoidLabelLayout = QVBoxLayout()
        solenoidLabelLayout.addWidget(QLabel("State"), alignment=Qt.AlignRight)
        solenoidLabelLayout.addWidget(QLabel("Invert"),
                                      alignment=Qt.AlignRight)

        self._layout.addLayout(solenoidLabelLayout)
        self._layout.addSpacing(5)

        self._solenoidButtons: List[SolenoidButton] = []
        for solenoidNumber in range(24):
            newButton = SolenoidButton(
                solenoidNumber, device.solenoidPolarities[solenoidNumber])
            newButton.solenoidClicked.connect(
                lambda s=newButton: self.ToggleSolenoid(s))
            newButton.polarityClicked.connect(
                lambda s=newButton: self.TogglePolarity(s))
            self._solenoidButtons.append(newButton)
            self._layout.addWidget(newButton, stretch=0)

        self.Update()

    def SetStartNumber(self):
        self.device.startNumber = self._startNumberDial.value()
        self.Update()
        self.numberChanged.emit()

    def ToggleEnable(self):
        self.device.SetEnabled(not self.device.isEnabled)
        self.Update()

    def ToggleSolenoid(self, button: 'SolenoidButton'):
        index = self._solenoidButtons.index(button)
        AppGlobals.Rig().SetSolenoidState(
            self.device.startNumber + index,
            not AppGlobals.Rig().GetSolenoidState(self.device.startNumber +
                                                  index))
        AppGlobals.Rig().FlushStates()
        self.Update()

    def TogglePolarity(self, button: 'SolenoidButton'):
        index = self._solenoidButtons.index(button)
        self.device.solenoidPolarities[
            index] = not self.device.solenoidPolarities[index]
        AppGlobals.Rig().FlushStates()
        self.Update()

    def Update(self):
        if not self.device.IsDeviceAvailable():
            self.deleteLater()
            return

        if self.device.isConnected:
            self._statusLabel.setText("Connected.")
        else:
            if self.device.isEnabled:
                self._statusLabel.setText(self.device.errorMessage)
            else:
                self._statusLabel.setText("Disabled.")

        self._enableToggle.setText({
            False: "Enable",
            True: "Disable"
        }[self.device.isEnabled])
        self._startNumberDial.setEnabled(self.device.isEnabled
                                         and self.device.isConnected)
        for i in range(24):
            self._solenoidButtons[i].setEnabled(self.device.isConnected
                                                and self.device.isEnabled)
            self._solenoidButtons[i].Update(self.device.startNumber + i,
                                            self.device.solenoidPolarities[i])
Пример #6
0
class PomoTimer(QWidget, BaseTimer):
    """
    PomoTimer: Pomodoro タイマーを提供する。

    1 pomodoro: 25min
    short break: 5min
    long break: 15min
    long break after 4pomodoro.
    """

    paused = Signal()

    def __init__(self):
        super().__init__()
        self.simple_timer = SimpleTimer(self)

        self.settings = {
            'pomo': 25,
            'short_break': 5,
            'long_break': 15,
            'long_break_after': 4
        }
        self.state_dict = {
            'work': 'Work!',
            'break': 'Break.',
            'pause': 'Pause',
            'wait': "Let's start."
        }
        self.work_timer = QTimer(self)
        self.work_timer.setSingleShot(True)
        self.break_timer = QTimer(self)
        self.break_timer.setSingleShot(True)

        self.pomo_count = 0
        self.pomo_count_lbl = QLabel(self)
        self.pomo_count_lbl.setText(f'{self.pomo_count} pomodoro finished.')
        self.state_lbl = QLabel(self)
        self.state_lbl.setText(self.state_dict['wait'])
        self.estimate_pomo = 0
        self.estimate_label = QLabel(self)
        self.estimate_label.setText('Estimate: ')
        self.estimate_pomo_widget = QSpinBox(self)
        self.estimate_pomo_widget.setValue(4)
        self.estimate_pomo_widget.setSuffix('  pomo')
        self.estimate_pomo_widget.setRange(1, 20)

        self.set_ui()
        self.set_connection()

    def set_ui(self):
        layout = self.simple_timer.layout()
        i = layout.indexOf(self.simple_timer.timer_edit)
        layout.takeAt(i)
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.estimate_label)
        hlayout.addWidget(self.estimate_pomo_widget)

        vlayout = QVBoxLayout()
        vlayout.addLayout(hlayout)
        vlayout.addWidget(self.pomo_count_lbl)
        vlayout.addWidget(self.state_lbl)
        vlayout.addWidget(self.simple_timer)
        self.setLayout(vlayout)

    def set_connection(self):
        self.work_timer.timeout.connect(self.timeout)
        self.break_timer.timeout.connect(self.start_work)

    def start(self):
        self.estimate_pomo = self.estimate_pomo_widget.value()
        self.start_work()

    def start_work(self):
        """
        Start timer for working on the task.
        :return:
        """
        self.state_lbl.setText(self.state_dict['work'])
        self.simple_timer.timer = self.work_timer
        self.simple_timer.timer_edit.setValue(self.settings['pomo'])
        self.simple_timer.start()
        self.started.emit()

    def start_break(self):
        """
        Start timer for working on the rest.
        Short break is normal break, long break comes every some tasks(default 4).
        :return:
        """
        self.state_lbl.setText(self.state_dict['break'])
        self.simple_timer.timer = self.break_timer
        if self.pomo_count % self.settings['long_break_after']:
            self.simple_timer.timer_edit.setValue(self.settings['short_break'])
        else:
            self.simple_timer.timer_edit.setValue(self.settings['long_break'])
        self.simple_timer.start()
        self.started.emit()

    def abort(self):
        self.reset()
        self.aborted.emit()

    def pause(self):
        self.state_lbl.setText(self.state_dict['pause'])
        self.simple_timer.pause()
        self.paused.emit()

    def resume(self):
        self.state_lbl.setText(self.state_dict['work'])
        self.simple_timer.resume()
        self.started.emit()

    def timeout(self):
        self.pomo_count += 1
        if self.pomo_count >= self.estimate_pomo:
            self.reset()
            self.finished.emit()
        else:
            self.start_break()

    def reset(self):
        self.pomo_count = 0
        self.simple_timer.reset()
        self.work_timer.stop()
        self.break_timer.stop()
        self.state_lbl.setText(self.state_dict['wait'])

    def get_notify_message(self):
        return ''

    @property
    def name(self):
        return 'Pomo Timer'

    def fake_start(self):
        self.simple_timer.setting_time = self.simple_timer.timer_edit.value()
        self.simple_timer.timer.start(self.simple_timer.setting_time * 1000)
        self.simple_timer.set_remain_update()
        self.simple_timer.started.emit()
Пример #7
0
class SimpleTimer(QWidget, BaseTimer):

    paused = Signal()

    def __init__(self, parent=None):

        super().__init__(parent)
        self.timer = QTimer(self)
        self.timer.setSingleShot(True)
        self.update_timer = QTimer(self)
        self.setting_time = 0
        self.remaining = 0

        self.remain_label = QLabel('00:00', self)
        self.remain_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.remain_label.setScaledContents(True)
        font = QFont()
        font.setPointSize(86)
        self.remain_label.setFont(font)
        self.timer_edit = QSpinBox(self)
        self.timer_edit.setRange(1, 99)
        self.timer_edit.setValue(25)

        self.set_ui()
        self.set_connection()

        self.show()

    def set_ui(self):
        vlayout = QVBoxLayout()
        vlayout.addWidget(self.remain_label, alignment=Qt.AlignHCenter)
        vlayout.addWidget(self.timer_edit)
        self.setLayout(vlayout)

    def set_connection(self):
        self.timer.timeout.connect(self.stop)
        self.update_timer.timeout.connect(self.remain_update)

    def start(self):
        self.setting_time = self.timer_edit.value()
        self.timer.start(self.setting_time * 60 * 1000)
        self.set_remain_update()
        self.started.emit()

    def set_remain_update(self):
        self.remain_update()
        self.update_timer.start(250)

    def stop(self):
        self.reset()
        self.finished.emit()

    def abort(self):
        self.reset()
        self.timer.stop()
        self.aborted.emit()

    def pause(self):
        self.update_timer.stop()
        self.remaining = self.timer.remainingTime()
        self.timer.stop()
        self.paused.emit()

    def resume(self):
        self.timer.start(self.remaining)
        self.set_remain_update()
        self.started.emit()

    def reset(self):
        self.timer.stop()
        self.update_timer.stop()
        self.remain_label.setText('00:00')
        self.remaining = 0

    def get_notify_message(self):
        remaining = self.timer.remainingTime() / 1000
        return '{0} minutes have passed.'.format(self.setting_time - int(remaining/60))

    def remain_update(self):
        remaining = self.timer.remainingTime() / 1000
        self.remain_label.setText('{min:02}:{sec:02}'.format(
            min=int(remaining / 60), sec=int(remaining % 60)))

    @property
    def name(self):
        return 'Simple Timer'
Пример #8
0
class ValveChipItem(WidgetChipItem):
    def __init__(self, valve: Valve):
        super().__init__()

        AppGlobals.Instance().onChipModified.connect(self.CheckForValve)

        self._valve = valve

        self.valveToggleButton = QToolButton()
        self.valveNumberLabel = QLabel("Number")
        self.valveNumberDial = QSpinBox()
        self.valveNumberDial.setMinimum(0)
        self.valveNumberDial.setValue(self._valve.solenoidNumber)
        self.valveNumberDial.setMaximum(9999)
        self.valveNumberDial.valueChanged.connect(self.UpdateValve)

        self.valveNameLabel = QLabel("Name")
        self.valveNameField = QLineEdit(self._valve.name)
        self.valveNameField.textChanged.connect(self.UpdateValve)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.valveToggleButton, alignment=Qt.AlignCenter)

        layout = QGridLayout()
        layout.addWidget(self.valveNameLabel, 0, 0)
        layout.addWidget(self.valveNameField, 0, 1)
        layout.addWidget(self.valveNumberLabel, 1, 0)
        layout.addWidget(self.valveNumberDial, 1, 1)

        mainLayout.addLayout(layout)
        self.containerWidget.setLayout(mainLayout)
        self.valveToggleButton.clicked.connect(self.Toggle)

        self.Update()
        self.Move(QPointF())

    def CheckForValve(self):
        if self._valve not in AppGlobals.Chip().valves:
            self.RemoveItem()

    def Move(self, delta: QPointF):
        if delta != QPointF():
            AppGlobals.Instance().onChipDataModified.emit()
        self._valve.position += delta
        self.GraphicsObject().setPos(self._valve.position)

    def SetEditDisplay(self, editing: bool):
        self.valveNameField.setVisible(editing)
        self.valveNameLabel.setVisible(editing)
        self.valveNumberLabel.setVisible(editing)
        self.valveNumberDial.setVisible(editing)
        super().SetEditDisplay(editing)

    def UpdateValve(self):
        self._valve.solenoidNumber = self.valveNumberDial.value()
        self._valve.name = self.valveNameField.text()
        AppGlobals.Instance().onChipDataModified.emit()

    def Toggle(self):
        AppGlobals.Rig().SetSolenoidState(
            self._valve.solenoidNumber,
            not AppGlobals.Rig().GetSolenoidState(self._valve.solenoidNumber),
            True)

    def RequestDelete(self):
        AppGlobals.Chip().valves.remove(self._valve)
        AppGlobals.Instance().onChipModified.emit()

    def Duplicate(self) -> 'ChipItem':
        newValve = Valve()
        newValve.position = QPointF(self._valve.position)
        newValve.name = self._valve.name
        newValve.solenoidNumber = AppGlobals.Chip().NextSolenoidNumber()

        AppGlobals.Chip().valves.append(newValve)
        AppGlobals.Instance().onChipModified.emit()
        return ValveChipItem(newValve)

    def Update(self):
        text = self._valve.name + "\n(" + str(self._valve.solenoidNumber) + ")"
        if text != self.valveToggleButton.text():
            self.valveToggleButton.setText(text)

        lastState = self.valveToggleButton.property("valveState")
        newState = {
            True: "OPEN",
            False: "CLOSED"
        }[AppGlobals.Rig().GetSolenoidState(self._valve.solenoidNumber)]
        if lastState != newState:
            self.valveToggleButton.setProperty("valveState", newState)
            self.valveToggleButton.setStyle(self.valveToggleButton.style())
Пример #9
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.renderArea = RenderArea()

        self.shapeComboBox = QComboBox()
        self.shapeComboBox.addItem("Polygon", RenderArea.Polygon)
        self.shapeComboBox.addItem("Rectangle", RenderArea.Rect)
        self.shapeComboBox.addItem("Rounded Rectangle", RenderArea.RoundedRect)
        self.shapeComboBox.addItem("Ellipse", RenderArea.Ellipse)
        self.shapeComboBox.addItem("Pie", RenderArea.Pie)
        self.shapeComboBox.addItem("Chord", RenderArea.Chord)
        self.shapeComboBox.addItem("Path", RenderArea.Path)
        self.shapeComboBox.addItem("Line", RenderArea.Line)
        self.shapeComboBox.addItem("Polyline", RenderArea.Polyline)
        self.shapeComboBox.addItem("Arc", RenderArea.Arc)
        self.shapeComboBox.addItem("Points", RenderArea.Points)
        self.shapeComboBox.addItem("Text", RenderArea.Text)
        self.shapeComboBox.addItem("Pixmap", RenderArea.Pixmap)

        shapeLabel = QLabel("&Shape:")
        shapeLabel.setBuddy(self.shapeComboBox)

        self.penWidthSpinBox = QSpinBox()
        self.penWidthSpinBox.setRange(0, 20)
        self.penWidthSpinBox.setSpecialValueText("0 (cosmetic pen)")

        penWidthLabel = QLabel("Pen &Width:")
        penWidthLabel.setBuddy(self.penWidthSpinBox)

        self.penStyleComboBox = QComboBox()
        self.penStyleComboBox.addItem("Solid", Qt.SolidLine)
        self.penStyleComboBox.addItem("Dash", Qt.DashLine)
        self.penStyleComboBox.addItem("Dot", Qt.DotLine)
        self.penStyleComboBox.addItem("Dash Dot", Qt.DashDotLine)
        self.penStyleComboBox.addItem("Dash Dot Dot", Qt.DashDotDotLine)
        self.penStyleComboBox.addItem("None", Qt.NoPen)

        penStyleLabel = QLabel("&Pen Style:")
        penStyleLabel.setBuddy(self.penStyleComboBox)

        self.penCapComboBox = QComboBox()
        self.penCapComboBox.addItem("Flat", Qt.FlatCap)
        self.penCapComboBox.addItem("Square", Qt.SquareCap)
        self.penCapComboBox.addItem("Round", Qt.RoundCap)

        penCapLabel = QLabel("Pen &Cap:")
        penCapLabel.setBuddy(self.penCapComboBox)

        self.penJoinComboBox = QComboBox()
        self.penJoinComboBox.addItem("Miter", Qt.MiterJoin)
        self.penJoinComboBox.addItem("Bevel", Qt.BevelJoin)
        self.penJoinComboBox.addItem("Round", Qt.RoundJoin)

        penJoinLabel = QLabel("Pen &Join:")
        penJoinLabel.setBuddy(self.penJoinComboBox)

        self.brushStyleComboBox = QComboBox()
        self.brushStyleComboBox.addItem("Linear Gradient",
                                        Qt.LinearGradientPattern)
        self.brushStyleComboBox.addItem("Radial Gradient",
                                        Qt.RadialGradientPattern)
        self.brushStyleComboBox.addItem("Conical Gradient",
                                        Qt.ConicalGradientPattern)
        self.brushStyleComboBox.addItem("Texture", Qt.TexturePattern)
        self.brushStyleComboBox.addItem("Solid", Qt.SolidPattern)
        self.brushStyleComboBox.addItem("Horizontal", Qt.HorPattern)
        self.brushStyleComboBox.addItem("Vertical", Qt.VerPattern)
        self.brushStyleComboBox.addItem("Cross", Qt.CrossPattern)
        self.brushStyleComboBox.addItem("Backward Diagonal", Qt.BDiagPattern)
        self.brushStyleComboBox.addItem("Forward Diagonal", Qt.FDiagPattern)
        self.brushStyleComboBox.addItem("Diagonal Cross", Qt.DiagCrossPattern)
        self.brushStyleComboBox.addItem("Dense 1", Qt.Dense1Pattern)
        self.brushStyleComboBox.addItem("Dense 2", Qt.Dense2Pattern)
        self.brushStyleComboBox.addItem("Dense 3", Qt.Dense3Pattern)
        self.brushStyleComboBox.addItem("Dense 4", Qt.Dense4Pattern)
        self.brushStyleComboBox.addItem("Dense 5", Qt.Dense5Pattern)
        self.brushStyleComboBox.addItem("Dense 6", Qt.Dense6Pattern)
        self.brushStyleComboBox.addItem("Dense 7", Qt.Dense7Pattern)
        self.brushStyleComboBox.addItem("None", Qt.NoBrush)

        brushStyleLabel = QLabel("&Brush Style:")
        brushStyleLabel.setBuddy(self.brushStyleComboBox)

        otherOptionsLabel = QLabel("Other Options:")
        self.antialiasingCheckBox = QCheckBox("&Antialiasing")
        self.transformationsCheckBox = QCheckBox("&Transformations")

        self.shapeComboBox.activated.connect(self.shapeChanged)
        self.penWidthSpinBox.valueChanged.connect(self.penChanged)
        self.penStyleComboBox.activated.connect(self.penChanged)
        self.penCapComboBox.activated.connect(self.penChanged)
        self.penJoinComboBox.activated.connect(self.penChanged)
        self.brushStyleComboBox.activated.connect(self.brushChanged)
        self.antialiasingCheckBox.toggled.connect(
            self.renderArea.setAntialiased)
        self.transformationsCheckBox.toggled.connect(
            self.renderArea.setTransformed)

        mainLayout = QGridLayout()
        mainLayout.setColumnStretch(0, 1)
        mainLayout.setColumnStretch(3, 1)
        mainLayout.addWidget(self.renderArea, 0, 0, 1, 4)
        mainLayout.setRowMinimumHeight(1, 6)
        mainLayout.addWidget(shapeLabel, 2, 1, Qt.AlignRight)
        mainLayout.addWidget(self.shapeComboBox, 2, 2)
        mainLayout.addWidget(penWidthLabel, 3, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penWidthSpinBox, 3, 2)
        mainLayout.addWidget(penStyleLabel, 4, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penStyleComboBox, 4, 2)
        mainLayout.addWidget(penCapLabel, 5, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penCapComboBox, 5, 2)
        mainLayout.addWidget(penJoinLabel, 6, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penJoinComboBox, 6, 2)
        mainLayout.addWidget(brushStyleLabel, 7, 1, Qt.AlignRight)
        mainLayout.addWidget(self.brushStyleComboBox, 7, 2)
        mainLayout.setRowMinimumHeight(8, 6)
        mainLayout.addWidget(otherOptionsLabel, 9, 1, Qt.AlignRight)
        mainLayout.addWidget(self.antialiasingCheckBox, 9, 2)
        mainLayout.addWidget(self.transformationsCheckBox, 10, 2)
        self.setLayout(mainLayout)

        self.shapeChanged()
        self.penChanged()
        self.brushChanged()
        self.antialiasingCheckBox.setChecked(True)

        self.setWindowTitle("Basic Drawing")

    def shapeChanged(self):
        shape = self.shapeComboBox.itemData(self.shapeComboBox.currentIndex(),
                                            IdRole)
        self.renderArea.setShape(shape)

    def penChanged(self):
        width = self.penWidthSpinBox.value()
        style = Qt.PenStyle(
            self.penStyleComboBox.itemData(
                self.penStyleComboBox.currentIndex(), IdRole))
        cap = Qt.PenCapStyle(
            self.penCapComboBox.itemData(self.penCapComboBox.currentIndex(),
                                         IdRole))
        join = Qt.PenJoinStyle(
            self.penJoinComboBox.itemData(self.penJoinComboBox.currentIndex(),
                                          IdRole))

        self.renderArea.setPen(QPen(Qt.blue, width, style, cap, join))

    def brushChanged(self):
        style = Qt.BrushStyle(
            self.brushStyleComboBox.itemData(
                self.brushStyleComboBox.currentIndex(), IdRole))

        if style == Qt.LinearGradientPattern:
            linearGradient = QLinearGradient(0, 0, 100, 100)
            linearGradient.setColorAt(0.0, Qt.white)
            linearGradient.setColorAt(0.2, Qt.green)
            linearGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(linearGradient))
        elif style == Qt.RadialGradientPattern:
            radialGradient = QRadialGradient(50, 50, 50, 70, 70)
            radialGradient.setColorAt(0.0, Qt.white)
            radialGradient.setColorAt(0.2, Qt.green)
            radialGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(radialGradient))
        elif style == Qt.ConicalGradientPattern:
            conicalGradient = QConicalGradient(50, 50, 150)
            conicalGradient.setColorAt(0.0, Qt.white)
            conicalGradient.setColorAt(0.2, Qt.green)
            conicalGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(conicalGradient))
        elif style == Qt.TexturePattern:
            self.renderArea.setBrush(QBrush(QPixmap(':/images/brick.png')))
        else:
            self.renderArea.setBrush(QBrush(Qt.green, style))
Пример #10
0
class Window(QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        self.iconGroupBox = QGroupBox()
        self.iconLabel = QLabel()
        self.iconComboBox = QComboBox()
        self.showIconCheckBox = QCheckBox()

        self.messageGroupBox = QGroupBox()
        self.typeLabel = QLabel()
        self.durationLabel = QLabel()
        self.durationWarningLabel = QLabel()
        self.titleLabel = QLabel()
        self.bodyLabel = QLabel()

        self.typeComboBox = QComboBox()
        self.durationSpinBox = QSpinBox()
        self.titleEdit = QLineEdit()
        self.bodyEdit = QTextEdit()
        self.showMessageButton = QPushButton()

        self.minimizeAction = QAction()
        self.maximizeAction = QAction()
        self.restoreAction = QAction()
        self.quitAction = QAction()

        self.trayIcon = QSystemTrayIcon()
        self.trayIconMenu = QMenu()

        self.createIconGroupBox()
        self.createMessageGroupBox()

        self.iconLabel.setMinimumWidth(self.durationLabel.sizeHint().width())

        self.createActions()
        self.createTrayIcon()

        self.showMessageButton.clicked.connect(self.showMessage)
        self.showIconCheckBox.toggled.connect(self.trayIcon.setVisible)
        self.iconComboBox.currentIndexChanged.connect(self.setIcon)
        self.trayIcon.messageClicked.connect(self.messageClicked)
        self.trayIcon.activated.connect(self.iconActivated)

        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.iconGroupBox)
        self.mainLayout.addWidget(self.messageGroupBox)
        self.setLayout(self.mainLayout)

        self.iconComboBox.setCurrentIndex(1)
        self.trayIcon.show()

        self.setWindowTitle("Systray")
        self.resize(400, 300)

    def setVisible(self, visible):
        self.minimizeAction.setEnabled(visible)
        self.maximizeAction.setEnabled(not self.isMaximized())
        self.restoreAction.setEnabled(self.isMaximized() or not visible)
        super().setVisible(visible)

    def closeEvent(self, event):
        if not event.spontaneous() or not self.isVisible():
            return
        if self.trayIcon.isVisible():
            QMessageBox.information(
                self, "Systray",
                "The program will keep running in the system tray. "
                "To terminate the program, choose <b>Quit</b> in the context "
                "menu of the system tray entry.")
            self.hide()
            event.ignore()

    @Slot(int)
    def setIcon(self, index):
        icon = self.iconComboBox.itemIcon(index)
        self.trayIcon.setIcon(icon)
        self.setWindowIcon(icon)
        self.trayIcon.setToolTip(self.iconComboBox.itemText(index))

    @Slot(str)
    def iconActivated(self, reason):
        if reason == QSystemTrayIcon.Trigger:
            pass
        if reason == QSystemTrayIcon.DoubleClick:
            self.iconComboBox.setCurrentIndex(
                (self.iconComboBox.currentIndex() + 1) %
                self.iconComboBox.count())
        if reason == QSystemTrayIcon.MiddleClick:
            self.showMessage()

    @Slot()
    def showMessage(self):
        self.showIconCheckBox.setChecked(True)
        selectedIcon = self.typeComboBox.itemData(
            self.typeComboBox.currentIndex())
        msgIcon = QSystemTrayIcon.MessageIcon(selectedIcon)

        if selectedIcon == -1:  # custom icon
            icon = QIcon(
                self.iconComboBox.itemIcon(self.iconComboBox.currentIndex()))
            self.trayIcon.showMessage(
                self.titleEdit.text(),
                self.bodyEdit.toPlainText(),
                icon,
                self.durationSpinBox.value() * 1000,
            )
        else:
            self.trayIcon.showMessage(
                self.titleEdit.text(),
                self.bodyEdit.toPlainText(),
                msgIcon,
                self.durationSpinBox.value() * 1000,
            )

    @Slot()
    def messageClicked(self):
        QMessageBox.information(
            None, "Systray", "Sorry, I already gave what help I could.\n"
            "Maybe you should try asking a human?")

    def createIconGroupBox(self):
        self.iconGroupBox = QGroupBox("Tray Icon")

        self.iconLabel = QLabel("Icon:")

        self.iconComboBox = QComboBox()
        self.iconComboBox.addItem(QIcon(":/images/bad.png"), "Bad")
        self.iconComboBox.addItem(QIcon(":/images/heart.png"), "Heart")
        self.iconComboBox.addItem(QIcon(":/images/trash.png"), "Trash")

        self.showIconCheckBox = QCheckBox("Show icon")
        self.showIconCheckBox.setChecked(True)

        iconLayout = QHBoxLayout()
        iconLayout.addWidget(self.iconLabel)
        iconLayout.addWidget(self.iconComboBox)
        iconLayout.addStretch()
        iconLayout.addWidget(self.showIconCheckBox)
        self.iconGroupBox.setLayout(iconLayout)

    def createMessageGroupBox(self):
        self.messageGroupBox = QGroupBox("Balloon Message")

        self.typeLabel = QLabel("Type:")

        self.typeComboBox = QComboBox()
        self.typeComboBox.addItem("None", QSystemTrayIcon.NoIcon)
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxInformation),
            "Information",
            QSystemTrayIcon.Information,
        )
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxWarning),
            "Warning",
            QSystemTrayIcon.Warning,
        )
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxCritical),
            "Critical",
            QSystemTrayIcon.Critical,
        )
        self.typeComboBox.addItem(QIcon(), "Custom icon", -1)
        self.typeComboBox.setCurrentIndex(1)

        self.durationLabel = QLabel("Duration:")

        self.durationSpinBox = QSpinBox()
        self.durationSpinBox.setRange(5, 60)
        self.durationSpinBox.setSuffix(" s")
        self.durationSpinBox.setValue(15)

        self.durationWarningLabel = QLabel(
            "(some systems might ignore this hint)")
        self.durationWarningLabel.setIndent(10)

        self.titleLabel = QLabel("Title:")
        self.titleEdit = QLineEdit("Cannot connect to network")
        self.bodyLabel = QLabel("Body:")

        self.bodyEdit = QTextEdit()
        self.bodyEdit.setPlainText(
            "Don't believe me. Honestly, I don't have a clue."
            "\nClick this balloon for details.")

        self.showMessageButton = QPushButton("Show Message")
        self.showMessageButton.setDefault(True)

        messageLayout = QGridLayout()
        messageLayout.addWidget(self.typeLabel, 0, 0)
        messageLayout.addWidget(self.typeComboBox, 0, 1, 1, 2)
        messageLayout.addWidget(self.durationLabel, 1, 0)
        messageLayout.addWidget(self.durationSpinBox, 1, 1)
        messageLayout.addWidget(self.durationWarningLabel, 1, 2, 1, 3)
        messageLayout.addWidget(self.titleLabel, 2, 0)
        messageLayout.addWidget(self.titleEdit, 2, 1, 1, 4)
        messageLayout.addWidget(self.bodyLabel, 3, 0)
        messageLayout.addWidget(self.bodyEdit, 3, 1, 2, 4)
        messageLayout.addWidget(self.showMessageButton, 5, 4)
        messageLayout.setColumnStretch(3, 1)
        messageLayout.setRowStretch(4, 1)
        self.messageGroupBox.setLayout(messageLayout)

    def createActions(self):
        self.minimizeAction = QAction("Minimize", self)
        self.minimizeAction.triggered.connect(self.hide)

        self.maximizeAction = QAction("Maximize", self)
        self.maximizeAction.triggered.connect(self.showMaximized)

        self.restoreAction = QAction("Restore", self)
        self.restoreAction.triggered.connect(self.showNormal)

        self.quitAction = QAction("Quit", self)
        self.quitAction.triggered.connect(qApp.quit)

    def createTrayIcon(self):
        self.trayIconMenu = QMenu(self)
        self.trayIconMenu.addAction(self.minimizeAction)
        self.trayIconMenu.addAction(self.maximizeAction)
        self.trayIconMenu.addAction(self.restoreAction)
        self.trayIconMenu.addSeparator()
        self.trayIconMenu.addAction(self.quitAction)

        self.trayIcon = QSystemTrayIcon(self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
Пример #11
0
class ImageFusionOptions(object):
    """
    UI class that can be used by the AddOnOptions Class to allow the user
    customise their input parameters for auto-registration.
    """
    def __init__(self, window_options):
        self.auto_image_fusion_frame = QtWidgets.QFrame()
        self.window = window_options
        self.moving_image = None
        self.fixed_image = None
        self.dict = {}

        self.setupUi()
        self.create_view()
        self.get_patients_info()

    def set_value(self, key, value):
        """
        Stores values into a dictionary to the corresponding key.
        Parameters
        ----------
        key (Any):

        value (Any):
        """
        self.dict[key] = value

    def create_view(self):
        """
        Create a table to hold all the ROI creation by isodose entries.
        """
        self.auto_image_fusion_frame.setVisible(False)

    def setVisible(self, visibility):
        """
        Custom setVisible function that will set the visibility of the GUI.

        Args:
            visibility (bool): flag for setting the GUI to visible
        """
        self.auto_image_fusion_frame.setVisible(visibility)

    def setupUi(self):
        """
        Constructs the GUI and sets the limit of each input field.
        """
        # Create a vertical Widget to hold Vertical Layout
        self.vertical_layout_widget = QWidget()
        self.vertical_layout = QtWidgets.QVBoxLayout()

        # Create a Widget and set layout to a GridLayout
        self.gridLayoutWidget = QWidget()
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setSizeConstraint(QLayout.SetDefaultConstraint)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setVerticalSpacing(0)

        # Create horizontal spacer in the middle of the grid
        hspacer = QtWidgets.QSpacerItem(QtWidgets.QSizePolicy.Expanding,
                                        QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(hspacer, 0, 5, 16, 1)

        # Labels
        self.fixed_image_label = QLabel("Fixed Image: ")
        fixed_image_sizePolicy = QSizePolicy(QSizePolicy.Maximum,
                                             QSizePolicy.Preferred)
        fixed_image_sizePolicy.setHorizontalStretch(0)
        fixed_image_sizePolicy.setVerticalStretch(0)
        fixed_image_sizePolicy.setHeightForWidth(
            self.fixed_image_label.sizePolicy().hasHeightForWidth())

        self.fixed_image_label.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                            | Qt.AlignVCenter)

        self.fixed_image_placeholder \
            = QLabel("This is a placeholder for fixed image")
        self.fixed_image_placeholder.setWordWrap(False)
        self.fixed_image_placeholder.setText(str(self.fixed_image))
        self.fixed_image_placeholder.setMaximumSize(200, 50)

        self.moving_image_label = QLabel("Moving Image: ")
        moving_image_label_sizePolicy = QSizePolicy(QSizePolicy.Maximum,
                                                    QSizePolicy.Maximum)
        moving_image_label_sizePolicy.setHorizontalStretch(0)
        moving_image_label_sizePolicy.setVerticalStretch(0)
        moving_image_label_sizePolicy.setHeightForWidth(
            self.moving_image_label.sizePolicy().hasHeightForWidth())
        self.moving_image_label.setSizePolicy(moving_image_label_sizePolicy)

        self.moving_image_placeholder = QLabel("This is a placeholder")
        self.moving_image_placeholder.setWordWrap(False)
        self.moving_image_placeholder.setText(str(self.moving_image))
        self.moving_image_placeholder.setMaximumSize(200, 50)

        self.gridLayout.addWidget(self.fixed_image_label, 0, 0)
        self.gridLayout.addWidget(self.fixed_image_placeholder, 0, 1)
        self.gridLayout.addWidget(self.moving_image_label, 0, 2)
        self.gridLayout.addWidget(self.moving_image_placeholder, 0, 3)

        # Default Numbers
        self.default_numbers_label = QLabel("Default Numbers")
        self.default_numbers_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                                | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.default_numbers_label, 1, 0)

        self.default_number_spinBox = QSpinBox(self.gridLayoutWidget)
        self.default_number_spinBox.setRange(-2147483648, 2147483647)
        self.default_number_spinBox.setSizePolicy(QSizePolicy.Minimum,
                                                  QSizePolicy.Fixed)
        self.default_number_spinBox.setToolTip(
            "Default voxel value. Defaults to -1000.")
        self.gridLayout.addWidget(self.default_number_spinBox, 1, 1)

        # Final Interp
        self.interp_order_label = QLabel("Final Interp")
        self.interp_order_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                             | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.interp_order_label, 2, 0)

        self.interp_order_spinbox = QSpinBox(self.gridLayoutWidget)
        self.interp_order_spinbox.setSizePolicy(QSizePolicy.Minimum,
                                                QSizePolicy.Fixed)
        self.interp_order_spinbox.setToolTip("The final interpolation order.")
        self.gridLayout.addWidget(self.interp_order_spinbox, 2, 1)

        # Metric
        self.metric_label = QLabel("Metric")
        self.metric_label.setAlignment(QtCore.Qt.AlignLeft | Qt.AlignTrailing
                                       | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.metric_label, 3, 0)

        self.metric_comboBox = QComboBox()
        self.metric_comboBox.addItem("correlation")
        self.metric_comboBox.addItem("mean_squares")
        self.metric_comboBox.addItem("mattes_mi")
        self.metric_comboBox.addItem("joint_hist_mi")
        self.metric_comboBox.setToolTip(
            "The metric to be optimised during image registration.")
        self.gridLayout.addWidget(self.metric_comboBox, 3, 1)

        # Number of Iterations
        self.no_of_iterations_label = QLabel("Number of Iterations")
        self.no_of_iterations_label.setAlignment(Qt.AlignLeft
                                                 | Qt.AlignTrailing
                                                 | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.no_of_iterations_label, 4, 0)

        self.no_of_iterations_spinBox = QSpinBox(self.gridLayoutWidget)
        self.no_of_iterations_spinBox.setSizePolicy(QSizePolicy.Minimum,
                                                    QSizePolicy.Fixed)
        self.no_of_iterations_spinBox.setRange(0, 100)
        self.no_of_iterations_spinBox.setToolTip(
            "Number of iterations in each multi-resolution step.")
        self.gridLayout.addWidget(self.no_of_iterations_spinBox, 4, 1)

        # Shrink Factor
        self.shrink_factor_label = QLabel("Shrink Factor")
        self.shrink_factor_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                              | Qt.AlignVCenter)

        self.gridLayout.addWidget(self.shrink_factor_label, 5, 0)

        self.shrink_factor_qLineEdit = QLineEdit()
        self.shrink_factor_qLineEdit.resize(
            self.shrink_factor_qLineEdit.sizeHint().width(),
            self.shrink_factor_qLineEdit.sizeHint().height())

        self.shrink_factor_qLineEdit.setValidator(
            QRegularExpressionValidator(
                QRegularExpression("^[0-9]*[,]?[0-9]*[,]?[0-9]")))

        self.shrink_factor_qLineEdit.setToolTip(
            "The multi-resolution downsampling factors. Can be up to three "
            "integer elements in an array. Example [8, 2, 1]")
        self.gridLayout.addWidget(self.shrink_factor_qLineEdit, 5, 1)

        # Optimiser
        self.optimiser_label = QLabel("Optimiser")
        self.optimiser_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                          | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.optimiser_label, 1, 2)

        self.optimiser_comboBox = QComboBox(self.gridLayoutWidget)
        self.optimiser_comboBox.addItem("lbfgsb")
        self.optimiser_comboBox.addItem("gradient_descent")
        self.optimiser_comboBox.addItem("gradient_descent_line_search")
        self.optimiser_comboBox.setToolTip(
            "The optimiser algorithm used for image registration.")
        self.gridLayout.addWidget(self.optimiser_comboBox, 1, 3)

        # Reg Method
        self.reg_method_label = QLabel("Reg Method")
        self.reg_method_label.setAlignment(QtCore.Qt.AlignLeft
                                           | Qt.AlignTrailing
                                           | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.reg_method_label, 2, 2)

        self.reg_method_comboBox = QComboBox()
        self.reg_method_comboBox.addItem("translation")
        self.reg_method_comboBox.addItem("rigid")
        self.reg_method_comboBox.addItem("similarity")
        self.reg_method_comboBox.addItem("affine")
        self.reg_method_comboBox.addItem("scaleversor")
        self.reg_method_comboBox.addItem("scaleskewversor")
        self.reg_method_comboBox.setToolTip(
            "The linear transformation model to be used for image "
            "registration.")
        self.gridLayout.addWidget(self.reg_method_comboBox, 2, 3)

        # Sampling Rate
        self.sampling_rate_label = QLabel("Sampling Rate")
        self.sampling_rate_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                              | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.sampling_rate_label, 3, 2)

        self.sampling_rate_spinBox = QDoubleSpinBox(self.gridLayoutWidget)
        self.sampling_rate_spinBox.setMinimum(0)
        self.sampling_rate_spinBox.setMaximum(1)
        self.sampling_rate_spinBox.setSingleStep(0.01)
        self.sampling_rate_spinBox.setSizePolicy(QSizePolicy.Minimum,
                                                 QSizePolicy.Fixed)
        self.sampling_rate_spinBox.setToolTip("The fraction of voxels sampled "
                                              "during each iteration.")
        self.gridLayout.addWidget(self.sampling_rate_spinBox, 3, 3)

        # Smooth Sigmas
        self.smooth_sigma_label = QLabel("Smooth Sigma")
        self.smooth_sigma_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                             | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.smooth_sigma_label, 4, 2)

        self.smooth_sigmas_qLineEdit = QLineEdit()
        self.smooth_sigmas_qLineEdit.resize(
            self.smooth_sigmas_qLineEdit.sizeHint().width(),
            self.smooth_sigmas_qLineEdit.sizeHint().height())
        self.smooth_sigmas_qLineEdit.setValidator(
            QRegularExpressionValidator(
                QRegularExpression("^[0-9]*[,]?[0-9]*[,]?[0-9]")))
        self.smooth_sigmas_qLineEdit.setToolTip(
            "The multi-resolution smoothing kernal scale (Gaussian). Can be "
            "up to three integer elements in an array. Example [4, 2, 1]")
        self.gridLayout.addWidget(self.smooth_sigmas_qLineEdit, 4, 3)

        # Label to hold warning labels.
        self.warning_label = QLabel()

        # Button for fast mode
        self.fast_mode_button = QtWidgets.QPushButton("Fast Mode")
        self.fast_mode_button.setCursor(
            QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.fast_mode_button.clicked.connect(self.set_fast_mode)

        # Add Widgets to the vertical layout
        self.vertical_layout.addWidget(self.fast_mode_button)
        self.vertical_layout.addWidget(self.gridLayoutWidget)
        self.vertical_layout.addWidget(self.warning_label)

        # Set layout of frame to the gridlayout widget
        self.auto_image_fusion_frame.setLayout(self.vertical_layout)

    def set_gridLayout(self):
        """
        Set the UI based on the values taken from the JSON
        """
        msg = ""

        # If-Elif statements for setting the dict
        # this can only be done in if-else statements.
        if self.dict["reg_method"] == "translation":
            self.reg_method_comboBox.setCurrentIndex(0)
        elif self.dict["reg_method"] == "rigid":
            self.reg_method_comboBox.setCurrentIndex(1)
        elif self.dict["reg_method"] == "similarity":
            self.reg_method_comboBox.setCurrentIndex(2)
        elif self.dict["reg_method"] == "affine":
            self.reg_method_comboBox.setCurrentIndex(3)
        elif self.dict["reg_method"] == "scaleversor":
            self.reg_method_comboBox.setCurrentIndex(4)
        elif self.dict["reg_method"] == "scaleskewversor":
            self.reg_method_comboBox.setCurrentIndex(5)
        else:
            msg += 'There was an error setting the reg_method value.\n'
            self.warning_label.setText(msg)

        if self.dict["metric"] == "coorelation":
            self.metric_comboBox.setCurrentIndex(0)
        elif self.dict["metric"] == "mean_squares":
            self.metric_comboBox.setCurrentIndex(1)
        elif self.dict["metric"] == "mattes_mi":
            self.metric_comboBox.setCurrentIndex(2)
        elif self.dict["metric"] == "joint_hist_mi":
            self.metric_comboBox.setCurrentIndex(3)
        else:
            msg += 'There was an error setting the metric value.\n'
            self.warning_label.setText(msg)

        if self.dict["optimiser"] == "lbfgsb":
            self.optimiser_comboBox.setCurrentIndex(0)
        elif self.dict["optimiser"] == "gradient_descent":
            self.optimiser_comboBox.setCurrentIndex(1)
        elif self.dict["optimiser"] == "gradient_descent_line_search":
            self.optimiser_comboBox.setCurrentIndex(2)
        else:
            msg += 'There was an error setting the optimiser value.\n'
            self.warning_label.setText(msg)

        # Check if all elements in list are ints
        if all(isinstance(x, int) for x in self.dict["shrink_factors"]):
            # Shrink_factors is stored as a list in JSON convert the list into
            # a string.
            shrink_factor_list_json = ', '.join(
                str(e) for e in self.dict["shrink_factors"])
            self.shrink_factor_qLineEdit.setText(shrink_factor_list_json)
        else:
            msg += 'There was an error setting the Shrink Factors value.\n'
            self.warning_label.setText(msg)

        # Check if all elements in list are ints
        if all(isinstance(x, int) for x in self.dict["smooth_sigmas"]):
            # Since smooth_sigma is stored as a list in JSON convert the list
            # into a string.
            smooth_sigma_list_json = ', '.join(
                str(e) for e in self.dict["smooth_sigmas"])
            self.smooth_sigmas_qLineEdit.setText(smooth_sigma_list_json)
        else:
            msg += 'There was an error setting the Smooth Sigmas value.\n'
            self.warning_label.setText(msg)

        try:
            self.sampling_rate_spinBox.setValue(
                float(self.dict["sampling_rate"]))
        except ValueError:
            msg += 'There was an error setting the Sampling Rate value.\n'
            self.warning_label.setText(msg)

        try:
            self.interp_order_spinbox.setValue(int(self.dict["final_interp"]))
        except ValueError:
            msg += 'There was an error setting the Final Interp value.\n'
            self.warning_label.setText(msg)

        try:
            self.no_of_iterations_spinBox.setValue(
                int(self.dict["number_of_iterations"]))
        except ValueError:
            msg += 'There was an error setting the Number of iterations ' \
                   'value.\n'
            self.warning_label.setText(msg)

        try:
            self.default_number_spinBox.setValue(
                int(self.dict["default_value"]))
        except ValueError:
            msg += 'There was an error setting the Default Number'
            self.warning_label.setText(msg)

    def get_patients_info(self):
        """
        Retrieve the patient's study description of the fixed image
        and for the moving image (if it exists).
        """
        patient_dict_container = PatientDictContainer()
        if not patient_dict_container.is_empty():
            filename = patient_dict_container.filepaths[0]
            dicom_tree_slice = DicomTree(filename)
            dict_tree = dicom_tree_slice.dict
            try:
                self.fixed_image = dict_tree["Series Instance UID"][0]
            except:
                self.fixed_image = ""
                self.warning_label.setText(
                    'Couldn\'t find the series instance '
                    'UID for the Fixed Image.')

        moving_dict_container = MovingDictContainer()
        if not moving_dict_container.is_empty():
            filename = moving_dict_container.filepaths[0]
            dicom_tree_slice = DicomTree(filename)
            dict_tree = dicom_tree_slice.dict
            try:
                self.moving_image = dict_tree["Series Instance UID"][0]
            except:
                self.moving_image = ""
                self.warning_label.setText(
                    'Couldn\'t find the series instance '
                    'UID for the Moving Image.')

        if moving_dict_container.is_empty() and self.moving_image != "":
            self.moving_image = ""

        self.fixed_image_placeholder.setText(str(self.fixed_image))
        self.moving_image_placeholder.setText(str(self.moving_image))

    def get_values_from_UI(self):
        """
        Sets values from the GUI to the dict that will be used to store the
        relevant parameters to imageFusion.json.
        """
        self.dict["reg_method"] = str(self.reg_method_comboBox.currentText())
        self.dict["metric"] = str(self.metric_comboBox.currentText())
        self.dict["optimiser"] = str(self.optimiser_comboBox.currentText())

        a_string = self.shrink_factor_qLineEdit.text().split(",")
        a_int = list(map(int, a_string))
        self.dict["shrink_factors"] = a_int

        a_string = self.smooth_sigmas_qLineEdit.text().split(",")
        a_int = list(map(int, a_string))
        self.dict["smooth_sigmas"] = a_int

        self.dict["sampling_rate"] = self.sampling_rate_spinBox.value()
        self.dict["final_interp"] = self.interp_order_spinbox.value()
        self.dict[
            "number_of_iterations"] = self.no_of_iterations_spinBox.value()
        self.dict["default_value"] = self.default_number_spinBox.value()

        return self.dict

    def check_parameter(self):
        """
        Check the number of values of the smooth sigma and shrink factors of 
        that are parameters used for images fusion.
        """
        len_smooth_sigmas = len(self.dict["smooth_sigmas"])
        len_shrink_factor = len(self.dict["shrink_factors"])
        if len_smooth_sigmas != len_shrink_factor:
            raise ValueError

    def set_fast_mode(self):
        """These settings are customised to be fast for images fusion."""
        self.reg_method_comboBox.setCurrentIndex(1)
        self.metric_comboBox.setCurrentIndex(1)
        self.optimiser_comboBox.setCurrentIndex(1)
        self.shrink_factor_qLineEdit.setText("8")
        self.smooth_sigmas_qLineEdit.setText("10")
        self.sampling_rate_spinBox.setValue(0.25)
        self.interp_order_spinbox.setValue(2)
        self.no_of_iterations_spinBox.setValue(50)
        self.default_number_spinBox.setValue(-1000)
Пример #12
0
class WindowNewExercise(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.setWindowFlag(Qt.Window)
        self.setWindowFlag(Qt.WindowStaysOnTopHint)
        self.setWindowTitle("Add New Exercise")
        self.setWindowModality(Qt.WindowModal)
        self.setLayout(QFormLayout())

        self.label_name = QLabel("Exercise Name:", self)
        self.line_edit_name = QLineEdit(self)
        self.layout().addRow(self.label_name, self.line_edit_name)
        self.label_measures = QLabel("Number of Measures:", self)
        self.spin_box_measures = QSpinBox(self)
        self.min, self.max = 0, 5
        self.spin_box_measures.setRange(self.min, self.max)
        self.spin_box_measures.valueChanged.connect(
            self.change_visibility_measure_widgets)
        self.layout().addRow(self.label_measures, self.spin_box_measures)

        self.labels_measure_type = []
        self.comboboxes_type = []
        self.labels_measure_name = []
        self.line_edits_measure_name = []
        for i in range(self.min, self.max):
            label_measure_type = QLabel(f"Type of Measure {i + 1}:", self)
            self.labels_measure_type.append(label_measure_type)
            combobox_type = QComboBox(self)
            self.comboboxes_type.append(combobox_type)
            self.layout().addRow(label_measure_type, combobox_type)
            combobox_type.hide()
            label_measure_type.hide()

            label_measure_name = QLabel(f"Name of Measure {i + 1}:", self)
            self.labels_measure_name.append(label_measure_name)
            line_edit_measure_name = QLineEdit(self)
            self.line_edits_measure_name.append(line_edit_measure_name)
            self.layout().addRow(label_measure_name, line_edit_measure_name)
            label_measure_name.hide()
            line_edit_measure_name.hide()

        self.button_discard = QPushButton("Discard Exercise", self)
        self.button_discard.clicked.connect(self.button_discard_action)
        self.button_add = QPushButton("Add Exercise", self)
        self.button_add.clicked.connect(self.button_add_action)
        self.layout().addRow(self.button_discard, self.button_add)

    def change_visibility_measure_widgets(self):
        number_measures = self.spin_box_measures.value()
        for i in range(self.min, self.max):
            if number_measures > i:
                self.labels_measure_type[i].show()
                self.comboboxes_type[i].show()
                self.labels_measure_name[i].show()
                self.line_edits_measure_name[i].show()
            else:
                self.labels_measure_type[i].hide()
                self.comboboxes_type[i].hide()
                self.labels_measure_name[i].hide()
                self.line_edits_measure_name[i].hide()

    def closeEvent(self, event: QCloseEvent) -> None:
        self.line_edit_name.setText("")
        self.spin_box_measures.setValue(0)
        for line_edit in self.line_edits_measure_name:
            line_edit.setText("")
        return super().closeEvent(event)

    def button_discard_action(self):
        self.close()

    def button_add_action(self):
        self.close()
Пример #13
0
class ParameterEditorItem(QWidget):
    onRemoveParameter = Signal(Parameter)
    onMoveParameterUp = Signal(Parameter)
    onMoveParameterDown = Signal(Parameter)
    onChanged = Signal()

    def __init__(self, parameter: Parameter):
        super().__init__()

        self.parameter = parameter

        deleteButton = QToolButton()
        deleteButton.setText("X")
        deleteButton.clicked.connect(
            lambda: self.onRemoveParameter.emit(self.parameter))
        upButton = QToolButton()
        upButton.setText("\u2191")
        upButton.clicked.connect(
            lambda: self.onMoveParameterUp.emit(self.parameter))
        downButton = QToolButton()
        downButton.setText("\u2193")
        downButton.clicked.connect(
            lambda: self.onMoveParameterDown.emit(self.parameter))

        buttonsLayout = QVBoxLayout()
        buttonsLayout.setAlignment(Qt.AlignTop)
        buttonsLayout.addWidget(deleteButton)
        buttonsLayout.addWidget(upButton)
        buttonsLayout.addWidget(downButton)

        self._nameLabel = QLabel("Name")
        self._nameField = QLineEdit()
        self._nameField.textChanged.connect(self.OnChanged)

        self._dataTypeLabel = QLabel("Data Type")
        self._dataTypeField = QComboBox()
        for dataType in DataType:
            self._dataTypeField.addItem(dataType.ToString(), userData=dataType)
        self._dataTypeField.currentIndexChanged.connect(self.OnChanged)

        self._defaultValueLabel = QLabel("Default Value")
        self._defaultInteger = QSpinBox()
        self._defaultInteger.valueChanged.connect(self.OnChanged)

        self._defaultFloat = QDoubleSpinBox()
        self._defaultFloat.valueChanged.connect(self.OnChanged)

        self._defaultBoolean = QComboBox()
        self._defaultBoolean.addItem("True", True)
        self._defaultBoolean.addItem("False", False)
        self._defaultBoolean.currentIndexChanged.connect(self.OnChanged)

        self._defaultString = QLineEdit()
        self._defaultString.textChanged.connect(self.OnChanged)

        self._minimumLabel = QLabel("Minimum")
        self._minimumFloat = QDoubleSpinBox()
        self._minimumFloat.valueChanged.connect(self.OnChanged)
        self._minimumInteger = QSpinBox()
        self._minimumInteger.valueChanged.connect(self.OnChanged)

        self._maximumLabel = QLabel("Maximum")
        self._maximumFloat = QDoubleSpinBox()
        self._maximumFloat.valueChanged.connect(self.OnChanged)
        self._maximumInteger = QSpinBox()
        self._maximumInteger.valueChanged.connect(self.OnChanged)

        gridLayout = QGridLayout()
        gridLayout.setAlignment(Qt.AlignTop)
        gridLayout.addWidget(self._nameLabel, 0, 0)
        gridLayout.addWidget(self._nameField, 0, 1)
        gridLayout.addWidget(self._dataTypeLabel, 1, 0)
        gridLayout.addWidget(self._dataTypeField, 1, 1)
        gridLayout.addWidget(self._defaultValueLabel, 2, 0)

        for defaultField in [
                self._defaultInteger, self._defaultFloat, self._defaultBoolean,
                self._defaultString
        ]:
            gridLayout.addWidget(defaultField, 2, 1)

        gridLayout.addWidget(self._minimumLabel, 3, 0)
        gridLayout.addWidget(self._minimumInteger, 3, 1)
        gridLayout.addWidget(self._minimumFloat, 3, 1)
        gridLayout.addWidget(self._maximumLabel, 4, 0)
        gridLayout.addWidget(self._maximumInteger, 4, 1)
        gridLayout.addWidget(self._maximumFloat, 4, 1)

        layout = QHBoxLayout()
        layout.addLayout(buttonsLayout)
        layout.addLayout(gridLayout)
        self.setLayout(layout)

        self.SetFieldsFromParameter()

    def SetFieldsFromParameter(self):
        self._nameField.setText(self.parameter.name)

        self._dataTypeField.setCurrentText(self.parameter.dataType.ToString())

        minFloat, maxFloat = self.parameter.minimumFloat, self.parameter.maximumFloat
        minInt, maxInt = self.parameter.minimumInteger, self.parameter.maximumInteger
        self._minimumFloat.setRange(-2**30, maxFloat)
        self._maximumFloat.setRange(minFloat, 2**30)
        self._minimumInteger.setRange(-2**30, maxInt)
        self._maximumInteger.setRange(minInt, 2**30)
        if self._minimumFloat.value() != minFloat:
            self._minimumFloat.setValue(minFloat)
        if self._maximumFloat.value() != maxFloat:
            self._maximumFloat.setValue(maxFloat)
        if self._minimumInteger.value() != minInt:
            self._minimumInteger.setValue(minInt)
        if self._maximumInteger.value() != maxInt:
            self._maximumInteger.setValue(maxInt)

        self._defaultInteger.setRange(minInt, maxInt)
        self._defaultFloat.setRange(minFloat, maxFloat)
        if self._defaultInteger.value() != self.parameter.defaultValueDict[
                DataType.INTEGER]:
            self._defaultInteger.setValue(
                self.parameter.defaultValueDict[DataType.INTEGER])
        if self._defaultFloat.value() != self.parameter.defaultValueDict[
                DataType.FLOAT]:
            self._defaultFloat.setValue(
                self.parameter.defaultValueDict[DataType.FLOAT])

        if self._defaultBoolean.currentData(
        ) != self.parameter.defaultValueDict[DataType.BOOLEAN]:
            self._defaultBoolean.setCurrentText(
                str(self.parameter.defaultValueDict[DataType.BOOLEAN]))

        if self._defaultString.text() != self.parameter.defaultValueDict[
                DataType.STRING]:
            self._defaultString.setText(
                self.parameter.defaultValueDict[DataType.STRING])

        self.UpdateVisibility()

    def UpdateVisibility(self):
        self._defaultInteger.setVisible(
            self._dataTypeField.currentData() is DataType.INTEGER)
        self._defaultFloat.setVisible(
            self._dataTypeField.currentData() is DataType.FLOAT)
        self._defaultBoolean.setVisible(
            self._dataTypeField.currentData() is DataType.BOOLEAN)
        self._defaultString.setVisible(
            self._dataTypeField.currentData() is DataType.STRING)

        self._minimumLabel.setVisible(self._dataTypeField.currentData() in
                                      [DataType.INTEGER, DataType.FLOAT])
        self._maximumLabel.setVisible(self._dataTypeField.currentData() in
                                      [DataType.INTEGER, DataType.FLOAT])
        self._minimumInteger.setVisible(
            self._dataTypeField.currentData() is DataType.INTEGER)
        self._maximumInteger.setVisible(
            self._dataTypeField.currentData() is DataType.INTEGER)
        self._minimumFloat.setVisible(
            self._dataTypeField.currentData() is DataType.FLOAT)
        self._maximumFloat.setVisible(
            self._dataTypeField.currentData() is DataType.FLOAT)
        self._minimumLabel.setVisible(self._dataTypeField.currentData() in
                                      [DataType.INTEGER, DataType.FLOAT])
        self._maximumLabel.setVisible(self._dataTypeField.currentData() in
                                      [DataType.INTEGER, DataType.FLOAT])

        self._defaultValueLabel.setVisible(self._dataTypeField.currentData(
        ) not in [DataType.VALVE, DataType.PROGRAM, DataType.PROGRAM_PRESET])

    def OnChanged(self):
        self.UpdateVisibility()
        self._minimumFloat.setMaximum(self._maximumFloat.value())
        self._maximumFloat.setMinimum(self._minimumFloat.value())
        self._minimumInteger.setMaximum(self._maximumInteger.value())
        self._maximumInteger.setMinimum(self._minimumInteger.value())
        self._defaultInteger.setRange(self._minimumInteger.value(),
                                      self._maximumInteger.value())
        self._defaultFloat.setRange(self._minimumFloat.value(),
                                    self._maximumFloat.value())
        self.onChanged.emit()

    def UpdateParameter(self):
        self.parameter.name = self._nameField.text()
        self.parameter.dataType = self._dataTypeField.currentData()

        self.parameter.defaultValueDict[
            DataType.INTEGER] = self._defaultInteger.value()
        self.parameter.defaultValueDict[
            DataType.FLOAT] = self._defaultFloat.value()
        self.parameter.defaultValueDict[
            DataType.BOOLEAN] = self._defaultBoolean.currentData()
        self.parameter.defaultValueDict[
            DataType.STRING] = self._defaultString.text()

        self.parameter.minimumInteger = self._minimumInteger.value()
        self.parameter.maximumInteger = self._maximumInteger.value()
        self.parameter.minimumFloat = self._minimumFloat.value()
        self.parameter.maximumFloat = self._maximumFloat.value()

        self.parameter.ValidateDefaultValues()

        self.SetFieldsFromParameter()