Fix #487: drag-selecting dynamic text fields silently converts their text source

updateForm() called on_m_text_from_cb_activated() directly, intending
only to enable the sibling widget matching the combo box's current
index ("For enable the good widget"). But that slot also loops over
every currently selected part and pushes an undo command overwriting
textFrom on any part that doesn't match, since it's normally only
reached via the combo box's own activated(int) signal (real user
interaction, never fired by programmatic setCurrentIndex()).

updateForm() runs on every selection change, so during a rubber-band
drag over dynamic text fields with different sources, each time a new
field enters the selection, the representative part's textFrom gets
force-applied to every other selected part - converting e.g. a
UserText field to ElementInfo mid-drag, before the user has released
the mouse or interacted with the combo box at all.

Split the cosmetic widget-enable logic into updateTextFromWidgetsEnabled(),
called from updateForm(). on_m_text_from_cb_activated() keeps the
part-mutating loop, now only reached from real user activation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-07-30 19:11:25 +12:00
parent 88962570a8
commit b60e73d93b
2 changed files with 16 additions and 2 deletions
+15 -2
View File
@@ -163,7 +163,7 @@ void DynamicTextFieldEditor::updateForm()
} }
} }
on_m_text_from_cb_activated(ui -> m_text_from_cb -> currentIndex()); //For enable the good widget updateTextFromWidgetsEnabled(ui -> m_text_from_cb -> currentIndex()); //For enable the good widget
} }
} }
@@ -327,7 +327,16 @@ void DynamicTextFieldEditor::on_m_elmt_info_cb_activated(const QString &arg1) {
} }
} }
void DynamicTextFieldEditor::on_m_text_from_cb_activated(int index) { /**
@brief DynamicTextFieldEditor::updateTextFromWidgetsEnabled
Enable the widget matching @p index (the "text from" combo box's current
index) and disable the other two. Purely cosmetic: called both from the
real user-activated slot below and from updateForm() when the form is
(re)filled for a part/selection, so it must never touch m_parts's data —
see on_m_text_from_cb_activated() for the part-mutating counterpart.
*/
void DynamicTextFieldEditor::updateTextFromWidgetsEnabled(int index)
{
ui -> m_user_text_le -> setDisabled(true); ui -> m_user_text_le -> setDisabled(true);
ui -> m_elmt_info_cb -> setDisabled(true); ui -> m_elmt_info_cb -> setDisabled(true);
ui -> m_composite_text_pb -> setDisabled(true); ui -> m_composite_text_pb -> setDisabled(true);
@@ -341,6 +350,10 @@ void DynamicTextFieldEditor::on_m_text_from_cb_activated(int index) {
else { else {
ui->m_composite_text_pb->setEnabled(true); ui->m_composite_text_pb->setEnabled(true);
} }
}
void DynamicTextFieldEditor::on_m_text_from_cb_activated(int index) {
updateTextFromWidgetsEnabled(index);
DynamicElementTextItem::TextFrom tf; DynamicElementTextItem::TextFrom tf;
if(index == 0) { if(index == 0) {
@@ -52,6 +52,7 @@ class DynamicTextFieldEditor : public ElementItemEditor {
void fillInfoComboBox(); void fillInfoComboBox();
void setUpConnections(); void setUpConnections();
void disconnectConnections(); void disconnectConnections();
void updateTextFromWidgetsEnabled(int index);
private slots: private slots:
void on_m_x_sb_editingFinished(); void on_m_x_sb_editingFinished();