Revamp the class link and unlink element command

git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@4001 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
blacksun
2015-06-08 18:18:35 +00:00
parent 5a81f9859f
commit e195ab634e
8 changed files with 369 additions and 214 deletions

View File

@@ -1 +1,2 @@
ChangeElementInformationCommand = 1
LinkElementCommand = 2

View File

@@ -1137,142 +1137,3 @@ void ChangeShapeStyleCommand::redo() {
diagram -> showMe();
QUndoCommand::redo();
}
/**
* @brief LinkElementsCommand::LinkElementsCommand
*Constructor
* @param elmt1 element to Link
* @param elmt2 element to link
* @param parent parent undo command
*/
LinkElementsCommand::LinkElementsCommand(Element *elmt1, Element *elmt2, QUndoCommand *parent) :
QUndoCommand(parent),
diagram_(elmt1->diagram()),
element_(elmt1),
first_redo(true)
{
elmt_list << elmt2;
if (elmt1->linkType() & Element::AllReport &&
elmt2->linkType() & Element::AllReport) {
setText(QObject::tr("Lier deux reports de folio",
"title for undo LinkElementsCommand if two elements are folio report"));
}
else if (element_->linkType() & (Element::Master|Element::Slave))
setText(QObject::tr("Editer les référence croisé", "edite the cross reference"));
else setText(QObject::tr("Lier deux éléments"));
previous_linked = elmt1->linkedElements();
}
LinkElementsCommand::LinkElementsCommand(Element *elmt1, QList<Element *> &elmtList, QUndoCommand *parent) :
QUndoCommand(parent),
diagram_(elmt1->diagram()),
element_(elmt1),
elmt_list(elmtList),
first_redo(true)
{
if (element_->linkType() & (Element::Master|Element::Slave))
setText(QObject::tr("Editer les référence croisé"));
else setText(QObject::tr("Lier deux éléments"));
previous_linked = elmt1->linkedElements();
}
/**
* @brief LinkElementsCommand::~LinkElementsCommand
*destructor
*/
LinkElementsCommand::~LinkElementsCommand(){}
/**
* @brief LinkElementsCommand::undo
*Undo command
*/
void LinkElementsCommand::undo() {
diagram_->showMe();
foreach (Element *elmt, elmt_list)
element_->unlinkElement(elmt);
foreach (Element *elmt, previous_linked)
element_->linkToElement(elmt);
QUndoCommand::undo();
}
/**
* @brief LinkElementsCommand::redo
*redo command
*/
void LinkElementsCommand::redo() {
diagram_->showMe();
foreach (Element *elmt, elmt_list)
element_->linkToElement(elmt);
//If element are report, check if text of this potential is identical.
if ((element_->linkType() &Element::AllReport) && first_redo) {
if(element_->conductors().count() && elmt_list.first()->conductors().count()) {
ConductorAutoNumerotation::checkPotential(element_->conductors().first());
}
first_redo = false;
}
QUndoCommand::redo();
}
/**
* @brief unlinkElementsCommand::unlinkElementsCommand
* Constructor, unlink elmt2 or all elements if elmt2 isn't specified
* @param elmt1 element to set undo command
* @param elmt2 element to be unlinked
* @param parent undo parent
*/
unlinkElementsCommand::unlinkElementsCommand(Element *elmt1, Element *elmt2, QUndoCommand *parent):
QUndoCommand(parent),
diagram_(elmt1->diagram()),
element_(elmt1)
{
if (elmt2) elmt_list << elmt2;
else elmt_list << elmt1->linkedElements();
setText(QObject::tr("Délier %n élément(s)", "", elmt_list.size()));
}
/**
* @brief unlinkElementsCommand::unlinkElementsCommand
* @param elmt1 Element to set the link
* @param elmtList list of all element to be linked to elmt1
* @param parent undo command
*/
unlinkElementsCommand::unlinkElementsCommand(Element *elmt1, QList<Element *> &elmtList, QUndoCommand *parent):
QUndoCommand(parent),
diagram_(elmt1->diagram()),
element_(elmt1),
elmt_list(elmtList)
{
setText(QObject::tr("Délier %n élément(s)", "", elmt_list.size()));
}
/**
* @brief unlinkElementsCommand::~unlinkElementsCommand
* destructor
*/
unlinkElementsCommand::~unlinkElementsCommand(){}
/**
* @brief unlinkElementsCommand::undo
*undo command
*/
void unlinkElementsCommand::undo() {
foreach (Element *elmt, elmt_list)
element_->linkToElement(elmt);
QUndoCommand::undo();
}
/**
* @brief unlinkElementsCommand::redo
*redo command
*/
void unlinkElementsCommand::redo() {
foreach (Element *elmt, elmt_list)
element_->unlinkElement(elmt);
QUndoCommand::redo();
}

View File

@@ -547,41 +547,4 @@ class ChangeShapeStyleCommand : public QUndoCommand {
Qt::PenStyle old_style, new_style;
Diagram *diagram;
};
class LinkElementsCommand : public QUndoCommand {
public:
// constructor destructor
LinkElementsCommand (Element *elmt1, Element *elmt2, QUndoCommand *parent = 0);
LinkElementsCommand (Element *elmt1, QList <Element *> &elmtList, QUndoCommand *parent = 0);
virtual ~LinkElementsCommand();
//methods
virtual void undo();
virtual void redo();
private:
//attributes
Diagram *diagram_;
Element *element_;
QList <Element *> elmt_list;
QList <Element *> previous_linked;
bool first_redo;
};
class unlinkElementsCommand : public QUndoCommand {
public:
//constructor destructor
unlinkElementsCommand (Element *elmt1, Element *elmt2 = 0, QUndoCommand *parent = 0);
unlinkElementsCommand (Element *elmt1, QList <Element *> &elmtList, QUndoCommand *parent = 0);
virtual ~unlinkElementsCommand();
//methods
virtual void undo();
virtual void redo();
private:
//attributes
Diagram *diagram_;
Element *element_;
QList <Element *> elmt_list;
};
#endif

View File

@@ -19,8 +19,8 @@
#include "ui_linksingleelementwidget.h"
#include "diagram.h"
#include "elementprovider.h"
#include "diagramcommands.h"
#include "elementselectorwidget.h"
#include "linkelementcommand.h"
/**
* @brief LinkSingleElementWidget::LinkSingleElementWidget
@@ -104,10 +104,17 @@ void LinkSingleElementWidget::apply()
*/
QUndoCommand *LinkSingleElementWidget::associatedUndo() const
{
if (esw_->selectedElement())
return new LinkElementsCommand(m_element, esw_->selectedElement());
else if (unlink_)
return new unlinkElementsCommand(m_element);
if (esw_->selectedElement() || unlink_)
{
LinkElementCommand *undo = new LinkElementCommand(m_element);
if (esw_->selectedElement())
undo->setLink(esw_->selectedElement());
else if (unlink_)
undo->unlinkAll();
return undo;
}
return nullptr;
}

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>400</height>
<width>265</width>
<height>182</height>
</rect>
</property>
<property name="windowTitle">

View File

@@ -20,9 +20,9 @@
#include <QListWidgetItem>
#include <diagramposition.h>
#include <elementprovider.h>
#include <diagramcommands.h>
#include <diagram.h>
#include <element.h>
#include <linkelementcommand.h>
/**
* @brief MasterPropertiesWidget::MasterPropertiesWidget
@@ -109,43 +109,35 @@ void MasterPropertiesWidget::reset() {
* If no change return nullptr.
* @return
*/
QUndoCommand* MasterPropertiesWidget::associatedUndo() const {
QUndoCommand* MasterPropertiesWidget::associatedUndo() const
{
QList <Element *> to_link;
QList <Element *> linked_ = m_element->linkedElements();
for (int i=0; i<ui->linked_list->count(); i++) {
for (int i=0; i<ui->linked_list->count(); i++)
to_link << lwi_hash[ui->linked_list->item(i)];
//The two list contain the same element, there is no change
if (to_link.size() == linked_.size())
{
bool equal = true;
foreach(Element *elmt, to_link)
if (!linked_.contains(elmt))
equal = false;
if(equal)
return nullptr;
}
//If same element are find in to_link and linked, that means
// element are already linked, so we remove element on the two list
//if linked_ contains element at the end of the operation,
//that means this element must be unlinked from @m_element
foreach (Element *elmt, to_link) {
if(linked_.contains(elmt)) {
to_link.removeAll(elmt);
linked_.removeAll(elmt);
}
}
LinkElementCommand *undo = new LinkElementCommand(m_element);
// if two list, contain element, we link and unlink @m_element with corresponding
//undo command, and add first command for parent of the second, user see only one
//undo command
if (linked_.count() && to_link.count()) {
LinkElementsCommand *lec = new LinkElementsCommand(m_element, to_link);
new unlinkElementsCommand(m_element, linked_, lec);
return lec;
}
//Else do the single undo command corresponding to the link.
else if (to_link.count()) {
return (new LinkElementsCommand(m_element, to_link));
}
else if (linked_.count()) {
return (new unlinkElementsCommand(m_element, linked_));
}
else {
return nullptr;
}
if (to_link.isEmpty())
undo->unlinkAll();
else
undo->setLink(to_link);
return undo;
}
/**

View File

@@ -0,0 +1,270 @@
/*
Copyright 2006-2015 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"
/**
* @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_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()) return false;
LinkElementCommand 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::addLink
* Add elements from the list to the linked element of edited element
* This method do several check to know if element can be linked or not.
* @param element_list
*/
void LinkElementCommand::addLink(QList<Element *> element_list)
{
setUpNewLink(element_list, false);
}
/**
* @brief LinkElementCommand::addLink
* This is an overloaded function
* @param element_
*/
void LinkElementCommand::addLink(Element *element_)
{
QList<Element *> list;
list << element_;
addLink(list);
}
/**
* @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(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);
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);
}

View File

@@ -0,0 +1,61 @@
/*
Copyright 2006-2015 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/>.
*/
#ifndef LINKELEMENTCOMMAND_H
#define LINKELEMENTCOMMAND_H
#include <QUndoCommand>
class Element;
/**
* @brief The LinkElementCommand class
* This undo class manage link between elements.
* In the same instance of this class, we can link and unlink elements from an edited element
* This undo class support the merge.
*/
class LinkElementCommand : public QUndoCommand
{
public:
LinkElementCommand(Element *element_, QUndoCommand *parent = 0);
virtual int id() const {return 2;}
virtual bool mergeWith(const QUndoCommand *other);
static bool isLinkable (Element *element_a, Element *element_b, bool already_linked = false);
void addLink (QList<Element *> element_list);
void addLink (Element *element_);
void setLink (QList<Element *> element_list);
void setLink (Element *element_);
void unlink (QList<Element *> element_list);
void unlinkAll ();
void undo();
void redo();
private:
void setUpNewLink (const QList<Element *> &element_list, bool already_link);
void makeLink (const QList <Element *> &element_list);
private:
Element *m_element;
QList<Element *> m_linked_before; //<Linked elements before this command, or when we call "undo"
QList<Element *> m_linked_after; //<Linked elements after this command, or when we recall "redo"
};
#endif // LINKELEMENTCOMMAND_H