def test_drop_load_data(self): m = QtCore.QMimeData() m.setUrls([QtCore.QUrl('test.fits')]) e = MagicMock() e.mimeData.return_value = m load = MagicMock() self.app.load_data = load self.app.dropEvent(e) assert load.call_count == 1
def __init__(self, canvas, frame, name=None): """ Create a new toolbar object Parameters ---------- canvas : Maptloblib canvas instance The drawing canvas to interact with frame : QWidget The QT frame that the canvas is embedded within. """ self.buttons = {} self.__active = None self.basedir = None NavigationToolbar2QT.__init__(self, canvas, frame) if name is not None: self.setWindowTitle(name) self.setIconSize(QtCore.QSize(25, 25)) self.layout().setSpacing(1) self.setFocusPolicy(Qt.StrongFocus) self._idKey = None # pyside is prone to segfaults if slots hold the only # reference to a signal, so we hold an extra reference # see https://bugreports.qt-project.org/browse/PYSIDE-88 self.__signals = []
def paintEvent(self, event): # We need to preserve aspect ratio. Figure out bounding box for # webcam image. im_dx = self._image.width() im_dy = self._image.height() im_ratio = im_dx / float(im_dy) wi_dx = self.width() wi_dy = self.height() wi_ratio = wi_dx / float(wi_dy) if wi_ratio > im_ratio: # Need to pad on sides xmin = wi_dx / 2. - wi_dy / 2. * im_ratio ymin = 0. width = wi_dy * im_ratio height = wi_dy else: # Need to pad on top/bottom xmin = 0. ymin = wi_dy / 2. - wi_dx / 2. / float(im_ratio) width = wi_dx height = wi_dx / float(im_ratio) painter = QtGui.QPainter(self) painter.drawImage(QtCore.QRect(xmin, ymin, width, height), self._image)
def _create_terminal(self): if self._terminal is not None: # already set up return if hasattr(self, '_terminal_exception'): # already failed to set up return self._terminal_button = QtGui.QToolButton(self._ui) self._terminal_button.setToolTip("Toggle IPython Prompt") i = get_icon('IPythonConsole') self._terminal_button.setIcon(i) self._terminal_button.setIconSize(QtCore.QSize(25, 25)) self._layer_widget.ui.button_row.addWidget(self._terminal_button) try: from glue.app.qt.terminal import glue_terminal widget = glue_terminal(data_collection=self._data, dc=self._data, hub=self._hub, session=self.session, application=self, **vars(env)) self._terminal_button.clicked.connect(self._toggle_terminal) except Exception as e: # pylint: disable=W0703 import traceback self._terminal_exception = traceback.format_exc() self._setup_terminal_error_dialog(e) return self._terminal = self.add_widget(widget, label='IPython') self._hide_terminal()
def _update_icons(self): self.setIconSize(QtCore.QSize(self.width(), 15)) for index in range(self.count()): cmap = self.itemData(index) icon = QtGui.QIcon( cmap2pixmap(cmap, size=(self.width(), 15), steps=200)) self.setItemIcon(index, icon)
def index(self, row, column, parent=QtCore.QModelIndex()): if column != 0: return QtCore.QModelIndex() if not parent.isValid(): parent_item = self.root else: parent_item = self._get_item(parent) if parent_item is None: return QtCore.QModelIndex() child_item = parent_item.child(row) if child_item: return self._make_index(row, column, child_item) else: return QtCore.QModelIndex()
def rowCount(self, index=QtCore.QModelIndex()): item = self._get_item(index) if item is None: return self.root.children_count return item.children_count
def _setup_symbol_combo(self): self._symbols = list(POINT_ICONS.keys()) for idx, symbol in enumerate(self._symbols): icon = symbol_icon(symbol) self.ui.combo_symbol.addItem(icon, '', userData=symbol) self.ui.combo_symbol.setIconSize(QtCore.QSize(20, 20)) self.ui.combo_symbol.setMinimumSize(10, 32)
def paint(self, canvas): xy = list(map(int, self._roi.get_center())) radius = int(self._roi.get_radius()) center = QtCore.QPoint(xy[0], canvas.height() - xy[1]) p = self.get_painter(canvas) p.drawEllipse(center, radius, radius) p.end()
def _update_intensity_label(self, x, y): lbl = self._intensity_label(x, y) self.label_widget.setText(lbl) fm = self.label_widget.fontMetrics() w, h = fm.width(lbl), fm.height() g = QtCore.QRect(20, self.central_widget.geometry().height() - h, w, h) self.label_widget.setGeometry(g)
def __init__(self, parent=None): super(LayerArtistView, self).__init__(parent) self.setDragEnabled(True) self.setAcceptDrops(True) self.setDragDropMode(QtGui.QAbstractItemView.InternalMove) self.setIconSize(QtCore.QSize(15, 15)) self.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.setContextMenuPolicy(Qt.ActionsContextMenu) self.setEditTriggers(self.NoEditTriggers) self._set_palette() self._actions = {} self._create_actions() self._timer = QtCore.QTimer(self) self._timer.timeout.connect(nonpartial(self._update_viewport)) self._timer.start(1000)
class ClickableLabel(QtGui.QLabel): """ A QtGui.QLabel you can click on to generate events """ clicked = QtCore.Signal() def mousePressEvent(self, event): self.clicked.emit()
def parent(self, index=None): if index is None: # overloaded QtCore.QObject.parent() return QtCore.QObject.parent(self) item = self._get_item(index) if item is None: return QtCore.QModelIndex() return self._make_index(item.row, item.column, item.parent)
def draw_polygon(self, canvas, x, y): x, y = self._transform(x, y) poly = QtGui.QPolygon() points = [QtCore.QPoint(xx, yy) for xx, yy in zip(x, y)] for p in points: poly.append(p) p = self.get_painter(canvas) p.drawPolyline(poly) p.end()
def process_dialog(delay=0, accept=False, reject=False, function=None): """ Context manager to automatically capture the active dialog and carry out certain actions. Note that only one of ``accept``, ``reject``, or ``function`` should be specified. Parameters ---------- delay : int, optional The delay in ms before acting on the dialog (since it may not yet exist when the context manager is called). accept : bool, optional If `True`, accept the dialog after the specified delay. reject : bool, optional If `False`, reject the dialog after the specified delay function : func, optional For more complex user actions, specify a function that takes the dialog as the first and only argument. """ def _accept(dialog): dialog.accept() def _reject(dialog): dialog.reject() n_args = sum((accept, reject, function is not None)) if n_args > 1: raise ValueError("Only one of ``accept``, ``reject``, or " "``function`` should be specified") elif n_args == 0: raise ValueError("One of ``accept``, ``reject``, or " "``function`` should be specified") if accept: function = _accept elif reject: function = _reject def wrapper(): from glue.external.qt import get_qapp app = get_qapp() dialog = app.focusWidget().window() function(dialog) timer = QtCore.QTimer() timer.setInterval(delay) timer.setSingleShot(True) timer.timeout.connect(wrapper) timer.start() yield
def set_setting(self, key, value): """ Update a persistent setting in the application. :param key: Name of a setting in the ``settings`` registry :type key: str :param value: New value for the setting :type value: str """ super(GlueApplication, self).set_setting(key, value) settings = QtCore.QSettings('glue-viz', 'glue') settings.setValue(key, value)
def start(self): # handoff between IOLoop and QApplication event loops loop = ioloop.IOLoop.instance() # We used to have a value of 0ms as the second argument # (callback_time) in the following call, but this caused the # application to hang on certain setups, so use 1ms instead. stopper = ioloop.PeriodicCallback(loop.stop, 1, loop) self.timer = QtCore.QTimer() self.timer.timeout.connect(loop.start) self.timer.start(100) stopper.start() super(EmbeddedQtKernelApp, self).start()
def __init__(self, parent=None): super(WebcamView, self).__init__() self._frozen = False self._webcam = Webcam() self._update_image() self._timer = QtCore.QTimer(self) self._timer.timeout.connect(self._update_image) self._timer.start(100)
class ColorizedCompletionTextEdit(CompletionTextEdit): updated = QtCore.Signal() def insertPlainText(self, *args): super(ColorizedCompletionTextEdit, self).insertPlainText(*args) self.reformat_text() self.updated.emit() def keyReleaseEvent(self, event): super(ColorizedCompletionTextEdit, self).keyReleaseEvent(event) self.reformat_text() self.updated.emit() def reformat_text(self): # Here every time a key is released, we re-colorize the expression. # We show valid components in blue, and invalid ones in red. We # recognized components because they contain a ":" which is not valid # Python syntax (except if one considers lambda functions, but we can # probably ignore that here) text = self.toPlainText() # If there are no : in the text we don't need to do anything if not ":" in text: return pattern = '[^\\s]*:[^\\s]*' def format_components(m): component = m.group(0) if component in self.word_list: return "<font color='#0072B2'><b>" + component + "</b></font> " else: return "<font color='#D55E00'><b>" + component + "</b></font> " html = re.sub(pattern, format_components, text) tc = self.textCursor() pos = tc.position() self.setHtml(html) # Sometimes the HTML gets rid of double spaces so we have to make # sure the position isn't greater than the text length. text = self.toPlainText() pos = min(pos, len(text)) tc.setPosition(pos) self.setTextCursor(tc) self.setAlignment(Qt.AlignCenter)
def __init__(self, parent=None): super(DataCollectionView, self).__init__(parent) self.doubleClicked.connect(self._edit) # this keeps the full-row of the selection bar in-sync self.pressed.connect(nonpartial(self._update_viewport)) # only edit label on model.new_item self.setItemDelegate(LabeledDelegate()) self.setEditTriggers(self.NoEditTriggers) self._timer = QtCore.QTimer(self) self._timer.timeout.connect(nonpartial(self._update_viewport)) self._timer.start(1000)
class MplWidget(QtGui.QWidget): """Widget defined in Qt Designer""" # signals rightDrag = QtCore.Signal(float, float) leftDrag = QtCore.Signal(float, float) def __init__(self, parent=None): # initialization of Qt MainWindow widget QtGui.QWidget.__init__(self, parent) # set the canvas to the Matplotlib widget self.canvas = MplCanvas() # create a vertical box layout self.vbl = QtGui.QVBoxLayout() self.vbl.setContentsMargins(0, 0, 0, 0) self.vbl.setSpacing(0) # add mpl widget to the vertical box self.vbl.addWidget(self.canvas) # set the layout to the vertical box self.setLayout(self.vbl) self.canvas.rightDrag.connect(self.rightDrag) self.canvas.leftDrag.connect(self.leftDrag)
def move_artist(self, artist, row): """Move an artist before the entry in row Row could be the end of the list (-> put it at the end) """ if len(self.artists) < 2: # can't rearrange lenght 0 or 1 list return try: loc = self.artists.index(artist) except ValueError: return dest = row if not self.beginMoveRows(QtCore.QModelIndex(), loc, loc, QtCore.QModelIndex(), dest): return if dest >= loc: row -= 1 self.artists.pop(loc) self.artists.insert(row, artist) self._update_zorder() self.endMoveRows()
class QColorBox(QtGui.QLabel): mousePressed = QtCore.Signal() colorChanged = QtCore.Signal() def __init__(self, *args, **kwargs): super(QColorBox, self).__init__(*args, **kwargs) self.mousePressed.connect(nonpartial(self.query_color)) self.colorChanged.connect(nonpartial(self.on_color_change)) self.setColor("#000000") def mousePressEvent(self, event): self.mousePressed.emit() event.accept() def query_color(self): color = QtGui.QColorDialog.getColor(self._qcolor, parent=self) if color.isValid(): self.setColor(qt4_to_mpl_color(color)) def setColor(self, color): self._color = color self.colorChanged.emit() def color(self): return self._color def on_color_change(self): self._qcolor = mpl_to_qt4_color(self.color()) image = QtGui.QImage(70, 22, QtGui.QImage.Format_RGB32) try: image.fill(self._qcolor) except TypeError: # PySide and old versions of PyQt require a RGBA integer image.fill(self._qcolor.rgba()) pixmap = QtGui.QPixmap.fromImage(image) self.setPixmap(pixmap)
def test_style_dialog(): # This is in part a regression test for a bug in Python 3. It is not a # full test of StyleDialog. session = simple_session() hub = session.hub collect = session.data_collection image = Data(label='im', x=[[1, 2], [3, 4]], y=[[2, 3], [4, 5]]) pos = QtCore.QPoint(10, 10) st = NonBlockingStyleDialog.dropdown_editor(image, pos)
def make_toolbar(self): tb = QtGui.QToolBar(parent=self) tb.setIconSize(QtCore.QSize(25, 25)) tb.layout().setSpacing(1) tb.setFocusPolicy(Qt.StrongFocus) agroup = QtGui.QActionGroup(tb) agroup.setExclusive(True) for (mode_text, mode_icon, mode_cb) in self._mouse_modes(): # TODO: add icons similar to the Matplotlib toolbar action = tb.addAction(mode_icon, mode_text) action.setCheckable(True) action.toggled.connect(mode_cb) agroup.addAction(action) action = tb.addAction(get_icon('glue_move'), "Pan") self.mode_actns['pan'] = action action.setCheckable(True) action.toggled.connect(lambda tf: self.mode_cb('pan', tf)) agroup.addAction(action) icon = QtGui.QIcon(os.path.join(ginga_icon_dir, 'hand_48.png')) action = tb.addAction(icon, "Free Pan") self.mode_actns['freepan'] = action action.setCheckable(True) action.toggled.connect(lambda tf: self.mode_cb('freepan', tf)) agroup.addAction(action) icon = QtGui.QIcon(os.path.join(ginga_icon_dir, 'rotate_48.png')) action = tb.addAction(icon, "Rotate") self.mode_actns['rotate'] = action action.setCheckable(True) action.toggled.connect(lambda tf: self.mode_cb('rotate', tf)) agroup.addAction(action) action = tb.addAction(get_icon('glue_contrast'), "Contrast") self.mode_actns['contrast'] = action action.setCheckable(True) action.toggled.connect(lambda tf: self.mode_cb('contrast', tf)) agroup.addAction(action) icon = QtGui.QIcon(os.path.join(ginga_icon_dir, 'cuts_48.png')) action = tb.addAction(icon, "Cuts") self.mode_actns['cuts'] = action action.setCheckable(True) action.toggled.connect(lambda tf: self.mode_cb('cuts', tf)) agroup.addAction(action) cmap_w = _colormap_mode(self, self.client.set_cmap) tb.addWidget(cmap_w) return tb
def _setup_widgets(self): self.layout = QtGui.QFormLayout() self.size_widget = QtGui.QSpinBox() self.size_widget.setMinimum(1) self.size_widget.setMaximum(40) self.size_widget.setValue(self.layer.style.markersize) self.label_widget = QtGui.QLineEdit() self.label_widget.setText(self.layer.label) self.label_widget.selectAll() self.symbol_widget = QtGui.QComboBox() for idx, symbol in enumerate(self._symbols): icon = symbol_icon(symbol) self.symbol_widget.addItem(icon, '') if symbol is self.layer.style.marker: self.symbol_widget.setCurrentIndex(idx) self.symbol_widget.setIconSize(QtCore.QSize(20, 20)) self.symbol_widget.setMinimumSize(10, 32) self.color_widget = ColorWidget() self.color_widget.setStyleSheet('ColorWidget {border: 1px solid;}') color = self.layer.style.color color = mpl_to_qt4_color(color, alpha=self.layer.style.alpha) self.set_color(color) self.okcancel = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) if self._edit_label: self.layout.addRow("Label", self.label_widget) self.layout.addRow("Symbol", self.symbol_widget) self.layout.addRow("Color", self.color_widget) self.layout.addRow("Size", self.size_widget) self.layout.addWidget(self.okcancel) self.setLayout(self.layout) self.layout.setContentsMargins(6, 6, 6, 6)
def __init__(self): self._draw_count = 0 interactive = matplotlib.is_interactive() matplotlib.interactive(False) self.roi_callback = None self.fig = Figure(facecolor='#ffffff') FigureCanvas.__init__(self, self.fig) FigureCanvas.setSizePolicy(self, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) FigureCanvas.updateGeometry(self) self.manager = FigureManager(self, 0) matplotlib.interactive(interactive) self._resize_timer = QtCore.QTimer() self._resize_timer.setInterval(250) self._resize_timer.setSingleShot(True) self._resize_timer.timeout.connect(self._on_timeout) self.renderer = None
def add_artist(self, row, artist): """Add a new artist""" self.beginInsertRows(QtCore.QModelIndex(), row, row) self.artists.insert(row, artist) self.endInsertRows() self.rowsInserted.emit(self.index(row), row, row)
def setupUi(self, ImageWidget): ImageWidget.setObjectName("ImageWidget") ImageWidget.resize(296, 217) ImageWidget.setBaseSize(QtCore.QSize(555, 500)) ImageWidget.setFocusPolicy(QtCore.Qt.StrongFocus) self.verticalLayout_2 = QtGui.QVBoxLayout(ImageWidget) self.verticalLayout_2.setContentsMargins(4, 4, 4, 4) self.verticalLayout_2.setObjectName("verticalLayout_2") self.option_dashboard = QtGui.QWidget(ImageWidget) self.option_dashboard.setObjectName("option_dashboard") self.verticalLayout = QtGui.QVBoxLayout(self.option_dashboard) self.verticalLayout.setContentsMargins(0, 0, 0, 10) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QtGui.QHBoxLayout() self.horizontalLayout.setSpacing(2) self.horizontalLayout.setContentsMargins(0, 0, 0, 0) self.horizontalLayout.setObjectName("horizontalLayout") self.label = QtGui.QLabel(self.option_dashboard) self.label.setObjectName("label") self.horizontalLayout.addWidget(self.label) self.displayDataCombo = GlueComboBox(self.option_dashboard) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.displayDataCombo.sizePolicy().hasHeightForWidth()) self.displayDataCombo.setSizePolicy(sizePolicy) self.displayDataCombo.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToMinimumContentsLength) self.displayDataCombo.setObjectName("displayDataCombo") self.horizontalLayout.addWidget(self.displayDataCombo) self.verticalLayout.addLayout(self.horizontalLayout) self.horizontalLayout_2 = QtGui.QHBoxLayout() self.horizontalLayout_2.setSpacing(2) self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.label_2 = QtGui.QLabel(self.option_dashboard) self.label_2.setObjectName("label_2") self.horizontalLayout_2.addWidget(self.label_2) self.attributeComboBox = GlueComboBox(self.option_dashboard) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.attributeComboBox.sizePolicy().hasHeightForWidth()) self.attributeComboBox.setSizePolicy(sizePolicy) self.attributeComboBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToMinimumContentsLength) self.attributeComboBox.setObjectName("attributeComboBox") self.horizontalLayout_2.addWidget(self.attributeComboBox) self.verticalLayout.addLayout(self.horizontalLayout_2) self.horizontalLayout_3 = QtGui.QHBoxLayout() self.horizontalLayout_3.setSpacing(2) self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.orientationLabel = QtGui.QLabel(self.option_dashboard) self.orientationLabel.setEnabled(True) self.orientationLabel.setObjectName("orientationLabel") self.horizontalLayout_3.addWidget(self.orientationLabel) self.sliceComboBox = GlueComboBox(self.option_dashboard) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sliceComboBox.sizePolicy().hasHeightForWidth()) self.sliceComboBox.setSizePolicy(sizePolicy) self.sliceComboBox.setObjectName("sliceComboBox") self.horizontalLayout_3.addWidget(self.sliceComboBox) self.verticalLayout.addLayout(self.horizontalLayout_3) self.imageSlider = QtGui.QSlider(self.option_dashboard) self.imageSlider.setEnabled(True) self.imageSlider.setOrientation(QtCore.Qt.Horizontal) self.imageSlider.setInvertedAppearance(False) self.imageSlider.setInvertedControls(True) self.imageSlider.setTickPosition(QtGui.QSlider.NoTicks) self.imageSlider.setTickInterval(0) self.imageSlider.setObjectName("imageSlider") self.verticalLayout.addWidget(self.imageSlider) spacerItem = QtGui.QSpacerItem(5, 59, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) self.verticalLayout_2.addWidget(self.option_dashboard) self.verticalLayout_2.setStretch(0, 1) self.retranslateUi(ImageWidget) QtCore.QMetaObject.connectSlotsByName(ImageWidget)
class RGBEdit(QtGui.QWidget): """A widget to set the contrast for individual layers in an RGB image Based off the ds9 RGB Frame widget :param artist: A :class:`~glue.viewers.image.layer_artist.RGBArtistLayerArtist` instance to control :param parent: Optional widget parent This widget sets the state of the artist object, such that contrast adjustments from a :class:`~glue.viewers.image.client` affect a particular RGB slice """ current_changed = QtCore.Signal(str) colors_changed = QtCore.Signal() def __init__(self, parent=None, artist=None): super(RGBEdit, self).__init__(parent) self._artist = artist l = QtGui.QGridLayout() current = QtGui.QLabel("Contrast") visible = QtGui.QLabel("Visible") l.addWidget(current, 0, 2, 1, 1) l.addWidget(visible, 0, 3, 1, 1) l.setColumnStretch(0, 0) l.setColumnStretch(1, 10) l.setColumnStretch(2, 0) l.setColumnStretch(3, 0) l.setRowStretch(0, 0) l.setRowStretch(1, 0) l.setRowStretch(2, 0) l.setRowStretch(3, 0) l.setRowStretch(4, 10) curr_grp = QtGui.QButtonGroup() self.current = {} self.vis = {} self.cid = {} for row, color in enumerate(['red', 'green', 'blue'], 1): lbl = QtGui.QLabel(color.title()) cid = ComponentIDCombo() curr = QtGui.QRadioButton() curr_grp.addButton(curr) vis = QtGui.QCheckBox() vis.setChecked(True) l.addWidget(lbl, row, 0, 1, 1) l.addWidget(cid, row, 1, 1, 1) l.addWidget(curr, row, 2, 1, 1) l.addWidget(vis, row, 3, 1, 1) curr.clicked.connect(self.update_current) vis.toggled.connect(self.update_visible) cid.currentIndexChanged.connect(self.update_layers) self.cid[color] = cid self.vis[color] = vis self.current[color] = curr self.setLayout(l) self.current['red'].click() @property def attributes(self): """A 3-tuple of the ComponentIDs for each RGB layer""" return tuple(self.cid[c].component for c in ['red', 'green', 'blue']) @attributes.setter def attributes(self, cids): for cid, c in zip(cids, ['red', 'green', 'blue']): if cid is None: continue self.cid[c].component = cid @property def rgb_visible(self): """ A 3-tuple of the visibility of each layer, as bools """ return tuple(self.vis[c].isChecked() for c in ['red', 'green', 'blue']) @rgb_visible.setter def rgb_visible(self, value): for v, c in zip(value, 'red green blue'.split()): self.vis[c].setChecked(v) @property def artist(self): return self._artist @artist.setter def artist(self, value): self._artist = value for cid in self.cid.values(): cid.data = value.layer self.update_layers() def update_layers(self): if self.artist is None: return r = self.cid['red'].component g = self.cid['green'].component b = self.cid['blue'].component changed = self.artist.r is not r or \ self.artist.g is not g or\ self.artist.b is not b self.artist.r = r self.artist.g = g self.artist.b = b if changed: self.colors_changed.emit() self.artist.update() self.artist.redraw() def update_current(self, *args): if self.artist is None: return for c in ['red', 'green', 'blue']: if self.current[c].isChecked(): self.artist.contrast_layer = c self.current_changed.emit(c) break else: raise RuntimeError("Could not determine which layer is current") def update_visible(self, *args): if self.artist is None: return self.artist.layer_visible['red'] = self.vis['red'].isChecked() self.artist.layer_visible['green'] = self.vis['green'].isChecked() self.artist.layer_visible['blue'] = self.vis['blue'].isChecked() self.artist.update() self.artist.redraw()