Пример #1
0
class TabBar(QCSWidget):

    tabSelected = QtCore.pyqtSignal(str)

    def __init__(self, spacing=10, parent=None):
        super().__init__(parent=parent)
        self.hbox = HBox(self, spacing=spacing, align=QtCore.Qt.AlignHCenter)
        self.tabs = dict()
        self.tab_group = QtWidgets.QButtonGroup()
        self.tab_group.setExclusive(True)

    def addTab(self, name, title):
        if name in self.tabs:
            return
        btn = QtWidgets.QPushButton(title)
        btn.setCheckable(True)
        self.hbox.addWidget(btn)
        self.tabs[name] = btn
        self.tab_group.addButton(btn)
        btn.toggled.connect(lambda t: t and self.tabSelected.emit(name))

    def setSelected(self, name):
        if name in self.tabs:
            self.tabs[name].setChecked(True)

    def clear(self):
        for tab in self.tabs.values():
            tab.setParent(None)
            self.tab_group.removeButton(tab)
        self.tabs.clear()
Пример #2
0
class AnnotationLabel(QCSWidget):

    __height__ = 30

    removed = QtCore.pyqtSignal(int)

    def __init__(self, label, level_dataset, parent=None):
        super().__init__(parent=parent)
        self.level_dataset = level_dataset
        self.label_idx = label['idx']
        self.label_color = label['color']
        self.label_name = label['name']
        self.label_visible = label['visible']

        self.btn_del = DelIconButton(secondary=True)
        self.txt_label_name = LineEdit(label['name'])
        self.btn_label_color = ColorButton(label['color'])
        self.btn_select = Spacing(35)
        self.setMinimumHeight(self.__height__)
        self.setFixedHeight(self.__height__)

        self.txt_label_name.editingFinished.connect(self.update_label)
        self.btn_label_color.colorChanged.connect(self.update_label)
        self.btn_del.clicked.connect(self.delete)

        hbox = HBox(self)
        hbox.addWidget(
            HWidgets(self.btn_del,
                     self.btn_label_color,
                     self.txt_label_name,
                     self.btn_select,
                     stretch=2))

    def update_label(self):
        label = dict(idx=self.label_idx,
                     name=self.txt_label_name.text(),
                     color=self.btn_label_color.color,
                     visible=self.label_visible)
        params = dict(level=self.level_dataset, workspace=True)
        result = Launcher.g.run('annotations', 'update_label', **params,
                                **label)
        if result:
            self.label_name = result['name']
            self.label_color = result['color']
            self.label_visible = result['visible']
            _AnnotationNotifier.notify()
        else:
            self.txt_label_name.setText(self.label_name)
            self.btn_label_color.setColor(self.label_color)

    def delete(self):
        params = dict(level=self.level_dataset,
                      workspace=True,
                      idx=self.label_idx)
        result = Launcher.g.run('annotations', 'delete_label', **params)
        if result:
            _AnnotationNotifier.notify()
            self.removed.emit(self.label_idx)
Пример #3
0
class AnnotationLevel(Card):

    removed = QtCore.pyqtSignal(str)

    def __init__(self, level, parent=None):
        super().__init__(level['name'],
                         editable=True,
                         collapsible=True,
                         removable=True,
                         addbtn=True,
                         parent=parent)
        self.level_id = level['id']
        self.le_title = LineEdit(level['name'])
        self.le_title.setProperty('header', True)
        self.labels = {}
        self._populate_labels()

    def card_title_edited(self, title):
        params = dict(level=self.level_id, name=title, workspace=True)
        return Launcher.g.run('annotations', 'rename_level', **params)

    def card_add_item(self):
        params = dict(level=self.level_id, workspace=True)
        result = Launcher.g.run('annotations', 'add_label', **params)
        if result:
            self._add_label_widget(result)
            _AnnotationNotifier.notify()

    def card_deleted(self):
        params = dict(level=self.level_id, workspace=True)
        result = Launcher.g.run('annotations', 'delete_level', **params)
        if result:
            self.removed.emit(self.level_id)
            _AnnotationNotifier.notify()

    def remove_label(self, idx):
        if idx in self.labels:
            self.labels.pop(idx).setParent(None)
            self.update_height()

    def _add_label_widget(self, label):
        widget = AnnotationLabel(label, self.level_id)
        widget.removed.connect(self.remove_label)
        self.add_row(widget)
        self.labels[label['idx']] = widget
        self.expand()

    def _populate_labels(self):
        params = dict(level=self.level_id, workspace=True)
        result = Launcher.g.run('annotations', 'get_labels', **params)
        if result:
            for k, label in result.items():
                if k not in self.labels:
                    self._add_label_widget(label)
Пример #4
0
class ColorButton(QtWidgets.QPushButton):

    colorChanged = QtCore.pyqtSignal(str)

    def __init__(self, color='#000000', clickable=True, **kwargs):
        super().__init__(**kwargs)
        self.setColor(color)
        if clickable:
            self.clicked.connect(self.on_click)

    def setColor(self, color):
        color = str(QtGui.QColor(color).name())
        if color is None:
            self.setStyleSheet("""
                QPushButton, QPushButton:hover {
                    background-color:
                        qlineargradient(
                            x1:0, y1:0, x2:1, y2:1,
                            stop: 0 white, stop: 0.15 white,
                            stop: 0.2 red,
                            stop: 0.25 white, stop: 0.45 white,
                            stop: 0.5 red,
                            stop: 0.55 white, stop: 0.75 white,
                            stop: 0.8 red, stop: 0.85 white
                        );
                }
            """)
        else:
            self.setStyleSheet("""
                QPushButton { background-color: %s; }
                QPushButton:hover {
                    background-color:
                        qlineargradient(
                            x1:0, y1:0, x2:0.5, y2:1,
                            stop: 0 white, stop: 1 %s
                        );
                    }
            """ % (color, color))

        self.color = color

    def on_click(self):
        c = QtWidgets.QColorDialog.getColor(QtGui.QColor(self.color), self.parent())
        if not c.isValid():
            return
        self.setColor(str(c.name()))
        self.colorChanged.emit(self.color)

    def value(self):
        return self.color
Пример #5
0
class AcceptModal(_Modal):

    accepted = QtCore.pyqtSignal()

    def __init__(self, message, btn_text='Close', parent=None):
        super().__init__(message, parent=parent)
        self.btn = PushButton(btn_text)
        if parent:
            self.btn.clicked.connect(parent.hide)
        self.btn.clicked.connect(self._trigger)
        self(HWidgets(None, self.btn, None))

    def _trigger(self):
        self.accepted.emit()
Пример #6
0
class YesNoModal(_Modal):

    accepted = QtCore.pyqtSignal(bool)

    def __init__(self, message, msg_yes='Accept', msg_no='Cancel', parent=None):
        super().__init__(message, parent=parent)
        self.yes = PushButton(msg_yes)
        self.no = PushButton(msg_no)
        self.yes.clicked.connect(self._yes)
        self.no.clicked.connect(self._no)
        self(HWidgets(None, self.no, None, self.yes, None))

    def _yes(self):
        self.accepted.emit(True)

    def _no(self):
        self.accepted.emit(False)
Пример #7
0
class LayerManager(QtWidgets.QMenu):

    __all_layers__ = {}

    paramsUpdated = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        vbox = VBox(self, spacing=5, margin=5)
        self.vmin = RealSlider(value=0, vmin=-1, vmax=1, auto_accept=False)
        self.vmax = RealSlider(value=1, vmin=0, vmax=1, auto_accept=False)
        vbox.addWidget(self.vmin)
        vbox.addWidget(self.vmax)
        self._layers = OrderedDict()
        for key, title, cls in self.__all_layers__:
            layer = cls(key)
            layer.updated.connect(self.on_layer_updated)
            vbox.addWidget(SubHeader(title))
            vbox.addWidget(layer)
            self._layers[key] = layer
        self.vmin.valueChanged.connect(self.on_layer_updated)
        self.vmax.valueChanged.connect(self.on_layer_updated)

    def refresh(self):
        for layer in self._layers.values():
            layer.update()
        return self

    def on_layer_updated(self):
        self.paramsUpdated.emit()

    def show_layer(self, layer, view):
        if layer in self._layers:
            self._layers[layer].select(view)

    def value(self):
        params = {k: v.value() for k, v in self._layers.items()}
        params['clim'] = (self.vmin.value(), self.vmax.value())
        return params

    def accept(self):
        self.vmin.accept()
        self.vmax.accept()
        for layer in self._layers.values():
            layer.accept()
Пример #8
0
 def __init__(self, icon, text='', size=None, checkable=False, parent=None, **kwargs):
     super().__init__(parent)
     self.setStyleSheet("""
         QToolButton {
             margin-left: 0px;
         }
         QToolButton::menu-indicator {
             width: 0px;
             border: none;
             image: none;
         }
     """)
     self.setText(text)
     self.setIcon(qta.icon(icon, **kwargs))
     if size is not None:
         self.setIconSize(QtCore.QSize(*size))
     self.setCheckable(checkable)
     self.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon);
Пример #9
0
class Layer(QCSWidget):

    updated = QtCore.pyqtSignal()

    def __init__(self, name='layer', source=None, cmap=None, parent=None):
        super().__init__(parent=parent)
        self.name = name
        self.source = source or ComboBox()
        self.cmap = cmap or CmapComboBox()
        self.slider = Slider(value=100, label=False, auto_accept=False)
        self.checkbox = CheckBox(checked=True)

        hbox = HBox(self, spacing=5, margin=(5, 0, 5, 0))
        hbox.addWidget(self.source, 1)
        hbox.addWidget(self.cmap, 1)
        hbox.addWidget(self.slider)
        hbox.addWidget(self.checkbox)

        if hasattr(self.source, 'currentIndexChanged'):
            self.source.currentIndexChanged.connect(self._params_updated)
        elif hasattr(self.source, 'valueChanged'):
            self.source.valueChanged.connect(self._params_updated)
        if hasattr(self.cmap, 'currentIndexChanged'):
            self.cmap.currentIndexChanged.connect(self._params_updated)
        elif hasattr(self.cmap, 'colorChanged'):
            self.cmap.colorChanged.connect(self._params_updated)

        self.slider.setMinimumWidth(150)
        self.slider.valueChanged.connect(self._params_updated)
        self.checkbox.toggled.connect(self._params_updated)

    def value(self):
        return (self.source.value(), self.cmap.value(), self.slider.value(),
                self.checkbox.value())

    def _params_updated(self):
        self.updated.emit()

    def accept(self):
        self.slider.accept()

    def select(self, view):
        self.source.select(view)
        self.updated.emit()
Пример #10
0
class QCSWidget(SWidget):

    resized = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(self.__class__.__name__, parent=parent)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.resized.emit()

    def __call__(self, widget, stretch=0, connect=None):
        if self.layout() is not None:
            self.layout().addWidget(widget, stretch=stretch)
            if connect and hasattr(widget, connect[0]):
                getattr(widget, connect[0]).connect(connect[1])

    def value(self):
        return None
Пример #11
0
class PluginNotifier(QtCore.QObject):
    updated = QtCore.pyqtSignal()
    def listen(self, *args, **kwargs):
        self.updated.connect(*args, **kwargs)
    def notify(self):
        self.updated.emit()
Пример #12
0
class SliceViewer(QCSWidget):

    slice_updated = QtCore.pyqtSignal(int)

    def __init__(self, layer_manager=None, parent=None):
        super().__init__(parent=parent)
        self.slider = Slider(auto_accept=False, center=True)
        self.viewer = Viewer()
        self.menu_panel = QtWidgets.QToolBar()
        self.tool_container = VBox(margin=0, spacing=0)
        self.current_tool = None

        vbox = VBox(self, margin=15, spacing=10)
        vbox.addWidget(self.slider)
        vbox.addWidget(self.viewer, 1)

        vbox2 = VBox(margin=0, spacing=0)
        vbox2.addLayout(self.tool_container)
        vbox2.addWidget(self.menu_panel)
        vbox.addLayout(vbox2)

        if layer_manager is None:
            layer_manager = WorkspaceLayerManager

        self.tools = []
        self.viz_params = None
        self.layer_manager = self.add_tool('Layer', 'fa.adjust', layer_manager)
        self.layer_manager.paramsUpdated.connect(self.params_updated)
        self.slider.valueChanged.connect(self.show_slice)
        self.slider.sliderReleased.connect(self._updated)

        self.viewer.mpl_connect('button_press_event', self.show_layer_manager)

        self.update()

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.Show:
            p = self.menu_panel
            point = QtCore.QPoint(0, -source.height())
            source.move(p.mapToGlobal(point))
        return source.event(event)

    def clear_tools(self):
        for tool in self.tools[1:]:
            if tool.menu():
                tool.menu().removeEventFilter(self)
            tool.setParent(None)
        self.tools = [self.tools[0]]

    def add_tool(self, name, icon, menu=None, tool=None):
        btn = ToolIconButton(icon,
                             name,
                             size=(36, 36),
                             color='white',
                             checkable=tool is not None and menu is None)
        self.tools.append(btn)
        self.menu_panel.addWidget(btn)

        if tool:
            tool.setProperty('menu', True)
            tool.setVisible(False)
            tool.set_viewer(self)
            self.tool_container.addWidget(tool)
            btn.toggled.connect(lambda flag: self.toggle_tool(tool, flag))

        if menu:
            menu = menu(btn)
            btn.setMenu(menu)
            btn.setPopupMode(QtWidgets.QToolButton.InstantPopup)
            btn.toggled.connect(btn.showMenu)
            menu.installEventFilter(self)
            return menu

    def toggle_tool(self, tool, flag):
        tool.setEnabled(flag)
        if flag:
            self.current_tool = tool
            for tool in layout_widgets(self.tool_container):
                tool.setVisible(False)
            self.current_tool.setVisible(True)
            self.current_tool.slice_updated(self.slider.value())
        else:
            tool.setVisible(False)
            self.current_tool = None

    def update_viz_params(self):
        params = self.layer_manager.value()
        self.viz_params = {k: v for k, v in params.items() if v[0] is not None}

    def show_slice(self, idx):
        params = dict(slice_idx=idx, workspace=True, timeit=True)
        params.update(self.viz_params)
        result = Launcher.g.run('render', 'render_workspace', **params)
        if result:
            image = decode_numpy(result)
            self.viewer.update_image(image)
        self.slider.accept()

    def update(self):
        self.update_viz_params()
        self.show_slice(self.slider.value())

    def _updated(self):
        idx = self.slider.value()
        self.slice_updated.emit(idx)

    def params_updated(self):
        self.update()
        self.layer_manager.accept()

    def setup(self):
        max_depth = DataModel.g.current_workspace_shape[0]
        self.slider.setMaximum(max_depth - 1)

    def show_layer_manager(self, event):
        if event.button != 3:
            return
        self.layer_manager.show()

    def triggerKeybinding(self, key, modifiers):
        if key == QtCore.Qt.Key_H:
            self.viewer.center()
        elif self.current_tool and hasattr(self.current_tool,
                                           'triggerKeybinding'):
            self.current_tool.triggerKeybinding(key, modifiers)

    def install_extension(self, ext):
        self.viewer.install_extension(ext)

    def show_layer(self, plugin, view):
        self.layer_manager.show_layer(plugin, view)
Пример #13
0
 def parent_resized(self):
     self.move(QtCore.QPoint(0, 0))
     self.resize(self.parent().size())
Пример #14
0
class Annotator(ViewerExtension):

    annotated = QtCore.pyqtSignal(tuple)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.color = (1, 0, 0, 1)
        self.color_overlay = (1, 0, 0, 0.5)

        self.annotating = False

        self.line = None
        self.line_width = 1

        self.region = None
        self.region_mask = None
        self.cmap = None

        self.current = dict()
        self.all_regions = set()

    def install(self, fig, axes):
        super().install(fig, axes)
        self.connect('button_press_event', self.draw_press)
        self.connect('button_release_event', self.draw_release)
        self.connect('motion_notify_event', self.draw_motion)
        self.data_size = DataModel.g.current_workspace_shape[1:]
        self.line_mask = np.zeros(self.data_size, np.bool)
        cmap = ListedColormap([(0, 0, 0, 0)] * 2)
        self.line_mask_ax = self.axes.imshow(self.line_mask,
                                             cmap=cmap,
                                             vmin=0,
                                             vmax=1)
        if self.region is not None:
            self.region_mask = self.axes.imshow(
                np.empty(self.data_size, np.uint8))
            self.initialize_region()

    def disable(self):
        super().disable()
        if self.line_mask_ax:
            self.line_mask_ax.remove()
            self.line_mask_ax = None
            self.line_mask = None
        if self.region_mask:
            self.region_mask.remove()
            self.region_mask = None

    def set_region(self, region):
        self.region = region
        if self.axes is None:
            return
        if self.region is None and self.region_mask is not None:
            self.region_mask.remove()
            self.region_mask = None
        if region is None:
            return
        if self.region_mask is None:
            self.region_mask = self.axes.imshow(
                np.empty(self.data_size, np.uint8))
        if region is not None:
            self.initialize_region()
        self.redraw()

    def initialize_region(self):
        n = self.region.max()
        self.region_mask.set_data(self.region)
        self.region_mask.set_clim(0, n)
        self.region_mask.set_alpha(1)
        self.initialize_region_cmap()

    def initialize_region_cmap(self):
        n = self.region.max() + 1
        cmap = [(0, 0, 0, 0)] * n
        self.cmap = ListedColormap(cmap)
        self.region_mask.set_cmap(self.cmap)

    def set_color(self, color):
        self.color = QtGui.QColor(color).getRgbF()
        self.color_overlay = self.color[:3] + (0.5, )
        self.line_mask_ax.set_cmap(ListedColormap([(0, 0, 0, 0), self.color]))

    def set_linewidth(self, line_width):
        self.line_width = line_width

    def draw_press(self, evt):
        if not evt.inaxes == self.axes or evt.button != 1:
            return
        if self.line is not None:
            self.draw_release(evt)

        self.annotating = True

        y = int(evt.ydata)
        x = int(evt.xdata)
        self.current = dict(y=[y], x=[x])
        self.line_mask[y, x] = True

        if self.region is not None and self.cmap is not None:
            if hasattr(self.cmap, '_lut'):
                sv = self.region[y, x]
                self.all_regions |= set([sv])
                self.cmap._lut[sv] = self.color_overlay
                self.region_mask.set_cmap(self.cmap)

        self.fig.redraw()

    def draw_motion(self, evt):
        if not evt.inaxes == self.axes or not self.annotating:
            return
        y = int(evt.ydata)
        x = int(evt.xdata)
        py = self.current['y'][-1]
        px = self.current['x'][-1]
        yy, xx = line(py, px, y, x)
        self.current['y'].append(y)
        self.current['x'].append(x)

        if self.line_width > 1:
            yy, xx = self.dilate_annotations(yy, xx)

        self.line_mask[yy, xx] = True
        self.line_mask_ax.set_data(self.line_mask)

        if self.region is not None and self.cmap is not None:
            svs = set(self.region[yy, xx])
            self.all_regions |= svs
            modified = False
            if hasattr(self.cmap, '_lut'):
                for sv in svs:
                    if self.cmap._lut[sv][-1] == 0:
                        self.cmap._lut[sv] = self.color_overlay
                        modified = True
            if modified:
                self.region_mask.set_cmap(self.cmap)
        self.fig.redraw()

    def draw_release(self, evt):
        if not self.annotating:
            return
        self.annotating = False
        if self.region is None:
            annotations = np.where(self.line_mask)
        else:
            annotations = tuple(self.all_regions)
        # Clear Line
        self.current.clear()
        self.line_mask[:] = False
        self.line_mask_ax.set_data(self.line_mask)
        # Clear regions
        if self.region is not None:
            self.initialize_region_cmap()
            self.all_regions = set()
        # Render clean
        self.fig.redraw()
        # Send result
        self.annotated.emit(annotations)

    def dilate_annotations(self, yy, xx):
        data = np.zeros_like(self.line_mask)
        data[yy, xx] = True

        r = np.ceil(self.line_width / 2)
        ymin = int(max(0, yy.min() - r))
        ymax = int(min(data.shape[0], yy.max() + 1 + r))
        xmin = int(max(0, xx.min() - r))
        xmax = int(min(data.shape[1], xx.max() + 1 + r))
        mask = data[ymin:ymax, xmin:xmax]

        mask = binary_dilation(mask, disk(self.line_width / 2).astype(np.bool))
        yy, xx = np.where(mask)
        yy += ymin
        xx += xmin
        return yy, xx
Пример #15
0
class MultiComboBox(QtWidgets.QPushButton, AbstractLazyWrapper):

    valueChanged = QtCore.pyqtSignal()

    def __init__(self, header=None, lazy=False, select=None,
                 text='Select', groupby=None, parent=None):
        self._items = []
        self._actions = []
        self._header = header
        self._groupby = groupby
        self._text = text
        QtWidgets.QPushButton.__init__(self, parent=parent)
        self._toolmenu = QtWidgets.QMenu(self)
        self._toolmenu.installEventFilter(self)
        AbstractLazyWrapper.__init__(self, lazy)
        self.setMenu(self._toolmenu)
        #self.setPopupMode(QtWidgets.QToolButton.InstantPopup)

        self.setProperty('combo', True)
        self._toolmenu.setProperty('combo', True)
        self._toolmenu.aboutToHide.connect(self._update_text)

        self._update_text()

        # TODO: improve this
        file_path = resource('qcs', 'survos.qcs')
        if op.isfile(file_path):
            with open(file_path, 'r') as f:
                style = f.read()
                self.setStyleSheet(style)
                self._toolmenu.setStyleSheet(style)

    def _add_header(self):
        if self._header is not None:
            self.addItem(*self._header)

    def _update_text(self):
        names = self.names()
        if len(names) == 0:
            self.setText(self._text)
        else:
            self.setText('; '.join(names))

    def eventFilter(self, target, evt):
        super().eventFilter(target, evt)
        if evt.type() == QtCore.QEvent.MouseButtonRelease:
            action = self._toolmenu.activeAction()
            if action:
                action.setChecked(not action.isChecked())
                self.valueChanged.emit()
            return True
        return False

    def addCategory(self, name):
        item = self.addItem(name)
        item.setEnabled(False)

    def addItem(self, key, value=None, icon=None, data=None, checkable=True):
        self._items.append((key, value, data))
        text = value if value else key
        if icon:
            action = self._toolmenu.addAction(icon, text)
        else:
            action = self._toolmenu.addAction(text)
        action.setCheckable(checkable)
        self._actions.append(action)
        return action

    def items(self):
        return (item for item in self._items)

    def removeItem(self, idx):
        self._items.pop(idx)
        self._toolmenu.removeAction(self._actions.pop(idx))

    def update(self):
        prev = list(self.keys())
        self.clear()
        self._add_header()
        self.fill()
        for i, (key, value, data) in enumerate(self.items()):
            if key in prev:
                prev.remove(key)
                self.setItemChecked(i, True)
        self._update_text()
        if len(prev) > 0:
            self.valueChanged.emit()

    def clear(self):
        self._items.clear()
        self._actions.clear()
        self._toolmenu.clear()

    def select(self, key):
        for i, (k, v, d) in enumerate(self._items):
            if not k:
                continue
            kname = k.split(op.sep)
            if k == key or (len(kname) > 1 and kname[1] == key):
                if not self.itemChecked(i):
                    self.setItemChecked(i, True)
                    self._update_text()
                    self.valueChanged.emit()
                    return True
                break
        return False

    def select_prefix(self, key):
        found = False
        for i, k in enumerate(self._items):
            if k and k[0].startswith(key):
                if not self.itemChecked(i):
                    found = True
                    self.setItemChecked(i, True)
        if found:
            self.valueChanged.emit()
        return found

    def key(self):
        return list(self.keys())

    def value(self):
        return list(self.values())

    def itemChecked(self, idx):
        return self._actions[idx].isChecked()

    def setItemChecked(self, idx, flag=True):
        self._actions[idx].setChecked(flag)

    def names(self):
        return list(item[1] for i, item in enumerate(self.items())
                    if self.itemChecked(i))

    def keys(self):
        return self.values(keys=True)

    def values(self, keys=False):
        values = (item[0] if item[2] is None or keys else item[2]
                  for i, item in enumerate(self.items())
                  if self.itemChecked(i))
        if keys:
            return values
        if self._groupby:
            result = defaultdict(list)
            for val in values:
                if len(self._groupby) == 2:
                    group, target = self._groupby
                    if group in val:
                        result[val[group]].append(val[target])
                else:
                    if self._groupby in val:
                        result[val[self._groupby]].append(val)
            return [(k, v) for k,v in result.items()]
        return values
Пример #16
0
class Slider(QCSWidget):

    valueChanged = QtCore.pyqtSignal(int)

    def __init__(self, value=None, vmax=100, vmin=0, step=1, tracking=True,
                 label=True, auto_accept=True, center=False, parent=None):
        super().__init__(parent=parent)
        if value is None:
            value = vmin
        self.setMinimumWidth(200)
        self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider.setMinimum(vmin)
        self.slider.setMaximum(vmax)
        self.slider.setValue(value)
        self.slider.setTickInterval(step)
        self.slider.setSingleStep(step)
        self.slider.setTracking(tracking)
        self.step = step

        hbox = HBox(self, spacing=5)
        if label:
            self.label = Label(str(value))
            self.label.setMinimumWidth(50)
            if center:
                hbox.addSpacing(50)
            hbox.addWidget(self.slider, 1)
            hbox.addWidget(self.label)
            self.valueChanged.connect(self.update_label)
        else:
            hbox.addWidget(self.slider, 1)

        self.slider.valueChanged.connect(self.value_changed)
        self.slider.wheelEvent = self.wheelEvent
        self.auto_accept = auto_accept
        self.locked_idx = None
        self.pending = None
        self.blockSignals = self.slider.blockSignals

    def value_changed(self, idx):
        if self.auto_accept:
            self.valueChanged.emit(idx)
        elif self.locked_idx is None:
            self.locked_idx = idx
            self.valueChanged.emit(idx)
        else:
            self.slider.blockSignals(True)
            self.slider.setValue(self.locked_idx)
            self.slider.blockSignals(False)
            self.pending = idx

    def accept(self):
        if self.pending is not None:
            val = self.pending
            self.pending = None
            self.slider.blockSignals(True)
            self.slider.setValue(val)
            self.slider.blockSignals(False)
            self.valueChanged.emit(val)
        self.locked_idx = None

    def update_label(self, idx):
        self.label.setText(str(idx))

    def wheelEvent(self, e):
        if e.angleDelta().y() > 0 and self.value() < self.maximum():
            self.setValue(self.value()+self.step)
        elif e.angleDelta().y() < 0 and self.value() > self.minimum():
            self.setValue(self.value()-self.step)

    def value(self):
        return self.pending or self.slider.value()

    def setValue(self, value):
        return self.slider.setValue(value)

    def __getattr__(self, key):
        return self.slider.__getattribute__(key)
Пример #17
0
 def eventFilter(self, source, event):
     if event.type() == QtCore.QEvent.Show:
         p = self.menu_panel
         point = QtCore.QPoint(0, -source.height())
         source.move(p.mapToGlobal(point))
     return source.event(event)