From 58de2ba26c67deb776b88a86721fec13ad637044 Mon Sep 17 00:00:00 2001 From: Nils <> Date: Thu, 16 Jul 2020 20:00:23 +0200 Subject: [PATCH] Add missing rects and removal of whitespace --- qtgui/conductor.py | 135 +++++++++++++++++++-------------------- qtgui/cursor.py | 21 +++++- qtgui/graphs.py | 22 +++++-- qtgui/grid.py | 21 +++++- qtgui/items.py | 9 ++- qtgui/mainwindow.py | 54 ++++++++-------- qtgui/menu.py | 26 ++++---- qtgui/musicstructures.py | 20 ++++-- qtgui/scorescene.py | 45 +++++++------ qtgui/scoreview.py | 16 ++--- qtgui/submenus.py | 28 ++++---- qtgui/trackEditor.py | 6 +- 12 files changed, 237 insertions(+), 166 deletions(-) diff --git a/qtgui/conductor.py b/qtgui/conductor.py index 9b81c7f..8e52396 100644 --- a/qtgui/conductor.py +++ b/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. -_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, - "startItem":1, - "block":2, - "item":4, - "handle":5, + "startItem":1, + "block":2, + "item":4, + "handle":5, } class Conductor(QtWidgets.QGraphicsItem): @@ -52,6 +52,8 @@ class Conductor(QtWidgets.QGraphicsItem): self.staticBlocks = None #Cached Block Data list 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.setParentItem(self) self.staffLine.setPos(0,0) @@ -64,10 +66,9 @@ class Conductor(QtWidgets.QGraphicsItem): api.callbacks.updateTempoTrack.append(self.createGraphicItemsFromData) api.callbacks.updateTempoTrackMeta.append(self.updateMetaData) - def paint(self, *args): - pass 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): for block in ConductorTransparentBlock.instances: @@ -97,7 +98,7 @@ class Conductor(QtWidgets.QGraphicsItem): for dictExportItem in staticRepresentationList: guiBlock = ConductorTransparentBlock(parent = self, staticExportItem = dictExportItem, x = 0, y = -10, w = dictExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio, h = 20) guiBlock.setParentItem(self) - guiBlock.setPos(dictExportItem["position"] / constantsAndConfigs.ticksToPixelRatio,0) + guiBlock.setPos(dictExportItem["position"] / constantsAndConfigs.ticksToPixelRatio,0) rightBorder = (dictExportItem["duration"] + dictExportItem["position"]) / constantsAndConfigs.ticksToPixelRatio self.updateStaffLine(rightBorder) @@ -108,7 +109,7 @@ class Conductor(QtWidgets.QGraphicsItem): return guiblock #else: # raise ValueError(f"{backendId} not found") - + def updateStaffLine(self, x): assert not self.staffLine.line().isNull() @@ -117,8 +118,8 @@ class Conductor(QtWidgets.QGraphicsItem): self.staffLine.setLine(line) self.staffLine.setZValue(_zValuesRelativeToConductor["line"]) - def createGraphicItemsFromData(self, staticRepresentationList): - + def createGraphicItemsFromData(self, staticRepresentationList): + self.staticPoints = staticRepresentationList removeInstancesFromScene(TempoPoint) @@ -129,8 +130,8 @@ class Conductor(QtWidgets.QGraphicsItem): x = point["position"] / constantsAndConfigs.ticksToPixelRatio p = TempoPoint(self, point, self.blockById(point["blockId"])) p.setParentItem(self) - p.setPos(x, y) - + p.setPos(x, y) + def stretchXCoordinates(self, factor): """Reposition the items on the X axis. @@ -163,21 +164,21 @@ class Conductor(QtWidgets.QGraphicsItem): def add(self, scenePos): """Use a scenePos (from self.mousePressEvent) to instruct the backend 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 if constantsAndConfigs.snapToGrid: sp = round(sp / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm - + unitsPerMinute, referenceTicks = api.tempoAtTickPosition(sp) api.insertTempoItemAtAbsolutePosition(sp, unitsPerMinute, referenceTicks, graphType = "standalone") class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem): """A simplified version of a Block. Since we don't use blocks in the GUI, only in the backend we still need them sometimes as macro strutures, where we don't care about the content. - + The block handle is at the END of a block. """ @@ -205,9 +206,9 @@ class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem): self.color = stringToColor(staticExportItem["name"]) self.trans = QtGui.QColor("transparent") self.setPen(self.trans) - self.setBrush(self.color) - self.setOpacity(0.2) #mimic background behaviour - self.staticExportItem = staticExportItem + self.setBrush(self.color) + self.setOpacity(0.2) #mimic background behaviour + self.staticExportItem = staticExportItem self.posBeforeMove = None self.cursorPosOnMoveStart = None @@ -230,14 +231,19 @@ class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem): self.startLabel = 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.setParentItem(self) self.marker.setPos(staticExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio, -1/2* self.rect().height()+2) #self.setZValue(_zValuesRelativeToConductor["handle"]) #includes the handle - + + #Doesn't need it because only pure QGraphicItem subclasses need that. But we are already a rect. + #def boundingRect(self, *args): + # return oneRectToReturnThemAll + + #Doesn't need it because only pure QGraphicItem subclasses need that. But we are already a rect. #def paint(self, *args): # """Prevent the selection rectangle when clicking the item""" #!! This also prevents the rectangle to show up. Very bad decision. @@ -251,13 +257,13 @@ class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem): self.marker.setX(self.marker.pos().x() * factor) def mouseMoveEvent(self, event): - """Don't use the qt system. we move ourselves""" + """Don't use the qt system. we move ourselves""" event.accept() def mousePressEvent(self, event): self.parent.mousePressEvent(event) - def mouseMoveEventCustom(self, event): + def mouseMoveEventCustom(self, event): """ Move the whole block, change the tempoTrack form. 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 #posScene = self.parent.parentScore.parentView.mapToScene(posView) #print (posGlobal, posView, posScene, event.scenePos()) - + if self.cursorPosOnMoveStart: self.setPos(event.scenePos().x(), self.posBeforeMove.y()) @@ -340,13 +346,13 @@ class ConductorBlockHandle(QtWidgets.QGraphicsRectItem): def __init__(self, parent): self.parentTransparentBlock = parent #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.setAcceptHoverEvents(True) 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.setBrush(QtGui.QColor("black")) - + self.minimalSize = api.D1 / constantsAndConfigs.ticksToPixelRatio pen = QtGui.QPen() # creates a default pen @@ -359,8 +365,8 @@ class ConductorBlockHandle(QtWidgets.QGraphicsRectItem): self.inactivePen.setColor(QtGui.QColor("black")) self.activePen = QtGui.QPen(pen) - self.activePen.setColor(QtGui.QColor("cyan")) - + self.activePen.setColor(QtGui.QColor("cyan")) + def shape(self): """Return a more accurate shape for this item so that 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 return path - def hoverEnterEvent(self, event): + def hoverEnterEvent(self, event): self.setPen(self.activePen) - #self.parentTransparentBlock.setBrush(self.parentTransparentBlock.color) - self.setBrush(QtGui.QColor("cyan")) + #self.parentTransparentBlock.setBrush(self.parentTransparentBlock.color) + self.setBrush(QtGui.QColor("cyan")) - def hoverLeaveEvent(self, event): + def hoverLeaveEvent(self, event): self.setPen(self.inactivePen) - #self.parentTransparentBlock.setBrush(self.parentTransparentBlock.trans) + #self.parentTransparentBlock.setBrush(self.parentTransparentBlock.trans) self.setBrush(QtGui.QColor("black")) def mousePressEvent(self, event): @@ -418,7 +424,7 @@ class ConductorBlockHandle(QtWidgets.QGraphicsRectItem): class TempoPoint(QtWidgets.QGraphicsItem): """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. """ @@ -429,19 +435,16 @@ class TempoPoint(QtWidgets.QGraphicsItem): super().__init__() self.staticExportItem = staticExportItem self.parentTempoTrack = parentTempoTrack - self.parentBlock = parentBlock + self.parentBlock = parentBlock self.setZValue(_zValuesRelativeToConductor["item"]) - - self.setAcceptHoverEvents(True) - - if not self.staticExportItem["positionInBlock"] == 0: + if not self.staticExportItem["positionInBlock"] == 0: 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 - else: + else: 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.setParentItem(self) @@ -465,7 +468,7 @@ class TempoPoint(QtWidgets.QGraphicsItem): for n in (self.note, self.number, self.arrow): 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): #painter.drawRect(self.boundingRect()) #uncomment to show the bounding rect @@ -491,21 +494,21 @@ class TempoPoint(QtWidgets.QGraphicsItem): event.accept() 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 - 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""" #if self.staticExportItem["positionInBlock"] == 0: # print ("no") - # #super().mousePressEvent(event) + # #super().mousePressEvent(event) event.accept() # - - def mouseReleaseEvent(self, event): + + def mouseReleaseEvent(self, event): if self.staticExportItem["positionInBlock"] == 0: #First in block can't be moved event.accept() return - + tickPositionAbsolute = self.scenePos().x() * constantsAndConfigs.ticksToPixelRatio if constantsAndConfigs.snapToGrid: @@ -513,17 +516,17 @@ class TempoPoint(QtWidgets.QGraphicsItem): api.moveTempoItem(self.staticExportItem["id"], tickPositionAbsolute) event.accept() - - def hoverEnterEvent(self, event): - self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(False) #Delete key collides with our hover-delete. - self.grabKeyboard() - self.wheelEventChangedValue = 0 + + def hoverEnterEvent(self, event): + self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(False) #Delete key collides with our hover-delete. + self.grabKeyboard() + self.wheelEventChangedValue = 0 for n in (self.note, self.number, self.arrow): 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.ungrabKeyboard() + self.ungrabKeyboard() for n in (self.note, self.number, self.arrow): if n: n.setDefaultTextColor(QtGui.QColor("black")) if self.wheelEventChangedValue: @@ -531,7 +534,6 @@ class TempoPoint(QtWidgets.QGraphicsItem): def wheelEvent(self, event): """This buffers until hoverLeaveEvent and then the new value is sent in self.hoverLeaveEvent""" - print ("w") if event.delta() > 0: self.wheelEventChangedValue += 1 else: @@ -542,15 +544,15 @@ class TempoPoint(QtWidgets.QGraphicsItem): def keyPressEvent(self, event): """Handle the delete item key. Needs grabKeyboard, but NOT setFocus - + The event will not be sent if it is blocked by a global shortcut. """ - key = event.key() + key = event.key() 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. self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(True) #Delete key collides with our hover-delete. - self.ungrabKeyboard() - api.removeTempoItem(self.staticExportItem["id"]) + self.ungrabKeyboard() + api.removeTempoItem(self.staticExportItem["id"]) else: return super().keyPressEvent(event) @@ -581,15 +583,16 @@ class TimeLine(QtWidgets.QGraphicsItem): def __init__(self, parent): super().__init__() - self.parent = parent + self.parent = parent # self.gridInSeconds = 10 api.callbacks.updateTempoTrackBlocks.append(self.redraw) #no redraw on init. self.parent.staticPoints is not set yet. def paint(self, *args): pass + def boundingRect(self, *args): - return oneRectToReturnThemAll + return self.parent.boundingRect() def redraw(self, staticRepresentationList): if not self.parent.staticPoints: @@ -640,7 +643,3 @@ class TimeLine(QtWidgets.QGraphicsItem): time grid""" for timePoint in self.TimePoint.instances: timePoint.setX(timePoint.pos().x() * factor) - - - - diff --git a/qtgui/cursor.py b/qtgui/cursor.py index 17b094f..a669295 100644 --- a/qtgui/cursor.py +++ b/qtgui/cursor.py @@ -31,6 +31,8 @@ pen.setJoinStyle(QtCore.Qt.RoundJoin) pen.setWidth(2) #pen.setColor(QtGui.QColor("red")) +oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection. + class PitchCursor(QtWidgets.QGraphicsRectItem): def __init__(self): """Does not need the actual dotOnLine. @@ -42,6 +44,8 @@ class PitchCursor(QtWidgets.QGraphicsRectItem): self.setPen(pen) self.setEnabled(False) + def boundingRect(self, *args): return oneRectToReturnThemAll + class PositionCursor(QtWidgets.QGraphicsRectItem): def __init__(self): """Does not need the actual position. @@ -53,6 +57,10 @@ class PositionCursor(QtWidgets.QGraphicsRectItem): self.setScale(0.8) self.setEnabled(False) + def boundingRect(self, *args): + return oneRectToReturnThemAll + + class Cursor(QtWidgets.QGraphicsItemGroup): """A cursor that shows the vertical as well as the horizontal position @@ -67,6 +75,10 @@ class Cursor(QtWidgets.QGraphicsItemGroup): api.callbacks.setCursor.append(self.setCursor) self.setEnabled(False) + def boundingRect(self, *args): + return oneRectToReturnThemAll + + def clearItemHighlight(self): """Gets called before a track changes. Most of the time when a new item is inserted/deleted. This means the gui track will be recreated and a current highlight on an item might get @@ -93,7 +105,7 @@ class Cursor(QtWidgets.QGraphicsItemGroup): x = cursorExportObject["tickindex"] / constantsAndConfigs.ticksToPixelRatio #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"]] self.setPos(x, currentGuiTrack.y() ) @@ -142,6 +154,10 @@ class Playhead(QtWidgets.QGraphicsLineItem): #self.hide() #self.maxHeight = QtWidgets.QDesktopWidget().geometry().height() #we really hope the screen resolution does not change during the session. + def boundingRect(self, *args): + return oneRectToReturnThemAll + + def setCursorPosition(self, tickindex:int, playbackStatus:bool): """Set the playhead to the right position, but keep the viewport stable. Shift the entire "page" if the cursor becomes invisible because its steps outside the viewport""" @@ -215,6 +231,9 @@ class Selection(QtWidgets.QGraphicsRectItem): self.setEnabled(False) api.callbacks.setSelection.append(self.setSelection) + def boundingRect(self, *args): + return oneRectToReturnThemAll + def setSelection(self, tupleOfCursorExportObjects): if tupleOfCursorExportObjects: validSelection, topleftCursorObject, bottomRightCursorObject = tupleOfCursorExportObjects diff --git a/qtgui/graphs.py b/qtgui/graphs.py index 556b542..e2ddb5e 100644 --- a/qtgui/graphs.py +++ b/qtgui/graphs.py @@ -25,6 +25,8 @@ from .constantsAndConfigs import constantsAndConfigs from template.qtgui.helper import stringToColor, removeInstancesFromScene, callContextMenu, stretchLine, stretchRect import engine.api as api +oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection. + class CCPath(QtWidgets.QGraphicsRectItem): """ A CCPath only exists when the backend track has a cc-part activated. @@ -66,6 +68,8 @@ class CCPath(QtWidgets.QGraphicsRectItem): self.blockdictCache = {} #blockId:guiBlock updated through self.updateGraphBlockTrack self.transparentBlockHandles = [] #transparentBlockHandles in correct order. updated through self.updateGraphBlockTrack + def boundingRect(self, *args): return oneRectToReturnThemAll + def itemChange(self, changeEnum, value): if changeEnum == QtWidgets.QGraphicsItem.ItemVisibleHasChanged: #12 if self.isVisible(): @@ -76,7 +80,7 @@ class CCPath(QtWidgets.QGraphicsRectItem): return super().itemChange(changeEnum, value) def mousePressEvent(self, event): - if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton + if event.button() == 1: #QtCore.Qt.LeftButton self.add(event.pos()) @property @@ -253,6 +257,8 @@ class CCGraphTransparentBlock(QtWidgets.QGraphicsRectItem): self.posBeforeMove = None self.cursorPosOnMoveStart = None + def boundingRect(self, *args): return oneRectToReturnThemAll + def stretchXCoordinates(self, factor): """Reposition the items on the X axis. Call goes through all parents/children, starting from ScoreView._stretchXCoordinates. @@ -359,6 +365,8 @@ class CCGraphBlockEndMarker(QtWidgets.QGraphicsLineItem): self.activePen = QtGui.QPen(pen) self.activePen.setColor(QtGui.QColor("cyan")) + def boundingRect(self, *args): return oneRectToReturnThemAll + def allItemsRightOfMe(self): for item in self.parentCCPath.items: if item.x() > self.x(): @@ -376,7 +384,7 @@ class CCGraphBlockEndMarker(QtWidgets.QGraphicsLineItem): """After moving a point around send an update to the backend""" 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 = self.x() x = x * constantsAndConfigs.ticksToPixelRatio @@ -390,7 +398,7 @@ class CCGraphBlockEndMarker(QtWidgets.QGraphicsLineItem): def mousePressEvent(self, 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(): i.hide() @@ -422,6 +430,8 @@ class CCInterpolatedPoint(QtWidgets.QGraphicsEllipseItem): self.setEnabled(False) self.setZValue(1) + def boundingRect(self, *args): return oneRectToReturnThemAll + class CCUserPoint(QtWidgets.QGraphicsEllipseItem): """the position is set by the parent""" def __init__(self, parentCCPath, staticExportItem): @@ -439,6 +449,8 @@ class CCUserPoint(QtWidgets.QGraphicsEllipseItem): self.interpolatedItemsLeft = [] self.setZValue(9) + def boundingRect(self, *args): return oneRectToReturnThemAll + def shape(self): """Return a more accurate shape for this item so that mouse hovering is more accurate""" @@ -450,7 +462,7 @@ class CCUserPoint(QtWidgets.QGraphicsEllipseItem): super().mousePressEvent(event) self.lastPos = self.pos() - if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton + if event.button() == 1: #QtCore.Qt.LeftButton self.setCursor(QtCore.Qt.BlankCursor) for i in self.interpolatedItemsLeft + self.interpolatedItemsRight: i.hide() @@ -480,7 +492,7 @@ class CCUserPoint(QtWidgets.QGraphicsEllipseItem): send an update to the backend""" super(CCUserPoint, self).mouseReleaseEvent(event) 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. def mouseMoveEvent(self, event): diff --git a/qtgui/grid.py b/qtgui/grid.py index 33e1730..470d8fb 100644 --- a/qtgui/grid.py +++ b/qtgui/grid.py @@ -21,15 +21,32 @@ along with this program. If not, see . import logging; logger = logging.getLogger(__name__); logger.info("import") + + #Standard Library #Third Party from PyQt5 import QtCore, QtGui, QtWidgets #Our Template Modules +from template.engine.sequencer import MAXIMUM_TICK_DURATION #Client Modules 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): """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. """ - def __init__(self, parent, horizontalSize=None): + def __init__(self, parent, horizontalSize=None): super(GuiGrid, self).__init__() self.parent = parent #QGraphicsScene @@ -81,6 +98,8 @@ class GuiGrid(QtWidgets.QGraphicsItemGroup): gridPen = QtGui.QPen(QtCore.Qt.DotLine) gridPen.setCosmetic(True) + def boundingRect(self, *args): return oneRectToReturnThemAll + def reactToHorizontalScroll(self, value): if not self.initialGridExists: return diff --git a/qtgui/items.py b/qtgui/items.py index f69d7b8..817e224 100644 --- a/qtgui/items.py +++ b/qtgui/items.py @@ -60,6 +60,9 @@ class GuiTieCurveGraphicsItem(QtWidgets.QGraphicsPathItem): self.noteExportObject = noteExportObject self.draw() + def boundingRect(self, *args): + return oneRectToReturnThemAll + def draw(self): lengthInPixel = self.noteExportObject["tieDistanceInTicks"] / constantsAndConfigs.ticksToPixelRatio path = QtGui.QPainterPath() @@ -756,13 +759,13 @@ class GuiMetricalInstruction(GuiItem): displayString = "Metrical " + r markerPosition = -2 markerHeight = 4 - + #A metrical instruction is by definition at the beginning of a measure #We therefore need to place the text above the barnumber self.text = QtWidgets.QGraphicsSimpleTextItem(displayString) 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.setParentItem(self) @@ -913,6 +916,6 @@ def staticItem2Item(staticItem): elif typ is "BlockEndMarker": return GuiBlockEndMarker(staticItem) elif typ in ("InstrumentChange", "ChannelChange", "LilypondText"): - return GuiGenericText(staticItem) + return GuiGenericText(staticItem) else: raise ValueError("Unknown Item Type:", staticItem) diff --git a/qtgui/mainwindow.py b/qtgui/mainwindow.py index bf08fc5..1dcfe26 100644 --- a/qtgui/mainwindow.py +++ b/qtgui/mainwindow.py @@ -60,7 +60,7 @@ class MainWindow(TemplateMainWindow): #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. #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", "

Most commands work in the appending position (last position in a track) and apply to the item before it.

Use it to apply dots, sharps and flats on the item you just inserted without moving the cursor back and forth.

"), translate("About", "

Learn the keyboard shortcuts! Laborejo is designed to work with the keyboard alone and with midi instruments for full speed.

Everytime you grab your mouse you loose concentration, precision and time."), translate("About", "

Spread/shrink the space between notes with Ctrl+Shift+Mousewheel or Ctrl+Shift with Plus and Minus.

"), @@ -74,19 +74,19 @@ class MainWindow(TemplateMainWindow): translate("About", "

There is no key-rebinding except numpad-shortcuts.

"), translate("About", "

Hidden tracks still output sound.

"), translate("About", "

Non-audible tracks still output instrument changes and CCs so that they can be switched on again in the middle of playback.

"), - ] + About.didYouKnow - + ] + About.didYouKnow + super().__init__() - #New menu entries and template-menu overrides - self.menu.addMenuEntry("menuDebug", "actionRedrawAllTracks", "Redraw all Tracks") - self.menu.connectMenuEntry("actionSave", api.save) - self.menu.hideSubmenu("menuFile") - 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 - - + #New menu entries and template-menu overrides + self.menu.addMenuEntry("menuDebug", "actionRedrawAllTracks", "Redraw all Tracks") + self.menu.connectMenuEntry("actionSave", api.save) + self.menu.hideSubmenu("menuFile") + 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 + + #Create the Main Widgets in the Stacked Widget self.scoreView = ScoreView(self) self.ui.mainStackWidget.addWidget(self.scoreView) @@ -99,8 +99,8 @@ class MainWindow(TemplateMainWindow): self.ui.actionData_Editor.setChecked(False) self.ui.mainStackWidget.addWidget(self.trackEditor) - #Bind shortcuts to actions (as init effect) - #TODO: Integrate better into template menu system. + #Bind shortcuts to actions (as init effect) + #TODO: Integrate better into template menu system. self.menuActionDatabase = MenuActionDatabase(self) #The menu needs to be started before api.startEngine #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 self.statusLabel = QtWidgets.QLabel() 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. - 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 - #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.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. #Here is the crowbar-method. - self.nsmClient.announceSaveStatus(isClean = True) - - + self.nsmClient.announceSaveStatus(isClean = True) + + def zoom(self, scaleFactor:float): - """Scale factor is absolute""" + """Scale factor is absolute""" self.scoreView.zoom(scaleFactor) - def stretchXCoordinates(self, factor:float): - self.scoreView.stretchXCoordinates(factor) + def stretchXCoordinates(self, factor:float): + self.scoreView.stretchXCoordinates(factor) def updateStatusBar(self, exportCursorDict): """Every cursor movement updates the statusBar message""" c = exportCursorDict - try: + try: i = c["item"] except: print (c) @@ -182,7 +182,7 @@ class LeftToolBarPrevailingDuration(QtWidgets.QLabel): api.callbacks.prevailingBaseDurationChanged.append(self.changed) def makeText(self, baseDuration): - if not stepMidiInput.midiInIsActive: + if not stepMidiInput.midiInIsActive: return "" labelText = "" diff --git a/qtgui/menu.py b/qtgui/menu.py index 5fce22f..11f6a30 100644 --- a/qtgui/menu.py +++ b/qtgui/menu.py @@ -113,7 +113,7 @@ class MenuActionDatabase(object): def __init__(self, mainWindow): self.mainWindow = mainWindow - self.modalKeys = ModalKeys() + self.modalKeys = ModalKeys() modes = QtWidgets.QActionGroup(self.mainWindow) modes.addAction(self.mainWindow.ui.actionNotation_Mode) @@ -275,7 +275,7 @@ class MenuActionDatabase(object): self.mainWindow.ui.actionDuplicateItem : api.duplicate, self.mainWindow.ui.actionUndo : api.undo, self.mainWindow.ui.actionRedo : api.redo, - + self.mainWindow.ui.actionRedrawAllTracks : api.updateCallbackAllTracks, #Toolbox @@ -293,15 +293,15 @@ class MenuActionDatabase(object): self.mainWindow.ui.actionReverse: api.reorderReverse, self.mainWindow.ui.actionAscending: api.reorderAscending, self.mainWindow.ui.actionDescending: api.reoderdDescending, - + #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.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 #Print and Export is in self.actions 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), } @@ -434,7 +434,7 @@ class MenuActionDatabase(object): if boolean: #Switch off midi input if stepMidiInput.midiInIsActive: - self.rememberMidi = stepMidiInput.midiInIsActive + self.rememberMidi = stepMidiInput.midiInIsActive stepMidiInput.toggleMidiIn() assert not 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.setEnabled(False) - def exportLy(self): + def exportLy(self): 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 = filename[0] #(path, filter) if filename: if not os.path.splitext(filename)[1]: #no file extension given? filename = filename + ".ly" - api.session.guiSharedDataToSave["lastExportDirectory"] = os.path.dirname(filename) + api.session.guiSharedDataToSave["lastExportDirectory"] = os.path.dirname(filename) api.exportLilypond(filename) class ToolBarCCType(QtWidgets.QSpinBox): @@ -556,7 +556,7 @@ class ToolBarMetronome(QtWidgets.QCheckBox): return False def updateFromCallback(self, exportDict): - """Gets the metronome dict""" + """Gets the metronome dict""" self.blockSignals(True) self.setStatus() assert self.isChecked() == exportDict["enabled"], (self.isChecked(), exportDict["enabled"]) @@ -576,8 +576,8 @@ class ToolBarPlaybackSpeed(QtWidgets.QDoubleSpinBox): self.setSingleStep(0.1) self.setPrefix(translate("menu", "Tempo ×")) #yes, this is the unicode multiplication sign × and not an x api.callbacks.tempoScalingChanged.append(self.updateFromCallback) - self.valueChanged.connect(self.changed) - self.setLineEdit(ToolBarPlaybackSpeed.CustomLineEdit()) + self.valueChanged.connect(self.changed) + self.setLineEdit(ToolBarPlaybackSpeed.CustomLineEdit()) class CustomLineEdit(QtWidgets.QLineEdit): def mousePressEvent(self, event): @@ -601,5 +601,5 @@ class ToolBarPlaybackSpeed(QtWidgets.QDoubleSpinBox): self.setValue(newValue) self.blockSignals(False) - def changed(self): - api.changeTempoScaling(self.value()) + def changed(self): + api.changeTempoScaling(self.value()) diff --git a/qtgui/musicstructures.py b/qtgui/musicstructures.py index 91682c4..026756f 100644 --- a/qtgui/musicstructures.py +++ b/qtgui/musicstructures.py @@ -43,6 +43,8 @@ from .submenus import BlockPropertiesEdit cosmeticPen = QtGui.QPen() cosmeticPen.setCosmetic(True) +oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection. + class GuiBlockHandle(QtWidgets.QGraphicsRectItem): """A simplified version of a Block. Since we don't use blocks in the GUI, only in the backend we still need them sometimes as macro strutures, where we don't care about the content. @@ -54,7 +56,7 @@ class GuiBlockHandle(QtWidgets.QGraphicsRectItem): """ def __init__(self, parent, staticExportItem, 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.parent = parent #GuiTrack instance self.color = None #inserted by the creating function in GuiTrack @@ -93,6 +95,8 @@ class GuiBlockHandle(QtWidgets.QGraphicsRectItem): self.startLabel = QtWidgets.QGraphicsSimpleTextItem("") self.endLabel = QtWidgets.QGraphicsSimpleTextItem("") + def boundingRect(self, *args): return oneRectToReturnThemAll + def stretchXCoordinates(self, factor): """Reposition the items on the X axis. Call goes through all parents/children, starting from ScoreView._stretchXCoordinates. @@ -188,9 +192,9 @@ class GuiTrack(QtWidgets.QGraphicsItem): def __init__(self, parentScore, staticExportItem): 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.parentScore = parentScore 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 @@ -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. + def boundingRect(self, *args): return oneRectToReturnThemAll + class NameGraphic(QtWidgets.QGraphicsSimpleTextItem): def __init__(self, text, parent): super().__init__(text) @@ -237,6 +243,8 @@ class GuiTrack(QtWidgets.QGraphicsItem): if result[1]: api.setTrackName(self.parent.staticExportItem["id"], nameString = result[0], initialInstrumentName = self.parent.staticExportItem["initialInstrumentName"], initialShortInstrumentName = self.parent.staticExportItem["initialShortInstrumentName"]) #keep the old lilypond names + #def boundingRect(self, *args): return oneRectToReturnThemAll + def contextMenuEvent(self, event): listOfLabelsAndFunctions = [ (translate("musicstructures", "edit name"), self._editName), ] callContextMenu(listOfLabelsAndFunctions) @@ -392,13 +400,15 @@ class GuiTrack(QtWidgets.QGraphicsItem): class TrackAnchor(QtWidgets.QGraphicsItem): """Handling all items as individuals when deleting a track to redraw it is too much. Better let Qt handle it all at once.""" - + def __init__(self, parent): super().__init__() self.parent = parent - self.setFlag(QtWidgets.QGraphicsItem.ItemHasNoContents, True) #only child items. Without this we get notImplementedError: QGraphicsItem.paint() is abstract and must be overridden + self.setFlag(QtWidgets.QGraphicsItem.ItemHasNoContents, True) #only child items. Without this we get notImplementedError: QGraphicsItem.paint() is abstract and must be overridden self.setFlag(QtWidgets.QGraphicsItem.ItemContainsChildrenInShape, True) + def boundingRect(self, *args): return oneRectToReturnThemAll + def createGraphicItemsFromData(self, staticRepresentationList): """Create staff objects including simple barlines""" diff --git a/qtgui/scorescene.py b/qtgui/scorescene.py index 68f6cda..cb44e9c 100644 --- a/qtgui/scorescene.py +++ b/qtgui/scorescene.py @@ -43,8 +43,8 @@ class GuiScore(QtWidgets.QGraphicsScene): def __init__(self, parentView): super().__init__() 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. @@ -69,7 +69,7 @@ class GuiScore(QtWidgets.QGraphicsScene): self.backColor.setNamedColor("#fdfdff") self.setBackgroundBrush(self.backColor) - self.grid = GuiGrid(parent=self) + self.grid = Grid(parentScene=self) 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.setZValue(-50) @@ -129,9 +129,9 @@ class GuiScore(QtWidgets.QGraphicsScene): #hidden track. 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: - track = self.tracks[trackId] + track = self.tracks[trackId] ccPath = track.ccPaths[ccNumber] ccPath.createGraphicItemsFromData(staticRepresentationList) @@ -170,8 +170,8 @@ class GuiScore(QtWidgets.QGraphicsScene): for cc in guiCCs: self.removeWhenIdle(self.tracks[trackId].ccPaths[cc]) del self.tracks[trackId].ccPaths[cc] - - + + def redraw(self, listOfStaticTrackRepresentations): """The order of guiTracks depends on the backend index. 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 called by callbacksDatabase.tracksChanged""" - + for track in self.tracks.values(): track.hide() @@ -278,22 +278,31 @@ class GuiScore(QtWidgets.QGraphicsScene): return None - def wheelEvent(self, event): - """We MUST handle the event somehow. Otherwise background grid items will block the views(!) + def notTrueAnymore_wheelEvent(self, event): + """ + 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. - 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. - + 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. - - 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()) #if type(item) is items.Note: - # super().wheelEvent(event) #send to child item - #else: - event.ignore() #so the view scrolls or we zoom + #super().wheelEvent(event) #send to child item + #else: + event.ignore() #so the view scrolls or we zoom + def stretchXCoordinates(self, factor): """Reposition the items on the X axis. diff --git a/qtgui/scoreview.py b/qtgui/scoreview.py index 741de22..ee46e31 100644 --- a/qtgui/scoreview.py +++ b/qtgui/scoreview.py @@ -36,8 +36,8 @@ import engine.api as api class ScoreView(QtWidgets.QGraphicsView): def __init__(self, mainWindow): - super().__init__() - self.mainWindow = mainWindow + super().__init__() + self.mainWindow = mainWindow self.scoreScene = GuiScore(parentView=self) self.setScene(self.scoreScene) @@ -83,9 +83,9 @@ class ScoreView(QtWidgets.QGraphicsView): self.setStyleSheet(style) 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. - else: + else: super().wheelEvent(event) #send to scene def centerOnCursor(self, cursorExportObject): @@ -101,10 +101,10 @@ class ScoreView(QtWidgets.QGraphicsView): def stretchXCoordinates(self, factor): self.scoreScene.stretchXCoordinates(factor) self.centerOnCursor(None) - + def zoom(self, scaleFactor:float): - """Scale factor is absolute""" - self.resetTransform() + """Scale factor is absolute""" + self.resetTransform() self.scale(scaleFactor, scaleFactor) def toggleNoteheadsRectangles(self): @@ -144,7 +144,7 @@ class ScoreView(QtWidgets.QGraphicsView): raise ValueError("Edit Mode unknown") def resizeEvent(self, event): - self.scoreScene.grid.reactToresizeEventOrZoom() + #self.scoreScene.grid.reactToresizeEventOrZoom() super().resizeEvent(event) def changeGridRhythm(self): diff --git a/qtgui/submenus.py b/qtgui/submenus.py index 0e372fe..24fab5b 100644 --- a/qtgui/submenus.py +++ b/qtgui/submenus.py @@ -31,7 +31,7 @@ translate = QtCore.QCoreApplication.translate #Template import template.engine.pitch as pitch from template.qtgui.helper import QHLine -from template.qtgui.submenus import * +from template.qtgui.submenus import * #Our own files import engine.api as api @@ -380,7 +380,7 @@ class TransposeMenu(Submenu): self.fromNote = QtWidgets.QComboBox() self.fromNote.addItems(pitch.sortedNoteNameList) - + self.fromNote.setCurrentIndex(pitch.sortedNoteNameList.index("c'")) self.layout.addRow("from", self.fromNote) @@ -417,11 +417,11 @@ class SecondaryProperties(Submenu): importantKeys = ("title", "composer", "instrument", "copyright") #Draw important metadata widgets first - for k in importantKeys: + for k in importantKeys: self.layout.addRow(k.title(), self.widgets[k]) - + self.layout.addRow(QHLine()) - + #Then the rest in alphabetical order for key, widget in sorted(self.widgets.items()): if not key in importantKeys: @@ -452,7 +452,7 @@ class SecondaryProperties(Submenu): elif typ == QtWidgets.QSpinBox or typ == QtWidgets.QDoubleSpinBox: return widget.value() - def process(self): + def process(self): api.setMetadata({key:self.getValueFromWidget(widget) for key, widget in self.widgets.items()}) self.done(True) #Instance gets killed afterwards. No need to save the new values. @@ -471,7 +471,7 @@ class SecondaryProgramChangeMenu(Submenu): self.msb = QtWidgets.QSpinBox() self.msb.setValue(type(self).lastMsbValue) self.lsb = QtWidgets.QSpinBox() - self.lsb.setValue(type(self).lastLsbValue) + self.lsb.setValue(type(self).lastLsbValue) 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)): @@ -479,7 +479,7 @@ class SecondaryProgramChangeMenu(Submenu): spinbox.setMaximum(127) spinbox.setSingleStep(1) self.layout.addRow(label, spinbox) - + self.layout.addRow(translate("submenus", "Short Name"), self.shortInstrumentName) self.insert = QtWidgets.QPushButton(translate("submenus", "Insert")) @@ -544,8 +544,8 @@ class GridRhytmEdit(Submenu): def process(self): constantsAndConfigs.gridRhythm = self.duration.value() - constantsAndConfigs.gridOpacity = self.opacity.value() / 100 - api.session.guiSharedDataToSave["grid_opacity"] = constantsAndConfigs.gridOpacity + constantsAndConfigs.gridOpacity = self.opacity.value() / 100 + api.session.guiSharedDataToSave["grid_opacity"] = constantsAndConfigs.gridOpacity 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.done(True) @@ -572,15 +572,15 @@ def pedalNoteChooser(mainWindow): if v == rhythmString[0]: api.pedalNotes(baseDuration) -def forwardText(mainWindow, title, function): +def forwardText(mainWindow, title, function): text, status = QtWidgets.QInputDialog.getText(mainWindow, title, title) if status: function(text) - - - + + + diff --git a/qtgui/trackEditor.py b/qtgui/trackEditor.py index 1904323..aa3102f 100644 --- a/qtgui/trackEditor.py +++ b/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.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.midiBankMsbSpinBox.valueChanged.connect(self.dataChanged) self.ui.midiBankLsbSpinBox.valueChanged.connect(self.dataChanged) @@ -138,7 +138,7 @@ class TrackWidget(QtWidgets.QGroupBox): api.unhideTrack(self.trackExportObject["id"]) else: api.hideTrack(self.trackExportObject["id"]) - + def audibleToggled(self, signal): assert signal == bool(self.ui.audibleCheckbox.checkState()) api.trackAudible(self.trackExportObject["id"], signal) @@ -299,7 +299,7 @@ class TrackWidget(QtWidgets.QGroupBox): self.ui.doubleTrackCheckbox.setChecked(trackExportObject["double"]) 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. self.ccChannels[i+1].setChecked(i in trackExportObject["ccChannels"]) #a checkbox widget.