Files
qelectrotech-source-mirror/sources/ui/conductorpropertieswidget.cpp
T
ispyisail 1c5fd5a284 Multi-wire panel: stable first wire, mixed fields, locked text, one reload
Review of #1205:

- The scene gives no order for its selection, so the "first" wire whose
  values the panel shows could change between two selections of the
  same wires. The wires are now sorted top to bottom, then left to right.
- A text field the selected wires do not agree on (function, section,
  cable...) is shown blank with the hint "Plusieurs valeurs". Typing any
  value there, including the first wire's own, now differs from what was
  shown, so it reaches every wire: 1.5 mm² on a 1.5 and a 2.5 wire works.
- The conductor text is locked while several wires are selected: the same
  number on all of them would make duplicates. "Apply to all conductors
  of this potential" with one wire selected still sets the number on the
  whole potential.
- One edit of N wires emitted N signals, each reloading the panel. They
  are now gathered into one reload, which matters since a reload reads
  every selected wire to find the mixed fields. Selections and targets
  are de-duplicated with sets, and a wire reached through an earlier
  wire's potential is not walked again. An edit that changes nothing
  returns before any potential is walked.

The rules move to sources/conductormultiedit.h, templates over the wire
type, so tst_conductormultiedit can check them against a fake wire:
order, targets with and without potentials, one undo step and its redo
for three wires, and the mixed fields. tst_conductorapplychanges now
gives the other wire the opposite value in every boolean field, so
copying one by mistake fails the test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 06:20:17 +13:00

369 lines
13 KiB
C++

/*
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 <http://www.gnu.org/licenses/>.
*/
#include "conductorpropertieswidget.h"
#include "../conductorproperties.h"
#include "../qetapp.h"
#include "../qtextorientationspinboxwidget.h"
#include "ui_conductorpropertieswidget.h"
/**
@brief ConductorPropertiesWidget::ConductorPropertiesWidget
Constructor
@param parent : paretn widget
*/
ConductorPropertiesWidget::ConductorPropertiesWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::ConductorPropertiesWidget)
{
ui->setupUi(this);
initWidget();
}
/**
@brief ConductorPropertiesWidget::ConductorPropertiesWidget
Constructor with properties
@param properties : properties to edit
@param parent : parent widget
*/
ConductorPropertiesWidget::ConductorPropertiesWidget(
const ConductorProperties &properties,
QWidget *parent) :
QWidget(parent),
ui(new Ui::ConductorPropertiesWidget)
{
ui -> setupUi(this);
initWidget();
setProperties(properties);
}
/**
@brief ConductorPropertiesWidget::~ConductorPropertiesWidget
destructor
*/
ConductorPropertiesWidget::~ConductorPropertiesWidget()
{
delete ui;
}
/**
@brief ConductorPropertiesWidget::setProperties
Set the properties
@param properties
*/
void ConductorPropertiesWidget::setProperties(
const ConductorProperties &properties)
{
if (m_properties == properties)
return;
m_properties = properties;
int index = ui -> m_line_style_cb -> findData(QPen(m_properties.style));
if (index != -1) ui -> m_line_style_cb -> setCurrentIndex(index);
ui->m_color_2_gb -> setChecked (m_properties.m_bicolor);
ui->m_dash_size_sb -> setValue (m_properties.m_dash_size);
ui->m_formula_le -> setText (m_properties.m_formula);
ui->m_text_le -> setText (m_properties.text);
ui->m_function_le -> setText (m_properties.m_function);
ui->m_cable_le -> setText (m_properties.m_cable);
ui->m_bus_le -> setText (m_properties.m_bus);
ui->m_tension_protocol_le -> setText (m_properties.m_tension_protocol);
ui->m_wire_color_le -> setText (m_properties.m_wire_color);
ui->m_wire_section_le -> setText (m_properties.m_wire_section);
ui->m_text_size_sb -> setValue (m_properties.text_size);
ui->m_cond_size_sb -> setValue (m_properties.cond_size);
ui->m_show_text_cb -> setChecked (m_properties.m_show_text);
ui->m_one_text_per_folio_cb -> setChecked (m_properties.m_one_text_per_folio);
ui->m_earth_cb -> setChecked (m_properties.singleLineProperties.hasGround);
ui->m_neutral_cb -> setChecked (m_properties.singleLineProperties.hasNeutral);
ui->m_pen_cb -> setChecked (m_properties.singleLineProperties.isPen());
ui->m_phase_cb -> setChecked (m_properties.singleLineProperties.phasesCount());
ui->m_phase_slider -> setValue (m_properties.singleLineProperties.phasesCount());
ui->m_color_kpb -> setColor(m_properties.color);
ui->m_color_2_kpb -> setColor(m_properties.m_color_2);
ui->m_text_color_kpb -> setColor(m_properties.text_color);
ui->m_horiz_cb->setCurrentIndex(m_properties.m_horizontal_alignment == Qt::AlignTop? 0 : 1);
ui->m_verti_cb->setCurrentIndex(m_properties.m_vertical_alignment == Qt::AlignLeft? 0 : 1);
m_verti_select -> setValue (m_properties.verti_rotate_text);
m_horiz_select -> setValue (m_properties.horiz_rotate_text);
setConductorType(m_properties.type);
updatePreview(false);
}
/**
@brief ConductorPropertiesWidget::properties
@return the edited properties
*/
ConductorProperties ConductorPropertiesWidget::properties() const
{
ConductorProperties properties_;
if (ui -> m_multiwires_gb -> isChecked()) properties_.type = ConductorProperties::Multi;
else if (ui -> m_singlewire_gb -> isChecked()) properties_.type = ConductorProperties::Single;
properties_.color = ui -> m_color_kpb->color();
properties_.m_bicolor = ui->m_color_2_gb->isChecked();
properties_.m_color_2 = ui->m_color_2_kpb->color();
properties_.m_dash_size = ui->m_dash_size_sb->value();
properties_.style = ui -> m_line_style_cb->itemData(ui->m_line_style_cb->currentIndex()).value<QPen>().style();
properties_.m_formula = ui->m_formula_le->text();
properties_.text = ui -> m_text_le -> text();
properties_.text_color = ui -> m_text_color_kpb->color();
properties_.m_function = ui -> m_function_le->text();
properties_.m_cable = ui -> m_cable_le->text();
properties_.m_bus = ui -> m_bus_le->text();
properties_.m_tension_protocol = ui -> m_tension_protocol_le->text();
properties_.m_wire_color = ui -> m_wire_color_le->text();
properties_.m_wire_section = ui -> m_wire_section_le->text();
properties_.text_size = ui -> m_text_size_sb -> value();
properties_.cond_size = ui -> m_cond_size_sb -> value();
properties_.m_show_text = ui -> m_show_text_cb -> isChecked();
properties_.m_one_text_per_folio = ui -> m_one_text_per_folio_cb -> isChecked();
properties_.verti_rotate_text = m_verti_select -> value();
properties_.horiz_rotate_text = m_horiz_select -> value();
properties_.m_vertical_alignment = ui->m_verti_cb->currentIndex() == 0? Qt::AlignLeft : Qt::AlignRight;
properties_.m_horizontal_alignment = ui->m_horiz_cb->currentIndex() == 0? Qt::AlignTop : Qt::AlignBottom;
properties_.singleLineProperties.hasGround = ui -> m_earth_cb -> isChecked();
properties_.singleLineProperties.hasNeutral = ui -> m_neutral_cb -> isChecked();
properties_.singleLineProperties.is_pen = ui -> m_pen_cb -> isChecked();
properties_.singleLineProperties.setPhasesCount(ui -> m_phase_cb -> isChecked() ? ui -> m_phase_sb -> value() : 0);
return properties_;
}
/**
@brief ConductorPropertiesWidget::event
@param event
@return
*/
bool ConductorPropertiesWidget::event(QEvent *event)
{
if (event->type() == QEvent::WindowActivate) {
ui -> m_formula_le -> setFocus();
}
return(QWidget::event(event));
}
/**
@brief ConductorPropertiesWidget::setReadOnly
@param ro if true this widget is disabled
*/
void ConductorPropertiesWidget::setReadOnly(const bool &ro) {
this->setDisabled(ro);
}
/**
@brief ConductorPropertiesWidget::addAutonumWidget
@param widget
*/
void ConductorPropertiesWidget::addAutonumWidget(QWidget *widget) {
ui->m_autonum_layout->addWidget(widget);
}
/**
@brief ConductorPropertiesWidget::setHiddenOneTextPerFolio
@param hide
*/
void ConductorPropertiesWidget::setHiddenOneTextPerFolio(const bool &hide) {
ui -> m_one_text_per_folio_cb -> setHidden(hide);
}
/**
@brief ConductorPropertiesWidget::setMixedTextFields
Mark the text fields whose value differs between several edited
conductors: they are shown blank, with a hint saying why.
@param mixed
*/
void ConductorPropertiesWidget::setMixedTextFields(
const QList<ConductorMultiEdit::TextField> &mixed)
{
using namespace ConductorMultiEdit;
const QList<QPair<TextField, QLineEdit *>> edits {
{Text, ui->m_text_le},
{Formula, ui->m_formula_le},
{Function, ui->m_function_le},
{TensionProtocol, ui->m_tension_protocol_le},
{WireColor, ui->m_wire_color_le},
{WireSection, ui->m_wire_section_le},
{Cable, ui->m_cable_le},
{Bus, ui->m_bus_le}};
for (const auto &edit : edits)
edit.second->setPlaceholderText(mixed.contains(edit.first)
? tr("Plusieurs valeurs", "several conductors, different values")
: QString());
}
/**
@brief ConductorPropertiesWidget::setTextLocked
Lock the conductor text while several conductors are edited at once:
the same number on all of them would make duplicates.
@param locked
*/
void ConductorPropertiesWidget::setTextLocked(bool locked)
{
m_text_locked = locked;
ui->m_text_le->setEnabled(!locked && ui->m_formula_le->text().isEmpty());
ui->m_text_le->setToolTip(locked
? tr("Plusieurs conducteurs sélectionnés : le texte se modifie "
"sur un seul conducteur à la fois.")
: tr("Texte"));
}
/**
@brief ConductorPropertiesWidget::setDisabledShowText
@param disable
*/
void ConductorPropertiesWidget::setDisabledShowText(const bool &disable) {
ui->m_show_text_cb->setDisabled(disable==true? true : false);
}
/**
@brief ConductorPropertiesWidget::setHiddenAvailableAutonum
Hide the label, combo box and push button of available autonum
@param hide
*/
void ConductorPropertiesWidget::setHiddenAvailableAutonum(const bool &hide)
{
ui->m_autonum_label->setHidden(hide);
ui->m_available_autonum_cb->setHidden(hide);
ui->m_edit_autonum_pb->setHidden(hide);
}
QComboBox *ConductorPropertiesWidget::autonumComboBox() const
{
return ui->m_available_autonum_cb;
}
QPushButton *ConductorPropertiesWidget::editAutonumPushButton() const
{
return ui->m_edit_autonum_pb;
}
/**
@brief ConductorPropertiesWidget::initWidget
*/
void ConductorPropertiesWidget::initWidget()
{
m_verti_select = QETApp::createTextOrientationSpinBoxWidget();
ui -> m_text_angle_gl -> addWidget(m_verti_select, 2, 0, Qt::AlignHCenter);
m_horiz_select = QETApp::createTextOrientationSpinBoxWidget();
ui -> m_text_angle_gl -> addWidget(m_horiz_select, 2, 1, Qt::AlignHCenter);
ui -> m_line_style_cb -> addItem(tr("Trait plein", "conductor style: solid line"), QPen(Qt::SolidLine));
ui -> m_line_style_cb -> addItem(tr("Trait en pointillés", "conductor style: dashed line"), QPen(Qt::DashLine));
ui -> m_line_style_cb -> addItem(tr("Traits et points", "conductor style: dashed and dotted line"), QPen(Qt::DashDotLine));
ui -> m_update_preview_pb -> setHidden(true);
connect(ui->m_multiwires_gb, &QGroupBox::toggled, [this](bool toggle) {this->ui->m_singlewire_gb->setChecked(!toggle);});
connect(ui->m_singlewire_gb, &QGroupBox::toggled, [this](bool toggle) {this->ui->m_multiwires_gb->setChecked(!toggle);});
connect(ui->m_formula_le, &QLineEdit::textChanged, [this](QString text) {this->ui->m_text_le->setEnabled(!m_text_locked && text.isEmpty());});
ui->m_multiwires_gb->setChecked(true);
ui->m_singlewire_gb->setChecked(true);
#if TODO_LIST
#pragma message("@TODO Add Kabel and Bus to qet")
#else
ui->m_cable_le->setDisabled(true);
ui->m_bus_le->setDisabled(true);
#endif
}
/**
@brief ConductorPropertiesWidget::setConductorType
Update this widget to the new conductor type
@param type
*/
void ConductorPropertiesWidget::setConductorType(ConductorProperties::ConductorType type) {
switch (type) {
case ConductorProperties::Multi:
ui -> m_multiwires_gb -> setChecked(true);
break;
case ConductorProperties::Single:
ui -> m_singlewire_gb -> setChecked(true);
break;
default:
ui -> m_multiwires_gb -> setChecked(true);
break;
}
}
/**
@brief ConductorPropertiesWidget::updatePreview
Update the preview for single lien
@param b true: update from the value displayed by this widget
false: update from the properties given at the constructor of this widget
*/
void ConductorPropertiesWidget::updatePreview(bool b) {
const QRect pixmap_rect(0, 0, 96, 96);
QPixmap pixmap(pixmap_rect.width(), pixmap_rect.height());
QPainter painter;
painter.begin(&pixmap);
painter.eraseRect(pixmap_rect);
painter.drawRect(pixmap_rect.adjusted(0,0,-1,-1));
painter.drawLine(QLineF(0, pixmap_rect.height() / 2, pixmap_rect.width(), pixmap_rect.height() / 2));
if (b) properties().singleLineProperties.draw(&painter, QET::Horizontal, pixmap_rect);
else m_properties.singleLineProperties.draw(&painter, QET::Horizontal, pixmap_rect);
painter.end();
ui -> m_preview_label -> setPixmap(pixmap);
}
/**
@brief ConductorPropertiesWidget::on_m_earth_cb_toggled
Update the widget when toggled
@param checked
*/
void ConductorPropertiesWidget::on_m_earth_cb_toggled(bool checked) {
if (checked && ui -> m_neutral_cb -> isChecked())
ui -> m_pen_cb -> setEnabled(true);
else ui -> m_pen_cb -> setDisabled(true);
}
/**
@brief ConductorPropertiesWidget::on_m_neutral_cb_toggled
Update the widget when toggled
@param checked
*/
void ConductorPropertiesWidget::on_m_neutral_cb_toggled(bool checked) {
if (checked && ui -> m_earth_cb -> isChecked())
ui -> m_pen_cb -> setEnabled(true);
else ui -> m_pen_cb -> setDisabled(true);
}
/**
@brief ConductorPropertiesWidget::on_m_update_preview_pb_clicked
Update the preview of single line.
m_update_preview_pb is a no used button and hidden, his role is only
to centralize signal from various widget to edit single ligne properties,
for update the preview
*/
void ConductorPropertiesWidget::on_m_update_preview_pb_clicked()
{
updatePreview();
}