Browse Source

Add missing rects and removal of whitespace

master
Nils 4 years ago
parent
commit
58de2ba26c
  1. 135
      qtgui/conductor.py
  2. 21
      qtgui/cursor.py
  3. 22
      qtgui/graphs.py
  4. 21
      qtgui/grid.py
  5. 9
      qtgui/items.py
  6. 54
      qtgui/mainwindow.py
  7. 26
      qtgui/menu.py
  8. 20
      qtgui/musicstructures.py
  9. 45
      qtgui/scorescene.py
  10. 16
      qtgui/scoreview.py
  11. 28
      qtgui/submenus.py
  12. 6
      qtgui/trackEditor.py

135
qtgui/conductor.py

@ -30,12 +30,12 @@ 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. 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. _zValuesRelativeToConductor = { #Only use for objects added directly to the Conductor, not their children.
"line":0, "line":0,
"startItem":1, "startItem":1,
"block":2, "block":2,
"item":4, "item":4,
"handle":5, "handle":5,
} }
class Conductor(QtWidgets.QGraphicsItem): class Conductor(QtWidgets.QGraphicsItem):
@ -52,6 +52,8 @@ class Conductor(QtWidgets.QGraphicsItem):
self.staticBlocks = None #Cached Block Data list self.staticBlocks = None #Cached Block Data list
self.staticMeta = None #Cached track meta data dict. self.staticMeta = None #Cached track meta data dict.
self.setFlag(QtWidgets.QGraphicsItem.ItemHasNoContents, True) #only child items. Without this we get notImplementedError: QGraphicsItem.paint() is abstract and must be overridden
self.staffLine = QtWidgets.QGraphicsLineItem(0,0,10,0) #x1, y1, x2, y2 self.staffLine = QtWidgets.QGraphicsLineItem(0,0,10,0) #x1, y1, x2, y2
self.staffLine.setParentItem(self) self.staffLine.setParentItem(self)
self.staffLine.setPos(0,0) self.staffLine.setPos(0,0)
@ -64,10 +66,9 @@ class Conductor(QtWidgets.QGraphicsItem):
api.callbacks.updateTempoTrack.append(self.createGraphicItemsFromData) api.callbacks.updateTempoTrack.append(self.createGraphicItemsFromData)
api.callbacks.updateTempoTrackMeta.append(self.updateMetaData) api.callbacks.updateTempoTrackMeta.append(self.updateMetaData)
def paint(self, *args):
pass
def boundingRect(self, *args): def boundingRect(self, *args):
return oneRectToReturnThemAll """The tempo track extends above the real tracks"""
return QtCore.QRectF(0, -1*self.totalHeight, 20000, 1.2*self.totalHeight) #x,y,w,h
def blockAt(self, xScenePosition): def blockAt(self, xScenePosition):
for block in ConductorTransparentBlock.instances: for block in ConductorTransparentBlock.instances:
@ -97,7 +98,7 @@ class Conductor(QtWidgets.QGraphicsItem):
for dictExportItem in staticRepresentationList: for dictExportItem in staticRepresentationList:
guiBlock = ConductorTransparentBlock(parent = self, staticExportItem = dictExportItem, x = 0, y = -10, w = dictExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio, h = 20) guiBlock = ConductorTransparentBlock(parent = self, staticExportItem = dictExportItem, x = 0, y = -10, w = dictExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio, h = 20)
guiBlock.setParentItem(self) guiBlock.setParentItem(self)
guiBlock.setPos(dictExportItem["position"] / constantsAndConfigs.ticksToPixelRatio,0) guiBlock.setPos(dictExportItem["position"] / constantsAndConfigs.ticksToPixelRatio,0)
rightBorder = (dictExportItem["duration"] + dictExportItem["position"]) / constantsAndConfigs.ticksToPixelRatio rightBorder = (dictExportItem["duration"] + dictExportItem["position"]) / constantsAndConfigs.ticksToPixelRatio
self.updateStaffLine(rightBorder) self.updateStaffLine(rightBorder)
@ -108,7 +109,7 @@ class Conductor(QtWidgets.QGraphicsItem):
return guiblock return guiblock
#else: #else:
# raise ValueError(f"{backendId} not found") # raise ValueError(f"{backendId} not found")
def updateStaffLine(self, x): def updateStaffLine(self, x):
assert not self.staffLine.line().isNull() assert not self.staffLine.line().isNull()
@ -117,8 +118,8 @@ class Conductor(QtWidgets.QGraphicsItem):
self.staffLine.setLine(line) self.staffLine.setLine(line)
self.staffLine.setZValue(_zValuesRelativeToConductor["line"]) self.staffLine.setZValue(_zValuesRelativeToConductor["line"])
def createGraphicItemsFromData(self, staticRepresentationList): def createGraphicItemsFromData(self, staticRepresentationList):
self.staticPoints = staticRepresentationList self.staticPoints = staticRepresentationList
removeInstancesFromScene(TempoPoint) removeInstancesFromScene(TempoPoint)
@ -129,8 +130,8 @@ class Conductor(QtWidgets.QGraphicsItem):
x = point["position"] / constantsAndConfigs.ticksToPixelRatio x = point["position"] / constantsAndConfigs.ticksToPixelRatio
p = TempoPoint(self, point, self.blockById(point["blockId"])) p = TempoPoint(self, point, self.blockById(point["blockId"]))
p.setParentItem(self) p.setParentItem(self)
p.setPos(x, y) p.setPos(x, y)
def stretchXCoordinates(self, factor): def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis. """Reposition the items on the X axis.
@ -163,21 +164,21 @@ class Conductor(QtWidgets.QGraphicsItem):
def add(self, scenePos): def add(self, scenePos):
"""Use a scenePos (from self.mousePressEvent) to instruct the backend """Use a scenePos (from self.mousePressEvent) to instruct the backend
to create a new tempo point. to create a new tempo point.
Uses the values from the item left of it Uses the values from the item left of it
""" """
sp = scenePos.x() * constantsAndConfigs.ticksToPixelRatio sp = scenePos.x() * constantsAndConfigs.ticksToPixelRatio
if constantsAndConfigs.snapToGrid: if constantsAndConfigs.snapToGrid:
sp = round(sp / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm sp = round(sp / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
unitsPerMinute, referenceTicks = api.tempoAtTickPosition(sp) unitsPerMinute, referenceTicks = api.tempoAtTickPosition(sp)
api.insertTempoItemAtAbsolutePosition(sp, unitsPerMinute, referenceTicks, graphType = "standalone") api.insertTempoItemAtAbsolutePosition(sp, unitsPerMinute, referenceTicks, graphType = "standalone")
class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem): class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem):
"""A simplified version of a Block. Since we don't use blocks in the GUI, only in the backend """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. we still need them sometimes as macro strutures, where we don't care about the content.
The block handle is at the END of a block. """ The block handle is at the END of a block. """
@ -205,9 +206,9 @@ class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem):
self.color = stringToColor(staticExportItem["name"]) self.color = stringToColor(staticExportItem["name"])
self.trans = QtGui.QColor("transparent") self.trans = QtGui.QColor("transparent")
self.setPen(self.trans) self.setPen(self.trans)
self.setBrush(self.color) self.setBrush(self.color)
self.setOpacity(0.2) #mimic background behaviour self.setOpacity(0.2) #mimic background behaviour
self.staticExportItem = staticExportItem self.staticExportItem = staticExportItem
self.posBeforeMove = None self.posBeforeMove = None
self.cursorPosOnMoveStart = None self.cursorPosOnMoveStart = None
@ -230,14 +231,19 @@ class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem):
self.startLabel = QtWidgets.QGraphicsSimpleTextItem("") self.startLabel = QtWidgets.QGraphicsSimpleTextItem("")
self.endLabel = QtWidgets.QGraphicsSimpleTextItem("") self.endLabel = QtWidgets.QGraphicsSimpleTextItem("")
#Add Resizing Handle at the end #Add Resizing Handle at the end
self.marker = ConductorBlockHandle(parent = self) self.marker = ConductorBlockHandle(parent = self)
self.marker.setParentItem(self) self.marker.setParentItem(self)
self.marker.setPos(staticExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio, -1/2* self.rect().height()+2) self.marker.setPos(staticExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio, -1/2* self.rect().height()+2)
#self.setZValue(_zValuesRelativeToConductor["handle"]) #includes the handle #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): #def paint(self, *args):
# """Prevent the selection rectangle when clicking the item""" # """Prevent the selection rectangle when clicking the item"""
#!! This also prevents the rectangle to show up. Very bad decision. #!! This also prevents the rectangle to show up. Very bad decision.
@ -251,13 +257,13 @@ class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem):
self.marker.setX(self.marker.pos().x() * factor) self.marker.setX(self.marker.pos().x() * factor)
def mouseMoveEvent(self, event): def mouseMoveEvent(self, event):
"""Don't use the qt system. we move ourselves""" """Don't use the qt system. we move ourselves"""
event.accept() event.accept()
def mousePressEvent(self, event): def mousePressEvent(self, event):
self.parent.mousePressEvent(event) self.parent.mousePressEvent(event)
def mouseMoveEventCustom(self, event): def mouseMoveEventCustom(self, event):
""" """
Move the whole block, change the tempoTrack form. Move the whole block, change the tempoTrack form.
Custom gets called by the scene mouse press event directly only when the right keys Custom gets called by the scene mouse press event directly only when the right keys
@ -272,7 +278,7 @@ class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem):
#posView = self.parent.parentScore.parentView.mapFromGlobal(posGlobal) #a widget #posView = self.parent.parentScore.parentView.mapFromGlobal(posGlobal) #a widget
#posScene = self.parent.parentScore.parentView.mapToScene(posView) #posScene = self.parent.parentScore.parentView.mapToScene(posView)
#print (posGlobal, posView, posScene, event.scenePos()) #print (posGlobal, posView, posScene, event.scenePos())
if self.cursorPosOnMoveStart: if self.cursorPosOnMoveStart:
self.setPos(event.scenePos().x(), self.posBeforeMove.y()) self.setPos(event.scenePos().x(), self.posBeforeMove.y())
@ -340,13 +346,13 @@ class ConductorBlockHandle(QtWidgets.QGraphicsRectItem):
def __init__(self, parent): def __init__(self, parent):
self.parentTransparentBlock = parent self.parentTransparentBlock = parent
#Line item super().__init__(0,-1, 0, parent.rect().height()-4) #x1, y1, x2, y2 #Line item super().__init__(0,-1, 0, parent.rect().height()-4) #x1, y1, x2, y2
super().__init__(-3, -2, 3, parent.rect().height()) #x, y, w, h super().__init__(-3, -2, 3, parent.rect().height()) #x, y, w, h
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable|QtWidgets.QGraphicsItem.ItemSendsGeometryChanges|QtWidgets.QGraphicsItem.ItemIsFocusable|QtWidgets.QGraphicsItem.ItemIgnoresParentOpacity) #QtWidgets.QGraphicsItem.ItemClipsToShape puts the item behind the parent rect and only receives event inside its own shape. self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable|QtWidgets.QGraphicsItem.ItemSendsGeometryChanges|QtWidgets.QGraphicsItem.ItemIsFocusable|QtWidgets.QGraphicsItem.ItemIgnoresParentOpacity) #QtWidgets.QGraphicsItem.ItemClipsToShape puts the item behind the parent rect and only receives event inside its own shape.
self.setAcceptHoverEvents(True) self.setAcceptHoverEvents(True)
self.setCursor(QtCore.Qt.SizeHorCursor) self.setCursor(QtCore.Qt.SizeHorCursor)
self.setZValue(_zValuesRelativeToConductor["handle"]) #The handle does not compete with the transparent block but with its contents! Therefore the startItem is set to have a custom lower priority than the handle self.setZValue(_zValuesRelativeToConductor["handle"]) #The handle does not compete with the transparent block but with its contents! Therefore the startItem is set to have a custom lower priority than the handle
self.setBrush(QtGui.QColor("black")) self.setBrush(QtGui.QColor("black"))
self.minimalSize = api.D1 / constantsAndConfigs.ticksToPixelRatio self.minimalSize = api.D1 / constantsAndConfigs.ticksToPixelRatio
pen = QtGui.QPen() # creates a default pen pen = QtGui.QPen() # creates a default pen
@ -359,8 +365,8 @@ class ConductorBlockHandle(QtWidgets.QGraphicsRectItem):
self.inactivePen.setColor(QtGui.QColor("black")) self.inactivePen.setColor(QtGui.QColor("black"))
self.activePen = QtGui.QPen(pen) self.activePen = QtGui.QPen(pen)
self.activePen.setColor(QtGui.QColor("cyan")) self.activePen.setColor(QtGui.QColor("cyan"))
def shape(self): def shape(self):
"""Return a more accurate shape for this item so that """Return a more accurate shape for this item so that
mouse hovering is more accurate""" mouse hovering is more accurate"""
@ -368,14 +374,14 @@ class ConductorBlockHandle(QtWidgets.QGraphicsRectItem):
path.addRect(QtCore.QRectF(-2, -2, 5, self.parentTransparentBlock.rect().height()+2 )) #this is directly related to inits parameter x, y, w, h path.addRect(QtCore.QRectF(-2, -2, 5, self.parentTransparentBlock.rect().height()+2 )) #this is directly related to inits parameter x, y, w, h
return path return path
def hoverEnterEvent(self, event): def hoverEnterEvent(self, event):
self.setPen(self.activePen) self.setPen(self.activePen)
#self.parentTransparentBlock.setBrush(self.parentTransparentBlock.color) #self.parentTransparentBlock.setBrush(self.parentTransparentBlock.color)
self.setBrush(QtGui.QColor("cyan")) self.setBrush(QtGui.QColor("cyan"))
def hoverLeaveEvent(self, event): def hoverLeaveEvent(self, event):
self.setPen(self.inactivePen) self.setPen(self.inactivePen)
#self.parentTransparentBlock.setBrush(self.parentTransparentBlock.trans) #self.parentTransparentBlock.setBrush(self.parentTransparentBlock.trans)
self.setBrush(QtGui.QColor("black")) self.setBrush(QtGui.QColor("black"))
def mousePressEvent(self, event): def mousePressEvent(self, event):
@ -418,7 +424,7 @@ class ConductorBlockHandle(QtWidgets.QGraphicsRectItem):
class TempoPoint(QtWidgets.QGraphicsItem): class TempoPoint(QtWidgets.QGraphicsItem):
"""A point where the values can be edited by the user. """A point where the values can be edited by the user.
The first TempoPoint cannot be hovered. It is instead attached to a block handle. The first TempoPoint cannot be hovered. It is instead attached to a block handle.
""" """
@ -429,19 +435,16 @@ class TempoPoint(QtWidgets.QGraphicsItem):
super().__init__() super().__init__()
self.staticExportItem = staticExportItem self.staticExportItem = staticExportItem
self.parentTempoTrack = parentTempoTrack self.parentTempoTrack = parentTempoTrack
self.parentBlock = parentBlock self.parentBlock = parentBlock
self.setZValue(_zValuesRelativeToConductor["item"]) self.setZValue(_zValuesRelativeToConductor["item"])
self.setAcceptHoverEvents(True) self.setAcceptHoverEvents(True)
if not self.staticExportItem["positionInBlock"] == 0: if not self.staticExportItem["positionInBlock"] == 0:
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable|QtWidgets.QGraphicsItem.ItemIsFocusable) self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable|QtWidgets.QGraphicsItem.ItemIsFocusable)
#Too irritating. And confuses with handle movement. self.setCursor(QtCore.Qt.SizeHorCursor) #this sets the cursor while the mouse is over the item. It is independent of AcceptHoverEvents #Too irritating. And confuses with handle movement. self.setCursor(QtCore.Qt.SizeHorCursor) #this sets the cursor while the mouse is over the item. It is independent of AcceptHoverEvents
else: else:
self.setZValue(0) #avoid hovering conflict with block handle self.setZValue(0) #avoid hovering conflict with block handle
self.ungrabMouse = api.nothing #to surpress a warning from the context menu self.ungrabMouse = api.nothing #to surpress a warning from the context menu
self.note = QtWidgets.QGraphicsTextItem("") self.note = QtWidgets.QGraphicsTextItem("")
self.note.setParentItem(self) self.note.setParentItem(self)
@ -465,7 +468,7 @@ class TempoPoint(QtWidgets.QGraphicsItem):
for n in (self.note, self.number, self.arrow): for n in (self.note, self.number, self.arrow):
if n: n.setDefaultTextColor(QtGui.QColor("black")) if n: n.setDefaultTextColor(QtGui.QColor("black"))
self.wheelEventChangedValue = 0 #resetted in hoverEnterEvent. But we still need it for new items that appear directly under the mouse cursor self.wheelEventChangedValue = 0 #resetted in hoverEnterEvent. But we still need it for new items that appear directly under the mouse cursor
def paint(self, painter, options, widget=None): def paint(self, painter, options, widget=None):
#painter.drawRect(self.boundingRect()) #uncomment to show the bounding rect #painter.drawRect(self.boundingRect()) #uncomment to show the bounding rect
@ -491,21 +494,21 @@ class TempoPoint(QtWidgets.QGraphicsItem):
event.accept() event.accept()
def mousePressEvent(self, event): def mousePressEvent(self, event):
"""Override the mousePressEvent to deactivate it. """Override the mousePressEvent to deactivate it.
Otherwise the event will be sent to the parent block and create a new TempoItem Otherwise the event will be sent to the parent block and create a new TempoItem
at this point even if there is already one. Effectively replacing a custom item with at this point even if there is already one. Effectively replacing a custom item with
default value""" default value"""
#if self.staticExportItem["positionInBlock"] == 0: #if self.staticExportItem["positionInBlock"] == 0:
# print ("no") # print ("no")
# #super().mousePressEvent(event) # #super().mousePressEvent(event)
event.accept() # event.accept() #
def mouseReleaseEvent(self, event): def mouseReleaseEvent(self, event):
if self.staticExportItem["positionInBlock"] == 0: if self.staticExportItem["positionInBlock"] == 0:
#First in block can't be moved #First in block can't be moved
event.accept() event.accept()
return return
tickPositionAbsolute = self.scenePos().x() * constantsAndConfigs.ticksToPixelRatio tickPositionAbsolute = self.scenePos().x() * constantsAndConfigs.ticksToPixelRatio
if constantsAndConfigs.snapToGrid: if constantsAndConfigs.snapToGrid:
@ -513,17 +516,17 @@ class TempoPoint(QtWidgets.QGraphicsItem):
api.moveTempoItem(self.staticExportItem["id"], tickPositionAbsolute) api.moveTempoItem(self.staticExportItem["id"], tickPositionAbsolute)
event.accept() event.accept()
def hoverEnterEvent(self, event): def hoverEnterEvent(self, event):
self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(False) #Delete key collides with our hover-delete. self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(False) #Delete key collides with our hover-delete.
self.grabKeyboard() self.grabKeyboard()
self.wheelEventChangedValue = 0 self.wheelEventChangedValue = 0
for n in (self.note, self.number, self.arrow): for n in (self.note, self.number, self.arrow):
if n: n.setDefaultTextColor(QtGui.QColor("cyan")) if n: n.setDefaultTextColor(QtGui.QColor("cyan"))
def hoverLeaveEvent(self, event): def hoverLeaveEvent(self, event):
self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(True) #Delete key collides with our hover-delete. self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(True) #Delete key collides with our hover-delete.
self.ungrabKeyboard() self.ungrabKeyboard()
for n in (self.note, self.number, self.arrow): for n in (self.note, self.number, self.arrow):
if n: n.setDefaultTextColor(QtGui.QColor("black")) if n: n.setDefaultTextColor(QtGui.QColor("black"))
if self.wheelEventChangedValue: if self.wheelEventChangedValue:
@ -531,7 +534,6 @@ class TempoPoint(QtWidgets.QGraphicsItem):
def wheelEvent(self, event): def wheelEvent(self, event):
"""This buffers until hoverLeaveEvent and then the new value is sent in self.hoverLeaveEvent""" """This buffers until hoverLeaveEvent and then the new value is sent in self.hoverLeaveEvent"""
print ("w")
if event.delta() > 0: if event.delta() > 0:
self.wheelEventChangedValue += 1 self.wheelEventChangedValue += 1
else: else:
@ -542,15 +544,15 @@ class TempoPoint(QtWidgets.QGraphicsItem):
def keyPressEvent(self, event): def keyPressEvent(self, event):
"""Handle the delete item key. """Handle the delete item key.
Needs grabKeyboard, but NOT setFocus Needs grabKeyboard, but NOT setFocus
The event will not be sent if it is blocked by a global shortcut. The event will not be sent if it is blocked by a global shortcut.
""" """
key = event.key() key = event.key()
if key == 16777223: if key == 16777223:
#after delete the item and tempo tracks gets recreated so we need to reactivate the shortcut now. It will work without these two lines, but that is only implicit behaviour. #after delete the item and tempo tracks gets recreated so we need to reactivate the shortcut now. It will work without these two lines, but that is only implicit behaviour.
self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(True) #Delete key collides with our hover-delete. self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(True) #Delete key collides with our hover-delete.
self.ungrabKeyboard() self.ungrabKeyboard()
api.removeTempoItem(self.staticExportItem["id"]) api.removeTempoItem(self.staticExportItem["id"])
else: else:
return super().keyPressEvent(event) return super().keyPressEvent(event)
@ -581,15 +583,16 @@ class TimeLine(QtWidgets.QGraphicsItem):
def __init__(self, parent): def __init__(self, parent):
super().__init__() super().__init__()
self.parent = parent self.parent = parent #
self.gridInSeconds = 10 self.gridInSeconds = 10
api.callbacks.updateTempoTrackBlocks.append(self.redraw) api.callbacks.updateTempoTrackBlocks.append(self.redraw)
#no redraw on init. self.parent.staticPoints is not set yet. #no redraw on init. self.parent.staticPoints is not set yet.
def paint(self, *args): def paint(self, *args):
pass pass
def boundingRect(self, *args): def boundingRect(self, *args):
return oneRectToReturnThemAll return self.parent.boundingRect()
def redraw(self, staticRepresentationList): def redraw(self, staticRepresentationList):
if not self.parent.staticPoints: if not self.parent.staticPoints:
@ -640,7 +643,3 @@ class TimeLine(QtWidgets.QGraphicsItem):
time grid""" time grid"""
for timePoint in self.TimePoint.instances: for timePoint in self.TimePoint.instances:
timePoint.setX(timePoint.pos().x() * factor) timePoint.setX(timePoint.pos().x() * factor)

21
qtgui/cursor.py

@ -31,6 +31,8 @@ pen.setJoinStyle(QtCore.Qt.RoundJoin)
pen.setWidth(2) pen.setWidth(2)
#pen.setColor(QtGui.QColor("red")) #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): class PitchCursor(QtWidgets.QGraphicsRectItem):
def __init__(self): def __init__(self):
"""Does not need the actual dotOnLine. """Does not need the actual dotOnLine.
@ -42,6 +44,8 @@ class PitchCursor(QtWidgets.QGraphicsRectItem):
self.setPen(pen) self.setPen(pen)
self.setEnabled(False) self.setEnabled(False)
def boundingRect(self, *args): return oneRectToReturnThemAll
class PositionCursor(QtWidgets.QGraphicsRectItem): class PositionCursor(QtWidgets.QGraphicsRectItem):
def __init__(self): def __init__(self):
"""Does not need the actual position. """Does not need the actual position.
@ -53,6 +57,10 @@ class PositionCursor(QtWidgets.QGraphicsRectItem):
self.setScale(0.8) self.setScale(0.8)
self.setEnabled(False) self.setEnabled(False)
def boundingRect(self, *args):
return oneRectToReturnThemAll
class Cursor(QtWidgets.QGraphicsItemGroup): class Cursor(QtWidgets.QGraphicsItemGroup):
"""A cursor that shows the vertical """A cursor that shows the vertical
as well as the horizontal position as well as the horizontal position
@ -67,6 +75,10 @@ class Cursor(QtWidgets.QGraphicsItemGroup):
api.callbacks.setCursor.append(self.setCursor) api.callbacks.setCursor.append(self.setCursor)
self.setEnabled(False) self.setEnabled(False)
def boundingRect(self, *args):
return oneRectToReturnThemAll
def clearItemHighlight(self): def clearItemHighlight(self):
"""Gets called before a track changes. Most of the time when a new item is inserted/deleted. """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 This means the gui track will be recreated and a current highlight on an item might get
@ -93,7 +105,7 @@ class Cursor(QtWidgets.QGraphicsItemGroup):
x = cursorExportObject["tickindex"] / constantsAndConfigs.ticksToPixelRatio x = cursorExportObject["tickindex"] / constantsAndConfigs.ticksToPixelRatio
#Finally shift the Position to the correct track. Trackindex from 0, naturally. #Finally shift the Position to the correct track. Trackindex from 0, naturally.
#self.setPos(x, constantsAndConfigs.timeLineOffsetNoteEditor + cursorExportObject["trackIndex"] * constantsAndConfigs.trackHeight) #self.setPos(x, constantsAndConfigs.timeLineOffsetNoteEditor + cursorExportObject["trackIndex"] * constantsAndConfigs.trackHeight)
currentGuiTrack = self.scene().tracks[cursorExportObject["trackId"]] currentGuiTrack = self.scene().tracks[cursorExportObject["trackId"]]
self.setPos(x, currentGuiTrack.y() ) self.setPos(x, currentGuiTrack.y() )
@ -142,6 +154,10 @@ class Playhead(QtWidgets.QGraphicsLineItem):
#self.hide() #self.hide()
#self.maxHeight = QtWidgets.QDesktopWidget().geometry().height() #we really hope the screen resolution does not change during the session. #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): def setCursorPosition(self, tickindex:int, playbackStatus:bool):
"""Set the playhead to the right position, but keep the viewport stable. """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""" Shift the entire "page" if the cursor becomes invisible because its steps outside the viewport"""
@ -215,6 +231,9 @@ class Selection(QtWidgets.QGraphicsRectItem):
self.setEnabled(False) self.setEnabled(False)
api.callbacks.setSelection.append(self.setSelection) api.callbacks.setSelection.append(self.setSelection)
def boundingRect(self, *args):
return oneRectToReturnThemAll
def setSelection(self, tupleOfCursorExportObjects): def setSelection(self, tupleOfCursorExportObjects):
if tupleOfCursorExportObjects: if tupleOfCursorExportObjects:
validSelection, topleftCursorObject, bottomRightCursorObject = tupleOfCursorExportObjects validSelection, topleftCursorObject, bottomRightCursorObject = tupleOfCursorExportObjects

22
qtgui/graphs.py

@ -25,6 +25,8 @@ from .constantsAndConfigs import constantsAndConfigs
from template.qtgui.helper import stringToColor, removeInstancesFromScene, callContextMenu, stretchLine, stretchRect from template.qtgui.helper import stringToColor, removeInstancesFromScene, callContextMenu, stretchLine, stretchRect
import engine.api as api 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): class CCPath(QtWidgets.QGraphicsRectItem):
""" """
A CCPath only exists when the backend track has a cc-part activated. A CCPath only exists when the backend track has a cc-part activated.
@ -66,6 +68,8 @@ class CCPath(QtWidgets.QGraphicsRectItem):
self.blockdictCache = {} #blockId:guiBlock updated through self.updateGraphBlockTrack self.blockdictCache = {} #blockId:guiBlock updated through self.updateGraphBlockTrack
self.transparentBlockHandles = [] #transparentBlockHandles in correct order. 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): def itemChange(self, changeEnum, value):
if changeEnum == QtWidgets.QGraphicsItem.ItemVisibleHasChanged: #12 if changeEnum == QtWidgets.QGraphicsItem.ItemVisibleHasChanged: #12
if self.isVisible(): if self.isVisible():
@ -76,7 +80,7 @@ class CCPath(QtWidgets.QGraphicsRectItem):
return super().itemChange(changeEnum, value) return super().itemChange(changeEnum, value)
def mousePressEvent(self, event): def mousePressEvent(self, event):
if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton if event.button() == 1: #QtCore.Qt.LeftButton
self.add(event.pos()) self.add(event.pos())
@property @property
@ -253,6 +257,8 @@ class CCGraphTransparentBlock(QtWidgets.QGraphicsRectItem):
self.posBeforeMove = None self.posBeforeMove = None
self.cursorPosOnMoveStart = None self.cursorPosOnMoveStart = None
def boundingRect(self, *args): return oneRectToReturnThemAll
def stretchXCoordinates(self, factor): def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis. """Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates. Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
@ -359,6 +365,8 @@ class CCGraphBlockEndMarker(QtWidgets.QGraphicsLineItem):
self.activePen = QtGui.QPen(pen) self.activePen = QtGui.QPen(pen)
self.activePen.setColor(QtGui.QColor("cyan")) self.activePen.setColor(QtGui.QColor("cyan"))
def boundingRect(self, *args): return oneRectToReturnThemAll
def allItemsRightOfMe(self): def allItemsRightOfMe(self):
for item in self.parentCCPath.items: for item in self.parentCCPath.items:
if item.x() > self.x(): if item.x() > self.x():
@ -376,7 +384,7 @@ class CCGraphBlockEndMarker(QtWidgets.QGraphicsLineItem):
"""After moving a point around """After moving a point around
send an update to the backend""" send an update to the backend"""
super(CCGraphBlockEndMarker, self).mouseReleaseEvent(event) super(CCGraphBlockEndMarker, self).mouseReleaseEvent(event)
if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton if event.button() == 1: #QtCore.Qt.LeftButton
x = event.scenePos().x() x = event.scenePos().x()
#x = self.x() #x = self.x()
x = x * constantsAndConfigs.ticksToPixelRatio x = x * constantsAndConfigs.ticksToPixelRatio
@ -390,7 +398,7 @@ class CCGraphBlockEndMarker(QtWidgets.QGraphicsLineItem):
def mousePressEvent(self, event): def mousePressEvent(self, event):
super(CCGraphBlockEndMarker, self).mousePressEvent(event) super(CCGraphBlockEndMarker, self).mousePressEvent(event)
if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton if event.button() == 1: #QtCore.Qt.LeftButton
for i in self.allItemsRightOfMe(): for i in self.allItemsRightOfMe():
i.hide() i.hide()
@ -422,6 +430,8 @@ class CCInterpolatedPoint(QtWidgets.QGraphicsEllipseItem):
self.setEnabled(False) self.setEnabled(False)
self.setZValue(1) self.setZValue(1)
def boundingRect(self, *args): return oneRectToReturnThemAll
class CCUserPoint(QtWidgets.QGraphicsEllipseItem): class CCUserPoint(QtWidgets.QGraphicsEllipseItem):
"""the position is set by the parent""" """the position is set by the parent"""
def __init__(self, parentCCPath, staticExportItem): def __init__(self, parentCCPath, staticExportItem):
@ -439,6 +449,8 @@ class CCUserPoint(QtWidgets.QGraphicsEllipseItem):
self.interpolatedItemsLeft = [] self.interpolatedItemsLeft = []
self.setZValue(9) self.setZValue(9)
def boundingRect(self, *args): return oneRectToReturnThemAll
def shape(self): def shape(self):
"""Return a more accurate shape for this item so that """Return a more accurate shape for this item so that
mouse hovering is more accurate""" mouse hovering is more accurate"""
@ -450,7 +462,7 @@ class CCUserPoint(QtWidgets.QGraphicsEllipseItem):
super().mousePressEvent(event) super().mousePressEvent(event)
self.lastPos = self.pos() self.lastPos = self.pos()
if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton if event.button() == 1: #QtCore.Qt.LeftButton
self.setCursor(QtCore.Qt.BlankCursor) self.setCursor(QtCore.Qt.BlankCursor)
for i in self.interpolatedItemsLeft + self.interpolatedItemsRight: for i in self.interpolatedItemsLeft + self.interpolatedItemsRight:
i.hide() i.hide()
@ -480,7 +492,7 @@ class CCUserPoint(QtWidgets.QGraphicsEllipseItem):
send an update to the backend""" send an update to the backend"""
super(CCUserPoint, self).mouseReleaseEvent(event) super(CCUserPoint, self).mouseReleaseEvent(event)
self.setCursor(QtCore.Qt.SizeAllCursor) self.setCursor(QtCore.Qt.SizeAllCursor)
if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton if event.button() == 1: #QtCore.Qt.LeftButton
api.changeGraphItem(self.staticExportItem["id"], self.getXDifferenceAsBackendValue(), self.getYAsBackendValue()) #send update to the backend, don't wait for callback. api.changeGraphItem(self.staticExportItem["id"], self.getXDifferenceAsBackendValue(), self.getYAsBackendValue()) #send update to the backend, don't wait for callback.
def mouseMoveEvent(self, event): def mouseMoveEvent(self, event):

21
qtgui/grid.py

@ -21,15 +21,32 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging; logger = logging.getLogger(__name__); logger.info("import") import logging; logger = logging.getLogger(__name__); logger.info("import")
#Standard Library #Standard Library
#Third Party #Third Party
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
#Our Template Modules #Our Template Modules
from template.engine.sequencer import MAXIMUM_TICK_DURATION
#Client Modules #Client Modules
from .constantsAndConfigs import constantsAndConfigs 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):
super().__init__(masterLine)
self.setEnabled(False)
self.setParentItem(parentGrid)
self.setAcceptedMouseButtons(QtCore.Qt.NoButton) #we still need this otherwise no rubberband.
class GuiGrid(QtWidgets.QGraphicsItemGroup): class GuiGrid(QtWidgets.QGraphicsItemGroup):
"""The grid consists of vertical and horizontal lines. """The grid consists of vertical and horizontal lines.
@ -49,7 +66,7 @@ class GuiGrid(QtWidgets.QGraphicsItemGroup):
A complete clean and redraw only happens when the tick rhythm changes. A complete clean and redraw only happens when the tick rhythm changes.
""" """
def __init__(self, parent, horizontalSize=None): def __init__(self, parent, horizontalSize=None):
super(GuiGrid, self).__init__() super(GuiGrid, self).__init__()
self.parent = parent #QGraphicsScene self.parent = parent #QGraphicsScene
@ -81,6 +98,8 @@ class GuiGrid(QtWidgets.QGraphicsItemGroup):
gridPen = QtGui.QPen(QtCore.Qt.DotLine) gridPen = QtGui.QPen(QtCore.Qt.DotLine)
gridPen.setCosmetic(True) gridPen.setCosmetic(True)
def boundingRect(self, *args): return oneRectToReturnThemAll
def reactToHorizontalScroll(self, value): def reactToHorizontalScroll(self, value):
if not self.initialGridExists: if not self.initialGridExists:
return return

9
qtgui/items.py

@ -60,6 +60,9 @@ class GuiTieCurveGraphicsItem(QtWidgets.QGraphicsPathItem):
self.noteExportObject = noteExportObject self.noteExportObject = noteExportObject
self.draw() self.draw()
def boundingRect(self, *args):
return oneRectToReturnThemAll
def draw(self): def draw(self):
lengthInPixel = self.noteExportObject["tieDistanceInTicks"] / constantsAndConfigs.ticksToPixelRatio lengthInPixel = self.noteExportObject["tieDistanceInTicks"] / constantsAndConfigs.ticksToPixelRatio
path = QtGui.QPainterPath() path = QtGui.QPainterPath()
@ -756,13 +759,13 @@ class GuiMetricalInstruction(GuiItem):
displayString = "Metrical " + r displayString = "Metrical " + r
markerPosition = -2 markerPosition = -2
markerHeight = 4 markerHeight = 4
#A metrical instruction is by definition at the beginning of a measure #A metrical instruction is by definition at the beginning of a measure
#We therefore need to place the text above the barnumber #We therefore need to place the text above the barnumber
self.text = QtWidgets.QGraphicsSimpleTextItem(displayString) self.text = QtWidgets.QGraphicsSimpleTextItem(displayString)
self.text.setParentItem(self) self.text.setParentItem(self)
self.text.setPos(0, -7 * constantsAndConfigs.stafflineGap) self.text.setPos(0, -7 * constantsAndConfigs.stafflineGap)
self.marker = GuiPositionMarker(markerHeight, markerPosition) self.marker = GuiPositionMarker(markerHeight, markerPosition)
self.marker.setParentItem(self) self.marker.setParentItem(self)
@ -913,6 +916,6 @@ def staticItem2Item(staticItem):
elif typ is "BlockEndMarker": elif typ is "BlockEndMarker":
return GuiBlockEndMarker(staticItem) return GuiBlockEndMarker(staticItem)
elif typ in ("InstrumentChange", "ChannelChange", "LilypondText"): elif typ in ("InstrumentChange", "ChannelChange", "LilypondText"):
return GuiGenericText(staticItem) return GuiGenericText(staticItem)
else: else:
raise ValueError("Unknown Item Type:", staticItem) raise ValueError("Unknown Item Type:", staticItem)

54
qtgui/mainwindow.py

@ -60,7 +60,7 @@ class MainWindow(TemplateMainWindow):
#Make the first three words matter! #Make the first three words matter!
#Do not start them all with "You can..." or "...that you can", in response to the Did you know? title. #Do not start them all with "You can..." or "...that you can", in response to the Did you know? title.
#We use injection into the class and not a parameter because this dialog gets shown by creating an object. We can't give the parameters when this is shown via the mainWindow menu. #We use injection into the class and not a parameter because this dialog gets shown by creating an object. We can't give the parameters when this is shown via the mainWindow menu.
About.didYouKnow = [ About.didYouKnow = [
translate("About", "<p>Most commands work in the appending position (last position in a track) and apply to the item before it.</p><p>Use it to apply dots, sharps and flats on the item you just inserted without moving the cursor back and forth.</p>"), translate("About", "<p>Most commands work in the appending position (last position in a track) and apply to the item before it.</p><p>Use it to apply dots, sharps and flats on the item you just inserted without moving the cursor back and forth.</p>"),
translate("About", "<p>Learn the keyboard shortcuts! Laborejo is designed to work with the keyboard alone and with midi instruments for full speed.</p>Everytime you grab your mouse you loose concentration, precision and time."), translate("About", "<p>Learn the keyboard shortcuts! Laborejo is designed to work with the keyboard alone and with midi instruments for full speed.</p>Everytime you grab your mouse you loose concentration, precision and time."),
translate("About", "<p>Spread/shrink the space between notes with Ctrl+Shift+Mousewheel or Ctrl+Shift with Plus and Minus.</p>"), translate("About", "<p>Spread/shrink the space between notes with Ctrl+Shift+Mousewheel or Ctrl+Shift with Plus and Minus.</p>"),
@ -74,19 +74,19 @@ class MainWindow(TemplateMainWindow):
translate("About", "<p>There is no key-rebinding except numpad-shortcuts.</p>"), translate("About", "<p>There is no key-rebinding except numpad-shortcuts.</p>"),
translate("About", "<p>Hidden tracks still output sound.</p>"), translate("About", "<p>Hidden tracks still output sound.</p>"),
translate("About", "<p>Non-audible tracks still output instrument changes and CCs so that they can be switched on again in the middle of playback.</p>"), translate("About", "<p>Non-audible tracks still output instrument changes and CCs so that they can be switched on again in the middle of playback.</p>"),
] + About.didYouKnow ] + About.didYouKnow
super().__init__() super().__init__()
#New menu entries and template-menu overrides #New menu entries and template-menu overrides
self.menu.addMenuEntry("menuDebug", "actionRedrawAllTracks", "Redraw all Tracks") self.menu.addMenuEntry("menuDebug", "actionRedrawAllTracks", "Redraw all Tracks")
self.menu.connectMenuEntry("actionSave", api.save) self.menu.connectMenuEntry("actionSave", api.save)
self.menu.hideSubmenu("menuFile") self.menu.hideSubmenu("menuFile")
self.menu.hideSubmenu("menuGeneric") self.menu.hideSubmenu("menuGeneric")
api.callbacks.setCursor.append(self.updateStatusBar) #returns a dict. This get's called after loading the file so the status bar is filled on self.show api.callbacks.setCursor.append(self.updateStatusBar) #returns a dict. This get's called after loading the file so the status bar is filled on self.show
#Create the Main Widgets in the Stacked Widget #Create the Main Widgets in the Stacked Widget
self.scoreView = ScoreView(self) self.scoreView = ScoreView(self)
self.ui.mainStackWidget.addWidget(self.scoreView) self.ui.mainStackWidget.addWidget(self.scoreView)
@ -99,8 +99,8 @@ class MainWindow(TemplateMainWindow):
self.ui.actionData_Editor.setChecked(False) self.ui.actionData_Editor.setChecked(False)
self.ui.mainStackWidget.addWidget(self.trackEditor) self.ui.mainStackWidget.addWidget(self.trackEditor)
#Bind shortcuts to actions (as init effect) #Bind shortcuts to actions (as init effect)
#TODO: Integrate better into template menu system. #TODO: Integrate better into template menu system.
self.menuActionDatabase = MenuActionDatabase(self) #The menu needs to be started before api.startEngine self.menuActionDatabase = MenuActionDatabase(self) #The menu needs to be started before api.startEngine
#Make toolbars unclosable #Make toolbars unclosable
@ -111,34 +111,34 @@ class MainWindow(TemplateMainWindow):
#The statusbar is intended for tooltips. To make it permanent we add our own widget #The statusbar is intended for tooltips. To make it permanent we add our own widget
self.statusLabel = QtWidgets.QLabel() self.statusLabel = QtWidgets.QLabel()
self.statusBar().insertPermanentWidget(0, self.statusLabel) self.statusBar().insertPermanentWidget(0, self.statusLabel)
self.scoreView.setFocus() #So the user can start typing from moment 0. self.scoreView.setFocus() #So the user can start typing from moment 0.
self.start() #Inherited from template main window #This shows the GUI, or not, depends on the NSM gui save setting. We need to call that after the menu, otherwise the about dialog will block and then we get new menu entries, which looks strange. self.start() #Inherited from template main window #This shows the GUI, or not, depends on the NSM gui save setting. We need to call that after the menu, otherwise the about dialog will block and then we get new menu entries, which looks strange.
stepMidiInput.start() #imported directly. Handles everything else internally, we just need to start it after the engine somehow. Which is here. stepMidiInput.start() #imported directly. Handles everything else internally, we just need to start it after the engine somehow. Which is here.
#Populate the left toolbar. The upper toolbar is created in menu.py #Populate the left toolbar. The upper toolbar is created in menu.py
self.ui.leftToolBar.addWidget(LeftToolBarPrevailingDuration(self)) #needs stepmidiinput started self.ui.leftToolBar.addWidget(LeftToolBarPrevailingDuration(self)) #needs stepmidiinput started
#Now all tracks and items from a loaded backend-file are created. We can setup the initial editMode and viewPort. #Now all tracks and items from a loaded backend-file are created. We can setup the initial editMode and viewPort.
self.scoreView.updateMode() #hide CCs at program start and other stuff self.scoreView.updateMode() #hide CCs at program start and other stuff
self.scoreView.scoreScene.grid.redrawTickGrid() #Init the grid only after everything got loaded and drawn to prevent a gap in the display. #TODO: which might be a bug. but this here works fine. self.scoreView.scoreScene.grid.redrawTickGrid() #Init the grid only after everything got loaded and drawn to prevent a gap in the display. #TODO: which might be a bug. but this here works fine.
#There is so much going on in the engine, we never reach a save status on load. #There is so much going on in the engine, we never reach a save status on load.
#Here is the crowbar-method. #Here is the crowbar-method.
self.nsmClient.announceSaveStatus(isClean = True) self.nsmClient.announceSaveStatus(isClean = True)
def zoom(self, scaleFactor:float): def zoom(self, scaleFactor:float):
"""Scale factor is absolute""" """Scale factor is absolute"""
self.scoreView.zoom(scaleFactor) self.scoreView.zoom(scaleFactor)
def stretchXCoordinates(self, factor:float): def stretchXCoordinates(self, factor:float):
self.scoreView.stretchXCoordinates(factor) self.scoreView.stretchXCoordinates(factor)
def updateStatusBar(self, exportCursorDict): def updateStatusBar(self, exportCursorDict):
"""Every cursor movement updates the statusBar message""" """Every cursor movement updates the statusBar message"""
c = exportCursorDict c = exportCursorDict
try: try:
i = c["item"] i = c["item"]
except: except:
print (c) print (c)
@ -182,7 +182,7 @@ class LeftToolBarPrevailingDuration(QtWidgets.QLabel):
api.callbacks.prevailingBaseDurationChanged.append(self.changed) api.callbacks.prevailingBaseDurationChanged.append(self.changed)
def makeText(self, baseDuration): def makeText(self, baseDuration):
if not stepMidiInput.midiInIsActive: if not stepMidiInput.midiInIsActive:
return "" return ""
labelText = "<font size=6>" labelText = "<font size=6>"

26
qtgui/menu.py

@ -113,7 +113,7 @@ class MenuActionDatabase(object):
def __init__(self, mainWindow): def __init__(self, mainWindow):
self.mainWindow = mainWindow self.mainWindow = mainWindow
self.modalKeys = ModalKeys() self.modalKeys = ModalKeys()
modes = QtWidgets.QActionGroup(self.mainWindow) modes = QtWidgets.QActionGroup(self.mainWindow)
modes.addAction(self.mainWindow.ui.actionNotation_Mode) modes.addAction(self.mainWindow.ui.actionNotation_Mode)
@ -275,7 +275,7 @@ class MenuActionDatabase(object):
self.mainWindow.ui.actionDuplicateItem : api.duplicate, self.mainWindow.ui.actionDuplicateItem : api.duplicate,
self.mainWindow.ui.actionUndo : api.undo, self.mainWindow.ui.actionUndo : api.undo,
self.mainWindow.ui.actionRedo : api.redo, self.mainWindow.ui.actionRedo : api.redo,
self.mainWindow.ui.actionRedrawAllTracks : api.updateCallbackAllTracks, self.mainWindow.ui.actionRedrawAllTracks : api.updateCallbackAllTracks,
#Toolbox #Toolbox
@ -293,15 +293,15 @@ class MenuActionDatabase(object):
self.mainWindow.ui.actionReverse: api.reorderReverse, self.mainWindow.ui.actionReverse: api.reorderReverse,
self.mainWindow.ui.actionAscending: api.reorderAscending, self.mainWindow.ui.actionAscending: api.reorderAscending,
self.mainWindow.ui.actionDescending: api.reoderdDescending, self.mainWindow.ui.actionDescending: api.reoderdDescending,
#Midi #Midi
self.mainWindow.ui.actionInstrument_Change: SecondaryProgramChangeMenu(self.mainWindow), #no lambda for submenus. They get created here once and have a __call__ option that executes them. There is no internal state in these menus. self.mainWindow.ui.actionInstrument_Change: SecondaryProgramChangeMenu(self.mainWindow), #no lambda for submenus. They get created here once and have a __call__ option that executes them. There is no internal state in these menus.
self.mainWindow.ui.actionChannel_Change: SecondaryChannelChangeMenu(self.mainWindow), #no lambda for submenus. They get created here once and have a __call__ option that executes them. There is no internal state in these menus. self.mainWindow.ui.actionChannel_Change: SecondaryChannelChangeMenu(self.mainWindow), #no lambda for submenus. They get created here once and have a __call__ option that executes them. There is no internal state in these menus.
#Lilypond #Lilypond
#Print and Export is in self.actions #Print and Export is in self.actions
self.mainWindow.ui.actionLyBarline: ChooseOne(self.mainWindow, translate("menu", "Choose a Barline"), api.getLilypondBarlineList()), self.mainWindow.ui.actionLyBarline: ChooseOne(self.mainWindow, translate("menu", "Choose a Barline"), api.getLilypondBarlineList()),
self.mainWindow.ui.actionLyRepeat: ChooseOne(self.mainWindow, translate("menu", "Choose a Repeat"), api.getLilypondRepeatList()), self.mainWindow.ui.actionLyRepeat: ChooseOne(self.mainWindow, translate("menu", "Choose a Repeat"), api.getLilypondRepeatList()),
self.mainWindow.ui.actionLyFree_Instruction: lambda: forwardText(self.mainWindow, translate("menu", "Enter Instruction"), api.lilypondText), self.mainWindow.ui.actionLyFree_Instruction: lambda: forwardText(self.mainWindow, translate("menu", "Enter Instruction"), api.lilypondText),
} }
@ -434,7 +434,7 @@ class MenuActionDatabase(object):
if boolean: if boolean:
#Switch off midi input #Switch off midi input
if stepMidiInput.midiInIsActive: if stepMidiInput.midiInIsActive:
self.rememberMidi = stepMidiInput.midiInIsActive self.rememberMidi = stepMidiInput.midiInIsActive
stepMidiInput.toggleMidiIn() stepMidiInput.toggleMidiIn()
assert not stepMidiInput.midiInIsActive assert not stepMidiInput.midiInIsActive
self.mainWindow.ui.actionPrevailingRest.setEnabled(stepMidiInput.midiInIsActive) self.mainWindow.ui.actionPrevailingRest.setEnabled(stepMidiInput.midiInIsActive)
@ -477,14 +477,14 @@ class MenuActionDatabase(object):
self.mainWindow.ui.actionRedo.setText(translate("menu", "Redo")) self.mainWindow.ui.actionRedo.setText(translate("menu", "Redo"))
self.mainWindow.ui.actionRedo.setEnabled(False) self.mainWindow.ui.actionRedo.setEnabled(False)
def exportLy(self): def exportLy(self):
lastExportDirectory = api.session.guiSharedDataToSave["lastExportDirectory"] if "lastExportDirectory" in api.session.guiSharedDataToSave else str(Path.home()) lastExportDirectory = api.session.guiSharedDataToSave["lastExportDirectory"] if "lastExportDirectory" in api.session.guiSharedDataToSave else str(Path.home())
filename = QtWidgets.QFileDialog.getSaveFileName(self.mainWindow, translate("menu", "Export Lilypond Source File"), lastExportDirectory, translate("menu", "Lilypond Source (*.ly)")) filename = QtWidgets.QFileDialog.getSaveFileName(self.mainWindow, translate("menu", "Export Lilypond Source File"), lastExportDirectory, translate("menu", "Lilypond Source (*.ly)"))
filename = filename[0] #(path, filter) filename = filename[0] #(path, filter)
if filename: if filename:
if not os.path.splitext(filename)[1]: #no file extension given? if not os.path.splitext(filename)[1]: #no file extension given?
filename = filename + ".ly" filename = filename + ".ly"
api.session.guiSharedDataToSave["lastExportDirectory"] = os.path.dirname(filename) api.session.guiSharedDataToSave["lastExportDirectory"] = os.path.dirname(filename)
api.exportLilypond(filename) api.exportLilypond(filename)
class ToolBarCCType(QtWidgets.QSpinBox): class ToolBarCCType(QtWidgets.QSpinBox):
@ -556,7 +556,7 @@ class ToolBarMetronome(QtWidgets.QCheckBox):
return False return False
def updateFromCallback(self, exportDict): def updateFromCallback(self, exportDict):
"""Gets the metronome dict""" """Gets the metronome dict"""
self.blockSignals(True) self.blockSignals(True)
self.setStatus() self.setStatus()
assert self.isChecked() == exportDict["enabled"], (self.isChecked(), exportDict["enabled"]) assert self.isChecked() == exportDict["enabled"], (self.isChecked(), exportDict["enabled"])
@ -576,8 +576,8 @@ class ToolBarPlaybackSpeed(QtWidgets.QDoubleSpinBox):
self.setSingleStep(0.1) self.setSingleStep(0.1)
self.setPrefix(translate("menu", "Tempo ×")) #yes, this is the unicode multiplication sign × and not an x self.setPrefix(translate("menu", "Tempo ×")) #yes, this is the unicode multiplication sign × and not an x
api.callbacks.tempoScalingChanged.append(self.updateFromCallback) api.callbacks.tempoScalingChanged.append(self.updateFromCallback)
self.valueChanged.connect(self.changed) self.valueChanged.connect(self.changed)
self.setLineEdit(ToolBarPlaybackSpeed.CustomLineEdit()) self.setLineEdit(ToolBarPlaybackSpeed.CustomLineEdit())
class CustomLineEdit(QtWidgets.QLineEdit): class CustomLineEdit(QtWidgets.QLineEdit):
def mousePressEvent(self, event): def mousePressEvent(self, event):
@ -601,5 +601,5 @@ class ToolBarPlaybackSpeed(QtWidgets.QDoubleSpinBox):
self.setValue(newValue) self.setValue(newValue)
self.blockSignals(False) self.blockSignals(False)
def changed(self): def changed(self):
api.changeTempoScaling(self.value()) api.changeTempoScaling(self.value())

20
qtgui/musicstructures.py

@ -43,6 +43,8 @@ from .submenus import BlockPropertiesEdit
cosmeticPen = QtGui.QPen() cosmeticPen = QtGui.QPen()
cosmeticPen.setCosmetic(True) 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): class GuiBlockHandle(QtWidgets.QGraphicsRectItem):
"""A simplified version of a Block. Since we don't use blocks in the GUI, only in the backend """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. we still need them sometimes as macro strutures, where we don't care about the content.
@ -54,7 +56,7 @@ class GuiBlockHandle(QtWidgets.QGraphicsRectItem):
""" """
def __init__(self, parent, staticExportItem, x, y, w, h): def __init__(self, parent, staticExportItem, x, y, w, h):
super().__init__(x, y, w, h) super().__init__(x, y, w, h)
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.ItemHasNoContents, True) #only child items. Without this we get notImplementedError: QGraphicsItem.paint() is abstract and must be overridden
self.setFlag(QtWidgets.QGraphicsItem.ItemContainsChildrenInShape, True) self.setFlag(QtWidgets.QGraphicsItem.ItemContainsChildrenInShape, True)
self.parent = parent #GuiTrack instance self.parent = parent #GuiTrack instance
self.color = None #inserted by the creating function in GuiTrack self.color = None #inserted by the creating function in GuiTrack
@ -93,6 +95,8 @@ class GuiBlockHandle(QtWidgets.QGraphicsRectItem):
self.startLabel = QtWidgets.QGraphicsSimpleTextItem("") self.startLabel = QtWidgets.QGraphicsSimpleTextItem("")
self.endLabel = QtWidgets.QGraphicsSimpleTextItem("") self.endLabel = QtWidgets.QGraphicsSimpleTextItem("")
def boundingRect(self, *args): return oneRectToReturnThemAll
def stretchXCoordinates(self, factor): def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis. """Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates. Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
@ -188,9 +192,9 @@ class GuiTrack(QtWidgets.QGraphicsItem):
def __init__(self, parentScore, staticExportItem): def __init__(self, parentScore, staticExportItem):
super().__init__() 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.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) self.setFlag(QtWidgets.QGraphicsItem.ItemContainsChildrenInShape, True)
self.parentScore = parentScore self.parentScore = parentScore
self.staticExportItem = staticExportItem #This is not the notes but the track meta data. The notes are called staticRepresentationList self.staticExportItem = staticExportItem #This is not the notes but the track meta data. The notes are called staticRepresentationList
self.items = [] #this is used for stretching and processing of the current items. scene clear is done diffently. See self.createGraphicItemsFromData self.items = [] #this is used for stretching and processing of the current items. scene clear is done diffently. See self.createGraphicItemsFromData
@ -221,6 +225,8 @@ class GuiTrack(QtWidgets.QGraphicsItem):
#self.secondStageInitNowThatWeHaveAScene gets called by the ScoreScene.redraw(), where new tracks get created. After it was inserted into the scene. #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): class NameGraphic(QtWidgets.QGraphicsSimpleTextItem):
def __init__(self, text, parent): def __init__(self, text, parent):
super().__init__(text) super().__init__(text)
@ -237,6 +243,8 @@ class GuiTrack(QtWidgets.QGraphicsItem):
if result[1]: 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 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): def contextMenuEvent(self, event):
listOfLabelsAndFunctions = [ (translate("musicstructures", "edit name"), self._editName), ] listOfLabelsAndFunctions = [ (translate("musicstructures", "edit name"), self._editName), ]
callContextMenu(listOfLabelsAndFunctions) callContextMenu(listOfLabelsAndFunctions)
@ -392,13 +400,15 @@ class GuiTrack(QtWidgets.QGraphicsItem):
class TrackAnchor(QtWidgets.QGraphicsItem): class TrackAnchor(QtWidgets.QGraphicsItem):
"""Handling all items as individuals when deleting a track to redraw it is too much. """Handling all items as individuals when deleting a track to redraw it is too much.
Better let Qt handle it all at once.""" Better let Qt handle it all at once."""
def __init__(self, parent): def __init__(self, parent):
super().__init__() super().__init__()
self.parent = parent 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.ItemHasNoContents, True) #only child items. Without this we get notImplementedError: QGraphicsItem.paint() is abstract and must be overridden
self.setFlag(QtWidgets.QGraphicsItem.ItemContainsChildrenInShape, True) self.setFlag(QtWidgets.QGraphicsItem.ItemContainsChildrenInShape, True)
def boundingRect(self, *args): return oneRectToReturnThemAll
def createGraphicItemsFromData(self, staticRepresentationList): def createGraphicItemsFromData(self, staticRepresentationList):
"""Create staff objects including simple barlines""" """Create staff objects including simple barlines"""

45
qtgui/scorescene.py

@ -43,8 +43,8 @@ class GuiScore(QtWidgets.QGraphicsScene):
def __init__(self, parentView): def __init__(self, parentView):
super().__init__() super().__init__()
self.parentView = parentView self.parentView = parentView
self.setItemIndexMethod(QtWidgets.QGraphicsScene.NoIndex) self.setItemIndexMethod(QtWidgets.QGraphicsScene.NoIndex)
self.tracks = {} #trackId:guiTrack, #if we don't save the instances here in Python space Qt will loose them and they will not be displayed without any error message. self.tracks = {} #trackId:guiTrack, #if we don't save the instances here in Python space Qt will loose them and they will not be displayed without any error message.
@ -69,7 +69,7 @@ class GuiScore(QtWidgets.QGraphicsScene):
self.backColor.setNamedColor("#fdfdff") self.backColor.setNamedColor("#fdfdff")
self.setBackgroundBrush(self.backColor) self.setBackgroundBrush(self.backColor)
self.grid = GuiGrid(parent=self) self.grid = Grid(parentScene=self)
self.addItem(self.grid) self.addItem(self.grid)
self.grid.setPos(0, -20 * constantsAndConfigs.stafflineGap) #this is more calculation than simply using self.yStart, and might require manual adjustment in the future, but at least it guarantees the grid matches the staffline positions self.grid.setPos(0, -20 * constantsAndConfigs.stafflineGap) #this is more calculation than simply using self.yStart, and might require manual adjustment in the future, but at least it guarantees the grid matches the staffline positions
self.grid.setZValue(-50) self.grid.setZValue(-50)
@ -129,9 +129,9 @@ class GuiScore(QtWidgets.QGraphicsScene):
#hidden track. #hidden track.
def updateGraphTrackCC(self, trackId, ccNumber, staticRepresentationList): def updateGraphTrackCC(self, trackId, ccNumber, staticRepresentationList):
"""TrackId is a real notation track which has a dict of CCs""" """TrackId is a real notation track which has a dict of CCs"""
if trackId in self.tracks: if trackId in self.tracks:
track = self.tracks[trackId] track = self.tracks[trackId]
ccPath = track.ccPaths[ccNumber] ccPath = track.ccPaths[ccNumber]
ccPath.createGraphicItemsFromData(staticRepresentationList) ccPath.createGraphicItemsFromData(staticRepresentationList)
@ -170,8 +170,8 @@ class GuiScore(QtWidgets.QGraphicsScene):
for cc in guiCCs: for cc in guiCCs:
self.removeWhenIdle(self.tracks[trackId].ccPaths[cc]) self.removeWhenIdle(self.tracks[trackId].ccPaths[cc])
del self.tracks[trackId].ccPaths[cc] del self.tracks[trackId].ccPaths[cc]
def redraw(self, listOfStaticTrackRepresentations): def redraw(self, listOfStaticTrackRepresentations):
"""The order of guiTracks depends on the backend index. """The order of guiTracks depends on the backend index.
This way it is a no-brainer, we don't need to maintain our own This way it is a no-brainer, we don't need to maintain our own
@ -182,7 +182,7 @@ class GuiScore(QtWidgets.QGraphicsScene):
through self.updateTrack which has its own api-callback through self.updateTrack which has its own api-callback
called by callbacksDatabase.tracksChanged""" called by callbacksDatabase.tracksChanged"""
for track in self.tracks.values(): for track in self.tracks.values():
track.hide() track.hide()
@ -278,22 +278,31 @@ class GuiScore(QtWidgets.QGraphicsScene):
return None return None
def wheelEvent(self, event): def notTrueAnymore_wheelEvent(self, event):
"""We MUST handle the event somehow. Otherwise background grid items will block the views(!) """
This docstring was either wrong in the first place or something changed in my code.
However, we do not need to eat wheelEvent here anymore. On the contrary: It will block
items, like the tempoItem from receiving wheelEvents.
The commented out if/else for item detection also has a chance to work, but we don't need
to test for that at all. Standard Qt-behavoiour is fine.
What follows is the old docstring, for legacy documentation reasons:
We MUST handle the event somehow. Otherwise background grid items will block the views(!)
wheel scrolling, even when disabled and setting accepting mouse events to none. wheel scrolling, even when disabled and setting accepting mouse events to none.
This is a qt bug that won't be fixed because API stability over correctnes (according to the This is a qt bug that won't be fixed because API stability over correctnes (according to the
bugtracker. bugtracker.
Contrary to other parts of the system event.ignore and accept actually mean something. Contrary to other parts of the system event.ignore and accept actually mean something.
ignore will tell the caller to use the event itself, e.g. scroll. ignore will tell the caller to use the event itself, e.g. scroll.
This event gets the wheel BEFORE the main window (zoom) This event gets the wheel BEFORE the main window (zoom)
""" """
#item = self.itemAt(event.scenePos(), self.parentView.transform()) #item = self.itemAt(event.scenePos(), self.parentView.transform())
#if type(item) is items.Note: #if type(item) is items.Note:
# super().wheelEvent(event) #send to child item #super().wheelEvent(event) #send to child item
#else: #else:
event.ignore() #so the view scrolls or we zoom event.ignore() #so the view scrolls or we zoom
def stretchXCoordinates(self, factor): def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis. """Reposition the items on the X axis.

16
qtgui/scoreview.py

@ -36,8 +36,8 @@ import engine.api as api
class ScoreView(QtWidgets.QGraphicsView): class ScoreView(QtWidgets.QGraphicsView):
def __init__(self, mainWindow): def __init__(self, mainWindow):
super().__init__() super().__init__()
self.mainWindow = mainWindow self.mainWindow = mainWindow
self.scoreScene = GuiScore(parentView=self) self.scoreScene = GuiScore(parentView=self)
self.setScene(self.scoreScene) self.setScene(self.scoreScene)
@ -83,9 +83,9 @@ class ScoreView(QtWidgets.QGraphicsView):
self.setStyleSheet(style) self.setStyleSheet(style)
def wheelEvent(self, event): def wheelEvent(self, event):
if QtWidgets.QApplication.keyboardModifiers() in (QtCore.Qt.ControlModifier, QtCore.Qt.ControlModifier|QtCore.Qt.ShiftModifier): #a workaround for a qt bug. see score.wheelEvent docstring. if QtWidgets.QApplication.keyboardModifiers() in (QtCore.Qt.ControlModifier, QtCore.Qt.ControlModifier|QtCore.Qt.ShiftModifier): #a workaround for a qt bug. see score.wheelEvent docstring.
event.ignore() #do not send to scene, but tell the mainWindow to use it. event.ignore() #do not send to scene, but tell the mainWindow to use it.
else: else:
super().wheelEvent(event) #send to scene super().wheelEvent(event) #send to scene
def centerOnCursor(self, cursorExportObject): def centerOnCursor(self, cursorExportObject):
@ -101,10 +101,10 @@ class ScoreView(QtWidgets.QGraphicsView):
def stretchXCoordinates(self, factor): def stretchXCoordinates(self, factor):
self.scoreScene.stretchXCoordinates(factor) self.scoreScene.stretchXCoordinates(factor)
self.centerOnCursor(None) self.centerOnCursor(None)
def zoom(self, scaleFactor:float): def zoom(self, scaleFactor:float):
"""Scale factor is absolute""" """Scale factor is absolute"""
self.resetTransform() self.resetTransform()
self.scale(scaleFactor, scaleFactor) self.scale(scaleFactor, scaleFactor)
def toggleNoteheadsRectangles(self): def toggleNoteheadsRectangles(self):
@ -144,7 +144,7 @@ class ScoreView(QtWidgets.QGraphicsView):
raise ValueError("Edit Mode unknown") raise ValueError("Edit Mode unknown")
def resizeEvent(self, event): def resizeEvent(self, event):
self.scoreScene.grid.reactToresizeEventOrZoom() #self.scoreScene.grid.reactToresizeEventOrZoom()
super().resizeEvent(event) super().resizeEvent(event)
def changeGridRhythm(self): def changeGridRhythm(self):

28
qtgui/submenus.py

@ -31,7 +31,7 @@ translate = QtCore.QCoreApplication.translate
#Template #Template
import template.engine.pitch as pitch import template.engine.pitch as pitch
from template.qtgui.helper import QHLine from template.qtgui.helper import QHLine
from template.qtgui.submenus import * from template.qtgui.submenus import *
#Our own files #Our own files
import engine.api as api import engine.api as api
@ -380,7 +380,7 @@ class TransposeMenu(Submenu):
self.fromNote = QtWidgets.QComboBox() self.fromNote = QtWidgets.QComboBox()
self.fromNote.addItems(pitch.sortedNoteNameList) self.fromNote.addItems(pitch.sortedNoteNameList)
self.fromNote.setCurrentIndex(pitch.sortedNoteNameList.index("c'")) self.fromNote.setCurrentIndex(pitch.sortedNoteNameList.index("c'"))
self.layout.addRow("from", self.fromNote) self.layout.addRow("from", self.fromNote)
@ -417,11 +417,11 @@ class SecondaryProperties(Submenu):
importantKeys = ("title", "composer", "instrument", "copyright") importantKeys = ("title", "composer", "instrument", "copyright")
#Draw important metadata widgets first #Draw important metadata widgets first
for k in importantKeys: for k in importantKeys:
self.layout.addRow(k.title(), self.widgets[k]) self.layout.addRow(k.title(), self.widgets[k])
self.layout.addRow(QHLine()) self.layout.addRow(QHLine())
#Then the rest in alphabetical order #Then the rest in alphabetical order
for key, widget in sorted(self.widgets.items()): for key, widget in sorted(self.widgets.items()):
if not key in importantKeys: if not key in importantKeys:
@ -452,7 +452,7 @@ class SecondaryProperties(Submenu):
elif typ == QtWidgets.QSpinBox or typ == QtWidgets.QDoubleSpinBox: elif typ == QtWidgets.QSpinBox or typ == QtWidgets.QDoubleSpinBox:
return widget.value() return widget.value()
def process(self): def process(self):
api.setMetadata({key:self.getValueFromWidget(widget) for key, widget in self.widgets.items()}) api.setMetadata({key:self.getValueFromWidget(widget) for key, widget in self.widgets.items()})
self.done(True) self.done(True)
#Instance gets killed afterwards. No need to save the new values. #Instance gets killed afterwards. No need to save the new values.
@ -471,7 +471,7 @@ class SecondaryProgramChangeMenu(Submenu):
self.msb = QtWidgets.QSpinBox() self.msb = QtWidgets.QSpinBox()
self.msb.setValue(type(self).lastMsbValue) self.msb.setValue(type(self).lastMsbValue)
self.lsb = QtWidgets.QSpinBox() self.lsb = QtWidgets.QSpinBox()
self.lsb.setValue(type(self).lastLsbValue) self.lsb.setValue(type(self).lastLsbValue)
self.shortInstrumentName = QtWidgets.QLineEdit() self.shortInstrumentName = QtWidgets.QLineEdit()
for label, spinbox in ((translate("submenus", "Program"), self.program), (translate("submenus", "Bank MSB"), self.msb), (translate("submenus", "Bank LSB"), self.lsb)): for label, spinbox in ((translate("submenus", "Program"), self.program), (translate("submenus", "Bank MSB"), self.msb), (translate("submenus", "Bank LSB"), self.lsb)):
@ -479,7 +479,7 @@ class SecondaryProgramChangeMenu(Submenu):
spinbox.setMaximum(127) spinbox.setMaximum(127)
spinbox.setSingleStep(1) spinbox.setSingleStep(1)
self.layout.addRow(label, spinbox) self.layout.addRow(label, spinbox)
self.layout.addRow(translate("submenus", "Short Name"), self.shortInstrumentName) self.layout.addRow(translate("submenus", "Short Name"), self.shortInstrumentName)
self.insert = QtWidgets.QPushButton(translate("submenus", "Insert")) self.insert = QtWidgets.QPushButton(translate("submenus", "Insert"))
@ -544,8 +544,8 @@ class GridRhytmEdit(Submenu):
def process(self): def process(self):
constantsAndConfigs.gridRhythm = self.duration.value() constantsAndConfigs.gridRhythm = self.duration.value()
constantsAndConfigs.gridOpacity = self.opacity.value() / 100 constantsAndConfigs.gridOpacity = self.opacity.value() / 100
api.session.guiSharedDataToSave["grid_opacity"] = constantsAndConfigs.gridOpacity api.session.guiSharedDataToSave["grid_opacity"] = constantsAndConfigs.gridOpacity
api.session.guiSharedDataToSave["grid_rhythm"] = constantsAndConfigs.gridRhythm api.session.guiSharedDataToSave["grid_rhythm"] = constantsAndConfigs.gridRhythm
self.mainWindow.scoreView.scoreScene.grid.redrawTickGrid() #opacity was already set live, but finally it will be used here again. self.mainWindow.scoreView.scoreScene.grid.redrawTickGrid() #opacity was already set live, but finally it will be used here again.
self.done(True) self.done(True)
@ -572,15 +572,15 @@ def pedalNoteChooser(mainWindow):
if v == rhythmString[0]: if v == rhythmString[0]:
api.pedalNotes(baseDuration) api.pedalNotes(baseDuration)
def forwardText(mainWindow, title, function): def forwardText(mainWindow, title, function):
text, status = QtWidgets.QInputDialog.getText(mainWindow, title, title) text, status = QtWidgets.QInputDialog.getText(mainWindow, title, title)
if status: if status:
function(text) function(text)

6
qtgui/trackEditor.py

@ -59,7 +59,7 @@ class TrackWidget(QtWidgets.QGroupBox):
self.ui.nameLineEdit.editingFinished.connect(self.nameChanged) #only user changes, not through setText() etc. self.ui.nameLineEdit.editingFinished.connect(self.nameChanged) #only user changes, not through setText() etc.
self.ui.deleteButton.clicked.connect(lambda: api.deleteTrack(self.trackExportObject["id"])) self.ui.deleteButton.clicked.connect(lambda: api.deleteTrack(self.trackExportObject["id"]))
self.ui.midiChannelSpinBox.valueChanged.connect(self.dataChanged) self.ui.midiChannelSpinBox.valueChanged.connect(self.dataChanged)
self.ui.midiProgramSpinBox.valueChanged.connect(self.dataChanged) self.ui.midiProgramSpinBox.valueChanged.connect(self.dataChanged)
self.ui.midiBankMsbSpinBox.valueChanged.connect(self.dataChanged) self.ui.midiBankMsbSpinBox.valueChanged.connect(self.dataChanged)
self.ui.midiBankLsbSpinBox.valueChanged.connect(self.dataChanged) self.ui.midiBankLsbSpinBox.valueChanged.connect(self.dataChanged)
@ -138,7 +138,7 @@ class TrackWidget(QtWidgets.QGroupBox):
api.unhideTrack(self.trackExportObject["id"]) api.unhideTrack(self.trackExportObject["id"])
else: else:
api.hideTrack(self.trackExportObject["id"]) api.hideTrack(self.trackExportObject["id"])
def audibleToggled(self, signal): def audibleToggled(self, signal):
assert signal == bool(self.ui.audibleCheckbox.checkState()) assert signal == bool(self.ui.audibleCheckbox.checkState())
api.trackAudible(self.trackExportObject["id"], signal) api.trackAudible(self.trackExportObject["id"], signal)
@ -299,7 +299,7 @@ class TrackWidget(QtWidgets.QGroupBox):
self.ui.doubleTrackCheckbox.setChecked(trackExportObject["double"]) self.ui.doubleTrackCheckbox.setChecked(trackExportObject["double"])
self.ui.audibleCheckbox.setChecked(trackExportObject["audible"]) self.ui.audibleCheckbox.setChecked(trackExportObject["audible"])
for i in range(0,16): #without 16 for i in range(0,16): #without 16
#Engine from 0 to 15, GUI from 1 to 16. #Engine from 0 to 15, GUI from 1 to 16.
self.ccChannels[i+1].setChecked(i in trackExportObject["ccChannels"]) #a checkbox widget. self.ccChannels[i+1].setChecked(i in trackExportObject["ccChannels"]) #a checkbox widget.

Loading…
Cancel
Save