def test_connect_current_combo(): class Test(object): a = CallbackProperty() t = Test() combo = QtGui.QComboBox() combo.addItem('a', 'a') combo.addItem('b', 'b') connect_current_combo(t, 'a', combo) combo.setCurrentIndex(1) assert t.a == 'b' combo.setCurrentIndex(0) assert t.a == 'a' combo.setCurrentIndex(-1) assert t.a is None t.a = 'b' assert combo.currentIndex() == 1 t.a = 'a' assert combo.currentIndex() == 0 # TODO: should the following not return an error? with pytest.raises(ValueError) as exc: t.a = 'c' assert exc.value.args[0] == 'c not found in combo box' t.a = None assert combo.currentIndex() == -1
def choose_vmin_vmax(self): dialog = load_ui('contrastlimits.ui', None, directory=os.path.dirname(__file__)) v = QtGui.QDoubleValidator() dialog.vmin.setValidator(v) dialog.vmax.setValidator(v) vmin, vmax = self.get_vmin_vmax() if vmin is not None: dialog.vmin.setText(str(vmin)) if vmax is not None: dialog.vmax.setText(str(vmax)) def _apply(): try: vmin = float(dialog.vmin.text()) vmax = float(dialog.vmax.text()) self.set_vmin_vmax(vmin, vmax) if self._move_callback is not None: self._move_callback(self) except ValueError: pass bb = dialog.buttonBox bb.button(bb.Apply).clicked.connect(_apply) dialog.accepted.connect(_apply) dialog.show() dialog.raise_() dialog.exec_()
def _update_deps(self): status = get_status_as_odict() self._text = "" for name, version in [('Glue', __version__)] + list(status.items()): check = QtGui.QTreeWidgetItem( self.ui.version_tree.invisibleRootItem(), [name, version]) self._text += "{0}: {1}\n".format(name, version)
def tint_pixmap(bm, color): """ Re-color a monochrome pixmap object using `color` Parameters ---------- bm : ``QBitmap`` The Pixmap object color : ``QColor`` The Qt color Returns ------- pixmap : ``QPixmap`` The new pixmap """ if bm.depth() != 1: raise TypeError("Input pixmap must have a depth of 1: %i" % bm.depth()) image = bm.toImage() image.setColor(1, color.rgba()) image.setColor(0, QtGui.QColor(0, 0, 0, 0).rgba()) result = QtGui.QPixmap.fromImage(image) return result
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 connect_float_edit(client, prop, widget): """ Connect widget.setText and client.prop Also pretty-print the number client.prop should be a callback property """ v = QtGui.QDoubleValidator(None) v.setDecimals(4) widget.setValidator(v) def update_prop(): val = widget.text() try: setattr(client, prop, float(val)) except ValueError: setattr(client, prop, 0) def update_widget(val): if val is None: val = 0. widget.setText(pretty_number(val)) add_callback(client, prop, update_widget) widget.editingFinished.connect(update_prop) update_widget(getattr(client, prop))
def _setup_options(self): """ Set up the combo box with the list of attributes """ # Set up radio buttons for subset mode selection if this is a subset if isinstance(self.layer, Subset): self._radio_size = QtWidgets.QButtonGroup() self._radio_size.addButton(self.ui.radio_subset_outline) self._radio_size.addButton(self.ui.radio_subset_data) else: self.ui.radio_subset_outline.hide() self.ui.radio_subset_data.hide() self.ui.label_subset_mode.hide() # Set up attribute list label_data = [(comp.label, comp) for comp in self.visible_components] update_combobox(self.ui.combo_attribute, label_data) # Set up connections with layer artist connect_current_combo(self.layer_artist, 'attribute', self.ui.combo_attribute) connect_float_edit(self.layer_artist, 'vmin', self.ui.value_min) connect_float_edit(self.layer_artist, 'vmax', self.ui.value_max) connect_color(self.layer_artist, 'color', self.ui.label_color) connect_value(self.layer_artist, 'alpha', self.ui.slider_alpha, value_range=(0, 1)) # Set up internal connections self.ui.radio_subset_outline.toggled.connect(self._update_subset_mode) self.ui.radio_subset_data.toggled.connect(self._update_subset_mode) self.ui.value_min.editingFinished.connect(self._cache_limits) self.ui.value_max.editingFinished.connect(self._cache_limits) self.ui.combo_attribute.currentIndexChanged.connect(self._update_limits)
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 _build_ui(self, callback): result = QtGui.QWidget() layout = QtGui.QFormLayout() layout.setFieldGrowthPolicy(layout.AllNonFixedFieldsGrow) result.setLayout(layout) for k in sorted(self.ui): v = self.ui[k] w = FormElement.auto(v) w.container = self.widget._layer_artist_container w.add_callback(callback) self._settings[k] = w if w.ui is not None: layout.addRow(k.title().replace('_', ' '), w.ui) return result
def _setup_widget(self): self.widget = QtGui.QTextEdit() self.widget.setHtml("To <b> slide </b> through the cube, " "drag the handle or double-click<br><br><br>" "To make a <b> new profile </b>, " "click-drag a new box in the image, or drag " "a subset onto the plot to the left") self.widget.setTextInteractionFlags(Qt.NoTextInteraction)
def _update_image(self): if not self._frozen: frame = self._webcam.capture_frame() self._image = QtGui.QImage( frame.tostring(), frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888).rgbSwapped() self._data = frame_to_data(frame) self.update()
def _init_limits(self): validator = QtGui.QDoubleValidator(None) validator.setDecimals(7) self.ui.xmin.setValidator(validator) self.ui.xmax.setValidator(validator) lo, hi = self.client.xlimits self.ui.xmin.setText(str(lo)) self.ui.xmax.setText(str(hi))
def __init__(self, argument, parent=None): super(ArgumentWidget, self).__init__(parent) self.layout = QtGui.QHBoxLayout() self.layout.setContentsMargins(1, 0, 1, 1) self.setLayout(self.layout) label = QtGui.QLabel(argument) self._label = label self._component_id = None self.layout.addWidget(label) self.editor = QtGui.QLineEdit() self.editor.setReadOnly(True) try: self.editor.setPlaceholderText("Drag a component from above") except AttributeError: # feature added in Qt 4.7 pass self.layout.addWidget(self.editor) self.setAcceptDrops(True)
def test_glue_action_button(): a = QtGui.QAction(None) a.setToolTip("testtooltip") a.setWhatsThis("testwhatsthis") a.setIcon(QtGui.QIcon("dummy_file")) a.setText('testtext') b = GlueActionButton() b.set_action(a) # assert b.icon() == a.icon() icons are copied, apparently assert b.text() == a.text() assert b.toolTip() == a.toolTip() assert b.whatsThis() == a.whatsThis() #stays in sync a.setText('test2') assert b.text() == 'test2'
def action(name, parent, tip='', icon=None, shortcut=None): """ Factory for making a new action """ a = QtGui.QAction(name, parent) a.setToolTip(tip) if icon: a.setIcon(get_icon(icon)) if shortcut: a.setShortcut(shortcut) return a
def toggle_record(self): if self.record_action.isChecked(): # pop up a window for file saving outfile, file_filter = getsavefilename( caption='Save Animation', filters='GIF Files (*.gif);;') # This indicates that the user cancelled if not outfile: self.record_action.blockSignals(True) self.record_action.setChecked(False) self.record_action.blockSignals(False) return self.record_action.setIcon(QtGui.QIcon(RECORD_STOP_ICON)) self.writer = imageio.get_writer(outfile) self.record_timer.start(0.1) else: self.record_timer.stop() self.record_action.setIcon(QtGui.QIcon(RECORD_START_ICON)) self.writer.close()
def __init__(self, *args, **kwargs): super(ContourMode, self).__init__(*args, **kwargs) self.icon = QtGui.QIcon(os.path.join(ROOT, "glue_contour.png")) self.mode_id = 'Contour' self.action_text = 'Contour' self.tool_tip = 'Define a region of intrest via contours' self.shortcut = 'N'
def __init__(self, *args, **kwargs): super(QMessageBoxPatched, self).__init__(*args, **kwargs) copy_action = QtGui.QAction('&Copy', self) copy_action.setShortcut(QtGui.QKeySequence.Copy) copy_action.triggered.connect(self.copy_detailed) select_all = QtGui.QAction('Select &All', self) select_all.setShortcut(QtGui.QKeySequence.SelectAll) select_all.triggered.connect(self.select_all) menubar = QtGui.QMenuBar() editMenu = menubar.addMenu('&Edit') editMenu.addAction(copy_action) editMenu.addAction(select_all) self.layout().setMenuBar(menubar)
def add_mode(self, mode): parent = QtGui.QToolBar.parent(self) def toggle(): self._custom_mode(mode) def enable(): # turn on if not if self._active != mode.mode_id: self._custom_mode(mode) action = QtGui.QAction(mode.icon, mode.action_text, parent) action.triggered.connect(nonpartial(toggle)) parent.addAction(action) self.__signals.extend([toggle, enable]) if mode.shortcut is not None: action.setShortcut(mode.shortcut) action.setShortcutContext(Qt.WidgetShortcut) action.setToolTip(mode.tool_tip) action.setCheckable(True) self.buttons[mode.mode_id] = action menu_actions = mode.menu_actions() if len(menu_actions) > 0: menu = QtGui.QMenu(self) for ma in mode.menu_actions(): ma.setParent(self) menu.addAction(ma) action.setMenu(menu) menu.triggered.connect(nonpartial(enable)) self.addAction(action) # bind action status to mode.enabled def toggle(state): action.setVisible(state) action.setEnabled(state) add_callback(mode, 'enabled', toggle) return action
def __init__(self, attribute_combo, lower_value, upper_value, mode_combo=None, flip_button=None, log_button=None, data=None, limits_cache=None): self.component_id_combo = attribute_combo self.mode_combo = mode_combo self.lower_value = lower_value self.upper_value = upper_value self.flip_button = flip_button self.log_button = log_button self.component_id_combo.currentIndexChanged.connect( self._update_limits) self.lower_value.editingFinished.connect(self._manual_edit) self.upper_value.editingFinished.connect(self._manual_edit) if self.log_button is None: self.log_button = QtGui.QToolButton() self.log_button.toggled.connect(self._manual_edit) if self.mode_combo is None: # Make hidden combo box to avoid having to always figure out if the # combo mode exists. This will then always be set to Min/Max. self.mode_combo = QtGui.QComboBox() self._setup_mode_combo() self.mode_combo.currentIndexChanged.connect(self._update_mode) if self.flip_button is not None: self.flip_button.clicked.connect(self._flip_limits) if limits_cache is None: limits_cache = {} self._limits = limits_cache self._callbacks = []
def _build_ui(self): w = QtGui.QComboBox() for p in sorted(self.params): w.addItem(p) if isinstance(self.params, list): self.params = dict((p, p) for p in self.params) w.currentIndexChanged.connect(nonpartial(self.changed)) return w
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 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 setup_method(self, method): self.data = example_data.test_data() self.collect = core.data_collection.DataCollection(list(self.data)) self.hub = self.collect.hub self.widget = LayerTreeWidget() self.win = QtGui.QMainWindow() self.win.setCentralWidget(self.widget) self.widget.setup(self.collect) for key, value in self.widget._actions.items(): self.__setattr__("%s_action" % key, value)
def __init__(self, app): w = QtGui.QTableWidget(parent=None) w.setColumnCount(2) w.setRowCount(len(list(app.settings))) w.setHorizontalHeaderLabels(["Setting", "Value"]) for row, (key, value) in enumerate(app.settings): k = QtGui.QTableWidgetItem(key) v = QtGui.QTableWidgetItem(str(value)) k.setFlags(k.flags() ^ (Qt.ItemIsEditable | Qt.ItemIsSelectable)) w.setItem(row, 0, k) w.setItem(row, 1, v) w.sortItems(0) w.cellChanged.connect(self.update_setting) w.setWindowModality(Qt.ApplicationModal) w.resize(350, 340) w.setColumnWidth(0, 160) w.setColumnWidth(1, 160) w.setWindowTitle("Glue Settings") self._widget = w self.app = app
def layer_artist_icon(artist): """Create a QtGui.QIcon for a LayerArtist instance""" # TODO: need a test for this from glue.viewers.image.layer_artist import ImageLayerArtist if not artist.enabled: bm = QtGui.QBitmap(icon_path('glue_delete')) elif isinstance(artist, ImageLayerArtist): bm = QtGui.QBitmap(icon_path('glue_image')) else: bm = QtGui.QBitmap( icon_path( POINT_ICONS.get(artist.layer.style.marker, 'glue_circle_point'))) color = mpl_to_qt4_color(artist.layer.style.color) pm = tint_pixmap(bm, color) return QtGui.QIcon(pm)
def __init__(self, parent=None): super(VispyWidget, self).__init__(parent=parent) # Prepare Vispy canvas. We set the depth_size to 24 to avoid issues # with isosurfaces on MacOS X self.canvas = scene.SceneCanvas(keys='interactive', show=False, config={'depth_size': 24}) # Set up a viewbox self.view = self.canvas.central_widget.add_view() self.view.parent = self.canvas.scene # Set whether we are emulating a 3D texture. This needs to be enabled # as a workaround on Windows otherwise VisPy crashes. self.emulate_texture = (sys.platform == 'win32' and sys.version_info[0] < 3) self.scene_transform = scene.STTransform() self.limit_transforms = {} # Add a 3D cube to show us the unit cube. The 1.001 factor is to make # sure that the grid lines are not 'hidden' by volume renderings on the # front side due to numerical precision. vertices, filled_indices, outline_indices = create_cube() self.axis = scene.visuals.Mesh(vertices['position'], outline_indices, color=(1, 1, 1), mode='lines') self.axis.transform = self.scene_transform self.view.add(self.axis) # Create a turntable camera. For now, this is the only camerate type # we support, but if we support more in future, we should implement # that here # Remove the fov=60 here to solve the mismatch of selection problem # self.view.camera = scene.cameras.TurntableCamera(parent=self.view.scene, distance=2) self.view.camera = scene.cameras.TurntableCamera( parent=self.view.scene, distance=2.0) # Add the native canvas widget to this widget layout = QtGui.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.canvas.native) self.setLayout(layout) # We need to call render here otherwise we'll later encounter an OpenGL # program validation error. self.canvas.render() # Set up callbacks add_callback(self, 'visible_axes', nonpartial(self._toggle_axes))
def _create_actions(self): tree = self.ui.layerTree sep = QtGui.QAction("", tree) sep.setSeparator(True) tree.addAction(sep) self._actions['save'] = SaveAction(self) self._actions['copy'] = CopyAction(self) self._actions['paste'] = PasteAction(self) self._actions['paste_special'] = PasteSpecialAction(self) self._actions['invert'] = Inverter(self) self._actions['new'] = NewAction(self) self._actions['clear'] = ClearAction(self) self._actions['delete'] = DeleteAction(self) self._actions['facet'] = FacetAction(self) self._actions['merge'] = MergeAction(self) self._actions['maskify'] = MaskifySubsetAction(self) # new component definer separator = QtGui.QAction("sep", tree) separator.setSeparator(True) tree.addAction(separator) a = action("Define new component", self, tip="Define a new component using python expressions") tree.addAction(a) a.triggered.connect(nonpartial(self._create_component)) self._actions['new_component'] = a # user-defined layer actions for name, callback, tooltip, icon in single_subset_action: self._actions[name] = SingleSubsetUserAction(self, callback, name=name, tooltip=tooltip, icon=icon) # right click pulls up menu tree.setContextMenuPolicy(Qt.ActionsContextMenu)
def __init__(self, parent=None, layer_style_widget_cls=None): super(LayerArtistWidget, self).__init__(parent=parent) self.layout = QtGui.QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.layer_style_widget_cls = layer_style_widget_cls self.layer_list = LayerArtistView(parent=self) self.layout.addWidget(self.layer_list) self.layer_options = QtGui.QWidget() self.layer_options_layout = QtGui.QStackedLayout() self.layer_options.setLayout(self.layer_options_layout) self.layout.addWidget(self.layer_options) self.setLayout(self.layout) self.layout_style_widgets = {}
class ClearAction(LayerAction): _title = "Clear subset" _tooltip = "Clear current subset" _shortcut = QtGui.QKeySequence('Ctrl+K') def _can_trigger(self): return self.single_selection_subset_group() def _do_action(self): assert self._can_trigger() subset = self.selected_layers()[0] subset.subset_state = core.subset.SubsetState()