Browse Source

New function to create a new empty block from an existing one, that has reserved duration same as the original one.

master
Nils 2 months ago
parent
commit
8599f74e41
  1. 1
      CHANGELOG
  2. 28
      engine/api.py
  3. 6
      engine/block.py
  4. 14
      engine/track.py
  5. 4
      qtgui/designer/mainwindow.py
  6. 6
      qtgui/designer/mainwindow.ui
  7. 1
      qtgui/menu.py
  8. 1
      qtgui/musicstructures.py

1
CHANGELOG

@ -7,6 +7,7 @@ External contributors notice at the end of the line: (LastName, FirstName / nick
## 2022-10-15 2.2.0
Add SOLO functionality alongside the existing audible/mute layer. Control via shortcuts, track editor, or track list widget
New function to create a new empty block from an existing one, that has reserved duration same as the original one.
Add more time signatures to the quick-insert dialog: 8/4, three variants of 7/8, two variants of 5/4 and more. Also reorder and better labels.
Fix splitting of notes that were created by a previous split.
Block Mode: Fix invisible block labels and graphics when dragging blocks (adopting to unannounced Qt regressions once again)

28
engine/api.py

@ -965,7 +965,7 @@ def duplicateBlock(blockId, times = 1):
callbacks._updateTrack(id(track))
#callbacks._setCursor()
def duplicateContentLinkBlock(blockId, times = 1):
def duplicateContentLinkBlock(blockId, times=1):
track, block = session.data.blockById(blockId)
session.history.register(lambda i=id(track), l=track.asListOfBlockIds(): rearrangeBlocks(i, l), descriptionString = "content link block")
for i in range(times):
@ -973,6 +973,23 @@ def duplicateContentLinkBlock(blockId, times = 1):
callbacks._updateTrack(id(track))
#callbacks._setCursor() #this will make the GUI jump around because it centers on the cursor
def duplicateToReservedSpaceBlock(blockId, times=1):
"""Create a new block that has the same duration as the given one.
The duration will be reserved.
Intended for the composition phase.
For example used to create a template for a second voice, where the total duration
is already known and can be reserved, so the following blocks are in the right place."""
track, block = session.data.blockById(blockId)
session.history.register(lambda i=id(track), l=track.asListOfBlockIds(): rearrangeBlocks(i, l), descriptionString = "duplicate block as reserved space")
for i in range(times):
track.duplicateToReservedSpaceBlock(block)
callbacks._updateTrack(id(track))
def duplicateToReservedSpaceCurrentBlock():
currentBlockId = id(session.data.currentTrack().currentBlock())
duplicateToReservedSpaceBlock(currentBlockId, 1) #handles callbacks and undo
def moveBlockToOtherTrack(blockId, newTrackId, listOfBlockIdsForNewTrack):
"""First move the block to the new track and then
rearrange both tracks
@ -1106,15 +1123,6 @@ def moveCurrentBlockToStartOfTrack():
moveBlockToStartOfTrack(id(session.data.currentTrack().currentBlock()))
#deprecated
def _setBlockData(block, newData):
"""DEPRECATED. This did not work. The linked blocks were not reduced.
At point of the bug reports, instead of fixing this, we used
duplicate block and delete which already provides all functionality"""
session.history.register(lambda bl=block, old=block.data: _setBlockData(bl, old), descriptionString = "set block data")
block.data = newData
#no callbacks needed.
#Cursor
def getCursorPitch():

6
engine/block.py

@ -151,7 +151,7 @@ class Block(object):
else:
self._parentTrack = None
def copy(self, newParentTrack):
def copy(self, newParentTrack, nameSuffix="-copy"):
"""Return an independet copy of this block.
It will not be inserted into a track here but in the parentTrack
@ -174,10 +174,10 @@ class Block(object):
if self in copyItem.parentBlocks: #TODO: investigate
copyItem.parentBlocks.remove(self)
if self.name.endswith("-copy"): #name is mutable, but getter and setter deal with that.
if self.name.endswith(nameSuffix): #name is mutable, but getter and setter deal with that.
new.name = self.name
else:
new.name = self.name + "-copy"
new.name = self.name + nameSuffix
new._minimumInTicks = self._minimumInTicks[:] #it is a mutable value, we make a copy of the list (which has an int inside, which is immutable and copied automatically)
return new

14
engine/track.py

@ -481,6 +481,20 @@ class Track(object):
self.blocks.insert(index +1, linked)
self.toPosition(originalPosition) #has head() in it
def duplicateToReservedSpaceBlock(self, block):
"""We actually do a copy and then remove the content.
While at the moment of creation (v2.2.0) it would be equally well to create a new empty
block and set the duration and name this way is better for future functionality."""
originalPosition = self.state.position()
index = self.blocks.index(block)
copy = block.copy(newParentTrack=self, nameSuffix="-reserved")
copy.data = list() #empty
copy.minimumInTicks = self.duration()
self.blocks.insert(index +1, copy)
self.toPosition(originalPosition) #has head() in it
def hasContentLinks(self):
return any(len(block.linkedContentBlocks) > 1 for block in self.blocks)

4
qtgui/designer/mainwindow.py

@ -697,6 +697,8 @@ class Ui_MainWindow(object):
self.actionToggle_Track_Solo_Playback.setObjectName("actionToggle_Track_Solo_Playback")
self.actionReset_all_Solo = QtWidgets.QAction(MainWindow)
self.actionReset_all_Solo.setObjectName("actionReset_all_Solo")
self.actionCreate_reserved_duration_empty_block_from_current = QtWidgets.QAction(MainWindow)
self.actionCreate_reserved_duration_empty_block_from_current.setObjectName("actionCreate_reserved_duration_empty_block_from_current")
self.menuObjects.addAction(self.actionMetrical_Instruction)
self.menuObjects.addAction(self.actionCustom_Metrical_Instruction)
self.menuObjects.addAction(self.actionClef)
@ -789,6 +791,7 @@ class Ui_MainWindow(object):
self.menuTracks.addAction(self.actionSplit_Current_Block)
self.menuTracks.addAction(self.actionAppend_Block)
self.menuTracks.addAction(self.actionDuplicate)
self.menuTracks.addAction(self.actionCreate_reserved_duration_empty_block_from_current)
self.menuTracks.addAction(self.actionUnlink_Current_Block)
self.menuTracks.addAction(self.actionCreate_Linked_Copy)
self.menuTracks.addAction(self.actionDelete_Current_Block)
@ -1068,3 +1071,4 @@ class Ui_MainWindow(object):
self.actionToggle_Track_Solo_Playback.setText(_translate("MainWindow", "Toggle Track Solo Playback"))
self.actionToggle_Track_Solo_Playback.setShortcut(_translate("MainWindow", "Z"))
self.actionReset_all_Solo.setText(_translate("MainWindow", "Reset Solo for all Tracks"))
self.actionCreate_reserved_duration_empty_block_from_current.setText(_translate("MainWindow", "Create reserved-duration empty block from current"))

6
qtgui/designer/mainwindow.ui

@ -168,6 +168,7 @@
<addaction name="actionSplit_Current_Block"/>
<addaction name="actionAppend_Block"/>
<addaction name="actionDuplicate"/>
<addaction name="actionCreate_reserved_duration_empty_block_from_current"/>
<addaction name="actionUnlink_Current_Block"/>
<addaction name="actionCreate_Linked_Copy"/>
<addaction name="actionDelete_Current_Block"/>
@ -1876,6 +1877,11 @@
<string>Reset Solo for all Tracks</string>
</property>
</action>
<action name="actionCreate_reserved_duration_empty_block_from_current">
<property name="text">
<string>Create reserved-duration empty block from current</string>
</property>
</action>
</widget>
<resources/>
<connections/>

1
qtgui/menu.py

@ -277,6 +277,7 @@ class MenuActionDatabase(object):
self.mainWindow.ui.actionSplit_Current_Block : api.splitBlock,
self.mainWindow.ui.actionJoin_with_next_Block : api.joinBlock,
self.mainWindow.ui.actionDuplicate : api.duplicateCurrentBlock,
self.mainWindow.ui.actionCreate_reserved_duration_empty_block_from_current : api.duplicateToReservedSpaceCurrentBlock,
self.mainWindow.ui.actionCreate_Linked_Copy : api.duplicateContentLinkCurrentBlock,
self.mainWindow.ui.actionUnlink_Current_Block : api.unlinkCurrentBlock,
self.mainWindow.ui.actionDelete_Current_Block : api.deleteCurrentBlock,

1
qtgui/musicstructures.py

@ -175,6 +175,7 @@ class GuiBlockHandle(QtWidgets.QGraphicsRectItem):
("separator", None),
#("split here", lambda: self.splitHere(event)), #Impossible because we can't see notes.
(translate("musicstructures", "duplicate"), lambda: api.duplicateBlock(self.staticExportItem["id"])),
(translate("musicstructures", "duplicate to reserved empty"), lambda: api.duplicateToReservedSpaceBlock(self.staticExportItem["id"])),
(translate("musicstructures", "create content link"), lambda: api.duplicateContentLinkBlock(self.staticExportItem["id"])),
(translate("musicstructures", "unlink"), lambda: api.unlinkBlock(self.staticExportItem["id"])),
(translate("musicstructures", "move to start"), lambda: api.moveBlockToStartOfTrack(self.staticExportItem["id"])),

Loading…
Cancel
Save