@@ -54,14 +54,14 @@ Item {
5454 proofModel .updateLines ()
5555 proofModel .updateRefs (myIdx, false )
5656
57- // After removal the boundary shifts to premiseCount - 1.
58- var insertAt = proofModel .premiseCount - 1
57+ // After removal, recomputePremiseCount has already fired and premiseCount
58+ // is now P-1. The insert boundary (first conclusion slot) is exactly premiseCount.
59+ var insertAt = proofModel .premiseCount
5960 theData .insertLine (insertAt, insertAt + 1 , pText, " choose" ,
6061 pSub, pSubSt, pSubEnd, pInd, [- 1 ])
6162 proofModel .updateLines ()
6263 proofModel .updateRefs (insertAt, true )
6364 listView .currentIndex = insertAt
64- proofModel .premiseCount = proofModel .premiseCount - 1
6565
6666 fileModified = true
6767 cConnector .evalText = " Evaluate Proof"
@@ -83,20 +83,41 @@ Item {
8383 proofModel .updateLines ()
8484 proofModel .updateRefs (insertAt2, true )
8585 listView .currentIndex = insertAt2
86- proofModel .premiseCount = proofModel .premiseCount + 1
8786
8887 fileModified = true
8988 cConnector .evalText = " Evaluate Proof"
9089 proofModel .clearErrors ()
9190 }
9291
93- property var combo2: [
94- [qsTr (" Modus Ponens" ), qsTr (" Addition" ), qsTr (" Simplification" ), qsTr (" Conjunction" ), qsTr (" Hypothetical Syllogism" ), qsTr (" Disjunctive Syllogism" ), qsTr (" Excluded middle" ), qsTr (" Constructive Dilemma" ), qsTr (" XOR Introduction" ), qsTr (" XOR Elimination" )],
95- [qsTr (" Implication" ), qsTr (" DeMorgan" ), qsTr (" Association" ), qsTr (" Commutativity" ), qsTr (" Idempotence" ), qsTr (" Distribution" ), qsTr (" Equivalence" ), qsTr (" Double Negation" ), qsTr (" Exportation" ), qsTr (" Subsumption" ), qsTr (" Contrapositive" )],
96- [qsTr (" Universal Generalization" ), qsTr (" Universal Instantiation" ), qsTr (" Existential Generalization" ), qsTr (" Existential Instantiation" ), qsTr (" Bound Variable Substitution" ), qsTr (" Null Quantifier" ), qsTr (" Prenex" ), qsTr (" Identity" ), qsTr (" Free Variable Substitution" )],
97- [qsTr (" Lemma" ), qsTr (" Subproof" ), qsTr (" Sequence" ), qsTr (" Induction" )],
98- [qsTr (" Identity " ), qsTr (" Negation" ), qsTr (" Dominance" ), qsTr (" Symbol Negation" )]
99- ]
92+ property var chooseCategories: getChooseCategories ()
93+ property var combo2: getCombo2 ()
94+
95+ function getChooseCategories () {
96+ return [qsTr (" Inference" ), qsTr (" Equivalence" ), qsTr (" Predicate" ), qsTr (" Miscellaneous" ), qsTr (" Boolean" )]
97+ }
98+
99+ function getCombo2 () {
100+ return [
101+ [qsTr (" Modus Ponens" ), qsTr (" Addition" ), qsTr (" Simplification" ), qsTr (" Conjunction" ), qsTr (" Hypothetical Syllogism" ), qsTr (" Disjunctive Syllogism" ), qsTr (" Excluded middle" ), qsTr (" Constructive Dilemma" ), qsTr (" XOR Introduction" ), qsTr (" XOR Elimination" )],
102+ [qsTr (" Implication" ), qsTr (" DeMorgan" ), qsTr (" Association" ), qsTr (" Commutativity" ), qsTr (" Idempotence" ), qsTr (" Distribution" ), qsTr (" Equivalence" ), qsTr (" Double Negation" ), qsTr (" Exportation" ), qsTr (" Subsumption" ), qsTr (" Contrapositive" )],
103+ [qsTr (" Universal Generalization" ), qsTr (" Universal Instantiation" ), qsTr (" Existential Generalization" ), qsTr (" Existential Instantiation" ), qsTr (" Bound Variable Substitution" ), qsTr (" Null Quantifier" ), qsTr (" Prenex" ), qsTr (" Identity" ), qsTr (" Free Variable Substitution" )],
104+ [qsTr (" Lemma" ), qsTr (" Subproof" ), qsTr (" Sequence" ), qsTr (" Induction" )],
105+ [qsTr (" Identity " ), qsTr (" Negation" ), qsTr (" Dominance" ), qsTr (" Symbol Negation" )]
106+ ]
107+ }
108+
109+ function refreshTranslations () {
110+ chooseCategories = getChooseCategories ()
111+ combo2 = getCombo2 ()
112+ }
113+
114+ Connections {
115+ target: settings
116+ function onLanguageChanged () {
117+ refreshTranslations ()
118+ }
119+ }
120+
100121 anchors .fill : parent
101122
102123 Shortcut {
@@ -196,7 +217,6 @@ Item {
196217 proofModel .updateLines ()
197218 proofModel .updateRefs (insertIndex, true )
198219 listView .currentIndex = insertIndex
199- proofModel .premiseCount = proofModel .premiseCount + 1
200220 fileModified = true
201221 cConnector .evalText = " Evaluate Proof"
202222 proofModel .clearErrors ()
@@ -233,16 +253,13 @@ Item {
233253 var myType = proofModel .data (proofModel .index (myIdx, 0 ), 258 )
234254
235255 if (listView .count > 1 ) {
236- if (myType === " premise" )
237- proofModel .premiseCount = proofModel .premiseCount - 1
238256 theData .removeLineAt (myIdx)
239257 proofModel .updateLines ()
240258 proofModel .updateRefs (myIdx, false )
241259 listView .currentIndex = Math .min (myIdx, listView .count - 1 )
242260 } else {
243261 theData .removeLineAt (0 )
244262 theData .insertLine (0 , 1 , " " , " premise" , false , false , false , 0 , [- 1 ])
245- proofModel .premiseCount = 1
246263 proofModel .updateLines ()
247264 listView .currentIndex = 0
248265 }
@@ -405,6 +422,11 @@ Item {
405422 property int indexx: model .index
406423 property bool vis: type === " premise" || type === " subproof"
407424 || type === " sf"
425+ // These delegate-level ints mirror the ProofModel roles.
426+ // They must live here (not inside a ComboBox) because inside a ComboBox,
427+ // `model` refers to the combo's own string-array model, NOT the row data.
428+ property int savedRuleCategory: model .ruleCategory
429+ property int savedRuleIndex: model .ruleIndex
408430 property string textFieldColor: {
409431 if (rootProofArea .selectedIndices .includes (indexx)) {
410432 return darkMode ? " #5C469C" : " #E6E6FA"
@@ -423,6 +445,18 @@ Item {
423445 listView .currentIndex = temp
424446 }
425447
448+ // Restore stored integer role values when language change resets combobox models.
449+ Connections {
450+ target: settings
451+ function onLanguageChanged () {
452+ if (outerColumn .savedRuleCategory >= 0 )
453+ chooseID .currentIndex = outerColumn .savedRuleCategory
454+ if (outerColumn .savedRuleIndex >= 0 )
455+ conclusionRuleID .currentIndex = outerColumn .savedRuleIndex
456+ }
457+ }
458+
459+
426460 RowLayout {
427461 id: root_delegate
428462 spacing: scaledSpacing
@@ -452,24 +486,28 @@ Item {
452486
453487 // Add this button's line to the current line's references
454488 onClicked: {
455- if (listView .currentIndex <= index)
489+ if (listView .currentIndex <= index) {
456490 console .log (" Invalid Operation : Can only reference to smaller line numbers" )
457- else if (proofModel .data (proofModel .index (
491+ cConnector .evalText = " ⚠ " + qsTr (" Invalid Operation: A proof line can only reference earlier line numbers." )
492+ } else if (proofModel .data (proofModel .index (
458493 listView .currentIndex , 0 ),
459- 257 ) === " premise" )
494+ 257 ) === " premise" ) {
460495 console .log (" Invalid Operation: Current Line is a premise" )
461- else if (proofModel .data (proofModel .index (
496+ cConnector .evalText = " ⚠ " + qsTr (" Invalid Operation: Cannot assign inference rules or references to a premise." )
497+ } else if (proofModel .data (proofModel .index (
462498 listView .currentIndex , 0 ),
463- 260 ) === true )
499+ 260 ) === true ) {
464500 // || proofModel.data(proofModel.index(listView.currentIndex,0),261) === true)
465501 console .log (" Invalid Operation: Subproof beginning" )
466- else if (proofModel .data (
502+ cConnector .evalText = " ⚠ " + qsTr (" Invalid Operation: Cannot modify or reference the start line of a subproof directly." )
503+ } else if (proofModel .data (
467504 proofModel .index (listView .currentIndex , 0 ),
468505 262 ) < model .ind && proofModel .data (
469506 proofModel .index (listView .currentIndex , 0 ),
470- 261 ) === false )
507+ 261 ) === false ) {
471508 console .log (" Invalid Operation: Invalid reference to subproof" )
472- else {
509+ cConnector .evalText = " ⚠ " + qsTr (" Invalid Operation: Cannot reference lines across closed subproof boundaries." )
510+ } else {
473511 cConnector .evalText = " Evaluate Proof"
474512 proofModel .clearErrors ()
475513 var array = Array .from (proofModel .data (
@@ -482,6 +520,7 @@ Item {
482520 proofModel .setData (proofModel .index (
483521 listView .currentIndex ,
484522 0 ), array, 263 )
523+ fileModified = true
485524 refreshTextFieldColor ()
486525 return
487526 }
@@ -490,6 +529,7 @@ Item {
490529 proofModel .setData (proofModel .index (
491530 listView .currentIndex , 0 ),
492531 array, 263 )
532+ fileModified = true
493533 refreshTextFieldColor ()
494534 }
495535 }
@@ -636,6 +676,8 @@ Item {
636676 }
637677 }
638678
679+ onTextEdited: fileModified = true
680+
639681 // Save Text inside Model
640682 onEditingFinished: {
641683 if (model .lText !== text) {
@@ -715,26 +757,16 @@ Item {
715757 onActivated: {
716758 editCombos = true
717759 proofModel .setData (proofModel .index (indexx, 0 ),
718- conclusionRuleID .currentText , 258 )
760+ currentIndex, 265 ) // RuleCategoryRole
761+ fileModified = true
719762 asteriskID .visible = false
720763 }
721764
722- model: [ qsTr ( " Inference " ), qsTr ( " Equivalence " ), qsTr ( " Predicate " ), qsTr ( " Miscellaneous " ), qsTr ( " Boolean " )]
765+ model: chooseCategories
723766
724- Component .onCompleted : {
725- if (! editCombos) {
726- if (combo2[0 ].includes (type))
727- currentIndex = 0
728- else if (combo2[1 ].includes (type))
729- currentIndex = 1
730- else if (combo2[2 ].includes (type))
731- currentIndex = 2
732- else if (combo2[3 ].includes (type))
733- currentIndex = 3
734- else
735- currentIndex = 4
736- }
737- }
767+ // Use delegate-level savedRuleCategory (not `model.ruleCategory` here,
768+ // because inside a ComboBox `model` shadows the row data).
769+ currentIndex: outerColumn .savedRuleCategory >= 0 ? outerColumn .savedRuleCategory : currentIndex
738770 }
739771
740772 // Second ComboBox to select rule
@@ -775,17 +807,34 @@ Item {
775807 onActivated: {
776808 editCombos = true
777809 proofModel .setData (proofModel .index (indexx, 0 ),
778- currentText, 258 )
810+ chooseID .currentIndex , 265 ) // RuleCategoryRole
811+ // Write the rule index integer (locale-invariant).
812+ proofModel .setData (proofModel .index (indexx, 0 ),
813+ currentIndex, 266 ) // RuleIndexRole
814+ fileModified = true
779815 asteriskID .visible = false
780816 }
781817
782- onModelChanged: {
783- if (! editCombos) {
784- currentIndex = model .indexOf (type)
785- }
818+ // DO NOT use a declarative `currentIndex:` binding here.
819+ // When chooseID.currentIndex changes, combo2[cat] changes,
820+ // which causes QML to reset currentIndex internally — destroying
821+ // any declarative binding. Instead we use onModelChanged to
822+ // re-apply the saved ruleIndex after the model swap settles.
823+ model: combo2[chooseID .currentIndex ]
824+
825+ Component .onCompleted : {
826+ // `model` here is the combo's string array — use outerColumn.savedRuleIndex.
827+ if (outerColumn .savedRuleIndex >= 0 )
828+ currentIndex = outerColumn .savedRuleIndex
786829 }
787830
788- model: combo2[chooseID .currentIndex ]
831+ onModelChanged: {
832+ // Fires when chooseID.currentIndex changes (during load or user action).
833+ if (! editCombos && outerColumn .savedRuleIndex >= 0 )
834+ currentIndex = outerColumn .savedRuleIndex // restore on load
835+ else if (editCombos)
836+ currentIndex = 0 // user picked a new category → start at rule 0
837+ }
789838 }
790839
791840 // Display Asterisk next to ComboBox if rule not chosen
@@ -841,6 +890,7 @@ Item {
841890 proofModel .setData (proofModel .index (
842891 listView .currentIndex ,
843892 0 ), ar, 263 )
893+ fileModified = true
844894 cConnector .evalText = " Evaluate Proof"
845895 proofModel .clearErrors ()
846896 }
@@ -869,10 +919,6 @@ Item {
869919 }
870920
871921 onClicked: {
872- if (computePremise) {
873- proofModel .recomputePremiseCount ()
874- computePremise = false
875- }
876922 optionsID .open ()
877923 }
878924
@@ -904,7 +950,6 @@ Item {
904950 listView .currentIndex = insertIndex
905951 cConnector .evalText = " Evaluate Proof"
906952 proofModel .clearErrors ()
907- proofModel .premiseCount = proofModel .premiseCount + 1
908953 }
909954 }
910955 Action {
@@ -1000,17 +1045,13 @@ Item {
10001045 proofModel .clearErrors ()
10011046
10021047 if (listView .count > 1 ) {
1003- if (type === " premise" )
1004- proofModel .premiseCount = proofModel .premiseCount - 1
1005-
10061048 var i = index
10071049 theData .removeLineAt (index)
10081050 proofModel .updateLines ()
10091051 proofModel .updateRefs (i, false )
10101052 } else {
10111053 theData .removeLineAt (0 )
10121054 theData .insertLine (0 , 1 , " " , " premise" , false , false , false , 0 , [- 1 ])
1013- proofModel .premiseCount = 1
10141055 proofModel .updateLines ()
10151056 listView .currentIndex = 0
10161057 console .log (" Goal 3: Last line reset to prevent blank screen crash." )
0 commit comments