QElectroTech  0.70
elementsmover.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2006-2019 The QElectroTech Team
3  This file is part of QElectroTech.
4 
5  QElectroTech is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 2 of the License, or
8  (at your option) any later version.
9 
10  QElectroTech is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "elementsmover.h"
19 #include "conductor.h"
20 #include "conductortextitem.h"
21 #include "diagram.h"
22 #include "diagramcommands.h"
23 #include "element.h"
24 #include "independenttextitem.h"
25 #include "diagramimageitem.h"
27 #include "dynamicelementtextitem.h"
28 #include "elementtextitemgroup.h"
29 
34  movement_running_(false),
35  current_movement_(),
36  diagram_(nullptr),
37  m_movement_driver(nullptr),
38  m_moved_content()
39 {
40 
41 }
42 
47 }
48 
54 bool ElementsMover::isReady() const {
55  return(!movement_running_);
56 }
57 
65 int ElementsMover::beginMovement(Diagram *diagram, QGraphicsItem *driver_item)
66 {
67  // They must be no movement in progress
68  if (movement_running_) return(-1);
69 
70  // Be sure we have diagram to work
71  if (!diagram) return(-1);
72  diagram_ = diagram;
73 
74  // Take count of driver item
75  m_movement_driver = driver_item;
76 
77  // At the beginning of movement, move is NULL
78  current_movement_ = QPointF(0.0, 0.0);
79 
82 
83  //Remove element text, if the parent element is selected.
84  QList<DynamicElementTextItem *> deti_list = m_moved_content.m_element_texts.toList();
85  for(DynamicElementTextItem *deti : deti_list) {
86  if(m_moved_content.m_elements.contains(deti->parentElement())) {
87  m_moved_content.m_element_texts.remove(deti);
88  }
89  }
90 
91  QList<ElementTextItemGroup *> etig_list = m_moved_content.m_texts_groups.toList();
92  for(ElementTextItemGroup *etig : etig_list) {
93  if (m_moved_content.m_elements.contains(etig->parentElement())) {
94  m_moved_content.m_texts_groups.remove(etig);
95  }
96  }
97 
98  if (!m_moved_content.count()) return(-1);
99 
100  /* At this point, we've got all info to manage movement.
101  * There is now a move in progress */
102  movement_running_ = true;
103 
104  return(m_moved_content.count());
105 }
106 
112 void ElementsMover::continueMovement(const QPointF &movement) {
113  if (!movement_running_ || movement.isNull()) return;
114 
115  current_movement_ += movement;
116 
117  //Move every movable item, except conductor
118  typedef DiagramContent dc;
119  for (QGraphicsItem *qgi : m_moved_content.items(dc::Elements | dc::TextFields | dc::Images | dc::Shapes | dc::ElementTextFields | dc::TextGroup))
120  {
121  if (qgi == m_movement_driver)
122  continue;
123  qgi -> setPos(qgi->pos() + movement);
124  }
125 
126  // Move some conductors
127  QList<Conductor *> c_list;
128  c_list.append(m_moved_content.m_conductors_to_move);
130 
131  for (Conductor *c : c_list)
132  {
133  //Due to a weird behavior, we must to ensure that the position of the conductor is to (0,0).
134  //If not, in some unknown case the function QGraphicsScene::itemsBoundingRect() return a rectangle
135  //that take in acount the pos() of the conductor, even if the bounding rect returned by the conductor is not in the pos().
136  //For the user this situation appear when the top right of the folio is not at the top right of the graphicsview,
137  //but displaced to the right and/or bottom.
138  if (c->pos() != QPointF(0,0)) {
139  c->setPos(0,0);
140  }
141  c->updatePath();
142  }
143 }
144 
152 {
153  // A movement must be inited
154  if (!movement_running_) return;
155 
156  //empty command to be used has parent of commands below
157  QUndoCommand *undo_object = new QUndoCommand();
158 
159  //Create undo move if there is a movement
160  if (!current_movement_.isNull()) {
161  QUndoCommand *quc = new MoveElementsCommand(diagram_, m_moved_content, current_movement_, undo_object);
162  undo_object->setText(quc->text());
163  }
164 
165  //There is only one element moved, and project authorize auto conductor,
166  //we try auto connection of conductor;
167  typedef DiagramContent dc;
168  if (m_moved_content.items(dc::TextFields | dc::Images | dc::Shapes).size() == 0 &&
169  m_moved_content.items(dc::Elements).size() == 1 &&
170  diagram_ -> project() -> autoConductor())
171  {
172  Element *elmt = m_moved_content.m_elements.first();
173 
174  int acc = elmt->AlignedFreeTerminals().size();
175 
176  while (!elmt -> AlignedFreeTerminals().isEmpty())
177  {
178  QPair <Terminal *, Terminal *> pair = elmt -> AlignedFreeTerminals().takeFirst();
179 
180  Conductor *conductor = new Conductor(pair.first, pair.second);
181 
182  //Create an undo object for each new auto conductor, with undo_object for parent
183  new AddItemCommand<Conductor *>(conductor, diagram_, QPointF(), undo_object);
184  if (undo_object->text().isEmpty())
185  undo_object->setText(QObject::tr("Ajouter %n conducteur(s)", "add a numbers of conductor one or more", acc));
186 
187  //Get all conductors at the same potential of conductor
188  QSet <Conductor *> conductors_list = conductor->relatedPotentialConductors();
189 
190  //Compare the properties of every conductors stored in conductors_list,
191  //if every conductors properties is equal, we use this properties for conductor.
192  ConductorProperties others_properties;
193  bool use_properties = false;
194  if (!conductors_list.isEmpty())
195  {
196  use_properties = true;
197  others_properties = (*conductors_list.begin())->properties();
198  foreach (Conductor *cond, conductors_list)
199  if (cond->properties() != others_properties)
200  use_properties = false;
201  }
202 
203  if (use_properties)
204  conductor->setProperties(others_properties);
205  else
206  {
207  conductor -> setProperties(diagram_ -> defaultConductorProperties);
208  //Autonum the new conductor, the undo command associated for this, have for parent undo_object
209  ConductorAutoNumerotation can (conductor, diagram_, undo_object);
210  can.numerate();
211  }
212  };
213  }
214 
215  //Add undo_object if have child
216  if (undo_object->childCount() >= 1)
217  diagram_ -> undoStack().push(undo_object);
218  else
219  delete undo_object;
220 
221  // There is no movement in progress now
222  movement_running_ = false;
224 }
QList< QPair< Terminal *, Terminal * > > AlignedFreeTerminals() const
Element::AlignedFreeTerminals.
Definition: element.cpp:1355
void continueMovement(const QPointF &)
ElementsMover::continueMovement Add a move to the current movement.
ConductorProperties properties
Conductor::properties.
Definition: conductor.h:48
The DynamicElementTextItem class This class provide a simple text field of element who can be added o...
virtual ~ElementsMover()
ElementsMover::~ElementsMover Destructor.
bool movement_running_
Definition: elementsmover.h:55
QList< Conductor * > m_conductors_to_move
QGraphicsItem * m_movement_driver
Definition: elementsmover.h:58
QPointF current_movement_
Definition: elementsmover.h:56
bool isReady() const
ElementsMover::isReady.
The AddItemCommand class This command add an item in a diagram The item to add is template...
void endMovement()
ElementsMover::endMovement Ended the current movement by creating an undo added to the undostack of t...
QIcon Conductor
Definition: qeticons.cpp:35
DiagramContent m_moved_content
Definition: elementsmover.h:59
QList< QGraphicsItem * > items(int=All) const
DiagramContent::items.
int removeNonMovableItems()
DiagramContent::removeNonMovableItems Remove all non movable item.
int beginMovement(Diagram *, QGraphicsItem *=nullptr)
ElementsMover::beginMovement Start a new movement.
void numerate()
ConductorAutoNumerotation::numerate execute the automatic numerotation.
QSet< DynamicElementTextItem * > m_element_texts
QIcon tr
Definition: qeticons.cpp:204
The ElementTextItemGroup class This class represent a group of element text Texts in the group can be...
ElementsMover()
ElementsMover::ElementsMover Constructor.
QList< Element * > m_elements
QList< Conductor * > m_conductors_to_update
Diagram * diagram_
Definition: elementsmover.h:57
void clear()
DiagramContent::clear Remove all items from the diagram content.
int count(int=All) const
DiagramContent::count.
QSet< ElementTextItemGroup * > m_texts_groups