From af35f15d1e687a5022f6ded952919b32910f5ece Mon Sep 17 00:00:00 2001 From: melancholytron Date: Wed, 10 Sep 2025 09:12:26 -0500 Subject: [PATCH] Fix comprehensive GUI sync for all parameters including delay controls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add complete delay system sync: toggle button, timing buttons, length, fade - Add root note and octave button updates from engine state - Add distribution pattern button sync - Fix delay timing button enable/disable states and styling - Add scale notes display update when root/octave changes - Ensure all delay controls properly enable/disable based on delay state - Fix missing delay fade value label updates Now all GUI controls should properly reflect engine state on startup and preset changes. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- gui/arpeggiator_controls.py | 97 ++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 2 deletions(-) diff --git a/gui/arpeggiator_controls.py b/gui/arpeggiator_controls.py index d7d8769..5bff8b3 100644 --- a/gui/arpeggiator_controls.py +++ b/gui/arpeggiator_controls.py @@ -1125,6 +1125,39 @@ class ArpeggiatorControls(QWidget): def update_gui_from_engine(self): """Update all GUI controls to match engine settings""" try: + # Update root note and octave buttons + if hasattr(self, 'root_note_buttons') and hasattr(self.arpeggiator, 'root_note'): + # Extract root note and octave from MIDI note + midi_note = self.arpeggiator.root_note + octave = midi_note // 12 + note_index = midi_note % 12 + + # Update root note buttons + if self.current_root_note in self.root_note_buttons: + self.apply_button_style(self.root_note_buttons[self.current_root_note], 12, "normal") + self.current_root_note = note_index + if note_index in self.root_note_buttons: + self.apply_button_style(self.root_note_buttons[note_index], 12, "active") + + # Update octave buttons + if hasattr(self, 'octave_buttons') and self.current_octave in self.octave_buttons: + self.apply_button_style(self.octave_buttons[self.current_octave], 12, "normal") + self.current_octave = octave + if octave in self.octave_buttons: + self.apply_button_style(self.octave_buttons[octave], 12, "active") + + # Update scale notes display when root note/octave changes + self.update_scale_notes_display() + + # Update distribution buttons + if hasattr(self, 'distribution_buttons') and hasattr(self.arpeggiator, 'channel_distribution'): + # Clear current distribution styling + if self.current_distribution in self.distribution_buttons: + self.apply_button_style(self.distribution_buttons[self.current_distribution], 12, "normal") + # Set new active distribution + self.current_distribution = self.arpeggiator.channel_distribution + if self.current_distribution in self.distribution_buttons: + self.apply_button_style(self.distribution_buttons[self.current_distribution], 12, "active") # Update scale buttons if hasattr(self, 'scale_buttons'): # Clear current scale styling @@ -1188,12 +1221,72 @@ class ArpeggiatorControls(QWidget): self.apply_button_style(self.note_limit_buttons[self.current_note_limit], 12, "blue") # Update delay controls - if hasattr(self, 'delay_enabled_checkbox'): - self.delay_enabled_checkbox.setChecked(self.arpeggiator.delay_enabled) + if hasattr(self, 'delay_toggle'): + self.delay_enabled = self.arpeggiator.delay_enabled + self.delay_toggle.setChecked(self.delay_enabled) + + if self.delay_enabled: + self.delay_toggle.setText("ON") + self.delay_toggle.setStyleSheet("background: #2d5a2d; color: white; font-size: 10px; font-weight: bold;") + # Enable all delay controls + if hasattr(self, 'delay_length_spin'): + self.delay_length_spin.setEnabled(True) + if hasattr(self, 'delay_timing_label'): + self.delay_timing_label.setEnabled(True) + if hasattr(self, 'delay_timing_widget'): + self.delay_timing_widget.setEnabled(True) + if hasattr(self, 'delay_fade_label'): + self.delay_fade_label.setEnabled(True) + if hasattr(self, 'delay_fade_slider'): + self.delay_fade_slider.setEnabled(True) + if hasattr(self, 'delay_fade_value'): + self.delay_fade_value.setEnabled(True) + else: + self.delay_toggle.setText("OFF") + self.delay_toggle.setStyleSheet("background: #5a2d2d; color: white; font-size: 10px; font-weight: bold;") + # Disable all delay controls + if hasattr(self, 'delay_length_spin'): + self.delay_length_spin.setEnabled(False) + if hasattr(self, 'delay_timing_label'): + self.delay_timing_label.setEnabled(False) + if hasattr(self, 'delay_timing_widget'): + self.delay_timing_widget.setEnabled(False) + if hasattr(self, 'delay_fade_label'): + self.delay_fade_label.setEnabled(False) + if hasattr(self, 'delay_fade_slider'): + self.delay_fade_slider.setEnabled(False) + if hasattr(self, 'delay_fade_value'): + self.delay_fade_value.setEnabled(False) + + # Update delay timing buttons + if hasattr(self, 'delay_timing_buttons') and hasattr(self.arpeggiator, 'delay_timing'): + # Clear current delay timing styling + if hasattr(self, 'current_delay_timing') and self.current_delay_timing in self.delay_timing_buttons: + self.apply_button_style(self.delay_timing_buttons[self.current_delay_timing], 10, "disabled") + # Set new active delay timing + self.current_delay_timing = self.arpeggiator.delay_timing + if self.current_delay_timing in self.delay_timing_buttons: + if self.delay_enabled: + self.apply_button_style(self.delay_timing_buttons[self.current_delay_timing], 10, "purple") + # Enable and style all timing buttons + for btn in self.delay_timing_buttons.values(): + btn.setEnabled(True) + if not btn.isChecked(): + self.apply_button_style(btn, 10, "normal") + else: + self.apply_button_style(self.delay_timing_buttons[self.current_delay_timing], 10, "disabled") + # Disable all timing buttons + for btn in self.delay_timing_buttons.values(): + btn.setEnabled(False) + self.apply_button_style(btn, 10, "disabled") + + # Update delay length and fade if hasattr(self, 'delay_length_spin'): self.delay_length_spin.setValue(self.arpeggiator.delay_length) if hasattr(self, 'delay_fade_slider'): self.delay_fade_slider.setValue(int(self.arpeggiator.delay_fade * 100)) + if hasattr(self, 'delay_fade_value'): + self.delay_fade_value.setText(f"{int(self.arpeggiator.delay_fade * 100)}%") # Update sliders and spinboxes if hasattr(self, 'gate_slider'):