Пример #1
0
    def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex):
        """Renders the delegate using the given painter and style option for the item specified by index.

        :param painter: A QPainter object to draw
        :param option: Options to describe what should be drawn
        :param index: _description_
        """
        if not index.isValid():
            return

        # Initialize the style options. This is not very Pythonic as it uses C++
        # references under the hood so opt is affected by the second call
        opt = QStyleOptionViewItem(option)
        self.initStyleOption(opt, index)

        # Standard setup, paint, restore operation
        painter.save()
        try:
            painter.setClipRect(opt.rect)
            foreground_colour, background_colour = index.data(Qt.ForegroundRole), index.data(Qt.BackgroundRole)
            if foreground_colour is not None:
                painter.setPen(foreground_colour)
            if background_colour is not None:
                painter.fillRect(option.rect, background_colour)
            padding = self._padding
            opt.rect = option.rect.adjusted(padding, padding, -padding, -padding)
            painter.drawText(opt.rect, int(Qt.AlignLeft | Qt.AlignVCenter),
                             opt.fontMetrics.elidedText(opt.text, Qt.ElideRight, opt.rect.width()))
        finally:
            painter.restore()
Пример #2
0
 def drop_canvas(self, key: QModelIndex):
     # TODO: do we use this anywhere?
     return
     intent = key.data(IntentsModel.intent_role)
     canvas = key.data(EnsembleModel.canvas_role)
     if canvas:
         canvas_can_be_removed = canvas.unrender(intent)
         if canvas_can_be_removed:
             key.model().removeRow(key.row(), key.parent())
             key.model().layoutChanged.emit()
Пример #3
0
    def paint(self, painter, option: QStyleOptionViewItem, index: QModelIndex) -> None:

        text = index.data(RealLabelHint)
        colors = index.data(RealJobColorHint)

        painter.save()
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setRenderHint(QPainter.SmoothPixmapTransform, True)

        border_pen = QPen()
        border_pen.setColor(QColorConstants.Black)
        border_pen.setWidth(1)

        if option.state & QStyle.State_Selected:

            # selection outline
            select_color = QColorConstants.Blue
            painter.setBrush(select_color)
            painter.setPen(border_pen)
            painter.drawRect(option.rect)

            # job status
            margin = 5
            rect = QRect(
                option.rect.x() + margin,
                option.rect.y() + margin,
                option.rect.width() - (margin * 2),
                option.rect.height() - (margin * 2),
            )
            painter.fillRect(rect, index.data(RealStatusColorHint))

            self._paint_inner_grid(painter, option.rect, colors)

            text_pen = QPen()
            text_pen.setColor(select_color)
            painter.setPen(text_pen)
            painter.drawText(option.rect, Qt.AlignCenter, text)

        else:
            # # job status
            painter.setBrush(index.data(RealStatusColorHint))
            painter.setPen(border_pen)
            painter.drawRect(option.rect)

            self._paint_inner_grid(painter, option.rect, colors)

            text_pen = QPen()
            text_pen.setColor(QColorConstants.Black)
            painter.setPen(text_pen)
            painter.drawText(option.rect, Qt.AlignCenter, text)

        painter.restore()
Пример #4
0
    def paint(self, painter, option: QStyleOptionViewItem,
              index: QModelIndex) -> None:
        text = index.data(RealLabelHint)
        colors = tuple(index.data(RealJobColorHint))
        real_status_color = index.data(RealStatusColorHint)

        painter.save()
        painter.setRenderHint(QPainter.Antialiasing, False)
        painter.setRenderHint(QPainter.TextAntialiasing, True)
        painter.setRenderHint(QPainter.SmoothPixmapTransform, False)

        border_pen = QPen()
        border_pen.setColor(QColorConstants.Black)
        border_pen.setWidth(1)

        painter.setBrush(QColorConstants.Blue)
        painter.setPen(border_pen)
        painter.drawRect(option.rect)

        margin = 0
        if option.state & QStyle.State_Selected:
            margin = 5

        real_status_rect = QRect(
            option.rect.x() + margin,
            option.rect.y() + margin,
            option.rect.width() - (margin * 2),
            option.rect.height() - (margin * 2),
        )
        painter.setBrush(QColorConstants.Gray)
        painter.setBrush(real_status_color)
        painter.drawRect(real_status_rect)

        job_rect_margin = 10
        job_rect = QRect(
            option.rect.x() + job_rect_margin,
            option.rect.y() + job_rect_margin,
            option.rect.width() - (job_rect_margin * 2),
            option.rect.height() - (job_rect_margin * 2),
        )

        self._paint_inner_grid(painter, job_rect, colors)

        text_pen = QPen()
        text_pen.setColor(QColorConstants.Black)
        painter.setPen(text_pen)
        painter.drawText(option.rect, Qt.AlignCenter, text)

        painter.restore()
Пример #5
0
 def paint(self, painter: QPainter, style: QStyleOptionViewItem,
           model: QModelIndex):
     if model.data() not in image_dict:
         image_dict[model.data()] = create_colormap_image(
             model.data(), self.color_dict)
     rect = QRect(style.rect.x(),
                  style.rect.y() + 2, style.rect.width(),
                  style.rect.height() - 4)
     painter.drawImage(rect, image_dict[model.data()])
     if int(style.state & QStyle.State_HasFocus):
         painter.save()
         pen = QPen()
         pen.setWidth(5)
         painter.setPen(pen)
         painter.drawRect(rect)
         painter.restore()
Пример #6
0
    def paint(
        self,
        painter: QPainter,
        style: QStyleOptionViewItem,
        model: QModelIndex,
    ):
        style2 = QStyleOptionViewItem(style)

        cbar_rect = QRect(
            style.rect.x(),
            style.rect.y() + PADDING,
            style.rect.width() - TEXT_WIDTH,
            style.rect.height() - 2 * PADDING,
        )
        text_rect = QRect(
            style.rect.width() - TEXT_WIDTH,
            style.rect.y() + PADDING,
            style.rect.width(),
            style.rect.height() - 2 * PADDING,
        )
        style2.rect = text_rect
        super().paint(painter, style2, model)
        cbar = make_colorbar(ensure_colormap(model.data()), (18, 100))
        image = QImage(
            cbar,
            cbar.shape[1],
            cbar.shape[0],
            QImage.Format_RGBA8888,
        )
        painter.drawImage(cbar_rect, image)
Пример #7
0
    def paint(self, painter, option: QStyleOptionViewItem,
              index: QModelIndex) -> None:
        data = index.data(ProgressRole)
        if data is None:
            return

        nr_reals = data["nr_reals"]
        status = data["status"]
        delta = option.rect.width() / nr_reals

        painter.save()

        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setRenderHint(QPainter.SmoothPixmapTransform, True)

        painter.fillRect(option.rect, self.background_color)

        i = 0
        for state, color_ref in REAL_STATE_TO_COLOR.items():

            if state not in status:
                continue

            state_progress = status[state]
            x = math.ceil(option.rect.x() + i * delta)
            y = option.rect.y()
            w = math.ceil(state_progress * delta)
            h = option.rect.height()
            color = QColor(*color_ref)

            painter.fillRect(x, y, w, h, color)

            i += state_progress

        painter.restore()
Пример #8
0
    def canvas_from_index(self, index: QModelIndex):
        if not index.isValid():
            return None

        if index.data(
                EnsembleModel.data_type_role) != WorkspaceDataType.Intent:
            print(f'WARNING: canvas_from_index index {index} is not an intent')
            return None

        # Canvas exists for index, return
        # TODO: in tab view, with multiple intents selected (e.g. 2 rows checked),
        #       non-0 row intents (every intent except first) does not have a valid object in canvas_role
        canvas = index.model().data(index, EnsembleModel.canvas_role)
        if canvas:
            return canvas

        # There is another canvas we know about we should use
        for match_index in self.all_intent_indexes(index.model()):
            if self.is_matching_canvas_type(index, match_index):
                canvas = match_index.model().data(match_index,
                                                  EnsembleModel.canvas_role)
                if canvas is not None:
                    index.model().setData(index, canvas,
                                          EnsembleModel.canvas_role)
                    return canvas

        # Does not exist, create new canvas and return
        intent = index.model().data(index, EnsembleModel.object_role)
        canvas_class_name = intent.canvas
        registry = pluginmanager
        canvas = self.canvas_from_registry(canvas_class_name, registry,
                                           intent.canvas_name)

        index.model().setData(index, canvas, EnsembleModel.canvas_role)
        return canvas
Пример #9
0
    def editorEvent(
        self,
        event: QtCore.QEvent,
        model: QtCore.QAbstractItemModel,
        option: QStyleOptionViewItem,
        index: QtCore.QModelIndex,
    ) -> bool:
        """Called when an event has occured in the editor.

        This can be used to customize how the delegate handles mouse/key events
        """
        if (event.type() == event.MouseButtonRelease
                and event.button() == Qt.RightButton):
            self.show_context_menu(index, model, event.globalPos(),
                                   option.widget)

        # if the user clicks quickly on the visibility checkbox, we *don't*
        # want it to be interpreted as a double-click.  We want the visibilty
        # to simply be toggled.
        if event.type() == event.MouseButtonDblClick:
            self.initStyleOption(option, index)
            style = option.widget.style()
            check_rect = style.subElementRect(
                style.SE_ItemViewItemCheckIndicator, option, option.widget)
            if check_rect.contains(event.pos()):
                cur_state = index.data(Qt.CheckStateRole)
                if model.flags(index) & Qt.ItemIsUserTristate:
                    state = Qt.CheckState((cur_state + 1) % 3)
                else:
                    state = Qt.Unchecked if cur_state else Qt.Checked
                return model.setData(index, state, Qt.CheckStateRole)
        # refer all other events to the QStyledItemDelegate
        return super().editorEvent(event, model, option, index)
Пример #10
0
    def data(self, index: QModelIndex, role: Qt.ItemDataRole):
        """Return data at `index` for the requested `role`.

        see https://doc.qt.io/qt-5/model-view-programming.html#item-roles
        """
        if role == Qt.EditRole:
            return index.data(Qt.UserRole).name
        if role == Qt.DecorationRole:  # thumbnail
            key_frame = index.data(Qt.UserRole)
            return QImage(
                key_frame.thumbnail,
                key_frame.thumbnail.shape[1],
                key_frame.thumbnail.shape[0],
                QImage.Format_RGBA8888,
            )
        if role == Qt.SizeHintRole:  # determines size of item
            return QSize(160, 34)
        return super().data(index, role)
Пример #11
0
 def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex):
     """
     Paint a checkbox without the label.
     """
     data = index.data()
     if data is None:
         logger.error(f"No data found at {index.row()}, {index.column()}")
         data = 0
     self.drawCheck(painter, option, option.rect, Qt.Unchecked if int(data) == 0 else Qt.Checked)
     self.drawFocus(painter, option, option.rect)
Пример #12
0
    def is_matching_canvas_type(self, index: QModelIndex,
                                match_index: QModelIndex):
        match_intent = match_index.data(EnsembleModel.object_role)
        intent = index.data(EnsembleModel.object_role)
        if not isinstance(intent, Intent):
            print(
                f"WARNING: during matching, index {index.data} is not an Intent"
            )
            return False
        if not isinstance(match_intent, Intent):
            print(
                f"WARNING: during matching, match_index {index.data} is not an Intent"
            )
            return False
        # assert isinstance(intent, Intent)
        # assert isinstance(match_intent, Intent)

        # Ignore self matching
        if intent is match_intent:
            return False

        match_canvas_type_string = match_intent.canvas
        intent_canvas_type_string = intent.canvas

        match_intent_canvas_type = pluginmanager.get_plugin_by_name(
            match_canvas_type_string, "IntentCanvasPlugin")
        intent_canvas_type = pluginmanager.get_plugin_by_name(
            intent_canvas_type_string, "IntentCanvasPlugin")

        if not issubclass(intent_canvas_type, match_intent_canvas_type) \
            and not issubclass(match_intent_canvas_type, intent_canvas_type):
            return False

        # By definition, if a match_key is not provided, the intent is un-matchable
        if intent.match_key is None or match_intent.match_key is None:
            return False

        if intent.match_key != match_intent.match_key:
            return False

        return True
Пример #13
0
    def dataChanged(self,
                    topLeft: QModelIndex,
                    bottomRight: QModelIndex,
                    roles=None):
        """
        Re-implements the QAbstractItemView.dataChanged() slot.

        When the data attached to the Qt.CheckStateRole has been changed, this will either render a Hint or remove the
        Hint visualization.

        Parameters
        ----------
        topLeft
            For now, the only index we are concerned with, which corresponds to the item's check state changing.
        bottomRight
            (Unused right now)
        roles
            List of roles attached to the data state change.

        """
        if roles is None:
            roles = []
        if self.model():
            # empty list indicates ALL roles have changed (see documentation)
            if Qt.CheckStateRole in roles or len(roles) == 0:
                hint = topLeft.data(Qt.UserRole)
                if hint:
                    if topLeft.data(Qt.CheckStateRole) == Qt.Checked:
                        if hint.group not in [
                                self._tabWidget.tabText(index)
                                for index in range(self._tabWidget.count())
                        ]:
                            canvas = hint.init_canvas(addLegend=True)
                            self._tabWidget.addTab(canvas, hint.group)
                        else:
                            canvas = self._findTab(hint.group)
                        hint.visualize(canvas)
                    else:
                        hint.remove()
            super(HintTabView, self).dataChanged(topLeft, bottomRight, roles)
Пример #14
0
 def createEditor(
     self,
     parent: QWidget,
     option: QStyleOptionViewItem,
     index: QtCore.QModelIndex,
 ) -> QWidget:
     """User has double clicked on layer name."""
     # necessary for geometry, otherwise editor takes up full width.
     self.get_layer_icon(option, index)
     editor = super().createEditor(parent, option, index)
     # make sure editor has same alignment as the display name
     editor.setAlignment(Qt.Alignment(index.data(Qt.TextAlignmentRole)))
     return editor
Пример #15
0
    def _activate(self, index: QModelIndex):
        display = index.data(
            HappiClientModel.displayRole)  # try to get display from model

        if not display:
            happi_item = index.data(HappiClientModel.happiItemRole)
            device = from_container(happi_item)

            try:
                device.wait_for_connection()
            except TimeoutError as ex:
                msg.logError(ex)

            controller_name = happi_item.extraneous.get(
                "controller_class", "typhos")
            controller = pluginmanager.get_plugin_by_name(
                controller_name, 'ControllerPlugin')
            display = controller(device)

            # Stash display back on the model
            self.model().setData(index, display, HappiClientModel.displayRole)

        self.sigShowControl.emit(display)
Пример #16
0
    def setData(self,
                index: QModelIndex,
                value: Any,
                role: Qt.ItemDataRole = Qt.EditRole) -> bool:
        if not index.isValid():
            return False

        if role == self.active_role:
            self._set_active_data(index, value)

        elif role == Qt.DisplayRole:
            # Intercept display text changes for ensembles (i.e. renaming) so we can update the title
            # also ONLY update the title if it is the active item
            if index.data(self.data_type_role
                          ) == WorkspaceDataType.Ensemble and index.data(
                              self.active_role):
                self._update_title(value)

        # Add other role handling here
        else:
            ...

        return super(EnsembleModel, self).setData(index, value, role)
Пример #17
0
    def paint(self, painter, option: QStyleOptionViewItem,
              index: QModelIndex) -> None:
        data = index.data(ProgressRole)
        nr_reals = 0
        status = {}
        if data:
            nr_reals = data["nr_reals"]
            status = data["status"]

        painter.save()
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setRenderHint(QPainter.SmoothPixmapTransform, True)

        background_color = QApplication.palette().color(QPalette.Window)
        painter.fillRect(option.rect.x(), option.rect.y(), option.rect.width(),
                         30, background_color)

        total_states = len(REAL_STATE_TO_COLOR.items())
        d = math.ceil(option.rect.width() / total_states)
        x_pos = 0
        for state, color_ref in REAL_STATE_TO_COLOR.items():

            state_progress = 0
            if state in status:
                state_progress = status[state]

            x = x_pos
            y = option.rect.y()
            w = d
            h = option.rect.height()
            margin = 5

            painter.setBrush(QColor(*color_ref))
            painter.drawRect(x, y + margin, 20, 20)
            painter.drawText(
                x + 25,
                y + margin,
                w - 25,
                h,
                Qt.AlignLeft,
                f"{state} ({state_progress}/{nr_reals})",
            )
            x_pos += d

        painter.restore()
Пример #18
0
    def paint(self, painter: QPainter, option: QStyleOptionViewItem,
              index: QModelIndex) -> None:
        super().paint(painter, option, index)

        cellState: CellState = index.data(Qt.BackgroundRole)
        if cellState == CellState.Invalid:
            padding = 0
            x = option.rect.x() + padding
            y = option.rect.y() + padding
            w = option.rect.width() - 1 - padding
            h = option.rect.height() - 1 - padding

            pen = QPen()
            pen.setColor(QColor(*(Color.Red).value))
            pen.setWidth(1)

            painter.setPen(pen)
            painter.drawRect(QRect(x, y, w, h))
Пример #19
0
 def currentChanged(self: QAbstractItemView, current: QModelIndex,
                    previous: QModelIndex):
     """The Qt current item has changed. Update the python model."""
     self._root.selection._current = current.data(Qt.UserRole)
     return super().currentChanged(current, previous)