Browse Source

Refactor bounding rects

master
Nils 4 years ago
parent
commit
a508a830a3
  1. 13
      qtgui/conductor.py
  2. 17
      qtgui/cursor.py
  3. 12
      qtgui/graphs.py
  4. 5
      qtgui/grid.py
  5. 66
      qtgui/items.py
  6. 31
      qtgui/musicstructures.py
  7. 4
      qtgui/scorescene.py

13
qtgui/conductor.py

@ -28,8 +28,6 @@ from template.helper import pairwise
from .submenus import SecondaryTempoChangeMenu, TempoBlockPropertiesEdit
import engine.api as api
oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection.
_zValuesRelativeToConductor = { #Only use for objects added directly to the Conductor, not their children.
"line":0,
"startItem":1,
@ -238,17 +236,6 @@ class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem):
#self.setZValue(_zValuesRelativeToConductor["handle"]) #includes the handle
#Doesn't need it because only pure QGraphicItem subclasses need that. But we are already a rect.
#def boundingRect(self, *args):
# return oneRectToReturnThemAll
#Doesn't need it because only pure QGraphicItem subclasses need that. But we are already a rect.
#def paint(self, *args):
# """Prevent the selection rectangle when clicking the item"""
#!! This also prevents the rectangle to show up. Very bad decision.
# pass
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.

17
qtgui/cursor.py

@ -31,8 +31,6 @@ pen.setJoinStyle(QtCore.Qt.RoundJoin)
pen.setWidth(2)
#pen.setColor(QtGui.QColor("red"))
oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection.
class PitchCursor(QtWidgets.QGraphicsRectItem):
def __init__(self):
"""Does not need the actual dotOnLine.
@ -44,8 +42,6 @@ class PitchCursor(QtWidgets.QGraphicsRectItem):
self.setPen(pen)
self.setEnabled(False)
def boundingRect(self, *args): return oneRectToReturnThemAll
class PositionCursor(QtWidgets.QGraphicsRectItem):
def __init__(self):
"""Does not need the actual position.
@ -57,9 +53,6 @@ class PositionCursor(QtWidgets.QGraphicsRectItem):
self.setScale(0.8)
self.setEnabled(False)
def boundingRect(self, *args):
return oneRectToReturnThemAll
class Cursor(QtWidgets.QGraphicsItemGroup):
"""A cursor that shows the vertical
@ -75,10 +68,6 @@ class Cursor(QtWidgets.QGraphicsItemGroup):
api.callbacks.setCursor.append(self.setCursor)
self.setEnabled(False)
def boundingRect(self, *args):
return oneRectToReturnThemAll
def clearItemHighlight(self):
"""Gets called before a track changes. Most of the time when a new item is inserted/deleted.
This means the gui track will be recreated and a current highlight on an item might get
@ -154,10 +143,6 @@ class Playhead(QtWidgets.QGraphicsLineItem):
#self.hide()
#self.maxHeight = QtWidgets.QDesktopWidget().geometry().height() #we really hope the screen resolution does not change during the session.
def boundingRect(self, *args):
return oneRectToReturnThemAll
def setCursorPosition(self, tickindex:int, playbackStatus:bool):
"""Set the playhead to the right position, but keep the viewport stable.
Shift the entire "page" if the cursor becomes invisible because its steps outside the viewport"""
@ -235,8 +220,6 @@ class Selection(QtWidgets.QGraphicsRectItem):
self.setEnabled(False)
api.callbacks.setSelection.append(self.setSelection)
def boundingRect(self, *args):
return oneRectToReturnThemAll
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.

12
qtgui/graphs.py

@ -25,8 +25,6 @@ from .constantsAndConfigs import constantsAndConfigs
from template.qtgui.helper import stringToColor, removeInstancesFromScene, callContextMenu, stretchLine, stretchRect
import engine.api as api
oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection.
class CCPath(QtWidgets.QGraphicsRectItem):
"""
A CCPath only exists when the backend track has a cc-part activated.
@ -68,8 +66,6 @@ class CCPath(QtWidgets.QGraphicsRectItem):
self.blockdictCache = {} #blockId:guiBlock updated through self.updateGraphBlockTrack
self.transparentBlockHandles = [] #transparentBlockHandles in correct order. updated through self.updateGraphBlockTrack
def boundingRect(self, *args): return oneRectToReturnThemAll
def itemChange(self, changeEnum, value):
if changeEnum == QtWidgets.QGraphicsItem.ItemVisibleHasChanged: #12
if self.isVisible():
@ -257,8 +253,6 @@ class CCGraphTransparentBlock(QtWidgets.QGraphicsRectItem):
self.posBeforeMove = None
self.cursorPosOnMoveStart = None
def boundingRect(self, *args): return oneRectToReturnThemAll
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
@ -365,8 +359,6 @@ class CCGraphBlockEndMarker(QtWidgets.QGraphicsLineItem):
self.activePen = QtGui.QPen(pen)
self.activePen.setColor(QtGui.QColor("cyan"))
def boundingRect(self, *args): return oneRectToReturnThemAll
def allItemsRightOfMe(self):
for item in self.parentCCPath.items:
if item.x() > self.x():
@ -430,8 +422,6 @@ class CCInterpolatedPoint(QtWidgets.QGraphicsEllipseItem):
self.setEnabled(False)
self.setZValue(1)
def boundingRect(self, *args): return oneRectToReturnThemAll
class CCUserPoint(QtWidgets.QGraphicsEllipseItem):
"""the position is set by the parent"""
def __init__(self, parentCCPath, staticExportItem):
@ -449,8 +439,6 @@ class CCUserPoint(QtWidgets.QGraphicsEllipseItem):
self.interpolatedItemsLeft = []
self.setZValue(9)
def boundingRect(self, *args): return oneRectToReturnThemAll
def shape(self):
"""Return a more accurate shape for this item so that
mouse hovering is more accurate"""

5
qtgui/grid.py

@ -36,9 +36,6 @@ from .constantsAndConfigs import constantsAndConfigs
import engine.api as api
oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection.
masterLine = QtCore.QLineF(0, 0, 0, 128*constantsAndConfigs.stafflineGap) # (x1, y1, x2, y2)
class RhythmLine(QtWidgets.QGraphicsLineItem):
def __init__(self, parentGrid):
@ -98,8 +95,6 @@ class GuiGrid(QtWidgets.QGraphicsItemGroup):
gridPen = QtGui.QPen(QtCore.Qt.DotLine)
gridPen.setCosmetic(True)
def boundingRect(self, *args): return oneRectToReturnThemAll
def reactToHorizontalScroll(self, value):
if not self.initialGridExists:
return

66
qtgui/items.py

@ -41,8 +41,6 @@ setPos(0,0)"""
#Atomic items:
oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection.
class GuiTieCurveGraphicsItem(QtWidgets.QGraphicsPathItem):
pen = QtGui.QPen()
pen.setCapStyle(QtCore.Qt.RoundCap)
@ -60,9 +58,6 @@ class GuiTieCurveGraphicsItem(QtWidgets.QGraphicsPathItem):
self.noteExportObject = noteExportObject
self.draw()
def boundingRect(self, *args):
return oneRectToReturnThemAll
def draw(self):
lengthInPixel = self.noteExportObject["tieDistanceInTicks"] / constantsAndConfigs.ticksToPixelRatio
path = QtGui.QPainterPath()
@ -89,13 +84,13 @@ class GuiTupletNumber(QtWidgets.QGraphicsItem):
pen.setColor(QtGui.QColor("darkGrey"))
pen.setWidth(1)
def paint(self, *args):
pass
def boundingRect(self, *args):
return oneRectToReturnThemAll
def boundingRect(self):
return self.childrenBoundingRect()
def __init__(self, upper, lower):
super().__init__()
self.setFlag(QtWidgets.QGraphicsItem.ItemHasNoContents, True) #only child items. Without this we get notImplementedError: QGraphicsItem.paint() is abstract and must be overridden
#self.upper = QtWidgets.QGraphicsSimpleTextItem(str(upper))
#self.divider = QtWidgets.QGraphicsLineItem(0,0,10,0)
#self.divider.rotate(-70)
@ -117,6 +112,7 @@ class GuiItem(QtWidgets.QGraphicsItem):
"""A blank item. Subclass to implement your own"""
def __init__(self, staticItem):
super().__init__()
self.setFlag(QtWidgets.QGraphicsItem.ItemHasNoContents, True) #only child items. Without this we get notImplementedError: QGraphicsItem.paint() is abstract and must be overridden
self.staticItem = staticItem
dur = self.staticItem["completeDuration"]
exceptions = ["BlockEndMarker"]
@ -137,10 +133,9 @@ class GuiItem(QtWidgets.QGraphicsItem):
in GuiChord"""
pass
def paint(self, *args):
pass
def boundingRect(self, *args):
return oneRectToReturnThemAll
def boundingRect(self):
return self.childrenBoundingRect()
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
@ -185,22 +180,6 @@ class GuiRectangleNotehead(QtWidgets.QGraphicsRectItem):
self.accidental.setPos(0, 0) #not analogue to the notehead acciental position because here we choose the rectangle as parent
self.accidental.setParentItem(self)
#NOTE: this was from a time when mouse modification was possible. Leave for later use.
#def shape(self):
# """Qt Function
# Return a more accurate shape for this item so that
# mouse hovering is more accurate.
#
# Must be within the bounding rect."""
# return self.path
#def boundingRect(self, *args):
# """Keep in syn with self.shape()"""
# return self.pathRect
#def paint(self, *args):
#Do NOT implement this. This actually works already. The parent item needs this.
class GuiRectangleVelocity(QtWidgets.QGraphicsRectItem):
"""Displays the velocity of one note when in rectangle view mode.
@ -250,21 +229,6 @@ class GuiRectangleVelocity(QtWidgets.QGraphicsRectItem):
#Misc Qt Flags
self.setAcceptHoverEvents(False) #Make this explicit so it will be remembered that the gui rectangle velocity is a display only.
#NOTE: this was from a time when mouse modification was possible. Leave for later use.
#def shape(self):
# """Qt Function
# Return a more accurate shape for this item so that
# mouse hovering is more accurate.
#
# Must be within the bounding rect."""
# return self.path
#def boundingRect(self, *args):
# """Keep in syn with self.shape()"""
# return self.pathRect
#def paint(self, *args):
#Do NOT implement this. This actually works already. The parent item needs this.
class GuiRectangle(QtWidgets.QGraphicsItem):
"""An alternative notehead, used to change velocity and duration
@ -281,24 +245,22 @@ class GuiRectangle(QtWidgets.QGraphicsItem):
def __init__(self, noteExportObject):
super().__init__()
self.setFlag(QtWidgets.QGraphicsItem.ItemHasNoContents, True) #only child items. Without this we get notImplementedError: QGraphicsItem.paint() is abstract and must be overridden
self.notehead = GuiRectangleNotehead(parent = self, noteExportObject = noteExportObject)
self.velocity = GuiRectangleVelocity(parent = self, noteExportObject = noteExportObject)
self.notehead.setZValue(10) #within GuiRectangle
def boundingRect(self, *args):
return oneRectToReturnThemAll
def paint(self, *args):
pass
def boundingRect(self):
return self.childrenBoundingRect()
class GuiNote(QtWidgets.QGraphicsItem):
def __init__(self, noteExportObject, directionRightAndUpwards):
super(GuiNote, self).__init__()
self.setFlag(QtWidgets.QGraphicsItem.ItemHasNoContents, True) #only child items. Without this we get notImplementedError: QGraphicsItem.paint() is abstract and must be overridden
self.createNote(noteExportObject, directionRightAndUpwards)
def paint(self, *args):
pass
def boundingRect(self, *args):
return oneRectToReturnThemAll
def boundingRect(self):
return self.childrenBoundingRect()
def createNote(self, noteExportObject, directionRightAndUpwards):
#note head

31
qtgui/musicstructures.py

@ -43,8 +43,6 @@ from .submenus import BlockPropertiesEdit
cosmeticPen = QtGui.QPen()
cosmeticPen.setCosmetic(True)
oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection.
class GuiBlockHandle(QtWidgets.QGraphicsRectItem):
"""A simplified version of a Block. Since we don't use blocks in the GUI, only in the backend
we still need them sometimes as macro strutures, where we don't care about the content.
@ -95,8 +93,6 @@ class GuiBlockHandle(QtWidgets.QGraphicsRectItem):
self.startLabel = QtWidgets.QGraphicsSimpleTextItem("")
self.endLabel = QtWidgets.QGraphicsSimpleTextItem("")
def boundingRect(self, *args): return oneRectToReturnThemAll
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
@ -212,8 +208,6 @@ class GuiTrack(QtWidgets.QGraphicsItem):
self.nameGraphic = self.NameGraphic(self.staticExportItem["name"], parent = self)
self.staticItems.append(self.nameGraphic)
#Add one central "Create new CC Path" button which is for all non-existing CC Paths of this track and reacte to the current constantsAndConfig.ccValue
#This button is not in the CCPath object because those only get created for existing backend-CCs.
self.universalCreateFirstCCBlock = QtWidgets.QGraphicsSimpleTextItem(translate("musicstructures", "Create CC Path"))
@ -225,7 +219,6 @@ class GuiTrack(QtWidgets.QGraphicsItem):
#self.secondStageInitNowThatWeHaveAScene gets called by the ScoreScene.redraw(), where new tracks get created. After it was inserted into the scene.
def boundingRect(self, *args): return oneRectToReturnThemAll
class NameGraphic(QtWidgets.QGraphicsSimpleTextItem):
def __init__(self, text, parent):
@ -243,8 +236,6 @@ class GuiTrack(QtWidgets.QGraphicsItem):
if result[1]:
api.setTrackName(self.parent.staticExportItem["id"], nameString = result[0], initialInstrumentName = self.parent.staticExportItem["initialInstrumentName"], initialShortInstrumentName = self.parent.staticExportItem["initialShortInstrumentName"]) #keep the old lilypond names
#def boundingRect(self, *args): return oneRectToReturnThemAll
def contextMenuEvent(self, event):
listOfLabelsAndFunctions = [ (translate("musicstructures", "edit name"), self._editName), ]
callContextMenu(listOfLabelsAndFunctions)
@ -255,6 +246,18 @@ class GuiTrack(QtWidgets.QGraphicsItem):
has a position, opacity, parent item etc. (All of that is not read in normal __init__)"""
pass
def boundingRect(self):
"""Without bounding rect not mousePressEvents for children"""
if self.staticExportItem["double"]: #double track, twice as high
h = 10 * constantsAndConfigs.stafflineGap
else:
h = 4 * constantsAndConfigs.stafflineGap
w = self.lengthInPixel
return QtCore.QRectF(0,0,w,h) #x,y,w,h - relative to self, so pos is always 0,0
def toggleNoteheadsRectangles(self):
for item in self.items:
item.updateVisibility()
@ -397,18 +400,13 @@ class GuiTrack(QtWidgets.QGraphicsItem):
y = beamNumberOffset + positionAsStaffline * constantsAndConfigs.stafflineGap / 2 - 1
shifterAnchor.setPos(x, y)
class TrackAnchor(QtWidgets.QGraphicsItem):
class TrackAnchor(QtWidgets.QGraphicsItemGroup):
"""Handling all items as individuals when deleting a track to redraw it is too much.
Better let Qt handle it all at once."""
def __init__(self, parent):
super().__init__()
self.parent = parent
self.setFlag(QtWidgets.QGraphicsItem.ItemHasNoContents, True) #only child items. Without this we get notImplementedError: QGraphicsItem.paint() is abstract and must be overridden
self.setFlag(QtWidgets.QGraphicsItem.ItemContainsChildrenInShape, True)
def boundingRect(self, *args): return oneRectToReturnThemAll
def createGraphicItemsFromData(self, staticRepresentationList):
"""Create staff objects including simple barlines"""
@ -426,7 +424,8 @@ class GuiTrack(QtWidgets.QGraphicsItem):
metaDataDict = staticRepresentationList.pop()
for staticItem in staticRepresentationList:
item = staticItem2Item(staticItem)
item.setParentItem(self.anchor)
#item.setParentItem(self.anchor)
self.anchor.addToGroup(item)
itemsAppend(item)
item.setPos(item.pixelPosition, 0) # Y axis is set by the position of the track. This sets the position of the whole ItemGroup. The actual pitch of a chord/note is set locally by the chord itself and of no concern here.
item.setZValue(5) #This is the z value within GuiTrack

4
qtgui/scorescene.py

@ -35,7 +35,7 @@ from .constantsAndConfigs import constantsAndConfigs
#from .grid import GuiGrid
from .conductor import Conductor, ConductorTransparentBlock
from .musicstructures import GuiBlockHandle, GuiTrack
from .graphs import CCGraphTransparentBlock
from .graphs import CCGraphTransparentBlock, CCPath
from .cursor import Cursor, Playhead, Selection
@ -160,7 +160,7 @@ class GuiScore(QtWidgets.QGraphicsScene):
guiCCs.remove(backendCC) #all right. no update needed.
else: #new CC. not existent in the Gui yet. Create.
#This is the place where we create new CCPaths
new = graphs.CCPath(parentGuiTrack = self.tracks[trackId], parentDataTrackId = trackId)
new = CCPath(parentGuiTrack = self.tracks[trackId], parentDataTrackId = trackId)
self.tracks[trackId].ccPaths[backendCC] = new #store in the GUI Track
new.setParentItem(self.tracks[trackId])
new.setPos(0,0)

Loading…
Cancel
Save