def _create_pixmap(self, path, color):
        """
        Internal function that creates a new item pixmap from the given path
        :param path: str
        :param color: str or QColor
        :return: QPixmap
        """

        if not path:
            return QPixmap()

        dpi = self.treeWidget().dpi()
        key = path + color + 'DPI-' + str(dpi)
        item_pixmap = self._PIXMAP_CACHE.get(key)
        if not item_pixmap:
            width = 20 * dpi
            height = 18 * dpi
            if '/' not in path and '\\' not in path:
                path = resources.get('icons', path)
            if not path or not os.path.exists(path):
                path = self.default_icon_path()
            pixmap2 = pixmap.Pixmap(path)
            pixmap2.set_color(color)
            pixmap2 = pixmap2.scaled(16 * dpi, 16 * dpi, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            x = (width - pixmap2.width()) / 2
            y = (height - pixmap2.height()) / 2
            item_pixmap = QPixmap(QSize(width, height))
            item_pixmap.fill(Qt.transparent)
            painter = QPainter(item_pixmap)
            painter.drawPixmap(x, y, pixmap2)
            painter.end()
            self._PIXMAP_CACHE[key] = item_pixmap

        return item_pixmap
Beispiel #2
0
def create_empty_image(output=None,
                       resolution_x=1920,
                       resolution_y=1080,
                       background_color=None):
    """
    Creates an empty image and stores it in the given path
    :param output: str
    :param resolution_x: int
    :param resolution_y: int
    :param background_color: list(int, int, int)
    :return: str or QImage
    """

    if background_color is None:
        background_color = [0, 0, 0]

    pixmap = QPixmap(resolution_x, resolution_y)
    pixmap.fill(QColor(*background_color))
    if output:
        output_path = path_utils.clean_path(output)
        output_dir = os.path.dirname(output_path)
        if os.access(output_dir, os.W_OK):
            pixmap.save(output_path)
            return output_path

    return QImage(pixmap)
Beispiel #3
0
def tint_pixmap(pixmap, tint_color=(255, 255, 255, 100), composition_mode=QPainter.CompositionMode_Plus):
    """
    Composite one pixmap on top of another
    :param pixmap:
    :param tint_color:
    :param composition_mode:
    :return:
    """

    tint_color = QColor(*tint_color)
    over_pixmap = QPixmap(pixmap.width(), pixmap.height())
    over_pixmap.fill(tint_color)
    over_pixmap.setMask(pixmap.mask())
    painter = QPainter(pixmap)
    painter.setCompositionMode(composition_mode)
    painter.drawPixmap(0, 0, over_pixmap.width(), over_pixmap.height(), over_pixmap)
    painter.end()
Beispiel #4
0
    def _render_svg(self, svg_path, replace_color=None):
        if issubclass(self._cls, QIcon) and not replace_color:
            return QIcon(svg_path)

        with open(svg_path, 'r+') as f:
            data_content = f.read()
            if replace_color is not None:
                data_content = data_content.replace('#555555', replace_color)
                self._render.load(QByteArray(data_content))
                pix = QPixmap(128, 128)
                pix.fill(Qt.transparent)
                painter = QPainter(pix)
                self._render.render(painter)
                painter.end()
                if issubclass(self._cls, QPixmap):
                    return pix
                else:
                    return self._cls(pix)
Beispiel #5
0
    def _setup_general_tab(self):
        general_widget = QWidget()
        general_layout = layouts.VerticalLayout(spacing=2,
                                                margins=(2, 2, 2, 2))
        general_widget.setLayout(general_layout)

        self._themes_combobox = combobox.BaseComboBox(parent=self)
        all_themes = resources.get_all_resources_of_type(
            resources.ResourceTypes.THEME)

        for i, theme in enumerate(all_themes):
            accent_color_hex = theme.accent_color
            accent_color = color.Color.hex_to_qcolor(
                accent_color_hex[1:] if accent_color_hex.
                startswith('#') else accent_color_hex)
            background_color_hex = theme.background_color
            background_color = color.Color.hex_to_qcolor(
                background_color_hex[1:] if accent_color_hex.
                startswith('#') else background_color_hex)
            accent_color_pixmap = QPixmap(25, 25)
            background_color_pixmap = QPixmap(25, 25)
            accent_color_pixmap.fill(accent_color)
            background_color_pixmap.fill(background_color)
            color_pixmap = QPixmap(50, 25)
            painter = QPainter(color_pixmap)
            painter.drawPixmap(0, 0, 25, 25, accent_color_pixmap)
            painter.drawPixmap(25, 0, 25, 25, background_color_pixmap)
            painter.end()

            color_icon = QIcon(color_pixmap)
            self._themes_combobox.addItem(color_icon, theme.name())

        general_layout.addWidget(self._themes_combobox)
        general_layout.addStretch()

        return general_widget
Beispiel #6
0
 def pixmap(self, size, mode, state):
     pm = QPixmap(size)
     pm.fill(Qt.transparent)
     self.paint(QPainter(pm), QRect(QPoint(0, 0), size), mode, state)
     return pm
Beispiel #7
0
    def create_drop_indicator_pixmap(palette, size, drop_area):
        border_color = palette.color(QPalette.Active, QPalette.Highlight)
        background_color = palette.color(QPalette.Active, QPalette.Base)
        area_background_color = palette.color(QPalette.Active,
                                              QPalette.Highlight).lighter(150)

        pm = QPixmap(size.width(), size.height())
        pm.fill(QColor(0, 0, 0, 0))

        painter = QPainter(pm)
        pen = painter.pen()
        base_rect = QRectF(pm.rect())

        painter.fillRect(base_rect, background_color)

        painter.save()
        area_rect = QRectF()
        area_line = QLineF()
        gradient = QLinearGradient()
        if drop_area == DropArea.TopDropArea:
            area_rect = QRectF(base_rect.x(), base_rect.y(), base_rect.width(),
                               base_rect.height() * 0.5)
            area_line = QLineF(area_rect.bottomLeft(), area_rect.bottomRight())
            gradient.setStart(area_rect.topLeft())
            gradient.setFinalStop(area_rect.bottomLeft())
            gradient.setColorAt(0, area_background_color)
            gradient.setColorAt(1, area_background_color.lighter(120))
        elif drop_area == DropArea.RightDropArea:
            area_rect = QRectF(base_rect.width() * 0.5, base_rect.y(),
                               base_rect.width() * 0.5, base_rect.height())
            area_line = QLineF(area_rect.topLeft(), area_rect.bottomLeft())
            gradient.setStart(area_rect.topLeft())
            gradient.setFinalStop(area_rect.topRight())
            gradient.setColorAt(0, area_background_color.lighter(120))
            gradient.setColorAt(1, area_background_color)
        elif drop_area == DropArea.BottomDropArea:
            area_rect = QRectF(base_rect.x(),
                               base_rect.height() * 0.5, base_rect.width(),
                               base_rect.height() * 0.5)
            area_line = QLineF(area_rect.topLeft(), area_rect.topRight())
            gradient.setStart(area_rect.topLeft())
            gradient.setFinalStop(area_rect.bottomLeft())
            gradient.setColorAt(0, area_background_color.lighter(120))
            gradient.setColorAt(1, area_background_color)
        elif drop_area == DropArea.LeftDropArea:
            area_rect = QRectF(base_rect.x(), base_rect.y(),
                               base_rect.width() * 0.5, base_rect.height())
            area_line = QLineF(area_rect.topRight(), area_rect.bottomRight())
            gradient.setStart(area_rect.topLeft())
            gradient.setFinalStop(area_rect.topRight())
            gradient.setColorAt(0, area_background_color)
            gradient.setColorAt(1, area_background_color.lighter(120))

        if area_rect.isValid():
            painter.fillRect(area_rect, gradient)
            pen = painter.pen()
            pen.setColor(border_color)
            pen.setStyle(Qt.DashLine)
            painter.setPen(pen)
            painter.drawLine(area_line)

        painter.restore()

        painter.save()
        pen = painter.pen()
        pen.setColor(border_color)
        pen.setWidth(1)

        painter.setPen(pen)
        painter.drawRect(base_rect.adjusted(0, 0, -pen.width(), -pen.width()))
        painter.restore()

        return pm
Beispiel #8
0
    def paintEvent(self, event: QPaintEvent) -> None:
        p = QPainter(self)
        self.m_normalMap.render(p, event.rect())
        p.setPen(Qt.black)
        p.drawText(
            self.rect(),
            Qt.AlignBottom | Qt.TextWordWrap,
            "Map data CCBYSA 2009 OpenStreetMap.org contributors",
        )
        p.end()

        if self.zoomed:
            dim = min(self.width(), self.height())
            magnifierSize = min(MAX_MAGNIFIER, dim * 2 / 3)
            radius = magnifierSize / 2
            ring = radius - 15
            box = QSize(magnifierSize, magnifierSize)

            if self.maskPixmap.size() != box:
                self.maskPixmap = QPixmap(box)
                self.maskPixmap.fill(Qt.transparent)

                g = QRadialGradient()
                g.setCenter(radius, radius)
                g.setFocalPoint(radius, radius)
                g.setRadius(radius)
                g.setColorAt(1.0, QColor(255, 255, 255, 0))
                g.setColorAt(0.5, QColor(128, 128, 128, 255))

                mask = QPainter(self.maskPixmap)
                mask.setRenderHint(QPainter.Antialiasing)
                mask.setCompositionMode(QPainter.CompositionMode_Source)
                mask.setBrush(g)
                mask.setPen(Qt.NoPen)
                mask.drawRect(self.maskPixmap.rect())
                mask.setBrush(QColor(Qt.transparent))
                mask.drawEllipse(g.center(), ring, ring)
                mask.end()

            center = self.dragPos - QPoint(0, radius)
            center = center + QPoint(0, radius / 2)
            corner = center - QPoint(radius, radius)

            xy = center * 2 - QPoint(radius, radius)

            # only set the dimension to the magnified portion
            if self.zoomPixmap.size() != box:
                zoomPixmap = QPixmap(box)
                zoomPixmap.fill(Qt.lightGray)

            if True:
                p = QPainter(zoomPixmap)
                p.translate(-xy)
                self.m_largeMap.render(p, QRect(xy, box))
                p.end()

            clipPath = QPainterPath()
            clipPath.addEllipse(center, ring, ring)

            p = QPainter(self)
            p.setRenderHint(QPainter.Antialiasing)
            p.setClipPath(clipPath)
            p.drawPixmap(corner, zoomPixmap)
            p.setClipping(False)
            p.drawPixmap(corner, self.maskPixmap)
            p.setPen(Qt.gray)
            p.drawPath(clipPath)
        if self.invert:
            p = QPainter(self)
            p.setCompositionMode(QPainter.CompositionMode_Difference)
            p.fillRect(event.rect(), Qt.white)
            p.end()
Beispiel #9
0
class LightMaps(QWidget):
    def __init__(self, parent: QWidget = None) -> None:
        super().__init__(parent)

        self.m_normalMap = SlippyMap(self)
        self.m_largeMap = SlippyMap(self)
        self.m_normalMap.updated.connect(self.updateMap)
        self.m_largeMap.updated.connect(self.update)
        self.pressed = False
        self.snapped = False
        self.pressPos = QPoint()
        self.dragPos = QPoint()
        self.tapTimer = QBasicTimer()
        self.zoomed = False
        self.zoomPixmap = QPixmap()
        self.maskPixmap = QPixmap()
        self.invert = False

    def setCenter(self, lat: float, lng: float):
        self.m_normalMap.latitude = lat
        self.m_normalMap.longitude = lng
        self.m_normalMap.invalidate()
        self.m_largeMap.latitude = lat
        self.m_largeMap.longitude = lng
        self.m_largeMap.invalidate()

    @Slot()
    def toggleNightMode(self) -> None:
        self.invert = not self.invert
        self.update()

    def activateZoom(self) -> None:
        self.zoomed = True
        self.tapTimer.stop()
        self.m_largeMap.zoom = self.m_normalMap.zoom + 1
        self.m_largeMap.width = self.m_normalMap.width * 2
        self.m_largeMap.height = self.m_normalMap.height * 2
        self.m_largeMap.latitude = self.m_normalMap.latitude
        self.m_largeMap.longitude = self.m_normalMap.longitude
        self.m_largeMap.invalidate()
        self.update()

    def resizeEvent(self, event: QResizeEvent) -> None:
        self.m_normalMap.width = self.width()
        self.m_normalMap.height = self.height()
        self.m_normalMap.invalidate()
        self.m_largeMap.width = self.m_normalMap.width * 2
        self.m_largeMap.height = self.m_normalMap.height * 2
        self.m_largeMap.invalidate()

    def paintEvent(self, event: QPaintEvent) -> None:
        p = QPainter(self)
        self.m_normalMap.render(p, event.rect())
        p.setPen(Qt.black)
        p.drawText(
            self.rect(),
            Qt.AlignBottom | Qt.TextWordWrap,
            "Map data CCBYSA 2009 OpenStreetMap.org contributors",
        )
        p.end()

        if self.zoomed:
            dim = min(self.width(), self.height())
            magnifierSize = min(MAX_MAGNIFIER, dim * 2 / 3)
            radius = magnifierSize / 2
            ring = radius - 15
            box = QSize(magnifierSize, magnifierSize)

            if self.maskPixmap.size() != box:
                self.maskPixmap = QPixmap(box)
                self.maskPixmap.fill(Qt.transparent)

                g = QRadialGradient()
                g.setCenter(radius, radius)
                g.setFocalPoint(radius, radius)
                g.setRadius(radius)
                g.setColorAt(1.0, QColor(255, 255, 255, 0))
                g.setColorAt(0.5, QColor(128, 128, 128, 255))

                mask = QPainter(self.maskPixmap)
                mask.setRenderHint(QPainter.Antialiasing)
                mask.setCompositionMode(QPainter.CompositionMode_Source)
                mask.setBrush(g)
                mask.setPen(Qt.NoPen)
                mask.drawRect(self.maskPixmap.rect())
                mask.setBrush(QColor(Qt.transparent))
                mask.drawEllipse(g.center(), ring, ring)
                mask.end()

            center = self.dragPos - QPoint(0, radius)
            center = center + QPoint(0, radius / 2)
            corner = center - QPoint(radius, radius)

            xy = center * 2 - QPoint(radius, radius)

            # only set the dimension to the magnified portion
            if self.zoomPixmap.size() != box:
                zoomPixmap = QPixmap(box)
                zoomPixmap.fill(Qt.lightGray)

            if True:
                p = QPainter(zoomPixmap)
                p.translate(-xy)
                self.m_largeMap.render(p, QRect(xy, box))
                p.end()

            clipPath = QPainterPath()
            clipPath.addEllipse(center, ring, ring)

            p = QPainter(self)
            p.setRenderHint(QPainter.Antialiasing)
            p.setClipPath(clipPath)
            p.drawPixmap(corner, zoomPixmap)
            p.setClipping(False)
            p.drawPixmap(corner, self.maskPixmap)
            p.setPen(Qt.gray)
            p.drawPath(clipPath)
        if self.invert:
            p = QPainter(self)
            p.setCompositionMode(QPainter.CompositionMode_Difference)
            p.fillRect(event.rect(), Qt.white)
            p.end()

    def timerEvent(self, event: QTimerEvent) -> None:
        if not self.zoomed:
            self.activateZoom()
        self.update()

    def mousePressEvent(self, event: QMouseEvent) -> None:
        if event.buttons() != Qt.LeftButton:
            return
        self.pressed = self.snapped = True
        self.pressPos = self.dragPos = event.pos()
        self.tapTimer.stop()
        self.tapTimer.start(HOLD_TIME, self)

    def mouseMoveEvent(self, event: QMouseEvent) -> None:
        if not event.buttons():
            return
        if not self.zoomed:
            if not self.pressed or not self.snapped:
                delta = event.pos() - self.pressPos
                self.pressPos = event.pos()
                self.m_normalMap.pan(delta)
                return
            else:
                threshold = 10
                delta = event.pos() - self.pressPos
                if self.snapped:
                    self.snapped &= delta.x() < threshold
                    self.snapped &= delta.y() < threshold
                    self.snapped &= delta.x() > -threshold
                    self.snapped &= delta.y() > -threshold
                if not self.snapped:
                    self.tapTimer.stop()
        else:
            self.dragPos = event.pos()
            self.update()

    def mouseReleaseEvent(self, event: QMouseEvent) -> None:
        self.zoomed = False
        self.update()

    def keyPressEvent(self, event: QKeyEvent) -> None:
        if not self.zoomed:
            if event.key() == Qt.Key_Left:
                self.m_normalMap.pan(QPoint(20, 0))
            if event.key() == Qt.Key_Right:
                self.m_normalMap.pan(QPoint(-20, 0))
            if event.key() == Qt.Key_Up:
                self.m_normalMap.pan(QPoint(0, 20))
            if event.key() == Qt.Key_Down:
                self.m_normalMap.pan(QPoint(0, -20))
            if event.key() == Qt.Key_Z or event.key() == Qt.Key_Select:
                self.dragPos = QPoint(self.width() / 2, self.height() / 2)
                self.activateZoom()
        else:
            if event.key() == Qt.Key_Z or event.key() == Qt.Key_Select:
                self.zoomed = False
                self.update()
            delta = QPoint(0, 0)
            if event.key() == Qt.Key_Left:
                delta = QPoint(-15, 0)
            if event.key() == Qt.Key_Right:
                delta = QPoint(15, 0)
            if event.key() == Qt.Key_Up:
                delta = QPoint(0, -15)
            if event.key() == Qt.Key_Down:
                delta = QPoint(0, 15)
            if delta != QPoint(0, 0):
                self.dragPos += delta
                self.update()

    @Slot(QRect)
    def updateMap(self, r):
        self.update(r)
Beispiel #10
0
class SlippyMap(QObject):
    def __init__(self, parent: QObject = None) -> None:
        super().__init__(parent)

        self.width: int = 400
        self.height: int = 300
        self.zoom: int = 15
        self.latitude: float = 59.9138204
        self.longitude: float = 10.7387413

        self.m_offset = QPoint()
        self.m_tilesRect = QRect()

        self.m_emptyTile = QPixmap(tdim, tdim)
        self.m_emptyTile.fill(Qt.lightGray)

        self.m_tilePixmaps: typing.Dict[QPointH, QPixmap] = dict()
        self.m_manager = QNetworkAccessManager()
        self.m_url = QUrl()

        cache = QNetworkDiskCache()
        cache.setCacheDirectory(
            QStandardPaths.writableLocation(QStandardPaths.CacheLocation))
        self.m_manager.setCache(cache)
        self.m_manager.finished.connect(self.handleNetworkData)

    def invalidate(self) -> None:
        if self.width <= 0 or self.height <= 0:
            return

        ct = tileForCoordinate(self.latitude, self.longitude, self.zoom)
        tx = ct.x()
        ty = ct.y()

        # top-left corner of the center tile
        xp = self.width / 2 - (tx - math.floor(tx)) * tdim
        yp = self.height / 2 - (ty - math.floor(ty)) * tdim

        xa = (xp + tdim - 1) / tdim
        ya = (yp + tdim - 1) / tdim
        xs = int(tx) - xa
        ys = int(ty) - ya

        # offset for top-left tile
        self.m_offset = QPoint(xp - xa * tdim, yp - ya * tdim)

        # last tile vertical and horizontal
        xe = int(tx) + (self.width - xp - 1) / tdim
        ye = int(ty) + (self.height - yp - 1) / tdim

        # build a rect
        self.m_tilesRect = QRect(xs, ys, xe - xs + 1, ye - ys + 1)

        if self.m_url.isEmpty():
            self.download()

        self.updated.emit(QRect(0, 0, self.width, self.height))

    def render(self, painter: QPainter, rect: QRect) -> None:
        for x in range(self.m_tilesRect.width() + 1):
            for y in range(self.m_tilesRect.height() + 1):
                tp = QPoint(x + self.m_tilesRect.left(),
                            y + self.m_tilesRect.top())
                box = self.tileRect(tp)
                if rect.intersects(box):
                    painter.drawPixmap(
                        box,
                        self.m_tilePixmaps.get(QPointH(tp), self.m_emptyTile))

    def pan(self, delta: QPoint) -> None:
        dx = QPointF(delta) / float(tdim)
        center = tileForCoordinate(self.latitude, self.longitude,
                                   self.zoom) - dx
        self.latitude = latitudeFromTile(center.y(), self.zoom)
        self.longitude = longitudeFromTile(center.x(), self.zoom)
        self.invalidate()

    updated = Signal(QRect)

    @Slot(QNetworkReply)
    def handleNetworkData(self, reply: QNetworkReply) -> None:
        img = QImage()
        tp = reply.request().attribute(QNetworkRequest.User)
        if not reply.error():
            if not img.load(reply, ""):
                img = QImage()
        reply.deleteLater()
        self.m_tilePixmaps[QPointH(tp)] = (self.m_emptyTile if img.isNull()
                                           else QPixmap.fromImage(img))
        self.updated.emit(self.tileRect(tp))

        # purge unused spaces
        bound = self.m_tilesRect.adjusted(-2, -2, 2, 2)
        self.m_tilePixmaps = {
            tp: pixmap
            for tp, pixmap in self.m_tilePixmaps.items() if bound.contains(tp)
        }

        self.download()

    @Slot()
    def download(self):
        grab = QPoint(0, 0)
        for x in range(self.m_tilesRect.width() + 1):
            for y in range(self.m_tilesRect.height() + 1):
                tp = self.m_tilesRect.topLeft() + QPoint(x, y)
                if QPointH(tp) not in self.m_tilePixmaps:
                    grab = tp
                    break

        if grab == QPoint(0, 0):
            self.m_url = QUrl()
            return
        path = "http://tile.openstreetmap.org/%d/%d/%d.png"
        self.m_url = QUrl(path % (self.zoom, grab.x(), grab.y()))
        request = QNetworkRequest()
        request.setUrl(self.m_url)
        request.setRawHeader(b"User-Agent",
                             b"The Qt Company (Qt) Graphics Dojo 1.0")
        request.setAttribute(QNetworkRequest.User, grab)
        self.m_manager.get(request)

    def tileRect(self, tp: QPoint):
        t = tp - self.m_tilesRect.topLeft()
        x = t.x() * tdim + self.m_offset.x()
        y = t.y() * tdim + self.m_offset.y()
        return QRect(x, y, tdim, tdim)