Beispiel #1
0
class LineChart(object):
    """
    linegraph
    """
    def __init__(self, data=None):
        if data is None:
            data = []
        self.data = data
        self.rect = QRect()
        self.color = QColor(0, 0, 200)
        self.background_color = QColor(255, 255, 255)

    def paint(self, painter):
        painter.fillRect(self.rect, self.background_color)
        if not self.data:
            return
        min_data = float(min(self.data))
        max_data = float(max(self.data))

        max_data += max_data / 2
        min_data -= min_data / 2
        diff = (max_data - min_data)

        multplier = self.rect.height() / diff
        w_multiplier = self.rect.width() / float(len(self.data))

        for i, d in enumerate(self.data):
            y = self.rect.height() - ((d - min_data) * multplier)
            x = i * w_multiplier
            draw_width = w_multiplier if w_multiplier > 1 else 1
            painter.fillRect(int(self.rect.x() + x), int(self.rect.y() + y),
                             int(math.ceil(draw_width)),
                             int(math.ceil(self.rect.height() - y)),
                             self.color)
 def adjust_resizers(self, geometry: QRect) -> None:
     """Top, Left, Right, Bottom resizers are 4 px wide, corner resizers are 8x8 pixels"""
     radius: int = self.__radius if self.__parent.use_shadow and not self.__parent.maximized else 0
     cr = QRect(0 + radius, 0 + radius,
                geometry.width() - radius * 2,
                geometry.height() - radius * 2)
     r_width: int = 4  # resizer width/height
     c_width: int = 8  # corner width/height
     crx: int = cr.x()
     cry: int = cr.y()
     crw: int = cr.width()
     crw_sr: int = crw + radius - r_width
     crh: int = cr.height()
     crh_sr: int = crh + radius - r_width
     self.__parent.resizer_top.setGeometry(crx + c_width, cry,
                                           crw - c_width * 2, r_width)
     self.__parent.resizer_bot.setGeometry(crx + c_width, crh_sr,
                                           crw - c_width * 2, r_width)
     self.__parent.resizer_lef.setGeometry(crx, cry + c_width, r_width,
                                           crh - c_width * 2)
     self.__parent.resizer_rig.setGeometry(crw_sr, cry + c_width, r_width,
                                           crh - c_width * 2)
     self.__parent.resizer_tr.setGeometry(crw - c_width + radius, cry,
                                          c_width, c_width)
     self.__parent.resizer_br.setGeometry(crw - c_width + radius,
                                          crh - c_width + radius, c_width,
                                          c_width)
     self.__parent.resizer_bl.setGeometry(crx, crh - c_width + radius,
                                          c_width, c_width)
     self.__parent.resizer_tl.setGeometry(crx, cry, c_width, c_width)
Beispiel #3
0
    def paintEvent(self, event):
        super(PixmapWidget, self).paintEvent(event)
        if not self.pixmap or self.pixmap.isNull():
            return
        p = QPainter(self)

        source = QRect(0, 0, self.pixmap.width(), self.pixmap.height())

        sw = float(source.width())
        sh = float(source.height())
        tw = float(self.width())+1
        th = float(self.height())+1
        tx = 0
        ty = 0
        if sw/tw > sh/th:
            ntw = tw
            nth = sh/sw*tw
            ty = (th-nth)/2
        else:
            nth = th
            ntw = sw/sh*th
            tx = (tw-ntw)/2

        target = QRect(tx, ty, ntw, nth)

        p.setBrush(self.bgBrush)
        p.setPen(self.bgPen)
        p.drawRect(self.rect())

        p.drawPixmap(target, self.pixmap, source)
Beispiel #4
0
 def drawCropTool(self, img):
     """
     Draws the 8 crop buttons around the displayed image,
     with their current margins.
     @param img:
     @type img: QImage
     """
     r = self.parent().img.resize_coeff(self.parent())
     left = self.btnDict['left']
     top = self.btnDict['top']
     bottom = self.btnDict['bottom']
     right = self.btnDict['right']
     cRect = QRect(round(left.margin), round(top.margin),
                   img.width() - round(right.margin + left.margin),
                   img.height() - round(bottom.margin + top.margin))
     p = cRect.topLeft() * r + QPoint(img.xOffset, img.yOffset)
     x, y = p.x(), p.y()
     w, h = cRect.width() * r, cRect.height() * r
     left.move(x - left.width(), y + h // 2)
     right.move(x + w, y + h // 2)
     top.move(x + w // 2, y - top.height())
     bottom.move(x + w // 2, y + h)
     topLeft = self.btnDict['topLeft']
     topLeft.move(x - topLeft.width(), y - topLeft.height())
     topRight = self.btnDict['topRight']
     topRight.move(x + w, y - topRight.height())
     bottomLeft = self.btnDict['bottomLeft']
     bottomLeft.move(x - bottomLeft.width(), y + h)
     bottomRight = self.btnDict['bottomRight']
     bottomRight.move(x + w, y + h)
Beispiel #5
0
def draw_wfm_pillow(rect: QRect, wfm_arr: WFMArray) -> QImage:
    vmin, vmax = -20, 120
    vsize = vmax - vmin

    in_height, in_width = wfm_arr.shape
    in_rect = QRect(0, 0, in_width, in_height)

    rect_h, rect_w = rect.height(), rect.width()
    h_scale = rect_h - 1
    w_scale = rect_w - 1

    wfm_arr['ypos'] = (wfm_arr['ypos'] * 100 / vmax * vsize -
                       vmin) / vsize * h_scale
    wfm_arr['xpos'] *= w_scale

    img = Image.new('RGBA', (rect_w, rect_h), (0, 0, 0, 0))
    d = ImageDraw.Draw(img)

    xy_arr = rfn.structured_to_unstructured(wfm_arr[['xpos', 'ypos']])

    for y in range(in_height):
        d.line(xy_arr[y], fill=(255, 255, 255, 255), width=1)

    qimg = im.toqimage()
    if in_rect != rect:
        qimg = qimg.scaled(rect.size())
    return qimg.mirrored(False, True)
Beispiel #6
0
    def is_inside_limit(limit: QRect, pos: QPoint):
        if pos.x() < limit.x() or pos.x() > limit.width():
            return False
        elif pos.y() < limit.y() or pos.y() > limit.height():
            return False

        return True
Beispiel #7
0
    def _rect_to_area(self, rect: QRect):

        return {
            "x": rect.left(),
            "y": rect.top(),
            "width": rect.width(),
            "height": rect.height()
        }
Beispiel #8
0
class VoronoiDiagram:
    def __init__(self, width, height, total_points=20):
        self.width = width
        self.height = height
        self.total_points = total_points
        self.points = []
        self.colors = []
        self.rect = QRect()

    def generate(self):
        self.points = []
        self.colors = []
        for i in range(self.total_points):
            v = QVector2D(random.random(), random.random())
            self.points.append(v)
            c = QColor(random.randint(0, 255), random.randint(0, 255),
                       random.randint(0, 255))
            self.colors.append(c)

    def get_closest_point(self, v):
        closest_length = 0
        is_first = True
        index = -1
        size_vector = QVector2D(self.width, self.height)

        for i, p in enumerate(self.points):
            length = (p * size_vector - v).length()
            if is_first:
                closest_length = length
                is_first = False
                index = i
                continue
            elif length < closest_length:
                closest_length = length
                index = i
        return index

    def paint(self, painter):

        chunk_x = float(self.rect.width()) / float(self.width)
        chunk_y = float(self.rect.height()) / float(self.height)
        size_vector = QVector2D(self.width, self.height)

        for y in range(self.height):
            for x in range(self.width):
                v = QVector2D(x, y)
                index = self.get_closest_point(v)
                c = self.colors[index]
                draw_x = math.floor(chunk_x * x)
                dray_y = math.floor(chunk_y * y)
                painter.setPen(QPen(c))
                painter.fillRect(draw_x, dray_y, math.ceil(chunk_x),
                                 math.ceil(chunk_y), c)

        painter.setPen(QPen(QColor(100, 100, 100)))
        for v in self.points:
            painter.drawRect(v.x() * size_vector.x() * chunk_x,
                             v.y() * size_vector.y() * chunk_y, 2, 2)
Beispiel #9
0
	def updateLineNumberArea(self, rect: QRect, dy: int = 0):
		# todo: move this into LineNumberArea
		if dy:
			self.lineNumberArea.scroll(0, dy)
		else:
			self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height())

		if rect.contains(self.viewport().rect()):
			self.setViewportMargins(self.lineNumberArea.numberWidth(), 0, 0, 0)
    def drawHeader(self):
        """Draw logo/copyright in the header"""
        pHeight = 90
        pMargin = 15
        icon_path = cm.DIR_ICONS + "app.png"

        self.header_lbl.setMinimumHeight(pHeight)
        self.header_lbl.setFrameShape(QFrame.StyledPanel)
        self.header_lbl.setContentsMargins(0, 0, 0, 0)

        pixmap = QPixmap(450, pHeight)
        pixmap.fill(Qt.transparent)

        iconY = (pHeight - 64) / 2
        logoRect = QRect(pMargin, iconY, 64, 64)

        painter = QPainter(pixmap)
        painter.setBrush(QBrush(Qt.red))
        painter.drawPixmap(
            logoRect,
            QPixmap(icon_path).scaled(
                logoRect.width(),
                logoRect.height(),
                Qt.KeepAspectRatio,
                Qt.SmoothTransformation,
            ),
        )

        titleRect = QRect(logoRect.right() + 10, iconY, 200, pHeight)

        font = QFont()
        font.setBold(True)
        font.setPixelSize(16)
        painter.setFont(font)
        painter.setPen(QPen(QApplication.instance().palette().text().color()))
        painter.drawText(titleRect, Qt.AlignTop, "Cutevariant")

        font_metrics = QFontMetrics(font)
        font.setBold(False)
        font.setPixelSize(12)
        painter.setFont(font)
        painter.setPen(QPen(Qt.darkGray))
        titleRect.setY(titleRect.y() + font_metrics.height())

        painter.drawText(
            titleRect,
            Qt.AlignTop,
            f"Version %s\nGPL3 Copyright (C) 2018-2020\nLabsquare.org" % __version__,
        )

        self.header_lbl.setPixmap(pixmap)

        # Painting is finished !
        # Avoid Segfault:
        # QPaintDevice: Cannot destroy paint device that is being painted
        painter.end()
Beispiel #11
0
def get_graticules(
        rect: QRect) -> Tuple[Dict[float, float], Dict[float, QLineF]]:
    """Get a set of graticules scaled to fit within the given :class:`QtCore.QRect`

    The scale ranges from -20 to 120 (ire) in increments of 10. An extra value of
    7.5 ire is included (NTSC setup level)

    Arguments:
        rect (:class:`QtCore.QRect`): The bounding box as a :class:`QtCore.QRect`

    Returns
    -------
    ire_vals : dict
        A mapping of ire values to their normalized positions
    lines : dict
        A mapping of :class:`QtCore.QLineF` objects with their ire values as keys
    """

    # Overall scale: -20 to 120
    # ire_vals = {
    #     0: 0,
    #     7.5: 16 / 255,      # NTSC black
    #     100: 235 / 255,
    # }
    ire_vals = {}
    # scale_factor = 255/219
    vmax = 120
    vmin = -20
    vsize = vmax - vmin
    ires = [
        -20, -10, 0, 7.5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120
    ]

    def ire_to_pos_norm(ire):
        v = ire
        # v = (ire * 219 + 16) / 255# * scale_factor
        return (v - vmin) / vsize

    for ire in ires:
        ire_vals[ire] = ire_to_pos_norm(ire)

    lines = {}

    rect_w = rect.width()
    rect_h = rect.height()

    w_scale = rect_w - 1
    h_scale = rect_h - 1

    for ire, pos_norm in ire_vals.items():
        pos_y = (pos_norm * h_scale - h_scale) * -1
        lines[float(ire)] = QLineF(0, pos_y, rect_w, pos_y)

    return ire_vals, lines
Beispiel #12
0
    def __init__(self):
        super().__init__(flags=Qt.Widget
                         | Qt.FramelessWindowHint
                         | Qt.BypassWindowManagerHint
                         | Qt.WindowTransparentForInput
                         | Qt.WindowStaysOnTopHint)
        self.logger = logging.getLogger(__name__ + "." +
                                        self.__class__.__name__)
        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.setStyleSheet("background: transparent")
        self._instances = {}

        virtual_screen = QRect(0, 0, 0, 0)

        for screen in QGuiApplication.screens():
            # TODO: Handle screen change
            geom = screen.virtualGeometry()
            virtual_screen = virtual_screen.united(geom)

        self.scene = QGraphicsScene(0,
                                    0,
                                    virtual_screen.width(),
                                    virtual_screen.height(),
                                    parent=self)

        self.view = QGraphicsView(self.scene, self)
        self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.view.setStyleSheet("background: transparent")
        self.view.setGeometry(0, 0, virtual_screen.width(),
                              virtual_screen.height())
        self.view.setInteractive(False)

        self.transparent_pen = QPen()
        self.transparent_pen.setBrush(Qt.NoBrush)

        self.setGeometry(virtual_screen)
Beispiel #13
0
    def erase_cursor_rect(self, pos: Tuple[int, int]):
        painter = QPainter(self.cursors_pixmap)

        cursor_rect = QRect(self.byte_rect)
        h = cursor_rect.height()
        i, j = pos

        cursor_rect.moveTopLeft(QPoint(i * self.byte_advance, j * h))

        painter.setCompositionMode(QPainter.CompositionMode_Source)
        painter.setPen(Qt.NoPen)
        painter.setBrush(Qt.transparent)
        painter.drawRect(cursor_rect)
        painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
Beispiel #14
0
    def fit_solution_in_view(self, solution):
        if not solution.rect:
            return

        solution_rect = QRect(
            QPoint(solution.rect.left, solution.rect.top),
            QPoint(solution.rect.right, solution.rect.bottom))

        viewport_rect = self.viewport.rect()

        # compute zoom level
        if solution_rect.width() > solution_rect.height():
            zoom = viewport_rect.width() / solution_rect.width(
            ) if viewport_rect.width() else 1
        else:
            zoom = viewport_rect.height() / solution_rect.height(
            ) if viewport_rect.height() else 1

        self.zoom = 0.80 * zoom if zoom else 1
        self.zoom = clamp(self.zoom, MIN_ZOOM, MAX_ZOOM)  # limit zoom level

        # center view on rect center
        self.pos = -QPointF(solution_rect.center())
Beispiel #15
0
    def paintEvent(self, e):
        """ Draws the color bar and arrow """
        if self.item():
            painter = QPainter(self)

            # Draws the color bar
            painter.setPen(Qt.NoPen)
            rect = QRect(0, 0, self.COLOR_BAR_WIDTH, self.COLOR_BAR_HEIGHT)
            painter.fillRect(rect,
                             self.item().data(renderSetupRoles.NODE_COLOR_BAR))
            oldBrush = painter.brush()

            if self.item().type(
            ) == renderSetup.RENDER_OVERRIDE_TYPE and self.item(
            ).isLocalRender():
                diameter = rect.width() - 2
                rect2 = QRect(rect.x() + 1,
                              rect.y() + (rect.height() - diameter) / 2,
                              diameter, diameter)
                brush = painter.brush()
                pen = painter.pen()
                hints = painter.renderHints()

                painter.setRenderHint(QPainter.Antialiasing, on=True)
                painter.setPen(Qt.NoPen)
                painter.setBrush(
                    QBrush(QColor(67, 79, 70), style=Qt.SolidPattern))
                painter.drawEllipse(rect2)

                painter.setRenderHints(hints)
                painter.setPen(pen)
                painter.setBrush(brush)

            # Draws the arrow
            painter.setBrush(self.ARROW_COLOR)
            if self.arrowPoints == BaseDelegate.EXPANDED_ARROW:
                painter.translate(self.EXPANDED_ARROW_OFFSET, 0.0)
            else:
                painter.translate(self.COLLAPSED_ARROW_OFFSET, 0.0)
            painter.drawPolygon(self.arrowPoints)
            painter.setBrush(oldBrush)

            # Draws the node type text
            painter.setPen(QPen(self.item().data(Qt.TextColorRole)))
            text = self.item().data(renderSetupRoles.NODE_TYPE_STR)
            painter.setFont(self.item().data(Qt.FontRole))
            painter.drawText(self.NODE_TYPE_TEXT_RECT, text,
                             QTextOption(Qt.AlignLeft | Qt.AlignVCenter))
Beispiel #16
0
    def calculate_screen_limits(self):
        screen = QRect(self.app.desktop().x(), self.app.desktop().y(),
                       self.app.desktop().width(), self.app.desktop().availableGeometry().height())

        width_margin = round(self.geometry().width() / 2)
        height_margin = round(self.geometry().height() / 2)

        # Case where secondary screen has negative values
        desktop_width = screen.x() + screen.width()

        min_x = screen.x() - width_margin
        min_y = screen.y() - height_margin
        max_x = desktop_width - width_margin
        max_y = screen.height() - height_margin

        return QRect(min_x, min_y, max_x, max_y)
class Physics2D:
    def __init__(self):
        self.objects = []
        self.rect = QRect()
        self.debug = False

        self.gravity = 9.81
        self.last_time = time.time()

    def circle_intersects(self, p0, r0, p1, r2):
        distance = p0 - p1
        if distance.length() < (r0 + r2):
            return True
        else:
            return False

    @classmethod
    def line_intersects(cls, p0, p1, p2, p3):
        """does the lines intersect
        """
        return True

    @classmethod
    def box_intersects(cls, boxa, boxb):
        return False

    def add_sphere(self, radius=10.0):
        sphere = Sphere(self)
        self.objects.append(sphere)
        sphere.radius = radius
        sphere.pos.setX(self.rect.width() / 2.0)
        sphere.pos.setY(self.rect.height() / 2.0)
        return sphere

    def tick(self):
        current_time = time.time()

        dt = current_time - self.last_time

        for obj in self.objects:
            obj.tick(dt)
        self.last_time = current_time

    def reflect(self, point, normal):
        v = point - (normal * QVector2D.dotProduct(point, normal) * 2)
        v.normalize()
        return v
Beispiel #18
0
    def print_to_pixmap(self, painter, byte_addr, string, pen):
        index = self.byte_index(byte_addr)
        byte_rect = QRect(self.byte_rect)
        h = byte_rect.height()

        painter.setBrush(BRUSH_EMPTY)

        for digit1, digit2 in pairs(string):
            i, j = next(index)
            txt = digit1 + digit2

            byte_rect.moveTopLeft(QPoint(i * self.byte_advance, j * h))
            painter.setPen(Qt.NoPen)
            painter.drawRect(byte_rect)

            painter.setPen(pen)
            painter.drawText(byte_rect, Qt.AlignCenter, f'{txt}')
Beispiel #19
0
    def draw_cursor_rect(self, pos: Tuple[int, int], brush, addr):
        painter = QPainter(self.cursors_pixmap)

        cursor_rect = QRect(self.byte_rect)
        h = cursor_rect.height()
        i, j = pos

        cursor_rect.moveTopLeft(QPoint(i * self.byte_advance, j * h))

        painter.setPen(Qt.NoPen)
        painter.setBrush(brush)
        painter.drawRect(cursor_rect)

        painter.setFont(self.font)
        txt = self.bytes_field[addr][0]
        painter.setPen(PEN_BCK)
        painter.drawText(cursor_rect, Qt.AlignCenter, f'{txt}')

        painter.end()
Beispiel #20
0
def paint_waveform_arr(rect: QRect, wfm_arr: WFMArray) -> QPainterPath:

    rect_w = rect.width()
    rect_h = rect.height()
    w_scale = rect_w - 1
    h_scale = rect_h - 1

    vmin, vmax = -20, 120
    vsize = vmax - vmin

    ypos = wfm_arr['ypos']
    ypos = (wfm_arr['ypos'] * 100 / vmax * vsize - vmin) / vsize
    ypos_w = (ypos * h_scale - h_scale) * -1
    wfm_range = (wfm_arr['ypos'].min(), wfm_arr['ypos'].max())
    ypos_range = (ypos.min(), ypos.max())
    ypos_w_range = (ypos_w.min(), ypos_w.max())
    # print(f'{wfm_range=}, {ypos_range=}, {ypos_w_range=}, {rect_h=}')
    wfm_arr['ypos'] = ypos_w

    h, w = wfm_arr.shape

    wfm_arr['xpos'] *= w_scale

    xy_arr = rfn.structured_to_unstructured(wfm_arr[['xpos', 'ypos']])

    paths = QPainterPath()
    for y in range(h):
        path = QPainterPath()
        y_arr = xy_arr[y]
        for x in range(w):
            xy = y_arr[x]
            if x > 0:
                path.lineTo(xy[0], xy[1])
            else:
                path.moveTo(xy[0], xy[1])

        paths.addPath(path)
    return paths
Beispiel #21
0
    def _locate_win_result(self, target_rect: QRect):
        if target_rect.width() < 2 or target_rect.height() < 2:
            return
        # Trigger a resize to regular size if previous size was fitted to a window
        self.img_view.change_viewer_size()

        if self.locate_btn.key_modifier == 0 and self.img_view.height() > 0:
            # No Key Modifier tries to keep aspect ratio
            height_factor: float = self.img_view.height() / self.img_view.width()
            height: int = round(target_rect.width() * height_factor)
            target_rect.setHeight(height)
            LOGGER.debug('Trying to keep aspect ratio at %s height factor. %s %s',
                         height_factor, target_rect.width(), height)
        elif self.locate_btn.key_modifier == Qt.ControlModifier:
            # Ctrl Key only moves window
            self.img_view.move(target_rect.topLeft())
            return
        elif self.locate_btn.key_modifier == Qt.ShiftModifier:
            # Shift/Any Key Modifier fits to window without respecting aspect ratio of image
            pass

        self.img_view.resize(target_rect.size())
        self.img_view.move(target_rect.topLeft())
Beispiel #22
0
class LevyFlight(object):
    MOVE_UP = 0
    MOVE_DOWN = 1
    MOVE_RIGHT = 2
    MOVE_LEFT = 3

    def create_random_vector2d(self):
        a = random.random() * math.pi * 2
        return QVector2D(math.cos(a), math.sin(a))

    def __init__(self):
        self.rect = QRect()
        self.path = []
        self.start_pos = QVector2D()
        self.pos = QVector2D()
        self.resolution = QSize()

        self.up_vector = QVector2D(0, -1)
        self.down_vector = QVector2D(0, 1)
        self.left_vector = QVector2D(-1, 0)
        self.right_vector = QVector2D(1, 0)

        self.head_color = QColor(250, 60, 50)
        self.tail_color = QColor(70, 70, 70)

    def reset(self):
        self.path = []
        self.pos = self.start_pos

    def setup(self):
        self.reset()

    def get_next_pos(self):
        pos_copy = QVector2D(self.pos)
        v = self.create_random_vector2d()
        if random.random() < 0.01:
            pos_copy += v * random.randint(20, 40)
        else:
            pos_copy += v * random.randint(1, 5)
        return pos_copy

    def tick(self):
        """
        Tick the random walker to do something
        """

        while True:
            pos = self.get_next_pos()
            is_valid = True
            if pos.x() > self.resolution.width():
                is_valid = False
            elif pos.x() < 0:
                is_valid = False
            elif pos.y() > self.resolution.height():
                is_valid = False
            elif pos.y() < 0:
                is_valid = False

            if is_valid:
                self.path.append(pos)
                self.pos = pos
                break

    def paint(self, painter):
        chunk_x = float(self.rect.width()) / self.resolution.width()
        chunk_y = float(self.rect.height()) / self.resolution.height()

        painter_path = QPainterPath()
        for i, pos in enumerate(self.path):
            x = pos.x() * chunk_x
            y = pos.y() * chunk_y
            p = QPoint(x, y)
            if i == 0:
                painter_path.moveTo(p)
            else:
                painter_path.lineTo(p)

        painter.drawPath(painter_path)
Beispiel #23
0
 def on_instance_moved(self, instance, pos: QRect):
     rect = self._instances[instance.wid]
     rect.setRect(0, 0, pos.width(), pos.height())
     rect.setPos(pos.x(), pos.y())
    def mouseMoveEvent(self, event: QMouseEvent) -> None:
        """Qt Mouse-Move Event"""
        def get_top_resize_values() -> Tuple[int, int]:
            """calculates vertial position and height"""
            py: int = (event.globalPos() - self.__mouse_pos).y()
            if self.__window_geometry_height - py < self.__parent.minimumSize(
            ).height():
                height: int = self.__parent.minimumSize().height()
                pos_y: int = self.__window_pos_y + self.__window_geometry_height - height
            else:
                height = self.__window_geometry_height - py
                pos_y = self.__window_pos_y + py
            return pos_y, height

        def get_left_resize_values() -> Tuple[int, int]:
            """calculates horizontal position and width"""
            px: int = (event.globalPos() - self.__mouse_pos).x()
            if self.__window_geometry_width - px < self.__parent.minimumSize(
            ).width():
                width: int = self.__parent.minimumSize().width()
                pos_x: int = self.__window_pos_x + self.__window_geometry_width - width
            else:
                width = self.__window_geometry_width - px
                pos_x = self.__window_pos_x + px
            return pos_x, width

        if self.__mouse_pressed:
            if self.__type == self.BOTTOM:
                py = (event.globalPos() - self.__mouse_pos).y()
                geometry = QRect(self.__window_geometry_x,
                                 self.__window_geometry_y,
                                 self.__window_geometry_width,
                                 self.__window_geometry_height + py)
            elif self.__type == self.RIGHT:
                px = (event.globalPos() - self.__mouse_pos).x()
                geometry = QRect(self.__window_geometry_x,
                                 self.__window_geometry_y,
                                 self.__window_geometry_width + px,
                                 self.__window_geometry_height)
            elif self.__type == self.TOP:
                pos_y, height = get_top_resize_values()
                geometry = QRect(self.__window_geometry_x, pos_y,
                                 self.__window_geometry_width, height)
            elif self.__type == self.LEFT:
                pos_x, width = get_left_resize_values()
                geometry = QRect(pos_x, self.__window_geometry_y, width,
                                 self.__window_geometry_height)
            elif self.__type == self.TOP_LEFT:
                pos_x, width = get_left_resize_values()
                pos_y, height = get_top_resize_values()
                geometry = QRect(pos_x, pos_y, width, height)
            elif self.__type == self.TOP_RIGHT:
                px = (event.globalPos() - self.__mouse_pos).x()
                pos_y, height = get_top_resize_values()
                geometry = QRect(self.__window_pos_x, pos_y,
                                 self.__window_geometry_width + px, height)
            elif self.__type == self.BOTTOM_LEFT:
                pos_x, width = get_left_resize_values()
                py = (event.globalPos() - self.__mouse_pos).y()
                geometry = QRect(pos_x, self.__window_pos_y, width,
                                 self.__window_geometry_height + py)
            elif self.__type == self.BOTTOM_RIGHT:
                px = (event.globalPos() - self.__mouse_pos).x()
                py = (event.globalPos() - self.__mouse_pos).y()
                geometry = QRect(self.__window_geometry_x,
                                 self.__window_geometry_y,
                                 self.__window_geometry_width + px,
                                 self.__window_geometry_height + py)
            if geometry.width() < self.__parent.minimumSize().width():
                geometry.setWidth(self.__parent.minimumSize().width())
            if geometry.height() < self.__parent.minimumSize().height():
                geometry.setHeight(self.__parent.minimumSize().height())
            self.__parent.setGeometry(geometry)
            self.adjust_resizers(geometry)
Beispiel #25
0
class SlippyMap(QObject):
    updated = Signal(QRect)

    def __init__(self, parent=None):
        """

        :param parent:
        """
        super(SlippyMap, self).__init__(parent)

        self._offset = QPoint()

        self._tiles_rectangle = QRect()

        self._tile_pixmaps = {}  # Point(x, y) to QPixmap mapping

        self._manager = QNetworkAccessManager()

        self._url = QUrl()

        # public vars
        self.width = 400
        self.height = 300
        self.zoom = 4
        self.latitude = 59.9138204
        self.longitude = 10.7387413

        self._emptyTile = QPixmap(TDIM, TDIM)
        self._emptyTile.fill(Qt.lightGray)

        self.request = QNetworkRequest()
        self.cache = QNetworkDiskCache()
        self.cache.setCacheDirectory(
            QStandardPaths.writableLocation(QStandardPaths.CacheLocation))
        self._manager.setCache(self.cache)
        self._manager.finished.connect(self.handle_network_data)

    def invalidate(self):
        """

        :return:
        """
        if self.width <= 0 or self.height <= 0:
            return

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

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

        # first tile vertical and horizontal
        xa = (xp + TDIM - 1) / TDIM
        ya = (yp + TDIM - 1) / TDIM
        xs = int(tx) - xa
        ys = int(ty) - ya

        # offset for top-left tile
        self._offset = QPoint(int(xp - xa * TDIM), int(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._tiles_rectangle = QRect(int(xs), int(ys), int(xe - xs + 1),
                                      int(ye - ys + 1))

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

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

    def render(self, p: QPainter, rect: QRect):
        """
        Render a tile
        :param p: QPainter instance, place where to pain the tiles
        :param rect: QRect instance, dimensions of the painter (the window that renders the tiles)
        :return: Nothing
        """

        rx = range(self._tiles_rectangle.width())
        ry = range(self._tiles_rectangle.height())

        for x, y in product(rx, ry):
            tp = Point(x + self._tiles_rectangle.left(),
                       y + self._tiles_rectangle.top())
            box = self.tile_rectangle(tp)
            if rect.intersects(box):
                p.drawPixmap(box, self._tile_pixmaps.get(tp, self._emptyTile))

    def pan(self, delta: QPoint):
        """
        Move the map
        :param delta: x, y delta as a QPoint instance
        :return: Nothing
        """
        dx = QPointF(delta) / float(TDIM)
        center = tile_for_coordinate(self.latitude, self.longitude,
                                     self.zoom) - dx
        self.latitude = latitude_from_tile(center.y(), self.zoom)
        self.longitude = longitude_from_tile(center.x(), self.zoom)
        self.invalidate()

    # slots
    def handle_network_data(self, reply: QNetworkReply):
        """
        This function is called automatically by a QNetworkAccessManager object (self._manager)
        :param reply: QNetworkReply instance
        :return: Nothing
        """
        img = QImage()

        tp = Point(reply.request().attribute(QNetworkRequest.User))

        url = reply.url()

        if not reply.error():  # if there was no url error...
            if img.load(reply, None):  # if the image loading went well...
                self._tile_pixmaps[tp] = QPixmap.fromImage(
                    img)  # store the image in the tiles dictionary

        reply.deleteLater()

        self.updated.emit(self.tile_rectangle(tp))

        # purge unused tiles
        bound = self._tiles_rectangle.adjusted(-2, -2, 2, 2)
        for tp in list(self._tile_pixmaps.keys()):
            if not bound.contains(tp):
                del self._tile_pixmaps[tp]
        self.download()

    def download(self):
        """
        Download tile
        :return: Nothing
        """
        grab = None

        rx = range(self._tiles_rectangle.width())
        ry = range(self._tiles_rectangle.height())

        for x, y in product(rx, ry):
            tp = Point(self._tiles_rectangle.topLeft() + QPoint(x, y))
            if tp not in self._tile_pixmaps:
                grab = QPoint(tp)
                break

        if grab is None:
            self._url = QUrl()
            return

        path = 'http://tile.openstreetmap.org/%d/%d/%d.png' % (
            self.zoom, grab.x(), grab.y())
        self._url = QUrl(path)
        self.request = QNetworkRequest()
        self.request.setUrl(self._url)
        self.request.setRawHeader(b'User-Agent',
                                  b'Nokia (PyQt) Graphics Dojo 1.0')
        self.request.setAttribute(QNetworkRequest.User, grab)
        self._manager.get(self.request)

        print('downloading z:', self.zoom, 'x:', grab.x(), 'y:', grab.y())

    def tile_rectangle(self, tp: Point):
        """
        Get tile rectangle
        :param tp: Tile point
        :return: QRect instance
        """
        t = tp - self._tiles_rectangle.topLeft()
        x = t.x() * TDIM + self._offset.x()
        y = t.y() * TDIM + self._offset.y()

        return QRect(x, y, TDIM, TDIM)
Beispiel #26
0
class PaletteWidget(QtWidgets.QWidget):

    # Color changed signal
    changed = QtCore.Signal()

    @property
    def color(self):
        return QtGui.QColor.fromHsvF(self._hue, self._saturation, self._value)

    @color.setter
    def color(self, value):
        # If this is an integer, assume is RGBA
        if not isinstance(value, QtGui.QColor):
            r = (value & 0xff000000) >> 24
            g = (value & 0xff0000) >> 16
            b = (value & 0xff00) >> 8
            value = QtGui.QColor.fromRgb(r, g, b)
        self._set_color(value)
        self.RGBvalue.setText(value.name())

    def __init__(self, parent=None, RGBvalue=None):
        super(PaletteWidget, self).__init__(parent)
        self._hue = 1.0
        self._saturation = 1.0
        self._value = 1.0
        self._hue_width = 24
        self._gap = 8
        self._color = QtGui.QColor.fromHslF(self._hue, 1.0, 1.0)
        self._calculate_bounds()
        self._draw_palette()
        self.RGBvalue = RGBvalue

    # Calculate the sizes of various bits of our UI
    def _calculate_bounds(self):
        width = self.width()
        height = self.height()
        # Hue palette
        self._hue_rect = QRect(width - self._hue_width, 0, self._hue_width, height)
        # Shades palette
        self._shades_rect = QRect(0, 0, width - (self._hue_width + self._gap), height)

    # Render our palette to an image
    def _draw_palette(self):

        # Create an image with a white background
        self._image = QtGui.QImage(QtCore.QSize(self.width(), self.height()), QtGui.QImage.Format.Format_RGB32)
        self._image.fill(QtGui.QColor.fromRgb(0xff, 0xff, 0xff))

        # Draw on our image with no pen
        qp = QtGui.QPainter()
        qp.begin(self._image)
        qp.setPen(QtCore.Qt.NoPen)

        # Render hues
        rect = self._hue_rect
        for x in xrange(rect.x(), rect.x() + rect.width()):
            for y in xrange(rect.y(), rect.y() + rect.height(), 8):
                h = float(y) / rect.height()
                s = 1.0
                v = 1.0
                c = QtGui.QColor.fromHsvF(h, s, v)
                qp.setBrush(c)
                qp.drawRect(x, y, 8, 8)

        # Render hue selection marker
        qp.setBrush(QtGui.QColor.fromRgb(0xff, 0xff, 0xff))
        qp.drawRect(rect.x(), self._hue * rect.height(), rect.width(), 2)

        # Render shades
        rect = self._shades_rect
        width = float(rect.width())
        steps = int(round(width / 8.0))
        step_size = width / steps
        x = rect.x()
        while x < rect.width() + rect.x():
            w = int(round(step_size))
            for y in xrange(rect.y(), rect.y() + rect.height(), 8):
                h = self._hue
                s = 1 - float(y) / rect.height()
                v = float(x) / rect.width()
                c = QtGui.QColor.fromHsvF(h, s, v)
                qp.setBrush(c)
                qp.drawRect(x, y, w, 8)
            x += w
            width -= w
            steps -= 1
            if steps > 0:
                step_size = width / steps

        # Render color selection marker
        qp.setBrush(QtGui.QColor.fromRgb(0xff, 0xff, 0xff))
        qp.drawRect(rect.x(), (1 - self._saturation) * rect.height(), rect.width(), 1)
        qp.drawRect(self._value * rect.width(), rect.y(), 1, rect.height())

        qp.end()

    def paintEvent(self, event):
        # Render our palette image to the screen
        qp = QtGui.QPainter()
        qp.begin(self)
        qp.drawImage(QPoint(0, 0), self._image)
        qp.end()

    def mousePressEvent(self, event):
        mouse = QPoint(event.pos())
        if event.buttons() & QtCore.Qt.LeftButton:
            # Click on hues?
            if self._hue_rect.contains(mouse.x(), mouse.y()):
                y = mouse.y()
                c = QtGui.QColor.fromHsvF(float(y) / self.height(), self._saturation, self._value)
                self.color = c
            # Click on colors?
            elif self._shades_rect.contains(mouse.x(), mouse.y()):
                # calculate saturation and value
                x = mouse.x()
                y = mouse.y()
                c = QtGui.QColor.fromHsvF(self._hue, 1 - float(y) / self._shades_rect.height(),
                                          float(x) / self._shades_rect.width())
                self.color = c

    def mouseMoveEvent(self, event):
        if event.buttons() & QtCore.Qt.LeftButton:
            self.mousePressEvent(event)

    def resizeEvent(self, event):
        self._calculate_bounds()
        self._draw_palette()

    # Set the current color
    def _set_color(self, c):
        h, s, v, _ = c.getHsvF()
        self._hue = h
        self._saturation = s
        self._value = v
        self._draw_palette()
        self.repaint()
        self.changed.emit()
class DLA(object):
    def __init__(self):
        super(DLA, self).__init__()
        self.on_stick_func = None
        self.walker_radius = WALKER_RADIUS
        self.rect = QRect()
        self.sticking_walkers = []
        self.active_walkers = []
        self.max_active_walkers = MAX_ACTIVE_WALKERS
        self.max_sticking_walkers = MAX_STICKING_WALKER

        self.finished = False
        self.walker_pen = QPen()
        self.walker_brush = QBrush(QColor())
        self.active_walker_color = QColor(150, 150, 150)

    def get_progress(self):
        progress = (len(self.sticking_walkers) - 1) / float(
            self.max_sticking_walkers)
        return progress

    def reset(self):
        self.setup()

    def setup(self):
        w = Walker(self, self.rect.width() / 2, self.rect.height() / 2)
        w.radius = self.walker_radius
        w.color = QColor(200, 0, 0)

        self.sticking_walkers = [w]
        self.active_walkers = []

        for i in range(self.max_active_walkers):
            self.active_walkers.append(self.spawn_new_walker())

        self.finished = False
        self.request_new_walker()

    def paint_walker(self, painter, w, color=None):
        painter.setPen(QPen(color or w.color))
        painter.setBrush(QBrush(color or w.color))
        painter.drawEllipse(math.floor(w.pos.x() - w.radius),
                            math.floor(w.pos.y() - w.radius),
                            math.ceil(w.radius * 2.0),
                            math.ceil(w.radius * 2.0))

    def paint(self, painter):
        for w in self.active_walkers:
            self.paint_walker(painter, w, self.active_walker_color)
        for w in self.sticking_walkers:
            self.paint_walker(painter, w)

    def spawn_new_walker(self):
        side = random.randint(0, 3)
        rand_value = random.random() * self.rect.width()
        if side == 0:
            walker = Walker(self, rand_value, self.rect.y())
        elif side == 1:
            walker = Walker(self, rand_value, self.rect.height())
        elif side == 2:
            walker = Walker(self, self.rect.x(), rand_value)
        elif side == 3:
            walker = Walker(self, self.rect.width(), rand_value)
        else:
            raise RuntimeError('not a valid choice')

        progress = self.get_progress()
        walker.radius = self.walker_radius
        # walker.radius = (1.0 - self.get_progress()) * self.walker_radius
        walker.color = QColor((1.0 - progress) * 150, 0, 150 * progress)
        return walker

    def request_new_walker(self):
        if len(self.sticking_walkers) <= self.max_sticking_walkers:
            walker = self.spawn_new_walker()
            self.active_walkers.append(walker)

    def tick(self):
        if not self.active_walkers:
            return

        for w in self.active_walkers:
            w.walk()

        for active_walker in self.active_walkers:
            active_sticks = False
            for sticking_walker in self.sticking_walkers:
                if active_walker.intersects(sticking_walker):
                    active_sticks = True
                    break

            if active_sticks:
                if self.on_stick_func:
                    self.on_stick_func()
                self.sticking_walkers.append(active_walker)
                self.active_walkers.pop(
                    self.active_walkers.index(active_walker))

                self.request_new_walker()
    def paintCell(
        self, painter: QtGui.QPainter, rect: QtCore.QRect, date: QtCore.QDate
    ):
        # Paint background
        if self.selectedDate() == date:
            painter.fillRect(rect, self.Color.selected_background)

        # Paint date text
        if self.selectedDate() != date:
            if self.monthShown() != date.month():
                painter.setPen(self.Color.unselected_month_date_text)
            elif qdate_is_weekend(date):
                painter.setPen(self.Color.unselected_weekend_date_text)
            else:
                painter.setPen(self.Color.unselected_date_text)
        else:
            painter.setPen(self.Color.selected_date_text)
        painter.setFont(QtGui.QFont("Helvetica", 20))
        painter.drawText(rect, QtCore.Qt.AlignTop, str(date.day()))

        # Get todo items to paint
        items = []
        try:
            items = self.todo_item_dict[date.year()][date.month()][date.day()]
        except KeyError:
            pass

        if len(items) != 0:
            # Paint number of todo items
            # Text color is same is date's
            completed_items_num = len([item for item in items if item["completed"]])
            x = 40
            y = 5
            width = rect.width() - x
            painter.setFont(QtGui.QFont("Helvetica", 14))
            item_number_str = f"{completed_items_num}/{len(items)} items"
            painter.drawText(
                rect.x() + x, rect.y() + y, width, rect.height(), 0, item_number_str
            )

            # Paint todo items
            x = 5
            y = 32
            width = rect.width() - x
            painter.setFont(QtGui.QFont("Helvetica", 10))
            for item in items:
                if y > rect.height():
                    break

                if item["completed"]:
                    painter.setPen(self.Color.completed_todo_item)
                else:
                    painter.setPen(self.Color.uncompleted_todo_item)

                height = rect.height() - y
                bounding_rect = painter.boundingRect(
                    rect.x() + x,
                    rect.y() + y,
                    width,
                    height,
                    QtCore.Qt.TextWordWrap,
                    item["name"],
                )
                painter.drawText(
                    rect.x() + x,
                    rect.y() + y,
                    width,
                    height,
                    QtCore.Qt.TextWordWrap,
                    item["name"],
                )
                y += bounding_rect.height()
Beispiel #29
0
    def paintCell(
        self, painter: QtGui.QPainter, rect: QtCore.QRect, qdate: QtCore.QDate
    ):
        date = qdate_to_date(qdate)
        # Paint date text
        if self.monthShown() != qdate.month():
            painter.setPen(self.Color.unselected_month_date_text)
        else:
            painter.setPen(self.Color.unselected_date_text)
        painter.setFont(QtGui.QFont("Helvetica", 20))
        painter.drawText(rect, QtCore.Qt.AlignTop, str(qdate.day()))

        # Get all of the chains for the current week
        for date_range, chains in self.month_chains.items():
            if date_range[0] <= date and date <= date_range[1]:
                display_chains = chains
                break
        else:
            display_chains = self.generate_week_info(qdate_to_date(qdate))

        # Paint completed chains
        completed_chains_num = 0
        x = 5
        y = 32
        width = rect.width() - x
        painter.setFont(QtGui.QFont("Helvetica", 10))
        for chain in display_chains:
            if y > rect.height():
                break

            height = rect.height() - y
            bounding_rect = painter.boundingRect(
                rect.x() + x,
                rect.y() + y,
                width,
                height,
                QtCore.Qt.TextWordWrap,
                chain,
            )
            if chain_handler.get_chain(chain, qdate.year(), qdate.month(), qdate.day()):
                # Draw colored rect
                painter.fillRect(
                    rect.x(),
                    rect.y() + y,
                    rect.width(),
                    min(bounding_rect.height(), rect.height() - y),
                    self.chain_color_dict[chain],
                )

                # Draw text
                painter.setPen(self.Color.chain_name_color)
                completed_chains_num += 1
                painter.drawText(
                    rect.x() + x,
                    rect.y() + y,
                    width,
                    height,
                    QtCore.Qt.TextWordWrap,
                    chain,
                )

            y += bounding_rect.height()

        # Paint number of completed todo items
        if completed_chains_num > 0:
            if self.monthShown() != qdate.month():
                painter.setPen(self.Color.unselected_month_date_text)
            else:
                painter.setPen(self.Color.unselected_date_text)
            x = 40
            y = 5
            width = rect.width() - x
            painter.setFont(QtGui.QFont("Helvetica", 14))
            item_number_str = f"{completed_chains_num}"
            painter.drawText(
                rect.x() + x, rect.y() + y, width, rect.height(), 0, item_number_str
            )

        # Surround current date in a blue border
        if datetime.date.today() == date:
            painter.setPen(self.Color.selected_background)
            painter.drawRect(rect.x(), rect.y(), rect.width(), rect.height())
Beispiel #30
0
 def __transform_for_paint(self, image: Image.Image,
                           rect: QRect) -> Image.Image:
     return image.crop((rect.x() / self._zoom, rect.y() / self._zoom,
                        (rect.x() + rect.width()) / self._zoom,
                        (rect.y() + rect.height()) / self._zoom)).resize(
                            (rect.width(), rect.height()))
Beispiel #31
0
def paint_graticules(
        painter: 'QtGui.QPainter',
        rect: QRect) -> Tuple[Dict[float, float], Dict[float, QLineF]]:
    """Draw graticules and text markers using the QPainter api

    Graticules are calculated using :func:`get_graticules` then drawn on the
    given :class:`QtGui.QPainter`. IRE value labels are then drawn alternating
    on the left and right sides

    Arguments:
        painter (:class:`QtGui.QPainter`): The QPainter to draw with
        rect (:class:`QtGui.QRect`): The bounding box to use for drawing

    Returns
    -------
    ire_vals : dict
        A mapping of ire values to their normalized positions
    lines : dict
        A mapping of :class:`QtCore.QLineF` objects with their ire values as keys
    """

    ire_vals, graticules = get_graticules(rect)

    rect_w = rect.width()
    rect_h = rect.height()

    vertical_sp = graticules[10].y1() - graticules[20].y1()
    txt_flags = Qt.TextSingleLine

    bounding_rect = QtCore.QRectF(0, 0, rect_w, rect_h)

    font = QtGui.QFont('monospace', 12)
    fmetrics = QtGui.QFontMetrics(font)
    txt_box = fmetrics.size(txt_flags, '100')
    # logger.debug(f'{vertical_sp=}, {txt_box=}')
    while txt_box.height() > vertical_sp * .75:
        if font.pointSize() - 1 < 1:
            break
        font.setPointSize(font.pointSize() - 1)
        fmetrics = QtGui.QFontMetrics(font)
        txt_box = fmetrics.size(txt_flags, '100')
        # logger.debug(f'{vertical_sp=}, {txt_box=}')

    # logger.info('graticules font size: {}'.format(font.pointSize()))

    lh_flags = Qt.AlignLeft | Qt.AlignTop  # | Qt.TextSingleLine
    rh_flags = Qt.AlignRight | Qt.AlignTop  # | Qt.TextSingleLine

    painter.setFont(font)
    painter.setPen(QColor('yellow'))
    # logger.debug(f'graticule rect: {rect}')
    # logger.debug(f'graticules: {graticules}')

    txt_left = True
    for ire, line in graticules.items():
        ypos = line.y1()
        if ire == 0 or ire == 100:
            painter.setPen(QColor('white'))
        else:
            painter.setPen(QColor('yellow'))
        painter.drawLine(line)

        _txt_box = QRectF(0, 0, txt_box.width(), txt_box.height())

        if txt_left:
            _txt_box.moveTopLeft(QPointF(0, ypos))
            if bounding_rect | _txt_box == bounding_rect:
                painter.drawText(_txt_box, f'{ire:g}', lh_flags)
        else:
            _txt_box.moveTopRight(QPointF(rect_w, ypos))
            if bounding_rect | _txt_box == bounding_rect:
                painter.drawText(_txt_box, f'{ire:g}', rh_flags)
        txt_left = not txt_left
    return ire_vals, graticules