Merge pull request #444 from Kellermorph/master

Follow-up: Address review comments for slave limit feature
This commit is contained in:
Laurent Trinques
2026-04-02 11:47:21 +02:00
committed by GitHub
10 changed files with 305 additions and 173 deletions

View File

@@ -1,4 +1,4 @@
/* /*
Copyright 2006-2026 The QElectroTech Team Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech. This file is part of QElectroTech.
@@ -96,8 +96,18 @@ void ElementPropertiesEditorWidget::upDateInterface()
} }
else if (m_data.m_type == ElementData::Master) { else if (m_data.m_type == ElementData::Master) {
ui->m_master_type_cb->setCurrentIndex( ui->m_master_type_cb->setCurrentIndex(
ui->m_master_type_cb->findData ( ui->m_master_type_cb->findData (
m_data.m_master_type)); m_data.m_master_type));
// NEU: Checkbox und Zahlenbox für max_slaves einstellen
if (m_data.m_max_slaves == -1) {
ui->max_slaves_checkbox->setChecked(false);
ui->max_slaves_spinbox->setEnabled(false);
} else {
ui->max_slaves_checkbox->setChecked(true);
ui->max_slaves_spinbox->setEnabled(true);
ui->max_slaves_spinbox->setValue(m_data.m_max_slaves);
}
} else if (m_data.m_type == ElementData::Terminal) { } else if (m_data.m_type == ElementData::Terminal) {
ui->m_terminal_type_cb->setCurrentIndex( ui->m_terminal_type_cb->setCurrentIndex(
ui->m_terminal_type_cb->findData( ui->m_terminal_type_cb->findData(
@@ -151,10 +161,13 @@ void ElementPropertiesEditorWidget::setUpInterface()
ui->m_terminal_func_cb->addItem(tr("Phase"), ElementData::TFPhase); ui->m_terminal_func_cb->addItem(tr("Phase"), ElementData::TFPhase);
ui->m_terminal_func_cb->addItem(tr("Neutre"), ElementData::TFNeutral); ui->m_terminal_func_cb->addItem(tr("Neutre"), ElementData::TFNeutral);
//Disable the edition of the first column of the information tree //Disable the edition of the first column of the information tree
//by this little workaround //by this little workaround
ui->m_tree->setItemDelegate(new EditorDelegate(this)); ui->m_tree->setItemDelegate(new EditorDelegate(this));
ui->m_tree->header()->resizeSection(0, 150);
// NEU: Checkbox mit der Zahlenbox verbinden (Aktivieren/Deaktivieren)
connect(ui->max_slaves_checkbox, SIGNAL(toggled(bool)), ui->max_slaves_spinbox, SLOT(setEnabled(bool)));
populateTree(); populateTree();
} }
@@ -226,6 +239,13 @@ void ElementPropertiesEditorWidget::on_m_buttonBox_accepted()
} }
else if (m_data.m_type == ElementData::Master) { else if (m_data.m_type == ElementData::Master) {
m_data.m_master_type = ui->m_master_type_cb->currentData().value<ElementData::MasterType>(); m_data.m_master_type = ui->m_master_type_cb->currentData().value<ElementData::MasterType>();
//If the checkbox is checked, save the number; otherwise, -1 (infinity)
if (ui->max_slaves_checkbox->isChecked()) {
m_data.m_max_slaves = ui->max_slaves_spinbox->value();
} else {
m_data.m_max_slaves = -1;
}
} }
else if (m_data.m_type == ElementData::Terminal) else if (m_data.m_type == ElementData::Terminal)
{ {

View File

@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>527</width> <width>527</width>
<height>442</height> <height>492</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -104,6 +104,23 @@
<item row="0" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="m_master_type_cb"/> <widget class="QComboBox" name="m_master_type_cb"/>
</item> </item>
<item row="1" column="0">
<widget class="QCheckBox" name="max_slaves_checkbox">
<property name="text">
<string>Définir le nombre maximal d'esclaves</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="max_slaves_spinbox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@@ -76,6 +76,16 @@ QDomElement ElementData::kindInfoToXml(QDomDocument &document)
xml_type.appendChild(type_txt); xml_type.appendChild(type_txt);
returned_elmt.appendChild(xml_type); returned_elmt.appendChild(xml_type);
// Save max_slaves only if a specific limit is set (not default -1)
if (m_max_slaves != -1) {
auto xml_max_slaves = document.createElement(QStringLiteral("kindInformation"));
xml_max_slaves.setAttribute(QStringLiteral("name"), QStringLiteral("max_slaves"));
auto max_slaves_txt = document.createTextNode(QString::number(m_max_slaves));
xml_max_slaves.appendChild(max_slaves_txt);
returned_elmt.appendChild(xml_max_slaves);
}
} }
else if (m_type == ElementData::Slave) else if (m_type == ElementData::Slave)
{ {
@@ -558,9 +568,12 @@ void ElementData::kindInfoFromXml(const QDomElement &xml_element)
} }
auto name = dom_elmt.attribute(QStringLiteral("name")); auto name = dom_elmt.attribute(QStringLiteral("name"));
if (m_type == ElementData::Master && if (m_type == ElementData::Master) {
name == QLatin1String("type")) { if (name == QLatin1String("type")) {
m_master_type = masterTypeFromString(dom_elmt.text()); m_master_type = masterTypeFromString(dom_elmt.text());
} else if (name == QLatin1String("max_slaves")) {
m_max_slaves = dom_elmt.text().toInt();
}
} }
else if (m_type == ElementData::Slave ) { else if (m_type == ElementData::Slave ) {
if (name == QLatin1String("type")) { if (name == QLatin1String("type")) {

View File

@@ -134,6 +134,7 @@ class ElementData : public PropertiesInterface
ElementData::Type m_type = ElementData::Simple; ElementData::Type m_type = ElementData::Simple;
ElementData::MasterType m_master_type = ElementData::Coil; ElementData::MasterType m_master_type = ElementData::Coil;
int m_max_slaves{-1};
ElementData::SlaveType m_slave_type = ElementData::SSimple; ElementData::SlaveType m_slave_type = ElementData::SSimple;
ElementData::SlaveState m_slave_state = ElementData::NO; ElementData::SlaveState m_slave_state = ElementData::NO;
@@ -141,7 +142,7 @@ class ElementData : public PropertiesInterface
ElementData::TerminalType m_terminal_type = ElementData::TTGeneric; ElementData::TerminalType m_terminal_type = ElementData::TTGeneric;
ElementData::TerminalFunction m_terminal_function = ElementData::TFGeneric; ElementData::TerminalFunction m_terminal_function = ElementData::TFGeneric;
int m_contact_count = 1; int m_contact_count{1};
DiagramContext m_informations; DiagramContext m_informations;
NamesList m_names_list; NamesList m_names_list;
QString m_drawing_information; QString m_drawing_information;

View File

@@ -1351,6 +1351,7 @@ void DynamicElementTextItem::updateXref()
{ {
m_slave_Xref_item = new QGraphicsTextItem(xref_label, this); m_slave_Xref_item = new QGraphicsTextItem(xref_label, this);
m_slave_Xref_item->setFont(QETApp::diagramTextsFont(5)); m_slave_Xref_item->setFont(QETApp::diagramTextsFont(5));
m_slave_Xref_item->setDefaultTextColor(Qt::black);
m_slave_Xref_item->installSceneEventFilter(this); m_slave_Xref_item->installSceneEventFilter(this);
m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::xChanged, this, &DynamicElementTextItem::updateXref); m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::xChanged, this, &DynamicElementTextItem::updateXref);

View File

@@ -183,3 +183,27 @@ void MasterElement::aboutDeleteXref()
return; return;
} }
} }
/**
* @brief MasterElement::isFull
* @return true if the master has reached its maximum number of slaves
*/
bool MasterElement::isFull() const
{
// Set default value to -1 (unlimited slaves)
int max_slaves = -1;
QVariant max_slaves_variant = kindInformations().value("max_slaves");
// Overwrite default if a valid limit is defined in the element's XML
if (max_slaves_variant.isValid() && !max_slaves_variant.toString().isEmpty()) {
max_slaves = max_slaves_variant.toInt();
}
// If no limit is set (-1), the master is never full
if (max_slaves == -1) {
return false;
}
// Return true if current connected elements reached or exceeded the limit
return connected_elements.size() >= max_slaves;
}

View File

@@ -44,6 +44,8 @@ class MasterElement : public Element
void unlinkElement (Element *elmt) override; void unlinkElement (Element *elmt) override;
void initLink (QETProject *project) override; void initLink (QETProject *project) override;
QRectF XrefBoundingRect() const; QRectF XrefBoundingRect() const;
bool isFull() const; // Check Slave-Limit
protected: protected:
QVariant itemChange( QVariant itemChange(

View File

@@ -16,7 +16,7 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>. along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "linksingleelementwidget.h" #include "linksingleelementwidget.h"
#include "../qetgraphicsitem/masterelement.h"
#include "../qetgraphicsitem/conductor.h" #include "../qetgraphicsitem/conductor.h"
#include "../diagram.h" #include "../diagram.h"
#include "../diagramposition.h" #include "../diagramposition.h"
@@ -386,7 +386,22 @@ QVector <QPointer<Element>> LinkSingleElementWidget::availableElements()
//If element is linked, remove is parent from the list //If element is linked, remove is parent from the list
if(!m_element->isFree()) elmt_vector.removeAll(m_element->linkedElements().first()); if(!m_element->isFree()) elmt_vector.removeAll(m_element->linkedElements().first());
// Filter out all master elements from the list
for (int i = elmt_vector.size() - 1; i >= 0; --i) {
Element *elmt = elmt_vector.at(i);
// If the item in the list is a master
if (elmt->linkType() == Element::Master) {
// We convert the generic element pointer into a MasterElement pointer
MasterElement *master = static_cast<MasterElement*>(elmt);
// If the master is full, we'll remove it from the list!
if (master->isFull()) {
elmt_vector.removeAt(i);
}
}
}
return elmt_vector; return elmt_vector;
} }

View File

@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>389</width> <width>389</width>
<height>442</height> <height>460</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -64,6 +64,23 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="3">
<widget class="QLabel" name="m_hidden_masters_label">
<property name="text">
<string>Remarque : les éléments maîtres ayant atteint leur nombre maximal d'esclaves sont masqués.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@@ -1,20 +1,20 @@
/* /*
Copyright 2006-2026 The QElectroTech Team * Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech. * This file is part of QElectroTech.
*
QElectroTech is free software: you can redistribute it and/or modify * QElectroTech is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or * the Free Software Foundation, either version 2 of the License, or
(at your option) any later version. * (at your option) any later version.
*
QElectroTech is distributed in the hope that it will be useful, * QElectroTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. * GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>. * along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "masterpropertieswidget.h" #include "masterpropertieswidget.h"
#include "../diagram.h" #include "../diagram.h"
@@ -25,64 +25,65 @@
#include "ui_masterpropertieswidget.h" #include "ui_masterpropertieswidget.h"
#include <QListWidgetItem> #include <QListWidgetItem>
#include <QMessageBox>
/** /**
@brief MasterPropertiesWidget::MasterPropertiesWidget * @brief MasterPropertiesWidget::MasterPropertiesWidget
Default constructor * Default constructor
@param elmt * @param elmt
@param parent * @param parent
*/ */
MasterPropertiesWidget::MasterPropertiesWidget(Element *elmt, QWidget *parent) : MasterPropertiesWidget::MasterPropertiesWidget(Element *elmt, QWidget *parent) :
AbstractElementPropertiesEditorWidget(parent), AbstractElementPropertiesEditorWidget(parent),
ui(new Ui::MasterPropertiesWidget), ui(new Ui::MasterPropertiesWidget),
m_project(nullptr) m_project(nullptr)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->m_free_tree_widget->setContextMenuPolicy(Qt::CustomContextMenu); ui->m_free_tree_widget->setContextMenuPolicy(Qt::CustomContextMenu);
ui->m_link_tree_widget->setContextMenuPolicy(Qt::CustomContextMenu); ui->m_link_tree_widget->setContextMenuPolicy(Qt::CustomContextMenu);
QStringList list; QStringList list;
QSettings settings; QSettings settings;
if (settings.value("genericpanel/folio", false).toBool()) { if (settings.value("genericpanel/folio", false).toBool()) {
list << tr("Vignette") list << tr("Vignette")
<< tr("Label de folio") << tr("Label de folio")
<< tr("Titre de folio") << tr("Titre de folio")
<< tr("Position"); << tr("Position");
} }
else { else {
list << tr("Vignette") list << tr("Vignette")
<< tr("N° de folio") << tr("N° de folio")
<< tr("Titre de folio") << tr("Titre de folio")
<< tr("Position"); << tr("Position");
} }
ui->m_free_tree_widget->setHeaderLabels(list); ui->m_free_tree_widget->setHeaderLabels(list);
ui->m_link_tree_widget->setHeaderLabels(list); ui->m_link_tree_widget->setHeaderLabels(list);
m_context_menu = new QMenu(this); m_context_menu = new QMenu(this);
m_link_action = new QAction(tr("Lier l'élément"), this); m_link_action = new QAction(tr("Lier l'élément"), this);
m_unlink_action = new QAction(tr("Délier l'élément"), this); m_unlink_action = new QAction(tr("Délier l'élément"), this);
m_show_qtwi = new QAction(tr("Montrer l'élément"), this); m_show_qtwi = new QAction(tr("Montrer l'élément"), this);
m_show_element = new QAction(tr("Montrer l'élément maître"), this); m_show_element = new QAction(tr("Montrer l'élément maître"), this);
m_save_header_state = new QAction(tr("Enregistrer la disposition"), this); m_save_header_state = new QAction(tr("Enregistrer la disposition"), this);
connect(ui->m_free_tree_widget, &QTreeWidget::itemDoubleClicked, connect(ui->m_free_tree_widget, &QTreeWidget::itemDoubleClicked,
this, &MasterPropertiesWidget::showElementFromTWI); this, &MasterPropertiesWidget::showElementFromTWI);
connect(ui->m_link_tree_widget, &QTreeWidget::itemDoubleClicked, connect(ui->m_link_tree_widget, &QTreeWidget::itemDoubleClicked,
this, &MasterPropertiesWidget::showElementFromTWI); this, &MasterPropertiesWidget::showElementFromTWI);
connect(ui->m_free_tree_widget, &QTreeWidget::customContextMenuRequested, connect(ui->m_free_tree_widget, &QTreeWidget::customContextMenuRequested,
[this](QPoint point) {this->customContextMenu(point, 1);}); [this](QPoint point) {this->customContextMenu(point, 1);});
connect(ui->m_link_tree_widget, &QTreeWidget::customContextMenuRequested, connect(ui->m_link_tree_widget, &QTreeWidget::customContextMenuRequested,
[this](QPoint point) {this->customContextMenu(point, 2);}); [this](QPoint point) {this->customContextMenu(point, 2);});
connect(m_link_action, &QAction::triggered, connect(m_link_action, &QAction::triggered,
this, &MasterPropertiesWidget::on_link_button_clicked); this, &MasterPropertiesWidget::on_link_button_clicked);
connect(m_unlink_action, &QAction::triggered, connect(m_unlink_action, &QAction::triggered,
this, &MasterPropertiesWidget::on_unlink_button_clicked); this, &MasterPropertiesWidget::on_unlink_button_clicked);
connect(m_show_qtwi, &QAction::triggered, connect(m_show_qtwi, &QAction::triggered,
[this]() {this->showElementFromTWI(this->m_qtwi_at_context_menu,0);}); [this]() {this->showElementFromTWI(this->m_qtwi_at_context_menu,0);});
connect(m_show_element, &QAction::triggered, [this]() connect(m_show_element, &QAction::triggered, [this]()
{ {
this->m_element->diagram()->showMe(); this->m_element->diagram()->showMe();
@@ -90,46 +91,46 @@ MasterPropertiesWidget::MasterPropertiesWidget(Element *elmt, QWidget *parent) :
if(this->m_showed_element) if(this->m_showed_element)
m_showed_element->setHighlighted(false); m_showed_element->setHighlighted(false);
}); });
QHeaderView *qhv = ui->m_free_tree_widget->header(); QHeaderView *qhv = ui->m_free_tree_widget->header();
qhv->setContextMenuPolicy(Qt::CustomContextMenu); qhv->setContextMenuPolicy(Qt::CustomContextMenu);
connect(qhv, &QHeaderView::customContextMenuRequested, connect(qhv, &QHeaderView::customContextMenuRequested,
this, &MasterPropertiesWidget::headerCustomContextMenuRequested); this, &MasterPropertiesWidget::headerCustomContextMenuRequested);
connect(m_save_header_state, &QAction::triggered, [qhv]() connect(m_save_header_state, &QAction::triggered, [qhv]()
{ {
QByteArray qba = qhv->saveState(); QByteArray qba = qhv->saveState();
QSettings settings; QSettings settings;
settings.setValue("link-element-widget/master-state", qba); settings.setValue("link-element-widget/master-state", qba);
}); });
setElement(elmt); setElement(elmt);
} }
/** /**
@brief MasterPropertiesWidget::~MasterPropertiesWidget * @brief MasterPropertiesWidget::~MasterPropertiesWidget
Destructor * Destructor
*/ */
MasterPropertiesWidget::~MasterPropertiesWidget() MasterPropertiesWidget::~MasterPropertiesWidget()
{ {
if (m_showed_element) if (m_showed_element)
m_showed_element->setHighlighted(false); m_showed_element->setHighlighted(false);
if(m_element) if(m_element)
m_element->setHighlighted(false); m_element->setHighlighted(false);
delete ui; delete ui;
} }
/** /**
@brief MasterPropertiesWidget::setElement * @brief MasterPropertiesWidget::setElement
Set the element to be edited * Set the element to be edited
@param element * @param element
*/ */
void MasterPropertiesWidget::setElement(Element *element) void MasterPropertiesWidget::setElement(Element *element)
{ {
if (m_element == element) if (m_element == element)
return; return;
if (m_showed_element) if (m_showed_element)
{ {
m_showed_element->setHighlighted(false); m_showed_element->setHighlighted(false);
@@ -137,40 +138,40 @@ void MasterPropertiesWidget::setElement(Element *element)
} }
if (m_element) if (m_element)
m_element->setHighlighted(false); m_element->setHighlighted(false);
if (m_project) if (m_project)
disconnect(m_project, SIGNAL(diagramRemoved(QETProject*,Diagram*)), disconnect(m_project, SIGNAL(diagramRemoved(QETProject*,Diagram*)),
this, SLOT(diagramWasdeletedFromProject())); this, SLOT(diagramWasdeletedFromProject()));
if(Q_LIKELY(element->diagram() && element->diagram()->project())) if(Q_LIKELY(element->diagram() && element->diagram()->project()))
{ {
m_project = element->diagram()->project(); m_project = element->diagram()->project();
connect(m_project, SIGNAL(diagramRemoved(QETProject*,Diagram*)), connect(m_project, SIGNAL(diagramRemoved(QETProject*,Diagram*)),
this, SLOT(diagramWasdeletedFromProject())); this, SLOT(diagramWasdeletedFromProject()));
} }
else else
m_project = nullptr; m_project = nullptr;
//Keep up to date this widget when the linked elements of m_element change //Keep up to date this widget when the linked elements of m_element change
if (m_element) if (m_element)
disconnect(m_element.data(), &Element::linkedElementChanged, disconnect(m_element.data(), &Element::linkedElementChanged,
this, &MasterPropertiesWidget::updateUi); this, &MasterPropertiesWidget::updateUi);
m_element = element; m_element = element;
connect(m_element.data(), &Element::linkedElementChanged, connect(m_element.data(), &Element::linkedElementChanged,
this, &MasterPropertiesWidget::updateUi); this, &MasterPropertiesWidget::updateUi);
updateUi(); updateUi();
} }
/** /**
@brief MasterPropertiesWidget::apply * @brief MasterPropertiesWidget::apply
If link between edited element and other change, * If link between edited element and other change,
apply the change with a QUndoCommand (got with method associatedUndo) * apply the change with a QUndoCommand (got with method associatedUndo)
pushed to the stack of element project. * pushed to the stack of element project.
Return true if link change, else false * Return true if link change, else false
@note is void no Return ??? * @note is void no Return ???
*/ */
void MasterPropertiesWidget::apply() void MasterPropertiesWidget::apply()
{ {
if (QUndoCommand *undo = associatedUndo()) if (QUndoCommand *undo = associatedUndo())
@@ -178,25 +179,25 @@ void MasterPropertiesWidget::apply()
} }
/** /**
@brief MasterPropertiesWidget::reset * @brief MasterPropertiesWidget::reset
Reset current widget, clear eveything and rebuild widget. * Reset current widget, clear eveything and rebuild widget.
*/ */
void MasterPropertiesWidget::reset() void MasterPropertiesWidget::reset()
{ {
foreach (QTreeWidgetItem *qtwi, m_qtwi_hash.keys()) foreach (QTreeWidgetItem *qtwi, m_qtwi_hash.keys())
delete qtwi; delete qtwi;
m_qtwi_hash.clear(); m_qtwi_hash.clear();
updateUi(); updateUi();
} }
/** /**
@brief MasterPropertiesWidget::associatedUndo * @brief MasterPropertiesWidget::associatedUndo
If link between the edited element and other change, * If link between the edited element and other change,
return a QUndoCommand with this change. * return a QUndoCommand with this change.
If no change return nullptr. * If no change return nullptr.
@return * @return
*/ */
QUndoCommand* MasterPropertiesWidget::associatedUndo() const QUndoCommand* MasterPropertiesWidget::associatedUndo() const
{ {
QList <Element *> to_link; QList <Element *> to_link;
@@ -205,7 +206,7 @@ QUndoCommand* MasterPropertiesWidget::associatedUndo() const
for (int i=0; i<ui->m_link_tree_widget->topLevelItemCount(); i++) for (int i=0; i<ui->m_link_tree_widget->topLevelItemCount(); i++)
to_link << m_qtwi_hash[ui->m_link_tree_widget->topLevelItem(i)]; to_link << m_qtwi_hash[ui->m_link_tree_widget->topLevelItem(i)];
//The two list contain the same element, there is no change //The two list contain the same element, there is no change
if (to_link.size() == linked_.size()) if (to_link.size() == linked_.size())
{ {
bool equal = true; bool equal = true;
@@ -229,11 +230,11 @@ QUndoCommand* MasterPropertiesWidget::associatedUndo() const
} }
/** /**
@brief MasterPropertiesWidget::setLiveEdit * @brief MasterPropertiesWidget::setLiveEdit
@param live_edit = true : live edit is enable * @param live_edit = true : live edit is enable
else false : live edit is disable. * else false : live edit is disable.
@return always true because live edit is handled by this editor widget * @return always true because live edit is handled by this editor widget
*/ */
bool MasterPropertiesWidget::setLiveEdit(bool live_edit) bool MasterPropertiesWidget::setLiveEdit(bool live_edit)
{ {
m_live_edit = live_edit; m_live_edit = live_edit;
@@ -241,9 +242,9 @@ bool MasterPropertiesWidget::setLiveEdit(bool live_edit)
} }
/** /**
@brief MasterPropertiesWidget::updateUi * @brief MasterPropertiesWidget::updateUi
Build the interface of the widget * Build the interface of the widget
*/ */
void MasterPropertiesWidget::updateUi() void MasterPropertiesWidget::updateUi()
{ {
ui->m_free_tree_widget->clear(); ui->m_free_tree_widget->clear();
@@ -256,75 +257,75 @@ void MasterPropertiesWidget::updateUi()
ElementProvider elmt_prov(m_project); ElementProvider elmt_prov(m_project);
QSettings settings; QSettings settings;
//Build the list of free available element //Build the list of free available element
QList <QTreeWidgetItem *> items_list; QList <QTreeWidgetItem *> items_list;
for(const auto &elmt : elmt_prov.freeElement(ElementData::Slave)) for(const auto &elmt : elmt_prov.freeElement(ElementData::Slave))
{ {
QTreeWidgetItem *qtwi = new QTreeWidgetItem(ui->m_free_tree_widget); QTreeWidgetItem *qtwi = new QTreeWidgetItem(ui->m_free_tree_widget);
qtwi->setIcon(0, elmt->pixmap()); qtwi->setIcon(0, elmt->pixmap());
if(settings.value("genericpanel/folio", false).toBool()) if(settings.value("genericpanel/folio", false).toBool())
{ {
autonum::sequentialNumbers seq; autonum::sequentialNumbers seq;
QString F =autonum::AssignVariables::formulaToLabel( QString F =autonum::AssignVariables::formulaToLabel(
elmt->diagram()->border_and_titleblock.folio(), elmt->diagram()->border_and_titleblock.folio(),
seq, seq,
elmt->diagram(), elmt->diagram(),
elmt); elmt);
qtwi->setText(1, F); qtwi->setText(1, F);
} }
else else
{ {
qtwi->setText(1, QString::number( qtwi->setText(1, QString::number(
elmt->diagram()->folioIndex() elmt->diagram()->folioIndex()
+ 1)); + 1));
} }
qtwi->setText(2, elmt->diagram()->title()); qtwi->setText(2, elmt->diagram()->title());
qtwi->setText(4, elmt->diagram()->convertPosition( qtwi->setText(4, elmt->diagram()->convertPosition(
elmt->scenePos()).toString()); elmt->scenePos()).toString());
items_list.append(qtwi); items_list.append(qtwi);
m_qtwi_hash.insert(qtwi, elmt); m_qtwi_hash.insert(qtwi, elmt);
} }
ui->m_free_tree_widget->addTopLevelItems(items_list); ui->m_free_tree_widget->addTopLevelItems(items_list);
items_list.clear(); items_list.clear();
//Build the list of already linked element //Build the list of already linked element
const QList<Element *> link_list = m_element->linkedElements(); const QList<Element *> link_list = m_element->linkedElements();
for(Element *elmt : link_list) for(Element *elmt : link_list)
{ {
QTreeWidgetItem *qtwi = new QTreeWidgetItem(ui->m_link_tree_widget); QTreeWidgetItem *qtwi = new QTreeWidgetItem(ui->m_link_tree_widget);
qtwi->setIcon(0, elmt->pixmap()); qtwi->setIcon(0, elmt->pixmap());
if(settings.value("genericpanel/folio", false).toBool()) if(settings.value("genericpanel/folio", false).toBool())
{ {
autonum::sequentialNumbers seq; autonum::sequentialNumbers seq;
QString F =autonum::AssignVariables::formulaToLabel( QString F =autonum::AssignVariables::formulaToLabel(
elmt->diagram()->border_and_titleblock.folio(), elmt->diagram()->border_and_titleblock.folio(),
seq, seq,
elmt->diagram(), elmt->diagram(),
elmt); elmt);
qtwi->setText(1, F); qtwi->setText(1, F);
} }
else else
{ {
qtwi->setText(1, QString::number( qtwi->setText(1, QString::number(
elmt->diagram()->folioIndex() elmt->diagram()->folioIndex()
+ 1)); + 1));
} }
qtwi->setText(2, elmt->diagram()->title()); qtwi->setText(2, elmt->diagram()->title());
qtwi->setText(3, elmt->diagram()->convertPosition( qtwi->setText(3, elmt->diagram()->convertPosition(
elmt->scenePos()).toString()); elmt->scenePos()).toString());
items_list.append(qtwi); items_list.append(qtwi);
m_qtwi_hash.insert(qtwi, elmt); m_qtwi_hash.insert(qtwi, elmt);
} }
if(items_list.count()) if(items_list.count())
ui->m_link_tree_widget->addTopLevelItems(items_list); ui->m_link_tree_widget->addTopLevelItems(items_list);
QVariant v = settings.value("link-element-widget/master-state"); QVariant v = settings.value("link-element-widget/master-state");
if(!v.isNull()) if(!v.isNull())
{ {
@@ -334,9 +335,9 @@ void MasterPropertiesWidget::updateUi()
} }
/** /**
@brief MasterPropertiesWidget::headerCustomContextMenuRequested * @brief MasterPropertiesWidget::headerCustomContextMenuRequested
@param pos * @param pos
*/ */
void MasterPropertiesWidget::headerCustomContextMenuRequested(const QPoint &pos) void MasterPropertiesWidget::headerCustomContextMenuRequested(const QPoint &pos)
{ {
m_context_menu->clear(); m_context_menu->clear();
@@ -345,36 +346,57 @@ void MasterPropertiesWidget::headerCustomContextMenuRequested(const QPoint &pos)
} }
/** /**
@brief MasterPropertiesWidget::on_link_button_clicked * @brief MasterPropertiesWidget::on_link_button_clicked
move current item in the free_list to linked_list * Moves the current item from the free_list to the linked_list,
*/ * provided the master's slave limit has not been reached.
*/
void MasterPropertiesWidget::on_link_button_clicked() void MasterPropertiesWidget::on_link_button_clicked()
{ {
//take the current item from free_list and push it to linked_list // Get the maximum number of allowed slaves from the element's information
QVariant max_slaves_variant = m_element->kindInformations().value("max_slaves");
if (max_slaves_variant.isValid() && !max_slaves_variant.toString().isEmpty()) {
int max_slaves = max_slaves_variant.toInt();
int current_slaves = ui->m_link_tree_widget->topLevelItemCount();
// If a limit is set and reached
if (max_slaves != -1 && current_slaves >= max_slaves) {
// Show a message box with the actual window as parent to ensure it's on top
QMessageBox::warning(this->window(),
tr("Nombre maximal d'esclaves atteint."),
tr("Cet élément maître ne peut accepter aucun nouvel esclave car il est plein (Limit: %1).").arg(max_slaves));
return;
}
}
// Move current item from free_list to linked_list
QTreeWidgetItem *qtwi = ui->m_free_tree_widget->currentItem(); QTreeWidgetItem *qtwi = ui->m_free_tree_widget->currentItem();
if (qtwi) if (qtwi)
{ {
ui->m_free_tree_widget->takeTopLevelItem( ui->m_free_tree_widget->takeTopLevelItem(
ui->m_free_tree_widget->indexOfTopLevelItem(qtwi)); ui->m_free_tree_widget->indexOfTopLevelItem(qtwi));
ui->m_link_tree_widget->insertTopLevelItem(0, qtwi); ui->m_link_tree_widget->insertTopLevelItem(0, qtwi);
if(m_live_edit) if(m_live_edit)
apply(); apply();
} }
} }
/** /**
@brief MasterPropertiesWidget::on_unlink_button_clicked * @brief MasterPropertiesWidget::on_unlink_button_clicked
move current item in linked_list to free_list * move current item in linked_list to free_list
*/ */
void MasterPropertiesWidget::on_unlink_button_clicked() void MasterPropertiesWidget::on_unlink_button_clicked()
{ {
//take the current item from linked_list and push it to free_list //take the current item from linked_list and push it to free_list
QTreeWidgetItem *qtwi = ui->m_link_tree_widget->currentItem(); QTreeWidgetItem *qtwi = ui->m_link_tree_widget->currentItem();
if(qtwi) if(qtwi)
{ {
ui->m_link_tree_widget->takeTopLevelItem( ui->m_link_tree_widget->takeTopLevelItem(
ui->m_link_tree_widget->indexOfTopLevelItem(qtwi)); ui->m_link_tree_widget->indexOfTopLevelItem(qtwi));
ui->m_free_tree_widget->insertTopLevelItem(0, qtwi); ui->m_free_tree_widget->insertTopLevelItem(0, qtwi);
if(m_live_edit) if(m_live_edit)
@@ -383,18 +405,18 @@ void MasterPropertiesWidget::on_unlink_button_clicked()
} }
/** /**
@brief MasterPropertiesWidget::showElementFromTWI * @brief MasterPropertiesWidget::showElementFromTWI
Show the element corresponding to the given QTreeWidgetItem * Show the element corresponding to the given QTreeWidgetItem
@param qtwi * @param qtwi
@param column * @param column
*/ */
void MasterPropertiesWidget::showElementFromTWI(QTreeWidgetItem *qtwi, int column) void MasterPropertiesWidget::showElementFromTWI(QTreeWidgetItem *qtwi, int column)
{ {
Q_UNUSED(column); Q_UNUSED(column);
if (m_showed_element) if (m_showed_element)
{ {
disconnect(m_showed_element, SIGNAL(destroyed()), disconnect(m_showed_element, SIGNAL(destroyed()),
this, SLOT(showedElementWasDeleted())); this, SLOT(showedElementWasDeleted()));
m_showed_element -> setHighlighted(false); m_showed_element -> setHighlighted(false);
} }
if (m_element) if (m_element)
@@ -404,23 +426,23 @@ void MasterPropertiesWidget::showElementFromTWI(QTreeWidgetItem *qtwi, int colum
m_showed_element->diagram()->showMe(); m_showed_element->diagram()->showMe();
m_showed_element->setHighlighted(true); m_showed_element->setHighlighted(true);
connect(m_showed_element, SIGNAL(destroyed()), connect(m_showed_element, SIGNAL(destroyed()),
this, SLOT(showedElementWasDeleted())); this, SLOT(showedElementWasDeleted()));
} }
/** /**
@brief MasterPropertiesWidget::showedElementWasDeleted * @brief MasterPropertiesWidget::showedElementWasDeleted
Set to nullptr the current showed element when he was deleted * Set to nullptr the current showed element when he was deleted
*/ */
void MasterPropertiesWidget::showedElementWasDeleted() void MasterPropertiesWidget::showedElementWasDeleted()
{ {
m_showed_element = nullptr; m_showed_element = nullptr;
} }
/** /**
@brief MasterPropertiesWidget::diagramWasdeletedFromProject * @brief MasterPropertiesWidget::diagramWasdeletedFromProject
This slot is called when a diagram is removed from the parent project * This slot is called when a diagram is removed from the parent project
of edited element to update the content of this widget * of edited element to update the content of this widget
*/ */
void MasterPropertiesWidget::diagramWasdeletedFromProject() void MasterPropertiesWidget::diagramWasdeletedFromProject()
{ {
// We use a timer because if the removed diagram // We use a timer because if the removed diagram
@@ -431,11 +453,11 @@ void MasterPropertiesWidget::diagramWasdeletedFromProject()
} }
/** /**
@brief MasterPropertiesWidget::customContextMenu * @brief MasterPropertiesWidget::customContextMenu
Display a context menu * Display a context menu
@param pos * @param pos
@param i : the tree widget where the context menu was requested. * @param i : the tree widget where the context menu was requested.
*/ */
void MasterPropertiesWidget::customContextMenu(const QPoint &pos, int i) void MasterPropertiesWidget::customContextMenu(const QPoint &pos, int i)
{ {
// add the size of the header to display the topleft of the QMenu // add the size of the header to display the topleft of the QMenu
@@ -444,14 +466,14 @@ void MasterPropertiesWidget::customContextMenu(const QPoint &pos, int i)
// section related to QAbstractScrollArea // section related to QAbstractScrollArea
QPoint point = pos; QPoint point = pos;
point.ry()+=ui->m_free_tree_widget->header()->height(); point.ry()+=ui->m_free_tree_widget->header()->height();
m_context_menu->clear(); m_context_menu->clear();
if (i == 1) if (i == 1)
{ {
point = ui->m_free_tree_widget->mapToGlobal(point); point = ui->m_free_tree_widget->mapToGlobal(point);
//Context at for free tree widget //Context at for free tree widget
if (ui->m_free_tree_widget->currentItem()) if (ui->m_free_tree_widget->currentItem())
{ {
m_qtwi_at_context_menu = ui->m_free_tree_widget->currentItem(); m_qtwi_at_context_menu = ui->m_free_tree_widget->currentItem();
@@ -462,8 +484,8 @@ void MasterPropertiesWidget::customContextMenu(const QPoint &pos, int i)
else else
{ {
point = ui->m_link_tree_widget->mapToGlobal(point); point = ui->m_link_tree_widget->mapToGlobal(point);
//context at for link tre widget //context at for link tre widget
if (ui->m_link_tree_widget->currentItem()) if (ui->m_link_tree_widget->currentItem())
{ {
m_qtwi_at_context_menu = ui->m_link_tree_widget->currentItem(); m_qtwi_at_context_menu = ui->m_link_tree_widget->currentItem();
@@ -471,7 +493,7 @@ void MasterPropertiesWidget::customContextMenu(const QPoint &pos, int i)
m_context_menu->addAction(m_show_qtwi); m_context_menu->addAction(m_show_qtwi);
} }
} }
m_context_menu->addAction(m_show_element); m_context_menu->addAction(m_show_element);
m_context_menu->popup(point); m_context_menu->popup(point);
} }