Beispiel #1
0
 def export(self, filename=None, add_margin=False):
     pw = QPdfWriter(filename)
     dpi = int(QApplication.primaryScreen().logicalDotsPerInch())
     pw.setResolution(dpi)
     pw.setPageMargins(QMarginsF(0, 0, 0, 0))
     size = QPageSize(self.getTargetRect().size())
     pw.setPageSize(size)
     painter = QPainter(pw)
     try:
         self.setExportMode(
             True, {
                 'antialias': True,
                 'background': self.background,
                 'painter': painter
             })
         painter.setRenderHint(QPainter.Antialiasing, True)
         painter.setRenderHint(QPainter.LosslessImageRendering, True)
         source_rect = self.getSourceRect()
         if add_margin:
             source_rect.setWidth(source_rect.width() + 25)
         self.getScene().render(painter, QRectF(self.getTargetRect()),
                                QRectF(source_rect))
     finally:
         self.setExportMode(False)
     painter.end()
Beispiel #2
0
    def image_display(self):
        """
        Update the ct_image to be displayed on the DICOM View.
        """
        # Lead CT
        ct_pixmaps = self.pt_ct_dict_container.get(
            "ct_pixmaps_" + self.slice_view)
        slider_id = self.slider.value()
        ct_image = ct_pixmaps[slider_id].toImage()

        # Load PT
        pt_pixmaps = self.pt_ct_dict_container.get(
            "pt_pixmaps_" + self.slice_view)
        m = float(len(pt_pixmaps)) / len(ct_pixmaps)
        pt_image = pt_pixmaps[int(m * slider_id)].toImage()

        # Get alpha
        alpha = float(self.alpha_slider.value() / 100)

        # Merge Images
        painter = QPainter()
        painter.begin(ct_image)
        painter.setOpacity(alpha)
        painter.drawImage(0, 0, pt_image)
        painter.end()

        # Load merged images
        merged_pixmap = QtGui.QPixmap.fromImage(ct_image)
        label = QtWidgets.QGraphicsPixmapItem(merged_pixmap)
        self.scene = QtWidgets.QGraphicsScene()
        self.scene.addItem(label)
    def paintEvent(self, event: QPaintEvent):
        outerRadius = min(self.width(), self.height())
        baseRect = QRectF(1, 1, outerRadius - 2, outerRadius - 2)
        buffer = QImage(outerRadius, outerRadius,
                        QImage.Format_ARGB32_Premultiplied)

        p = QPainter(buffer)
        p.setRenderHint(QPainter.Antialiasing)

        self.rebuildDataBrushIfNeeded()
        self.drawBackground(p, buffer.rect())
        self.drawBase(p, baseRect)

        if self.m_value > 0:
            delta = (self.m_max - self.m_min) / (self.m_value - self.m_min)
        else:
            delta = 0

        self.drawValue(p, baseRect, self.m_value, delta)

        innerRect, innerRadius = self.calculateInnerRect(outerRadius)

        self.drawInnerBackground(p, innerRect)
        self.drawText(p, innerRect, innerRadius, self.m_value)
        p.end()

        painter = QPainter(self)
        painter.fillRect(baseRect, self.palette().window())
        painter.drawImage(0, 0, buffer)
Beispiel #4
0
    def paintEvent(self, event):
        """
        Paint the widget.
        """
        super(WaTorGraph, self).paintEvent(event)

        painter = QPainter(self)

        fish, sharks = self._world.stats()

        shark = self.helper_calc_y_pos(sharks)
        fish = self.helper_calc_y_pos(fish)

        draw = ImageDraw.Draw(self._image)
        draw.line([(self._prev_tick, self._prev_shark),
                   (self._tick, shark)], (0, 0, 255), 2)
        draw.line([(self._prev_tick, self._prev_fish),
                   (self._tick, fish)], (0, 255, 0), 2)

        painter.drawImage(QPoint(0, 0), ImageQt(self._image))
        painter.end()

        self._prev_tick = self._tick
        self._prev_shark = shark
        self._prev_fish = fish
        self._tick += 2

        if self._tick >= self._widget_size.width():
            self.reset()
def create_blue_green_rect():
    pixmap = QPixmap(4, 2)
    painter = QPainter(pixmap)
    try:
        painter.fillRect(0, 0, 2, 2, QColor('blue'))
        painter.fillRect(2, 0, 2, 2, QColor('green'))
    finally:
        painter.end()
    return pixmap
Beispiel #6
0
 def create_painter(self) -> typing.Iterator[QPainter]:
     white = QColor('white')
     pixmap = QPixmap(self.width, self.height)
     pixmap.fill(white)
     painter = QPainter(pixmap)
     try:
         yield painter
     finally:
         painter.end()
Beispiel #7
0
def paint_with_opacity(pixmap: QPixmap, opacity: float):
    transparent_image = QImage(QSize(36, 36),
                               QImage.Format_ARGB32_Premultiplied)
    transparent_image.fill(Qt.transparent)
    painter = QPainter(transparent_image)
    painter.setOpacity(opacity)
    painter.drawPixmap(18 - pixmap.width() / 2, 18 - pixmap.height() / 2,
                       pixmap)
    painter.end()
    return QPixmap.fromImage(transparent_image)
Beispiel #8
0
    def paintEvent(self, event):
        size = self.size()

        # draw background
        painter = QPainter()
        painter.begin(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(QColor(255, 255, 255, 255))
        painter.setBrush(self.fill_color)
        painter.drawRect(0, 0, size.width(), size.height())
        painter.end()
Beispiel #9
0
    def slotPrintPreview(self):
        pix = QPixmap(1000, 200)
        pix.fill(Qt.white)

        painter = QPainter(pix)
        view.print(painter, pix.rect())
        painter.end()

        label = QLabel(this)
        label.setPixmap(pix)
        label.show()
Beispiel #10
0
    def assert_equal(self):
        __tracebackhide__ = True
        self.end()
        self.different_pixels = 0
        actual_image: QImage = self.actual.device().toImage()
        expected_image: QImage = self.expected.device().toImage()
        diff_pixmap = QPixmap(actual_image.width(), actual_image.height())
        diff = QPainter(diff_pixmap)
        try:
            white = QColor('white')
            diff.fillRect(0, 0, actual_image.width(), actual_image.height(),
                          white)
            for x in range(actual_image.width()):
                for y in range(actual_image.height()):
                    actual_colour = actual_image.pixelColor(x, y)
                    expected_colour = expected_image.pixelColor(x, y)
                    diff.setPen(
                        self.diff_colour(actual_colour, expected_colour, x, y))
                    diff.drawPoint(x, y)
        finally:
            diff.end()
        diff_image: QImage = diff.device().toImage()

        display_diff(actual_image, diff_image, expected_image,
                     self.different_pixels)

        if self.different_pixels == 0:
            return
        actual_image.save(str(self.work_dir / (self.name + '_actual.png')))
        expected_image.save(str(self.work_dir / (self.name + '_expected.png')))
        diff_path = self.work_dir / (self.name + '_diff.png')
        is_saved = diff_image.save(str(diff_path))
        diff_width = self.diff_max_x - self.diff_min_x + 1
        diff_height = self.diff_max_y - self.diff_min_y + 1
        diff_section = QImage(diff_width, diff_height, QImage.Format_RGB32)
        diff_section_painter = QPainter(diff_section)
        try:
            diff_section_painter.drawPixmap(0, 0, diff_width, diff_height,
                                            QPixmap.fromImage(diff_image),
                                            self.diff_min_x, self.diff_min_y,
                                            diff_width, diff_height)
        finally:
            diff_section_painter.end()
        # To see an image dumped in the Travis CI log, copy the text from the
        # log, and paste it in test_pixmap_differ.test_decode_image.
        print(f'Encoded image of differing section '
              f'({self.diff_min_x}, {self.diff_min_y}) - '
              f'({self.diff_max_x}, {self.diff_max_y}):')
        print(encode_image(diff_section))
        message = f'Found {self.different_pixels} different pixels, '
        message += f'see' if is_saved else 'could not write'
        message += f' {diff_path.relative_to(Path(__file__).parent.parent)}.'
        assert self.different_pixels == 0, message
Beispiel #11
0
 def export_arr(self, frame_index: int):
     self.scene.update_frame(frame_index)
     img = QImage(self.video_data.width, self.video_data.height,
                  QImage.Format_ARGB32)
     painter = QPainter()
     painter.begin(img)
     self.scene.render(painter)
     painter.end()
     shape = (img.height(), img.bytesPerLine() * 8 // img.depth(), 4)
     ptr = img.bits()
     arr = np.array(ptr, dtype=np.uint8).reshape(shape)
     arr = arr[..., :3]
     return arr
Beispiel #12
0
 def create_icon(player_colour: QColor) -> QPixmap:
     size = 200
     icon = QPixmap(size, size)
     icon.fill(Qt.transparent)
     painter = QPainter(icon)
     try:
         painter.setBrush(player_colour)
         pen = QPen()
         pen.setWidth(3)
         painter.setPen(pen)
         painter.drawEllipse(1, 1, size - 2, size - 2)
     finally:
         painter.end()
     return icon
    def show_synced(self, is_sync: bool) -> None:
        p1 = QPixmap(self.icon().pixmap(self.icon().actualSize(QSize(1024, 1024))))
        p2 = self.get_icon(is_sync)

        mode = QPainter.CompositionMode_SourceOver
        s = p1.size().expandedTo(p2.size())
        result = QPixmap(s)
        result.fill(Qt.transparent)
        painter = QPainter(result)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.drawPixmap(QPoint(), p1)
        painter.setCompositionMode(mode)
        painter.drawPixmap(result.rect(), p2, p2.rect())
        painter.end()
        self.setIcon(QIcon(result))
Beispiel #14
0
    def paintEvent(self, event):
        """
        Paint the widget.
        """
        super(WaTorWidget, self).paintEvent(event)

        painter = QPainter(self)

        for y in range(self._size.height()):
            for x in range(self._size.width()):
                pos = QPoint(x, y) * self._scale
                painter.drawPixmap(pos, self._water.pixmap)

        for pos, mob in self._world.mobs.items():
            painter.drawPixmap(pos * self._scale, mob.pixmap)

        painter.end()
	def __init__(self):
		# Sidebar icons are 28x28 points. Should be at least 56x56 pixels for
		# HiDPI display compatibility. They will be automatically made theme
		# aware, so you need only provide a grayscale image, where white is
		# the color of the shape.
		icon = QImage(56, 56, QImage.Format_RGB32)
		icon.fill(0)

		# Render an "H" as the example icon
		p = QPainter()
		p.begin(icon)
		p.setFont(QFont("Open Sans", 56))
		p.setPen(QColor(255, 255, 255, 255))
		p.drawText(QRectF(0, 0, 56, 56), Qt.AlignCenter, "H")
		p.end()

		SidebarWidgetType.__init__(self, icon, "Hello")
Beispiel #16
0
    def assert_equal(self):
        __tracebackhide__ = True
        self.end()
        self.different_pixels = 0
        actual_image: QImage = self.actual.device().toImage()
        expected_image: QImage = self.expected.device().toImage()
        diff_pixmap = QPixmap(actual_image.width(), actual_image.height())
        diff = QPainter(diff_pixmap)
        try:
            white = QColor('white')
            diff.fillRect(0, 0, actual_image.width(), actual_image.height(),
                          white)
            for x in range(actual_image.width()):
                for y in range(actual_image.height()):
                    actual_colour = actual_image.pixelColor(x, y)
                    expected_colour = expected_image.pixelColor(x, y)
                    diff.setPen(
                        self.diff_colour(actual_colour, expected_colour, x, y))
                    diff.drawPoint(x, y)
        finally:
            diff.end()
        diff_image: QImage = diff.device().toImage()

        display_diff(actual_image, diff_image, expected_image,
                     self.different_pixels)

        if self.different_pixels == 0:
            return
        actual_image.save(str(self.work_dir / (self.name + '_actual.png')))
        expected_image.save(str(self.work_dir / (self.name + '_expected.png')))
        diff_path = self.work_dir / (self.name + '_diff.png')
        is_saved = diff_image.save(str(diff_path))
        diff_width = self.diff_max_x - self.diff_min_x + 1
        diff_height = self.diff_max_y - self.diff_min_y + 1
        diff_section = QImage(diff_width, diff_height, QImage.Format_RGB32)
        diff_section_painter = QPainter(diff_section)
        try:
            diff_section_painter.drawPixmap(0, 0, diff_width, diff_height,
                                            QPixmap.fromImage(diff_image),
                                            self.diff_min_x, self.diff_min_y,
                                            diff_width, diff_height)
        finally:
            diff_section_painter.end()
        message = f'Found {self.different_pixels} different pixels.'
        assert self.different_pixels == 0, message
Beispiel #17
0
def main():
    parser = parse_args()
    pov_file: Path = parser.pov_file
    stem = pov_file.stem
    shadow_stem = re.sub(r'-(\d+)$', r'-shadow-\1', stem)
    temp_file = pov_file.parent / (stem + '-temp.png')
    temp_shadow_file = pov_file.parent / (shadow_stem + '-temp.png')
    png_file = pov_file.parent / (shadow_stem + '.png')
    current_images = Path(__file__).parent.parent / 'shibumi_images'
    current_file = current_images / png_file.name
    if current_file.exists():
        png_file = current_file
    args = ['povray',
            '-D',
            f'+I{pov_file}',
            '+V',
            '-W640',
            '-H480',
            '+ua',
            f'+O{temp_file}']
    run(args, check=True)

    app = QApplication()
    images_path = Path(__file__).parent
    shadow_file = images_path / 'ball-r-shadow-1.png'
    shadow = QPixmap(str(shadow_file))
    rendered = QPixmap(str(temp_file))
    cropped = rendered.copy(120, 20, 400, 400)
    scaled = cropped.scaled(98,
                            102,
                            Qt.KeepAspectRatio,
                            Qt.SmoothTransformation)

    painter = QPainter(shadow)
    try:
        painter.drawPixmap(7, 2, scaled)
    finally:
        painter.end()
    assert app

    shadow.save(str(temp_shadow_file), 'png')
    temp_file.unlink()
    temp_shadow_file.rename(png_file)
    print(f'Generated {png_file} from {pov_file}.')
Beispiel #18
0
    def paint_puzzle(self, writer: QPaintDevice):
        self.check_clues()
        painter = QPainter(writer)
        try:
            print_shuffler = ArtShuffler(self.art_shuffler.rows,
                                         self.art_shuffler.cols,
                                         writer,
                                         QRect(0, 0, writer.width(),
                                               round(writer.height() / 2)),
                                         clues=self.clues,
                                         row_clues=self.row_clues,
                                         column_clues=self.column_clues)
            print_shuffler.cells = self.art_shuffler.cells[:]
            print_shuffler.is_shuffled = self.art_shuffler.is_shuffled
            selected_pixmap = self.get_selected_pixmap()
            print_shuffler.draw(selected_pixmap, painter)

            print_shuffler.rect.moveTop(writer.height() / 2)
            print_shuffler.draw_grid(selected_pixmap, painter)
        finally:
            painter.end()
    def setIcons(self) -> None:
        settings = QSettings()
        colored = str(settings.value('iconColors', 'True')) == 'True'

        self._icons: Dict[str, QIcon] = {}

        pixmap = QPixmap(str(getRuntimePath('resources/icons/dia.ico')))
        painter = QPainter(pixmap)
        painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
        painter.fillRect(pixmap.rect(), QColor('#427aa1') if colored else QColor('#333333'))
        painter.end()
        self._icons['mod'] = QIcon(pixmap)

        pixmap = QPixmap(str(getRuntimePath('resources/icons/puzzle.ico')))
        painter = QPainter(pixmap)
        painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
        painter.fillRect(pixmap.rect(), QColor('#aad576') if colored else QColor('#333333'))
        painter.end()
        self._icons['dlc'] = QIcon(pixmap)

        pixmap = QPixmap(str(getRuntimePath('resources/icons/folder.ico')))
        painter = QPainter(pixmap)
        painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
        painter.fillRect(pixmap.rect(), QColor('#E55934') if colored else QColor('#333333'))
        painter.end()
        self._icons['bin'] = QIcon(pixmap)

        pixmap = QPixmap(str(getRuntimePath('resources/icons/patch.ico')))
        painter = QPainter(pixmap)
        painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
        painter.fillRect(pixmap.rect(), QColor('#b08968') if colored else QColor('#333333'))
        painter.end()
        self._icons['pat'] = QIcon(pixmap)

        pixmap = QPixmap(str(getRuntimePath('resources/icons/question.ico')))
        painter = QPainter(pixmap)
        painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
        painter.fillRect(pixmap.rect(), QColor('#ffcf40') if colored else QColor('#333333'))
        painter.end()
        self._icons['udf'] = QIcon(pixmap)
Beispiel #20
0
        def paintEvent(self, event):
            painter = QPainter(self)
            painter.fillRect(event.rect(), self.numberBarColor)

            block = self.editor.firstVisibleBlock()

            # Iterate over all visible text blocks in the document.
            while block.isValid():
                blockNumber = block.blockNumber()
                block_top = self.editor.blockBoundingGeometry(
                    block).translated(self.editor.contentOffset()).top()

                # Check if the position of the block is out side of the visible area.
                if not block.isVisible() or block_top >= event.rect().bottom():
                    break

                # We want the line number for the selected line to be bold.
                if blockNumber == self.editor.textCursor().blockNumber():
                    self.font.setBold(True)
                    painter.setPen(bnstyles["blockSelected"])
                else:
                    self.font.setBold(False)
                    painter.setPen(bnstyles["blockNormal"])
                painter.setFont(self.font)

                # Draw the line number right justified at the position of the line.
                paint_rect = QRect(0, block_top, self.width(),
                                   self.editor.fontMetrics().height())
                painter.drawText(paint_rect, Qt.AlignLeft,
                                 str(blockNumber + 1))

                block = block.next()

            painter.end()

            QWidget.paintEvent(self, event)
    def paintEvent(self, event):
        super(MouseEventMixin, self).paintEvent(event)

        if not self.__image:
            return

        if self.__image.height() == 0 or self.height(
        ) == 0 or self.__image.width() == 0:
            return

        image_aspect_ratio = self.__image.width() / self.__image.height()
        view_aspect_ratio = self.width() / self.height()
        if view_aspect_ratio <= image_aspect_ratio:
            image_height = self.width() / image_aspect_ratio
            rect = QRectF(0, (self.height() - image_height) / 2, self.width(),
                          image_height)
        else:
            image_widh = self.height() * image_aspect_ratio
            rect = QRectF((self.width() - image_widh) / 2, 0, image_widh,
                          self.height())

        painter = QPainter(self.viewport())
        painter.drawImage(rect, self.__image)
        painter.end()
    def setupMenu(self) -> None:
        self.setMenuBar(QMenuBar(self))
        settings = QSettings()

        # mods menu

        menuMods: QMenu = self.menuBar().addMenu('&Mods')

        downIcon = QIcon(str(getRuntimePath('resources/icons/down.ico')))
        gearIcon = QIcon(str(getRuntimePath('resources/icons/gear.ico')))
        dirsIcon = QIcon(str(
            getRuntimePath('resources/icons/open-folder.ico')))
        colrIcon = QIcon(
            str(getRuntimePath('resources/icons/color-circle.ico')))
        smilIcon = QIcon(str(getRuntimePath('resources/icons/smile.ico')))

        actionAddModFromFile = menuMods.addAction('&Add Mods')
        actionAddModFromFile.triggered.connect(self.showAddModFromFileDialog)
        actionAddModFromFolder = menuMods.addAction('Add u&npacked Mod')
        actionAddModFromFolder.triggered.connect(
            self.showAddModFromFolderDialog)
        actionDownloadMod = menuMods.addAction('&Download Mod')
        actionDownloadMod.setIcon(downIcon)
        actionDownloadMod.triggered.connect(self.showDownloadModDialog)

        menuMods.addSeparator()
        actionGetInfo = menuMods.addAction('Update Mod de&tails')
        actionGetInfo.setIcon(downIcon)
        actionGetInfo.triggered.connect(self.showGetInfoDialog)
        actionGetUpdates = menuMods.addAction('Check for Mod &updates')
        actionGetUpdates.setIcon(downIcon)
        actionGetUpdates.triggered.connect(self.showGetUpdatesDialog)

        menuMods.addSeparator()
        actionExport = menuMods.addAction('&Export Modlist')
        actionExport.triggered.connect(self.showExportDialog)

        menuMods.aboutToShow.connect(lambda: [
            actionDownloadMod.setDisabled(not str(settings.value('nexusAPIKey'))),
            actionGetInfo.setDisabled(
                not str(settings.value('nexusAPIKey')) or \
                not len(self.model) or \
                not self.mainwidget.modlist.selectionModel().hasSelection()),
            actionGetUpdates.setDisabled(
                not str(settings.value('nexusAPIKey')) or \
                not len(self.model) or \
                not self.mainwidget.modlist.selectionModel().hasSelection()),
            actionExport.setDisabled(not len(self.model))
        ])

        # view menu

        menuView: QMenu = self.menuBar().addMenu('&View')

        showSummary = menuView.addAction('Show &Summary')
        showSummary.setCheckable(True)
        showSummary.setChecked(settings.value('showSummary', 'True') == 'True')
        showSummary.triggered.connect(lambda checked: [
            settings.setValue('showSummary', str(checked)),
            self.mainwidget.summary.setVisible(checked)
        ])
        menuView.addSeparator()

        toggleHighlightNewest = menuView.addAction('Highlight &Newest')
        toggleHighlightNewest.setCheckable(True)
        toggleHighlightNewest.setChecked(
            settings.value('highlightNewest', 'True') == 'True')
        toggleHighlightNewest.triggered.connect(lambda checked: [
            settings.setValue('highlightNewest', str(checked)),
            self.model.updateCallbacks.fire(self.model)
        ])
        iconHighlightNewest = QPixmap(256, 256)
        iconHighlightNewest.fill(Qt.transparent)
        painter = QPainter(iconHighlightNewest)
        painter.setBrush(QBrush(QColor(222, 255, 222)))
        painter.drawEllipse(10, 10, 236, 236)
        toggleHighlightNewest.setIcon(QIcon(iconHighlightNewest))
        painter.end()

        toggleHighlightRecent = menuView.addAction('Highlight &Recent')
        toggleHighlightRecent.setCheckable(True)
        toggleHighlightRecent.setChecked(
            settings.value('highlightRecent', 'True') == 'True')
        toggleHighlightRecent.triggered.connect(lambda checked: [
            settings.setValue('highlightRecent', str(checked)),
            self.model.updateCallbacks.fire(self.model)
        ])
        iconHighlightRecent = QPixmap(256, 256)
        iconHighlightRecent.fill(Qt.transparent)
        painter = QPainter(iconHighlightRecent)
        painter.setBrush(QBrush(QColor(222, 226, 255)))
        painter.drawEllipse(10, 10, 236, 236)
        toggleHighlightRecent.setIcon(QIcon(iconHighlightRecent))
        painter.end()

        toggleHighlightUnmanaged = menuView.addAction('Highlight &Unmanaged')
        toggleHighlightUnmanaged.setCheckable(True)
        toggleHighlightUnmanaged.setChecked(
            settings.value('highlightUnmanaged', 'True') == 'True')
        toggleHighlightUnmanaged.triggered.connect(lambda checked: [
            settings.setValue('highlightUnmanaged', str(checked)),
            self.model.updateCallbacks.fire(self.model)
        ])
        iconHighlightUnmanaged = QPixmap(256, 256)
        iconHighlightUnmanaged.fill(Qt.transparent)
        painter = QPainter(iconHighlightUnmanaged)
        painter.setBrush(QBrush(QColor(250, 220, 220)))
        painter.drawEllipse(10, 10, 236, 236)
        toggleHighlightUnmanaged.setIcon(QIcon(iconHighlightUnmanaged))
        painter.end()

        toggleHighlightDisabled = menuView.addAction('Highlight &Disabled')
        toggleHighlightDisabled.setCheckable(True)
        toggleHighlightDisabled.setChecked(
            settings.value('highlightDisabled', 'True') == 'True')
        toggleHighlightDisabled.triggered.connect(lambda checked: [
            settings.setValue('highlightDisabled', str(checked)),
            self.model.updateCallbacks.fire(self.model)
        ])
        iconHighlightDisabled = QPixmap(256, 256)
        iconHighlightDisabled.fill(Qt.transparent)
        painter = QPainter(iconHighlightDisabled)
        painter.setBrush(QBrush(QColor(230, 230, 230)))
        painter.drawEllipse(10, 10, 236, 236)
        toggleHighlightDisabled.setIcon(QIcon(iconHighlightDisabled))
        painter.end()

        menuView.addSeparator()
        toggleColors = menuView.addAction('&Colored Icons')
        toggleColors.setCheckable(True)
        toggleColors.setChecked(settings.value('iconColors', 'True') == 'True')
        toggleColors.triggered.connect(lambda checked: [
            settings.setValue('iconColors', str(checked)),
            self.mainwidget.modlist.listmodel.setIcons(),
            self.model.updateCallbacks.fire(self.model)
        ])
        toggleColors.setIcon(colrIcon)

        menuView.addSeparator()
        toggleCompact = menuView.addAction('Compact &Mode')
        toggleCompact.setCheckable(True)
        toggleCompact.setChecked(
            settings.value('compactMode', 'False') == 'True')
        toggleCompact.triggered.connect(lambda checked: [
            settings.setValue('compactMode', str(checked)),
            self.mainwidget.modlist.setSectionSize(checked)
        ])

        # settings menu

        menuSettings: QMenu = self.menuBar().addMenu('&Tools')
        actionSettings = menuSettings.addAction('&Settings')
        actionSettings.setIcon(gearIcon)
        actionSettings.triggered.connect(self.showSettingsDialog)

        menuSettings.addSeparator()
        actionOpenGameDirectory = menuSettings.addAction(
            'Open &Game directory')
        actionOpenGameDirectory.setIcon(dirsIcon)
        actionOpenGameDirectory.triggered.connect(
            lambda: util.openDirectory(self.model.gamepath))
        actionOpenConfigDirectory = menuSettings.addAction(
            'Open &Config directory')
        actionOpenConfigDirectory.setIcon(dirsIcon)
        actionOpenConfigDirectory.triggered.connect(
            lambda: util.openDirectory(self.model.configpath))

        # info menu

        menuInfo: QMenu = self.menuBar().addMenu('&Info')

        actionFeedback = menuInfo.addAction('Send &Feedback')
        actionFeedback.setIcon(smilIcon)
        actionFeedback.triggered.connect(
            lambda: QDesktopServices.openUrl(QUrl(w3modmanager.URL_ISSUES)))
        menuInfo.addSeparator()
        actionAbout = menuInfo.addAction('&About')
        actionAbout.setIcon(QIcon.fromTheme('document-open'))
        actionAbout.triggered.connect(self.showAboutDialog)
Beispiel #23
0
    def paintEvent(self, pe) -> None:
        if not self.inhibit_paint:

            extent = 1.5 * np.pi
            offset = 1.25 * np.pi

            painter = QPainter(self)

            # So that we can use the background color
            painter.setBackgroundMode(Qt.OpaqueMode)

            # Smooth out the circle
            painter.setRenderHint(QPainter.Antialiasing)

            # Use background color
            bgColor = painter.background().color()
            painter.setBrush(painter.background())
            if self._text not in implementedKnobs:
                painter.setBrush(QtGui.QBrush(QtGui.QColor(int("0xcccccc",
                                                               0))))

            # Store color from stylesheet, pen will be overridden
            pointColor = QColor(painter.pen().color())

            # print(QDial.width(self), QDial.height(self))

            # draw widget borders
            pen = QPen(QColor(self._ringColor), 1)
            pen.setCapStyle(Qt.SquareCap)
            painter.setPen(pen)
            # uncomment the following line to draw outer rect
            # painter.drawRect(0, 0, np.floor(QDial.width(self)), QDial.height(self))

            # No border
            painter.setPen(QPen(Qt.NoPen))

            # the heignt of the widget is 2*radius + 2*fontsize1 + 2*fontsize2
            # where fontsize1 = .4radius and fontsize2 = .9*.4*radius
            # so QDial.height = radius * (2+.4*2+.4*.9*2)
            #

            fontsize1factor = .4
            fontsize2reduction = .9
            fontsize2factor = fontsize1factor * fontsize2reduction

            center_x = QDial.width(self) / 2.0
            center_y = QDial.height(self) / 2.0

            if not self._hasFixedSize:
                if not self._hasFixedFontSize:
                    radius = np.min(
                        (QDial.width(self) / 2. - self._knobMargin,
                         QDial.height(self) /
                         (2. + 2 * fontsize1factor + 2 * fontsize2factor) -
                         self._knobMargin))
                    radius = np.max((radius, 1))
                    # print("Radius = ", radius, ", height = ", QDial.height(self), ", width = ", QDial.width(self))
                    center_y = center_y - radius * (fontsize1factor +
                                                    fontsize2factor)
                else:
                    radius = np.min(
                        (QDial.width(self) / 2. - self._knobMargin,
                         (QDial.height(self) - 4 * self._fixedFontSize) / 2. -
                         self._knobMargin))
                    radius = np.max((radius, 1))
                    center_y = center_y - (self._fixedFontSize *
                                           (1 + fontsize2reduction))
            else:
                radius = self._fixedSize / 2.
                radius = np.max((radius, 1))
                center_y = center_y - radius * (fontsize1factor +
                                                fontsize2factor)

            self.radius = radius

            # Draw arc
            rectangle = QtCore.QRectF(center_x - radius, center_y - radius,
                                      2 * radius, 2 * radius)
            """The startAngle and spanAngle must be specified in 1/16th of a degree, 
			i.e. a full circle equals 5760 (16 * 360). 
			Positive values for the angles mean counter-clockwise 
			while negative values mean the clockwise direction. 
			Zero degrees is at the 3 o'clock position."""

            linewidth = radius / 30. * 2

            # linewidth = 1
            pen = QPen(QColor(self._ringColor), linewidth)
            pen.setCapStyle(Qt.RoundCap)
            # pen.setCapStyle(Qt.FlatCap)

            painter.setPen(pen)

            # adapt to linewidth to make it more pleasant to the eye
            capRadius = linewidth / 4
            angleCap = np.arcsin(capRadius / radius)

            start_deg = (90 - np.rad2deg(extent / 2)) + np.rad2deg(angleCap)
            start_16deg = start_deg * 16

            extent_deg = np.rad2deg(extent) - 2 * np.rad2deg(angleCap)
            extent_16deg = extent_deg * 16

            painter.drawArc(rectangle, start_16deg, extent_16deg)

            #draw inner circle
            pen = QPen(QColor(pointColor), linewidth)
            pen.setCapStyle(Qt.RoundCap)

            painter.setPen(pen)
            painter.setBrush(QtGui.QColor(bgColor))

            radius_inner = 15. / 20. * radius
            painter.drawEllipse(QtCore.QPointF(center_x, center_y),
                                radius_inner, radius_inner)

            self.center = QtCore.QPointF(center_x, center_y)
            """
			# Get ratio between current value and maximum to calculate angle
			if (param != NULL):
				if (param->value != this->value()) 
					param->setValue(this->value())
			"""
            ratio = (QDial.value(self) - QDial.minimum(self)) / (
                QDial.maximum(self) - QDial.minimum(self))

            # The maximum amount of degrees is 270, offset by 225
            angle = ratio * extent - offset

            # Draw the indicator
            painter.setBrush(QBrush(pointColor))

            a_y = center_y + np.sin(angle) * (radius - .1)
            a_x = center_x + np.cos(angle) * (radius - .1)

            pen = QPen(pointColor, linewidth)
            pen.setCapStyle(Qt.RoundCap)
            painter.setPen(pen)

            painter.drawLine(a_x, a_y, np.round(center_x), center_y)

            if not self._hasFixedFontSize:
                fontsize1 = radius * fontsize1factor
                if self.sizeType == 1 and fontsize1 != Knob.fontsize1:
                    Knob.fontsize1 = fontsize1
                else:
                    fontsize1 = Knob.fontsize1
                fontsize2 = fontsize1 * fontsize2reduction
            else:
                fontsize1 = self._fixedFontSize
                fontsize2 = fontsize1 * fontsize2reduction

            self.fontsize1 = fontsize1

            textRect_ = QtCore.QRectF(0, center_y + radius, QDial.width(self),
                                      2 * fontsize1)

            if self.coloredTitle:
                painter.setPen(QColor(int(titleColor, 0)))

            f = painter.font()
            f.setPointSizeF(fontsize1)
            painter.setFont(f)
            # painter.drawRect(textRect_)
            painter.drawText(textRect_, Qt.AlignHCenter | Qt.AlignTop,
                             self._text)
            # painter.drawText(textRect_, Qt.AlignHCenter | Qt.AlignTop, str(fontsize1))

            textRect_ = QtCore.QRectF(0, center_y + radius + fontsize1 * 2,
                                      QDial.width(self), 2 * fontsize2)

            if self.hasFocus():
                painter.setPen(QtGui.QColor("red"))

            f.setPointSizeF(fontsize2)
            painter.setFont(f)
            # painter.drawRect(textRect_)
            painter.drawText(textRect_, Qt.AlignHCenter | Qt.AlignTop,
                             str(QDial.value(self)))

            painter.end()
Beispiel #24
0
class ScreenSelection(QtWidgets.QGroupBox):
    def __init__(self, parent: DisplayCalibration):
        QtWidgets.QGroupBox.__init__(self,
                                     'Fullscreen selection (double click)')
        self.main = parent

        self.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding,
                           QtWidgets.QSizePolicy.Policy.Expanding)

        self.painter = QPainter()

    def mouseDoubleClickEvent(self, ev, *args, **kwargs):
        for screen_id, screen_coords in enumerate(
                self._get_widget_screen_coords()):
            rect = QtCore.QRectF(*screen_coords)

            if not rect.contains(QtCore.QPoint(ev.pos().x(), ev.pos().y())):
                continue

            print(f'Set display to fullscreen on screen {screen_id}')

            screen = access.application.screens()[screen_id]
            px_ratio = screen.devicePixelRatio()
            self.main.global_settings.screen_id.set_value(screen_id)
            self.main.global_settings.win_x_pos.set_value(
                screen.geometry().x())
            self.main.global_settings.win_y_pos.set_value(
                screen.geometry().y())
            self.main.global_settings.win_width.set_value(
                int(screen.geometry().width() * px_ratio))
            self.main.global_settings.win_height.set_value(
                int(screen.geometry().height() * px_ratio))

            access.application.processEvents()

    @staticmethod
    def _get_norm_screen_coords() -> np.ndarray:

        # Get connected screens
        avail_screens = access.application.screens()

        # Calculate total display area bounding box
        area = [[
            s.geometry().width() * s.devicePixelRatio(),
            s.geometry().height() * s.devicePixelRatio()
        ] for s in avail_screens]
        area = np.sum(area, axis=0)

        xmin = np.min([s.geometry().x() for s in avail_screens])
        ymin = np.min([s.geometry().y() for s in avail_screens])

        # Define normalization functions
        xnorm = lambda x: (x - xmin) / area[0]
        ynorm = lambda y: (y - ymin) / area[1]

        # Add screen dimensions
        screens = []
        for s in avail_screens:
            g = s.geometry()
            screens.append([
                xnorm(g.x() * s.devicePixelRatio()),  # x
                ynorm(g.y() * s.devicePixelRatio()),  # y
                xnorm(g.width() * s.devicePixelRatio()),  # width
                ynorm(g.height() * s.devicePixelRatio())
            ])  # height

        return np.array(screens)

    def _get_widget_screen_coords(self):
        s = self._get_norm_screen_coords()
        s[:, 0] *= self.size().width()
        s[:, 1] *= self.size().height()
        s[:, 2] *= self.size().width()
        s[:, 3] *= self.size().height()

        return s.astype(int)

    def paintEvent(self, QPaintEvent):

        for i, screen in enumerate(self._get_widget_screen_coords()):

            rect = QtCore.QRect(*screen)

            self.painter.begin(self)

            self.painter.setBrush(QtCore.Qt.BrushStyle.Dense4Pattern)
            self.painter.drawRect(rect)

            self.painter.setPen(QColor(168, 34, 3))
            self.painter.setFont(QFont('Decorative', 30))
            self.painter.drawText(rect, QtCore.Qt.AlignmentFlag.AlignCenter,
                                  str(i))

            self.painter.end()
Beispiel #25
0
    def paintEvent(self, event):

        paint = QPainter()
        paint.begin(self)
        paint.save()

        size = self.size()
        width = size.width()
        height = size.height()
        units = self.data.get('units')

        proportion = self.getProportion()

        horizontalOrientation = self.data.get('horizontal_orientation')

        if horizontalOrientation:

            rulerLength = width
            traceLengthLimit = height

        else:  # vertical orientation
            rulerLength = height
            traceLengthLimit = width

            paint.translate(width, 0)
            paint.rotate(90)

            # the length of the traces (lines)
        small = traceLengthLimit / 6
        medium = traceLengthLimit / 4
        large = traceLengthLimit / 3

        limit = rulerLength / proportion

        # draw less lines for centimeters
        if units == 'cm':
            step = 10

        else:
            step = 5

        # begin drawing
        fontSize = 10
        font = QFont('Serif', fontSize)
        fontMetrics = QFontMetrics(font)

        # draw background
        background = self.data.get('background_color')
        paint.fillRect(0, 0, rulerLength, traceLengthLimit, background)

        # draw the lines
        paint.setPen(self.data.get('lines_color'))
        paint.setFont(font)

        # the builtin range() doesn't support floats
        def float_range(current, end, rangeStep):
            while current < end:
                yield current
                current += rangeStep

            # we skip 0 and start in the first step, since there's no point in drawing the first line/text (it would appear cut off, since we're at the limit)

        for a in float_range(step, limit, step):

            position = a * proportion

            if (a % 100) == 0:
                lineLength = large

                if units == 'px':
                    text = '{}{}'.format(str(a), units)
                else:
                    text = '{}{}'.format(str(int(a / 100)), units)

                textWidth = fontMetrics.boundingRect(text).width()

                paint.drawText(position - textWidth / 2,
                               traceLengthLimit / 2 + fontSize / 2, text)

            elif (a % 50) == 0:
                lineLength = large

                # since 'cm' has a different step compared to the other units
                if units == 'cm':
                    lineLength = medium

            elif (a % 25) == 0:
                lineLength = medium

            else:
                lineLength = small

            paint.drawLine(position, 0, position, lineLength)
            paint.drawLine(position, traceLengthLimit, position,
                           traceLengthLimit - lineLength)

        # paint the division lines

        if self.data.get('division_lines'):
            paint.setPen(self.data.get('divisions_color'))
            halfPoint = rulerLength / 2
            quarterPoint = rulerLength / 4
            threeQuarterPoint = 3 / 4 * rulerLength

            paint.drawLine(quarterPoint, 0, quarterPoint, traceLengthLimit)
            paint.drawLine(halfPoint, 0, halfPoint, traceLengthLimit)
            paint.drawLine(threeQuarterPoint, 0, threeQuarterPoint,
                           traceLengthLimit)

        paint.restore()
        paint.end()
def test_board_size_3(pixmap_differ: PixmapDiffer):
    actual: QPainter
    expected: QPainter
    with pixmap_differ.create_painters(240, 240,
                                       'margo_board_size_3') as (actual,
                                                                 expected):
        expected_scene = QGraphicsScene(0, 0, 240, 240)
        full_board = MargoDisplay.load_pixmap('board-1.png')
        width = full_board.width()
        height = full_board.height()
        top_height = round(height * 0.28)
        mid_height = round(height * 0.21)
        bottom_height = round(height * 0.29)
        left_width = round(width * 0.28)
        mid_width = round(width * 0.22)
        right_width = round(width * 0.279)
        assembled_board = QPixmap(left_width + mid_width + right_width,
                                  top_height + mid_height + bottom_height)
        assembled_board.fill(Qt.transparent)
        assembled_painter = QPainter(assembled_board)
        # top left
        assembled_painter.drawPixmap(0, 0, left_width, top_height, full_board,
                                     0, 0, left_width, top_height)
        # top middle
        assembled_painter.drawPixmap(left_width, 0, mid_width, top_height,
                                     full_board, left_width, 0, mid_width,
                                     top_height)
        # top right
        assembled_painter.drawPixmap(left_width + mid_width, 0, right_width,
                                     top_height, full_board,
                                     width - right_width, 0, right_width,
                                     top_height)
        # left middle
        assembled_painter.drawPixmap(0, top_height, left_width, mid_height,
                                     full_board, 0, top_height, left_width,
                                     mid_height)
        # middle middle
        assembled_painter.drawPixmap(left_width, top_height, mid_width,
                                     mid_height, full_board, left_width,
                                     top_height, mid_width, mid_height)
        # right middle
        assembled_painter.drawPixmap(left_width + mid_width, top_height,
                                     right_width, mid_height, full_board,
                                     width - right_width, top_height,
                                     right_width, mid_height)
        # bottom left
        assembled_painter.drawPixmap(0, top_height + mid_height, left_width,
                                     bottom_height, full_board, 0,
                                     height - bottom_height, left_width,
                                     bottom_height)
        # bottom middle
        assembled_painter.drawPixmap(left_width, top_height + mid_height,
                                     mid_width, bottom_height, full_board,
                                     left_width, height - bottom_height,
                                     mid_width, bottom_height)
        # bottom right
        assembled_painter.drawPixmap(left_width + mid_width,
                                     top_height + mid_height, right_width,
                                     bottom_height, full_board,
                                     width - right_width,
                                     height - bottom_height, right_width,
                                     bottom_height)
        assembled_painter.end()
        scaled_board = assembled_board.scaled(240, 240, Qt.KeepAspectRatio,
                                              Qt.SmoothTransformation)
        board_item = expected_scene.addPixmap(scaled_board)
        board_item.setPos(2, 0)
        white_ball = MargoDisplay.load_pixmap('ball-w-shadow-1.png',
                                              QSize(76, 76))
        black_ball = MargoDisplay.load_pixmap('ball-b-shadow-1.png',
                                              QSize(76, 76))

        expected_scene.addPixmap(white_ball).setPos(15, 145)
        expected_scene.addPixmap(black_ball).setPos(81, 79)
        expected_scene.render(expected)

        display = MargoDisplay(size=3)
        display.resize(348, 264)

        board_text = """\
  A C E
5 . . . 5

3 . B . 3

1 W . . 1
  A C E
>B
"""
        display.update_board(SpargoState(board_text, size=3))

        render_display(display, actual)
Beispiel #27
0
class PixmapDiffer:
    def __init__(self):
        self.name = None
        self.actual_pixmap = self.expected_pixmap = None
        self.actual = self.expected = None
        self.different_pixels = 0
        self.diff_min_x = self.diff_min_y = None
        self.diff_max_x = self.diff_max_y = None
        self.max_diff = 0

        self.names = set()

        self.work_dir: Path = (Path(__file__).parent.parent / 'tests' /
                               'pixmap_diffs')
        self.work_dir.mkdir(exist_ok=True)
        for work_file in self.work_dir.iterdir():
            if work_file.name == 'README.md':
                continue
            assert work_file.suffix == '.png', work_file
            work_file.unlink()

    @contextmanager
    def create_painters(self,
                        width: int,
                        height: int,
                        name: str,
                        max_diff: int = 0
                        ) -> typing.Iterator[typing.Tuple[QPainter, QPainter]]:
        self.max_diff = max_diff
        try:
            yield self.start(width, height, name)
        finally:
            self.end()
        self.assert_equal()

    def start(self, width: int, height: int,
              name: str) -> typing.Tuple[QPainter, QPainter]:
        """ Create painters for the actual and expected images.

        Caller must either call end() or assert_equal() to properly clean up
        the painters and pixmaps. Caller may either paint through the returned
        painters, or call the end() method and create a new painter on the
        same device. Order matters, though!
        """
        assert name not in self.names, f'Duplicate name: {name!r}.'
        self.names.add(name)
        self.name = name

        white = QColor('white')
        self.actual_pixmap = QPixmap(width, height)
        self.actual_pixmap.fill(white)
        self.actual = QPainter(self.actual_pixmap)
        self.expected_pixmap = QPixmap(width, height)
        self.expected_pixmap.fill(white)
        self.expected = QPainter(self.expected_pixmap)

        return self.actual, self.expected

    def end(self):
        if self.actual and self.actual.isActive():
            self.actual.end()
        if self.expected and self.expected.isActive():
            self.expected.end()

    def assert_equal(self):
        __tracebackhide__ = True
        self.end()
        self.different_pixels = 0
        actual_image: QImage = self.actual.device().toImage()
        expected_image: QImage = self.expected.device().toImage()
        diff_pixmap = QPixmap(actual_image.width(), actual_image.height())
        diff = QPainter(diff_pixmap)
        try:
            white = QColor('white')
            diff.fillRect(0, 0, actual_image.width(), actual_image.height(),
                          white)
            for x in range(actual_image.width()):
                for y in range(actual_image.height()):
                    actual_colour = actual_image.pixelColor(x, y)
                    expected_colour = expected_image.pixelColor(x, y)
                    diff.setPen(
                        self.diff_colour(actual_colour, expected_colour, x, y))
                    diff.drawPoint(x, y)
        finally:
            diff.end()
        diff_image: QImage = diff.device().toImage()

        display_diff(actual_image, diff_image, expected_image,
                     self.different_pixels)

        if self.different_pixels == 0:
            return
        actual_image.save(str(self.work_dir / (self.name + '_actual.png')))
        expected_image.save(str(self.work_dir / (self.name + '_expected.png')))
        diff_path = self.work_dir / (self.name + '_diff.png')
        is_saved = diff_image.save(str(diff_path))
        diff_width = self.diff_max_x - self.diff_min_x + 1
        diff_height = self.diff_max_y - self.diff_min_y + 1
        diff_section = QImage(diff_width, diff_height, QImage.Format_RGB32)
        diff_section_painter = QPainter(diff_section)
        try:
            diff_section_painter.drawPixmap(0, 0, diff_width, diff_height,
                                            QPixmap.fromImage(diff_image),
                                            self.diff_min_x, self.diff_min_y,
                                            diff_width, diff_height)
        finally:
            diff_section_painter.end()
        # To see an image dumped in the Travis CI log, copy the text from the
        # log, and paste it in test_pixmap_differ.test_decode_image.
        print(f'Encoded image of differing section '
              f'({self.diff_min_x}, {self.diff_min_y}) - '
              f'({self.diff_max_x}, {self.diff_max_y}):')
        print(encode_image(diff_section))
        message = f'Found {self.different_pixels} different pixels, '
        message += f'see' if is_saved else 'could not write'
        message += f' {diff_path.relative_to(Path(__file__).parent.parent)}.'
        assert self.different_pixels == 0, message

    def diff_colour(self, actual_colour: QColor, expected_colour: QColor,
                    x: int, y: int):
        diff_size = (abs(actual_colour.red() - expected_colour.red()) +
                     abs(actual_colour.green() - expected_colour.green()) +
                     abs(actual_colour.blue() - expected_colour.blue()))
        if diff_size <= self.max_diff:
            diff_colour = actual_colour.toRgb()
            diff_colour.setAlpha(diff_colour.alpha() // 3)
            return diff_colour
        if self.different_pixels == 0:
            self.diff_min_x = self.diff_max_x = x
            self.diff_min_y = self.diff_max_y = y
        else:
            self.diff_min_x = min(self.diff_min_x, x)
            self.diff_max_x = max(self.diff_max_x, x)
            self.diff_min_y = min(self.diff_min_y, y)
            self.diff_max_y = max(self.diff_max_y, y)

        self.different_pixels += 1
        # Colour
        dr = 0xff
        dg = (actual_colour.green() + expected_colour.green()) // 5
        db = (actual_colour.blue() + expected_colour.blue()) // 5

        # Opacity
        da = 0xff
        return QColor(dr, dg, db, da)
def test_board_size_2(pixmap_differ: PixmapDiffer):
    actual: QPainter
    expected: QPainter
    with pixmap_differ.create_painters(240, 240,
                                       'margo_board_size_2') as (actual,
                                                                 expected):
        expected_scene = QGraphicsScene(0, 0, 240, 240)
        full_board = MargoDisplay.load_pixmap('board-1.png')
        width = full_board.width()
        height = full_board.height()
        top_height = round(height * 0.28)
        left_width = round(width * 0.28)
        right_width = round(width * 0.279)
        bottom_height = round(height * 0.29)
        assembled_board = QPixmap(left_width + right_width,
                                  top_height + bottom_height)
        assembled_board.fill(Qt.transparent)
        assembled_painter = QPainter(assembled_board)
        # top left
        assembled_painter.drawPixmap(0, 0, left_width, top_height, full_board,
                                     0, 0, left_width, top_height)
        # top right
        assembled_painter.drawPixmap(left_width, 0, right_width, top_height,
                                     full_board, width - right_width, 0,
                                     right_width, top_height)
        # bottom left
        assembled_painter.drawPixmap(0, top_height, left_width, bottom_height,
                                     full_board, 0, height - bottom_height,
                                     left_width, bottom_height)
        # bottom right
        assembled_painter.drawPixmap(left_width, top_height, right_width,
                                     bottom_height, full_board,
                                     width - right_width,
                                     height - bottom_height, right_width,
                                     bottom_height)
        assembled_painter.end()
        scaled_board = assembled_board.scaled(232, 240, Qt.KeepAspectRatio,
                                              Qt.SmoothTransformation)
        board_item = expected_scene.addPixmap(scaled_board)
        board_item.setPos(4, 0)
        white_ball = MargoDisplay.load_pixmap('ball-w-shadow-1.png',
                                              QSize(103, 103))
        black_ball = MargoDisplay.load_pixmap('ball-b-shadow-1.png',
                                              QSize(103, 103))

        expected_scene.addPixmap(white_ball).setPos(23, 108)
        expected_scene.addPixmap(black_ball).setPos(113, 18)
        expected_scene.render(expected)

        display = MargoDisplay(size=2)

        trigger_resize(display, 292, 240)
        display.resize(348, 264)
        board_text = """\
  A C
3 . B 3

1 W . 1
  A C
>B
"""
        display.update_board(SpargoState(board_text, size=2))

        render_display(display, actual)