def sizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) -> QSize: widget = option.widget template = self.template(-10**self.ndigits, self.ndecimals) span = self.spanData(index) if span is not None: vmin, vmax = span t1 = self.template(vmin, self.ndecimals) t2 = self.template(vmax, self.ndecimals) template = max((t1, t2), key=len) style = widget.style() if widget is not None else QApplication.style() # Keep ref to style wrapper. This is ugly, wrong but the wrapping of # C++ QStyle instance takes ~5% unless the wrapper already exists. self.__style = style opt = QStyleOptionViewItem(option) opt.features |= QStyleOptionViewItem.HasDisplay sh = QSize() key = option.font.key(), template if key not in self.__sh_cache: for d in map(str, range(10)): opt.text = template.replace("X", d) sh_ = style.sizeFromContents(QStyle.CT_ItemViewItem, opt, QSize(), widget) sh = sh.expandedTo(sh_) self.__sh_cache[key] = sh else: sh = self.__sh_cache[key] return QSize(sh)
def paint(self, painter, option, index): options = QStyleOptionViewItem(option) row_obj = index.data(Qt.DisplayRole) self.initStyleOption(options, index) # print(option.rect.width()) style = QApplication.style( ) if options.widget is None else options.widget.style() doc = QTextDocument() doc.setHtml(row_obj.to_html()) doc.setTextWidth(option.rect.width() - 10) # doc.setPageSize(300) # print(doc.loadResource(3)) options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() text_rect = style.subElementRect(QStyle.SE_ItemViewItemText, options) painter.save() painter.translate(text_rect.topLeft()) painter.setClipRect(text_rect.translated(-text_rect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def paint(self, painter, option, index): options = QStyleOptionViewItem(option) self.initStyleOption(options, index) style = QApplication.style( ) if options.widget is None else options.widget.style() doc = QtGui.QTextDocument() doc.setHtml(options.text) options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QtGui.QAbstractTextDocumentLayout.PaintContext() if options.state & QStyle.State_Selected: ctx.palette.setColor( QtGui.QPalette.Text, options.palette.color(QtGui.QPalette.Active, QtGui.QPalette.HighlightedText)) textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def paint(self, painter, option, index): options = QStyleOptionViewItem(option) self.initStyleOption(options,index) style = QApplication.style() if options.widget is None else options.widget.style() doc = QtGui.QTextDocument() doc.setHtml(options.text) options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QtGui.QAbstractTextDocumentLayout.PaintContext() if options.state & QStyle.State_Selected: ctx.palette.setColor(QtGui.QPalette.Text, options.palette.color(QtGui.QPalette.Active, QtGui.QPalette.HighlightedText)) textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def _prepare_text_document(self, option, index): # This logic must be shared between paint and sizeHint for consitency options = QStyleOptionViewItem(option) self.initStyleOption(options, index) doc = QTextDocument() doc.setDocumentMargin(self._margin) doc.setHtml(options.text) icon_height = doc.size().height() - 2 options.decorationSize = QSize(icon_height, icon_height) return options, doc
def test_init_style_options(self): delegate = self.delegate model = self.model index = model.index(0, 0) model.setData(index, 1, Qt.DisplayRole) opt = QStyleOptionViewItem() delegate.initStyleOption(opt, index) self.assertEqual(opt.displayAlignment, Qt.AlignRight) model.setData(index, "A", Qt.DisplayRole) opt = QStyleOptionViewItem() delegate.initStyleOption(opt, index) self.assertEqual(opt.displayAlignment, Qt.AlignLeft)
def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex) -> None: opt = QStyleOptionViewItem(option) self.initStyleOption(opt, index) widget = option.widget style = QApplication.style() if widget is None else widget.style() # Keep ref to style wrapper. This is ugly, wrong but the wrapping of # C++ QStyle instance takes ~5% unless the wrapper already exists. self.__style = style text = opt.text opt.text = "" style.drawControl(QStyle.CE_ItemViewItem, opt, painter, widget) trect = style.subElementRect(QStyle.SE_ItemViewItemText, opt, widget) opt.text = text self.drawViewItemText(style, painter, opt, trect)
def test_delegate(self): opt = QStyleOptionViewItem() index = self.model.index(0, 0) self.delegate.initStyleOption(opt, index) self.assertEqual(opt.text, "0x0") icon = QIcon(SvgIconEngine(b'<svg></svg>')) yellow = QColor(Qt.yellow) magenta = QColor(Qt.magenta) data = { Qt.DisplayRole: "AA", Qt.FontRole: QFont("Times New Roman"), Qt.TextAlignmentRole: Qt.AlignRight, Qt.CheckStateRole: Qt.Checked, Qt.DecorationRole: icon, Qt.ForegroundRole: yellow, Qt.BackgroundRole: magenta, } self.model.setItemData(index, data) self.delegate.initStyleOption(opt, index) self.assertEqual(opt.font.family(), QFont("Times New Roman").family()) self.assertEqual(opt.displayAlignment, Qt.AlignRight) self.assertEqual(opt.backgroundBrush.color(), magenta) self.assertEqual(opt.palette.text().color(), yellow) self.assertFalse(opt.icon.isNull()) self.assertEqual(opt.icon.cacheKey(), icon.cacheKey()) res = self.delegate.cachedData(index, Qt.DisplayRole) self.assertEqual(res, "AA") res = self.delegate.cachedItemData( index, (Qt.DisplayRole, Qt.TextAlignmentRole)) self.assertIn(Qt.DisplayRole, res) self.assertIn(Qt.TextAlignmentRole, res) self.assertEqual(res[Qt.TextAlignmentRole], Qt.AlignRight) self.assertEqual(res[Qt.DisplayRole], "AA")
def test_delegate(self): self.prepare_data() w = self.widget w.var_hints = self.var_hints # Def: Keep, x: EqFreq 3, y: Keep, z: Remove, t (time): Bin 2, u (time): self.send_signal(w.Inputs.data, self.data) model = w.varview.model() delegate: ListViewSearch.DiscDelegate = w.varview.itemDelegate() option = QStyleOptionViewItem() delegate.initStyleOption(option, model.index(0)) self.assertTrue(option.font.bold()) option = QStyleOptionViewItem() delegate.initStyleOption(option, model.index(4)) self.assertFalse(option.font.bold())
def sizeHint(self, option, index): options = QStyleOptionViewItem(option) self.initStyleOption(options, index) doc = QtGui.QTextDocument() doc.setHtml(options.text) doc.setTextWidth(options.rect.width()) return QtCore.QSize(doc.idealWidth(), doc.size().height())
def setUp(self): self.data = Table("iris") self.model = model = VariableItemModel() model.set_data(self.data) widget = OWCreateInstance() self.delegate = VariableDelegate(widget) self.parent = QWidget() self.opt = QStyleOptionViewItem()
def sizeHint(self, option, index): option = QStyleOptionViewItem(option) self.initStyleOption(option, index) size = QStyledItemDelegate.sizeHint(self, option, index) # TODO: get the default QMenu item height from the current style. size.setHeight(max(size.height(), 25)) return size
def paint( self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex ) -> None: opt = QStyleOptionViewItem(option) self.initStyleOption(opt, index) widget = option.widget style = QApplication.style() if widget is None else widget.style() self.__style = style text = opt.text opt.text = "" style.drawControl(QStyle.CE_ItemViewItem, opt, painter, widget) textrect = style.subElementRect( QStyle.SE_ItemViewItemText, opt, widget) ratio = self.barFillRatioData(index) if ratio is not None and 0. <= ratio <= 1.: color = self.barColorData(index) if color is None: color = self.color if not color.isValid(): color = opt.palette.color(QPalette.Foreground) rect = option.rect pw = self.penWidth hmargin = 3 + pw / 2 # + half pen width for the round line cap vmargin = 1 textoffset = pw + vmargin * 2 baseline = rect.bottom() - textoffset / 2 width = (rect.width() - 2 * hmargin) * ratio painter.save() painter.setRenderHint(QPainter.Antialiasing) pen = self.__pen pen.setColor(color) pen.setWidth(pw) painter.setPen(pen) line = self.__line left = rect.left() + hmargin line.setLine(left, baseline, left + width, baseline) painter.drawLine(line) painter.restore() textrect.adjust(0, 0, 0, -textoffset) opt.text = text self.drawViewItemText(style, painter, opt, textrect)
def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex): word_list = index.data(Qt.DisplayRole) if word_list.flags & WordList.Modified: option = QStyleOptionViewItem(option) option.palette.setColor(QPalette.Text, QColor(Qt.red)) option.palette.setColor(QPalette.Highlight, QColor(Qt.darkRed)) option.palette.setColor(QPalette.HighlightedText, QColor(Qt.white)) super().paint(painter, option, index)
def paint_with_data( delegate: QAbstractItemDelegate, data: Dict[int, Any], options: QStyleOptionViewItem = None ) -> None: model = create_model(1, 1) index = model.index(0, 0) model.setItemData(index, data) opt = QStyleOptionViewItem(options) if options is not None else QStyleOptionViewItem() size = delegate.sizeHint(opt, index).expandedTo(QSize(10, 10)) opt.rect = QRect(QPoint(0, 0), size) delegate.initStyleOption(opt, index) img = QImage(opt.rect.size(), QImage.Format_ARGB32_Premultiplied) p = QPainter(img) try: delegate.paint(p, opt, index) finally: p.end()
def sizeHint(self, option, index): # type: (QStyleOptionViewItem, QModelIndex) -> QSize option = QStyleOptionViewItem(option) self.initStyleOption(option, index) size = super().sizeHint(option, index) # TODO: get the default QMenu item height from the current style. size.setHeight(max(size.height(), 25)) return size
def sizeHint(self, option, index): options = QStyleOptionViewItem(option) gene_obj = index.data(Qt.DisplayRole) self.initStyleOption(options, index) doc = QTextDocument() doc.setHtml(gene_obj.to_html()) doc.setTextWidth(options.rect.width() - 10) return QSize(doc.idealWidth(), doc.size().height())
def sizeHint(self, option, index): # type: (QStyleOptionViewItem, QModelIndex) -> QSize opt = QStyleOptionViewItem(option) self.initStyleOption(option, index) opt.features |= QStyleOptionViewItem.HasDecoration widget = option.widget style = widget.style() if widget is not None else QApplication.style() sh = style.sizeFromContents( QStyle.CT_ItemViewItem, opt, QSize(), widget) return sh
def initStyleOption(self, option: QStyleOptionViewItem, index: QModelIndex) -> None: data = self.cachedItemData(index, self.roles) init_style_option(self, option, index, data, self.roles) if data.get(Qt.TextAlignmentRole) is None \ and Qt.TextAlignmentRole in self.roles \ and isinstance(data.get(Qt.DisplayRole), _TypesAlignRight): option.displayAlignment = \ (option.displayAlignment & ~Qt.AlignHorizontal_Mask) | \ Qt.AlignRight
def paintEvent(self, event): style = self.style() # type: QStyle painter = QPainter(self) option = QStyleOption() option.initFrom(self) style.drawPrimitive(QStyle.PE_Widget, option, painter, self) option = QStyleOptionViewItem() self.initStyleOption(option) style.drawControl(QStyle.CE_ItemViewItem, option, painter, self)
def test_qabstractitemview_view_options(self): view = QTableView() with warnings.catch_warnings(record=True): opt1 = view.viewOptions() self.assertIs(opt1.widget, view) self.assertTrue(opt1.showDecorationSelected) opt2 = QStyleOptionViewItem() view.initViewItemOption(opt2) self.assertIs(opt2.widget, view) self.assertTrue(opt2.showDecorationSelected)
def sizeHint(self): # type: () -> QSize """ Reimplemented. Provide sensible size hint based on the view's contents. """ flow = self.flow() if self.model() is None or not self.model().rowCount(): style = self.style() opt = self.viewOptions() opt.features = QStyleOptionViewItem.ViewItemFeature( opt.features | QStyleOptionViewItem.HasDecoration | QStyleOptionViewItem.HasDisplay | QStyleOptionViewItem.WrapText ) opt.text = "X" * 12 + "\nX" sh = style.sizeFromContents( QStyle.CT_ItemViewItem, opt, QSize(), self) else: # Sample the first 20 items for a size hint. The objective is to # get a representative height due to the word wrapping model = self.model() samplesize = min(20, model.rowCount()) shs = [self.sizeHintForIndex(model.index(i, 0)) for i in range(samplesize)] if flow == QListView.TopToBottom: sh = QSize(max(s.width() for s in shs), 200) else: sh = QSize(200, max(s.height() for s in shs)) margins = self.contentsMargins() if flow == QListView.TopToBottom: sh = sh + QSize(margins.left() + margins.right(), 0) else: sh = sh + QSize(0, margins.top() + margins.bottom()) if flow == QListView.TopToBottom and \ self.verticalScrollBarPolicy() != Qt.ScrollBarAlwaysOff: ssh = self.verticalScrollBar().sizeHint() return QSize(sh.width() + ssh.width(), sh.height()) elif self.flow() == QListView.LeftToRight and \ self.horizontalScrollBarPolicy() != Qt.ScrollBarAlwaysOff: ssh = self.horizontalScrollBar().sizeHint() return QSize(sh.width(), sh.height() + ssh.height()) else: return sh
def test_delegate(self): model = DistanceMatrixModel() matrix = np.array([[0.0, 0.1, 0.2], [0.1, 0.0, 0.1], [0.2, 0.1, 0.0]]) model.set_data(matrix) delegate = TableBorderItem() for row, col in product(range(model.rowCount()), range(model.columnCount())): index = model.index(row, col) option = QStyleOptionViewItem() size = delegate.sizeHint(option, index).expandedTo(QSize(30, 18)) delegate.initStyleOption(option, index) img = QImage(size, QImage.Format_ARGB32_Premultiplied) painter = QPainter(img) try: delegate.paint(painter, option, index) finally: painter.end()
def editorEvent(self, event, model, option, index): flags = model.flags(index) if not flags & Qt.ItemIsUserCheckable or \ not option.state & QStyle.State_Enabled or \ not flags & Qt.ItemIsEnabled: return False checkstate = model.data(index, Qt.CheckStateRole) if checkstate is None: return False widget = option.widget style = widget.style() if widget else QApplication.style() if event.type() in { QEvent.MouseButtonPress, QEvent.MouseButtonRelease, QEvent.MouseButtonDblClick }: pos = event.pos() opt = QStyleOptionViewItem(option) self.initStyleOption(opt, index) rect = style.subElementRect(QStyle.SE_ItemViewItemCheckIndicator, opt, widget) if event.button() != Qt.LeftButton or not rect.contains(pos): return False if event.type() in { QEvent.MouseButtonPress, QEvent.MouseButtonDblClick }: return True elif event.type() == QEvent.KeyPress: if event.key() != Qt.Key_Space and event.key() != Qt.Key_Select: return False else: return False if model.flags(index) & Qt.ItemIsTristate: checkstate = (checkstate + 1) % 3 else: checkstate = \ Qt.Unchecked if checkstate == Qt.Checked else Qt.Checked return model.setData(index, checkstate, Qt.CheckStateRole)
def editorEvent(self, event, model, option, index): # type: (QEvent, QAbstractItemModel, QStyleOptionViewItem, QModelIndex) -> bool """ Reimplemented. """ flags = model.flags(index) if not flags & Qt.ItemIsUserCheckable or \ not option.state & QStyle.State_Enabled or \ not flags & Qt.ItemIsEnabled: return False checkstate = model.data(index, Qt.CheckStateRole) if checkstate is None: return False widget = option.widget style = widget.style() if widget is not None else QApplication.style() if event.type() in { QEvent.MouseButtonPress, QEvent.MouseButtonRelease, QEvent.MouseButtonDblClick }: pos = event.pos() opt = QStyleOptionViewItem(option) self.initStyleOption(opt, index) rect = style.subElementRect(QStyle.SE_ItemViewItemCheckIndicator, opt, widget) if event.button() != Qt.LeftButton or not rect.contains(pos): return False if event.type() in { QEvent.MouseButtonPress, QEvent.MouseButtonDblClick }: return True elif event.type() == QEvent.KeyPress: if event.key() != Qt.Key_Space and event.key() != Qt.Key_Select: return False else: return False checkstate = self.nextCheckState(checkstate, index) return model.setData(index, checkstate, Qt.CheckStateRole)
def test_delegate(self): cases = ( (DState(Default(Leave()), None, None), ""), (DState(Leave(), None, None), "(leave)"), (DState(MDL(), [1], None), "(entropy)"), (DState(MDL(), [], None), "<removed>"), (DState(EqualFreq(2), [1], None), "(equal frequency k=2)"), (DState(EqualWidth(2), [1], None), "(equal width k=2)"), (DState(Remove(), None, None), "(removed)"), (DState(Custom([1]), None, None), "(custom)"), ) delegate = DiscDelegate() var = DiscreteVariable("C", ("a", "b")) model = VariableListModel() model.append(var) for state, text in cases: model.setData(model.index(0), state, Qt.UserRole) option = QStyleOptionViewItem() delegate.initStyleOption(option, model.index(0)) self.assertIn(text, option.text)
def init_style_option( delegate: QStyledItemDelegate, option: QStyleOptionViewItem, index: QModelIndex, data: Mapping[int, Any], roles: Optional[Container[int]] = None, ) -> None: """ Like `QStyledItemDelegate.initStyleOption` but fill in the fields from `data` mapping. If `roles` is not `None` init the `option` for the specified `roles` only. """ # pylint: disable=too-many-branches option.styleObject = None option.index = index if roles is None: roles = data features = 0 if Qt.DisplayRole in roles: value = data.get(Qt.DisplayRole) if value is not None: option.text = delegate.displayText(value, option.locale) features |= _QStyleOptionViewItem_HasDisplay if Qt.FontRole in roles: value = data.get(Qt.FontRole) font = cast_(QFont, value) if font is not None: font = font.resolve(option.font) option.font = font option.fontMetrics = QFontMetrics(option.font) if Qt.ForegroundRole in roles: value = data.get(Qt.ForegroundRole) foreground = cast_(QBrush, value) if foreground is not None: option.palette.setBrush(QPalette.Text, foreground) if Qt.BackgroundRole in roles: value = data.get(Qt.BackgroundRole) background = cast_(QBrush, value) if background is not None: option.backgroundBrush = background if Qt.TextAlignmentRole in roles: value = data.get(Qt.TextAlignmentRole) alignment = cast_(int, value) if alignment is not None: alignment = alignment & _AlignmentMask option.displayAlignment = _AlignmentCache[alignment] if Qt.CheckStateRole in roles: state = data.get(Qt.CheckStateRole) if state is not None: features |= _QStyleOptionViewItem_HasCheckIndicator state = cast_(int, state) if state is not None: option.checkState = state if Qt.DecorationRole in roles: value = data.get(Qt.DecorationRole) if value is not None: features |= _QStyleOptionViewItem_HasDecoration if isinstance(value, QIcon): option.icon = value elif isinstance(value, QColor): pix = QPixmap(option.decorationSize) pix.fill(value) option.icon = QIcon(pix) elif isinstance(value, QPixmap): option.icon = QIcon(value) option.decorationSize = (value.size() / value.devicePixelRatio()).toSize() elif isinstance(value, QImage): pix = QPixmap.fromImage(value) option.icon = QIcon(value) option.decorationSize = (pix.size() / pix.devicePixelRatio()).toSize() option.features |= features
def get_style_option() -> QStyleOptionViewItem: opt = QStyleOptionViewItem() delegate.initStyleOption(opt, model.index(0)) return opt