class MovingMessage(FadeMessage): def __init__(self, message, str = None, pos = None): cfg = Config('messages', message) if (pos is None): self.pos = QPoint(*cfg.get('position')) else: self.pos = QPoint(*pos) self.velocity = cfg.get('velocity') FadeMessage.__init__(self, message, str) def with_controller(self): self.rect = QRect(0, 0, self.controller.width(), self.controller.height()) self.rect.moveCenter(self.pos) def tick(self, elapsed): FadeMessage.tick(self, elapsed) self.pos.setX(self.pos.x() + self.velocity[0] * elapsed) self.pos.setY(self.pos.y() + self.velocity[1] * elapsed) self.rect.moveCenter(self.pos) def draw(self): FadeMessage.draw(self) if (self.color.alpha() == 0): self.rect = self.bounding_text_rect
def paintEvent(self, ev): """Called when paint is needed, finds out which page to magnify.""" layout = self.parent().surface().pageLayout() pos = self.geometry().center() - self.parent().surface().pos() page = layout.pageAt(pos) if not page: return pagePos = pos - page.pos() newPage = Page(page, self._scale) if not newPage.same_page(self._page): if self._page: self._page.magnifier = None self._page = newPage self._page.magnifier = self relx = pagePos.x() / float(page.width()) rely = pagePos.y() / float(page.height()) image = cache.image(self._page) img_rect = QRect(self.rect()) if not image: cache.generate(self._page) image = cache.image(self._page, False) if image: img_rect.setWidth(self.width() * image.width() / self._page.width()) img_rect.setHeight(self.height() * image.height() / self._page.height()) if image: img_rect.moveCenter(QPoint(relx * image.width(), rely * image.height())) p = QPainter(self) p.drawImage(self.rect(), image, img_rect) p.setRenderHint(QPainter.Antialiasing, True) p.setPen(QPen(QColor(192, 192, 192, 128), 6)) p.drawEllipse(self.rect().adjusted(2, 2, -2, -2))
def paintVerticalCell(self, painter: QPainter, hv: QHeaderView, cellIndex: QModelIndex, leafIndex: QModelIndex, logicalLeafIndex: int, styleOptions: QStyleOptionHeader, sectionRect: QRect, left: int): uniopt = QStyleOptionHeader(styleOptions) self.setForegroundBrush(uniopt, cellIndex) self.setBackgroundBrush(uniopt, cellIndex) width = self.cellSize(cellIndex, hv, uniopt).width() if cellIndex == leafIndex: width = sectionRect.width() - left top = self.currentCellLeft(cellIndex, leafIndex, logicalLeafIndex, sectionRect.top(), hv) height = self.currentCellWidth(cellIndex, leafIndex, logicalLeafIndex, hv) r = QRect(left, top, width, height) uniopt.text = cellIndex.data(Qt.DisplayRole) painter.save() uniopt.rect = r if cellIndex.data(Qt.UserRole): hv.style().drawControl(QStyle.CE_HeaderSection, uniopt, painter, hv) m = QMatrix() m.rotate(-90) painter.setWorldMatrix(m, True) new_r = QRect(0, 0, r.height(), r.width()) new_r.moveCenter(QPoint(-r.center().y(), r.center().x())) uniopt.rect = new_r hv.style().drawControl(QStyle.CE_HeaderLabel, uniopt, painter, hv) else: hv.style().drawControl(QStyle.CE_Header, uniopt, painter, hv) painter.restore() return left + width
def paintEvent(self, ev): """Called when paint is needed, finds out which page to magnify.""" layout = self.parent().pageLayout() pos = self.geometry().center() page = layout.pageAt(pos) if not page: return pagePos = pos - page.pos() newPage = Page(page, self._scale) if newPage != self._page: if self._page: self._page.magnifier = None self._page = newPage self._page.magnifier = self relx = pagePos.x() / float(page.width()) rely = pagePos.y() / float(page.height()) image = cache.image(self._page) img_rect = QRect(self.rect()) if not image: cache.generate(self._page) image = cache.image(self._page, False) if image: img_rect.setWidth(self.width() * image.width() / self._page.width()) img_rect.setHeight(self.height() * image.height() / self._page.height()) if image: img_rect.moveCenter(QPoint(relx * image.width(), rely * image.height())) QPainter(self).drawImage(self.rect(), image, img_rect)
class MovingMessage(FadeMessage): def __init__(self, message, str=None, pos=None): cfg = Config('messages', message) if (pos is None): self.pos = QPoint(*cfg.get('position')) else: self.pos = QPoint(*pos) self.velocity = cfg.get('velocity') FadeMessage.__init__(self, message, str) def with_controller(self): self.rect = QRect(0, 0, self.controller.width(), self.controller.height()) self.rect.moveCenter(self.pos) def tick(self, elapsed): FadeMessage.tick(self, elapsed) self.pos.setX(self.pos.x() + self.velocity[0] * elapsed) self.pos.setY(self.pos.y() + self.velocity[1] * elapsed) self.rect.moveCenter(self.pos) def draw(self): FadeMessage.draw(self) if (self.color.alpha() == 0): self.rect = self.bounding_text_rect
def decorate_welcome_icon(icon, background_color): """Return a `QIcon` with a circle shaped background. """ welcome_icon = QIcon() sizes = [32, 48, 64, 80] background_color = NAMED_COLORS.get(background_color, background_color) background_color = QColor(background_color) grad = radial_gradient(background_color) for size in sizes: icon_pixmap = icon.pixmap(5 * size / 8, 5 * size / 8) icon_size = icon_pixmap.size() icon_rect = QRect(QPoint(0, 0), icon_size) pixmap = QPixmap(size, size) pixmap.fill(QColor(0, 0, 0, 0)) p = QPainter(pixmap) p.setRenderHint(QPainter.Antialiasing, True) p.setBrush(QBrush(grad)) p.setPen(Qt.NoPen) ellipse_rect = QRect(0, 0, size, size) p.drawEllipse(ellipse_rect) icon_rect.moveCenter(ellipse_rect.center()) p.drawPixmap(icon_rect.topLeft(), icon_pixmap) p.end() welcome_icon.addPixmap(pixmap) return welcome_icon
def paintEvent(self, ev): """Called when paint is needed, finds out which page to magnify.""" layout = self.parent().pageLayout() pos = self.geometry().center() page = layout.pageAt(pos) if not page: return pagePos = pos - page.pos() newPage = Page(page, self._scale) if newPage != self._page: if self._page: self._page.magnifier = None self._page = newPage self._page.magnifier = self relx = pagePos.x() / float(page.width()) rely = pagePos.y() / float(page.height()) image = cache.image(self._page) img_rect = QRect(self.rect()) if not image: cache.generate(self._page) image = cache.image(self._page, False) if image: img_rect.setWidth(self.width() * image.width() / self._page.width()) img_rect.setHeight(self.height() * image.height() / self._page.height()) if image: img_rect.moveCenter( QPoint(relx * image.width(), rely * image.height())) QPainter(self).drawImage(self.rect(), image, img_rect)
def read_state(load=True): home = os.path.expanduser('~') r = QRect(0, 0, 640, 480) r.moveCenter(QApplication.desktop().availableGeometry().center()) geometry = [r.x(), r.y(), r.width(), r.height()] state = dict(last_file_parent=home, last_dir_parent=home, last_save=home, geometry=geometry, zoom_factor=1.0, history=[], history_current=-1, scroll_values={}) try: if load and os.path.exists(state_file): f = gzip.open(state_file, 'rb') try: loaded = json.load(f) state.update(loaded) finally: f.close() except: show_error(_('Failed to load saved application state')) return state
def paint(self, painter): opacity = 1.0 - float(self.anim.currentTime()) / self.anim.duration() pen = QPen(QColor(255, 0, 0, opacity * 255)) pen.setWidth(3) painter.setPen(pen) painter.setBrush(Qt.transparent) rect = QRect(0, 0, self.radius * 2, self.radius * 2) rect.moveCenter(self.center) painter.drawEllipse(rect)
def paintEvent(self, ev): image = self.viewer.image() painter = QPainter(self) if self.size() == image.size(): painter.drawImage(ev.rect(), image, ev.rect()) else: s = image.size() s.scale(self.size(), Qt.KeepAspectRatio) r = QRect() r.setSize(s) r.moveCenter(self.rect().center()) painter.drawPixmap(r, self.viewer.pixmap(s))
def drawBackground(self, painter, rect): QGraphicsView.drawBackground(self, painter, rect) if not self.__backgroundIcon.isNull(): painter.setClipRect(rect) vrect = QRect(QPoint(0, 0), self.viewport().size()) vrect = self.mapToScene(vrect).boundingRect() pm = self.__backgroundIcon.pixmap(vrect.size().toSize().boundedTo( QSize(200, 200))) pmrect = QRect(QPoint(0, 0), pm.size()) pmrect.moveCenter(vrect.center().toPoint()) if rect.toRect().intersects(pmrect): painter.drawPixmap(pmrect, pm)
def drawBackground(self, painter, rect): QGraphicsView.drawBackground(self, painter, rect) if not self.__backgroundIcon.isNull(): painter.setClipRect(rect) vrect = QRect(QPoint(0, 0), self.viewport().size()) vrect = self.mapToScene(vrect).boundingRect() pm = self.__backgroundIcon.pixmap( vrect.size().toSize().boundedTo(QSize(200, 200)) ) pmrect = QRect(QPoint(0, 0), pm.size()) pmrect.moveCenter(vrect.center().toPoint()) if rect.toRect().intersects(pmrect): painter.drawPixmap(pmrect, pm)
def __updateWindowGeometry(self): if not self.isWindow() or self.__hasExplicitSize: return def framemargins(widget): frame, geom = widget.frameGeometry(), widget.geometry() return QMargins(geom.left() - frame.left(), geom.top() - frame.top(), geom.right() - frame.right(), geom.bottom() - frame.bottom()) def fitRect(rect, targetrect): size = rect.size().boundedTo(targetgeom.size()) newrect = QRect(rect.topLeft(), size) dx, dy = 0, 0 if newrect.left() < targetrect.left(): dx = targetrect.left() - newrect.left() if newrect.top() < targetrect.top(): dy = targetrect.top() - newrect.top() if newrect.right() > targetrect.right(): dx = targetrect.right() - newrect.right() if newrect.bottom() > targetrect.bottom(): dy = targetrect.bottom() - newrect.bottom() return newrect.translated(dx, dy) margins = framemargins(self) minsize = QSize(120, 120) pixsize = self.__pixmap.size() available = QApplication.desktop().availableGeometry(self) available = available.adjusted(margins.left(), margins.top(), -margins.right(), -margins.bottom()) # extra adjustment so the preview does not cover the whole desktop available = available.adjusted(10, 10, -10, -10) targetsize = pixsize.boundedTo(available.size()).expandedTo(minsize) pixsize.scale(targetsize, Qt.KeepAspectRatio) if not self.testAttribute(Qt.WA_WState_Created) or \ self.testAttribute(Qt.WA_WState_Hidden): center = available.center() else: center = self.geometry().center() targetgeom = QRect(QPoint(0, 0), pixsize) targetgeom.moveCenter(center) if not available.contains(targetgeom): targetgeom = fitRect(targetgeom, available) self.__inUpdateWindowGeometry = True self.setGeometry(targetgeom) self.__inUpdateWindowGeometry = False
def updateStandardIcons(self): size = QSize(16, 16) rect = QRect(QPoint(), self.iconSize()) transform = QTransform() transform.rotate(90) pixmap = self.style().standardIcon(QStyle.SP_TitleBarNormalButton, None, self.widgetForAction(self.aFloat)).pixmap(size) rect.moveCenter(pixmap.rect().center()) pixmap = pixmap.copy(rect) self.aFloat.setIcon(QIcon(pixmap)) pixmap = self.style().standardIcon(QStyle.SP_TitleBarCloseButton, None, self.widgetForAction(self.aClose)).pixmap(size) rect.moveCenter(pixmap.rect().center()) pixmap = pixmap.copy(rect) self.aClose.setIcon(QIcon(pixmap))
def draw(self, rect, indicator, depth, new_depth): p = self.p if depth: p.drawLine(rect.center(), QPoint(rect.center().x(), rect.y())) if new_depth: p.drawLine(rect.center(), QPoint(rect.center().x(), rect.bottom())) if new_depth < depth and not indicator: p.drawLine(rect.center(), QPoint(rect.right()-1, rect.center().y())) if indicator: square = QRect(0, 0, 8, 8) square.moveCenter(rect.center() - QPoint(1, 1)) p.fillRect(square, self.w.palette().color(QPalette.Base)) p.drawRect(square) x = rect.center().x() y = rect.center().y() p.drawLine(QPoint(x-2, y), QPoint(x+2, y)) if indicator == OPEN: p.drawLine(QPoint(x, y-2), QPoint(x, y+2))
def updateStandardIcons(self): size = QSize(16, 16) rect = QRect(QPoint(), self.iconSize()) transform = QTransform() transform.rotate(90) pixmap = self.style().standardIcon( QStyle.SP_TitleBarNormalButton, None, self.widgetForAction(self.aFloat)).pixmap(size) rect.moveCenter(pixmap.rect().center()) pixmap = pixmap.copy(rect) self.aFloat.setIcon(QIcon(pixmap)) pixmap = self.style().standardIcon(QStyle.SP_TitleBarCloseButton, None, self.widgetForAction( self.aClose)).pixmap(size) rect.moveCenter(pixmap.rect().center()) pixmap = pixmap.copy(rect) self.aClose.setIcon(QIcon(pixmap))
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 = opt.icon icon_size = opt.iconSize # TODO: add shift for pressed as set by the style (PM_ButtonShift...) pm = None if not icon.isNull(): if opt.state & QStyle.State_Enabled: mode = QIcon.Normal else: mode = QIcon.Disabled pm = opt.icon.pixmap( rect.size().boundedTo(icon_size), mode, QIcon.On if opt.state & QStyle.State_On else QIcon.Off) 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 == QStyleOptionToolBoxV2.OnlyOneTab or \ self.position == QStyleOptionToolBoxV2.Beginning or \ self.selected & \ QStyleOptionToolBoxV2.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 pm: pm_rect = QRect(QPoint(0, 0), pm.size()) centered_rect = QRect(pm_rect) centered_rect.moveCenter(icon_area_rect.center()) p.drawPixmap(centered_rect, pm, pm_rect) p.restore()
def paintVerticalCell(self, painter: QPainter, hv: QHeaderView, cellIndex: QModelIndex, leafIndex: QModelIndex, logicalLeafIndex: int, styleOptions: QStyleOptionHeader, sectionRect: QRect, left: int): uniopt = QStyleOptionHeader(styleOptions) self.setForegroundBrush(uniopt, cellIndex) self.setBackgroundBrush(uniopt, cellIndex) width=self.cellSize(cellIndex, hv, uniopt).width() if cellIndex==leafIndex: width=sectionRect.width()-left top=self.currentCellLeft(cellIndex, leafIndex, logicalLeafIndex, sectionRect.top(), hv) height=self.currentCellWidth(cellIndex, leafIndex, logicalLeafIndex, hv) r = QRect(left, top, width, height) uniopt.text = cellIndex.data(Qt.DisplayRole) painter.save() uniopt.rect = r if cellIndex.data(Qt.UserRole): hv.style().drawControl(QStyle.CE_HeaderSection, uniopt, painter, hv) m = QMatrix() m.rotate(-90) painter.setWorldMatrix(m, True) new_r = QRect(0, 0, r.height(), r.width()) new_r.moveCenter(QPoint(-r.center().y(), r.center().x())) uniopt.rect = new_r hv.style().drawControl(QStyle.CE_HeaderLabel, uniopt, painter, hv) else: hv.style().drawControl(QStyle.CE_Header, uniopt, painter, hv) painter.restore() return left+width def paintVerticalSection(self, painter: QPainter, sectionRect: QRect, logicalLeafIndex: int, hv: QHeaderView, styleOptions: QStyleOptionHeader, leafIndex: QModelIndex): oldBO = painter.brushOrigin() left = sectionRect.x() indexes = QModelIndexList(self.parentIndexes(leafIndex)) for i in range(indexes.size()): realStyleOptions = QStyleOptionHeader(styleOptions) if i<indexes.size()-1 and (realStyleOptions.state&QStyle.State_Sunken or realStyleOptions.state&QStyle.State_On): t = QStyle.State(QStyle.State_Sunken | QStyle.State_On) realStyleOptions.state = realStyleOptions.state&~t #FIXME: parent items are not highlighted left=self.paintVerticalCell(painter, hv, indexes[i], leafIndex, logicalLeafIndex, realStyleOptions, sectionRect, left) painter.setBrushOrigin(oldBO) def __init__(self, orientation: Qt.Orientation, parent: QWidget): super().__init__(orientation, parent) self._pd = self.private_data() self.sectionResized.connect(self.on_sectionResized) self.setHighlightSections(self.options.get("highlightSections")) self.setClickable(self.options.get("clickable")) self.show() #force to be visible getattr(parent, "set%sHeader"%("Horizontal", "Vertical")[orientation!=Qt.Horizontal])(self) self.sectionMoved.connect(self.on_sectionMoved) def on_sectionMoved(self, logicalIndex, oldVisualIndex, newVisualIndex): view, model = self.parent(), self.parent().model() if not hasattr(model, "reorder"): return #reorder underlying data of models with /reorder/ def only if getattr(self, "manual_move", False): self.manual_move=False return self.manual_move=True self.moveSection(newVisualIndex, oldVisualIndex) #cancel move if model.reorder(oldVisualIndex, newVisualIndex, self.orientation()): #Reorder column widths / row heights horizontal = self.orientation()==Qt.Horizontal itemSize = (view.rowHeight, view.columnWidth)[horizontal] setItemSize = (view.setRowHeight, view.setColumnWidth)[horizontal] rng = sorted((oldVisualIndex, newVisualIndex)) options = [(itemSize(i), i) for i in range(rng[0], rng[1]+1)] options.insert(newVisualIndex-rng[0], options.pop(oldVisualIndex-rng[0])) for i, col in enumerate(range(rng[0], rng[1]+1)): setItemSize(col, options[i][0]) getattr(view, "select"+("Row", "Column")[horizontal])(newVisualIndex) #FIXME: don't select if sorting is enable? if self.isSortIndicatorShown(): sortIndIndex = next((i for i, o in enumerate(options) if o[1]==self.sortIndicatorSection()), None) if sortIndIndex is not None: #sort indicator is among sections being reordered self.setSortIndicator(sortIndIndex+rng[0], self.sortIndicatorOrder()) #FIXME: does unnecessary sorting model.layoutChanged.emit() #update view def styleOptionForCell(self, logicalInd: int)->QStyleOptionHeader: opt = QStyleOptionHeader() self.initStyleOption(opt) if self.isSortIndicatorShown() and self.sortIndicatorSection()==logicalInd: opt.sortIndicator = (QStyleOptionHeader.SortUp, QStyleOptionHeader.SortDown)[self.sortIndicatorOrder()==Qt.AscendingOrder] if self.window().isActiveWindow(): opt.state = opt.state|QStyle.State_Active opt.textAlignment = Qt.AlignCenter opt.iconAlignment = Qt.AlignVCenter opt.section = logicalInd visual = self.visualIndex(logicalInd) if self.count() == 1: opt.position = QStyleOptionHeader.OnlyOneSection else: if visual == 0: opt.position = QStyleOptionHeader.Beginning else: opt.position = QStyleOptionHeader.End if visual==self.count()-1 else QStyleOptionHeader.Middle if self.isClickable(): # if logicalIndex == d.hover: # ... if self.highlightSections() and self.selectionModel(): if self.orientation()==Qt.Horizontal: if self.selectionModel().columnIntersectsSelection(logicalInd, self.rootIndex()): opt.state = opt.state|QStyle.State_On if self.selectionModel().isColumnSelected(logicalInd, self.rootIndex()): opt.state = opt.state|QStyle.State_Sunken else: if self.selectionModel().rowIntersectsSelection(logicalInd, self.rootIndex()): opt.state = opt.state|QStyle.State_On if self.selectionModel().isRowSelected(logicalInd, self.rootIndex()): opt.state = opt.state|QStyle.State_Sunken if self.selectionModel(): previousSelected=False if self.orientation()==Qt.Horizontal: previousSelected = self.selectionModel().isColumnSelected(self.logicalIndex(visual - 1), self.rootIndex()) else: previousSelected = self.selectionModel().isRowSelected(self.logicalIndex(visual - 1), self.rootIndex()) nextSelected=False if self.orientation()==Qt.Horizontal: nextSelected = self.selectionModel().isColumnSelected(self.logicalIndex(visual + 1), self.rootIndex()) else: nextSelected = self.selectionModel().isRowSelected(self.logicalIndex(visual + 1), self.rootIndex()) if previousSelected and nextSelected: opt.selectedPosition = QStyleOptionHeader.NextAndPreviousAreSelected else: if previousSelected: opt.selectedPosition = QStyleOptionHeader.PreviousIsSelected else: if nextSelected: opt.selectedPosition = QStyleOptionHeader.NextIsSelected else: opt.selectedPosition = QStyleOptionHeader.NotAdjacent return opt def sectionSizeFromContents(self, logicalIndex: int)->QSize: if self._pd.headerModel: curLeafIndex = QModelIndex(self._pd.leafIndex(logicalIndex)) if curLeafIndex.isValid(): styleOption = QStyleOptionHeader(self.styleOptionForCell(logicalIndex)) s = QSize(self._pd.cellSize(curLeafIndex, self, styleOption)) curLeafIndex=curLeafIndex.parent() while curLeafIndex.isValid(): if self.orientation() == Qt.Horizontal: s.setHeight(s.height()+self._pd.cellSize(curLeafIndex, self, styleOption).height()) else: s.setWidth(s.width()+self._pd.cellSize(curLeafIndex, self, styleOption).width()) curLeafIndex=curLeafIndex.parent() return s return super().sectionSizeFromContents(logicalIndex) def paintSection(self, painter: QPainter, rect: QRect, logicalIndex: int): if rect.isValid(): leafIndex = QModelIndex(self._pd.leafIndex(logicalIndex)) if leafIndex.isValid(): if self.orientation() == Qt.Horizontal: self._pd.paintHorizontalSection(painter, rect, logicalIndex, self, self.styleOptionForCell(logicalIndex), leafIndex) else: self._pd.paintVerticalSection(painter, rect, logicalIndex, self, self.styleOptionForCell(logicalIndex), leafIndex) return super().paintSection(painter, rect, logicalIndex) def on_sectionResized(self, logicalIndex: int): if self.isSectionHidden(logicalIndex): return leafIndex = QModelIndex(self._pd.leafIndex(logicalIndex)) if leafIndex.isValid(): leafsList = QModelIndexList(self._pd.leafs(self._pd.findRootIndex(leafIndex))) for n in range(leafsList.indexOf(leafIndex), 0, -1): logicalIndex-=1 w = self.viewport().width() h = self.viewport().height() pos = self.sectionViewportPosition(logicalIndex) r = QRect(pos, 0, w - pos, h) if self.orientation() == Qt.Horizontal: if self.isRightToLeft(): r.setRect(0, 0, pos + self.sectionSize(logicalIndex), h) else: r.setRect(0, pos, w, h - pos) self.viewport().update(r.normalized()) def setModel(self, model): super().setModel(model) model.layoutChanged.connect(self.layoutChanged) self.layoutChanged() def layoutChanged(self): if self.model(): self._pd.initFromNewModel(self.orientation(), self.model()) axis = ("column", "row")[self.orientation()!=Qt.Horizontal] cnt = getattr(self.model(), axis+"Count")(QModelIndex()) if cnt: self.initializeSections(0, cnt-1) MultiIndexHeaderView=HierarchicalHeaderView class DataFrameModel(QtCore.QAbstractTableModel): #na_values:least|greatest - for sorting options = {"striped": True, "stripesColor": "#fafafa", "na_values": "least", "tooltip_min_len": 21} def __init__(self, dataframe=None): super().__init__() self.setDataFrame(dataframe if dataframe is not None else pd.DataFrame()) def setDataFrame(self, dataframe): self.df = dataframe.copy() # self.df_full = self.df self.layoutChanged.emit() def rowCount(self, parent): return len(self.df) def columnCount(self, parent): return len(self.df.columns) def readLevel(self, y=0, xs=0, xe=None, orient=None): c = getattr(self.df, ("columns", "index")[orient!=HorizontalHeaderDataRole]) if not hasattr(c, "levels"): #not MultiIndex return [QtGui.QStandardItem(str(i)) for i in c] sibl = [] section_start, v, xe = xs, None, xe or len(c) for i in range(xs, xe): label = c.labels[y][i] if label!=v: if y+1<len(c.levels) and i>xs: children = self.readLevel(y+1, section_start, i, orient=orient) sibl[-1].appendRow(children) item = QtGui.QStandardItem(str(c.levels[y][label])) sibl.append(item) section_start = i v=label if y+1<len(c.levels): children = self.readLevel(y+1, section_start, orient=orient) sibl[-1].appendRow(children) return sibl def data(self, index, role): row, col = index.row(), index.column() if role in (Qt.DisplayRole, Qt.ToolTipRole): ret = self.df.iat[row, col] if ret is not None and ret==ret: #convert to str except for None, NaN, NaT if isinstance(ret, float): ret = "{:n}".format(ret) elif isinstance(ret, datetime.date): #FIXME: show microseconds optionally ret = ret.strftime(("%x", "%c")[isinstance(ret, datetime.datetime)]) else: ret = str(ret) if role == Qt.ToolTipRole: if len(ret)<self.options["tooltip_min_len"]: ret = "" return ret elif role == Qt.BackgroundRole: if self.options["striped"] and row%2: return QBrush(QColor(self.options["stripesColor"])) elif role in (HorizontalHeaderDataRole, VerticalHeaderDataRole): hm = QtGui.QStandardItemModel() hm.appendRow(self.readLevel(orient=role)) return hm def reorder(self, oldIndex, newIndex, orientation): "Reorder columns / rows" horizontal = orientation==Qt.Horizontal cols = list(self.df.columns if horizontal else self.df.index) cols.insert(newIndex, cols.pop(oldIndex)) self.df = self.df[cols] if horizontal else self.df.T[cols].T return True # def filter(self, filt=None): # self.df = self.df_full if filt is None else self.df[filt] # self.layoutChanged.emit() def headerData(self, section, orientation, role): if role != Qt.DisplayRole: return label = getattr(self.df, ("columns", "index")[orientation!=Qt.Horizontal])[section] # return label if type(label) is tuple else label return ("\n", " | ")[orientation!=Qt.Horizontal].join(str(i) for i in label) if type(label) is tuple else str(label) def dataFrame(self): return self.df def sort(self, column, order): # print("sort", column, order) #FIXME: double sort after setSortingEnabled(True) if len(self.df): asc = order==Qt.AscendingOrder na_pos = 'first' if (self.options["na_values"]=="least")==asc else 'last' self.df.sort_values(self.df.columns[column], ascending=asc, inplace=True, na_position=na_pos) self.layoutChanged.emit() if __name__=="__main__": import sys, locale locale.setlocale(locale.LC_ALL, '') #system locale settings app = QtGui.QApplication(sys.argv) form = QtGui.QWidget() form.setAttribute(Qt.WA_DeleteOnClose) #http://stackoverflow.com/a/27178019/1119602 form.setMinimumSize(700, 260) view = QtGui.QTableView() QtGui.QVBoxLayout(form).addWidget(view) form.show() #Prepare data tuples=[('bar', 'one', 'q'), ('bar', 'two', 'q'), ('baz', 'one', 'q'), ('baz', 'two', 'q'), ('foo', 'one', 'q'), ('foo', 'two', 'q'), ('qux', 'one', 'q'), ('qux', 'two', 'q')] index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second', 'third']) df=pd.DataFrame(pd.np.random.randn(6, 6), index=index[:6], columns=index[:6]) print("DataFrame:\n%s"%df) #Prepare view # oldh, oldv = view.horizontalHeader(), view.verticalHeader() # oldh.setParent(form), oldv.setParent(form) #Save old headers for some reason MultiIndexHeaderView(Qt.Horizontal, view) MultiIndexHeaderView(Qt.Vertical, view) view.horizontalHeader().setMovable(True) #reorder DataFrame columns manually #Set data view.setModel(DataFrameModel(df)) view.resizeColumnsToContents() view.resizeRowsToContents() #Set sorting enabled (after setting model) view.setSortingEnabled(True) sys.exit(app.exec())
def drawScaleContents(self, painter, center, radius): rect = QRect(0, 0, 2 * radius, 2 * radius + 30) rect.moveCenter(center) painter.setPen(self.palette().color(QPalette.Text)) painter.drawText(rect, Qt.AlignBottom | Qt.AlignHCenter, self.direction)
class SMSTextMessage(object): def __init__(self, message, str=None): cfg = Config('chats', message) if (str is None): self.str = cfg.get('message') else: self.str = str self.str = self.str.replace('\\\n', '').replace('\n', '\n\n') self.duration = cfg.get('duration') self.font = FontManager.getFont(cfg.get('font')) self.font.setPointSize(cfg.get('font_size')) self.font_color = QColor.fromRgb(*cfg.get('font_color')) self.image = QImage(cfg.get('image_path')) p = cfg.get('image_pos') self.image_rect = QRect(0., 0., self.image.width(), self.image.height()) self.image_rect.moveCenter(QPoint(p[0], p[1])) self.text_rect = QRect(*cfg.get('text_rect')) self.has_cursor = True self.blink_elapsed = 0. self.blink_time = cfg.get('blink_time') self.elapsed = 0. self.message_sz = len(self.str) def tick(self, elapsed): self.controller.tick_parent(self, elapsed) self.elapsed += elapsed self.blink_elapsed += elapsed if (self.blink_elapsed >= self.blink_time): self.blink_elapsed -= self.blink_time self.has_cursor = not self.has_cursor def draw(self): self.controller.draw_parent(self) ortho_projection(self.controller.width(), self.controller.height()) self.qpainter.drawImage(self.image_rect, self.image) i = int((self.elapsed / self.duration) * self.message_sz) text = self.str[0:i] if (self.has_cursor): text += '|' self.qpainter.setFont(self.font) self.qpainter.setPen(self.font_color) #self.qpainter.fillRect(self.text_rect, self.font_color) self.qpainter.drawText(self.text_rect, qt_sms_flag, text) def keyPressEvent(self, event): k = event.key() if (k == Qt.Key_Return or k == Qt.Key_Enter): if (event.isAutoRepeat()): return if (self.elapsed >= self.duration): self.controller.pop_screen(self) else: self.elapsed = self.duration + 0.1 return return True
def loadImages(self): self.game.board.image = QImage(self.game.board.image) names = self.game.board.territoryNames() progress = QProgressDialog("Loading Board", "", 0, len(names)) progress.setCancelButton(None) progress.setMinimumDuration(0) for (i, name) in enumerate(names): progress.setValue(i) t = self.game.board.getTerritory(name) t.image = QImage(t.image) #generate region map regionOverlay = QImage(self.imageSize(), QImage.Format_ARGB32_Premultiplied) regionOverlay.fill(0) painter = QPainter() painter.begin(regionOverlay) labels = [] for r in self.game.board.regions: regionMask = QImage(self.imageSize(), QImage.Format_ARGB32_Premultiplied) regionMask.fill(0) p = QPainter() p.begin(regionMask) center = QPoint(0, 0) for t in r.territories: p.drawImage(0, 0, t.image) center += QPoint(*t.center) center /= len(r.territories) p.end() regionImage = QImage(self.imageSize(), QImage.Format_ARGB32_Premultiplied) regionImage.fill(0) p.begin(regionImage) p.setCompositionMode(QPainter.CompositionMode_Source) color = [randint(0, 255) for i in range(3)] + [200] p.fillRect(regionImage.rect(), QColor(*color)) p.setCompositionMode(QPainter.CompositionMode_DestinationIn) p.drawImage(0, 0, regionMask) p.end() painter.drawImage(0, 0, regionImage) text = "%s: %d" % (r.name, r.bonus) labels.append((center, text)) for l in labels: (center, text) = l height = painter.fontMetrics().height() + 8 width = painter.fontMetrics().width(text) + 8 painter.setPen(Qt.white) painter.setBrush(QColor(0, 0, 0, 200)) textRect = QRect(0, 0, width, height) textRect.moveCenter(center) painter.drawRect(textRect) painter.drawText(textRect, Qt.AlignCenter, text) painter.end() regionMap = self.game.board.image.copy() painter.begin(regionMap) painter.drawImage(0, 0, regionOverlay) painter.end() self.regionMap = QPixmap.fromImage(regionMap) self.scaledRegionMap = self.regionMap self.ownershipMap = QPixmap.fromImage(self.game.board.image) self.scaledOwnershipMap = self.ownershipMap troopCountMap = QImage(self.game.board.image.size(), QImage.Format_ARGB32_Premultiplied) troopCountMap.fill(0) self.troopCountMap = QPixmap.fromImage(troopCountMap) self.scaledTroopCountMap = self.troopCountMap
class SMSTextMessage(object): def __init__(self, message, str = None): cfg = Config('chats', message) if (str is None): self.str = cfg.get('message') else: self.str = str self.str = self.str.replace('\\\n', '').replace('\n','\n\n') self.duration = cfg.get('duration') self.font = FontManager.getFont(cfg.get('font')) self.font.setPointSize(cfg.get('font_size')) self.font_color = QColor.fromRgb(*cfg.get('font_color')) self.image = QImage(cfg.get('image_path')) p = cfg.get('image_pos') self.image_rect = QRect(0.,0.,self.image.width(),self.image.height()) self.image_rect.moveCenter(QPoint(p[0],p[1])) self.text_rect = QRect(*cfg.get('text_rect')) self.has_cursor = True self.blink_elapsed = 0. self.blink_time = cfg.get('blink_time') self.elapsed = 0. self.message_sz = len(self.str) def tick(self, elapsed): self.controller.tick_parent(self, elapsed) self.elapsed += elapsed self.blink_elapsed += elapsed if (self.blink_elapsed >= self.blink_time): self.blink_elapsed -= self.blink_time self.has_cursor = not self.has_cursor def draw(self): self.controller.draw_parent(self) ortho_projection( self.controller.width(), self.controller.height() ) self.qpainter.drawImage(self.image_rect, self.image) i = int((self.elapsed / self.duration) * self.message_sz) text = self.str[0:i] if (self.has_cursor): text += '|' self.qpainter.setFont(self.font) self.qpainter.setPen(self.font_color) #self.qpainter.fillRect(self.text_rect, self.font_color) self.qpainter.drawText(self.text_rect, qt_sms_flag, text) def keyPressEvent(self, event): k = event.key() if (k == Qt.Key_Return or k == Qt.Key_Enter): if (event.isAutoRepeat()): return if (self.elapsed >= self.duration): self.controller.pop_screen(self) else: self.elapsed = self.duration + 0.1 return return True