def showMoveHelper(self, visible=None): """show help text In empty HandBoards""" if visible is None: visible = not self.uiTiles if self.__moveHelper and not isAlive(self.__moveHelper): return if visible: if not self.__moveHelper: splitter = QGraphicsRectItem(self) hbCenter = self.rect().center() splitter.setRect( hbCenter.x() * 0.5, hbCenter.y(), hbCenter.x() * 1, 1) helpItems = [splitter] for name, yFactor in [(m18n('Move Exposed Tiles Here'), 0.5), (m18n('Move Concealed Tiles Here'), 1.5)]: helper = QGraphicsSimpleTextItem(name, self) helper.setScale(3) nameRect = QRectF() nameRect.setSize( helper.mapToParent(helper.boundingRect()).boundingRect().size()) center = QPointF(hbCenter) center.setY(center.y() * yFactor) helper.setPos(center - nameRect.center()) if self.sceneRotation() == 180: rotateCenter(helper, 180) helpItems.append(helper) self.__moveHelper = self.scene().createItemGroup(helpItems) self.__moveHelper.setVisible(True) else: if self.__moveHelper: self.__moveHelper.setVisible(False)
def showMoveHelper(self, visible=None): """show help text In empty HandBoards""" if visible is None: visible = not self.uiTiles if self.__moveHelper and not isAlive(self.__moveHelper): return if visible: if not self.__moveHelper: splitter = QGraphicsRectItem(self) hbCenter = self.rect().center() splitter.setRect(hbCenter.x() * 0.5, hbCenter.y(), hbCenter.x() * 1, 1) helpItems = [splitter] for name, yFactor in [(i18n('Move Exposed Tiles Here'), 0.5), (i18n('Move Concealed Tiles Here'), 1.5) ]: helper = QGraphicsSimpleTextItem(name, self) helper.setScale(3) nameRect = QRectF() nameRect.setSize( helper.mapToParent( helper.boundingRect()).boundingRect().size()) center = QPointF(hbCenter) center.setY(center.y() * yFactor) helper.setPos(center - nameRect.center()) if sceneRotation(self) == 180: rotateCenter(helper, 180) helpItems.append(helper) self.__moveHelper = self.scene().createItemGroup(helpItems) self.__moveHelper.setVisible(True) else: if self.__moveHelper: self.__moveHelper.setVisible(False)
def tileFacePos(self): """the face pos of a uiTile relative to its origin""" if not Internal.Preferences.showShadows: return QPointF() lightSource = self.rotatedLightSource() xoffset = self.tileset.shadowWidth() - 1 if 'E' in lightSource else 0 yoffset = self.tileset.shadowHeight() - 1 if 'S' in lightSource else 0 return QPointF(xoffset, yoffset)
def __paintCross(self, painter): """paint a cross on the tile""" with Painter(painter): faceSize = self.tileset.faceSize width = faceSize.width() height = faceSize.height() painter.translate(self.facePos()) painter.drawLine(QPointF(0.0, 0.0), QPointF(width, height)) painter.drawLine(QPointF(width, 0.0), QPointF(0.0, height))
def center(self): """returns the center point of the wall in relation to the faces of the upper level""" faceRect = self.tileFaceRect() result = faceRect.topLeft() + self.shiftZ(1) + \ QPointF(self.length // 2 * faceRect.width(), faceRect.height() / 2) result.setX(result.x() + faceRect.height() / 2) # corner tile return result
def boundingRect(self): """define the part of the tile we want to see. Do not return QRect() if tileset is not known because that makes QGraphicsscene crash""" if self.tileset: self._boundingRect = QRectF( QPointF(), self.tileset.tileSize if Internal.Preferences.showShadows else self.tileset.faceSize) return self._boundingRect
def moveDict(self): """a dict with attributes for the new position, normally pos, rotation and scale""" sideCenter = self.board.center() boardPos = QPointF( sideCenter.x() * 1.63, sideCenter.y() - self.boundingRect().height() / 2.0) scenePos = self.board.mapToScene(boardPos) return {'pos': scenePos, 'rotation': sceneRotation(self.board)}
def dropEvent(self, event): """drop into this handboard""" uiTile = event.mimeData().uiTile lowerHalf = self.mapFromScene(QPointF( event.scenePos())).y() >= self.rect().height() / 2.0 if self.dropTile(uiTile, lowerHalf): event.accept() else: event.ignore() self._noPen()
def chart(self, rect, index, playerItem): """returns list(QPointF) for a player in a specific tree cell""" chartHeight = float(rect.height()) * 4 yScale = chartHeight / (self.minY - self.maxY) yOffset = rect.height() * index.row() yValues = list(playerItem.chartPoints(index.column(), self.steps)) yValues = [(y - self.maxY) * yScale - yOffset for y in yValues] stepX = float(rect.width()) / self.steps xValues = list(x * stepX for x in range(self.steps + 1)) return list(QPointF(x, y) for x, y in zip(xValues, yValues))
def moveDict(self): """a dict with attributes for the new position, normally pos, rotation and scale""" assert self.board width = self.tileset.faceSize.width() height = self.tileset.faceSize.height() shiftZ = self.board.shiftZ(self.level) boardPos = QPointF( self.xoffset * width, self.yoffset * height) + shiftZ scenePos = self.board.mapToScene(boardPos) return {'pos': scenePos, 'rotation': sceneRotation(self.board), 'scale': self.board.scale()}
def shiftZ(self, level): """used for 3D: compute the needed shift for the uiTile. level is the vertical position. 0 is the face position on ground level, -1 is the imprint a uiTile makes on the surface it stands on""" if not Internal.Preferences.showShadows: return QPointF() shiftX = 0 shiftY = 0 if level != 0: lightSource = self.rotatedLightSource() stepX = level * self.tileset.shadowWidth() / 2 stepY = level * self.tileset.shadowHeight() / 2 if 'E' in lightSource: shiftX = stepX if 'W' in lightSource: shiftX = -stepX if 'N' in lightSource: shiftY = -stepY if 'S' in lightSource: shiftY = stepY return QPointF(shiftX, shiftY)
def dragMoveEvent(self, event): """allow dropping of uiTile from ourself only to other state (open/concealed)""" uiTile = event.mimeData().uiTile localY = self.mapFromScene(QPointF(event.scenePos())).y() centerY = self.rect().height() / 2.0 newLowerHalf = localY >= centerY noMansLand = centerY / 6 if -noMansLand < localY - centerY < noMansLand and not uiTile.isBonus: doAccept = False elif uiTile.board != self: doAccept = True elif uiTile.isBonus: doAccept = False else: oldLowerHalf = uiTile.board.isHandBoard and uiTile in uiTile.board.lowerHalfTiles( ) doAccept = oldLowerHalf != newLowerHalf event.setAccepted(doAccept)
def pixmapFromSvg(self, pmapSize=None, withBorders=None): """returns a pixmap with default size as given in SVG and optional borders/shadows""" if withBorders is None: withBorders = Internal.Preferences.showShadows if withBorders: wantSize = self.tileset.tileSize.toSize() else: wantSize = self.tileset.faceSize.toSize() if not pmapSize: pmapSize = wantSize result = QPixmap(pmapSize) result.fill(Qt.transparent) painter = QPainter(result) if not painter.isActive(): logException( 'painter is not active. Wanted size: %s' % str(pmapSize)) try: xScale = float(pmapSize.width()) / wantSize.width() yScale = float(pmapSize.height()) / wantSize.height() except ZeroDivisionError: xScale = 1 yScale = 1 if not withBorders: painter.scale(*self.tileset.tileFaceRelation()) painter.translate(-self.facePos()) renderer = self.tileset.renderer() renderer.render(painter, self.__elementId()) painter.resetTransform() self._drawDarkness(painter) if self.showFace(): faceSize = self.tileset.faceSize.toSize() faceSize = QSize( faceSize.width() * xScale, faceSize.height() * yScale) painter.translate(self.facePos()) renderer.render(painter, self.tileset.svgName[self.tile.exposed], QRectF(QPointF(), QSizeF(faceSize))) return result
def __fillLastMeldComboWith(self, winnerMelds, indexedMeld, lastTile): """fill last meld combo with prepared content""" winner = self.game.winner faceWidth = winner.handBoard.tileset.faceSize.width() * 0.5 faceHeight = winner.handBoard.tileset.faceSize.height() * 0.5 restoredIdx = None for meld in winnerMelds: pixMap = QPixmap(faceWidth * len(meld), faceHeight) pixMap.fill(Qt.transparent) self.__meldPixMaps.append(pixMap) painter = QPainter(pixMap) for element in meld: painter.drawPixmap( 0, 0, winner.handBoard.tilesByElement(element)[0].pixmapFromSvg( QSize(faceWidth, faceHeight), withBorders=False)) painter.translate(QPointF(faceWidth, 0.0)) self.cbLastMeld.addItem(QIcon(pixMap), '', str(meld)) if indexedMeld == str(meld): restoredIdx = self.cbLastMeld.count() - 1 if not restoredIdx and indexedMeld: # try again, maybe the meld changed between concealed and exposed indexedMeld = indexedMeld.lower() for idx in range(self.cbLastMeld.count()): meldContent = str(self.cbLastMeld.itemData(idx)) if indexedMeld == meldContent.lower(): restoredIdx = idx if lastTile not in meldContent: lastTile = lastTile.swapped assert lastTile in meldContent with BlockSignals(self.cbLastTile ): # we want to continue right here idx = self.cbLastTile.findData(lastTile) self.cbLastTile.setCurrentIndex(idx) break if not restoredIdx: restoredIdx = 0 self.cbLastMeld.setCurrentIndex(restoredIdx) self.cbLastMeld.setIconSize(QSize(faceWidth * 3, faceHeight))