diff --git a/cmake/qet_compilation_vars.cmake b/cmake/qet_compilation_vars.cmake
index d3178901e..60fddcf55 100644
--- a/cmake/qet_compilation_vars.cmake
+++ b/cmake/qet_compilation_vars.cmake
@@ -716,6 +716,8 @@ set(QET_SRC_FILES
${QET_DIR}/sources/ui/borderpropertieswidget.h
${QET_DIR}/sources/ui/compositetexteditdialog.cpp
${QET_DIR}/sources/ui/compositetexteditdialog.h
+ ${QET_DIR}/sources/ui/conductorpropertieseditorwidget.cpp
+ ${QET_DIR}/sources/ui/conductorpropertieseditorwidget.h
${QET_DIR}/sources/ui/contactgroupselectiondialog.cpp
${QET_DIR}/sources/ui/contactgroupselectiondialog.h
${QET_DIR}/sources/ui/conductorpropertiesdialog.cpp
diff --git a/lang/qet_en.ts b/lang/qet_en.ts
index 7a899eabf..6f4dae9f4 100644
--- a/lang/qet_en.ts
+++ b/lang/qet_en.ts
@@ -912,6 +912,31 @@ Note: these options DO NOT allow or block auto numberings, only their update pol
Edit the properties of several conductors
+
+ ConductorPropertiesEditorWidget
+
+
+ Appliquer les propriétés à l'ensemble des conducteurs de ce potentiel
+ Apply properties to all conductors of this potential
+
+
+
+ Modifier les propriétés d'un conducteur
+ undo caption
+ Edit conductor properties
+
+
+
+ Modifier les propriétés de plusieurs conducteurs
+ undo caption
+ Edit the properties of several conductors
+
+
+
+ Conducteur
+ Conductor
+
+ConductorPropertiesWidget
diff --git a/sources/factory/propertieseditorfactory.cpp b/sources/factory/propertieseditorfactory.cpp
index 6a18db924..48a39738b 100644
--- a/sources/factory/propertieseditorfactory.cpp
+++ b/sources/factory/propertieseditorfactory.cpp
@@ -22,6 +22,8 @@
#include "../qetgraphicsitem/ViewItem/qetgraphicstableitem.h"
#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"
@@ -30,11 +32,13 @@
#include "../qetgraphicsitem/qetshapeitem.h"
#include "../ui/dynamicelementtextitemeditor.h"
#include "../ui/elementpropertieswidget.h"
+#include "../ui/conductorpropertieseditorwidget.h"
#include "../ui/imagepropertieswidget.h"
#include "../ui/inditextpropertieswidget.h"
#include "../ui/shapegraphicsitempropertieswidget.h"
#include
+#include
/**
@brief PropertiesEditorFactory::propertiesEditor
@@ -83,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
@@ -100,6 +115,28 @@ PropertiesEditorWidget *PropertiesEditorFactory::propertiesEditor(
switch (type_)
{
+ case Conductor::Type: //1001
+ {
+ //Off unless enabled in the preferences (General page): selecting
+ //a conductor then brings up nothing in the dock, as before.
+ if (!QSettings().value(
+ QStringLiteral("diagrameditor/conductor_properties_panel"),
+ false).toBool()) {
+ return nullptr;
+ }
+ //Prototype (#500): single-conductor editing in the dock.
+ if (count_ > 1) {
+ return nullptr;
+ }
+ auto conductor = static_cast(item);
+
+ if (class_name == ConductorPropertiesEditorWidget::staticMetaObject.className())
+ {
+ static_cast(editor)->setConductor(conductor);
+ return editor;
+ }
+ return new ConductorPropertiesEditorWidget(conductor, parent);
+ }
case Element::Type: //1000
{
if (count_ > 1) {
diff --git a/sources/ui/conductorpropertieseditorwidget.cpp b/sources/ui/conductorpropertieseditorwidget.cpp
new file mode 100644
index 000000000..384e43f11
--- /dev/null
+++ b/sources/ui/conductorpropertieseditorwidget.cpp
@@ -0,0 +1,287 @@
+/*
+ Copyright 2006-2026 The QElectroTech Team
+ This file is part of QElectroTech.
+
+ QElectroTech is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ QElectroTech is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with QElectroTech. If not, see .
+*/
+#include "conductorpropertieseditorwidget.h"
+
+#include "../QPropertyUndoCommand/qpropertyundocommand.h"
+#include "../diagram.h"
+#include "../qetgraphicsitem/conductor.h"
+#include "conductorpropertieswidget.h"
+#include "../qtextorientationspinboxwidget.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ @brief ConductorPropertiesEditorWidget::ConductorPropertiesEditorWidget
+ @param conductor : conductor to edit
+ @param parent : parent widget
+*/
+ConductorPropertiesEditorWidget::ConductorPropertiesEditorWidget(
+ Conductor *conductor, QWidget *parent) :
+ PropertiesEditorWidget(parent),
+ m_cpw(new ConductorPropertiesWidget(this))
+{
+ // The conductor widget is dialog-sized (min width ~600px), far too wide for
+ // a dock. Host it in a scroll area with a small minimum width so the dock
+ // can be dragged to any width (a scrollbar appears when narrower than the
+ // content). QET already persists dock geometry across restarts via
+ // QETDiagramEditor save/restoreState, so the chosen width is remembered.
+ // "Apply to all conductors of the potential": same semantics as the modal
+ // dialog's checkbox (ConductorPropertiesDialog::applyAll), pinned at the top
+ // of the panel so it stays visible above the scrolling tabs (#500). Unlike
+ // the dialog the choice is persisted, so a user who always wants it on (or
+ // off) sets it once. It is a child of this editor, not of m_cpw, so it is
+ // deliberately outside the live-edit signal wiring in connectChangeSignals()
+ // (toggling it must not push an edit, only change how the next edit applies).
+ // Reuse the modal dialog's exact wording for consistency (and so the
+ // existing translation applies).
+ m_apply_all_cb = new QCheckBox(
+ tr("Appliquer les propriétés à l'ensemble des conducteurs de ce potentiel"),
+ this);
+ m_apply_all_cb->setChecked(QSettings().value(
+ QStringLiteral("diagrameditor/conductor_apply_all"), true).toBool());
+ connect(m_apply_all_cb, &QCheckBox::toggled, this, [](bool on) {
+ QSettings().setValue(
+ QStringLiteral("diagrameditor/conductor_apply_all"), on);
+ });
+
+ auto *scroll = new QScrollArea(this);
+ scroll->setWidgetResizable(true);
+ scroll->setFrameShape(QFrame::NoFrame);
+ scroll->setWidget(m_cpw);
+ auto *layout = new QVBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(m_apply_all_cb);
+ 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);
+}
+
+ConductorPropertiesEditorWidget::~ConductorPropertiesEditorWidget()
+{}
+
+/**
+ @brief ConductorPropertiesEditorWidget::setConductor
+ Set (or change) the conductor whose properties are edited.
+ @param conductor
+*/
+void ConductorPropertiesEditorWidget::setConductor(Conductor *conductor)
+{
+ if (!conductor) return;
+ if (m_conductor && m_conductor != conductor)
+ disconnect(m_conductor, &Conductor::propertiesChange,
+ this, &ConductorPropertiesEditorWidget::updateUi);
+ m_conductor = conductor;
+ //Keep the dock in sync when the conductor is edited elsewhere (e.g. the
+ //modal "Edit conductor" dialog); otherwise a stale snapshot would be
+ //written back on the next apply() and overwrite that change (issue #500).
+ connect(m_conductor, &Conductor::propertiesChange,
+ this, &ConductorPropertiesEditorWidget::updateUi, Qt::UniqueConnection);
+ setEnabled(true);
+ updateUi();
+}
+
+/**
+ @brief ConductorPropertiesEditorWidget::apply
+ Push the edit onto the diagram's undo stack.
+*/
+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.
+*/
+void ConductorPropertiesEditorWidget::reset()
+{
+ if (!m_conductor) return;
+ m_updating = true;
+ m_cpw->setProperties(m_initial);
+ m_updating = false;
+}
+
+/**
+ @brief ConductorPropertiesEditorWidget::updateUi
+ Reload the widget from the conductor (e.g. when the selection changes).
+*/
+void ConductorPropertiesEditorWidget::updateUi()
+{
+ if (!m_conductor) return;
+ m_updating = true;
+ m_initial = m_conductor->properties();
+ m_cpw->setProperties(m_initial);
+ m_updating = false;
+}
+
+/**
+ @brief ConductorPropertiesEditorWidget::associatedUndo
+ @return the edit as a QPropertyUndoCommand, or nullptr if unchanged.
+
+ When "apply to all" is ticked, every conductor on the same potential is
+ updated in the same undo step (one undo reverts them all), exactly as the
+ modal dialog does (ConductorPropertiesDialog::PropertiesDialog). Otherwise
+ only the selected conductor is changed.
+*/
+QUndoCommand *ConductorPropertiesEditorWidget::associatedUndo() const
+{
+ if (!m_conductor) return nullptr;
+
+ const ConductorProperties new_properties = m_cpw->properties();
+ if (new_properties == m_conductor->properties()) return nullptr;
+
+ QVariant old_value, new_value;
+ old_value.setValue(m_conductor->properties());
+ new_value.setValue(new_properties);
+
+ auto *undo = new QPropertyUndoCommand(
+ m_conductor, "properties", old_value, new_value);
+ undo->setText(tr("Modifier les propriétés d'un conducteur", "undo caption"));
+
+ // Propagate to every conductor on the same potential, as the modal dialog
+ // does: each related conductor becomes a child command of the same undo
+ // step, set to the same target properties.
+ if (m_apply_all_cb && m_apply_all_cb->isChecked())
+ {
+ const auto potential = m_conductor->relatedPotentialConductors();
+ if (!potential.isEmpty())
+ {
+ undo->setText(tr("Modifier les propriétés de plusieurs conducteurs",
+ "undo caption"));
+ for (Conductor *potential_conductor : potential)
+ {
+ QVariant old_v;
+ old_v.setValue(potential_conductor->properties());
+ new QPropertyUndoCommand(
+ potential_conductor, "properties", old_v, new_value, undo);
+ }
+ }
+ }
+ return undo;
+}
+
+/**
+ @brief ConductorPropertiesEditorWidget::title
+ @return the panel title.
+*/
+QString ConductorPropertiesEditorWidget::title() const
+{
+ return tr("Conducteur");
+}
diff --git a/sources/ui/conductorpropertieseditorwidget.h b/sources/ui/conductorpropertieseditorwidget.h
new file mode 100644
index 000000000..0479a6bee
--- /dev/null
+++ b/sources/ui/conductorpropertieseditorwidget.h
@@ -0,0 +1,70 @@
+/*
+ Copyright 2006-2026 The QElectroTech Team
+ This file is part of QElectroTech.
+
+ QElectroTech is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ QElectroTech is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with QElectroTech. If not, see .
+*/
+#ifndef CONDUCTORPROPERTIESEDITORWIDGET_H
+#define CONDUCTORPROPERTIESEDITORWIDGET_H
+
+#include "../PropertiesEditor/propertieseditorwidget.h"
+#include "../conductorproperties.h"
+
+#include
+#include
+
+class Conductor;
+class ConductorPropertiesWidget;
+class QCheckBox;
+
+/**
+ @brief The ConductorPropertiesEditorWidget class
+ Hosts the existing ConductorPropertiesWidget in the dockable selection-
+ properties panel, so a selected conductor can be edited in place like the
+ other item types, instead of only through the modal dialog (issue #500).
+ A pinned "apply to all conductors of the potential" checkbox (persisted)
+ mirrors the modal dialog's option to propagate edits to the whole potential.
+*/
+class ConductorPropertiesEditorWidget : public PropertiesEditorWidget
+{
+ Q_OBJECT
+
+ public:
+ explicit ConductorPropertiesEditorWidget(
+ Conductor *conductor = nullptr, QWidget *parent = nullptr);
+ ~ConductorPropertiesEditorWidget() override;
+
+ void setConductor(Conductor *conductor);
+
+ void apply() override;
+ void reset() override;
+ 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;
+ QCheckBox *m_apply_all_cb = nullptr;
+ Conductor *m_conductor = nullptr;
+ ConductorProperties m_initial;
+ QList m_live_connections;
+ bool m_updating = false;
+};
+
+#endif // CONDUCTORPROPERTIESEDITORWIDGET_H
diff --git a/sources/ui/configpage/generalconfigurationpage.cpp b/sources/ui/configpage/generalconfigurationpage.cpp
index 1340b9b66..41fa915bd 100644
--- a/sources/ui/configpage/generalconfigurationpage.cpp
+++ b/sources/ui/configpage/generalconfigurationpage.cpp
@@ -102,6 +102,7 @@ GeneralConfigurationPage::GeneralConfigurationPage(QWidget *parent) :
else
ui->m_use_windows_mode_rb->setChecked(true);
ui->m_zoom_out_beyond_folio->setChecked(settings.value("diagrameditor/zoom-out-beyond-of-folio", false).toBool());
+ ui->m_conductor_properties_panel->setChecked(settings.value("diagrameditor/conductor_properties_panel", false).toBool());
ui->m_use_gesture_trackpad->setChecked(settings.value("diagramview/gestures", false).toBool());
ui->m_save_label_paste->setChecked(settings.value("diagramcommands/erase-label-on-copy", true).toBool());
ui->m_enable_scripting->setChecked(QetSettings::scriptingEnabled());
@@ -295,6 +296,7 @@ void GeneralConfigurationPage::applyConf()
settings.setValue("diagrameditor/viewmode", view_mode) ;
settings.setValue("diagrameditor/highlight-integrated-elements", ui->m_highlight_integrated_elements->isChecked());
settings.setValue("diagrameditor/zoom-out-beyond-of-folio", ui->m_zoom_out_beyond_folio->isChecked());
+ settings.setValue("diagrameditor/conductor_properties_panel", ui->m_conductor_properties_panel->isChecked());
settings.setValue("diagrameditor/autosave-interval", ui->m_autosave_sb->value());
settings.setValue("diagrameditor/grid_display_startup", ui->grid_startup_cb->isChecked());
diff --git a/sources/ui/configpage/generalconfigurationpage.ui b/sources/ui/configpage/generalconfigurationpage.ui
index 177314d93..cfd57dd5c 100644
--- a/sources/ui/configpage/generalconfigurationpage.ui
+++ b/sources/ui/configpage/generalconfigurationpage.ui
@@ -63,6 +63,13 @@
+
+
+
+ Afficher les propriétés d'un conducteur sélectionné dans le panneau Propriétés de la sélection
+
+
+
@@ -1205,6 +1212,7 @@ Vous pouvez spécifier ici la valeur par défaut de ce champ pour les éléments
m_use_system_color_cbm_use_gesture_trackpadm_zoom_out_beyond_folio
+ m_conductor_properties_panelm_use_windows_mode_rbm_use_tab_mode_rbm_save_label_paste