@@ -83,12 +83,20 @@ ApplicationWindow {
8383 validate (data .current , 0 )
8484 validate (data .voltage , 1 )
8585 restoringScenario = true
86+ // Legacy presets can contain disabled output rows. This simple
87+ // matrix has no channel enable controls by design. At application
88+ // startup ONLY (never during live RUNNING), migrate disabled
89+ // outputs to enabled channels with zero magnitude, preserving
90+ // the previous zero-output effect without hidden OFF flags.
91+ var migratedDisabled = 0
8692 function assign (model , rows ) {
8793 for (var i = 0 ; i < 4 ; ++ i) {
88- model .setProperty (i, " magnitude" , rows[i][0 ])
94+ const wasDisabled = rows[i][2 ] === false
95+ model .setProperty (i, " magnitude" , wasDisabled ? 0 : rows[i][0 ])
8996 model .setProperty (i, " phase" , rows[i][1 ])
90- model .setProperty (i, " enabled" , rows[i][ 2 ] )
97+ model .setProperty (i, " enabled" , true )
9198 model .setProperty (i, " quality" , rows[i][3 ])
99+ if (wasDisabled) migratedDisabled += 1
92100 }
93101 }
94102 assign (currentModel, data .current )
@@ -101,6 +109,13 @@ ApplicationWindow {
101109 refreshPreview ()
102110 restoringScenario = false
103111 pendingApply = true
112+ if (migratedDisabled > 0 ) {
113+ // Persist the migration to avoid redoing it on next launch.
114+ // Explicitly notify the operator; no serial output is sent.
115+ scenarioSettings .lastScenario = JSON .stringify (scenarioSnapshot ())
116+ showMessage (" Legacy preset: " + migratedDisabled +
117+ " disabled channel(s) restored as enabled at 0 magnitude. Review before START." , true )
118+ }
104119 } catch (e) {
105120 restoringScenario = false
106121 scenarioSettings .lastScenario = " "
@@ -516,6 +531,18 @@ ApplicationWindow {
516531 }
517532 // START always serializes the same ListModels that draw the table,
518533 // including all eight current phase angles and enabled flags.
534+ // Never silently START with an invisible disabled channel. The
535+ // legacy restore path migrates at boot; an unexpected future state
536+ // must be corrected explicitly instead of serialized unnoticed.
537+ for (var group = 0 ; group < 2 ; ++ group) {
538+ var rows = groupModel (group)
539+ for (var row = 0 ; row < 4 ; ++ row) {
540+ if (rows .get (row).enabled !== true ) {
541+ showMessage (" Hidden disabled channel detected. Restore the scenario before START." , true )
542+ return null
543+ }
544+ }
545+ }
519546 var draft = scenarioSnapshot ()
520547 draft .currentScale = currentScale
521548 draft .voltageScale = voltageScale
@@ -1062,32 +1089,18 @@ ApplicationWindow {
10621089 CalmButton { theme: studioTheme; uiFont: root .uiFont ; text: " 50" ; implicitWidth: 44 ; onClicked: root .setFrequencyValue (50 ) }
10631090 CalmButton { theme: studioTheme; uiFont: root .uiFont ; text: " 60" ; implicitWidth: 44 ; onClicked: root .setFrequencyValue (60 ) }
10641091 Rectangle { width: 1 ; height: 24 ; color: studioTheme .lineSoft }
1065- StudioDarkCheckBox {
1092+ StudioLinkSwitch {
10661093 theme: studioTheme
10671094 uiFont: root .uiFont
1068- enabled: root .signalFrequency > 0
1095+ enabled: root .signalFrequency > 0 && ! workflowBar . startQueued
10691096 checked: root .phaseLink
1070- text: " 3-phase link"
10711097 onToggled: {
1098+ // Link is an editing preference, not a wire
1099+ // setpoint. No 8-channel live replay or
1100+ // pendingApply on a presentation-only switch.
10721101 root .phaseLink = checked
1073- // Linking phases changes future edit behavior only;
1074- // never silently rewrite existing setpoints.
1075- root .markScenarioDirty ()
1076- if (workflowBar .injectionRunning && workflowBar .session
1077- && workflowBar .session .liveControlReady ) {
1078- // Persist *all eight current table values* on
1079- // live link changes; the displayed draft
1080- // must never silently diverge from TX.
1081- var ok = true
1082- for (var group = 0 ; group < 2 ; ++ group)
1083- for (var row = 0 ; row < 4 ; ++ row)
1084- ok = root .sendSignal (group, row) && ok
1085- if (ok) root .pendingApply = false
1086- else root .showMessage (" Not all live phases were sent. Stop/Start to apply the table." , true )
1087- }
1102+ root .saveScenarioTimer .restart ()
10881103 }
1089- font .family : root .uiFont
1090- font .pixelSize : 9
10911104 }
10921105 Item { Layout .fillWidth : true }
10931106 }
0 commit comments