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)
def _draw_fold_indicator(self, top, mouse_over, collapsed, painter): """ Draw the fold indicator/trigger (arrow). :param top: Top position :param mouse_over: Whether the mouse is over the indicator :param collapsed: Whether the trigger is collapsed or not. :param painter: QPainter """ rect = QRect(0, top, self.sizeHint().width(), self.sizeHint().height()) if self._native_icons: opt = QStyleOptionViewItem() opt.rect = rect opt.state = (QStyle.State_Active | QStyle.State_Item | QStyle.State_Children) if not collapsed: opt.state |= QStyle.State_Open if mouse_over: opt.state |= (QStyle.State_MouseOver | QStyle.State_Enabled | QStyle.State_Selected) opt.palette.setBrush(QPalette.Window, self.palette().highlight()) opt.rect.translate(-2, 0) self.style().drawPrimitive(QStyle.PE_IndicatorBranch, opt, painter, self) else: index = 0 if not collapsed: index = 2 if mouse_over: index += 1 ima.icon(self._indicators_icons[index]).paint(painter, rect)
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()
def _style_option(self, index): """Get default style option for index""" option = QStyleOptionViewItem() option.font = self.font() option.rect = self.visualRect(index) option.state = QStyle.State_Enabled return option
def test_custom_eliding_delegate_respects_padding(self): padding = 3 delegate = CustomTextElidingDelegate(padding) painter = mock.MagicMock(spec=QPainter) # we cannot mock the style & index as they are passed to a C++ type that expects real types style, model = QStyleOptionViewItem(), QStandardItemModel(1, 1) style.rect = QRect(0, 0, 99, 29) # give a non-zero sized rectangle to paint in text = str(math.pi) model.setData(model.index(0, 0), text, Qt.DisplayRole) delegate.paint(painter, style, model.index(0, 0)) painter.save.assert_called_once() painter.setPen.assert_not_called() painter.fillRect.assert_not_called() painter.drawText.assert_called_once() painter.restore.assert_called_once() # first call and second argument is the text that will be painted # the exact text depends on the font metric so we have a looser requirement # for matching drawn_text = painter.drawText.call_args[0][2] self.assertTrue(drawn_text.startswith("3.141592")) # Qt uses the 'horizontal ellipsis' unicode symbol for ellision. # To avoid confusion with it look like 3 separate '.' characters in code # we use the unicode codepoint directly self.assertTrue(drawn_text.endswith(b"\xe2\x80\xa6".decode("utf-8")))
def test_custom_eliding_delegate_respects_forgeround_color(self): padding = 3 delegate = CustomTextElidingDelegate(padding) painter = mock.MagicMock(spec=QPainter) # we cannot mock the style & index as they are passed to a C++ type that expects real types style, model = QStyleOptionViewItem(), QStandardItemModel(1, 1) style.rect = QRect(0, 0, 99, 29) # give a non-zero sized rectangle to paint in text, foreground = str(math.pi), QColor(10, 10, 10) model.setData(model.index(0, 0), text, Qt.DisplayRole) model.setData(model.index(0, 0), foreground, Qt.ForegroundRole) delegate.paint(painter, style, model.index(0, 0)) painter.setPen.assert_called_once_with(foreground) painter.fillRect.assert_not_called()
def test_custom_eliding_delegate_respects_background_color(self): padding = 3 delegate = CustomTextElidingDelegate(padding) painter = mock.MagicMock(spec=QPainter) # we cannot mock the style & index as they are passed to a C++ type that expects real types style, model = QStyleOptionViewItem(), QStandardItemModel(1, 1) style.rect = QRect(0, 0, 99, 29) # give a non-zero sized rectangle to paint in text, background = str(math.pi), QColor(5, 5, 5) model.setData(model.index(0, 0), text, Qt.DisplayRole) model.setData(model.index(0, 0), background, Qt.BackgroundRole) delegate.paint(painter, style, model.index(0, 0)) painter.setPen.assert_not_called() painter.fillRect.assert_called_once() # the background color object seems different but we only care about value equality self.assertEqual(background, painter.fillRect.call_args[0][1])