mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2025-09-14 20:33:05 +02:00
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5449 bfdf4180-ca20-0410-9c96-a3a8aa849046
282 lines
8.8 KiB
C++
282 lines
8.8 KiB
C++
/*
|
|
Copyright 2006-2017 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 "linkelementcommand.h"
|
|
#include "element.h"
|
|
#include "diagram.h"
|
|
#include "conductorautonumerotation.h"
|
|
#include "conductor.h"
|
|
#include "potentialselectordialog.h"
|
|
|
|
/**
|
|
* @brief LinkElementCommand::LinkElementCommand
|
|
* Constructor
|
|
* @param element_ : element where we work the link / unlink
|
|
* @param parent : parent undo
|
|
*/
|
|
LinkElementCommand::LinkElementCommand(Element *element_, QUndoCommand *parent):
|
|
QUndoCommand(parent),
|
|
m_element(element_),
|
|
m_first_redo (true)
|
|
{
|
|
m_linked_before = m_linked_after = m_element->linkedElements();
|
|
setText(QObject::tr("Éditer les référence croisé", "edite the cross reference"));
|
|
}
|
|
|
|
/**
|
|
* @brief LinkElementCommand::mergeWith
|
|
* @param other try to merge this command with other
|
|
* @return true if merge with success else false
|
|
*/
|
|
bool LinkElementCommand::mergeWith(const QUndoCommand *other)
|
|
{
|
|
if (id() != other->id() || other->childCount()) return false;
|
|
auto const *undo = static_cast<const LinkElementCommand *> (other);
|
|
if (m_element != undo->m_element) return false;
|
|
m_linked_after = undo->m_linked_after;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief LinkElementCommand::isLinkable
|
|
* @param element_a
|
|
* @param element_b
|
|
* @param already_linked
|
|
* @return true if element_a and element_b can be linked between them.
|
|
* There is few condition to be linked :
|
|
* 1- element_a and element_b must be linkable type. (Ex : A is master and B is slave 'OK', A and B is master 'KO')
|
|
* 2- For element type slave and report (no matter if element is 'A' or 'B'), the element must be free (not connected to an element)
|
|
* 3- we can override the section 2 by set already_linked to true. In this case, if slave or report is already
|
|
* linked to the other element ('A' or 'B') return true, but if linked to another element (not 'A' or 'B') return false
|
|
*/
|
|
bool LinkElementCommand::isLinkable(Element *element_a, Element *element_b, bool already_linked)
|
|
{
|
|
switch(element_a->linkType())
|
|
{
|
|
case Element::Simple: return false;
|
|
|
|
case Element::NextReport:
|
|
{
|
|
//Type isn't good
|
|
if (element_b->linkType() != Element::PreviousReport) return false;
|
|
//two report is free
|
|
if (element_a->isFree() && element_b->isFree()) return true;
|
|
//Reports aren't free but are already linked between them and and already_linked is true
|
|
if (element_a->linkedElements().contains(element_b) && already_linked) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
case Element::PreviousReport:
|
|
{
|
|
//Type isn't good
|
|
if (element_b->linkType() != Element::NextReport) return false;
|
|
//two report is free
|
|
if (element_a->isFree() && element_b->isFree()) return true;
|
|
//Reports aren't free but are already linked between them and and already_linked is true
|
|
if (element_a->linkedElements().contains(element_b) && already_linked) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
case Element::Master:
|
|
{
|
|
//Type isn't good
|
|
if (element_b->linkType() != Element::Slave) return false;
|
|
//element_b is free
|
|
if (element_b->isFree()) return true;
|
|
//element_b isn't free but already linked to element_a and already_linked is true
|
|
if (element_a->linkedElements().contains(element_b) && already_linked) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
case Element::Slave:
|
|
{
|
|
//Type isn't good
|
|
if (element_b->linkType() != Element::Master) return false;
|
|
//Element_a is free
|
|
if (element_a->isFree()) return true;
|
|
//element_a isn't free but already linked to element_b and already_linked is true;
|
|
if (element_b->linkedElements().contains(element_a) && already_linked) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
case Element::Terminale: return false;
|
|
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief LinkElementCommand::setLink
|
|
* Replace all linked elements of edited element by elements stored in @element_list
|
|
* This method do several check to know if element can be linked or not.
|
|
* @param element_list
|
|
*/
|
|
void LinkElementCommand::setLink(const QList<Element *>& element_list)
|
|
{
|
|
m_linked_after.clear();
|
|
setUpNewLink(element_list, true);
|
|
}
|
|
|
|
/**
|
|
* @brief LinkElementCommand::setLink
|
|
* This is an overloaded function.
|
|
* @param element_
|
|
*/
|
|
void LinkElementCommand::setLink(Element *element_)
|
|
{
|
|
QList<Element *> list;
|
|
list << element_;
|
|
setLink(list);
|
|
}
|
|
|
|
/**
|
|
* @brief LinkElementCommand::unlink
|
|
* Unlink all elements of element_list from the edited element.
|
|
* @param element_list
|
|
*/
|
|
void LinkElementCommand::unlink(QList<Element *> element_list)
|
|
{
|
|
foreach(Element *elmt, element_list)
|
|
m_linked_after.removeAll(elmt);
|
|
}
|
|
|
|
/**
|
|
* @brief LinkElementCommand::unlinkAll
|
|
* Unlink all element of the edited element
|
|
*/
|
|
void LinkElementCommand::unlinkAll() {
|
|
m_linked_after.clear();
|
|
}
|
|
|
|
/**
|
|
* @brief LinkElementCommand::undo
|
|
* Undo this command
|
|
*/
|
|
void LinkElementCommand::undo()
|
|
{
|
|
if(m_element->diagram()) m_element->diagram()->showMe();
|
|
makeLink(m_linked_before);
|
|
QUndoCommand::undo();
|
|
}
|
|
|
|
/**
|
|
* @brief LinkElementCommand::redo
|
|
* Redo this command
|
|
*/
|
|
void LinkElementCommand::redo()
|
|
{
|
|
if(m_element->diagram()) m_element->diagram()->showMe();
|
|
makeLink(m_linked_after);
|
|
|
|
//If the action is to link two reports together, we check if the conductors
|
|
//of the new potential have the same text, function, and protocol.
|
|
//if not, a dialog ask what do to.
|
|
if (m_first_redo && (m_element->linkType() & Element::AllReport) \
|
|
&& m_element->conductors().size() \
|
|
&& m_linked_after.size() && m_linked_after.first()->conductors().size())
|
|
{
|
|
//fill list of potential
|
|
QSet <Conductor *> c_list = m_element->conductors().first()->relatedPotentialConductors();
|
|
c_list << m_element->conductors().first();
|
|
//fill list of text
|
|
QStringList str_txt;
|
|
QStringList str_funct;
|
|
QStringList str_tens;
|
|
for (const Conductor *c : c_list)
|
|
{
|
|
str_txt << c->properties().text;
|
|
str_funct << c->properties().m_function;
|
|
str_tens << c->properties().m_tension_protocol;
|
|
}
|
|
|
|
//check text list, isn't same in potential, ask user what to do
|
|
if (!QET::eachStrIsEqual(str_txt) || !QET::eachStrIsEqual(str_funct) || !QET::eachStrIsEqual(str_tens))
|
|
{
|
|
PotentialSelectorDialog psd(m_element, this);
|
|
psd.exec();
|
|
}
|
|
m_first_redo = false;
|
|
}
|
|
QUndoCommand::redo();
|
|
}
|
|
|
|
/**
|
|
* @brief LinkElementCommand::setUpNewLink
|
|
* Update the content of m_link_after with the content of @element_list.
|
|
* Each linkable element (know via the static method isLinkable) is added to m_linked_after
|
|
* @already_link is used for the static method isLinkable.
|
|
* @param element_list
|
|
* @param already_link
|
|
*/
|
|
void LinkElementCommand::setUpNewLink(const QList<Element *> &element_list, bool already_link)
|
|
{
|
|
//m_element is a master we can connect several element to it
|
|
//if m_element isn't master (may be a report or slave) we can connect only one element
|
|
if (m_element->linkType() == Element::Master || element_list.size() == 1)
|
|
{
|
|
foreach(Element *elmt, element_list)
|
|
if (isLinkable(m_element, elmt, already_link))
|
|
m_linked_after << elmt;
|
|
}
|
|
else
|
|
{
|
|
qDebug() << "LinkElementCommand::setUpNewLink : try to link several elements to a report element or slave element,"
|
|
" only the first element of the list will be taken to be linked";
|
|
foreach(Element *elmt, element_list)
|
|
if (isLinkable(m_element, elmt, already_link))
|
|
{
|
|
m_linked_after << elmt;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief LinkElementCommand::makeLink
|
|
* Make the link between m_element and element_list;
|
|
* This method unlink elements if needed.
|
|
* @param element_list
|
|
*/
|
|
void LinkElementCommand::makeLink(const QList<Element *> &element_list)
|
|
{
|
|
//List is empty, that mean m_element must be free, so we unlink all elements
|
|
if (element_list.isEmpty())
|
|
{
|
|
m_element->unlinkAllElements();
|
|
return;
|
|
}
|
|
|
|
//We link all element from element_list
|
|
foreach(Element *elmt, element_list)
|
|
m_element->linkToElement(elmt);
|
|
|
|
//At this point may be there are unwanted linked elements to m_element. We must to unlink it.
|
|
//Elements from @element_list are wanted so we compare @element_list to current linked element of @m_element
|
|
QList<Element *> to_unlink = m_element->linkedElements();
|
|
foreach(Element *elmt, element_list)
|
|
to_unlink.removeAll(elmt);
|
|
|
|
//All elements stored in to_unlink is unwanted we unlink it from m_element
|
|
if (!to_unlink.isEmpty())
|
|
foreach(Element *elmt, to_unlink)
|
|
m_element->unlinkElement(elmt);
|
|
}
|