Esempio n. 1
0
    def setupUI(self):
        self.openGLWidget = QOpenGLWidget(self)  #Create the GLWidget
        self.openGLWidget.setGeometry(0, 0, self.sizeX, self.sizeY)
        self.openGLWidget.initializeGL()
        self.openGLWidget.resizeGL(
            self.sizeX, self.sizeY
        )  #Resize GL's knowledge of the window to match the physical size?
        self.openGLWidget.paintGL = self.paintGL  #override the default function with my own?

        if self.opMode != 'show':
            self.filterSlider = QSlider(Qt.Vertical, self)
            self.filterSlider.setGeometry(self.sizeX + 10,
                                          int(self.sizeY / 2) - 100, 30, 200)
            self.filterSlider.valueChanged[int].connect(self.barFilter)

            self.limitDisplay = QLabel(self)
            self.limitDisplay.setGeometry(self.sizeX,
                                          int(self.sizeY / 2) - 130, 50, 30)
            self.limitDisplay.setAlignment(Qt.AlignCenter)
            self.limitDisplay.setText('-1')

            self.marchButton = QPushButton(self)
            self.marchButton.setGeometry(self.sizeX,
                                         int(self.sizeY / 2) - 160, 50, 30)
            self.marchButton.setText('March!')
            self.marchButton.clicked.connect(self.marchStep)
    def __init__(self, programa):
        QOpenGLWidget.__init__(self)
        self.programa = programa
        self.desviacion_x = 0
        self.desviacion_y = 0
        self.desviacion_z = 0
        self.theta = 405
        self.phi = 45
        self.zoom = 150
        self.x = sin(radians(self.theta)) * cos(radians(
            self.phi)) + self.desviacion_x
        self.z = sin(radians(self.theta)) * sin(radians(
            self.phi)) + self.desviacion_z
        self.y = cos(radians(self.theta)) + self.desviacion_y

        # Vértices de los planos
        self.vertices_plano_vertical_arriba = ((500, 0, 500), (500, 0, 0),
                                               (-500, 0, 0), (-500, 0, 500))
        self.vertices_plano_vertical_debajo = ((500, 0, 0), (-500, 0, 0),
                                               (-500, 0, -500), (500, 0, -500))
        self.vertices_plano_horizontal_delante = ((500, 0, 0), (500, 500, 0),
                                                  (-500, 500, 0), (-500, 0, 0))
        self.vertices_plano_horizontal_detras = ((500, 0, 0), (500, -500, 0),
                                                 (-500, -500, 0), (-500, 0, 0))
        self.vertices_borde_plano_vertical = ((500, 0, 500), (-500, 0, 500),
                                              (-500, 0, -500), (500, 0, -500))
        self.vertices_borde_plano_horizontal = ((500, 500, 0), (500, -500, 0),
                                                (-500, -500, 0), (-500, 500,
                                                                  0))

        self.ultima_posicion = QPoint()

        self.m = [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]
 def resizeEvent(self, evento):
     # Mantiene una relación de aspecto cuadrada
     if self.width() > self.height():
         self.resize(self.height(), self.height())
     elif self.height() > self.width():
         self.resize(self.width(), self.width())
     QOpenGLWidget.resizeEvent(self, evento)
Esempio n. 4
0
 def __init__(self, parent, radius, quality):
     QOpenGLWidget.__init__(self, parent)
     self.__radius = radius
     self.__quality = quality
     self.__xRotation = 0
     self.__yRotation = 0
     self.__zRotation = 0
     self.__lastPoint = QPoint()
    def update(self):

        self._logger.debug('')

        self.update_model_view_projection_matrix()
        if IS_PYQT5:
            QOpenGLWidget.update(self)
        else:
            self.updateGL()
Esempio n. 6
0
 def initializeGL(self):
     QOpenGLWidget.makeCurrent(self.openGLWidget)
     gl.glEnable(gl.GL_BLEND)
     gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
     gl.glEnable(gl.GL_DEPTH_TEST)
     gl.glDepthMask(1)
     gl.glDepthFunc(gl.GL_LEQUAL)
     self.object = gl.glGenLists(self.NLists)
     gl.glNewList(self.object, gl.GL_COMPILE)
     gl.glEndList()
    def wheelEvent(self, evento):
        angulo = evento.angleDelta().y()
        if angulo < 0:
            self.zoom += 10
        elif angulo > 0:
            self.zoom -= 10

        if self.zoom < 10:
            self.zoom = 10

        QOpenGLWidget.wheelEvent(self, evento)
    def __init__(self, parent: QWidget = None):
        """
        On initialization, we need to bind the Ctrl/command key to
        enable manipulation of the view.
        """
        QGraphicsView.__init__(self, parent)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setRubberBandSelectionMode(Qt.IntersectsItemShape)
        self._no_drag = QGraphicsView.RubberBandDrag
        self._yes_drag = QGraphicsView.ScrollHandDrag

        # reset things that are state dependent
        self.clearGraphicsView()

        self._x0 = 0
        self._y0 = 0
        self._scale_size = 1.0
        self._scale_limit_max = 16.0  # OLD 3.0
        self._scale_limit_min = 0.21
        self._scale_up_rate = 0.01
        self._scale_down_rate = 0.01
        self._scale_fit_factor = .5  # sets initial zoom level
        self._show_details = True
        self._last_scale_factor = 0.0
        self.scene_root_item = None  # the item to transform
        # Keyboard panning
        self._key_pan_delta_x = styles.PATH_BASE_WIDTH * 21
        self._key_pan_delta_y = styles.PATH_HELIX_HEIGHT + styles.PATH_HELIX_PADDING / 2
        # Modifier keys and buttons
        self._key_mod = Qt.Key_Control
        self._button_pan: Qt.MouseButtons = Qt.LeftButton
        self._button_pan_alt: Qt.MouseButtons = Qt.MidButton
        self._button_zoom: Qt.MouseButtons = Qt.RightButton

        self.toolbar = None  # custom hack for the paint tool palette
        self._name = None

        # a ``SelectionItemGroup`` object when not ``None``
        self._selection_lock = None

        self.setContextMenuPolicy(Qt.CustomContextMenu)

        if GL:
            self.is_GL = True
            # self.glwidget = QGLWidget(QGLFormat(QGL.SampleBuffers))
            self.glwidget = QOpenGLWidget()
            # self.setupGL()
            self.gl = self.glwidget.context().versionFunctions()
            self.setViewport(self.glwidget)
            self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
            # self.resetGL()
        else:
            self.is_GL = False
            self.setViewportUpdateMode(QGraphicsView.MinimalViewportUpdate)
Esempio n. 9
0
    def update(self):

        self._logger.debug('')

        # if IS_QOpenGLWidget:
        self.makeCurrent()
        self.update_model_view_projection_matrix()
        if IS_QOpenGLWidget:
            QOpenGLWidget.update(self)
        else:
            self.updateGL()
Esempio n. 10
0
    def __init__(self, parent):
        QOpenGLWidget.__init__(self, parent)
        self.layers = []
        self.colorpalette_regions = [(1, 1, 1), (1, 0.7, 0.7), (0.7, 1, 0.7),
                                     (0.7, 0.7, 1)]

        self.colorpalette_paths = [(0, 0, 1), (0, 1, 0), (1, 0, 0), (0, 1, 1),
                                   (1, 0, 1), (1, 1, 0)]
        self.dim = 2
        self.zoom = 1.9
        self.rotation = np.zeros(2)
        self.translation = np.array([-0.5, -0.5, 0])
Esempio n. 11
0
    def __init__(self, obj_path, parent=None):
        super().__init__(parent)

        surface_format = QSurfaceFormat()
        surface_format.setSamples(16)
        QOpenGLWidget.setFormat(self, surface_format)

        self.projection = QMatrix4x4()
        self.vertex_buf_offsets = [3, 3, 2] #position, normal, tex_coord
        self.vertex_buf_stride = sum(self.vertex_buf_offsets)

        self.obj_path = obj_path
        self.initialized = False
Esempio n. 12
0
    def __init__(self, parent, debug=False):
        QOpenGLWidget.__init__(self, parent)
        global debugger
        debugger = Debug(debug, 'OpenGLWidget')
        self.debug = debug
        self.viewerTab = parent
        self.notebook = parent.notebook
        self.setMinimumSize(640, 672)
        self.lightingOn = True
        self.diffuseMaterialFactor = 0.9
        self.ambientMaterialFactor = 0.4
        self.specularMaterialFactor = 0.7
        self.glintMaterialFactor = 100.0
        self.diffuseLightFactor = 0.8
        self.ambientLightFactor = 0.6
        self.specularLightFactor = 1.0
        self.linearAttenuation = True
        self.image_size = 15.0
        self.white = np.array([1.0, 1.0, 1.0, 1.0])
        self.spheres = deque()
        self.cylinders = deque()
        self.arrows = deque()
        self.current_phase = 0
        self.phase_direction = 1
        self.number_of_phases = 1
        self.sphere_slices = 20
        self.sphere_stacks = 20
        self.cylinder_slices = 8
        self.cylinder_stacks = 2
        self.timer = None
        self.show_arrows = True
        self.timer_interval = 60
        self.my_width = None
        self.my_height = None
        self.background_colour = None

        self.show_full_screen = False
        self.writer = None
        self.rotation_centre = np.array([0.0, 0.0, 0.0])
        self.matrix = np.eye(4, dtype=np.float32)
        self.light_switches = None
        d = 200.0
        self.light_positions = [[-d, d, d], [d, -d, d], [-d, -d, d], [d, d, d],
                                [-d, d, -d], [d, -d, -d], [-d, -d, -d],
                                [d, d, -d]]
        self.lights = [
            GL_LIGHT0, GL_LIGHT1, GL_LIGHT2, GL_LIGHT3, GL_LIGHT4, GL_LIGHT5,
            GL_LIGHT6, GL_LIGHT7
        ]
Esempio n. 13
0
    def __init__(self, parent=None):
        super().__init__(parent)

        if USE_OPENGL and not isRemoteSession():
            fmt = QSurfaceFormat()
            fmt.setSamples(4)
            self.setViewport(QOpenGLWidget())
            self.viewport().setFormat(fmt)
            self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        else:
            self.setViewportUpdateMode(QGraphicsView.SmartViewportUpdate)

        layout = QFormLayout(self)
        layout.setContentsMargins(0, 0, 6, 0)
        layout.setFormAlignment(Qt.AlignRight | Qt.AlignBottom)
        self.minimap = MiniMapGraphicsView(self)
        layout.addWidget(self.minimap)
        self.setLayout(layout)

        self.setCacheMode(QGraphicsView.CacheBackground)
        self.setRenderHint(QPainter.Antialiasing)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QGraphicsView.AnchorViewCenter)
        
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setOptimizationFlags(QGraphicsView.DontSavePainterState | QGraphicsView.DontAdjustForAntialiasing)

        self.setStyleSheet(
            """NetworkView:focus {
                border: 3px solid palette(highlight);
            }""")
Esempio n. 14
0
    def __init__(self,
                 camera,
                 homography_transform,
                 stimulus_widget,
                 parent=None):
        super().__init__(parent)
        self._camera = camera
        self._homography_transform = homography_transform
        self.homography_points = []
        self.stimulus_widget = stimulus_widget

        current_directory = os.path.dirname(__file__)
        relative_location = '../views/StimulusWindowHomographySetup.ui'
        path = os.path.join(current_directory, relative_location)
        uic.loadUi(path, self)

        self.exposureDoubleSpinBox.device = camera

        self.gainDoubleSpinBox.device = camera

        self.cameraFrameGraphicsView.setViewport(QOpenGLWidget())

        self.camera_scene = self.cameraFrameGraphicsView.scene()

        self.camera_display = QGraphicsPixmapItem()
        self.camera_scene.addItem(self.camera_display)
        self.camera_display.setPos(0, 0)
        self.camera_scene.installEventFilter(ClickCapture(self))

        self.first_shown = True
Esempio n. 15
0
 def __init__(self, parent=None):
     super().__init__(parent)
     self.setViewport(QOpenGLWidget())
     scene = QGraphicsScene()
     scene.setBackgroundBrush(Qt.gray)
     self.setScene(scene)
     self.setMouseTracking(True)
Esempio n. 16
0
    def paintGL(self):
        QOpenGLWidget.makeCurrent(self.openGLWidget)
        ambient = [1.0, 1.0, 1.0, 0.04]
        lightpos = [1.0, 10.0, 100.0]
        gl.glLightModelfv(gl.GL_LIGHT_MODEL_AMBIENT,
                          ambient)  # Определяем текущую модель освещения
        gl.glEnable(gl.GL_LIGHTING)
        gl.glEnable(gl.GL_LIGHT0)
        gl.glEnable(gl.GL_DEPTH_TEST)
        gl.glEnable(gl.GL_COLOR_MATERIAL)
        gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION,
                     lightpos)  # Определяем положение источника света
        try:
            self.prepere_scene()
            if self.active:
                self.prepare_orientation()
                if self.ViewAtoms:
                    gl.glCallList(self.object)  # atoms

                if self.CanSearch:
                    self.get_atom_on_screen()

                if self.ViewBonds and (len(self.MainModel.bonds) > 0):
                    gl.glCallList(self.object + 2)  # find_bonds_exact

                if self.ViewVoronoi:
                    gl.glCallList(self.object + 1)  # Voronoi

                if self.ViewBox:
                    gl.glCallList(self.object +
                                  3)  # lattice_parameters_abc_angles

                if self.ViewSurface:
                    gl.glCallList(self.object + 4)  # Surface

                if self.ViewContour:
                    gl.glCallList(self.object + 5)  # Contour

                if self.ViewContourFill:
                    gl.glCallList(self.object + 6)  # ContourFill

                if self.ViewAxes:
                    gl.glCallList(self.object + 7)  # Axes

        except Exception as exc:
            print(exc)
            pass
Esempio n. 17
0
 def __init__(self, scene):
     super(self.__class__, self).__init__(scene)
     self._scene = scene
     self.setViewport(QOpenGLWidget())
     self.setDragMode(QGraphicsView.ScrollHandDrag)
     self.fitInView(self._scene.sceneRect(), Qt.KeepAspectRatio)
     self._scene.get_sprites().set_scale(self.transform().m11())
     self.update()
Esempio n. 18
0
    def __init__(self, obj_path, parent=None):
        super().__init__(parent)

        surface_format = QSurfaceFormat()
        surface_format.setSamples(16)
        QOpenGLWidget.setFormat(self, surface_format)

        self.projection = QMatrix4x4()
        self.vertex_buf_offsets = [3, 3, 2]  # position, normal, tex_coord
        self.vertex_buf_stride = sum(self.vertex_buf_offsets)

        self.obj_path = obj_path
        self.initialized = False

        if not has_libGL:
            get_main_window().show_status(
                'OpenGL library not found. Disabling 3D view.')
Esempio n. 19
0
 def __init__(self, mode):
     super(mainWindow, self).__init__()
     self.setGeometry(0, 0, 500, 500)
     self.openGLWidget = QOpenGLWidget(self)
     self.openGLWidget.setGeometry(0, 0, 500, 500)
     if mode == 'unsafe':
         self.shader = _shader(self, self.openGLWidget)
         self.shader.resize(500, 500)
         #self.cube1 = cube((0, 0, 0))
         #self.cube2 = cube((1, 0, 0))
         #self.cube3 = cube((0, 0, 1))
         #self.shader.addShapes(self.cube1, self.cube2, self.cube3)
         #self.shader.navigate(vVal = -45)
         #self.shader.update()
     else:
         with shaderManager(self, self.openGLWidget) as shader:
             self.shader = shader
             self.shader.resize(500, 500)
Esempio n. 20
0
    def toggleOpenGL(self):
        vp = QWidget()

        if self.openGlButton.isChecked():
            fmt = QSurfaceFormat()
            fmt.setSamples(8)
            vp = QOpenGLWidget()
            vp.setFormat(fmt)

        self.graphicsView.setViewport(vp)
Esempio n. 21
0
    def __init__(self, parent: QWidget = None):
        """
        On initialization, we need to bind the Ctrl/command key to
        enable manipulation of the view.
        """
        QGraphicsView.__init__(self, parent)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setRubberBandSelectionMode(Qt.IntersectsItemShape)
        self._no_drag = QGraphicsView.RubberBandDrag
        self._yes_drag = QGraphicsView.ScrollHandDrag

        # reset things that are state dependent
        self.clearGraphicsView()

        self._x0 = 0
        self._y0 = 0
        self._scale_size = 1.0
        self._scale_limit_max = 16.0  # OLD 3.0
        self._scale_limit_min = 0.21
        self._scale_up_rate = 0.01
        self._scale_down_rate = 0.01
        self._scale_fit_factor = .5  # sets initial zoom level
        self._show_details = True
        self._last_scale_factor = 0.0
        self.scene_root_item = None  # the item to transform
        # Keyboard panning
        self._key_pan_delta_x = styles.PATH_BASE_WIDTH * 21
        self._key_pan_delta_y = styles.PATH_HELIX_HEIGHT + styles.PATH_HELIX_PADDING/2
        # Modifier keys and buttons
        self._key_mod = Qt.Key_Control
        self._button_pan: Qt.MouseButtons = Qt.LeftButton
        self._button_pan_alt: Qt.MouseButtons = Qt.MidButton
        self._button_zoom: Qt.MouseButtons = Qt.RightButton

        self.toolbar = None  # custom hack for the paint tool palette
        self._name = None

        # a ``SelectionItemGroup`` object when not ``None``
        self._selection_lock = None

        self.setContextMenuPolicy(Qt.CustomContextMenu)

        if GL:
            self.is_GL = True
            # self.glwidget = QGLWidget(QGLFormat(QGL.SampleBuffers))
            self.glwidget = QOpenGLWidget()
            # self.setupGL()
            self.gl = self.glwidget.context().versionFunctions()
            self.setViewport(self.glwidget)
            self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
            # self.resetGL()
        else:
            self.is_GL = False
            self.setViewportUpdateMode(QGraphicsView.MinimalViewportUpdate)
Esempio n. 22
0
    def __init__(self, parent):
        QOpenGLWidget.__init__(self, parent=parent)

        # Adding samples
        format = QSurfaceFormat()
        format.setSamples(8)
        self.setFormat(format)

        self.programLocations: Dict[str, GLuint]

        self.view: View = View()
        self.functionModel = FunctionModel(2)
        self.axesModel = AxisModel()
        self.evalPointsModel = EvalPointsModel()
        self.evalLinesModel = EvalLinesModel()
        self.userModels = []
        self.locations = {}

        self.screenView = None
        self.mouse: List[int] = None
        self.setMouseTracking(True)
Esempio n. 23
0
    def Setup(self):
        self.setWindowTitle("Thwacker")
        self.setWindowIcon(QIcon())

        self.setMinimumSize(QSize(750,500))

        #ContentSections
        self.Content = QGroupBox()
        self.ContentLayout = QGridLayout()

        # ToolBar
        ToolsToolBar = QToolBar('Tools')
        self.Tools = self.addToolBar(Qt.LeftToolBarArea,ToolsToolBar)

        #OpenGl
        self.GlViewport = QOpenGLWidget()
        self.GlViewport.initializeGL()
        self.GlViewport.paintGL = self.paintGL
        self.GlViewport.initializeGL = self.initializeGL

        self._glTimer = QBasicTimer()
        self._glTimer.start(1000/60, self)

        self.VMFVerts = []
        self.ReadVmf('./test.vmf')
        
        self.ContentLayout.addWidget(self.GlViewport,0,0)
        gluPerspective(45, self.width()/self.height(), 0.1, 50)

        self.Triangle = self.VMFVerts
        self.Indices = [] ;
        for i in range(len(self.VMFVerts)): self.Indices.append(i)
        

        self.Content.setLayout(self.ContentLayout)
        QApplication.setStyle(QStyleFactory.create('Cleanlooks'))
        self.setCentralWidget(self.Content)
        self.showMaximized()
        self.update()
Esempio n. 24
0
 def __init__(self, parent, samplerate, duration, texsize, moreUniforms={}):
     QOpenGLWidget.__init__(self, parent)
     self.move(10000., 1000.)
     self.program = 0
     self.iSampleRateLocation = 0
     self.iBlockOffsetLocation = 0
     self.hasShader = False
     self.duration = duration
     self.samplerate = samplerate
     self.texsize = texsize
     self.blocksize = self.texsize * self.texsize
     self.nsamples = self.duration * self.samplerate  # it was *2
     self.nblocks = int(ceil(float(self.nsamples) / float(self.blocksize)))
     self.nsamples_real = self.nblocks * self.blocksize  # this too was *2
     self.duration_real = float(self.nsamples_real) / float(self.samplerate)
     self.music = None
     self.floatmusic = None
     self.moreUniforms = moreUniforms
     self.sequence_texture_handle = None
     self.sequence_texture = None
     self.sequence_texture_size = None
     self.setTextureFormat(GL_RGBA)
    def keyPressEvent(self, evento):
        if evento.key() == Qt.Key_W:
            self.theta -= 1
        elif evento.key() == Qt.Key_A:
            self.phi -= 1
        elif evento.key() == Qt.Key_S:
            self.theta += 1
        elif evento.key() == Qt.Key_D:
            self.phi += 1
        elif evento.key() == Qt.Key_Q:
            self.desviacion_z += 1
        elif evento.key() == Qt.Key_E:
            self.desviacion_z -= 1
        elif evento.key() == Qt.Key_Left:
            self.desviacion_x += 1
        elif evento.key() == Qt.Key_Up:
            self.desviacion_y += 1
        elif evento.key() == Qt.Key_Right:
            self.desviacion_x -= 1
        elif evento.key() == Qt.Key_Down:
            self.desviacion_y -= 1
        elif evento.key() == Qt.Key_1:
            self.ver_alzado()
        elif evento.key() == Qt.Key_2:
            self.ver_planta()
        elif evento.key() == Qt.Key_3:
            self.ver_perfil()
        elif evento.key() == Qt.Key_R:
            self.ver_reset()
        elif evento.key() == Qt.Key_Minus:
            self.zoom += 10
        elif evento.key() == Qt.Key_Plus:
            self.zoom -= 10

        self.recalcular_posicion()

        self.update()
        QOpenGLWidget.keyPressEvent(self, evento)
Esempio n. 26
0
    def __init__(self, parent=None):
        super(ASCGraphicsView, self).__init__(parent)
        self.scene = QGraphicsScene(self)

        self.raw_img_item = QGraphicsPixmapItem()
        self.raw_img_item.setZValue(0)
        self.anno_img_item = QGraphicsPixmapItem()
        self.anno_img_item.setZValue(1)

        self.cross_bar_v_line_item = QGraphicsLineItem()
        self.cross_bar_h_line_item = QGraphicsLineItem()
        self.cross_bar_v_line_item.setZValue(100)
        self.cross_bar_h_line_item.setZValue(100)
        self.cross_bar_v_line_item.setPen(
            QPen(Qt.blue, 0, Qt.DotLine, Qt.FlatCap, Qt.RoundJoin))
        self.cross_bar_h_line_item.setPen(
            QPen(Qt.blue, 0, Qt.DotLine, Qt.FlatCap, Qt.RoundJoin))

        self.paint_brush_circle_item = QGraphicsEllipseItem()
        self.paint_brush_rect_item = QGraphicsPolygonItem()
        self.paint_brush_circle_item.setZValue(10)
        self.paint_brush_rect_item.setZValue(11)
        self.paint_brush_circle_item.setVisible(False)
        self.paint_brush_rect_item.setVisible(False)
        self.paint_brush_circle_item.setPen(
            QPen(Qt.red, 0, Qt.DotLine, Qt.FlatCap, Qt.RoundJoin))
        self.paint_brush_rect_item.setPen(
            QPen(Qt.red, 0, Qt.DotLine, Qt.FlatCap, Qt.RoundJoin))

        self.scene.addItem(self.raw_img_item)
        self.scene.addItem(self.anno_img_item)
        self.scene.addItem(self.cross_bar_v_line_item)
        self.scene.addItem(self.cross_bar_h_line_item)
        self.scene.addItem(self.paint_brush_circle_item)
        self.scene.addItem(self.paint_brush_rect_item)

        self.setScene(self.scene)
        self.setViewport(QOpenGLWidget())

        self._last_button_press = Qt.NoButton
        self._last_pos_middle_button = None
        self._last_pos_right_button = None

        self._brush_stats = {'type': BRUSH_TYPE_NO_BRUSH, 'size': 5}

        self.setResizeAnchor(QGraphicsView.AnchorViewCenter)

        self.slice_scroll_bar = None
        self.image_size = None
        self.is_valid = False
Esempio n. 27
0
    def setupUI(self):
        self.openGLWidget = QOpenGLWidget(self)  #Create the GLWidget
        self.openGLWidget.setGeometry(0, 0, self.width, self.height)
        self.openGLWidget.initializeGL()
        self.openGLWidget.resizeGL(
            self.width, self.height
        )  #Resize GL's knowledge of the window to match the physical size?
        self.openGLWidget.paintGL = self.paintGL  #override the default function with my own?

        self.marchButton = QPushButton(self)
        self.marchButton.setGeometry(350, self.height, 60, 25)
        self.marchButton.setText('Step 0')
        self.marchButton.clicked.connect(self.cycle)

        self.readout = QLabel(self)
        self.readout.setGeometry(240, self.height, 110, 25)
        self.readout.setText("[0, 0, 0, 0, 0, 0, 0, 0]")

        self.indicators = []
        for i in range(8):
            indicator = QWidget(self)
            indicator.setGeometry(i * 30, self.height, 25, 25)
            indicator.setStyleSheet("background-color: blue;")
            self.indicators.append(indicator)
Esempio n. 28
0
    def __init__(self, args):
        super(TestApplication, self).__init__(args)

        print("EFFECTIVE QT VERSION : " + str(QT_VERSION_STR))

        self.mainWin = QWidget()
        self.mainWin.resize(600, 600)
        self.mainWin.setWindowTitle('Minimal GL test')

        self.mainWidget = QOpenGLWidget()
        self.layout = QVBoxLayout(self.mainWin)
        self.layout.addWidget(self.mainWidget)

        self.mainWin.show()

        ctx = QOpenGLContext.currentContext()
        format = ctx.format()

        print("EFFECTIVE GL VERSION : " + str(ctx.format().version()))
Esempio n. 29
0
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        # Render on OpenGL
        self.setViewport(QOpenGLWidget())

        self.xvalues = {}

        self.chart = QChart()

        self.setChart(self.chart)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignTop)
        self.ncurves = 0
        self.setRenderHint(QPainter.Antialiasing)

        # Cursor (with chart as parent)
        self.cursor = QGraphicsLineItem(self.chart)

        self.cursor.setZValue(100.0)
        # self.scene().addItem(self.cursor)

        # Selection features
        # self.setRubberBand(QChartView.HorizontalRubberBand)
        self.selectionBand = QRubberBand(QRubberBand.Rectangle, self)
        self.selecting = False
        self.initialClick = QPoint()

        # Track mouse
        self.setMouseTracking(True)

        self.labelValue = QLabel(self)
        self.labelValue.setStyleSheet(
            "background-color: rgba(255,255,255,75%); color: black;")
        self.labelValue.setAlignment(Qt.AlignCenter)
        self.labelValue.setMargin(5)
        self.labelValue.setVisible(False)

        self.build_style()

        self.selection_start_time = None
        self.selection_stop_time = None
        self.cursor_time = None
Esempio n. 30
0
    def __init__(self, homography_transform, intensity_mask, parent=None):
        super().__init__(parent)
        self._crosshair = False
        self._crosshair_thickness = 1
        self._apply_intensity_mask = False
        self._invert = False
        self.setViewport(QOpenGLWidget())
        self.gaussian_shader_program = QOpenGLShaderProgram()
        self.homography_transform = homography_transform
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.horizontalScrollBar().disconnect()
        self.verticalScrollBar().disconnect()
        self.intensity_mask = intensity_mask

        self.intensity_mask_renderer = GaussianIntensityMaskRenderer(
            parent=self)

        # background_brush = QBrush()
        # background_brush.setStyle(Qt.SolidPattern)
        # background_brush.setColor(Qt.black)
        # self.setBackgroundBrush(background_brush)

        self.horizontal_line = QGraphicsLineItem()
        self.vertical_line = QGraphicsLineItem()

        self.setTransformationAnchor(QGraphicsView.NoAnchor)

        self.horizontal_line.setLine(0, 1080 / 2, 1920, 1080 / 2)
        self.vertical_line.setLine(1920 / 2, 0, 1920 / 2, 1080)

        self.pen = QPen(Qt.white)
        self.horizontal_line.setPen(self.pen)
        self.vertical_line.setPen(self.pen)

        self.view_matrix = QMatrix4x4()
        self.dx = 0
        self.dy = 0
        self.angle = 0
        self.scale_value = 1

        self.setSceneRect(0, 0, 9000, 9000)
Esempio n. 31
0
 def show(self):
     self.main_view.setViewport(QOpenGLWidget())
     self.main_view.setRenderHint(QPainter.Antialiasing)
     self.main_view.show()
Esempio n. 32
0
class CustomQGraphicsView(QGraphicsView):
    """
    Base class for QGraphicsViews with Mouse Zoom and Pan support via the
    Control/Command shortcut key.

    A QGraphics View stores info on the view and handles mouse events for
    zooming and panning

    Ctrl-MidMouseButton = Pan
    Ctrl-RightMouseButton = Dolly Zoom
    MouseWheel = Zoom

    Args:
        parent(QWidget): type of QWidget such as QWidget.main_splitter() for the type of
                         View its has

    For details on these and other miscellaneous methods, see below.
    """
    def __init__(self, parent=None):
        """
        On initialization, we need to bind the Ctrl/command key to
        enable manipulation of the view.
        """
        QGraphicsView.__init__(self, parent)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setRubberBandSelectionMode(Qt.IntersectsItemShape)
        self._no_drag = QGraphicsView.RubberBandDrag
        self._yes_drag = QGraphicsView.ScrollHandDrag

        # reset things that are state dependent
        self.clearGraphicsView()

        self._x0 = 0
        self._y0 = 0
        self._scale_size = 1.0
        self._scale_limit_max = 24.0  # OLD 3.0
        self._scale_limit_min = 0.21
        self._scale_up_rate = 0.01
        self._scale_down_rate = 0.01
        self._scale_fit_factor = .5  # sets initial zoom level
        self._show_details = True
        self._last_scale_factor = 0.0
        self.scene_root_item = None  # the item to transform
        # Keyboard panning
        self._key_pan_delta_x = styles.PATH_BASE_WIDTH * 21
        self._key_pan_delta_y = styles.PATH_HELIX_HEIGHT + styles.PATH_HELIX_PADDING/2
        # Modifier keys and buttons
        self._key_mod = Qt.Key_Control
        self._button_pan = Qt.LeftButton
        self._button_pan_alt = Qt.MidButton
        self._button_zoom = Qt.RightButton

        self.toolbar = None  # custom hack for the paint tool palette
        self._name = None

        self.setContextMenuPolicy(Qt.CustomContextMenu)

        if GL:
            self.is_GL = True
            # self.glwidget = QGLWidget(QGLFormat(QGL.SampleBuffers))
            self.glwidget = QOpenGLWidget()
            # self.setupGL()
            self.gl = self.glwidget.context().versionFunctions()
            self.setViewport(self.glwidget)
            self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
            # self.resetGL()
        else:
            self.is_GL = False
            self.setViewportUpdateMode(QGraphicsView.MinimalViewportUpdate)
            # self.setViewportUpdateMode(QGraphicsView.SmartViewportUpdate)
        # self.setFocusPolicy(Qt.ClickFocus)
    # end def

    levelOfDetailChangedSignal = pyqtSignal(bool)

    def __repr__(self):
        clsName = self.__class__.__name__
        objId = self._name if self._name else str(id(self))[-4:]
        return "<%s %s>" % (clsName, objId)

    def setName(self, name):
        self._name = name
    # end def

    def setViewportUpdateOn(self, is_enabled):
        if is_enabled:
            self.setViewportUpdateMode(QGraphicsView.MinimalViewportUpdate)
        else:
            self.setViewportUpdateMode(QGraphicsView.NoViewportUpdate)
    # end def

    def activateSelection(self, is_active):
        if self._selection_lock:
            self._selection_lock.clearSelection(False)
        self.clearSelectionLockAndCallbacks()
        if is_active:
            self._no_drag = QGraphicsView.RubberBandDrag
        else:
            self._no_drag = QGraphicsView.NoDrag
        if self.dragMode() != self._yes_drag:
            self.setDragMode(self._no_drag)
    # end def

    def clearGraphicsView(self):
        # Event handling
        self._has_focus = False
        # Misc
        self.clearSelectionLockAndCallbacks()
        # Pan and dolly defaults
        self._transform_enable = False
        self._dolly_zoom_enable = False
        self.setDragMode(self._no_drag)
    # end def

    def clearSelectionLockAndCallbacks(self):
        self._selection_lock = None # a selection group to limit types of items selected
        self._press_list = [] # bookkeeping to handle passing mouseReleaseEvents to QGraphicsItems that don't get them
    # end def

    def _setGLView(self, boolval):
        scene = self.scene()
        if boolval and self.is_GL is False:
            self.is_GL = True
            # scene.drawBackground = self._drawBackgroundGL
            # self.setViewport(QGLWidget(QGLFormat(QGL.SampleBuffers)))
            # self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        elif not boolval and self.is_GL is True:
            self.is_GL = False
            # scene.drawBackground = self.drawBackgroundNonGL
            # self.setViewport(QWidget())
            # self.setViewportUpdateMode(QGraphicsView.MinimalViewportUpdate)
    # end def

    def setupGL(self):
        scene = self.scene()
        # win = self.scene_root_item.window()
        self.is_GL = True
        self.is_GL_switch_allowed = True
        self.qTimer = QTimer()
        # self.drawBackgroundNonGL = scene.drawBackground
        # scene.drawBackground = self._drawBackgroundGL
        # format = QGLFormat(QGL.SampleBuffers)
        # format.setSamples(16)
        # print "# of samples", format.samples(), format.sampleBuffers()
        # self.setViewport(QGLWidget(format))
        # self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
    # end def

    def _resetLOD(self):
        scale_factor = self.transform().m11()
        # print("scale_factor", scale_factor)
        self.scene_root_item.window().statusBar().showMessage("%0.2f" % scale_factor)
        if scale_factor < 0.75:
            self._show_details = False
            self.levelOfDetailChangedSignal.emit(False) # zoomed out
        elif scale_factor > 0.8:
            self._show_details = True
            self.levelOfDetailChangedSignal.emit(True) # zoomed in
    # end def

    def _resetGL(self):
        scale_factor = self.transform().m11()
        # print("scale_factor", scale_factor)
        self.scene_root_item.window().statusBar().showMessage("%0.2f" % scale_factor)

        if scale_factor < .15:# and self.is_GL_switch_allowed:
            # self.is_GL_switch_allowed = False
            self._setGLView(True)
            self._show_details = False
            self.levelOfDetailChangedSignal.emit(False) # zoomed out
            self.qTimer.singleShot(500, self._allowGLSwitch)
        elif scale_factor > .2:# and self.is_GL_switch_allowed:
            # self.is_GL_switch_allowed = False
            self._setGLView(False)
            self._show_details = True
            self.levelOfDetailChangedSignal.emit(True) # zoomed in
            self.qTimer.singleShot(500, self._allowGLSwitch)
    # end def

    def shouldShowDetails(self):
        return self._show_details
    # end def

    def _allowGLSwitch(self):
        self.is_GL_switch_allowed = True
    # end def

    def _drawBackgroundGL(self, painter, rect):
        """
        This method is for overloading the QGraphicsScene.
        """
        if painter.paintEngine().type() != QPaintEngine.OpenGL and \
            painter.paintEngine().type() != QPaintEngine.OpenGL2:

            qWarning("OpenGLScene: drawBackground needs a QGLWidget to be set as viewport on the graphics view");
            return
        # end if
        painter.beginNativePainting()
        GL.glDisable(GL.GL_DEPTH_TEST) # disable for 2D drawing
        GL.glClearColor(1.0, 1.0, 1.0, 1.0)
        GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)

        painter.endNativePainting()
    # end def

    def focusInEvent(self, event):
        self._has_focus = True

    def focusOutEvent(self, event):
        self._transform_enable = False
        self._dolly_zoom_enable = False
        self._has_focus = False
        self._transform_enable = False
    # end def

    def setSelectionLock(self, selection_lock):
        self._selection_lock = selection_lock
    # end def

    def selectionLock(self):
        return self._selection_lock
    # end def

    def setScaleFitFactor(self, value):
        """docstring for setScaleFitFactor"""
        self._scale_fit_factor = value
    # end def

    def setKeyPan(self, button):
        """Set the class pan button remotely"""
        self._button_pan = button
    # end def

    def addToPressList(self, item):
        """docstring for addToPressList"""
        # self._press_list[self._press_list_idx].append(item)
        self._press_list.append(item)
    # end def

    def keyPanDeltaX(self):
        """Returns the distance in scene space to move the scene_root_item when
        panning left or right."""
        # PyQt isn't aware that QGraphicsObject isa QGraphicsItem and so
        # it returns a separate python object if, say, childItems() returns
        # a QGraphicsObject casted to a QGraphicsItem. If this is the case,
        # we can still find the QGraphicsObject thusly:
        candidateDxDeciders = list(self.scene_root_item.childItems())
        candidateDxDeciders = candidateDxDeciders +\
                           [cd.toGraphicsObject() for cd in candidateDxDeciders]
        for cd in candidateDxDeciders:
            if cd is None:
                continue
            keyPanDXMethod = getattr(cd, 'keyPanDeltaX', None)
            if keyPanDXMethod is not None:
                return keyPanDXMethod()
        return 100

    def keyPanDeltaY(self):
        """Returns the distance in scene space to move the scene_root_item when
        panning left or right."""
        candidateDyDeciders = list(self.scene_root_item.childItems())
        candidateDyDeciders = candidateDyDeciders +\
                           [cd.toGraphicsObject() for cd in candidateDyDeciders]
        for cd in candidateDyDeciders:
            if cd is None:
                continue
            keyPanDYMethod = getattr(cd, 'keyPanDeltaY', None)
            if keyPanDYMethod is not None:
                return keyPanDYMethod()
        return 100

    def keyPressEvent(self, event):
        """
        Handle key presses for mouse-drag transforms and arrow-key panning.
        """
        if not self._has_focus:  # we don't have focus -> ignore keypress
            return
        if event.key() == self._key_mod:
            self._transform_enable = True
            QGraphicsView.keyPressEvent(self, event)
        elif event.key() == Qt.Key_Left:
            transform = self.scene_root_item.transform()
            transform.translate(self.keyPanDeltaX(), 0)
            self.scene_root_item.setTransform(transform)
        elif event.key() == Qt.Key_Up:
            transform = self.scene_root_item.transform()
            transform.translate(0, self.keyPanDeltaY())
            self.scene_root_item.setTransform(transform)
        elif event.key() == Qt.Key_Right:
            transform = self.scene_root_item.transform()
            transform.translate(-self.keyPanDeltaX(), 0)
            self.scene_root_item.setTransform(transform)
        elif event.key() == Qt.Key_Down:
            transform = self.scene_root_item.transform()
            transform.translate(0, -self.keyPanDeltaY())
            self.scene_root_item.setTransform(transform)
        elif event.key() == Qt.Key_Plus:
            self.zoomIn(0.3)
        elif event.key() == Qt.Key_Minus:
            self.zoomIn(0.03)
        else:
            return QGraphicsView.keyPressEvent(self, event)
        # end else
    # end def

    def keyReleaseEvent(self, event):
        """docstring for keyReleaseEvent"""
        if event.key() == self._key_mod:
            self._transform_enable = False
            self._dolly_zoom_enable = False
            self._panDisable()
        # end if
        else:
            QGraphicsView.keyReleaseEvent(self, event)
        # end else
    # end def

    def enterEvent(self, event):
        # self.setFocus() # this call robs selection from key focus
        self.setDragMode(self._no_drag)
        QGraphicsView.enterEvent(self, event)

    def leaveEvent(self, event):
        self.clearFocus()
        QGraphicsView.leaveEvent(self, event)

    def mouseMoveEvent(self, event):
        """
        Must reimplement mouseMoveEvent of QGraphicsView to allow
        ScrollHandDrag due to the fact that events are intercepted
        breaks this feature.
        """
        if self._transform_enable == True:
            if self.dragMode() == self._yes_drag:
                # Add stuff to handle the pan event
                posf = event.localPos()
                xf = posf.x()
                yf = posf.y()

                factor = self.transform().m11()

                transform = self.scene_root_item.transform()
                transform.translate((xf - self._x0)/factor,\
                                             (yf - self._y0)/factor)
                self.scene_root_item.setTransform(transform)

                self._x0 = xf
                self._y0 = yf
            elif self._dolly_zoom_enable == True:
                self.dollyZoom(event)
        # adding this allows events to be passed to items underneath
        QGraphicsView.mouseMoveEvent(self, event)
    # end def

    def mousePressEvent(self, event):
        """docstring for mousePressEvent"""
        if self._transform_enable == True and qApp.keyboardModifiers():
            which_buttons = event.buttons()
            if which_buttons in [self._button_pan, self._button_pan_alt]:
                self._panEnable()
                posf = event.localPos()
                self._x0 = posf.x()
                self._y0 = posf.y()
            elif which_buttons == self._button_zoom:
                self._dolly_zoom_enable = True
                self._last_scale_factor = 0
                # QMouseEvent.y() returns the position of the mouse cursor
                # relative to the widget
                self._y0 = event.localPos().y()
            else:
                QGraphicsView.mousePressEvent(self, event)
        else:
            QGraphicsView.mousePressEvent(self, event)
    # end def

    def mouseReleaseEvent(self, event):
        """If panning, stop. If handles were pressed, release them."""
        if self._transform_enable == True:
            # QMouseEvent.button() returns the button that triggered the event
            which_button = event.button()
            if which_button in [self._button_pan, self._button_pan_alt]:
                self._panDisable()
            elif which_button == self._button_zoom:
                self._dolly_zoom_enable = False
            else:
                return QGraphicsView.mouseReleaseEvent(self, event)
        # end if
        else:
            if len(self._press_list):  # Notify any pressed items to release
                event_pos = event.pos()
                for item in self._press_list:
                    #try:
                    # print("item release", item)
                    item.customMouseRelease(event)
                    #except:
                    #    item.mouseReleaseEvent(event)
                #end for
                self._press_list = []
            # end if
            if self._selection_lock:
                self._selection_lock.processPendingToAddList()
            return QGraphicsView.mouseReleaseEvent(self, event)

    # end def

    def _panEnable(self):
        """Enable ScrollHandDrag Mode in QGraphicsView (displays a hand
        pointer)"""
        self.setDragMode(self._yes_drag)
    # end def

    def _panDisable(self):
        """Disable ScrollHandDrag Mode in QGraphicsView (displays a hand
        pointer)"""
        self.setDragMode(self._no_drag)
    # end def

    def fname(self):
        """docstring for fname"""
        pass

    def wheelEvent(self, event):
        self.safeScale(event.angleDelta().y())
    # end def

    def safeScale(self, delta):
        current_scale_level = self.transform().m11()
        scale_factor = 1 + delta * \
           (self._scale_down_rate if delta < 0 else self._scale_up_rate) * \
           (app().prefs.zoom_speed/100.)
        new_scale_level = current_scale_level * scale_factor
        new_scale_level = util.clamp(current_scale_level * scale_factor,\
                              self._scale_limit_min,\
                              self._scale_limit_max)
        scale_change = new_scale_level / current_scale_level
        self.scale(scale_change, scale_change)

        self._resetLOD()
    # end def

    def zoomIn(self, fraction_of_max=0.5):
        current_scale_level = self.transform().m11()
        scale_change = (fraction_of_max * self._scale_limit_max) / current_scale_level
        self.scale(scale_change, scale_change)
    # end def

    def zoomOut(self, fraction_of_min=1):
        current_scale_level = self.transform().m11()
        scale_change = (fraction_of_min * self._scale_limit_min) / current_scale_level
        self.scale(scale_change, scale_change)
    # end def

    def dollyZoom(self, event):
        """docstring for dollyZoom"""
        # QMouseEvent.y() returns the position of the mouse cursor relative
        # to the widget
        yf = event.y()
        denom = abs(yf - self._y0)
        if denom > 0:
            scale_factor = (self.height() / 2) % denom
            if self._last_scale_factor != scale_factor:
                self._last_scale_factor = scale_factor
                # zoom in if mouse y position is getting bigger
                if yf - self._y0 > 0:
                    self.safeScale(yf - self._y0)
                # end else
                else:  # else id smaller zoom out
                    self.safeScale(yf - self._y0)
                # end else
        # end if
    # end def

    def _resetScale(self):
        """reset the scale to 1"""
        # use the transform value if you want to get how much the view
        # has been scaled
        self._scale_size = self.transform().m11()

        # self._scale_limit_min = 0.41*self._scale_size
        # make it so fitting in view is zoomed minimum
        # still gives you one zoom level out before violates limit
        self._scale_limit_min = self._scale_size*self._scale_fit_factor

        # use this if you want to reset the zoom in limit
        # self._scale_limit_max = 3.0*self._scale_size

        self._last_scale_factor = 0.0
    # end def

    def zoomToFit(self):
        # print("zoom to fit", self._name)
        # Auto zoom to center the scene
        thescene = self.scene_root_item.scene()
        # order matters?
        self.scene_root_item.resetTransform() # zero out translations
        self.resetTransform() # zero out scaling
        if self.toolbar:  # HACK: move toolbar so it doesn't affect sceneRect
            self.toolbar.setPos(0, 0)
        thescene.setSceneRect(thescene.itemsBoundingRect())
        scene_rect = thescene.sceneRect()
        if self.toolbar:  # HACK, pt2: move toolbar back
            self.toolbar.setPos(self.mapToScene(0, 0))
        self.fitInView(scene_rect, Qt.KeepAspectRatio) # fit in view
        self._resetScale() # adjust scaling so that translation works
        # adjust scaling so that the items don't fill 100% of the view
        # this is good for selection
        self.scale(self._scale_fit_factor, self._scale_fit_factor)
        self._scale_size *= self._scale_fit_factor
        self._resetLOD()
    # end def

    def paintEvent(self, event):
        if self.toolbar:
            self.toolbar.setPos(self.mapToScene(0, 0))
        QGraphicsView.paintEvent(self, event)
Esempio n. 33
0
 def add_scene(self, scene: ModelScene, name="Scene"):
     view = ModelView(scene)
     view.setViewport(QOpenGLWidget())
     self.mainpane.addTab(ViewPane(view), name)
Esempio n. 34
0
    def __init__(self, initMode: DriveMode) -> None:
        # Init values
        self.mode = initMode
        self.tachometerEngineRpm = 0  # 0 - 9000
        self.tachometerEngineLevel = DashboardLevel.inactive
        self.tachometerGearboxRpm = 0  # 0 - 9000
        self.tachometerGearboxLevel = DashboardLevel.inactive
        self.tachometerGear1Rpm = 0  # 0 - 9000
        self.tachometerGear2Rpm = 0  # 0 - 9000
        self.tachometerGear3Rpm = 0  # 0 - 9000
        self.tachometerGear4Rpm = 0  # 0 - 9000
        self.tachometerGear5Rpm = 0  # 0 - 9000
        self.accelerometerAngel = 0  # -180 - +180
        self.accelerometerValue = 0.0  # 0.0 - 1.0
        self.accelerometerLevel = DashboardLevel.inactive
        self.steeringWheelEncoderAngel = 0  # -7 - +7
        self.steeringWheelEncoderLevel = DashboardLevel.inactive
        self.turnLeftIndicatorLevel = DashboardLevel.inactive
        self.turnRightIndicatorLevel = DashboardLevel.inactive
        self.oilWarningIndicatorLevel = DashboardLevel.inactive
        self.watterWarningIndicatorLevel = DashboardLevel.inactive
        self.gearNumberValue = 0  # 0 - 5
        self.speedometerValue = 0  # 0 - 999
        self.speedometerLevel = DashboardLevel.inactive
        self.stopwatchMills = 0  # 0 - 99
        self.stopwatchSeconds = 0  # 0 - 59
        self.stopwatchMinutes = 0  # 0 - 59
        self.stopwatchHours = 0  # 0 - 9
        self.stopwatchLevel = DashboardLevel.inactive
        self.oilManometerValue = 0.0  # 0.0 - 9.99
        self.oilManometerLevel = DashboardLevel.inactive
        self.oilThermometerValue = 0  # 0 - 999
        self.oilThermometerLevel = DashboardLevel.inactive
        self.watterThermometerValue = 0  # 0 - 999
        self.watterThermometerLevel = DashboardLevel.inactive
        self.odometerValue = 0  # 0 - 9999
        self.odometerLevel = DashboardLevel.inactive
        # Init UI
        super(Dashboard, self).__init__()
        viewport = QOpenGLWidget()
        viewportFormat = QSurfaceFormat()
        viewportFormat.setSwapInterval(0)  # disable VSync
        viewportFormat.setSamples(2**8)
        viewportFormat.setDefaultFormat(viewportFormat)
        viewport.setFormat(viewportFormat)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setGeometry(0, 0, self.WINDOW_WIDTH, self.WINDOW_HEIGHT)
        self.setStyleSheet("border: 0px")
        self.setWindowTitle("Dashboard")
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.scene = QGraphicsScene(0, 0, self.WINDOW_WIDTH,
                                    self.WINDOW_HEIGHT)
        self.setScene(self.scene)
        self.setViewport(viewport)
        self.setInteractive(False)
        self.levelPens = {
            DashboardLevel.inactive: QPen(self.INACTIVE_COLOR, 1,
                                          Qt.SolidLine),
            DashboardLevel.ok: QPen(self.OK_COLOR, 1, Qt.SolidLine),
            DashboardLevel.warning: QPen(self.WARNING_COLOR, 1, Qt.SolidLine),
            DashboardLevel.dangerous: QPen(self.DANGEROUS_COLOR, 1,
                                           Qt.SolidLine)
        }
        self.levelBrushes = {
            DashboardLevel.inactive: QBrush(self.INACTIVE_COLOR,
                                            Qt.SolidPattern),
            DashboardLevel.ok: QBrush(self.OK_COLOR, Qt.SolidPattern),
            DashboardLevel.warning: QBrush(self.WARNING_COLOR,
                                           Qt.SolidPattern),
            DashboardLevel.dangerous: QBrush(self.DANGEROUS_COLOR,
                                             Qt.SolidPattern)
        }
        # Helpers
        dirPath = os.path.dirname(os.path.abspath(__file__))
        inactivePen = self.levelPens[DashboardLevel.inactive]
        inactiveBrush = self.levelBrushes[DashboardLevel.inactive]

        def buildPolygonItem(origin: QPointF, polygon: List[QPointF]):
            return self.scene.addPolygon(
                QPolygonF([
                    QPointF(p.x() + origin.x(),
                            p.y() + origin.y()) for p in polygon
                ]), inactivePen, inactiveBrush)

        def makeNumberItems(origin: QPointF, polygon: Dict[str,
                                                           List[QPointF]]):
            return {k: buildPolygonItem(origin, p) for k, p in polygon.items()}

        # Add background
        self.backgroundPixmaps = {
            DriveMode.race:
            QPixmap(os.path.join(dirPath, "background_race.png")).scaled(
                self.WINDOW_WIDTH, self.WINDOW_HEIGHT),
            DriveMode.street:
            QPixmap(os.path.join(dirPath, "background_street.png")).scaled(
                self.WINDOW_WIDTH, self.WINDOW_HEIGHT)
        }
        logging.debug(
            f"[Dashboard.__init__] Loaded: backgroundPixmaps = {self.backgroundPixmaps}, initMode = {initMode}"
        )
        self.backgroundItem = QGraphicsPixmapItem()
        self.backgroundItem.setZValue(-1)
        self.scene.addItem(self.backgroundItem)
        # Add tachometer graphics
        self.tachometerEngineItems = \
            {k: self.scene.addPolygon(p, inactivePen, inactiveBrush)
             for k, p in PolygonsMapping.TACHOMETER_ENGINE.items()}
        self.tachometerGearboxItems = \
            {k: self.scene.addPolygon(p, inactivePen, inactiveBrush)
             for k, p in PolygonsMapping.TACHOMETER_GEARBOX.items()}
        self.tachometerGearsPens = {
            "A": QPen(self.TACHOMETER_GEARS_ARROW_COLOR, 1, Qt.SolidLine),
            "N": QPen(self.TACHOMETER_GEARS_NUMBER_COLOR, 1, Qt.SolidLine)
        }
        self.tachometerGearsBrushes = {
            "A": QBrush(self.TACHOMETER_GEARS_ARROW_COLOR, Qt.SolidPattern),
            "N": QBrush(self.TACHOMETER_GEARS_NUMBER_COLOR, Qt.SolidPattern)
        }

        def makeGearsTransforms(translate: QPointF, rotate: int):
            arrowTrans = QTransform()
            arrowTrans.translate(translate.x(), translate.y())
            arrowTrans.rotate(rotate)
            numberTrans = QTransform()
            numberTrans.translate(translate.x(), translate.y())
            return arrowTrans, numberTrans
        self.tachometerGearsTransforms = \
            {k: makeGearsTransforms(p[0], p[1]) for k, p in PolygonsMapping.TACHOMETER_GEARS["T"].items()}

        def tachometerGearsItem(gearNumber: int):
            (arrowTrans, numberTrans) = self.tachometerGearsTransforms[0]
            arrowItem = self.scene.addPolygon(
                PolygonsMapping.TACHOMETER_GEARS["A"], inactivePen,
                inactiveBrush)
            arrowItem.setTransform(arrowTrans)
            numberItem = buildPolygonItem(
                PolygonsMapping.TACHOMETER_GEARS["N"]["O"],
                PolygonsMapping.TACHOMETER_GEARS["N"]["P"][gearNumber])
            numberItem.setTransform(numberTrans)
            return arrowItem, numberItem

        self.tachometerGearsItems = {
            1: tachometerGearsItem(1),
            2: tachometerGearsItem(2),
            3: tachometerGearsItem(3),
            4: tachometerGearsItem(4),
            5: tachometerGearsItem(5)
        }

        # Add accelerometer graphics
        def makeEllipse(points: Tuple[QPointF, QPointF]):
            return self.scene.addEllipse(points[0].x(), points[0].y(),
                                         points[1].x() - points[0].x(),
                                         points[1].y() - points[0].y(),
                                         inactivePen, inactiveBrush)

        self.accelerometerCenterItem = makeEllipse(
            PolygonsMapping.ACCELEROMETER["C"])
        self.accelerometerSectorItem = makeEllipse(
            PolygonsMapping.ACCELEROMETER["S"])
        self.accelerometerSectorItem.setStartAngle(
            int((270 - (self.ACCELEROMETER_MIN_ANGEL / 2))) * 16)
        self.accelerometerSectorItem.setSpanAngle(
            self.ACCELEROMETER_MIN_ANGEL * 16)
        # Add steering wheel encoder graphics
        self.steeringWheelEncoderItems = \
            {k: self.scene.addPolygon(p, inactivePen, inactiveBrush)
             for k, p in PolygonsMapping.STEERING_WHEEL_ENCODER.items()}

        # Add turn indicator graphics
        def makeTurnIndicatorItem(initCoordinates: Dict[str, Any]):
            return buildPolygonItem(initCoordinates["C"], initCoordinates["P"])

        self.turnIndicatorLeftItem = makeTurnIndicatorItem(
            PolygonsMapping.TURN_INDICATOR["L"])
        self.turnIndicatorRightItem = makeTurnIndicatorItem(
            PolygonsMapping.TURN_INDICATOR["R"])

        # Add warning indicators graphics
        def makeWarningIndicatorItems(initCoordinates: Dict[str, Any]):
            return [
                buildPolygonItem(initCoordinates["C"], p)
                for p in initCoordinates["P"]
            ]

        self.oilWarningIndicatorItems = makeWarningIndicatorItems(
            PolygonsMapping.WARNING_INDICATORS["OIL"])
        self.watterWarningIndicatorItems = makeWarningIndicatorItems(
            PolygonsMapping.WARNING_INDICATORS["WATTER"])
        # Add gear number graphics
        self.gearNumberPen = QPen(self.GEAR_NUMBER_COLOR, 1, Qt.SolidLine)
        self.gearNumberBrush = QBrush(self.GEAR_NUMBER_COLOR, Qt.SolidPattern)
        self.gearNumberItems = makeNumberItems(
            PolygonsMapping.GEAR_NUMBER["C"], PolygonsMapping.GEAR_NUMBER["P"])
        # Add speedometer graphics
        self.speedometer001Items = makeNumberItems(
            PolygonsMapping.SPEEDOMETER[1], PolygonsMapping.SPEED_NUMBERS)
        self.speedometer010Items = makeNumberItems(
            PolygonsMapping.SPEEDOMETER[10], PolygonsMapping.SPEED_NUMBERS)
        self.speedometer100Items = makeNumberItems(
            PolygonsMapping.SPEEDOMETER[100], PolygonsMapping.SPEED_NUMBERS)
        # Add stopwatch graphics
        self.stopwatchMS01Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["MS01"],
            PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchMS10Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["MS10"],
            PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchS01Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["S01"], PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchS10Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["S10"], PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchM01Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["M01"], PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchM10Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["M10"], PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchH01Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["H01"], PolygonsMapping.STANDARD_NUMBERS)
        # Add oil manometer graphics
        self.oilManometer0d01Items = makeNumberItems(
            PolygonsMapping.OIL_MANOMETER[0.01],
            PolygonsMapping.STANDARD_NUMBERS)
        self.oilManometer0d10Items = makeNumberItems(
            PolygonsMapping.OIL_MANOMETER[0.1],
            PolygonsMapping.STANDARD_NUMBERS)
        self.oilManometer1d00Items = makeNumberItems(
            PolygonsMapping.OIL_MANOMETER[1], PolygonsMapping.STANDARD_NUMBERS)
        # Add oil thermometer graphics
        self.oilThermometer001Items = makeNumberItems(
            PolygonsMapping.OIL_THERMOMETER[1],
            PolygonsMapping.STANDARD_NUMBERS)
        self.oilThermometer010Items = makeNumberItems(
            PolygonsMapping.OIL_THERMOMETER[10],
            PolygonsMapping.STANDARD_NUMBERS)
        self.oilThermometer100Items = makeNumberItems(
            PolygonsMapping.OIL_THERMOMETER[100],
            PolygonsMapping.STANDARD_NUMBERS)
        # Add watter thermometer graphics
        self.watterThermometer001Items = makeNumberItems(
            PolygonsMapping.WATTER_THERMOMETER[1],
            PolygonsMapping.STANDARD_NUMBERS)
        self.watterThermometer010Items = makeNumberItems(
            PolygonsMapping.WATTER_THERMOMETER[10],
            PolygonsMapping.STANDARD_NUMBERS)
        self.watterThermometer100Items = makeNumberItems(
            PolygonsMapping.WATTER_THERMOMETER[100],
            PolygonsMapping.STANDARD_NUMBERS)
        # Add odometer graphics
        self.watterOdometer0001Items = makeNumberItems(
            PolygonsMapping.ODOMETER[1], PolygonsMapping.STANDARD_NUMBERS)
        self.watterOdometer0010Items = makeNumberItems(
            PolygonsMapping.ODOMETER[10], PolygonsMapping.STANDARD_NUMBERS)
        self.watterOdometer0100Items = makeNumberItems(
            PolygonsMapping.ODOMETER[100], PolygonsMapping.STANDARD_NUMBERS)
        self.watterOdometer1000Items = makeNumberItems(
            PolygonsMapping.ODOMETER[1000], PolygonsMapping.STANDARD_NUMBERS)
        # Initial rendering
        self.renderBackground()
        self.renderTachometerScale(self.tachometerEngineItems,
                                   self.tachometerEngineRpm,
                                   self.tachometerEngineLevel)
        self.renderTachometerScale(self.tachometerGearboxItems,
                                   self.tachometerGearboxRpm,
                                   self.tachometerGearboxLevel)
        self.renderAccelerometer()
        self.renderSteeringWheelEncoder()
        self.renderTurnLeftIndicator()
        self.renderTurnRightIndicator()
        self.renderOilWarningIndicator()
        self.renderWatterWarningIndicator()
        self.renderGearNumber()
        self.renderSpeedometer()
        self.renderStopwatch()
        self.renderOilManometer()
        self.renderOilThermometer()
        self.renderWatterThermometer()
        self.renderOdometer()
Esempio n. 35
0
class CustomQGraphicsView(QGraphicsView):
    """
    Base class for QGraphicsViews with Mouse Zoom and Pan support via the
    Control/Command shortcut key.

    A QGraphics View stores info on the view and handles mouse events for
    zooming and panning

    Ctrl-MidMouseButton = Pan
    Ctrl-RightMouseButton = Dolly Zoom
    MouseWheel = Zoom

    Args:
        parent(QWidget): type of QWidget such as QWidget.main_splitter() for the type of
                         View its has

    For details on these and other miscellaneous methods, see below.
    """
    def __init__(self, parent=None):
        """
        On initialization, we need to bind the Ctrl/command key to
        enable manipulation of the view.
        """
        QGraphicsView.__init__(self, parent)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setRubberBandSelectionMode(Qt.IntersectsItemShape)
        self._no_drag = QGraphicsView.RubberBandDrag
        self._yes_drag = QGraphicsView.ScrollHandDrag

        # reset things that are state dependent
        self.clearGraphicsView()

        self._x0 = 0
        self._y0 = 0
        self._scale_size = 1.0
        self._scale_limit_max = 16.0  # OLD 3.0
        self._scale_limit_min = 0.21
        self._scale_up_rate = 0.01
        self._scale_down_rate = 0.01
        self._scale_fit_factor = .5  # sets initial zoom level
        self._show_details = True
        self._last_scale_factor = 0.0
        self.scene_root_item = None  # the item to transform
        # Keyboard panning
        self._key_pan_delta_x = styles.PATH_BASE_WIDTH * 21
        self._key_pan_delta_y = styles.PATH_HELIX_HEIGHT + styles.PATH_HELIX_PADDING / 2
        # Modifier keys and buttons
        self._key_mod = Qt.Key_Control
        self._button_pan = Qt.LeftButton
        self._button_pan_alt = Qt.MidButton
        self._button_zoom = Qt.RightButton

        self.toolbar = None  # custom hack for the paint tool palette
        self._name = None

        self.setContextMenuPolicy(Qt.CustomContextMenu)

        if GL:
            self.is_GL = True
            # self.glwidget = QGLWidget(QGLFormat(QGL.SampleBuffers))
            self.glwidget = QOpenGLWidget()
            # self.setupGL()
            self.gl = self.glwidget.context().versionFunctions()
            self.setViewport(self.glwidget)
            self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
            # self.resetGL()
        else:
            self.is_GL = False
            self.setViewportUpdateMode(QGraphicsView.MinimalViewportUpdate)
            # self.setViewportUpdateMode(QGraphicsView.SmartViewportUpdate)
        # self.setFocusPolicy(Qt.ClickFocus)

    # end def

    levelOfDetailChangedSignal = pyqtSignal(bool)

    def __repr__(self):
        clsName = self.__class__.__name__
        objId = self._name if self._name else str(id(self))[-4:]
        return "<%s %s>" % (clsName, objId)

    def setName(self, name):
        self._name = name

    # end def

    def setViewportUpdateOn(self, is_enabled):
        if is_enabled:
            self.setViewportUpdateMode(QGraphicsView.MinimalViewportUpdate)
        else:
            self.setViewportUpdateMode(QGraphicsView.NoViewportUpdate)

    # end def

    def activateSelection(self, is_active):
        if self._selection_lock:
            self._selection_lock.clearSelection(False)
        self.clearSelectionLockAndCallbacks()
        if is_active:
            self._no_drag = QGraphicsView.RubberBandDrag
        else:
            self._no_drag = QGraphicsView.NoDrag
        if self.dragMode() != self._yes_drag:
            self.setDragMode(self._no_drag)

    # end def

    def clearGraphicsView(self):
        # Event handling
        self._has_focus = False
        # Misc
        self.clearSelectionLockAndCallbacks()
        # Pan and dolly defaults
        self._transform_enable = False
        self._dolly_zoom_enable = False
        self.setDragMode(self._no_drag)

    # end def

    def clearSelectionLockAndCallbacks(self):
        self._selection_lock = None  # a selection group to limit types of items selected
        self._press_list = [
        ]  # bookkeeping to handle passing mouseReleaseEvents to QGraphicsItems that don't get them

    # end def

    def _setGLView(self, boolval):
        # scene = self.scene()
        if boolval and self.is_GL is False:
            self.is_GL = True
            # scene.drawBackground = self._drawBackgroundGL
            # self.setViewport(QGLWidget(QGLFormat(QGL.SampleBuffers)))
            # self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        elif not boolval and self.is_GL is True:
            self.is_GL = False
            # scene.drawBackground = self.drawBackgroundNonGL
            # self.setViewport(QWidget())
            # self.setViewportUpdateMode(QGraphicsView.MinimalViewportUpdate)

    # end def

    def setupGL(self):
        # scene = self.scene()
        # win = self.scene_root_item.window()
        self.is_GL = True
        self.is_GL_switch_allowed = True
        self.qTimer = QTimer()
        # self.drawBackgroundNonGL = scene.drawBackground
        # scene.drawBackground = self._drawBackgroundGL
        # format = QGLFormat(QGL.SampleBuffers)
        # format.setSamples(16)
        # print "# of samples", format.samples(), format.sampleBuffers()
        # self.setViewport(QGLWidget(format))
        # self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)

    # end def

    def _resetLOD(self):
        scale_factor = self.transform().m11()
        # print("scale_factor", scale_factor)
        self.scene_root_item.window().statusBar().showMessage("%0.2f" %
                                                              scale_factor)
        if scale_factor < 0.75:
            self._show_details = False
            self.levelOfDetailChangedSignal.emit(False)  # zoomed out
        elif scale_factor > 0.8:
            self._show_details = True
            self.levelOfDetailChangedSignal.emit(True)  # zoomed in

    # end def

    def _resetGL(self):
        scale_factor = self.transform().m11()
        # print("scale_factor", scale_factor)
        self.scene_root_item.window().statusBar().showMessage("%0.2f" %
                                                              scale_factor)

        if scale_factor < .15:  # and self.is_GL_switch_allowed:
            # self.is_GL_switch_allowed = False
            self._setGLView(True)
            self._show_details = False
            self.levelOfDetailChangedSignal.emit(False)  # zoomed out
            self.qTimer.singleShot(500, self._allowGLSwitch)
        elif scale_factor > .2:  # and self.is_GL_switch_allowed:
            # self.is_GL_switch_allowed = False
            self._setGLView(False)
            self._show_details = True
            self.levelOfDetailChangedSignal.emit(True)  # zoomed in
            self.qTimer.singleShot(500, self._allowGLSwitch)

    # end def

    def shouldShowDetails(self):
        return self._show_details

    # end def

    def _allowGLSwitch(self):
        self.is_GL_switch_allowed = True

    # end def

    def _drawBackgroundGL(self, painter, rect):
        """
        This method is for overloading the QGraphicsScene.
        """
        if painter.paintEngine().type() != QPaintEngine.OpenGL and \
           painter.paintEngine().type() != QPaintEngine.OpenGL2:

            qWarning(
                "OpenGLScene: drawBackground needs a QGLWidget to be set as viewport on the graphics view"
            )
            return
        # end if
        painter.beginNativePainting()
        GL.glDisable(GL.GL_DEPTH_TEST)  # disable for 2D drawing
        GL.glClearColor(1.0, 1.0, 1.0, 1.0)
        GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)

        painter.endNativePainting()

    # end def

    def focusInEvent(self, event):
        self._has_focus = True

    def focusOutEvent(self, event):
        self._transform_enable = False
        self._dolly_zoom_enable = False
        self._has_focus = False
        self._transform_enable = False

    # end def

    def setSelectionLock(self, selection_lock):
        self._selection_lock = selection_lock

    # end def

    def selectionLock(self):
        return self._selection_lock

    # end def

    def setScaleFitFactor(self, value):
        """docstring for setScaleFitFactor"""
        self._scale_fit_factor = value

    # end def

    def setKeyPan(self, button):
        """Set the class pan button remotely"""
        self._button_pan = button

    # end def

    def addToPressList(self, item):
        """docstring for addToPressList"""
        # self._press_list[self._press_list_idx].append(item)
        self._press_list.append(item)

    # end def

    def keyPanDeltaX(self):
        """Returns the distance in scene space to move the scene_root_item when
        panning left or right."""
        # PyQt isn't aware that QGraphicsObject is a QGraphicsItem and so
        # it returns a separate python object if, say, childItems() returns
        # a QGraphicsObject cast to a QGraphicsItem. If this is the case,
        # we can still find the QGraphicsObject thusly:
        candidateDxDeciders = list(self.scene_root_item.childItems())
        candidateDxDeciders = candidateDxDeciders + [
            cd.toGraphicsObject() for cd in candidateDxDeciders
        ]
        for cd in candidateDxDeciders:
            if cd is None:
                continue
            keyPanDXMethod = getattr(cd, 'keyPanDeltaX', None)
            if keyPanDXMethod is not None:
                return keyPanDXMethod()
        return 100

    def keyPanDeltaY(self):
        """Returns the distance in scene space to move the scene_root_item when
        panning left or right."""
        candidateDyDeciders = list(self.scene_root_item.childItems())
        candidateDyDeciders = candidateDyDeciders + [
            cd.toGraphicsObject() for cd in candidateDyDeciders
        ]
        for cd in candidateDyDeciders:
            if cd is None:
                continue
            keyPanDYMethod = getattr(cd, 'keyPanDeltaY', None)
            if keyPanDYMethod is not None:
                return keyPanDYMethod()
        return 100

    def keyPressEvent(self, event):
        """
        Handle key presses for mouse-drag transforms and arrow-key panning.
        """
        if not self._has_focus:  # we don't have focus -> ignore keypress
            return
        if event.key() == self._key_mod:
            self._transform_enable = True
            QGraphicsView.keyPressEvent(self, event)
        elif event.key() == Qt.Key_Left:
            transform = self.scene_root_item.transform()
            transform.translate(self.keyPanDeltaX(), 0)
            self.scene_root_item.setTransform(transform)
        elif event.key() == Qt.Key_Up:
            transform = self.scene_root_item.transform()
            transform.translate(0, self.keyPanDeltaY())
            self.scene_root_item.setTransform(transform)
        elif event.key() == Qt.Key_Right:
            transform = self.scene_root_item.transform()
            transform.translate(-self.keyPanDeltaX(), 0)
            self.scene_root_item.setTransform(transform)
        elif event.key() == Qt.Key_Down:
            transform = self.scene_root_item.transform()
            transform.translate(0, -self.keyPanDeltaY())
            self.scene_root_item.setTransform(transform)
        elif event.key() == Qt.Key_Plus:
            self.zoomIn(0.3)
        elif event.key() == Qt.Key_Minus:
            self.zoomIn(0.03)
        else:
            if hasattr(self.scene_root_item, KEY_PRESS_EVENT):
                getattr(self.scene_root_item, KEY_PRESS_EVENT)(event)

    # end def

    def keyReleaseEvent(self, event):
        if event.key() == self._key_mod:
            self._transform_enable = False
            self._dolly_zoom_enable = False
            self._panDisable()
        else:
            if hasattr(self.scene_root_item, KEY_RELEASE_EVENT):
                getattr(self.scene_root_item, KEY_RELEASE_EVENT)(event)

    # end def

    def enterEvent(self, event):
        # self.setFocus() # this call robs selection from key focus
        self.setDragMode(self._no_drag)
        QGraphicsView.enterEvent(self, event)

    def leaveEvent(self, event):
        self.clearFocus()
        QGraphicsView.leaveEvent(self, event)

    def mouseMoveEvent(self, event):
        """
        Must override mouseMoveEvent of QGraphicsView to allow
        ScrollHandDrag due to the fact that events are intercepted
        breaks this feature.
        """
        if self._transform_enable:
            if self.dragMode() == self._yes_drag:
                # Add stuff to handle the pan event
                posf = event.localPos()
                xf = posf.x()
                yf = posf.y()

                factor = self.transform().m11()

                transform = self.scene_root_item.transform()

                transform.translate((xf - self._x0) / factor,
                                    (yf - self._y0) / factor)
                self.scene_root_item.setTransform(transform)
                self._x0 = xf
                self._y0 = yf
            elif self._dolly_zoom_enable:
                self.dollyZoom(event)
        # adding this allows events to be passed to items underneath
        QGraphicsView.mouseMoveEvent(self, event)

    # end def

    def mousePressEvent(self, event):
        """docstring for mousePressEvent"""
        if self._transform_enable and qApp.keyboardModifiers():
            which_buttons = event.buttons()
            if which_buttons in [self._button_pan, self._button_pan_alt]:
                self._panEnable()
                posf = event.localPos()
                self._x0 = posf.x()
                self._y0 = posf.y()
            elif which_buttons == self._button_zoom:
                self._dolly_zoom_enable = True
                self._last_scale_factor = 0
                # QMouseEvent.y() returns the position of the mouse cursor
                # relative to the widget
                self._y0 = event.localPos().y()
            else:
                QGraphicsView.mousePressEvent(self, event)
        else:
            QGraphicsView.mousePressEvent(self, event)

    # end def

    def mouseReleaseEvent(self, event):
        """If panning, stop. If handles were pressed, release them."""
        if self._transform_enable:
            # QMouseEvent.button() returns the button that triggered the event
            which_button = event.button()
            if which_button in [self._button_pan, self._button_pan_alt]:
                self._panDisable()
            elif which_button == self._button_zoom:
                self._dolly_zoom_enable = False
            else:
                return QGraphicsView.mouseReleaseEvent(self, event)
        # end if
        else:
            if len(self._press_list):  # Notify any pressed items to release
                # event_pos = event.pos()
                for item in self._press_list:
                    item.customMouseRelease(event)
                self._press_list = []
            # end if
            if self._selection_lock:
                self._selection_lock.processPendingToAddList()
            return QGraphicsView.mouseReleaseEvent(self, event)

    # end def

    def _panEnable(self):
        """Enable ScrollHandDrag Mode in QGraphicsView (displays a hand
        pointer)"""
        self.setDragMode(self._yes_drag)

    # end def

    def _panDisable(self):
        """Disable ScrollHandDrag Mode in QGraphicsView (displays a hand
        pointer)"""
        self.setDragMode(self._no_drag)

    # end def

    def fname(self):
        """docstring for fname"""

    def wheelEvent(self, event):
        self.safeScale(event.angleDelta().y())

    # end def

    def safeScale(self, delta):
        current_scale_level = self.transform().m11()
        scale_factor = 1 + delta * (self._scale_down_rate if delta < 0 else self._scale_up_rate) * \
            (app().prefs.zoom_speed/100.)
        new_scale_level = current_scale_level * scale_factor
        new_scale_level = util.clamp(current_scale_level * scale_factor,
                                     self._scale_limit_min,
                                     self._scale_limit_max)
        scale_change = new_scale_level / current_scale_level
        self.scale(scale_change, scale_change)
        self._resetLOD()

    # end def

    def zoomIn(self, fraction_of_max=0.5):
        current_scale_level = self.transform().m11()
        scale_change = (fraction_of_max *
                        self._scale_limit_max) / current_scale_level
        self.scale(scale_change, scale_change)

    # end def

    def zoomOut(self, fraction_of_min=1):
        current_scale_level = self.transform().m11()
        scale_change = (fraction_of_min *
                        self._scale_limit_min) / current_scale_level
        self.scale(scale_change, scale_change)

    # end def

    def dollyZoom(self, event):
        """docstring for dollyZoom"""
        # QMouseEvent.y() returns the position of the mouse cursor relative
        # to the widget
        yf = event.y()
        denom = abs(yf - self._y0)
        if denom > 0:
            scale_factor = (self.height() / 2) % denom
            if self._last_scale_factor != scale_factor:
                self._last_scale_factor = scale_factor
                # zoom in if mouse y position is getting bigger
                if yf - self._y0 > 0:
                    self.safeScale(yf - self._y0)
                # end else
                else:  # else id smaller zoom out
                    self.safeScale(yf - self._y0)
                # end else
        # end if

    # end def

    def _resetScale(self):
        """reset the scale to 1"""
        # use the transform value if you want to get how much the view
        # has been scaled
        self._scale_size = self.transform().m11()

        # self._scale_limit_min = 0.41*self._scale_size
        # make it so fitting in view is zoomed minimum
        # still gives you one zoom level out before violates limit
        self._scale_limit_min = self._scale_size * self._scale_fit_factor

        # use this if you want to reset the zoom in limit
        # self._scale_limit_max = 3.0*self._scale_size

        self._last_scale_factor = 0.0

    # end def

    def zoomToFit(self):
        # print("zoom to fit", self._name)
        # Auto zoom to center the scene
        thescene = self.scene_root_item.scene()
        # order matters?
        self.scene_root_item.resetTransform()  # zero out translations
        self.resetTransform()  # zero out scaling
        if self.toolbar:  # HACK: move toolbar so it doesn't affect sceneRect
            self.toolbar.setPos(0, 0)
        thescene.setSceneRect(thescene.itemsBoundingRect())
        scene_rect = thescene.sceneRect()
        if self.toolbar:  # HACK, pt2: move toolbar back
            self.toolbar.setPos(self.mapToScene(0, 0))
        self.fitInView(scene_rect, Qt.KeepAspectRatio)  # fit in view
        self._resetScale()  # adjust scaling so that translation works
        # adjust scaling so that the items don't fill 100% of the view
        # this is good for selection
        self.scale(self._scale_fit_factor, self._scale_fit_factor)
        self._scale_size *= self._scale_fit_factor
        self._resetLOD()

    # end def

    def paintEvent(self, event):
        if self.toolbar:
            self.toolbar.setPos(self.mapToScene(0, 0))
        QGraphicsView.paintEvent(self, event)
    def __init__(self, parent=None, **kw):
        # the current button
        self._ActiveButton = Qt.NoButton

        # private attributes
        self.__saveX = 0
        self.__saveY = 0
        self.__saveModifiers = Qt.NoModifier
        self.__saveButtons = Qt.NoButton
        self.__wheelDelta = 0

        # do special handling of some keywords:
        # stereo, rw

        try:
            stereo = bool(kw['stereo'])
        except KeyError:
            stereo = False

        try:
            rw = kw['rw']
        except KeyError:
            rw = None

        # create qt-level widget
        if QVTKRWIBase == "QWidget":
            if "wflags" in kw:
                wflags = kw['wflags']
            else:
                wflags = Qt.WindowFlags()
            QWidget.__init__(self, parent, wflags | Qt.MSWindowsOwnDC)
        elif QVTKRWIBase == "QGLWidget":
            QGLWidget.__init__(self, parent)

        if rw:  # user-supplied render window
            self._RenderWindow = rw
        else:
            self._RenderWindow = vtk.vtkRenderWindow()

        wid = self._get_win_id()
        self._RenderWindow.SetWindowInfo(wid)

        self._should_set_parent_info = (sys.platform == 'win32')

        if stereo:  # stereo mode
            self._RenderWindow.StereoCapableWindowOn()
            self._RenderWindow.SetStereoTypeToCrystalEyes()

        try:
            self._Iren = kw['iren']
        except KeyError:
            self._Iren = vtk.vtkGenericRenderWindowInteractor()

        self._Iren.SetRenderWindow(self._RenderWindow)

        if hasattr(self, 'devicePixelRatio'):
            self._pixel_ratio = self.devicePixelRatio()
        else:
            self._pixel_ratio = 1.0

        # do all the necessary qt setup
        self.setAttribute(Qt.WA_OpaquePaintEvent)
        self.setAttribute(Qt.WA_PaintOnScreen)
        self.setMouseTracking(True) # get all mouse events
        self.setFocusPolicy(Qt.WheelFocus)
        self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))

        self._Timer = QTimer(self)
        self._Timer.timeout.connect(self.TimerEvent)

        # add wheel timer to fix scrolling issue with trackpad
        self.wheel_timer = None
        if PyQtImpl != 'PyQt5':
            self.wheel_timer = QTimer()
            self.wheel_timer.setSingleShot(True)
            self.wheel_timer.setInterval(25)
            self.wheel_timer.timeout.connect(self._emit_wheel_event)
            self._saved_wheel_event_info = ()

        self._Iren.AddObserver('CreateTimerEvent', messenger.send)
        messenger.connect(self._Iren, 'CreateTimerEvent', self.CreateTimer)
        self._Iren.AddObserver('DestroyTimerEvent', messenger.send)
        messenger.connect(self._Iren, 'DestroyTimerEvent', self.DestroyTimer)
        self._RenderWindow.AddObserver('CursorChangedEvent', messenger.send)
        messenger.connect(self._RenderWindow, 'CursorChangedEvent',
                          self.CursorChangedEvent)

        # Create a hidden child widget and connect its destroyed signal to its
        # parent ``Finalize`` slot. The hidden children will be destroyed
        # before its parent thus allowing cleanup of VTK elements.
        self._hidden = QWidget(self)
        self._hidden.hide()
        self._hidden.destroyed.connect(self.Finalize)