You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

130 lines
5.6 KiB

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
Laborejo2 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 3 of the License, or
(at your option) 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.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging; logger = logging.getLogger(__name__); logger.info("import")
from PyQt5 import QtCore, QtGui, QtWidgets, QtWidgets
from .constantsAndConfigs import constantsAndConfigs
import engine.api as api
class Playhead(QtWidgets.QGraphicsLineItem):
"""Performance optimisation log.
Playhead update is called very often to get a smooth movement of the cursor.
This draws in 50% to 100% of the CPU, combined with out scrollbar-linking and extension.
With positive results
acceptHoverEvents() - slightly slower
No results:
using centerOn() instead of custom scrollbar movement is uglier and takes the same CPU
returning a static bounding rect: no effect
Setting the Cache Mode seems to have no positive effect on performance, if not makes it worse.
self.setCacheMode(QtWidgets.QGraphicsLineItem.DeviceCoordinateCache)
self.setCacheMode(QtWidgets.QGraphicsLineItem.ItemCoordinateCache)
set.setEnabled - no difference
cosmetic Pen, no difference
using OpenGL or not for the parent view
using any update mode for the parent view.
itemFlags
"""
def __init__(self, parentScoreScene):
super().__init__(0, 0, 0, 128*constantsAndConfigs.stafflineGap) # (x1, y1, x2, y2)
self.parentScoreScene = parentScoreScene
self.pen = QtGui.QPen()
self.pen.setWidth(3)
self.pen.setCosmetic(True)
self.setPen(self.pen)
self.setEnabled(False)
api.callbacks.setPlaybackTicks.append(self.setCursorPosition)
api.callbacks.recordingModeChanged.append(self.setRecordingMode)
#self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable)
#self.setAcceptedMouseButtons(QtCore.Qt.LeftButton)
self.setZValue(90)
#self.parentScoreScene.parentView.verticalScrollBar().valueChanged.connect(self.setLineToWindowHeigth)
#self.hide()
#self.maxHeight = QtWidgets.QDesktopWidget().geometry().height() #we really hope the screen resolution does not change during the session.
def setCursorPosition(self, tickindex:int, playbackStatus:bool):
"""the tickindex to pixel index on the x axis is a fixed 1:n
relation. What you see is where you are. No jumps, the playhead
stays on course."""
oldx = self.x()
x = tickindex / constantsAndConfigs.ticksToPixelRatio
if x != oldx: #better idle CPU
self.setX(x)
if x != oldx and constantsAndConfigs.followPlayhead and playbackStatus:
#self.parentScoreScene.parentView.centerOn(self) Do not use center on. It centers for Y as well which creates a recursion and the score gets taller and taller.
#self.scene().parentView.horizontalScrollBar().setValue(x - 150)
#xV = self.parentScoreScene.parentView.mapFromScene(x,0).x()
#self.parentScoreScene.parentView.horizontalScrollBar().setValue(x * constantsAndConfigs.zoomFactor)
#y = self.parentScoreScene.sceneRect().center().y()
#y = self.parentScoreScene.parentView.verticalScrollBar().value()
#self.parentScoreScene.parentView.centerOn(x, y)
r = self.parentScoreScene.parentView.mapToScene(self.parentScoreScene.parentView.geometry())
x -= QtCore.QRectF(r.boundingRect()).width() / 2
self.parentScoreScene.parentView.horizontalScrollBar().setValue(x * constantsAndConfigs.zoomFactor)
def setRecordingMode(self, state:bool):
if state:
self.pen.setColor(QtGui.QColor("red"))
else:
self.pen.setColor(QtGui.QColor("black"))
self.setPen(self.pen)
def dont_mousePressEvent(self, event):
"""Eat the event to prevent propagation to the underlying empty scene, which draws
notes"""
event.playhead = True
def dont_mouseMoveEvent(self, event):
"""Only allow movement in Y direction.
Only triggered when dragging."""
#super().mouseMoveEvent(event) allows free movement through Qt. Don't call that.
p = event.scenePos().x()
if p < 0:
p = 0
#self.setPos(p, self.scene().parentView.mapToScene(0, 0).y())
self.setX(p)
api.seek(p * constantsAndConfigs.ticksToPixelRatio)
event.accept()
def dont_mouseReleaseEvent(self, event):
if constantsAndConfigs.snapToGrid:
x = event.scenePos().x() * constantsAndConfigs.ticksToPixelRatio
p = round(x / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
if p < 0:
p = 0
api.seek(p)
#def hoverEnterEvent(self, event):
# self.setCursor(QtCore.Qt.SizeHorCursor)
# self.update() #the default implementation calls this. event.accept/ignore has no effect.
#def hoverLeaveEvent(self, event):
# self.unsetCursor()
# self.update() #the default implementation calls this. event.accept/ignore has no effect.