Browse Source

Add initial signature region in the GUI and in the engine for default sigs. Required graphical clef work and adjustments of the gui keysig

master
Nils 2 years ago
parent
commit
8106dcf077
  1. 11
      engine/api.py
  2. 7
      engine/items.py
  3. 31
      engine/track.py
  4. 14
      qtgui/designer/trackWidget.py
  5. 21
      qtgui/designer/trackWidget.ui
  6. 29
      qtgui/items.py
  7. 15
      qtgui/musicstructures.py
  8. 13969
      qtgui/resources.py
  9. 1
      qtgui/resources/resources.qrc
  10. 64
      qtgui/resources/svg/clefBass^8.svg
  11. 6
      qtgui/scorescene.py
  12. 13
      qtgui/trackEditor.py

11
engine/api.py

@ -736,12 +736,15 @@ def setTrackSettings(trId, dictionary):
break break
if not clean: if not clean:
trackObject.initialClefKeyword = dictionary["initialClefKeyword"]
trackObject.initialMidiChannel = dictionary["initialMidiChannel"] trackObject.initialMidiChannel = dictionary["initialMidiChannel"]
trackObject.initialMidiBankMsb = dictionary["initialMidiBankMsb"] trackObject.initialMidiBankMsb = dictionary["initialMidiBankMsb"]
trackObject.initialMidiBankLsb = dictionary["initialMidiBankLsb"] trackObject.initialMidiBankLsb = dictionary["initialMidiBankLsb"]
trackObject.initialMidiProgram = dictionary["initialMidiProgram"] trackObject.initialMidiProgram = dictionary["initialMidiProgram"]
trackObject.ccChannels = dictionary["ccChannels"] trackObject.ccChannels = dictionary["ccChannels"]
trackObject.midiTranspose = dictionary["midiTranspose"] trackObject.midiTranspose = dictionary["midiTranspose"]
trackObject.durationSettingsSignature.defaultOn = dictionary["duration.defaultOn"] trackObject.durationSettingsSignature.defaultOn = dictionary["duration.defaultOn"]
trackObject.durationSettingsSignature.defaultOff = dictionary["duration.defaultOff"] trackObject.durationSettingsSignature.defaultOff = dictionary["duration.defaultOff"]
trackObject.durationSettingsSignature.staccatoOn = dictionary["duration.staccatoOn"] trackObject.durationSettingsSignature.staccatoOn = dictionary["duration.staccatoOn"]
@ -771,6 +774,8 @@ def setTrackSettings(trId, dictionary):
trackObject.dynamicSettingsSignature.dynamics["sf"] = dictionary["dynamics.sf"] trackObject.dynamicSettingsSignature.dynamics["sf"] = dictionary["dynamics.sf"]
trackObject.dynamicSettingsSignature.dynamics["sff"] = dictionary["dynamics.sff"] trackObject.dynamicSettingsSignature.dynamics["sff"] = dictionary["dynamics.sff"]
session.history.register(lambda trId=trId, previousSettings=previousSettings: setTrackSettings(trId, previousSettings), descriptionString = "change track settings") session.history.register(lambda trId=trId, previousSettings=previousSettings: setTrackSettings(trId, previousSettings), descriptionString = "change track settings")
callbacks._tracksChanged() callbacks._tracksChanged()
callbacks._updateSingleTrackAllCC(trId) callbacks._updateSingleTrackAllCC(trId)
@ -1819,6 +1824,12 @@ def insertMultiMeasureRest(numberOfMeasures):
insertItem(items.MultiMeasureRest(numberOfMeasures)) insertItem(items.MultiMeasureRest(numberOfMeasures))
#Clefs #Clefs
def getPossibleClefKeywords():
"""GUI can use this to fill drop down lists etc.
Not sorted, but will use the new python sorted-as-inserted dict feature,
so a little bit of consistency is probable."""
return list(items.Clef.inComparisonToTrebleClef.keys())
def insertClef(clefString): def insertClef(clefString):
clef = items.Clef(clefString) clef = items.Clef(clefString)
insertItem(clef) insertItem(clef)

7
engine/items.py

@ -2284,7 +2284,9 @@ class Clef(Item):
so seeing the clef hints at what voice it is. Therefore we can use a clef a basis for random so seeing the clef hints at what voice it is. Therefore we can use a clef a basis for random
note generation or even range checking and warnings. """ note generation or even range checking and warnings. """
offset = { offset = {
#This is for notes, not for the clef!
#the offset of the middle line. Basically: After the clef, how many diatonic steps (gaps/line) is the middle line away from b'/h' (1720)? #the offset of the middle line. Basically: After the clef, how many diatonic steps (gaps/line) is the middle line away from b'/h' (1720)?
#7 steps is one octave #7 steps is one octave
#negative goes up, positive goes down. #negative goes up, positive goes down.
@ -2303,7 +2305,7 @@ class Clef(Item):
"soprano" : -2, #C clef on the lowest line "soprano" : -2, #C clef on the lowest line
"varbaritone" :-10, #F Clef on the middle line "varbaritone" :-10, #F Clef on the middle line
"subbass" : -14, #F Clef on the highest line "subbass" : -14, #F Clef on the highest line
#"midiDrum" : -12, #Percussion clef in the middle for layout, but bass clef in reality. Used for Midi. "midiDrum" : -12, #Percussion clef in the middle for layout, but bass clef in reality. Used for Midi.
"percussion" : -6, #Percussion clef in the middle, for lilypond. Needs midi transposition, a special case checked for when doing midi export. "percussion" : -6, #Percussion clef in the middle, for lilypond. Needs midi transposition, a special case checked for when doing midi export.
} }
@ -2317,7 +2319,7 @@ class Clef(Item):
"bass" : 2, #F Clef on the second highest line "bass" : 2, #F Clef on the second highest line
"bass^8" : 2, "bass^8" : 2,
"bass_8" : 2, "bass_8" : 2,
#"midiDrum" : 2, #Same as Bass "midiDrum" : 2, #Same as Bass. It's in this list so the api can return it.
"percussion" : 1, #Same as Alto "percussion" : 1, #Same as Alto
} }
@ -2326,6 +2328,7 @@ class Clef(Item):
def __init__(self, clefString): def __init__(self, clefString):
super().__init__() super().__init__()
assert clefString in Clef.inComparisonToTrebleClef
self.clefString = clefString self.clefString = clefString
self._secondInit(parentBlock = None) #see Item._secondInit. self._secondInit(parentBlock = None) #see Item._secondInit.

31
engine/track.py

@ -273,9 +273,8 @@ class TrackState(object):
"""TrackState stays not the same for one track but gets recreated, at least in track.head(). """TrackState stays not the same for one track but gets recreated, at least in track.head().
This means init is always position 0.""" This means init is always position 0."""
#in init these will get recreated all the time. This confuses cashing and hashing
defaultClef = Clef("treble") defaultClef = Clef("treble")
defaultDynamicSignature = DynamicSignature("custom") defaultDynamicSignature = DynamicSignature("custom") #This is the start dynamic value like 'forte', not the DynamicSettingsSignature
defaultMetricalInstruction = MetricalInstruction(tuple(), isMetrical = False) defaultMetricalInstruction = MetricalInstruction(tuple(), isMetrical = False)
defaultKeySignature = KeySignature(20, [0,0,0,0,0,0,0]) defaultKeySignature = KeySignature(20, [0,0,0,0,0,0,0])
@ -288,7 +287,8 @@ class TrackState(object):
self.barlines = [] #a list of ints/tickpositions. These are the non-editable, non-movable single barlines. self.barlines = [] #a list of ints/tickpositions. These are the non-editable, non-movable single barlines.
#stacks. There is always one item left in the stack, the default: #stacks. There is always one item left in the stack, the default:
self.keySignatures = [self.defaultKeySignature] #C Major self.keySignatures = [self.defaultKeySignature] #C Major
self.clefs = [self.defaultClef] #self.clefs = [self.defaultClef]
self.clefs = [Clef(track.initialClefKeyword)]
self.metricalInstructions = [self.defaultMetricalInstruction] #no barlines, no metrical information. self.metricalInstructions = [self.defaultMetricalInstruction] #no barlines, no metrical information.
self.dynamicSignatures = [self.defaultDynamicSignature] self.dynamicSignatures = [self.defaultDynamicSignature]
self.dynamicRamp = None #Not for cursor movement so it is not a stack. self.dynamicRamp = None #Not for cursor movement so it is not a stack.
@ -398,6 +398,13 @@ class Track(object):
self.initialInstrumentName = "" #different than the track name. e.g. "Violin" self.initialInstrumentName = "" #different than the track name. e.g. "Violin"
self.initialShortInstrumentName = "" # e.g. "vl" self.initialShortInstrumentName = "" # e.g. "vl"
#Since version 2.1.0 the initial signature can be set by the user, mostly as a GUI convenience.
#These are used by the track-state init/head
self.initialClefKeyword:str = "treble" #it is much easier to handle the keyword with save/load and setting this value, so we are not using the item.Clef class
#self.initialMetricalInstruction = MetricalInstruction(tuple(), isMetrical = False)
#self.initialKeySignature = KeySignature(20, [0,0,0,0,0,0,0])
self.asMetronomeData = None #This track as metronome version. Is always up to date through export. self.asMetronomeData = None #This track as metronome version. Is always up to date through export.
self._processAfterInit() self._processAfterInit()
@ -842,6 +849,13 @@ class Track(object):
else: else:
timeSig = "\\once \\override Staff.TimeSignature #'stencil = ##f \\cadenzaOn\n" timeSig = "\\once \\override Staff.TimeSignature #'stencil = ##f \\cadenzaOn\n"
for item in self.blocks[0].data[:4]:
if type(item) is Clef:
clef = ""
break
else:
clef = "\\clef " + self.initialClefKeyword + "\n" #internal clef keywords are the same as lilypond
carryLilypondRanges = {} #handed from item to item for ranges such as tuplets. Can act like a stack or simply remember stuff. carryLilypondRanges = {} #handed from item to item for ranges such as tuplets. Can act like a stack or simply remember stuff.
upbeatLy = "\\partial {} ".format(Duration.createByGuessing(self.upbeatInTicks).lilypond(carryLilypondRanges)) if self.upbeatInTicks else "" upbeatLy = "\\partial {} ".format(Duration.createByGuessing(self.upbeatInTicks).lilypond(carryLilypondRanges)) if self.upbeatInTicks else ""
@ -897,7 +911,7 @@ class Track(object):
pass pass
if lyData: if lyData:
return timeSig + upbeatLy + lyData + "\n" return clef + timeSig + upbeatLy + lyData + "\n"
else: else:
return "" #Empty track return "" #Empty track
@ -911,6 +925,7 @@ class Track(object):
"dynamicSettingsSignature" : self.dynamicSettingsSignature.serialize(), "dynamicSettingsSignature" : self.dynamicSettingsSignature.serialize(),
"double" : self.double, "double" : self.double,
"initialClefKeyword" : self.initialClefKeyword,
"initialMidiChannel" : self.initialMidiChannel, "initialMidiChannel" : self.initialMidiChannel,
"initialMidiProgram" : self.initialMidiProgram, "initialMidiProgram" : self.initialMidiProgram,
"initialMidiBankMsb" : self.initialMidiBankMsb, "initialMidiBankMsb" : self.initialMidiBankMsb,
@ -945,6 +960,12 @@ class Track(object):
self.initialInstrumentName = serializedData["initialInstrumentName"] self.initialInstrumentName = serializedData["initialInstrumentName"]
self.initialShortInstrumentName = serializedData["initialShortInstrumentName"] self.initialShortInstrumentName = serializedData["initialShortInstrumentName"]
#Version 2.1.0
if "initialClefKeyword" in serializedData:
self.initialClefKeyword = serializedData["initialClefKeyword"]
else:
self.initialClefKeyword = "treble"
self._processAfterInit() self._processAfterInit()
return self return self
@ -977,6 +998,7 @@ class Track(object):
"upbeatInTicks": int(self.upbeatInTicks), "upbeatInTicks": int(self.upbeatInTicks),
"double" : self.double, "double" : self.double,
"audible" : self.sequencerInterface.enabled, "audible" : self.sequencerInterface.enabled,
"initialClefKeyword" : self.initialClefKeyword,
"initialMidiChannel" : self.initialMidiChannel, "initialMidiChannel" : self.initialMidiChannel,
"initialMidiProgram" : self.initialMidiProgram, "initialMidiProgram" : self.initialMidiProgram,
"initialMidiBankMsb" : self.initialMidiBankMsb, "initialMidiBankMsb" : self.initialMidiBankMsb,
@ -1232,6 +1254,7 @@ class Track(object):
metaData["barlines"] = barlines.keys() metaData["barlines"] = barlines.keys()
metaData["duration"] = self.state.tickindex #tickindex is now at the end, so this is the end duration. This includes Blocks minimumDuration as well since it is included in left/right metaData["duration"] = self.state.tickindex #tickindex is now at the end, so this is the end duration. This includes Blocks minimumDuration as well since it is included in left/right
metaData["beams"] = resultBeamGroups metaData["beams"] = resultBeamGroups
metaData["initialClef"] = self.initialClefKeyword
#Notes #Notes
t = (midiNotesBinaryCboxData, 0, self.state.tickindex) t = (midiNotesBinaryCboxData, 0, self.state.tickindex)

14
qtgui/designer/trackWidget.py

@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_trackGroupWidget(object): class Ui_trackGroupWidget(object):
def setupUi(self, trackGroupWidget): def setupUi(self, trackGroupWidget):
trackGroupWidget.setObjectName("trackGroupWidget") trackGroupWidget.setObjectName("trackGroupWidget")
trackGroupWidget.resize(1448, 530) trackGroupWidget.resize(1419, 548)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
@ -132,7 +132,14 @@ class Ui_trackGroupWidget(object):
self.horizontalLayout.addItem(spacerItem) self.horizontalLayout.addItem(spacerItem)
self.verticalLayout.addWidget(self.track) self.verticalLayout.addWidget(self.track)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setSpacing(12)
self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label_30 = QtWidgets.QLabel(trackGroupWidget)
self.label_30.setObjectName("label_30")
self.horizontalLayout_2.addWidget(self.label_30)
self.initialClef_comboBox = QtWidgets.QComboBox(trackGroupWidget)
self.initialClef_comboBox.setObjectName("initialClef_comboBox")
self.horizontalLayout_2.addWidget(self.initialClef_comboBox)
self.label = QtWidgets.QLabel(trackGroupWidget) self.label = QtWidgets.QLabel(trackGroupWidget)
self.label.setObjectName("label") self.label.setObjectName("label")
self.horizontalLayout_2.addWidget(self.label) self.horizontalLayout_2.addWidget(self.label)
@ -468,8 +475,9 @@ class Ui_trackGroupWidget(object):
self.midiBankLsbSpinBox.setPrefix(_translate("trackGroupWidget", "Bank LSB")) self.midiBankLsbSpinBox.setPrefix(_translate("trackGroupWidget", "Bank LSB"))
self.midiTransposeSpinBox.setPrefix(_translate("trackGroupWidget", "Transpose ")) self.midiTransposeSpinBox.setPrefix(_translate("trackGroupWidget", "Transpose "))
self.deleteButton.setText(_translate("trackGroupWidget", "Delete")) self.deleteButton.setText(_translate("trackGroupWidget", "Delete"))
self.label.setText(_translate("trackGroupWidget", "Instrument Name")) self.label_30.setText(_translate("trackGroupWidget", "Initial Clef"))
self.label_2.setText(_translate("trackGroupWidget", "Short Instrument Name")) self.label.setText(_translate("trackGroupWidget", "Instrument PDF Name"))
self.label_2.setText(_translate("trackGroupWidget", "Short Instrument PDF Name"))
self.advanced.setTitle(_translate("trackGroupWidget", "Advanced")) self.advanced.setTitle(_translate("trackGroupWidget", "Advanced"))
self.label_3.setText(_translate("trackGroupWidget", "Derfault On")) self.label_3.setText(_translate("trackGroupWidget", "Derfault On"))
self.label_4.setText(_translate("trackGroupWidget", "Default Off")) self.label_4.setText(_translate("trackGroupWidget", "Default Off"))

21
qtgui/designer/trackWidget.ui

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1448</width> <width>1419</width>
<height>530</height> <height>548</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -328,10 +328,23 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>12</number>
</property>
<item>
<widget class="QLabel" name="label_30">
<property name="text">
<string>Initial Clef</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="initialClef_comboBox"/>
</item>
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Instrument Name</string> <string>Instrument PDF Name</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -345,7 +358,7 @@
<item> <item>
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Short Instrument Name</string> <string>Short Instrument PDF Name</string>
</property> </property>
</widget> </widget>
</item> </item>

29
qtgui/items.py

@ -639,6 +639,16 @@ class GuiRest(GuiItem):
tuplet.setPos(2, -4-constantsAndConfigs.stafflineGap*2) tuplet.setPos(2, -4-constantsAndConfigs.stafflineGap*2)
class GuiKeySignature(GuiItem): class GuiKeySignature(GuiItem):
pitchModYOffset = {
#The svg graphics are not aligned "musically". We need to adjust their positions.
0 : -1.25,
10 : -1.25,
20 : -0.5,
-10 : -1.75,
-20 : -1.75,
}
def __init__(self, staticItem): def __init__(self, staticItem):
super(GuiKeySignature, self).__init__(staticItem) super(GuiKeySignature, self).__init__(staticItem)
self.createGraphicItemsFromData() self.createGraphicItemsFromData()
@ -650,7 +660,9 @@ class GuiKeySignature(GuiItem):
for i, (accidentalOnLine, pitchMod) in enumerate(self.staticItem["accidentalsOnLines"]): for i, (accidentalOnLine, pitchMod) in enumerate(self.staticItem["accidentalsOnLines"]):
glyph = GuiKeySignature.accidentals[pitchMod]() glyph = GuiKeySignature.accidentals[pitchMod]()
glyph.setParentItem(self) glyph.setParentItem(self)
glyph.setPos(constantsAndConfigs.magicPixel + i*1.5*constantsAndConfigs.magicPixel, constantsAndConfigs.stafflineGap * accidentalOnLine / 2) #These accidental graphics are shifted to the left in the .svg so they can be placed just as noteheads and match automatically. So we set them +x here. x = constantsAndConfigs.magicPixel + i*1.5*constantsAndConfigs.magicPixel
y = (accidentalOnLine/2) * constantsAndConfigs.stafflineGap + GuiKeySignature.pitchModYOffset[pitchMod]*constantsAndConfigs.stafflineGap
glyph.setPos(x, y)
if not self.staticItem["accidentalsOnLines"]: if not self.staticItem["accidentalsOnLines"]:
#No accidentals in the keysig (C-Major, D-Dorian etc.) gets a big natural sign. #No accidentals in the keysig (C-Major, D-Dorian etc.) gets a big natural sign.
@ -700,11 +712,26 @@ class GuiClef(GuiItem):
"treble^8" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefTreble^8.svg"), "treble^8" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefTreble^8.svg"),
"bass" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefBass.svg"), "bass" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefBass.svg"),
"bass_8" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefBass_8.svg"), "bass_8" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefBass_8.svg"),
"bass^8" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefBass^8.svg"),
"alto" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefAlto.svg"), "alto" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefAlto.svg"),
"midiDrum" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefPercussion.svg"), "midiDrum" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefPercussion.svg"),
"percussion" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefPercussion.svg"), "percussion" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefPercussion.svg"),
} }
#If you want to position the clef on the staff lines use these.
#We need to have different one for each graphics because the graphics just start at y=0 without any musical "knowledge"
cleffYOnStaff = {
"treble" : -3.5*constantsAndConfigs.stafflineGap,
"treble_8" : -3.5*constantsAndConfigs.stafflineGap,
"treble^8" : -5*constantsAndConfigs.stafflineGap,
"bass" : -2*constantsAndConfigs.stafflineGap,
"bass_8" : -2*constantsAndConfigs.stafflineGap,
"bass^8" : -3*constantsAndConfigs.stafflineGap,
"alto" : -1.75*constantsAndConfigs.stafflineGap,
"midiDrum" : -0.85*constantsAndConfigs.stafflineGap,
"percussion" : -0.85*constantsAndConfigs.stafflineGap,
}
class GuiTimeSignature(GuiItem): class GuiTimeSignature(GuiItem):
"""leave this in the code because of the cool svg subrender feature""" """leave this in the code because of the cool svg subrender feature"""

15
qtgui/musicstructures.py

@ -36,13 +36,16 @@ from template.qtgui.helper import stretchLine, stretchRect, callContextMenu, rem
import engine.api as api import engine.api as api
from . import graphs from . import graphs
from .items import staticItem2Item, GuiTieCurveGraphicsItem from .items import staticItem2Item, GuiTieCurveGraphicsItem, GuiClef
from .constantsAndConfigs import constantsAndConfigs from .constantsAndConfigs import constantsAndConfigs
from .submenus import BlockPropertiesEdit from .submenus import BlockPropertiesEdit
cosmeticPen = QtGui.QPen() cosmeticPen = QtGui.QPen()
cosmeticPen.setCosmetic(True) cosmeticPen.setCosmetic(True)
sceneXOffsetForInitialSigs = -75
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.
@ -342,11 +345,11 @@ class GuiTrack(QtWidgets.QGraphicsItem):
treble + bass clef.""" treble + bass clef."""
def createLine(yOffset): def createLine(yOffset):
line = QtWidgets.QGraphicsLineItem(QtCore.QLineF(0, 0, lengthInPixel, 0)) line = QtWidgets.QGraphicsLineItem(QtCore.QLineF(0, 0, lengthInPixel+abs(sceneXOffsetForInitialSigs), 0))
line.setParentItem(self) line.setParentItem(self)
line.setPen(cosmeticPen) line.setPen(cosmeticPen)
self.staffLines.append(line) self.staffLines.append(line)
line.setPos(0, yOffset*constantsAndConfigs.stafflineGap) line.setPos(sceneXOffsetForInitialSigs, yOffset*constantsAndConfigs.stafflineGap)
line.setZValue(-5) #This is the z value within GuiTrack line.setZValue(-5) #This is the z value within GuiTrack
for l in self.staffLines: for l in self.staffLines:
@ -461,6 +464,12 @@ class GuiTrack(QtWidgets.QGraphicsItem):
self.anchor.setParentItem(self) self.anchor.setParentItem(self)
metaDataDict = staticRepresentationList.pop() metaDataDict = staticRepresentationList.pop()
#Initial Signatures, if present. Negative X-axis values
clefSVGItem = GuiClef.clefs[metaDataDict["initialClef"]]() #just the graphics
self.anchor.addToGroup(clefSVGItem)
clefSVGItem.setPos(sceneXOffsetForInitialSigs+5, GuiClef.cleffYOnStaff[metaDataDict["initialClef"]])
#Real items, positive X-axis values
for staticItem in staticRepresentationList: for staticItem in staticRepresentationList:
item = staticItem2Item(staticItem) item = staticItem2Item(staticItem)
#item.setParentItem(self.anchor) #item.setParentItem(self.anchor)

13969
qtgui/resources.py

File diff suppressed because it is too large

1
qtgui/resources/resources.qrc

@ -12,6 +12,7 @@
<file>svg/blockEnd.svg</file> <file>svg/blockEnd.svg</file>
<file>svg/clefAlto.svg</file> <file>svg/clefAlto.svg</file>
<file>svg/clefBass_8.svg</file> <file>svg/clefBass_8.svg</file>
<file>svg/clefBass^8.svg</file>
<file>svg/clefBass.svg</file> <file>svg/clefBass.svg</file>
<file>svg/clefPercussion.svg</file> <file>svg/clefPercussion.svg</file>
<file>svg/clefTreble^8.svg</file> <file>svg/clefTreble^8.svg</file>

64
qtgui/resources/svg/clefBass^8.svg

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
width="16.775"
height="27.769798"
id="svg3169"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
sodipodi:docname="clefBass^8.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="692"
id="namedview3018"
showgrid="false"
inkscape:zoom="8.9152026"
inkscape:cx="5.7766494"
inkscape:cy="4.0941302"
inkscape:window-x="0"
inkscape:window-y="20"
inkscape:window-maximized="0"
inkscape:current-layer="svg3169"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata3177">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3175" />
<path
d="m 14.175,18.119798 c 0,-0.725 0.575,-1.3 1.3,-1.3 0.725,0 1.3,0.575 1.3,1.3 0,0.725001 -0.575,1.3 -1.3,1.3 -0.725,0 -1.3,-0.574999 -1.3,-1.3 z m 0,-6.25 c 0,-0.725 0.575,-1.3 1.3,-1.3 0.725,0 1.3,0.575 1.3,1.3 0,0.725 -0.575,1.3 -1.3,1.3 -0.725,0 -1.3,-0.575 -1.3,-1.3 z M 6.1,8.4697982 c 4.275,0 7.3,2.1499998 7.3,6.1999998 0,6.575 -6.6,10.375 -12.925,13.025 -0.05,0.05 -0.125,0.075 -0.2,0.075 -0.15,0 -0.275,-0.125 -0.275,-0.275 0,-0.075 0.025,-0.15 0.075,-0.2 5.075,-2.95 10.375,-6.625 10.375,-12.35 0,-3.025 -1.6,-5.9249998 -4.35,-5.9249998 -1.975,0 -3.45,1.4249998 -4.1,3.3249998 0.35,-0.2 0.7,-0.325 1.075,-0.325 1.375,0 2.5,1.125 2.5,2.5 0,1.45 -1.1,2.675 -2.5,2.675 -1.5,0 -2.8,-1.2 -2.8,-2.675 0,-3.3 2.575,-6.0499998 5.825,-6.0499998 z"
id="path3171"
inkscape:connector-curvature="0" />
<path
glyph-name="eight"
d="m 8.7230788,3.7691237 c 0.4933672,-0.5103799 0.918684,-1.0547843 0.918684,-1.7523033 0,-0.9527089 -0.9867346,-1.54815154 -2.0245067,-1.54815154 -0.8336202,0 -1.3269873,0.64648084 -1.3269873,1.27594894 0,0.374279 0.153114,0.7145316 0.5273924,0.9356961 z m 0.459342,0.2722027 c 0.9356962,0.5444053 1.4460752,1.326987 1.4460752,2.1606077 0,1.2249107 -1.1058223,2.4157968 -3.1473411,2.4157968 -1.5651644,0 -3.0452656,-0.9016707 -3.0452656,-2.3477468 0,-0.8676453 0.6805062,-1.4630879 1.3269872,-2.0585314 -0.7485569,-0.4763544 -1.08881,-1.1738725 -1.08881,-1.8543787 0,-1.139848 1.0207594,-2.24567179 2.9431896,-2.24567179 1.3610124,0 2.6879999,0.68050655 2.6879999,1.90541819 0,0.816608 -0.5444051,1.4290634 -1.1228352,2.024506 z M 6.2392309,4.4836554 C 5.6608006,4.9940353 5.1163955,5.5214279 5.1163955,6.2699841 c 0,1.1738734 1.1228354,1.9904814 2.3647594,1.9904814 0.935696,0 1.4971136,-0.7315444 1.4971136,-1.446076 0,-0.4253163 -0.1871391,-0.8676453 -0.6294682,-1.1228353 z"
id="path3728"
inkscape:connector-curvature="0"
style="stroke-width:0.903155" />
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

6
qtgui/scorescene.py

@ -34,11 +34,10 @@ import engine.api as api
from .constantsAndConfigs import constantsAndConfigs from .constantsAndConfigs import constantsAndConfigs
from .grid import GuiGrid from .grid import GuiGrid
from .conductor import Conductor, ConductorTransparentBlock from .conductor import Conductor, ConductorTransparentBlock
from .musicstructures import GuiBlockHandle, GuiTrack from .musicstructures import GuiBlockHandle, GuiTrack, sceneXOffsetForInitialSigs
from .graphs import CCGraphTransparentBlock, CCPath from .graphs import CCGraphTransparentBlock, CCPath
from .cursor import Cursor, Playhead, Selection from .cursor import Cursor, Playhead, Selection
class GuiScore(QtWidgets.QGraphicsScene): class GuiScore(QtWidgets.QGraphicsScene):
def __init__(self, parentView): def __init__(self, parentView):
super().__init__() super().__init__()
@ -121,7 +120,8 @@ class GuiScore(QtWidgets.QGraphicsScene):
return 0 #self.parentView.geometry().width() return 0 #self.parentView.geometry().width()
def updateSceneRect(self): def updateSceneRect(self):
self.parentView.setSceneRect(QtCore.QRectF(-5, self.yStart, self.maxTrackLength() + 300, self.cachedSceneHeight)) #x,y,w,h #self.parentView.setSceneRect(QtCore.QRectF(-5, self.yStart, self.maxTrackLength() + 300, self.cachedSceneHeight)) #x,y,w,h
self.parentView.setSceneRect(QtCore.QRectF(sceneXOffsetForInitialSigs, self.yStart, self.maxTrackLength() + 300 + abs(sceneXOffsetForInitialSigs), self.cachedSceneHeight)) #x,y,w,h
def updateTrack(self, trackId, staticRepresentationList): def updateTrack(self, trackId, staticRepresentationList):
"""for callbacks""" """for callbacks"""

13
qtgui/trackEditor.py

@ -37,6 +37,7 @@ from .submenus import TickWidget, CombinedTickWidget
from contextlib import contextmanager from contextlib import contextmanager
import engine.api as api import engine.api as api
LIST_OF_CLEF_KEYWORDS = api.getPossibleClefKeywords() #TODO: translate? But keep the keyword as index. setData
class TrackWidget(QtWidgets.QGroupBox): class TrackWidget(QtWidgets.QGroupBox):
#TODO: ideas: number of blocks, list of block names which CCs are set, review/change durationSettingsSignature, dynamicSettingsSignature #TODO: ideas: number of blocks, list of block names which CCs are set, review/change durationSettingsSignature, dynamicSettingsSignature
@ -68,6 +69,11 @@ class TrackWidget(QtWidgets.QGroupBox):
self.ui.instrumentName.editingFinished.connect(self.nameChanged) self.ui.instrumentName.editingFinished.connect(self.nameChanged)
self.ui.shortInstrumentName.editingFinished.connect(self.nameChanged) self.ui.shortInstrumentName.editingFinished.connect(self.nameChanged)
#Set the initial clef. Unlike the metrical instruction the engine actually has a default clef, which is the treble clef
self.ui.initialClef_comboBox.addItems(LIST_OF_CLEF_KEYWORDS) #Current index is set in self.updateData
self.ui.initialClef_comboBox.currentIndexChanged.connect(self.dataChanged)
#Create a menu with checkboxes to allow switching on and off of additional channels for the CC sub-track #Create a menu with checkboxes to allow switching on and off of additional channels for the CC sub-track
#However, we will not use normal checkable Menu actions since they close the menu after triggering. even blockSignals does not prevent closing #However, we will not use normal checkable Menu actions since they close the menu after triggering. even blockSignals does not prevent closing
@ -196,6 +202,8 @@ class TrackWidget(QtWidgets.QGroupBox):
"""Our data changed. Send to Engine""" """Our data changed. Send to Engine"""
with self.blockUiSignals(): with self.blockUiSignals():
dictionary = {} dictionary = {}
dictionary["initialClefKeyword"] = self.ui.initialClef_comboBox.currentText()
dictionary["initialMidiChannel"] = self.ui.midiChannelSpinBox.value()-1 dictionary["initialMidiChannel"] = self.ui.midiChannelSpinBox.value()-1
dictionary["initialMidiProgram"] = self.ui.midiProgramSpinBox.value() dictionary["initialMidiProgram"] = self.ui.midiProgramSpinBox.value()
dictionary["initialMidiBankMsb"] = self.ui.midiBankMsbSpinBox.value() dictionary["initialMidiBankMsb"] = self.ui.midiBankMsbSpinBox.value()
@ -244,6 +252,9 @@ class TrackWidget(QtWidgets.QGroupBox):
self.trackExportObject = trackExportObject self.trackExportObject = trackExportObject
self.ui.upbeatSpinBox.setValue(trackExportObject["upbeatInTicks"]) self.ui.upbeatSpinBox.setValue(trackExportObject["upbeatInTicks"])
self.ui.nameLineEdit.setText(trackExportObject["name"]) self.ui.nameLineEdit.setText(trackExportObject["name"])
self.ui.initialClef_comboBox.setCurrentIndex(LIST_OF_CLEF_KEYWORDS.index(trackExportObject["initialClefKeyword"]))
self.ui.midiChannelSpinBox.setValue(trackExportObject["initialMidiChannel"]+1) self.ui.midiChannelSpinBox.setValue(trackExportObject["initialMidiChannel"]+1)
self.ui.midiProgramSpinBox.setValue(trackExportObject["initialMidiProgram"]) self.ui.midiProgramSpinBox.setValue(trackExportObject["initialMidiProgram"])
self.ui.midiBankMsbSpinBox.setValue(trackExportObject["initialMidiBankMsb"]) self.ui.midiBankMsbSpinBox.setValue(trackExportObject["initialMidiBankMsb"])
@ -415,7 +426,7 @@ class TrackEditor(QtWidgets.QWidget):
"""This comes in for every small item change. But only per track""" """This comes in for every small item change. But only per track"""
trackWidget = self.tracks[trackId] trackWidget = self.tracks[trackId]
prefix = translate("trackEditorPythonFile", "Block Order:") + " " prefix = translate("trackEditorPythonFile", "Block Order:") + " "
trackWidget.ui.blocksLabel.setText(prefix + " ".join(block["name"] for block in listOfBlockExportDicts)) trackWidget.ui.blocksLabel.setText(prefix + ", ".join(block["name"] for block in listOfBlockExportDicts))
def setAllUpbeats(self): def setAllUpbeats(self):

Loading…
Cancel
Save