Browse Source

Add custom key signature command to build a free scale on any root

master
Nils 3 years ago
parent
commit
a0af825e5e
  1. 1
      CHANGELOG
  2. 26
      engine/api.py
  3. 20
      engine/items.py
  4. 249
      qtgui/customkeysignature.py
  5. 396
      qtgui/designer/customKeySignature.py
  6. 820
      qtgui/designer/customKeySignature.ui
  7. 14
      qtgui/designer/mainwindow.py
  8. 22
      qtgui/designer/mainwindow.ui
  9. 7
      qtgui/items.py
  10. 5
      qtgui/menu.py
  11. 2
      qtgui/tracklistwidget.py
  12. 64
      template/engine/pitch.py

1
CHANGELOG

@ -6,6 +6,7 @@ External contributors notice at the end of the line: (LastName, FirstName / nick
## 2022-07-15 2.1.0
New function: custom key signature for any combination.
Add two new functions to paste directly transposed (modal and real transposition)
When not in F4-StepInput Mode use midi keyboard as pitch-cursor.
Add midi-in selector drop down, as seen in Tembro and Fluajho.

26
engine/api.py

@ -524,7 +524,7 @@ def pasteObjects(customBuffer=None, updateCursor=True, overwriteSelection=True):
if updateCursor:
callbacks._setCursor()
def pasteObjectsTransposedReal(root:int=None, toPitch:int=None, adjustToKeySignature=False):
def pasteObjectsTransposedReal(root:int=None, toPitch:int=None, adjustToKeySignKeySignature=False):
"""Uses the global/session clipboard buffer but pastes a transposed version, starting on the
pitch cursor position, that is adjusted to the current keysignature.
@ -1070,6 +1070,12 @@ def getCursorSimpleLyNote():
lyNote = pitchmath.pitch2ly[pitch].strip("'").strip(",").lower()
return lyNote
def getCursorPlainNote():
"""get the cursor pitch as plain note, for usage in a keysig etc."""
root = pitchmath.plain(session.data.cursor.pitchindex)
keysig = session.data.currentTrack().state.keySignature()
pitchToInsert = pitchmath.toScale(root, keysig)
return pitchToInsert
def toPosition(position:int):
"""Move the cursor to this position in the current track. """
@ -1806,8 +1812,10 @@ def insertLegatoSlur():
#Key Signatures
def insertKeySignature(root:int, scheme:list, lilypondOverride:str=None):
keysig = items.KeySignature(pitchmath.plain(root), scheme)
"""Scheme is deviation from _a_ major scale, relative to the root note"""
keysig = items.KeySignature(root, scheme)
if lilypondOverride:
keysig.lilypondParameters["override"] = lilypondOverride
insertItem(keysig)
@ -1833,7 +1841,7 @@ def insertCommonKeySignature(root:int, scheme:str):
"""example:
insertCommonKeySignature(P_C, "Major")
"""
schemes = {
schemes = { #Scheme is deviation from _a_ major scale, relative to the root note
"Major": [0,0,0,0,0,0,0],
"Minor": [0,0,-10,0,0,-10,-10],
"Dorian": [0,0,-10,0,0,0,-10],
@ -1861,13 +1869,15 @@ def insertCursorCommonKeySignature(scheme:str):
into account.
Scheme is a string as seen in commonKeySignaturesAsList()
Scheme is deviation from _a_ major scale, relative to the root note
"""
if not scheme in commonKeySignaturesAsList():
raise ValueError("Unknown key signature scheme string: " + scheme)
root = pitchmath.plain(session.data.cursor.pitchindex)
keysig = session.data.currentTrack().state.keySignature()
pitchToInsert = pitchmath.toScale(session.data.cursor.pitchindex, keysig)
#pitchToInsert = pitchmath.toScale(session.data.cursor.pitchindex, keysig)
pitchToInsert = pitchmath.toScale(root, keysig)
insertCommonKeySignature(pitchToInsert, scheme)
@ -1934,6 +1944,14 @@ def insertCommonMetricalInstrucions(scheme):
}
insertMetricalInstruction(schemes[scheme], lilypondOverride = lilypond[scheme])
def metricalTest():
scheme = ((D4, D4, D4), D4, D4) # wrong. should be...
scheme = (D4, D4, D4, D4, D4) #... just this.
scheme = ((D4, D4), (D4, D4, D4)) #real 5/4 as 2+3
scheme = ( ((D4, D4), (D4, D4)), ((D4, D4, D4), (D4, D4)) ) #3 level 9/4
insertMetricalInstruction( scheme, lilypondOverride = "\\time 9/4" )
#Velocity and Dynamic Signatures
def insertDynamicSignature(keyword):
dynSig = items.DynamicSignature(keyword)

20
engine/items.py

@ -2066,7 +2066,7 @@ class KeySignature(Item):
G Major: KeySignature(220, [0, 0, 0, 10, 0, 0, 0])
Indian Scale ?: KeySignature(220, [0, -10, -20, 0, 0, -10, -20, 0]) #c, des, eeses, f, g, aes, beses, c
The input deviationFromMajorScale is transformed to an absolute
The input deviationFromMajorScale is a relative scale and transformed to an absolute
keysig, compatible with Lilypond, in init.
The result is saved permanently in self.keysigList in the following
@ -2093,7 +2093,7 @@ class KeySignature(Item):
def __init__(self, root, deviationFromMajorScale):
super().__init__()
assert root < 350 #really a plain note?
assert root < 350 #is it really a plain note?
assert pitchmath.plain(root) == root
self.root:int = root
self.deviationFromMajorScale = deviationFromMajorScale
@ -2141,6 +2141,7 @@ class KeySignature(Item):
self.keysigList = tuple(self.keysigList) #from list to tuple for hashing and caching
def hash(self):
return self.keysigList
@ -2445,7 +2446,15 @@ class TimeSignature(Item): #Deprecated since 1750
class MetricalInstruction(Item):
def __init__(self, treeOfInstructions, isMetrical = True):
"""Don't edit. Delete and create a new one"""
"""Don't edit. Delete and create a new one
A few examples, but this has a real explanation in the manual
5/4 as 3+2 ((D4, D4, D4), (D4, D4))
5/4 broken as 3 + 2 unstressed notes ((D4, D4, D4), D4, D4)
this should have been (D4, D4, D4, D4, D4)
"""
super().__init__()
for value in flatList(treeOfInstructions):
if not type(value) is int:
@ -2493,11 +2502,14 @@ class MetricalInstruction(Item):
return new
def asText(self):
if not self.lilypondParameters["override"]:
return "MetricalInstruction"
if self.lilypondParameters["override"] == "\\mark \"X\" \\cadenzaOn":
return "\\time X"
elif self.lilypondParameters["override"].startswith("\\cadenzaOff"):
return self.lilypondParameters["override"][12:]
elif self.lilypondParameters["override"]:
return self.lilypondParameters["override"]
else:
return "MetricalInstruction"

249
qtgui/customkeysignature.py

@ -0,0 +1,249 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2022, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
Laborejo2 is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging; logger = logging.getLogger(__name__); logger.info("import")
#Third Party
from PyQt5 import QtCore, QtGui, QtWidgets
#Template Modules
from template.engine.pitch import baseNotesToAccidentalNames, plain, intervalAutomatic, diatonicIndex
#Our Modules
from .designer.customKeySignature import Ui_customKeySignature
import engine.api as api
class CustomKeySignatureWidget(QtWidgets.QDialog):
def __init__(self, mainWindow):
"""Init is called everytime the dialog gets shown"""
super().__init__(mainWindow)
self.mainWindow = mainWindow
self.ui = Ui_customKeySignature()
self.ui.setupUi(self)
self.ui.buttonBox.accepted.connect(self.process)
self.ui.buttonBox.rejected.connect(self.reject)
currentCursorPitch = api.getCursorPlainNote()
self.resultLabels = (
self.ui.label_result_c,
self.ui.label_result_d,
self.ui.label_result_e,
self.ui.label_result_f,
self.ui.label_result_g,
self.ui.label_result_a,
self.ui.label_result_b,
)
self.rootNotes = {
20 : self.ui.root_c ,
70 : self.ui.root_d ,
120 : self.ui.root_e ,
170 : self.ui.root_f ,
220 : self.ui.root_g ,
270 : self.ui.root_a ,
320 : self.ui.root_b ,
10 : self.ui.root_ces ,
60 : self.ui.root_des ,
110 : self.ui.root_ees ,
160 : self.ui.root_fes ,
210 : self.ui.root_ges ,
260 : self.ui.root_aes ,
310 : self.ui.root_bes ,
30 : self.ui.root_cis ,
80: self.ui.root_dis ,
130 : self.ui.root_eis ,
180: self.ui.root_fis ,
230 : self.ui.root_gis ,
280: self.ui.root_ais ,
330 : self.ui.root_bis ,
}
#Add reverse lookup
self.buttonToRootNote = {}
for key, value in self.rootNotes.items():
self.buttonToRootNote[value] = key
self.rootNotes[currentCursorPitch].setChecked(True)
for button in self.rootNotes.values():
button.clicked.connect(self.sanityCheck)
### Scale Radio Buttons.
### Please note that the names are just shorthands because we create a relative scale here.
### Those really should be roman numerals for first note, second note, third etc. but this is cumbersome to write
self.scaleButtons = (
(
self.ui.isis_c ,
self.ui.is_c ,
self.ui.nat_c ,
self.ui.es_c ,
self.ui.eses_c ,
),
(
self.ui.isis_d ,
self.ui.is_d ,
self.ui.nat_d ,
self.ui.es_d ,
self.ui.eses_d ,
),
(
self.ui.isis_e ,
self.ui.is_e ,
self.ui.nat_e ,
self.ui.es_e ,
self.ui.eses_e ,
),
(
self.ui.isis_f ,
self.ui.is_f ,
self.ui.nat_f ,
self.ui.es_f ,
self.ui.eses_f ,
),
(
self.ui.isis_g ,
self.ui.is_g ,
self.ui.nat_g ,
self.ui.es_g ,
self.ui.eses_g ,
),
(
self.ui.isis_a ,
self.ui.is_a ,
self.ui.nat_a ,
self.ui.es_a ,
self.ui.eses_a ,
),
(
self.ui.isis_b ,
self.ui.is_b ,
self.ui.nat_b ,
self.ui.es_b ,
self.ui.eses_b ,
),
)
for group in self.scaleButtons:
group[2].setChecked(True) #Make natural the default.
for button in group:
button.setStyleSheet("QRadioButton { font : 18px }")
button.clicked.connect(self.sanityCheck)
self.exec() #blocks until the dialog gets closed
def blockSignals(self, state:bool):
for group in self.scaleButtons:
for button in group:
button.blockSignals(state)
for button in self.rootNotes.values():
button.blockSignals(state)
def findRootPitch(self)->int:
for rootButton, basePitch in self.buttonToRootNote.items():
if rootButton.isChecked():
return basePitch
else:
raise RuntimeError()
def groupToInScalePitch(self, groupIndex:int, checkSpecificStep:int=None):
selectedRootPitch = self.findRootPitch()
stepInCMajor = (groupIndex+1)*50 - 30
#The transposed interval scale is also major, of course.
stepInMajorRootScale = intervalAutomatic(originalPitch=stepInCMajor, rootPitch=20, targetPitch=selectedRootPitch)
if checkSpecificStep is None:
#find the accidental mod
group = self.scaleButtons[groupIndex]
for counter, button in enumerate(reversed(group)): #group is isis to eses, so we need to reverse.
if button.isChecked():
#counter remains
break
else:
counter = checkSpecificStep
mod = 10*counter-20 #offset by -20 because the scale starts at -20 for double flat but we enumerate from 0
#keysig = api.majorKeySignature(selectedRootPitch) #we deal with deviation from the major scale so we need the major scale for that root note
plainPitch = plain(stepInMajorRootScale + mod)
pitchOk = diatonicIndex(stepInMajorRootScale) == diatonicIndex(plainPitch) #did we cross a diatonic note boundary? That means this was a triple accidental
return plainPitch, pitchOk
def sanityCheck(self, buttonChecked:bool):
"""Called after every change to the whole widget.
Recalculates note names and checks if any of the steps result in triple accidentals.
We choose signal:clicked because signal:toggled triggers this signal twice because
for each radio toggle another radio button get's deactivated automatically."""
for groupIndex, group in enumerate(self.scaleButtons):
#Sanity check. Check for triple accidentals
for counter, button in enumerate(reversed(group)):
plainPitch, pitchOk = self.groupToInScalePitch(groupIndex, counter)
if pitchOk:
button.setEnabled(True)
else:
button.setEnabled(False)
if button.isChecked():
button.setChecked(False) #setChecked does NOT activate the clicked signal. We are safe from recursive calls.
group[2].setChecked(True) #Activate natural as fallback
#Calculate Labels
plainPitch, pitchOk = self.groupToInScalePitch(groupIndex)
assert pitchOk
self.resultLabels[groupIndex].setText(baseNotesToAccidentalNames[plainPitch])
def process(self):
selectedRootPitch = self.findRootPitch()
#Gather selected scale into engine scale list, which is the deviation from the major scale.
#THIS IS A RELATIVE SCALE, not accidentals for notes. The GUI shows roman numerals for scale building, not note names.
#-20 is double flat, -10 is flat, 0 is natural, 10 is sharp, 20 is double sharp
#self.scaleButtons is semi-correctly ordered: ascending scale (outer list) but from double sharp to double flat (inner list). we reverse the latter
deviationFromMajorScale = []
for group in self.scaleButtons:
for counter, button in enumerate(reversed(group)):
if button.isChecked():
deviationFromMajorScale.append(10*counter -20)
api.insertKeySignature(root=selectedRootPitch, scheme=deviationFromMajorScale)
self.done(True)

396
qtgui/designer/customKeySignature.py

@ -0,0 +1,396 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'customKeySignature.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_customKeySignature(object):
def setupUi(self, customKeySignature):
customKeySignature.setObjectName("customKeySignature")
customKeySignature.resize(517, 533)
self.verticalLayout_8 = QtWidgets.QVBoxLayout(customKeySignature)
self.verticalLayout_8.setSpacing(12)
self.verticalLayout_8.setObjectName("verticalLayout_8")
self.keysig_instruction_label = QtWidgets.QLabel(customKeySignature)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.keysig_instruction_label.sizePolicy().hasHeightForWidth())
self.keysig_instruction_label.setSizePolicy(sizePolicy)
self.keysig_instruction_label.setWordWrap(True)
self.keysig_instruction_label.setObjectName("keysig_instruction_label")
self.verticalLayout_8.addWidget(self.keysig_instruction_label)
self.group_root = QtWidgets.QGroupBox(customKeySignature)
self.group_root.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.group_root.setObjectName("group_root")
self.gridLayout = QtWidgets.QGridLayout(self.group_root)
self.gridLayout.setObjectName("gridLayout")
self.root_dis = QtWidgets.QRadioButton(self.group_root)
self.root_dis.setObjectName("root_dis")
self.gridLayout.addWidget(self.root_dis, 4, 1, 1, 1)
self.root_des = QtWidgets.QRadioButton(self.group_root)
self.root_des.setObjectName("root_des")
self.gridLayout.addWidget(self.root_des, 2, 1, 1, 1)
self.root_ees = QtWidgets.QRadioButton(self.group_root)
self.root_ees.setObjectName("root_ees")
self.gridLayout.addWidget(self.root_ees, 2, 2, 1, 1)
self.root_b = QtWidgets.QRadioButton(self.group_root)
self.root_b.setObjectName("root_b")
self.gridLayout.addWidget(self.root_b, 0, 6, 1, 1)
self.root_fes = QtWidgets.QRadioButton(self.group_root)
self.root_fes.setObjectName("root_fes")
self.gridLayout.addWidget(self.root_fes, 2, 3, 1, 1)
self.root_f = QtWidgets.QRadioButton(self.group_root)
self.root_f.setObjectName("root_f")
self.gridLayout.addWidget(self.root_f, 0, 3, 1, 1)
self.root_eis = QtWidgets.QRadioButton(self.group_root)
self.root_eis.setObjectName("root_eis")
self.gridLayout.addWidget(self.root_eis, 4, 2, 1, 1)
self.root_gis = QtWidgets.QRadioButton(self.group_root)
self.root_gis.setObjectName("root_gis")
self.gridLayout.addWidget(self.root_gis, 4, 4, 1, 1)
self.root_bes = QtWidgets.QRadioButton(self.group_root)
self.root_bes.setObjectName("root_bes")
self.gridLayout.addWidget(self.root_bes, 2, 6, 1, 1)
self.root_d = QtWidgets.QRadioButton(self.group_root)
self.root_d.setObjectName("root_d")
self.gridLayout.addWidget(self.root_d, 0, 1, 1, 1)
self.root_fis = QtWidgets.QRadioButton(self.group_root)
self.root_fis.setObjectName("root_fis")
self.gridLayout.addWidget(self.root_fis, 4, 3, 1, 1)
self.root_g = QtWidgets.QRadioButton(self.group_root)
self.root_g.setObjectName("root_g")
self.gridLayout.addWidget(self.root_g, 0, 4, 1, 1)
self.root_ces = QtWidgets.QRadioButton(self.group_root)
self.root_ces.setObjectName("root_ces")
self.gridLayout.addWidget(self.root_ces, 2, 0, 1, 1)
self.root_ais = QtWidgets.QRadioButton(self.group_root)
self.root_ais.setObjectName("root_ais")
self.gridLayout.addWidget(self.root_ais, 4, 5, 1, 1)
self.root_ges = QtWidgets.QRadioButton(self.group_root)
self.root_ges.setObjectName("root_ges")
self.gridLayout.addWidget(self.root_ges, 2, 4, 1, 1)
self.root_cis = QtWidgets.QRadioButton(self.group_root)
self.root_cis.setObjectName("root_cis")
self.gridLayout.addWidget(self.root_cis, 4, 0, 1, 1)
self.root_a = QtWidgets.QRadioButton(self.group_root)
self.root_a.setObjectName("root_a")
self.gridLayout.addWidget(self.root_a, 0, 5, 1, 1)
self.root_c = QtWidgets.QRadioButton(self.group_root)
self.root_c.setChecked(True)
self.root_c.setObjectName("root_c")
self.gridLayout.addWidget(self.root_c, 0, 0, 1, 1)
self.root_e = QtWidgets.QRadioButton(self.group_root)
self.root_e.setObjectName("root_e")
self.gridLayout.addWidget(self.root_e, 0, 2, 1, 1)
self.root_aes = QtWidgets.QRadioButton(self.group_root)
self.root_aes.setObjectName("root_aes")
self.gridLayout.addWidget(self.root_aes, 2, 5, 1, 1)
self.root_bis = QtWidgets.QRadioButton(self.group_root)
self.root_bis.setObjectName("root_bis")
self.gridLayout.addWidget(self.root_bis, 4, 6, 1, 1)
self.verticalLayout_8.addWidget(self.group_root)
self.group_accidentals = QtWidgets.QGroupBox(customKeySignature)
self.group_accidentals.setObjectName("group_accidentals")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.group_accidentals)
self.horizontalLayout.setObjectName("horizontalLayout")
self.group_c = QtWidgets.QGroupBox(self.group_accidentals)
self.group_c.setAlignment(QtCore.Qt.AlignCenter)
self.group_c.setObjectName("group_c")
self.verticalLayout = QtWidgets.QVBoxLayout(self.group_c)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
self.isis_c = QtWidgets.QRadioButton(self.group_c)
self.isis_c.setObjectName("isis_c")
self.verticalLayout.addWidget(self.isis_c)
self.is_c = QtWidgets.QRadioButton(self.group_c)
self.is_c.setObjectName("is_c")
self.verticalLayout.addWidget(self.is_c)
self.nat_c = QtWidgets.QRadioButton(self.group_c)
self.nat_c.setChecked(True)
self.nat_c.setObjectName("nat_c")
self.verticalLayout.addWidget(self.nat_c)
self.es_c = QtWidgets.QRadioButton(self.group_c)
self.es_c.setObjectName("es_c")
self.verticalLayout.addWidget(self.es_c)
self.eses_c = QtWidgets.QRadioButton(self.group_c)
self.eses_c.setObjectName("eses_c")
self.verticalLayout.addWidget(self.eses_c)
spacerItem = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.verticalLayout.addItem(spacerItem)
self.label_result_c = QtWidgets.QLabel(self.group_c)
self.label_result_c.setAlignment(QtCore.Qt.AlignCenter)
self.label_result_c.setObjectName("label_result_c")
self.verticalLayout.addWidget(self.label_result_c)
self.horizontalLayout.addWidget(self.group_c)
self.groupd_d = QtWidgets.QGroupBox(self.group_accidentals)
self.groupd_d.setAlignment(QtCore.Qt.AlignCenter)
self.groupd_d.setObjectName("groupd_d")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupd_d)
self.verticalLayout_2.setSpacing(0)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.isis_d = QtWidgets.QRadioButton(self.groupd_d)
self.isis_d.setObjectName("isis_d")
self.verticalLayout_2.addWidget(self.isis_d)
self.is_d = QtWidgets.QRadioButton(self.groupd_d)
self.is_d.setObjectName("is_d")
self.verticalLayout_2.addWidget(self.is_d)
self.nat_d = QtWidgets.QRadioButton(self.groupd_d)
self.nat_d.setChecked(True)
self.nat_d.setObjectName("nat_d")
self.verticalLayout_2.addWidget(self.nat_d)
self.es_d = QtWidgets.QRadioButton(self.groupd_d)
self.es_d.setObjectName("es_d")
self.verticalLayout_2.addWidget(self.es_d)
self.eses_d = QtWidgets.QRadioButton(self.groupd_d)
self.eses_d.setObjectName("eses_d")
self.verticalLayout_2.addWidget(self.eses_d)
spacerItem1 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.verticalLayout_2.addItem(spacerItem1)
self.label_result_d = QtWidgets.QLabel(self.groupd_d)
self.label_result_d.setAlignment(QtCore.Qt.AlignCenter)
self.label_result_d.setObjectName("label_result_d")
self.verticalLayout_2.addWidget(self.label_result_d)
self.horizontalLayout.addWidget(self.groupd_d)
self.group_e = QtWidgets.QGroupBox(self.group_accidentals)
self.group_e.setAlignment(QtCore.Qt.AlignCenter)
self.group_e.setObjectName("group_e")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.group_e)
self.verticalLayout_3.setSpacing(0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.isis_e = QtWidgets.QRadioButton(self.group_e)
self.isis_e.setObjectName("isis_e")
self.verticalLayout_3.addWidget(self.isis_e)
self.is_e = QtWidgets.QRadioButton(self.group_e)
self.is_e.setObjectName("is_e")
self.verticalLayout_3.addWidget(self.is_e)
self.nat_e = QtWidgets.QRadioButton(self.group_e)
self.nat_e.setChecked(True)
self.nat_e.setObjectName("nat_e")
self.verticalLayout_3.addWidget(self.nat_e)
self.es_e = QtWidgets.QRadioButton(self.group_e)
self.es_e.setObjectName("es_e")
self.verticalLayout_3.addWidget(self.es_e)
self.eses_e = QtWidgets.QRadioButton(self.group_e)
self.eses_e.setObjectName("eses_e")
self.verticalLayout_3.addWidget(self.eses_e)
spacerItem2 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.verticalLayout_3.addItem(spacerItem2)
self.label_result_e = QtWidgets.QLabel(self.group_e)
self.label_result_e.setAlignment(QtCore.Qt.AlignCenter)
self.label_result_e.setObjectName("label_result_e")
self.verticalLayout_3.addWidget(self.label_result_e)
self.horizontalLayout.addWidget(self.group_e)
self.group_f = QtWidgets.QGroupBox(self.group_accidentals)
self.group_f.setAlignment(QtCore.Qt.AlignCenter)
self.group_f.setObjectName("group_f")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.group_f)
self.verticalLayout_5.setSpacing(0)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.isis_f = QtWidgets.QRadioButton(self.group_f)
self.isis_f.setObjectName("isis_f")
self.verticalLayout_5.addWidget(self.isis_f)
self.is_f = QtWidgets.QRadioButton(self.group_f)
self.is_f.setObjectName("is_f")
self.verticalLayout_5.addWidget(self.is_f)
self.nat_f = QtWidgets.QRadioButton(self.group_f)
self.nat_f.setChecked(True)
self.nat_f.setObjectName("nat_f")
self.verticalLayout_5.addWidget(self.nat_f)
self.es_f = QtWidgets.QRadioButton(self.group_f)
self.es_f.setObjectName("es_f")
self.verticalLayout_5.addWidget(self.es_f)
self.eses_f = QtWidgets.QRadioButton(self.group_f)
self.eses_f.setObjectName("eses_f")
self.verticalLayout_5.addWidget(self.eses_f)
spacerItem3 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.verticalLayout_5.addItem(spacerItem3)
self.label_result_f = QtWidgets.QLabel(self.group_f)
self.label_result_f.setAlignment(QtCore.Qt.AlignCenter)
self.label_result_f.setObjectName("label_result_f")
self.verticalLayout_5.addWidget(self.label_result_f)
self.horizontalLayout.addWidget(self.group_f)
self.group_g = QtWidgets.QGroupBox(self.group_accidentals)
self.group_g.setAlignment(QtCore.Qt.AlignCenter)
self.group_g.setObjectName("group_g")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.group_g)
self.verticalLayout_6.setSpacing(0)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.isis_g = QtWidgets.QRadioButton(self.group_g)
self.isis_g.setObjectName("isis_g")
self.verticalLayout_6.addWidget(self.isis_g)
self.is_g = QtWidgets.QRadioButton(self.group_g)
self.is_g.setObjectName("is_g")
self.verticalLayout_6.addWidget(self.is_g)
self.nat_g = QtWidgets.QRadioButton(self.group_g)
self.nat_g.setChecked(True)
self.nat_g.setObjectName("nat_g")
self.verticalLayout_6.addWidget(self.nat_g)
self.es_g = QtWidgets.QRadioButton(self.group_g)
self.es_g.setObjectName("es_g")
self.verticalLayout_6.addWidget(self.es_g)
self.eses_g = QtWidgets.QRadioButton(self.group_g)
self.eses_g.setObjectName("eses_g")
self.verticalLayout_6.addWidget(self.eses_g)
spacerItem4 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.verticalLayout_6.addItem(spacerItem4)
self.label_result_g = QtWidgets.QLabel(self.group_g)
self.label_result_g.setAlignment(QtCore.Qt.AlignCenter)
self.label_result_g.setObjectName("label_result_g")
self.verticalLayout_6.addWidget(self.label_result_g)
self.horizontalLayout.addWidget(self.group_g)
self.group_a = QtWidgets.QGroupBox(self.group_accidentals)
self.group_a.setAlignment(QtCore.Qt.AlignCenter)
self.group_a.setObjectName("group_a")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.group_a)
self.verticalLayout_4.setSpacing(0)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.isis_a = QtWidgets.QRadioButton(self.group_a)
self.isis_a.setObjectName("isis_a")
self.verticalLayout_4.addWidget(self.isis_a)
self.is_a = QtWidgets.QRadioButton(self.group_a)
self.is_a.setObjectName("is_a")
self.verticalLayout_4.addWidget(self.is_a)
self.nat_a = QtWidgets.QRadioButton(self.group_a)
self.nat_a.setChecked(True)
self.nat_a.setObjectName("nat_a")
self.verticalLayout_4.addWidget(self.nat_a)
self.es_a = QtWidgets.QRadioButton(self.group_a)
self.es_a.setObjectName("es_a")
self.verticalLayout_4.addWidget(self.es_a)
self.eses_a = QtWidgets.QRadioButton(self.group_a)
self.eses_a.setObjectName("eses_a")
self.verticalLayout_4.addWidget(self.eses_a)
spacerItem5 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.verticalLayout_4.addItem(spacerItem5)
self.label_result_a = QtWidgets.QLabel(self.group_a)
self.label_result_a.setAlignment(QtCore.Qt.AlignCenter)
self.label_result_a.setObjectName("label_result_a")
self.verticalLayout_4.addWidget(self.label_result_a)
self.horizontalLayout.addWidget(self.group_a)
self.group_b = QtWidgets.QGroupBox(self.group_accidentals)
self.group_b.setAlignment(QtCore.Qt.AlignCenter)
self.group_b.setObjectName("group_b")
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.group_b)
self.verticalLayout_7.setSpacing(0)
self.verticalLayout_7.setObjectName("verticalLayout_7")
self.isis_b = QtWidgets.QRadioButton(self.group_b)
self.isis_b.setObjectName("isis_b")
self.verticalLayout_7.addWidget(self.isis_b)
self.is_b = QtWidgets.QRadioButton(self.group_b)
self.is_b.setObjectName("is_b")
self.verticalLayout_7.addWidget(self.is_b)
self.nat_b = QtWidgets.QRadioButton(self.group_b)
self.nat_b.setChecked(True)
self.nat_b.setObjectName("nat_b")
self.verticalLayout_7.addWidget(self.nat_b)
self.es_b = QtWidgets.QRadioButton(self.group_b)
self.es_b.setObjectName("es_b")
self.verticalLayout_7.addWidget(self.es_b)
self.eses_b = QtWidgets.QRadioButton(self.group_b)
self.eses_b.setObjectName("eses_b")
self.verticalLayout_7.addWidget(self.eses_b)
spacerItem6 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.verticalLayout_7.addItem(spacerItem6)
self.label_result_b = QtWidgets.QLabel(self.group_b)
self.label_result_b.setAlignment(QtCore.Qt.AlignCenter)
self.label_result_b.setObjectName("label_result_b")
self.verticalLayout_7.addWidget(self.label_result_b)
self.horizontalLayout.addWidget(self.group_b)
self.verticalLayout_8.addWidget(self.group_accidentals)
self.buttonBox = QtWidgets.QDialogButtonBox(customKeySignature)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout_8.addWidget(self.buttonBox)
spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_8.addItem(spacerItem7)
self.retranslateUi(customKeySignature)
self.buttonBox.accepted.connect(customKeySignature.accept) # type: ignore
self.buttonBox.rejected.connect(customKeySignature.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(customKeySignature)
def retranslateUi(self, customKeySignature):
_translate = QtCore.QCoreApplication.translate
customKeySignature.setWindowTitle(_translate("customKeySignature", "Custom Key Signature"))
self.keysig_instruction_label.setText(_translate("customKeySignature", "<html><head/><body><p>Design your own scale. The key signature will be calculated. Choose a root note and how each step deviates from it\'s major scale. E.g. leaving all switches on &quot;natural&quot; will result in the major scale. Setting step III to flat will result in &quot;melodic minor&quot;.</p><p>Not all combinations are possible: e.g. root G with step VII double sharp. <br/>G-Major\'s &quot;natural&quot; VII is already f-sharp, thus choosing a normal sharp already results in a key signature with a double sharp &quot;cross&quot;. Switching VII to double sharp would result in a &quot;triple sharp&quot; key signature.<br/></p></body></html>"))
self.group_root.setTitle(_translate("customKeySignature", "Root Note"))
self.root_dis.setText(_translate("customKeySignature", "D♯"))
self.root_des.setText(_translate("customKeySignature", "D♭"))
self.root_ees.setText(_translate("customKeySignature", "E♭"))
self.root_b.setText(_translate("customKeySignature", "B / H"))
self.root_fes.setText(_translate("customKeySignature", "F♭"))
self.root_f.setText(_translate("customKeySignature", "F"))
self.root_eis.setText(_translate("customKeySignature", "E♯"))
self.root_gis.setText(_translate("customKeySignature", "G♯"))
self.root_bes.setText(_translate("customKeySignature", "B♭ / H♭"))
self.root_d.setText(_translate("customKeySignature", "D"))
self.root_fis.setText(_translate("customKeySignature", "F♯"))
self.root_g.setText(_translate("customKeySignature", "G"))
self.root_ces.setText(_translate("customKeySignature", "C♭"))
self.root_ais.setText(_translate("customKeySignature", "A♯"))
self.root_ges.setText(_translate("customKeySignature", "G♭"))
self.root_cis.setText(_translate("customKeySignature", "C♯"))
self.root_a.setText(_translate("customKeySignature", "A"))
self.root_c.setText(_translate("customKeySignature", "C"))
self.root_e.setText(_translate("customKeySignature", "E"))
self.root_aes.setText(_translate("customKeySignature", "A♭"))
self.root_bis.setText(_translate("customKeySignature", "B♯ / H♯"))
self.group_accidentals.setTitle(_translate("customKeySignature", "Scale - Deviation from the Major Scale"))
self.group_c.setTitle(_translate("customKeySignature", ""))
self.isis_c.setText(_translate("customKeySignature", "𝄪"))
self.is_c.setText(_translate("customKeySignature", ""))
self.nat_c.setText(_translate("customKeySignature", ""))
self.es_c.setText(_translate("customKeySignature", ""))
self.eses_c.setText(_translate("customKeySignature", "𝄫"))
self.label_result_c.setText(_translate("customKeySignature", "c"))
self.groupd_d.setTitle(_translate("customKeySignature", ""))
self.isis_d.setText(_translate("customKeySignature", "𝄪"))
self.is_d.setText(_translate("customKeySignature", ""))
self.nat_d.setText(_translate("customKeySignature", ""))
self.es_d.setText(_translate("customKeySignature", ""))
self.eses_d.setText(_translate("customKeySignature", "𝄫"))
self.label_result_d.setText(_translate("customKeySignature", "d"))
self.group_e.setTitle(_translate("customKeySignature", ""))
self.isis_e.setText(_translate("customKeySignature", "𝄪"))
self.is_e.setText(_translate("customKeySignature", ""))
self.nat_e.setText(_translate("customKeySignature", ""))
self.es_e.setText(_translate("customKeySignature", ""))
self.eses_e.setText(_translate("customKeySignature", "𝄫"))
self.label_result_e.setText(_translate("customKeySignature", "e"))
self.group_f.setTitle(_translate("customKeySignature", ""))
self.isis_f.setText(_translate("customKeySignature", "𝄪"))
self.is_f.setText(_translate("customKeySignature", ""))
self.nat_f.setText(_translate("customKeySignature", ""))
self.es_f.setText(_translate("customKeySignature", ""))
self.eses_f.setText(_translate("customKeySignature", "𝄫"))
self.label_result_f.setText(_translate("customKeySignature", "f"))
self.group_g.setTitle(_translate("customKeySignature", ""))
self.isis_g.setText(_translate("customKeySignature", "𝄪"))
self.is_g.setText(_translate("customKeySignature", ""))
self.nat_g.setText(_translate("customKeySignature", ""))
self.es_g.setText(_translate("customKeySignature", ""))
self.eses_g.setText(_translate("customKeySignature", "𝄫"))
self.label_result_g.setText(_translate("customKeySignature", "g"))
self.group_a.setTitle(_translate("customKeySignature", ""))
self.isis_a.setText(_translate("customKeySignature", "𝄪"))
self.is_a.setText(_translate("customKeySignature", ""))
self.nat_a.setText(_translate("customKeySignature", ""))
self.es_a.setText(_translate("customKeySignature", ""))
self.eses_a.setText(_translate("customKeySignature", "𝄫"))
self.label_result_a.setText(_translate("customKeySignature", "a"))
self.group_b.setTitle(_translate("customKeySignature", ""))
self.isis_b.setText(_translate("customKeySignature", "𝄪"))
self.is_b.setText(_translate("customKeySignature", ""))
self.nat_b.setText(_translate("customKeySignature", ""))
self.es_b.setText(_translate("customKeySignature", ""))
self.eses_b.setText(_translate("customKeySignature", "𝄫"))
self.label_result_b.setText(_translate("customKeySignature", "b"))

820
qtgui/designer/customKeySignature.ui

@ -0,0 +1,820 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>customKeySignature</class>
<widget class="QDialog" name="customKeySignature">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>517</width>
<height>533</height>
</rect>
</property>
<property name="windowTitle">
<string>Custom Key Signature</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="spacing">
<number>12</number>
</property>
<item>
<widget class="QLabel" name="keysig_instruction_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Design your own scale. The key signature will be calculated. Choose a root note and how each step deviates from it's major scale. E.g. leaving all switches on &amp;quot;natural&amp;quot; will result in the major scale. Setting step III to flat will result in &amp;quot;melodic minor&amp;quot;.&lt;/p&gt;&lt;p&gt;Not all combinations are possible: e.g. root G with step VII double sharp. &lt;br/&gt;G-Major's &amp;quot;natural&amp;quot; VII is already f-sharp, thus choosing a normal sharp already results in a key signature with a double sharp &amp;quot;cross&amp;quot;. Switching VII to double sharp would result in a &amp;quot;triple sharp&amp;quot; key signature.&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="group_root">
<property name="title">
<string>Root Note</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="1">
<widget class="QRadioButton" name="root_dis">
<property name="text">
<string>D♯</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="root_des">
<property name="text">
<string>D♭</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QRadioButton" name="root_ees">
<property name="text">
<string>E♭</string>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QRadioButton" name="root_b">
<property name="text">
<string>B / H</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QRadioButton" name="root_fes">
<property name="text">
<string>F♭</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QRadioButton" name="root_f">
<property name="text">
<string>F</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QRadioButton" name="root_eis">
<property name="text">
<string>E♯</string>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QRadioButton" name="root_gis">
<property name="text">
<string>G♯</string>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QRadioButton" name="root_bes">
<property name="text">
<string>B♭ / H♭</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="root_d">
<property name="text">
<string>D</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QRadioButton" name="root_fis">
<property name="text">
<string>F♯</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QRadioButton" name="root_g">
<property name="text">
<string>G</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="root_ces">
<property name="text">
<string>C♭</string>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QRadioButton" name="root_ais">
<property name="text">
<string>A♯</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QRadioButton" name="root_ges">
<property name="text">
<string>G♭</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QRadioButton" name="root_cis">
<property name="text">
<string>C♯</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QRadioButton" name="root_a">
<property name="text">
<string>A</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="root_c">
<property name="text">
<string>C</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QRadioButton" name="root_e">
<property name="text">
<string>E</string>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QRadioButton" name="root_aes">
<property name="text">
<string>A♭</string>
</property>
</widget>
</item>
<item row="4" column="6">
<widget class="QRadioButton" name="root_bis">
<property name="text">
<string>B♯ / H♯</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="group_accidentals">
<property name="title">
<string>Scale - Deviation from the Major Scale</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="group_c">
<property name="title">
<string>Ⅰ</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="isis_c">
<property name="text">
<string>𝄪</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="is_c">
<property name="text">
<string>♯</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="nat_c">
<property name="text">
<string>♮</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="es_c">
<property name="text">
<string>♭</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="eses_c">
<property name="text">
<string>𝄫</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_result_c">
<property name="text">
<string>c</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupd_d">
<property name="title">
<string>Ⅱ</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="isis_d">
<property name="text">
<string>𝄪</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="is_d">
<property name="text">
<string>♯</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="nat_d">
<property name="text">
<string>♮</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="es_d">
<property name="text">
<string>♭</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="eses_d">
<property name="text">
<string>𝄫</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_result_d">
<property name="text">
<string>d</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="group_e">
<property name="title">
<string>Ⅲ</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="isis_e">
<property name="text">
<string>𝄪</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="is_e">
<property name="text">
<string>♯</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="nat_e">
<property name="text">
<string>♮</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="es_e">
<property name="text">
<string>♭</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="eses_e">
<property name="text">
<string>𝄫</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_result_e">
<property name="text">
<string>e</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="group_f">
<property name="title">
<string>Ⅳ</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="isis_f">
<property name="text">
<string>𝄪</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="is_f">
<property name="text">
<string>♯</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="nat_f">
<property name="text">
<string>♮</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="es_f">
<property name="text">
<string>♭</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="eses_f">
<property name="text">
<string>𝄫</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_result_f">
<property name="text">
<string>f</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="group_g">
<property name="title">
<string>Ⅴ</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="isis_g">
<property name="text">
<string>𝄪</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="is_g">
<property name="text">
<string>♯</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="nat_g">
<property name="text">
<string>♮</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="es_g">
<property name="text">
<string>♭</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="eses_g">
<property name="text">
<string>𝄫</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_result_g">
<property name="text">
<string>g</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="group_a">
<property name="title">
<string>Ⅵ</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="isis_a">
<property name="text">
<string>𝄪</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="is_a">
<property name="text">
<string>♯</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="nat_a">
<property name="text">
<string>♮</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="es_a">
<property name="text">
<string>♭</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="eses_a">
<property name="text">
<string>𝄫</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_result_a">
<property name="text">
<string>a</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="group_b">
<property name="title">
<string>Ⅶ</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="isis_b">
<property name="text">
<string>𝄪</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="is_b">
<property name="text">
<string>♯</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="nat_b">
<property name="text">
<string>♮</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="es_b">
<property name="text">
<string>♭</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="eses_b">
<property name="text">
<string>𝄫</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_8">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_result_b">
<property name="text">
<string>b</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok&l