diff --git a/sources/factory/propertieseditorfactory.cpp b/sources/factory/propertieseditorfactory.cpp index f08935423..8098f995a 100644 --- a/sources/factory/propertieseditorfactory.cpp +++ b/sources/factory/propertieseditorfactory.cpp @@ -23,6 +23,7 @@ #include "../qetgraphicsitem/ViewItem/ui/graphicstablepropertieseditor.h" #include "../qetgraphicsitem/ViewItem/ui/projectdbmodelpropertieswidget.h" #include "../qetgraphicsitem/conductor.h" +#include "../qetgraphicsitem/conductortextitem.h" #include "../qetgraphicsitem/diagramimageitem.h" #include "../qetgraphicsitem/dynamicelementtextitem.h" #include "../qetgraphicsitem/element.h" @@ -86,6 +87,17 @@ PropertiesEditorWidget *PropertiesEditorFactory::propertiesEditor( return nullptr; } QGraphicsItem *item = items.first(); + + //Selecting a conductor's text label edits its parent conductor (#500), + //mirroring how double-clicking the label opens the conductor dialog. + if (count_ == 1) { + if (auto *cti = qgraphicsitem_cast(item)) { + if (Conductor *parent_cond = cti->parentConductor()) { + items = {parent_cond}; + item = parent_cond; + } + } + } const int type_ = item->type(); //The editor widget can only edit one item diff --git a/sources/ui/conductorpropertieseditorwidget.cpp b/sources/ui/conductorpropertieseditorwidget.cpp index e79450c71..b0a0d7d33 100644 --- a/sources/ui/conductorpropertieseditorwidget.cpp +++ b/sources/ui/conductorpropertieseditorwidget.cpp @@ -21,8 +21,18 @@ #include "../diagram.h" #include "../qetgraphicsitem/conductor.h" #include "conductorpropertieswidget.h" +#include "../qtextorientationspinboxwidget.h" +#include + +#include +#include +#include +#include +#include #include +#include +#include #include /** @@ -48,6 +58,11 @@ ConductorPropertiesEditorWidget::ConductorPropertiesEditorWidget( layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(scroll); setMinimumWidth(120); + // Expand vertically to fill the dock like the other editors do (otherwise + // the panel sits at its small size hint with empty space below it, #500), + // while keeping a minimum height so it stays usable when the dock is short. + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + setMinimumHeight(200); setDisabled(true); setConductor(conductor); } @@ -74,12 +89,93 @@ void ConductorPropertiesEditorWidget::setConductor(Conductor *conductor) */ void ConductorPropertiesEditorWidget::apply() { + // Ignore the field-change signals emitted while the widget is being loaded + // programmatically (updateUi/reset): mid-load the widget holds a partial + // state that must not be committed onto the conductor. + if (m_updating) return; if (!m_conductor || !m_conductor->diagram()) return; if (QUndoCommand *undo = associatedUndo()) m_conductor->diagram()->undoStack().push(undo); m_initial = m_conductor->properties(); } +/** + @brief ConductorPropertiesEditorWidget::setLiveEdit + In live-edit mode (how the dock uses every editor), each field change is + applied immediately instead of via an explicit apply() call. Without this + override the base class is a no-op and edits in the dock were never applied + (issue #500). + @param live_edit true to enable live edit + @return always true +*/ +bool ConductorPropertiesEditorWidget::setLiveEdit(bool live_edit) +{ + if (m_live_edit == live_edit) return true; + m_live_edit = live_edit; + + if (m_live_edit) connectChangeSignals(); + else disconnectChangeSignals(); + + return true; +} + +/** + @brief ConductorPropertiesEditorWidget::connectChangeSignals + Wire every editable control of the hosted ConductorPropertiesWidget to + apply(). Commit-style signals (editingFinished / activated / toggled / + sliderReleased) are used rather than per-keystroke ones so each edit yields + a single, clean undo step. Loading the widget programmatically (updateUi) + also fires some of these, but apply() is a no-op then because + associatedUndo() returns nullptr when the properties are unchanged. +*/ +void ConductorPropertiesEditorWidget::connectChangeSignals() +{ + if (!m_cpw) return; + + const auto add = [this](QMetaObject::Connection c) { + m_live_connections << c; + }; + + for (auto *w : m_cpw->findChildren()) + add(connect(w, &QLineEdit::editingFinished, + this, &ConductorPropertiesEditorWidget::apply)); + for (auto *w : m_cpw->findChildren()) + add(connect(w, &QAbstractSpinBox::editingFinished, + this, &ConductorPropertiesEditorWidget::apply)); + for (auto *w : m_cpw->findChildren()) + add(connect(w, QOverload::of(&QComboBox::activated), + this, &ConductorPropertiesEditorWidget::apply)); + for (auto *w : m_cpw->findChildren()) + add(connect(w, &QSlider::sliderReleased, + this, &ConductorPropertiesEditorWidget::apply)); + for (auto *w : m_cpw->findChildren()) + add(connect(w, &KColorButton::changed, + this, &ConductorPropertiesEditorWidget::apply)); + for (auto *w : m_cpw->findChildren()) + add(connect(w, QOverload<>::of(&QTextOrientationSpinBoxWidget::editingFinished), + this, &ConductorPropertiesEditorWidget::apply)); + // Checkboxes and the checkable group boxes (single/multi wire, bicolor…). + for (auto *w : m_cpw->findChildren()) + if (w->isCheckable()) + add(connect(w, &QAbstractButton::toggled, + this, &ConductorPropertiesEditorWidget::apply)); + for (auto *w : m_cpw->findChildren()) + if (w->isCheckable()) + add(connect(w, &QGroupBox::toggled, + this, &ConductorPropertiesEditorWidget::apply)); +} + +/** + @brief ConductorPropertiesEditorWidget::disconnectChangeSignals + Tear down the live-edit connections made by connectChangeSignals(). +*/ +void ConductorPropertiesEditorWidget::disconnectChangeSignals() +{ + for (const QMetaObject::Connection &c : m_live_connections) + disconnect(c); + m_live_connections.clear(); +} + /** @brief ConductorPropertiesEditorWidget::reset Discard the in-progress edit, restoring the conductor's current properties. @@ -87,7 +183,9 @@ void ConductorPropertiesEditorWidget::apply() void ConductorPropertiesEditorWidget::reset() { if (!m_conductor) return; + m_updating = true; m_cpw->setProperties(m_initial); + m_updating = false; } /** @@ -97,8 +195,10 @@ void ConductorPropertiesEditorWidget::reset() void ConductorPropertiesEditorWidget::updateUi() { if (!m_conductor) return; + m_updating = true; m_initial = m_conductor->properties(); m_cpw->setProperties(m_initial); + m_updating = false; } /** diff --git a/sources/ui/conductorpropertieseditorwidget.h b/sources/ui/conductorpropertieseditorwidget.h index 365e34ff7..42df3b93b 100644 --- a/sources/ui/conductorpropertieseditorwidget.h +++ b/sources/ui/conductorpropertieseditorwidget.h @@ -21,6 +21,9 @@ #include "../PropertiesEditor/propertieseditorwidget.h" #include "../conductorproperties.h" +#include +#include + class Conductor; class ConductorPropertiesWidget; @@ -48,11 +51,18 @@ class ConductorPropertiesEditorWidget : public PropertiesEditorWidget void updateUi() override; QUndoCommand *associatedUndo() const override; QString title() const override; + bool setLiveEdit(bool live_edit) override; + + private: + void connectChangeSignals(); + void disconnectChangeSignals(); private: ConductorPropertiesWidget *m_cpw = nullptr; Conductor *m_conductor = nullptr; ConductorProperties m_initial; + QList m_live_connections; + bool m_updating = false; }; #endif // CONDUCTORPROPERTIESEDITORWIDGET_H