Browse Source

Reduce to vertical grid. Fix some spacing and counting

master
Nils 2 years ago
parent
commit
1ba8f6f41b
  1. 6
      qtgui/constantsAndConfigs.py
  2. 15
      qtgui/cursor.py
  3. 111
      qtgui/grid.py
  4. 8
      qtgui/scoreview.py

6
qtgui/constantsAndConfigs.py

@ -28,8 +28,8 @@ from PyQt5 import QtGui
class ConstantsAndConfigs(TemplateConstantsAndConfigs):
def __init__(self):
super().__init__()
super().__init__()
self.ticksToPixelRatio = 128*3*5 #bigger value means less space between notes #api.D128 and 128*3*5 is also good. This gets changed during runtime as "Stretch Factor". Also: the QSettings save and reload this on a per-file basis.
#a quarter note has 53760 ticks. that is 53760 / 1920 = 28 pixels.
self.stafflineGap = 7 #it is 7 because it is an odd number, which has a middle. 123 4 567 which translates 1:1 to pixels.
@ -38,7 +38,7 @@ class ConstantsAndConfigs(TemplateConstantsAndConfigs):
self.negativeMagicPixel = -2
self.trackHeight = self.stafflineGap * 10
self.trackHeight = self.stafflineGap * 12
self.noteHeadMode = True #False means rectangle noteheads
self.noteHeadMode = True #False means rectangle noteheads
self.availableEditModes = ("notation", "cc", "block")

15
qtgui/cursor.py

@ -186,14 +186,13 @@ class Playhead(QtWidgets.QGraphicsLineItem):
api.seek(p * constantsAndConfigs.ticksToPixelRatio)
event.accept()
#TODO: grid does not exist anymore
#def 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 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)

111
qtgui/grid.py

@ -46,11 +46,10 @@ class RhythmLine(QtWidgets.QGraphicsLineItem):
class GuiGrid(QtWidgets.QGraphicsItemGroup):
"""The grid consists of vertical and horizontal lines.
Horiontal lines help to eyeball what pitch the cursor is on, vertical help to eyeball
"""The grid consists of vertical lines.
lines help to estimate
the rhythm or tick positions e.g. when trying to find the right place for a tempo change or CC.
Horizontal lines have always a more-than-enough width and X position.
Vertical lines are always at the top of the screen and reach down more-than-enough.
We only need to take care that there are enough lines, not about their dimensions or positions.
@ -63,7 +62,7 @@ class GuiGrid(QtWidgets.QGraphicsItemGroup):
A complete clean and redraw only happens when the tick rhythm changes.
"""
def __init__(self, parentScene, horizontalSize=None):
def __init__(self, parentScene):
super(GuiGrid, self).__init__()
self.parent = parentScene #QGraphicsScene
@ -72,50 +71,23 @@ class GuiGrid(QtWidgets.QGraphicsItemGroup):
self.initialGridExists = False
self.gapVertical = None #gets recalculated if gridRhythm is changed by the user, or through stretching.
self.gapHorizontal = None #is constant, but for symetry reasons this is put into redrawTickGrid as well
self.width = None #recalculated in reactToresizeEventOrZoom
self.height = None #recalculated in reactToresizeEventOrZoom
self.reactToresizeEventOrZoom()
self.linesHorizontal = [] #later the grid lines will be stored here
self.linesVertical = [] #later the grid lines will be stored here
self.horizontalScrollbarWaitForGapJump = 0
self.oldHorizontalValue = 0
self.verticalScrollbarWaitForGapJump = 0
self.oldVerticalValue = 0
self.parent.parentView.verticalScrollBar().valueChanged.connect(self.reactToVerticalScroll)
self.parent.parentView.horizontalScrollBar().valueChanged.connect(self.reactToHorizontalScroll)
self.setOpacity(constantsAndConfigs.gridOpacity)
gridPen = QtGui.QPen(QtCore.Qt.DotLine)
gridPen.setCosmetic(True)
def reactToHorizontalScroll(self, value):
if not self.initialGridExists:
return
#Keep horizontal lines in view
leftBorderAsScenePos = self.parent.parentView.mapToScene(0, 0).x()
for hline in self.linesHorizontal:
hline.setX(leftBorderAsScenePos)
#Shift vertical lines to new positions, respecting the grid steps
delta = value - self.oldHorizontalValue #in pixel. positive=right, negative=left. the higher the number the faster the scrolling.
delta *= 1/constantsAndConfigs.zoomFactor
self.horizontalScrollbarWaitForGapJump += delta
self.oldHorizontalValue = value
if abs(self.horizontalScrollbarWaitForGapJump) > self.gapVertical: #collect scrollpixels until we scrolled more than one gap
gapMultiplier, rest = divmod(self.horizontalScrollbarWaitForGapJump, self.gapVertical) #really fast scrolling can jump more than one gap
for vline in self.linesVertical:
vline.setX(vline.x() + gapMultiplier*self.gapVertical)
self.horizontalScrollbarWaitForGapJump = rest #keep the rest for the next scroll
assert abs(self.horizontalScrollbarWaitForGapJump) < self.gapVertical
def reactToVerticalScroll(self, value):
if not self.initialGridExists:
return
@ -125,36 +97,33 @@ class GuiGrid(QtWidgets.QGraphicsItemGroup):
for vline in self.linesVertical:
vline.setY(topBorderAsScenePos)
#Shift horizontal lines to a new position, respecting the staffline gap
#Shift lines to a new position,
delta = value - self.oldVerticalValue #in pixel. positive=down, negative=up. the higher the number the faster the scrolling.
delta *= 1/constantsAndConfigs.zoomFactor
self.verticalScrollbarWaitForGapJump += delta
self.oldVerticalValue = value
if abs(self.verticalScrollbarWaitForGapJump) > self.gapHorizontal: #collect scrollpixels until we scrolled more than one gap
gapMultiplier, rest = divmod(self.verticalScrollbarWaitForGapJump, self.gapHorizontal) #really fast scrolling can jump more than one gap
for hline in self.linesHorizontal:
hline.setY(hline.y() + gapMultiplier*self.gapHorizontal)
if abs(self.verticalScrollbarWaitForGapJump) > self.gapVertical: #collect scrollpixels until we scrolled more than one gap
gapMultiplier, rest = divmod(self.verticalScrollbarWaitForGapJump, self.gapVertical) #really fast scrolling can jump more than one gap
self.verticalScrollbarWaitForGapJump = rest #keep the rest for the next scroll
assert abs(self.verticalScrollbarWaitForGapJump) < self.gapHorizontal
assert abs(self.verticalScrollbarWaitForGapJump) < self.gapVertical
def reactToresizeEventOrZoom(self):
"""Called by the Views resizeEvent.
When the views geometry changes or zooms we may need to create more lines.
Never delete and never make smaller though."""
scoreViewWidgetHeight = self.parent.parentView.height()
scoreViewWidgetWidth = self.parent.parentView.width()
scoreViewWidgetHeight = self.parent.height() #Use the scene, not the view. The view (in the past) was very wrong.
scoreViewWidgetWidth = self.parent.width()
if (not self.height) or scoreViewWidgetHeight * 2 > self.height:
self.height = scoreViewWidgetHeight * 2
if (not self.width) or scoreViewWidgetWidth * 2 > self.width:
self.width = scoreViewWidgetWidth * 2
if (not self.height) or scoreViewWidgetHeight > self.height:
self.height = scoreViewWidgetHeight
if (not self.width) or scoreViewWidgetWidth > self.width:
self.width = scoreViewWidgetWidth
if self.initialGridExists:
assert self.linesHorizontal and self.linesVertical, (self.linesHorizontal, self.linesVertical)
assert self.linesVertical, self.linesVertical
assert self.parent.parentView.isVisible(), self.parent.parentView.isVisible()
self._fillVerticalLines()
self._fillHorizontalLines()
def _fillVerticalLines(self):
"""Only allowed to get called by reactToresizeEventOrZoom because we need an updated
@ -175,27 +144,6 @@ class GuiGrid(QtWidgets.QGraphicsItemGroup):
self._createVerticalLines(start=self.nrOfVerticalLines, end=newLineCount) #This draws only yet nonexisting lines.
self.nrOfVerticalLines = newLineCount #for next time
def _fillHorizontalLines(self):
"""Only allowed to get called by reactToresizeEventOrZoom because we need an updated
self.width value.
To be honest.. this is also called by stretchXCoordinates when shrinking the display so
we need more lines. That does not depend on self.width but on the newLineCount """
#Check if we need longer lines. Do this before creating new lines, because new lines
#have the heighest
oldWidth = self.linesHorizontal[-1].line().x2() #this is a bit less than .length() so we use that
if self.width > oldWidth:
for hline in self.linesHorizontal:
line = hline.line()
line.setLength(self.width)
hline.setLine(line)
#Check if we need new lines
newLineCount = int(self.height / self.gapHorizontal)
if newLineCount > self.nrOfHorizontalLines:
newLineCount += int(newLineCount - self.nrOfHorizontalLines)
self._createHorizontalLines(start=self.nrOfHorizontalLines, end=newLineCount) #This draws only yet nonexisting lines.
self.nrOfHorizontalLines = newLineCount #for next time
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
@ -203,20 +151,10 @@ class GuiGrid(QtWidgets.QGraphicsItemGroup):
self.gapVertical = constantsAndConfigs.gridRhythm / constantsAndConfigs.ticksToPixelRatio #this is necessary every time after stretching (ticksToPixelRatio) and after changing the gridRhythm
for vline in self.linesVertical: #rhythm- and barlines
#if vline.x() < 400:
# print(vline.x(), vline.x() * factor)
vline.setX(vline.x() * factor)
self._fillVerticalLines()
for hline in self.linesHorizontal: #pitch helper lines
stretchLine(hline, factor)
self._fillHorizontalLines()
print()
print()
def updateMode(self, nameAsString):
assert nameAsString in constantsAndConfigs.availableEditModes
if nameAsString == "block":
@ -230,46 +168,31 @@ class GuiGrid(QtWidgets.QGraphicsItemGroup):
"""Lines get an offset that matches the grid-rythm.
So we get more draw area left, if the sceneRect will move into that area for some reason"""
for i in range(start, end): #range includes the first value but not the end. We know that and all functions in GuiGrid are designed accordingly. For example reactToLongerDuration starts on the highest value of the old number of lines since that was never drawn in the last round.
vline = self.parent.addLine(0, -5*self.gapHorizontal, 0, self.height, GuiGrid.gridPen) #x1, y1, x2, y2, pen
vline = self.parent.addLine(0, 0, 0, self.height, GuiGrid.gridPen) #x1, y1, x2, y2, pen
self.addToGroup(vline) #first add to group, then set pos
vline.setPos(i * self.gapVertical, 0)
vline.setEnabled(False)
vline.setAcceptedMouseButtons(QtCore.Qt.NoButton)
self.linesVertical.append(vline)
def _createHorizontalLines(self, start, end):
"""Lines get an offset that matches the pitch and staff-lines
So we get more draw area on top, if the sceneRect will move into that area for some reason"""
for i in range(start, end): #range includes the first value but not the end. We know that and all functions in GuiGrid are designed accordingly. For example reactToMoreTracks starts on the highest value of the old number of lines since that was never drawn in the last round.
hline = self.parent.addLine(0, 0, self.width, 0, GuiGrid.gridPen) #x1, y1, x2, y2, pen
self.addToGroup(hline) #first add to group, then set pos
hline.setPos(0, i * self.gapHorizontal)
hline.setEnabled(False)
hline.setAcceptedMouseButtons(QtCore.Qt.NoButton)
self.linesHorizontal.append(hline)
def redrawTickGrid(self):
"""A complete redraw.
This gets called once after the main window gets shown. (in init main window).
After that only called after the used changes the tick rhythm manually.
After that only called after the user changes the tick rhythm manually.
"""
if self.initialGridExists:
#it is possible that the grid did not change. proceed nevertheless
for l in self.linesHorizontal + self.linesVertical:
for l in self.linesVertical:
self.parent.removeWhenIdle(l)
self.linesHorizontal = [] #like the staff lines
self.linesVertical = [] #makes comparing tick positions easier by eye
self.gapVertical = constantsAndConfigs.gridRhythm / constantsAndConfigs.ticksToPixelRatio #this is necessarry every time after stretching (ticksToPixelRatio) and after changing the gridRhythm
self.gapHorizontal = constantsAndConfigs.stafflineGap #never changes
self.nrOfHorizontalLines = int(self.height / self.gapHorizontal) #we save that value if the score grows and we need more lines. Initially we use the screen size, not the content.
self.nrOfVerticalLines = int(self.width / self.gapVertical) #we save that value if the score grows and we need more lines. Initially we use the screen size, not the content.
self._createVerticalLines(0, self.nrOfVerticalLines)
self._createHorizontalLines(0, self.nrOfHorizontalLines)
self.initialGridExists = True

8
qtgui/scoreview.py

@ -143,10 +143,10 @@ class ScoreView(QtWidgets.QGraphicsView):
else:
raise ValueError("Edit Mode unknown")
#Grid is gone
#def resizeEvent(self, event):
# self.scoreScene.grid.reactToresizeEventOrZoom()
# super().resizeEvent(event)
def resizeEvent(self, event):
"""Triggers mostly when new notes are entered"""
self.scoreScene.grid.reactToresizeEventOrZoom()
super().resizeEvent(event)
def changeGridRhythm(self):
GridRhytmEdit(mainWindow=self.mainWindow) #handles everything.

Loading…
Cancel
Save