class ColorPicker(QPushButton): class Events(QObject): color_changed = Signal(QColor) def __init__(self, parent: Optional[QWidget] = None): super(ColorPicker, self).__init__(parent) self.events = ColorPicker.Events() self.setAutoFillBackground(True) self._color_dialog = QColorDialog(self) self._color_dialog.setWindowFlags(Qt.Widget) self._color_dialog.setOptions(QColorDialog.DontUseNativeDialog | QColorDialog.NoButtons) self._menu = QMenu(self) action = QWidgetAction(self) action.setDefaultWidget(self._color_dialog) self._menu.addAction(action) self.setMenu(self._menu) # noinspection PyUnresolvedReferences self._menu.aboutToShow.connect(lambda: self._color_dialog.show()) # noinspection PyUnresolvedReferences self._color_dialog.currentColorChanged.connect( self.events.color_changed) # noinspection PyUnresolvedReferences self._color_dialog.currentColorChanged.connect( lambda color: self.update()) self.update() def update(self): color = self._color_dialog.currentColor() self.setText(color.name()) text_color_name = 'black' if qGray(color.rgb()) > 127 else 'white' self.setStyleSheet( f'ColorPicker {{ color: {text_color_name}; background-color: {color.name()}; }}' ) super(ColorPicker, self).update() @property def color(self) -> QColor: return self._color_dialog.currentColor() @color.setter def color(self, color: QColor): self._color_dialog.setCurrentColor(color)
class MaskControl(QWidget): def __init__(self, settings: ViewSettings): super().__init__() self.settings = settings self.color_picker = QColorDialog() self.color_picker.setWindowFlag(Qt.Widget) self.color_picker.setOptions(QColorDialog.DontUseNativeDialog | QColorDialog.NoButtons) self.opacity_spin = QDoubleSpinBox() self.opacity_spin.setRange(0, 1) self.opacity_spin.setSingleStep(0.1) self.opacity_spin.setDecimals(2) self.change_mask_color_btn = QPushButton("Change mask color") self.current_mask_color_preview = ColorShow( self.settings.get_from_profile("mask_presentation_color", [255, 255, 255])) self.opacity_spin.setValue( self.settings.get_from_profile("mask_presentation_opacity", 1)) self.current_mask_color_preview.setAutoFillBackground(True) self.change_mask_color_btn.clicked.connect(self.change_color) self.opacity_spin.valueChanged.connect(self.change_opacity) layout = QVBoxLayout() layout.addWidget(self.color_picker) layout2 = QHBoxLayout() layout2.addWidget(self.change_mask_color_btn) layout2.addWidget(self.current_mask_color_preview, 1) layout2.addWidget(QLabel("Mask opacity")) layout2.addWidget(self.opacity_spin) layout.addLayout(layout2) self.setLayout(layout) def set_color_preview(self, color): self.current_mask_color_preview.set_color(color) def change_color(self): color = self.color_picker.currentColor() color = (color.red(), color.green(), color.blue()) self.settings.set_in_profile("mask_presentation_color", color) self.settings.mask_representation_changed_emit() self.set_color_preview(color) def change_opacity(self): self.settings.set_in_profile("mask_presentation_opacity", self.opacity_spin.value()) self.settings.mask_representation_changed_emit()
class LabelEditor(QWidget): """Widget for create label scheme.""" def __init__(self, settings: ViewSettings): super().__init__() self.settings = settings self.color_list = [] self.chosen = None self.prohibited_names = set(self.settings.label_color_dict.keys() ) # Prohibited name is added to reduce # probability of colormap cache collision self.color_picker = QColorDialog() self.color_picker.setWindowFlag(Qt.Widget) self.color_picker.setOptions(QColorDialog.DontUseNativeDialog | QColorDialog.NoButtons) self.add_color_btn = QPushButton("Add color") self.add_color_btn.clicked.connect(self.add_color) self.remove_color_btn = QPushButton("Remove last color") self.remove_color_btn.clicked.connect(self.remove_color) self.save_btn = QPushButton("Save") self.save_btn.clicked.connect(self.save) self.color_layout = QHBoxLayout() layout = QVBoxLayout() layout.addWidget(self.color_picker) btn_layout = QHBoxLayout() btn_layout.addWidget(self.add_color_btn) btn_layout.addWidget(self.remove_color_btn) btn_layout.addWidget(self.save_btn) layout.addLayout(btn_layout) layout.addLayout(self.color_layout) self.setLayout(layout) @Slot(list) def set_colors(self, colors: list): for _ in range(self.color_layout.count()): el = self.color_layout.takeAt(0) if el.widget(): el.widget().deleteLater() for color in colors: self.color_layout.addWidget(ColorShow(color, self)) def remove_color(self): if self.color_layout.count(): el = self.color_layout.takeAt(self.color_layout.count() - 1) el.widget().deleteLater() def add_color(self): color = self.color_picker.currentColor() self.color_layout.addWidget( ColorShow([color.red(), color.green(), color.blue()], self)) def get_colors(self): count = self.color_layout.count() return [ self.color_layout.itemAt(i).widget().color for i in range(count) ] def save(self): count = self.color_layout.count() if not count: return rand_name = custom_name_generate(self.prohibited_names, self.settings.label_color_dict) self.prohibited_names.add(rand_name) self.settings.label_color_dict[rand_name] = self.get_colors() def mousePressEvent(self, e: QMouseEvent): child = self.childAt(e.pos()) if not isinstance(child, ColorShow): self.chosen = None return self.chosen = child def mouseMoveEvent(self, e: QMouseEvent): if self.chosen is None: return index = self.color_layout.indexOf(self.chosen) index2 = int(e.x() / self.width() * self.color_layout.count() + 0.5) if index2 != index: self.color_layout.insertWidget(index2, self.chosen) def mouseReleaseEvent(self, e: QMouseEvent): self.chosen = None
class ColormapCreator(QWidget): """ Widget for creating colormap. """ colormap_selected = Signal(Colormap) """ emitted on save button click. Contains current colormap in format accepted by :py:func:`create_color_map` """ def __init__(self): super().__init__() self.color_picker = QColorDialog() self.color_picker.setWindowFlag(Qt.Widget) self.color_picker.setOptions(QColorDialog.DontUseNativeDialog | QColorDialog.NoButtons) self.show_colormap = ColormapEdit() self.clear_btn = QPushButton("Clear") self.save_btn = QPushButton("Save") self.distribute_btn = QPushButton("Distribute evenly") self.reverse_btn = QPushButton("Reverse") self.info_label = InfoLabel( [ "<strong>Tip:</strong> Select color and double click on a color bar below. " + "Repeat to add another colors.", "<strong>Tip:</strong> Double click on a marker to remove it.", "<strong>Tip:</strong> Press and hold mouse left button on a marker to drag and drop it on color bar.", ], delay=10000, ) layout = QVBoxLayout() layout.addWidget(self.color_picker) layout.addWidget(self.info_label) layout.addWidget(self.show_colormap) btn_layout = QHBoxLayout() btn_layout.addStretch(1) btn_layout.addWidget(self.reverse_btn) btn_layout.addWidget(self.distribute_btn) btn_layout.addWidget(self.clear_btn) btn_layout.addWidget(self.save_btn) layout.addLayout(btn_layout) self.setLayout(layout) self.show_colormap.double_clicked.connect(self.add_color) self.clear_btn.clicked.connect(self.show_colormap.clear) self.save_btn.clicked.connect(self.save) self.reverse_btn.clicked.connect(self.show_colormap.reverse) self.distribute_btn.clicked.connect(self.show_colormap.distribute_evenly) def add_color(self, pos): color = self.color_picker.currentColor() self.show_colormap.add_color(pos, color_from_qcolor(color)) def save(self): if self.show_colormap.colormap: self.colormap_selected.emit(self.show_colormap.colormap) def current_colormap(self) -> Colormap: """:return: current colormap""" return self.show_colormap.colormap def set_colormap(self, colormap: Colormap): """set current colormap""" self.show_colormap.colormap = colormap self.show_colormap.refresh()