|  | #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Custom Mini Canvas Preview, a custom Qt4 widget
# Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the doc/GPL.txt file.
# ------------------------------------------------------------------------------------------------------------
# Imports (Config)
from carla_config import *
# ------------------------------------------------------------------------------------------------------------
# Imports (Global)
from math import floor
if config_UseQt5:
    from PyQt5.QtCore import pyqtSignal, Qt, QRectF, QTimer
    from PyQt5.QtGui import QBrush, QColor, QCursor, QPainter, QPen
    from PyQt5.QtWidgets import QFrame
else:
    from PyQt4.QtCore import pyqtSignal, Qt, QRectF, QTimer
    from PyQt4.QtGui import QBrush, QColor, QCursor, QFrame, QPainter, QPen
# ------------------------------------------------------------------------------------------------------------
# Antialiasing settings
from patchcanvas import options, ANTIALIASING_FULL
# ------------------------------------------------------------------------------------------------------------
# Static Variables
iX = 0
iY = 1
iWidth  = 2
iHeight = 3
# ------------------------------------------------------------------------------------------------------------
# Widget Class
class CanvasPreviewFrame(QFrame):
    miniCanvasMoved = pyqtSignal(float, float)
    # x = 2
    # y = 2
    # w = width-4
    # h = height-3
    # bounds -1 px
    kInternalWidth  = 210-6 # -4 for width + -1px*2 bounds
    kInternalHeight = 162-5 # -3 for height + -1px*2 bounds
    def __init__(self, parent):
        QFrame.__init__(self, parent)
        #self.setMinimumWidth(210)
        #self.setMinimumHeight(162)
        #self.setMaximumHeight(162)
        self.fRealParent = None
        self.fScene = None
        self.fRenderSource   = QRectF(0.0, 0.0, 0.0, 0.0)
        self.fRenderTarget   = QRectF(0.0, 0.0, 0.0, 0.0)
        self.fUseCustomPaint = False
        self.fInitialX = 0.0
        self.fScale    = 1.0
        self.fViewBg    = QColor(0, 0, 0)
        self.fViewBrush = QBrush(QColor(75, 75, 255, 30))
        self.fViewPen   = QPen(Qt.blue, 1)
        self.fViewRect  = [3.0, 3.0, 10.0, 10.0]
        self.fMouseDown = False
    def init(self, scene, realWidth, realHeight, useCustomPaint = False):
        self.fScene = scene
        self.fRenderSource = QRectF(0.0, 0.0, float(realWidth), float(realHeight))
        if self.fUseCustomPaint != useCustomPaint:
            self.fUseCustomPaint = useCustomPaint
            self.repaint()
    def setRealParent(self, parent):
        self.fRealParent = parent
    def setViewPosX(self, xp):
        self.fViewRect[iX] = (xp * self.kInternalWidth) - (xp * (self.fViewRect[iWidth]/self.fScale)) + xp
        self.update()
    def setViewPosY(self, yp):
        self.fViewRect[iY] = (yp * self.kInternalHeight) - (yp * (self.fViewRect[iHeight]/self.fScale)) + yp
        self.update()
    def setViewScale(self, scale):
        self.fScale = scale
        if self.fRealParent is not None:
            QTimer.singleShot(0, self.fRealParent.slot_miniCanvasCheckAll)
    def setViewSize(self, width, height):
        self.fViewRect[iWidth]  = width  * self.kInternalWidth
        self.fViewRect[iHeight] = height * self.kInternalHeight
        self.update()
    def setViewTheme(self, bgColor, brushColor, penColor):
        brushColor.setAlpha(40)
        penColor.setAlpha(100)
        self.fViewBg    = bgColor
        self.fViewBrush = QBrush(brushColor)
        self.fViewPen   = QPen(penColor, 1)
    def handleMouseEvent(self, eventX, eventY):
        x = float(eventX) - self.fInitialX
        y = float(eventY) - 3.0
        if x < 0.0:
            x = 0.0
        elif x > self.kInternalWidth:
            x = float(self.kInternalWidth)
        if y < 0.0:
            y = 0.0
        elif y > self.kInternalHeight:
            y = float(self.kInternalHeight)
        xp = x/self.kInternalWidth
        yp = y/self.kInternalHeight
        self.fViewRect[iX] = x - (xp * self.fViewRect[iWidth]/self.fScale) + xp
        self.fViewRect[iY] = y - (yp * self.fViewRect[iHeight]/self.fScale) + yp
        self.update()
        self.miniCanvasMoved.emit(xp, yp)
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.fMouseDown = True
            self.setCursor(QCursor(Qt.SizeAllCursor))
            self.handleMouseEvent(event.x(), event.y())
            return event.accept()
        QFrame.mouseMoveEvent(self, event)
    def mouseMoveEvent(self, event):
        if self.fMouseDown:
            self.handleMouseEvent(event.x(), event.y())
            return event.accept()
        QFrame.mouseMoveEvent(self, event)
    def mouseReleaseEvent(self, event):
        if self.fMouseDown:
            self.setCursor(QCursor(Qt.ArrowCursor))
            self.fMouseDown = False
            return event.accept()
        QFrame.mouseReleaseEvent(self, event)
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing == ANTIALIASING_FULL))
        if self.fUseCustomPaint:
            painter.setBrush(QColor(36, 36, 36))
            painter.setPen(QColor(62, 62, 62))
            painter.drawRect(2, 2, self.width()-4, self.height()-4)
            painter.setBrush(self.fViewBg)
            painter.setPen(self.fViewBg)
            painter.drawRect(3, 3, self.width()-6, self.height()-6)
        else:
            painter.setBrush(self.fViewBg)
            painter.setPen(self.fViewBg)
            painter.drawRoundedRect(3, 3, self.width()-6, self.height()-6, 3, 3)
        self.fScene.render(painter, self.fRenderTarget, self.fRenderSource, Qt.KeepAspectRatio)
        width  = self.fViewRect[iWidth]/self.fScale
        height = self.fViewRect[iHeight]/self.fScale
        if width > self.kInternalWidth:
            width = self.kInternalWidth
        if height > self.kInternalHeight:
            height = self.kInternalHeight
        # cursor
        lineHinting = painter.pen().widthF() / 2
        painter.setBrush(self.fViewBrush)
        painter.setPen(self.fViewPen)
        painter.drawRect(QRectF(
            floor(self.fViewRect[iX]+self.fInitialX)+lineHinting,
            floor(self.fViewRect[iY]+3)+lineHinting,
            round(width)-1, round(height)-1))
        if self.fUseCustomPaint:
            event.accept()
        else:
            QFrame.paintEvent(self, event)
    def resizeEvent(self, event):
        self.fInitialX     = float(self.width())/2.0 - float(self.kInternalWidth)/2.0
        self.fRenderTarget = QRectF(self.fInitialX, 3.0, float(self.kInternalWidth), float(self.kInternalHeight))
        if self.fRealParent is not None:
            QTimer.singleShot(0, self.fRealParent.slot_miniCanvasCheckAll)
        QFrame.resizeEvent(self, event)
 |