diff --git a/sources/TerminalStrip/terminalstrip.cpp b/sources/TerminalStrip/terminalstrip.cpp index 7b7d0a146..6106415e2 100644 --- a/sources/TerminalStrip/terminalstrip.cpp +++ b/sources/TerminalStrip/terminalstrip.cpp @@ -1,4 +1,4 @@ -/* +/* Copyright 2006-2021 The QElectroTech Team This file is part of QElectroTech. @@ -251,6 +251,16 @@ class PhysicalTerminal m_real_terminal = terminals; } + /** + * @brief addTerminals + * Append the real terminal \p terminal + * to this physical terminal. + * @param terminal + */ + void addTerminal(shared_real_terminal terminal) { + m_real_terminal.append(terminal); + } + /** * @brief levelCount * @return the number of level of this terminal @@ -541,6 +551,47 @@ bool TerminalStrip::setOrderTo(QVector sorted_vector) return true; } +/** + * @brief TerminalStrip::groupTerminal + * Add \p added_terminal to \p receiver_terminal. + * At the end of this method, the physical terminal represented by \p added_terminal is removed + * and \p receiver_terminal become a multi-level terminal. + * Emit the signal orderChanged(); + * @param added_terminal + * @param receiver_terminal + * @return true if success + */ +bool TerminalStrip::groupTerminal(const PhysicalTerminalData &receiver_terminal, const QVector &added_terminals) +{ + if (!m_physical_terminals.contains(receiver_terminal.physical_terminal)) { + qDebug() << "TerminalStrip::groupTerminal : Arguments terminals don't belong to this strip. Operation aborted."; + return false; + } + + auto physical_receiver_terminal = receiver_terminal.physical_terminal; + + for (const auto &ptd : qAsConst(added_terminals)) + { + if (!m_physical_terminals.contains(ptd.physical_terminal)) { + continue; + } + + //Add every real terminal of ptd to receiver terminal + for (auto const &rtd_ : qAsConst(ptd.real_terminals_vector)) + { + if (auto rt = realTerminal(rtd_.element_)) { + physical_receiver_terminal->addTerminal(rt); + } + } + + //Remove ptd + m_physical_terminals.removeOne(ptd.physical_terminal); + } + + emit orderChanged(); + return true; +} + /** * @brief TerminalStrip::terminalElement * @return A vector of all terminal element owned by this strip diff --git a/sources/TerminalStrip/terminalstrip.h b/sources/TerminalStrip/terminalstrip.h index b56785532..2731f33ac 100644 --- a/sources/TerminalStrip/terminalstrip.h +++ b/sources/TerminalStrip/terminalstrip.h @@ -107,6 +107,7 @@ class TerminalStrip : public QObject PhysicalTerminalData physicalTerminalData(int index) const; QVector physicalTerminalData() const; bool setOrderTo(QVector sorted_vector); + bool groupTerminal(const PhysicalTerminalData &receiver_terminal, const QVector &added_terminals); QVector> terminalElement() const; diff --git a/sources/TerminalStrip/ui/terminalstripeditor.cpp b/sources/TerminalStrip/ui/terminalstripeditor.cpp index 80dea35ba..170ae9552 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.cpp +++ b/sources/TerminalStrip/ui/terminalstripeditor.cpp @@ -45,8 +45,10 @@ TerminalStripEditor::TerminalStripEditor(QETProject *project, QWidget *parent) : m_project(project) { ui->setupUi(this); + ui->m_table_widget->setItemDelegate(new TerminalStripModelDelegate(ui->m_terminal_strip_tw)); ui->m_remove_terminal_strip_pb->setDisabled(true); + ui->m_group_terminals_pb->setDisabled(true); buildTree(); ui->m_terminal_strip_tw->expandRecursively(ui->m_terminal_strip_tw->rootIndex()); setUpUndoConnections(); @@ -307,11 +309,51 @@ void TerminalStripEditor::setCurrentStrip(TerminalStrip *strip_) m_model = new TerminalStripModel(strip_, this); ui->m_table_widget->setModel(m_model); + spanMultiLevelTerminals(); connect(m_current_strip, &TerminalStrip::orderChanged, this, &TerminalStripEditor::on_m_reload_pb_clicked); + connect(ui->m_table_widget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &TerminalStripEditor::selectionChanged); } } +/** + * @brief TerminalStripEditor::spanMultiLevelTerminals + * Span row of m_table_widget for multi-level terminal + */ +void TerminalStripEditor::spanMultiLevelTerminals() +{ + if (!m_current_strip) { + return; + } + + ui->m_table_widget->clearSpans(); + auto current_row = 0; + for (auto i = 0 ; i < m_current_strip->physicalTerminalCount() ; ++i) + { + const auto level_count = m_current_strip->physicalTerminalData(i).real_terminals_vector.size(); + if (level_count > 1) { + ui->m_table_widget->setSpan(current_row, 0, level_count, 1); + } + current_row += level_count; + } +} + +/** + * @brief TerminalStripEditor::selectionChanged + * Update the editor according to the current selection + */ +void TerminalStripEditor::selectionChanged() +{ + if (!m_model) { + return; + } + + auto index_list = ui->m_table_widget->selectionModel()->selectedIndexes(); + auto terminal_vector = m_model->terminalsForIndex(index_list); + + ui->m_group_terminals_pb->setEnabled(terminal_vector.size() > 1 ? true : false); +} + /** * @brief TerminalStripEditor::on_m_add_terminal_strip_pb_clicked * Action when user click on add terminal strip button @@ -474,3 +516,19 @@ void TerminalStripEditor::on_m_auto_ordering_pb_clicked() } } +/** + * @brief TerminalStripEditor::on_m_group_terminals_pb_clicked + */ +void TerminalStripEditor::on_m_group_terminals_pb_clicked() +{ + if (m_model && m_current_strip) + { + auto ptd_vector = m_model->terminalsForIndex(ui->m_table_widget->selectionModel()->selectedIndexes()); + if (ptd_vector.size() >= 2) + { + auto receiver_ = ptd_vector.takeFirst(); + m_current_strip->groupTerminal(receiver_, ptd_vector); + } + } +} + diff --git a/sources/TerminalStrip/ui/terminalstripeditor.h b/sources/TerminalStrip/ui/terminalstripeditor.h index b00910437..216a65d71 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.h +++ b/sources/TerminalStrip/ui/terminalstripeditor.h @@ -50,6 +50,8 @@ class TerminalStripEditor : public QDialog QTreeWidgetItem* addTerminalStrip(TerminalStrip *terminal_strip); void addFreeTerminal(); void setCurrentStrip(TerminalStrip *strip_); + void spanMultiLevelTerminals(); + void selectionChanged(); private slots: void on_m_add_terminal_strip_pb_clicked(); @@ -58,6 +60,7 @@ class TerminalStripEditor : public QDialog void on_m_terminal_strip_tw_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); void on_m_dialog_button_box_clicked(QAbstractButton *button); void on_m_auto_ordering_pb_clicked(); + void on_m_group_terminals_pb_clicked(); private: Ui::TerminalStripEditor *ui; diff --git a/sources/TerminalStrip/ui/terminalstripeditor.ui b/sources/TerminalStrip/ui/terminalstripeditor.ui index 35dba993c..f81bfbbde 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.ui +++ b/sources/TerminalStrip/ui/terminalstripeditor.ui @@ -178,14 +178,7 @@ - - - - Position automatique - - - - + Qt::Vertical @@ -198,6 +191,20 @@ + + + + Position automatique + + + + + + + Grouper les bornes + + + diff --git a/sources/TerminalStrip/ui/terminalstripmodel.cpp b/sources/TerminalStrip/ui/terminalstripmodel.cpp index b9e78e973..96a3de070 100644 --- a/sources/TerminalStrip/ui/terminalstripmodel.cpp +++ b/sources/TerminalStrip/ui/terminalstripmodel.cpp @@ -89,7 +89,7 @@ QVariant TerminalStripModel::data(const QModelIndex &index, int role) const if (role == Qt::DisplayRole) { switch (index.column()) { - case POS_CELL : return index.row(); + case POS_CELL : return physicalDataAtIndex(index.row()).pos_; case LEVEL_CELL : return rtd.level_; case LABEL_CELL : return rtd.label_; case XREF_CELL : return rtd.Xref_; @@ -270,6 +270,35 @@ bool TerminalStripModel::isXrefCell(const QModelIndex &index, Element **element) return false; } +/** + * @brief TerminalStripModel::terminalsForIndex + * @param index_list + * @return A vector of PhysicalTerminalData represented by index_list. + * If sereval index point to the same terminal the vector have only one PhysicalTerminalData + */ +QVector TerminalStripModel::terminalsForIndex(QModelIndexList index_list) const +{ + QVector vector_; + if (index_list.isEmpty()) { + return vector_; + } + + QSet set_; + + //We use a QSet to avoid insert several time the same terminal. + for (auto index : index_list) { + if (index.isValid()) { + set_.insert(index.row()); + } + } + + for (auto i : set_) { + vector_.append(physicalDataAtIndex(i)); + } + + return vector_; +} + void TerminalStripModel::fillRealTerminalData() { //Get all physical terminal @@ -340,6 +369,43 @@ void TerminalStripModel::replaceDataAtRow(RealTerminalData data, int row) } } +/** + * @brief TerminalStripModel::physicalDataAtIndex + * @param index + * @return the physical terminal data at \p index. + * We need to use this method because the model can have more index than physical + * terminal, because physical terminal can be multi-level and each level + * have is own row. + * If \p index is out of range, return a default PhysicalTerminalData (pos_ is set to -1 by default) + */ +PhysicalTerminalData TerminalStripModel::physicalDataAtIndex(int index) const +{ + if (m_physical_terminal_data.isEmpty()) { + return PhysicalTerminalData(); + } + + int current_checked_index = -1; + int current_phy = -1; + bool match_ = false; + + for (const auto &ptd_ : qAsConst(m_physical_terminal_data)) + { + current_checked_index += ptd_.real_terminals_vector.size(); + ++current_phy; + + if (current_checked_index >= index) { + match_ = true; + break; + } + } + + if (match_) { + return m_physical_terminal_data.at(current_phy); + } else { + return PhysicalTerminalData(); + } +} + /*********************************************************** * Alittle delegate for add a combobox to edit type * and a spinbox to edit the level of a terminal diff --git a/sources/TerminalStrip/ui/terminalstripmodel.h b/sources/TerminalStrip/ui/terminalstripmodel.h index 27051667e..d1e86d853 100644 --- a/sources/TerminalStrip/ui/terminalstripmodel.h +++ b/sources/TerminalStrip/ui/terminalstripmodel.h @@ -43,11 +43,13 @@ class TerminalStripModel : public QAbstractTableModel QVector modifiedRealTerminalData() const; bool isXrefCell(const QModelIndex &index, Element **element = nullptr); + QVector terminalsForIndex(QModelIndexList index_list) const; private: void fillRealTerminalData(); RealTerminalData dataAtRow(int row) const; void replaceDataAtRow(RealTerminalData data, int row); + PhysicalTerminalData physicalDataAtIndex(int index) const; private: QPointer m_terminal_strip;