Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions tests/ui/timelines/harmony/test_harmony_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,28 @@ def test_right_click(self, tlui):
exec_mock.assert_called_once()


class TestInversionClamp:
def test_letter_symbol_does_not_crash_when_quality_loses_inversion(self, tlui):
harmony, _ = tlui.create_harmony(0, quality="dominant-seventh", inversion=3)
tlui.timeline.set_component_data(harmony.id, "quality", "major")
# Pre-fix: music21.chord.ChordException — no 3rd inversion on triad.
_ = tlui.get_element(harmony.id).letter_symbol

def test_roman_numeral_label_does_not_crash_when_quality_loses_inversion(
self, tlui
):
harmony, _ = tlui.create_harmony(0, quality="dominant-seventh", inversion=3)
tlui.timeline.set_component_data(harmony.id, "quality", "major")
_ = tlui.get_element(harmony.id).roman_numeral_label

def test_letter_symbol_label_omits_dropped_inversion(self, tlui):
harmony, _ = tlui.create_harmony(0, quality="dominant-seventh", inversion=3)
tlui.timeline.set_component_data(harmony.id, "quality", "major")
# Major triad max inversion is 2, so the 3rd-inversion suffix
# (INVERSION_TO_INTERVAL[3] == 7) must not appear in the label.
assert "/&7" not in tlui.get_element(harmony.id).letter_symbol_label


class TestCopyPaste:
def test_paste_single_into_timeline(self, tlui, tilia_state):
_, hui = tlui.create_harmony(0)
Expand Down
14 changes: 11 additions & 3 deletions tilia/ui/timelines/harmony/elements/harmony.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from PySide6.QtWidgets import QGraphicsItem, QGraphicsTextItem

from tilia.requests import Get, Post, get, post
from tilia.timelines.harmony.constants import get_inversion_amount
from tilia.ui.coords import time_x_converter
from tilia.ui.timelines.base.element import TimelineUIElement
from tilia.ui.timelines.drag import DragManager
Expand Down Expand Up @@ -69,6 +70,13 @@ def font_type(self):
def key(self):
return self.timeline_ui.get_key_by_time(self.get_data("time"))

@property
def clamped_inversion(self):
return min(
self.get_data("inversion"),
get_inversion_amount(self.get_data("quality")),
)

@property
def letter_symbol(self):
symbol = music21.harmony.ChordSymbol(
Expand All @@ -78,7 +86,7 @@ def letter_symbol(self):
self.get_data("accidental"),
)
+ QUALITY_TO_ABBREVIATION[self.get_data("quality")],
inversion=self.get_data("inversion"),
inversion=self.clamped_inversion,
)
applied_to = self.get_data("applied_to")
if applied_to:
Expand Down Expand Up @@ -119,7 +127,7 @@ def roman_numeral_label(self):
self.get_data("quality"),
self.key,
self.get_data("applied_to"),
self.get_data("inversion"),
self.clamped_inversion,
)

@property
Expand Down Expand Up @@ -150,7 +158,7 @@ def letter_symbol_label(self):
case 2:
figure = figure.replace("##", "`#`#")

if inversion := self.get_data("inversion"):
if inversion := self.clamped_inversion:
# bass_step = harmony.calculate.bass_step(self.get_data('step'), inversion)
# figure += '/' + INT_TO_NOTE_NAME[bass_step] # TODO calculate bass note
figure += "/&" + str(INVERSION_TO_INTERVAL[inversion])
Expand Down
Loading