def drawViewItemText(self, style: QStyle, painter: QPainter, option: QStyleOptionViewItem, rect: QRect) -> None: """ Draw view item text in `rect` using `style` and `painter`. """ margin = style.pixelMetric(QStyle.PM_FocusFrameHMargin, None, option.widget) + 1 rect = rect.adjusted(margin, 0, -margin, 0) font = option.font st = self.__static_text_elided_cache(option.text, font, option.fontMetrics, option.textElideMode, rect.width()) tsize = st.size() textalign = int(option.displayAlignment) text_pos_x = text_pos_y = 0.0 if textalign & _Qt_AlignLeft: text_pos_x = rect.left() elif textalign & _Qt_AlignRight: text_pos_x = rect.x() + rect.width() - tsize.width() elif textalign & _Qt_AlignHCenter: text_pos_x = rect.x() + rect.width() / 2 - tsize.width() / 2 if textalign & _Qt_AlignVCenter: text_pos_y = rect.y() + rect.height() / 2 - tsize.height() / 2 elif textalign & _Qt_AlignTop: text_pos_y = rect.top() elif textalign & _Qt_AlignBottom: text_pos_y = rect.top() + rect.height() - tsize.height() painter.setPen(self.__pen_cache(option.palette, option.state)) painter.setFont(font) painter.drawStaticText(QPointF(text_pos_x, text_pos_y), st)
def paint(self, painter, option, index): rect = QRect(option.rect) is_selected = index.data(VariableSelectionModel.IsSelected) full_selection = index.model().sourceModel().is_full() if option.state & QStyle.State_MouseOver: if not full_selection or (full_selection and is_selected): txt = [" 添加 ", " 删除 "][is_selected] txtw = painter.fontMetrics().horizontalAdvance(txt) painter.save() painter.setPen(Qt.NoPen) painter.setBrush(option.palette.brush(QPalette.Button)) brect = QRect( rect.x() + rect.width() - 8 - txtw, rect.y(), txtw, rect.height() ) painter.drawRoundedRect(brect, 4, 4) painter.setPen(option.palette.color(QPalette.ButtonText)) painter.drawText(brect, Qt.AlignCenter, txt) painter.restore() painter.save() double_pen = painter.pen() double_pen.setWidth(2 * double_pen.width()) if is_selected: next = index.sibling(index.row() + 1, index.column()) if not next.isValid(): painter.setPen(double_pen) painter.drawLine(rect.bottomLeft(), rect.bottomRight()) elif not next.data(VariableSelectionModel.IsSelected): painter.drawLine(rect.bottomLeft(), rect.bottomRight()) elif not index.row(): down = QPoint(0, painter.pen().width()) painter.setPen(double_pen) painter.drawLine(rect.topLeft() + down, rect.topRight() + down) else: prev = index.sibling(index.row() - 1, index.column()) if prev.data(VariableSelectionModel.IsSelected): painter.drawLine(rect.topLeft(), rect.topRight()) painter.restore() super().paint(painter, option, index)
def paint(self, painter, option, index): rect = QRect(option.rect) is_selected = index.data(VariableSelectionModel.IsSelected) if option.state & QStyle.State_MouseOver: txt = [" Add ", " Remove "][is_selected] txtw = painter.fontMetrics().width(txt) painter.save() painter.setPen(Qt.NoPen) painter.setBrush(QColor("#ccc")) brect = QRect(rect.x() + rect.width() - 8 - txtw, rect.y(), txtw, rect.height()) painter.drawRoundedRect(brect, 4, 4) painter.restore() painter.drawText(brect, Qt.AlignCenter, txt) painter.save() double_pen = painter.pen() double_pen.setWidth(2 * double_pen.width()) if is_selected: next = index.sibling(index.row() + 1, index.column()) if not next.isValid(): painter.setPen(double_pen) painter.drawLine(rect.bottomLeft(), rect.bottomRight()) elif not next.data(VariableSelectionModel.IsSelected): painter.drawLine(rect.bottomLeft(), rect.bottomRight()) elif not index.row(): down = QPoint(0, painter.pen().width()) painter.setPen(double_pen) painter.drawLine(rect.topLeft() + down, rect.topRight() + down) else: prev = index.sibling(index.row() - 1, index.column()) if prev.data(VariableSelectionModel.IsSelected): painter.drawLine(rect.topLeft(), rect.topRight()) painter.restore() super().paint(painter, option, index)
def __paintEventNoStyle(self): p = QPainter(self) opt = QStyleOptionToolButton() self.initStyleOption(opt) fm = QFontMetrics(opt.font) palette = opt.palette # highlight brush is used as the background for the icon and background # when the tab is expanded and as mouse hover color (lighter). brush_highlight = palette.highlight() if opt.state & QStyle.State_Sunken: # State 'down' pressed during a mouse press (slightly darker). background_brush = brush_darker(brush_highlight, 110) elif opt.state & QStyle.State_MouseOver: background_brush = brush_darker(brush_highlight, 95) elif opt.state & QStyle.State_On: background_brush = brush_highlight else: # The default button brush. background_brush = palette.button() rect = opt.rect icon_area_rect = QRect(rect) icon_area_rect.setRight(int(icon_area_rect.height() * 1.26)) text_rect = QRect(rect) text_rect.setLeft(icon_area_rect.right() + 10) # Background (TODO: Should the tab button have native # toolbutton shape, drawn using PE_PanelButtonTool or even # QToolBox tab shape) # Default outline pen pen = QPen(palette.color(QPalette.Mid)) p.save() p.setPen(Qt.NoPen) p.setBrush(QBrush(background_brush)) p.drawRect(rect) # Draw the background behind the icon if the background_brush # is different. if not opt.state & QStyle.State_On: p.setBrush(brush_highlight) p.drawRect(icon_area_rect) # Line between the icon and text p.setPen(pen) p.drawLine(icon_area_rect.topRight(), icon_area_rect.bottomRight()) if opt.state & QStyle.State_HasFocus: # Set the focus frame pen and draw the border pen = QPen(QColor(FOCUS_OUTLINE_COLOR)) p.setPen(pen) p.setBrush(Qt.NoBrush) # Adjust for pen rect = rect.adjusted(0, 0, -1, -1) p.drawRect(rect) else: p.setPen(pen) # Draw the top/bottom border if self.position == QStyleOptionToolBox.OnlyOneTab or \ self.position == QStyleOptionToolBox.Beginning or \ self.selected & \ QStyleOptionToolBox.PreviousIsSelected: p.drawLine(rect.topLeft(), rect.topRight()) p.drawLine(rect.bottomLeft(), rect.bottomRight()) p.restore() p.save() text = fm.elidedText(opt.text, Qt.ElideRight, text_rect.width()) p.setPen(QPen(palette.color(QPalette.ButtonText))) p.setFont(opt.font) p.drawText(text_rect, int(Qt.AlignVCenter | Qt.AlignLeft) | \ int(Qt.TextSingleLine), text) if not opt.icon.isNull(): if opt.state & QStyle.State_Enabled: mode = QIcon.Normal else: mode = QIcon.Disabled if opt.state & QStyle.State_On: state = QIcon.On else: state = QIcon.Off icon_area_rect = icon_area_rect icon_rect = QRect(QPoint(0, 0), opt.iconSize) icon_rect.moveCenter(icon_area_rect.center()) opt.icon.paint(p, icon_rect, Qt.AlignCenter, mode, state) p.restore()
def showPopup(self): # type: () -> None """ Reimplemented from QComboBox.showPopup Popup up a customized view and filter edit line. Note ---- The .popup(), .lineEdit(), .completer() of the base class are not used. """ if self.__popup is not None: # We have user entered state that cannot be disturbed # (entered filter text, scroll offset, ...) return # pragma: no cover if self.count() == 0: return opt = QStyleOptionComboBox() self.initStyleOption(opt) popup = QListView( uniformItemSizes=True, horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff, verticalScrollBarPolicy=Qt.ScrollBarAsNeeded, iconSize=self.iconSize(), ) popup.setFocusProxy(self.__searchline) popup.setParent(self, Qt.Popup | Qt.FramelessWindowHint) popup.setItemDelegate(_ComboBoxListDelegate(popup)) proxy = QSortFilterProxyModel( popup, filterCaseSensitivity=Qt.CaseInsensitive ) proxy.setFilterKeyColumn(self.modelColumn()) proxy.setSourceModel(self.model()) popup.setModel(proxy) root = proxy.mapFromSource(self.rootModelIndex()) popup.setRootIndex(root) self.__popup = popup self.__proxy = proxy self.__searchline.setText("") self.__searchline.setPlaceholderText("Filter...") self.__searchline.setVisible(True) self.__searchline.textEdited.connect(proxy.setFilterFixedString) style = self.style() # type: QStyle popuprect_origin = style.subControlRect( QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxListBoxPopup, self ) # type: QRect popuprect_origin = QRect( self.mapToGlobal(popuprect_origin.topLeft()), popuprect_origin.size() ) editrect = style.subControlRect( QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxEditField, self ) # type: QRect self.__searchline.setGeometry(editrect) desktop = QApplication.desktop() screenrect = desktop.availableGeometry(self) # type: QRect # get the height for the view listrect = QRect() for i in range(min(proxy.rowCount(root), self.maxVisibleItems())): index = proxy.index(i, self.modelColumn(), root) if index.isValid(): listrect = listrect.united(popup.visualRect(index)) if listrect.height() >= screenrect.height(): break window = popup.window() # type: QWidget window.ensurePolished() if window.layout() is not None: window.layout().activate() else: QApplication.sendEvent(window, QEvent(QEvent.LayoutRequest)) margins = qwidget_margin_within(popup.viewport(), window) height = (listrect.height() + 2 * popup.spacing() + margins.top() + margins.bottom()) popup_size = (QSize(popuprect_origin.width(), height) .expandedTo(window.minimumSize()) .boundedTo(window.maximumSize()) .boundedTo(screenrect.size())) popuprect = QRect(popuprect_origin.bottomLeft(), popup_size) popuprect = dropdown_popup_geometry( popuprect, popuprect_origin, screenrect) popup.setGeometry(popuprect) current = proxy.mapFromSource( self.model().index(self.currentIndex(), self.modelColumn(), self.rootModelIndex())) popup.setCurrentIndex(current) popup.scrollTo(current, QAbstractItemView.EnsureVisible) popup.show() popup.setFocus(Qt.PopupFocusReason) popup.installEventFilter(self) popup.viewport().installEventFilter(self) popup.viewport().setMouseTracking(True) self.update() self.__popupTimer.restart()
class MapMixin: """ This mixin provides maps for `OWScatterPlotBase` based visualizations. It expects an `OWScatterPlotBase` like object that must have: * `plot_widget` attribute of type pg.PlotWidget * `view_box` attribute of type MapViewBox * `master` attribute of type OWWidget """ show_internet_error = Signal(bool) def __init__(self): self.tile_provider = TILE_PROVIDERS[DEFAULT_TILE_PROVIDER] self.tile_attribution = AttributionItem( parent=self.plot_widget.getViewBox()) self.tile_attribution.setHtml(self.tile_provider.attribution) self.mem_cache = {} self.map = None # type: Optional[Image.Image] # we use a background map so transitions between zoom levels looks nicer self.b_map_item = None self.map_item = None self.__new_map_items() self.ts = QRect(0, 0, 1, 1) self.ts_norm = QRect(0, 0, 1, 1) self.tz = 1 self.zoom_changed = False self.loader = ImageLoader(self) self.futures = [] self.view_box.setAspectLocked(lock=True, ratio=1) self.view_box.sigRangeChangedManually.connect(self.update_map) self.view_box.set_tile_provider(self.tile_provider) def _create_legend(self, anchor, brush=QBrush(QColor(232, 232, 232, 200))): # by default the legend transparency was to high for colorful maps legend = LegendItem(brush=brush) legend.setParentItem(self.plot_widget.getViewBox()) legend.restoreAnchor(anchor) return legend @staticmethod def __new_map_item(z): map_item = ImageItem(autoLevels=False) map_item.setOpts(axisOrder='row-major') map_item.setZValue(z) return map_item def __new_map_items(self): if self.b_map_item is not None: self.plot_widget.removeItem(self.b_map_item) self.b_map_item = self.__new_map_item(-3) self.plot_widget.addItem(self.b_map_item) if self.map_item is not None: self.plot_widget.removeItem(self.map_item) self.map_item = self.__new_map_item(-2) self.plot_widget.addItem(self.map_item) def _update_view_range(self, min_x, max_x, min_y, max_y, keep_zoom=False): if not keep_zoom: self.view_box.recalculate_zoom(max_x - min_x, max_y - min_y) center = Point(min_x + (max_x - min_x) / 2, min_y + (max_y - min_y) / 2) self.view_box.match_zoom(center) def update_map(self): """Get current view box to calculate which tiles to draw.""" [min_x, max_x], [min_y, max_y] = self.view_box.viewRange() new_zoom = self.view_box.get_zoom() self.zoom_changed = self.tz != new_zoom self.tz = new_zoom # flip y to calculate edge tiles tile_min_x, tile_max_y = norm2tile(min_x, 1 - min_y, self.tz) tile_max_x, tile_min_y = norm2tile(max_x, 1 - max_y, self.tz) # round them to get edge tiles x, y tile_min_x = max(int(np.floor(tile_min_x)), 0) tile_min_y = max(int(np.floor(tile_min_y)), 0) tile_max_x = min(int(np.ceil(tile_max_x)), 2 ** self.tz) tile_max_y = min(int(np.ceil(tile_max_y)), 2 ** self.tz) self.ts = QRect(tile_min_x, tile_min_y, tile_max_x - tile_min_x, tile_max_y - tile_min_y) # transform rounded tile coordinates back min_edge_x, min_edge_y = tile2norm(tile_min_x, tile_min_y, self.tz) max_edge_x, max_edge_y = tile2norm(tile_max_x, tile_max_y, self.tz) # flip y back to transform map min_edge_y, max_edge_y = 1 - min_edge_y, 1 - max_edge_y # rectangle where to put the map into self.ts_norm = QRectF(min_edge_x, min_edge_y, max_edge_x - min_edge_x, max_edge_y - min_edge_y) self._map_z_shift() self._load_new_map() def _map_z_shift(self): """If zoom changes move current map to background and draw new over it""" if self.zoom_changed: self.plot_widget.removeItem(self.b_map_item) self.b_map_item = self.map_item self.b_map_item.setZValue(-3) self.map_item = self.__new_map_item(-2) self.plot_widget.addItem(self.map_item) def _load_new_map(self): """Prepare tiles that are needed in new view.""" in_mem = [] to_download = [] for x in range(self.ts.width()): for y in range(self.ts.height()): tile = _TileItem(x=self.ts.x() + x, y=self.ts.y() + y, z=self.tz, tile_provider=self.tile_provider) if tile in self.mem_cache: in_mem.append(tile) else: to_download.append(tile) self._load_from_mem(in_mem) self._load_from_net(to_download) def _load_from_mem(self, tiles: List[_TileItem]): """Create new image object to draw tiles onto it. Tiles that are stored in memory are drawn immediately.""" self.map = Image.new('RGBA', (self.ts.width() * self.tile_provider.size, self.ts.height() * self.tile_provider.size), color="#ffffff00") for t in tiles: self._add_patch(t) self._update_map_item() def _add_patch(self, t): """Add tile to full image.""" px = (t.x - self.ts.x()) * self.tile_provider.size py = (t.y - self.ts.y()) * self.tile_provider.size self.map.paste(self.mem_cache[t], (px, py)) def _update_map_item(self): """Update ImageItem with current image.""" self.map_item.setImage(np.array(self.map)) self.map_item.setRect(self.ts_norm) def _load_from_net(self, tiles: List[_TileItem]): """Tiles that are not in memory are downloaded concurrently and are added to the main image dynamically.""" if self.zoom_changed: self._cancel_futures() self.futures = [] for t in tiles: self._load_one_from_net(t) def _load_one_from_net(self, t: _TileItem): """ Download a tile from the internet. For a tile if we already tried to download it three times then show no internet error. If we managed to get a tile from the internet clear no internet warning """ if t.n_loadings == 3: print(t) self.show_internet_error.emit(True) return future = self.loader.get(t) @future.add_done_callback def set_tile(_future): if _future.cancelled(): return assert _future.done() _tile = _future._tile if _future.exception(): _tile.n_loadings += 1 # retry to download image self._load_one_from_net(_tile) else: img = _future.result() # Added by Jean 2020/05/30 for support of tianditu.gov.cn # Download tianditu.gov.cn text marker for the same tile and merge it to the map tile # from contextily.tile import _fetch_tile # def _load_one_from_net(self, t: _TileItem): # def set_tile(_future): # ...... if "tianditu" in _tile.url: url = _tile.url print(url) getMarker = False if "vec_w" in url: url = url.replace("vec_w","cva_w") getMarker = True elif "img_w" in url: url = url.replace("img_w","cia_w") getMarker = True elif "ter_w" in url: url = url.replace("ter_w","cta_w") getMarker = True if getMarker: # Dowload the corresponding marker tile image = Image.fromarray( _fetch_tile(url, 0, 3), 'RGBA') # Merge the marker tile to the corresponding map tile r, g, b, alpha = image.split() img = img.convert("RGBA") img = Image.composite(image, img, alpha) print(url) if not _tile.disc_cache: self.show_internet_error.emit(False) self.mem_cache[_tile] = img self._add_patch(_tile) self._update_map_item() self.futures.remove(_future) self.futures.append(future) def _cancel_futures(self): for future in self.futures: future.cancel() if future._reply is not None: future._reply.close() future._reply.deleteLater() future._reply = None def _update_tile_provider(self, tp): self.clear_map() self.tile_provider = tp self.view_box.set_tile_provider(self.tile_provider) self.tile_attribution.setHtml(self.tile_provider.attribution) self.update_map() def clear_map(self): self._cancel_futures() self.futures = [] self.map = None self.tz = 1 self.__new_map_items()
def __layout(self): # position itself over `widget` # pylint: disable=too-many-branches widget = self.__widget if widget is None: return alignment = self.__alignment policy = self.sizePolicy() if widget.window() is self.window() and not self.isWindow(): if widget.isWindow(): bounds = widget.rect() else: bounds = QRect(widget.mapTo(widget.window(), QPoint(0, 0)), widget.size()) tl = self.parent().mapFrom(widget.window(), bounds.topLeft()) bounds = QRect(tl, widget.size()) else: if widget.isWindow(): bounds = widget.geometry() else: bounds = QRect(widget.mapToGlobal(QPoint(0, 0)), widget.size()) if self.isWindow(): bounds = bounds else: bounds = QRect(self.parent().mapFromGlobal(bounds.topLeft()), bounds.size()) sh = self.sizeHint() minsh = self.minimumSizeHint() minsize = self.minimumSize() if minsize.isNull(): minsize = minsh maxsize = bounds.size().boundedTo(self.maximumSize()) minsize = minsize.boundedTo(maxsize) effectivesh = sh.expandedTo(minsize).boundedTo(maxsize) hpolicy = policy.horizontalPolicy() vpolicy = policy.verticalPolicy() if not effectivesh.isValid(): effectivesh = QSize(0, 0) vpolicy = hpolicy = QSizePolicy.Ignored def getsize(hint, minimum, maximum, policy): if policy == QSizePolicy.Ignored: return maximum elif policy & QSizePolicy.ExpandFlag: return maximum else: return max(hint, minimum) width = getsize(effectivesh.width(), minsize.width(), maxsize.width(), hpolicy) heightforw = self.heightForWidth(width) if heightforw > 0: height = getsize(heightforw, minsize.height(), maxsize.height(), vpolicy) else: height = getsize(effectivesh.height(), minsize.height(), maxsize.height(), vpolicy) size = QSize(width, height) if alignment & Qt.AlignLeft: x = bounds.x() elif alignment & Qt.AlignRight: x = bounds.x() + bounds.width() - size.width() else: x = bounds.x() + max(0, bounds.width() - size.width()) // 2 if alignment & Qt.AlignTop: y = bounds.y() elif alignment & Qt.AlignBottom: y = bounds.y() + bounds.height() - size.height() else: y = bounds.y() + max(0, bounds.height() - size.height()) // 2 geom = QRect(QPoint(x, y), size) self.setGeometry(geom)
def __layout(self): # position itself over `widget` widget = self.__widget if widget is None: return alignment = self.__alignment policy = self.sizePolicy() if widget.isWindow(): bounds = widget.geometry() else: bounds = QRect(widget.mapToGlobal(QPoint(0, 0)), widget.size()) if self.isWindow(): bounds = bounds else: bounds = QRect(self.parent().mapFromGlobal(bounds.topLeft()), bounds.size()) sh = self.sizeHint() minsh = self.minimumSizeHint() minsize = self.minimumSize() if minsize.isNull(): minsize = minsh maxsize = bounds.size().boundedTo(self.maximumSize()) minsize = minsize.boundedTo(maxsize) effectivesh = sh.expandedTo(minsize).boundedTo(maxsize) hpolicy = policy.horizontalPolicy() vpolicy = policy.verticalPolicy() def getsize(hint, minimum, maximum, policy): if policy == QSizePolicy.Ignored: return maximum elif policy & QSizePolicy.ExpandFlag: return maximum else: return max(hint, minimum) width = getsize(effectivesh.width(), minsize.width(), maxsize.width(), hpolicy) heightforw = self.heightForWidth(width) if heightforw > 0: height = getsize(heightforw, minsize.height(), maxsize.height(), vpolicy) else: height = getsize(effectivesh.height(), minsize.height(), maxsize.height(), vpolicy) size = QSize(width, height) if alignment & Qt.AlignLeft: x = bounds.x() elif alignment & Qt.AlignRight: x = bounds.right() - size.width() else: x = bounds.x() + max(0, bounds.width() - size.width()) // 2 if alignment & Qt.AlignTop: y = bounds.y() elif alignment & Qt.AlignBottom: y = bounds.bottom() - size.height() else: y = bounds.y() + max(0, bounds.height() - size.height()) // 2 geom = QRect(QPoint(x, y), size) self.setGeometry(geom)
def __paintEventNoStyle(self): p = QPainter(self) opt = QStyleOptionToolButton() self.initStyleOption(opt) fm = QFontMetrics(opt.font) palette = opt.palette # highlight brush is used as the background for the icon and background # when the tab is expanded and as mouse hover color (lighter). brush_highlight = palette.highlight() foregroundrole = QPalette.ButtonText if opt.state & QStyle.State_Sunken: # State 'down' pressed during a mouse press (slightly darker). background_brush = brush_darker(brush_highlight, 110) foregroundrole = QPalette.HighlightedText elif opt.state & QStyle.State_MouseOver: background_brush = brush_darker(brush_highlight, 95) foregroundrole = QPalette.HighlightedText elif opt.state & QStyle.State_On: background_brush = brush_highlight foregroundrole = QPalette.HighlightedText else: # The default button brush. background_brush = palette.button() rect = opt.rect icon_area_rect = QRect(rect) icon_area_rect.setRight(int(icon_area_rect.height() * 1.26)) text_rect = QRect(rect) text_rect.setLeft(icon_area_rect.right() + 10) # Background (TODO: Should the tab button have native # toolbutton shape, drawn using PE_PanelButtonTool or even # QToolBox tab shape) # Default outline pen pen = QPen(palette.color(QPalette.Mid)) p.save() p.setPen(Qt.NoPen) p.setBrush(QBrush(background_brush)) p.drawRect(rect) # Draw the background behind the icon if the background_brush # is different. if not opt.state & QStyle.State_On: p.setBrush(brush_highlight) p.drawRect(icon_area_rect) # Line between the icon and text p.setPen(pen) p.drawLine(icon_area_rect.topRight(), icon_area_rect.bottomRight()) if opt.state & QStyle.State_HasFocus: # Set the focus frame pen and draw the border pen = QPen(QColor(FOCUS_OUTLINE_COLOR)) p.setPen(pen) p.setBrush(Qt.NoBrush) # Adjust for pen rect = rect.adjusted(0, 0, -1, -1) p.drawRect(rect) else: p.setPen(pen) # Draw the top/bottom border if self.position == QStyleOptionToolBox.OnlyOneTab or \ self.position == QStyleOptionToolBox.Beginning or \ self.selected & \ QStyleOptionToolBox.PreviousIsSelected: p.drawLine(rect.topLeft(), rect.topRight()) p.drawLine(rect.bottomLeft(), rect.bottomRight()) p.restore() p.save() text = fm.elidedText(opt.text, Qt.ElideRight, text_rect.width()) p.setPen(QPen(palette.color(foregroundrole))) p.setFont(opt.font) p.drawText(text_rect, int(Qt.AlignVCenter | Qt.AlignLeft) | \ int(Qt.TextSingleLine), text) if not opt.icon.isNull(): if opt.state & QStyle.State_Enabled: mode = QIcon.Normal else: mode = QIcon.Disabled if opt.state & QStyle.State_On: state = QIcon.On else: state = QIcon.Off icon_area_rect = icon_area_rect icon_rect = QRect(QPoint(0, 0), opt.iconSize) icon_rect.moveCenter(icon_area_rect.center()) opt.icon.paint(p, icon_rect, Qt.AlignCenter, mode, state) p.restore()