[qet] [4001] Revamp the class link and unlink element command |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/qet Archives
]
Revision: 4001
Author: blacksun
Date: 2015-06-08 20:18:35 +0200 (Mon, 08 Jun 2015)
Log Message:
-----------
Revamp the class link and unlink element command
Modified Paths:
--------------
trunk/dev_doc/ID_of_QUndoCommand.txt
trunk/sources/diagramcommands.cpp
trunk/sources/diagramcommands.h
trunk/sources/ui/linksingleelementwidget.cpp
trunk/sources/ui/linksingleelementwidget.ui
trunk/sources/ui/masterpropertieswidget.cpp
Added Paths:
-----------
trunk/sources/undocommand/linkelementcommand.cpp
trunk/sources/undocommand/linkelementcommand.h
Modified: trunk/dev_doc/ID_of_QUndoCommand.txt
===================================================================
--- trunk/dev_doc/ID_of_QUndoCommand.txt 2015-06-08 15:23:05 UTC (rev 4000)
+++ trunk/dev_doc/ID_of_QUndoCommand.txt 2015-06-08 18:18:35 UTC (rev 4001)
@@ -1 +1,2 @@
ChangeElementInformationCommand = 1
+LinkElementCommand = 2
Modified: trunk/sources/diagramcommands.cpp
===================================================================
--- trunk/sources/diagramcommands.cpp 2015-06-08 15:23:05 UTC (rev 4000)
+++ trunk/sources/diagramcommands.cpp 2015-06-08 18:18:35 UTC (rev 4001)
@@ -1137,142 +1137,3 @@
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();
-}
Modified: trunk/sources/diagramcommands.h
===================================================================
--- trunk/sources/diagramcommands.h 2015-06-08 15:23:05 UTC (rev 4000)
+++ trunk/sources/diagramcommands.h 2015-06-08 18:18:35 UTC (rev 4001)
@@ -547,41 +547,4 @@
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
Modified: trunk/sources/ui/linksingleelementwidget.cpp
===================================================================
--- trunk/sources/ui/linksingleelementwidget.cpp 2015-06-08 15:23:05 UTC (rev 4000)
+++ trunk/sources/ui/linksingleelementwidget.cpp 2015-06-08 18:18:35 UTC (rev 4001)
@@ -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,11 +104,18 @@
*/
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;
}
Modified: trunk/sources/ui/linksingleelementwidget.ui
===================================================================
--- trunk/sources/ui/linksingleelementwidget.ui 2015-06-08 15:23:05 UTC (rev 4000)
+++ trunk/sources/ui/linksingleelementwidget.ui 2015-06-08 18:18:35 UTC (rev 4001)
@@ -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">
Modified: trunk/sources/ui/masterpropertieswidget.cpp
===================================================================
--- trunk/sources/ui/masterpropertieswidget.cpp 2015-06-08 15:23:05 UTC (rev 4000)
+++ trunk/sources/ui/masterpropertieswidget.cpp 2015-06-08 18:18:35 UTC (rev 4001)
@@ -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 @@
* 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)];
- }
- //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);
- }
- }
+ //The two list contain the same element, there is no change
+ if (to_link.size() == linked_.size())
+ {
+ bool equal = true;
- // 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;
+ foreach(Element *elmt, to_link)
+ if (!linked_.contains(elmt))
+ equal = false;
+
+ if(equal)
+ return nullptr;
}
- //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;
- }
+
+ LinkElementCommand *undo = new LinkElementCommand(m_element);
+
+ if (to_link.isEmpty())
+ undo->unlinkAll();
+ else
+ undo->setLink(to_link);
+
+ return undo;
}
/**
Added: trunk/sources/undocommand/linkelementcommand.cpp
===================================================================
--- trunk/sources/undocommand/linkelementcommand.cpp (rev 0)
+++ trunk/sources/undocommand/linkelementcommand.cpp 2015-06-08 18:18:35 UTC (rev 4001)
@@ -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);
+}
Added: trunk/sources/undocommand/linkelementcommand.h
===================================================================
--- trunk/sources/undocommand/linkelementcommand.h (rev 0)
+++ trunk/sources/undocommand/linkelementcommand.h 2015-06-08 18:18:35 UTC (rev 4001)
@@ -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