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 "elementtextitemgroup.h"
19 #include "dynamicelementtextitem.h"
20 #include "element.h"
21 #include "diagram.h"
22 #include "addelementtextcommand.h"
23 #include "QPropertyUndoCommand/qpropertyundocommand.h"
24 #include "crossrefitem.h"
25 #include "qetapp.h"
26 #include "masterelement.h"
27 #include "qgraphicsitemutility.h"
28
29 #include <QPainter>
30 #include <QGraphicsSceneMouseEvent>
31 #include <utility>
32
sorting(QGraphicsItem * qgia,QGraphicsItem * qgib)33 bool sorting(QGraphicsItem *qgia, QGraphicsItem *qgib)
34 {
35 return qgia->pos().y() < qgib->pos().y();
36 }
37
38 /**
39 * @brief ElementTextItemGroup::ElementTextItemGroup
40 * @param parent
41 */
ElementTextItemGroup(const QString & name,Element * parent)42 ElementTextItemGroup::ElementTextItemGroup(const QString &name, Element *parent) :
43 QGraphicsItemGroup(parent),
44 m_name(name),
45 m_parent_element(parent)
46 {
47 setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
48 connect(parent, &Element::linkedElementChanged, this, &ElementTextItemGroup::updateXref);
49 }
50
~ElementTextItemGroup()51 ElementTextItemGroup::~ElementTextItemGroup()
52 {}
53
54 /**
55 * @brief ElementTextItemGroup::addToGroup
56 * @param item
57 */
addToGroup(QGraphicsItem * item)58 void ElementTextItemGroup::addToGroup(QGraphicsItem *item)
59 {
60 if(item->type() == DynamicElementTextItem::Type)
61 {
62 //Befor add text to this group we must to set the text at the same rotation of this group
63 if((item->rotation() != rotation()) && !m_block_alignment_update)
64 item->setRotation(rotation());
65
66 QGraphicsItemGroup::addToGroup(item);
67 updateAlignment();
68
69 DynamicElementTextItem *deti = qgraphicsitem_cast<DynamicElementTextItem *>(item);
70 connect(deti, &DynamicElementTextItem::fontChanged, this, &ElementTextItemGroup::updateAlignment);
71 connect(deti, &DynamicElementTextItem::textChanged, this, &ElementTextItemGroup::updateAlignment);
72 connect(deti, &DynamicElementTextItem::textFromChanged, this, &ElementTextItemGroup::updateAlignment);
73 connect(deti, &DynamicElementTextItem::infoNameChanged, this, &ElementTextItemGroup::updateAlignment);
74 connect(deti, &DynamicElementTextItem::compositeTextChanged, this, &ElementTextItemGroup::updateAlignment);
75 connect(deti, &DynamicElementTextItem::plainTextChanged, this, &ElementTextItemGroup::updateAlignment);
76 connect(deti, &DynamicElementTextItem::textWidthChanged, this, &ElementTextItemGroup::updateAlignment);
77
78 connect(deti, &DynamicElementTextItem::textFromChanged, this, &ElementTextItemGroup::updateXref);
79 connect(deti, &DynamicElementTextItem::infoNameChanged, this, &ElementTextItemGroup::updateXref);
80
81 updateXref();
82 }
83 }
84
85 /**
86 * @brief ElementTextItemGroup::removeFromGroup
87 * @param item
88 */
removeFromGroup(QGraphicsItem * item)89 void ElementTextItemGroup::removeFromGroup(QGraphicsItem *item)
90 {
91 QGraphicsItemGroup::removeFromGroup(item);
92 //the item transformation is not reseted, we must to do it, because for exemple if the group rotation is 45°
93 //When item is removed from group, visually the item is unchanged (so 45°) but if we call item->rotation() the returned value is 0.
94 item->resetTransform();
95 item->setRotation(this->rotation());
96 item->setFlag(QGraphicsItem::ItemIsSelectable, true);
97 updateAlignment();
98
99 if(DynamicElementTextItem *deti = qgraphicsitem_cast<DynamicElementTextItem *>(item))
100 {
101 disconnect(deti, &DynamicElementTextItem::fontChanged, this, &ElementTextItemGroup::updateAlignment);
102 disconnect(deti, &DynamicElementTextItem::textChanged, this, &ElementTextItemGroup::updateAlignment);
103 disconnect(deti, &DynamicElementTextItem::textFromChanged, this, &ElementTextItemGroup::updateAlignment);
104 disconnect(deti, &DynamicElementTextItem::infoNameChanged, this, &ElementTextItemGroup::updateAlignment);
105 disconnect(deti, &DynamicElementTextItem::compositeTextChanged, this, &ElementTextItemGroup::updateAlignment);
106 disconnect(deti, &DynamicElementTextItem::plainTextChanged, this, &ElementTextItemGroup::updateAlignment);
107 disconnect(deti, &DynamicElementTextItem::textWidthChanged, this, &ElementTextItemGroup::updateAlignment);
108
109 disconnect(deti, &DynamicElementTextItem::textFromChanged, this, &ElementTextItemGroup::updateXref);
110 disconnect(deti, &DynamicElementTextItem::infoNameChanged, this, &ElementTextItemGroup::updateXref);
111
112 updateXref();
113 }
114 }
115
116 /**
117 * @brief ElementTextItemGroup::blockAlignmentUpdate
118 * If true, the texts in this group are never aligned, moved, rotated etc...
119 * the texts stay as it was, until blockAlignmentUpdate is set to false.
120 * @param block
121 */
blockAlignmentUpdate(bool block)122 void ElementTextItemGroup::blockAlignmentUpdate(bool block)
123 {
124 m_block_alignment_update = block;
125 }
126
127 /**
128 * @brief ElementTextItemGroup::setAlignement
129 * Set the alignement of this group
130 * @param alignement
131 */
setAlignment(Qt::Alignment alignement)132 void ElementTextItemGroup::setAlignment(Qt::Alignment alignement)
133 {
134 m_alignment = alignement;
135 updateAlignment();
136 emit alignmentChanged(alignement);
137 }
138
alignment() const139 Qt::Alignment ElementTextItemGroup::alignment() const
140 {
141 return m_alignment;
142 }
143
144 /**
145 * @brief ElementTextItemGroup::setAlignment
146 * Update the alignement of the items in this group, according
147 * to the current alignement.
148 * @param alignement
149 */
updateAlignment()150 void ElementTextItemGroup::updateAlignment()
151 {
152 if(m_block_alignment_update)
153 return;
154
155 prepareGeometryChange();
156
157 QList <DynamicElementTextItem *> texts = this->texts();
158
159 qreal rotation_ = rotation();
160
161 //Set the rotation of this group to 0° relative to the scene
162 qreal rot = rotation();
163 QGraphicsItem *parent = parentItem();
164 while (parent) {
165 rot += parent->rotation();
166 parent = parent->parentItem();
167 }
168 if(rot != 0)
169 setRotation(rotation() - rot);
170
171
172 if(texts.size() == 1)
173 {
174 prepareGeometryChange();
175
176 QGraphicsItem *first = texts.first();
177 setPos(mapFromScene(first->mapToScene(pos())));
178 first->setPos(0,0);
179 }
180 else if (texts.size() > 1)
181 {
182 qreal width = 0;
183 for(QGraphicsItem *item : texts)
184 if(item->boundingRect().width() > width)
185 width = item->boundingRect().width();
186
187 prepareGeometryChange();
188 std::sort(texts.begin(), texts.end(), sorting);
189
190 qreal y_offset = 0;
191
192 if(m_alignment == Qt::AlignLeft)
193 {
194 QPointF ref = texts.first()->pos();
195
196 for(QGraphicsItem *item : texts)
197 {
198 item->setPos(0, ref.y()+y_offset);
199 y_offset+=item->boundingRect().height() + m_vertical_adjustment;
200 }
201 }
202 else if(m_alignment == Qt::AlignVCenter)
203 {
204 QPointF ref(width/2,0);
205
206 for(QGraphicsItem *item : texts)
207 {
208 item->setPos(ref.x() - item->boundingRect().width()/2,
209 ref.y() + y_offset);
210 y_offset+=item->boundingRect().height() + m_vertical_adjustment;
211 }
212 }
213 else if (m_alignment == Qt::AlignRight)
214 {
215 QPointF ref(width,0);
216
217 for(QGraphicsItem *item : texts)
218 {
219 item->setPos(ref.x() - item->boundingRect().width(),
220 ref.y() + y_offset);
221 y_offset+=item->boundingRect().height() + m_vertical_adjustment;
222 }
223 }
224 }
225
226 //Restor the rotation
227 setRotation(rotation_);
228
229 if(m_Xref_item)
230 m_Xref_item->autoPos();
231 if(m_slave_Xref_item)
232 adjustSlaveXrefPos();
233 if(m_hold_to_bottom_of_page)
234 autoPos();
235 }
236
237 /**
238 * @brief ElementTextItemGroup::setVerticalAdjustment
239 * Set the value of the vertical adjustment to @v.
240 * The vertical adjutment is use to adjust the space between the texts of this group.
241 * @param v
242 */
setVerticalAdjustment(int v)243 void ElementTextItemGroup::setVerticalAdjustment(int v)
244 {
245 prepareGeometryChange();
246 m_vertical_adjustment = v;
247 updateAlignment();
248 emit verticalAdjustmentChanged(v);
249 }
250
251 /**
252 * @brief ElementTextItemGroup::setName
253 * @param name Set the name of this group
254 */
setName(QString name)255 void ElementTextItemGroup::setName(QString name)
256 {
257 m_name = std::move(name);
258 emit nameChanged(m_name);
259 }
260
setHoldToBottomPage(bool hold)261 void ElementTextItemGroup::setHoldToBottomPage(bool hold)
262 {
263 if(m_hold_to_bottom_of_page == hold)
264 return;
265
266 m_hold_to_bottom_of_page = hold;
267 if(m_hold_to_bottom_of_page)
268 {
269 setFlag(QGraphicsItem::ItemIsSelectable, false);
270 setFlag(QGraphicsItem::ItemIsMovable, false);
271 connect(m_parent_element, &Element::yChanged, this, &ElementTextItemGroup::autoPos);
272 connect(m_parent_element, &Element::rotationChanged, this, &ElementTextItemGroup::autoPos);
273 if(m_parent_element->linkType() == Element::Master)
274 {
275 //We use timer to let the time of the parent element xref to be updated, befor update the position of this group
276 //because the position of this group is related to the size of the parent element Xref
277 m_linked_changed_timer = connect(m_parent_element, &Element::linkedElementChanged,
278 [this]() {QTimer::singleShot(200, this, &ElementTextItemGroup::autoPos);});
279 if(m_parent_element->diagram())
280 m_XrefChanged_timer = connect(m_parent_element->diagram()->project(), &QETProject::XRefPropertiesChanged,
281 [this]() {QTimer::singleShot(200, this, &ElementTextItemGroup::autoPos);});
282 }
283 autoPos();
284 }
285 else
286 {
287 setFlag(QGraphicsItem::ItemIsSelectable, true);
288 setFlag(QGraphicsItem::ItemIsMovable, true);
289 disconnect(m_parent_element, &Element::yChanged, this, &ElementTextItemGroup::autoPos);
290 disconnect(m_parent_element, &Element::rotationChanged, this, &ElementTextItemGroup::autoPos);
291 if(m_parent_element->linkType() == Element::Master)
292 {
293 disconnect(m_linked_changed_timer);
294 if(m_XrefChanged_timer)
295 disconnect(m_XrefChanged_timer);
296 }
297 }
298
299 emit holdToBottomPageChanged(hold);
300 }
301
setFrame(const bool frame)302 void ElementTextItemGroup::setFrame(const bool frame)
303 {
304 m_frame = frame;
305 update();
306 emit frameChanged(m_frame);
307 }
308
frame() const309 bool ElementTextItemGroup::frame() const {
310 return m_frame;
311 }
312
313 /**
314 * @brief ElementTextItemGroup::texts
315 * @return Every texts in this group
316 */
texts() const317 QList<DynamicElementTextItem *> ElementTextItemGroup::texts() const
318 {
319 QList<DynamicElementTextItem *> list;
320 for(QGraphicsItem *qgi : childItems())
321 {
322 if(qgi->type() == DynamicElementTextItem::Type)
323 list << static_cast<DynamicElementTextItem *>(qgi);
324 }
325 return list;
326 }
327
328 /**
329 * @brief ElementTextItemGroup::diagram
330 * @return The diagram of this group, or nullptr if this group is not in a diagram
331 */
diagram() const332 Diagram *ElementTextItemGroup::diagram() const
333 {
334 if(scene())
335 return static_cast<Diagram *>(scene());
336 else
337 return nullptr;
338 }
339
340 /**
341 * @brief ElementTextItemGroup::parentElement
342 * @return The parent element of this group or nullptr
343 */
parentElement() const344 Element *ElementTextItemGroup::parentElement() const
345 {
346 if(parentItem() && parentItem()->type() == Element::Type)
347 return static_cast<Element *>(parentItem());
348 else
349 return nullptr;
350 }
351
352 /**
353 * @brief ElementTextItemGroup::toXml
354 * Export data of this group to xml
355 * @param dom_document
356 * @return
357 */
toXml(QDomDocument & dom_document) const358 QDomElement ElementTextItemGroup::toXml(QDomDocument &dom_document) const
359 {
360 QDomElement dom_element = dom_document.createElement(this->xmlTaggName());
361 dom_element.setAttribute("name", m_name);
362
363 dom_element.setAttribute("x", QString::number(pos().x()));
364 dom_element.setAttribute("y", QString::number(pos().y()));
365
366 QMetaEnum me = QMetaEnum::fromType<Qt::Alignment>();
367 dom_element.setAttribute("alignment", me.valueToKey(m_alignment));
368
369 dom_element.setAttribute("rotation", this->rotation());
370 dom_element.setAttribute("vertical_adjustment", m_vertical_adjustment);
371 dom_element.setAttribute("frame", m_frame? "true" : "false");
372
373 dom_element.setAttribute("hold_to_bottom_page", m_hold_to_bottom_of_page == true ? "true" : "false");
374
375 QDomElement dom_texts = dom_document.createElement("texts");
376 for(DynamicElementTextItem *deti : texts())
377 {
378 QDomElement text = dom_document.createElement("text");
379 text.setAttribute("uuid", deti->uuid().toString());
380 dom_texts.appendChild(text);
381 }
382
383 dom_element.appendChild(dom_texts);
384 return dom_element;
385 }
386
387 /**
388 * @brief ElementTextItemGroup::fromXml
389 * Import data of this group from xml
390 * @param dom_element
391 */
fromXml(QDomElement & dom_element)392 void ElementTextItemGroup::fromXml(QDomElement &dom_element)
393 {
394 if (dom_element.tagName() != xmlTaggName()) {
395 qDebug() << "ElementTextItemGroup::fromXml : Wrong tagg name";
396 return;
397 }
398
399 setName(dom_element.attribute("name", "no name"));
400 QMetaEnum me = QMetaEnum::fromType<Qt::Alignment>();
401 setAlignment(Qt::Alignment(me.keyToValue(dom_element.attribute("alignment").toStdString().data())));
402
403 setPos(dom_element.attribute("x", QString::number(0)).toDouble(),
404 dom_element.attribute("y", QString::number(0)).toDouble());
405
406 setRotation(dom_element.attribute("rotation", QString::number(0)).toDouble());
407 setVerticalAdjustment(dom_element.attribute("vertical_adjustment").toInt());
408 setFrame(dom_element.attribute("frame", "false") == "true"? true : false);
409
410 QString hold = dom_element.attribute("hold_to_bottom_page", "false");
411 setHoldToBottomPage(hold == "true" ? true : false);
412
413 if(parentElement())
414 {
415 m_block_alignment_update = true;
416 for(const QDomElement& text : QET::findInDomElement(dom_element, "texts", "text"))
417 {
418 DynamicElementTextItem *deti = nullptr;
419 QUuid uuid(text.attribute("uuid"));
420
421 for(DynamicElementTextItem *txt : parentElement()->dynamicTextItems())
422 if(txt->uuid() == uuid)
423 deti = txt;
424
425 if (deti)
426 parentElement()->addTextToGroup(deti, this);
427 }
428 m_block_alignment_update = false;
429 }
430 }
431
432 /**
433 * @brief ElementTextItemGroup::paint
434 * @param painter
435 * @param option
436 * @param widget
437 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)438 void ElementTextItemGroup::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
439 {
440 Q_UNUSED(option);
441 Q_UNUSED(widget);
442 if(isSelected())
443 {
444 painter->save();
445 QPen t;
446 t.setColor(Qt::gray);
447 t.setStyle(Qt::DashDotLine);
448 t.setCosmetic(true);
449 painter->setPen(t);
450 painter->drawRoundRect(boundingRect().adjusted(1, 1, -1, -1), 10, 10);
451
452 painter->restore();
453 }
454 if(m_frame)
455 {
456 qreal font_size = 1;
457 QRectF rect;
458 for(DynamicElementTextItem *deti : this->texts())
459 {
460 font_size = std::max(font_size, deti->font().pointSizeF());
461 rect = rect.united(mapFromItem(deti, deti->frameRect()).boundingRect());
462 }
463
464 //Adjust the thickness according to the font size
465 qreal w=0.3;
466 if (font_size >= 5)
467 {
468 w = font_size*0.1;
469 if(w > 2.5)
470 w = 2.5;
471 }
472
473 painter->save();
474 QPen pen;
475 pen.setWidthF(w);
476 painter->setPen(pen);
477 painter->setRenderHint(QPainter::Antialiasing);
478
479 //Adjust the rounding of the rectangle according to the size of the font
480 qreal ro = font_size/3;
481 painter->drawRoundedRect(rect, ro, ro);
482 painter->restore();
483 }
484 }
485
486 /**
487 * @brief ElementTextItemGroup::boundingRect
488 * @return
489 */
boundingRect() const490 QRectF ElementTextItemGroup::boundingRect() const
491 {
492 //If we refer to the Qt doc, the bounding rect of a QGraphicsItemGroup,
493 //is the bounding of all childrens in the group
494 //When add an item in the group, the bounding rect is good, but
495 //if we move an item already in the group, the bounding rect of the group stay unchanged.
496 //We reimplement this function to avoid this behavior.
497 QRectF rect;
498 for(QGraphicsItem *qgi : texts())
499 {
500 QRectF r(qgi->pos(), QSize(qgi->boundingRect().width(), qgi->boundingRect().height()));
501 rect = rect.united(r);
502 }
503 return rect;
504 }
505
setRotation(qreal angle)506 void ElementTextItemGroup::setRotation(qreal angle)
507 {
508 QGraphicsItemGroup::setRotation(angle);
509 emit rotationChanged(angle);
510 }
511
setPos(const QPointF & pos)512 void ElementTextItemGroup::setPos(const QPointF &pos)
513 {
514 QPointF old_pos = this->pos();
515 QGraphicsItemGroup::setPos(pos);
516 if (old_pos.x() != this->pos().x())
517 emit xChanged();
518 if (old_pos.y() != this->pos().y())
519 emit yChanged();
520 }
521
setPos(qreal x,qreal y)522 void ElementTextItemGroup::setPos(qreal x, qreal y)
523 {
524 QPointF old_pos = this->pos();
525 QGraphicsItemGroup::setPos(x,y);
526 if (old_pos.x() != this->pos().x())
527 emit xChanged();
528 if (old_pos.y() != this->pos().y())
529 emit yChanged();
530 }
531
532 /**
533 * @brief ElementTextItemGroup::mousePressEvent
534 * @param event
535 */
mousePressEvent(QGraphicsSceneMouseEvent * event)536 void ElementTextItemGroup::mousePressEvent(QGraphicsSceneMouseEvent *event)
537 {
538 if(event->button() == Qt::LeftButton)
539 {
540 m_first_move = true;
541 if(event->modifiers() & Qt::ControlModifier)
542 setSelected(!isSelected());
543 }
544
545 QGraphicsItemGroup::mousePressEvent(event);
546 }
547
548 /**
549 * @brief ElementTextItemGroup::mouseMoveEvent
550 * @param event
551 */
mouseMoveEvent(QGraphicsSceneMouseEvent * event)552 void ElementTextItemGroup::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
553 {
554 if((event->buttons() & Qt::LeftButton) && (flags() & ItemIsMovable))
555 {
556 if(diagram() && m_first_move)
557 diagram()->elementTextsMover().beginMovement(diagram(), this);
558
559 if(m_first_move)
560 {
561 m_initial_position = pos();
562 if(parentElement())
563 parentElement()->setHighlighted(true);
564 }
565
566 QPointF current_parent_pos;
567 QPointF button_down_parent_pos;
568 current_parent_pos = mapToParent(mapFromScene(event->scenePos()));
569 button_down_parent_pos = mapToParent(mapFromScene(event->buttonDownScenePos(Qt::LeftButton)));
570
571 QPointF new_pos = m_initial_position + current_parent_pos - button_down_parent_pos;
572 event->modifiers() == Qt::ControlModifier ? setPos(new_pos) : setPos(Diagram::snapToGrid(new_pos));
573
574 if(diagram())
575 diagram()->elementTextsMover().continueMovement(event);
576 } else {
577 event->ignore();
578 }
579
580 if(m_first_move)
581 m_first_move = false;
582 }
583
584 /**
585 * @brief ElementTextItemGroup::mouseReleaseEvent
586 * @param event
587 */
mouseReleaseEvent(QGraphicsSceneMouseEvent * event)588 void ElementTextItemGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
589 {
590 if(diagram())
591 {
592 diagram()->elementTextsMover().endMovement();
593 if(parentElement())
594 parentElement()->setHighlighted(false);
595 }
596
597 if(!(event->modifiers() & Qt::ControlModifier))
598 QGraphicsItemGroup::mouseReleaseEvent(event);
599 }
600
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event)601 void ElementTextItemGroup::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
602 {
603 if(m_slave_Xref_item)
604 {
605 if(m_slave_Xref_item->boundingRect().contains(mapToItem(m_slave_Xref_item, event->pos())))
606 {
607 if(parentElement()->linkType() == Element::Slave && !parentElement()->linkedElements().isEmpty())
608 {
609 m_slave_Xref_item->setDefaultTextColor(Qt::black);
610 Element *elmt = parentElement()->linkedElements().first();
611
612 //Unselect and ungrab mouse to prevent unwanted
613 //move when linked element is in the same scene of this.
614 setSelected(false);
615 ungrabMouse();
616
617 if(scene() != elmt->scene())
618 elmt->diagram()->showMe();
619 elmt->setSelected(true);
620
621 //Zoom to the element
622 for(QGraphicsView *view : elmt->scene()->views())
623 {
624 QRectF fit = elmt->sceneBoundingRect();
625 fit.adjust(-200, -200, 200, 200);
626 view->fitInView(fit, Qt::KeepAspectRatioByExpanding);
627 }
628 }
629 }
630 }
631 }
632
633 /**
634 * @brief ElementTextItemGroup::keyPressEvent
635 * @param event
636 */
keyPressEvent(QKeyEvent * event)637 void ElementTextItemGroup::keyPressEvent(QKeyEvent *event)
638 {
639 if(event->modifiers() == Qt::ControlModifier)
640 {
641 if(event->key() == Qt::Key_Left && m_alignment != Qt::AlignLeft)
642 {
643 if(diagram())
644 diagram()->undoStack().push(new AlignmentTextsGroupCommand(this, Qt::AlignLeft));
645 else
646 setAlignment(Qt::AlignLeft);
647 }
648 else if (event->key() == Qt::Key_Up && m_alignment != Qt::AlignVCenter)
649 {
650 if(diagram())
651 diagram()->undoStack().push(new AlignmentTextsGroupCommand(this, Qt::AlignVCenter));
652 else
653 setAlignment(Qt::AlignVCenter);
654 }
655 else if (event->key() == Qt::Key_Right && m_alignment != Qt::AlignRight)
656 {
657 if(diagram())
658 diagram()->undoStack().push(new AlignmentTextsGroupCommand(this, Qt::AlignRight));
659 else
660 setAlignment(Qt::AlignRight);
661 }
662 }
663 event->ignore();
664 }
665
hoverEnterEvent(QGraphicsSceneHoverEvent * event)666 void ElementTextItemGroup::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
667 {
668 //The pos of the event is not in this item coordinate,
669 //but in child item hovered by the mouse, so we use the scene pos.
670 if(m_slave_Xref_item &&
671 m_slave_Xref_item->boundingRect().contains(m_slave_Xref_item->mapFromScene(event->scenePos())))
672 m_slave_Xref_item->setDefaultTextColor(Qt::blue);
673
674 QGraphicsItemGroup::hoverEnterEvent(event);
675 }
676
hoverLeaveEvent(QGraphicsSceneHoverEvent * event)677 void ElementTextItemGroup::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
678 {
679 if(m_slave_Xref_item)
680 m_slave_Xref_item->setDefaultTextColor(Qt::black);
681
682 QGraphicsItemGroup::hoverLeaveEvent(event);
683 }
684
updateXref()685 void ElementTextItemGroup::updateXref()
686 {
687 if(m_parent_element->diagram())
688 {
689 QETProject *project = m_parent_element->diagram()->project();
690
691 if(m_parent_element->linkType() == Element::Master &&
692 !m_parent_element->linkedElements().isEmpty())
693 {
694
695 XRefProperties xrp = project->defaultXRefProperties(m_parent_element->kindInformations()["type"].toString());
696
697 if(xrp.snapTo() == XRefProperties::Label)
698 {
699 //At least one text owned by this group must be set with
700 //textFrom -> element info and element info name -> label
701 //for display a xref
702 for(DynamicElementTextItem *deti : texts())
703 {
704 if(deti->textFrom() == DynamicElementTextItem::ElementInfo &&
705 deti->infoName() == "label")
706 {
707 if(!m_Xref_item)
708 m_Xref_item = new CrossRefItem(m_parent_element, this);
709 m_Xref_item->autoPos();
710 return;
711 }
712 }
713 }
714 }
715 else if(m_parent_element->linkType() == Element::Slave &&
716 !m_parent_element->linkedElements().isEmpty())
717 {
718 Element *master_elmt = m_parent_element->linkedElements().first();
719 for(DynamicElementTextItem *deti : texts())
720 {
721 if((deti->textFrom() == DynamicElementTextItem::ElementInfo && deti->infoName() == "label") ||
722 (deti->textFrom() == DynamicElementTextItem::CompositeText && deti->compositeText().contains("%{label")))
723 {
724 XRefProperties xrp = project->defaultXRefProperties(master_elmt->kindInformations()["type"].toString());
725 QString xref_label = xrp.slaveLabel();
726 xref_label = autonum::AssignVariables::formulaToLabel(xref_label, master_elmt->rSequenceStruct(), master_elmt->diagram(), master_elmt);
727
728 if(!m_slave_Xref_item)
729 {
730 m_slave_Xref_item = new QGraphicsTextItem(xref_label, this);
731 m_slave_Xref_item->setFont(QETApp::diagramTextsFont(5));
732
733 m_update_slave_Xref_connection << connect(master_elmt, &Element::xChanged, this, &ElementTextItemGroup::updateXref);
734 m_update_slave_Xref_connection << connect(master_elmt, &Element::yChanged, this, &ElementTextItemGroup::updateXref);
735 m_update_slave_Xref_connection << connect(master_elmt, &Element::elementInfoChange, this, &ElementTextItemGroup::updateXref);
736 m_update_slave_Xref_connection << connect(project, &QETProject::projectDiagramsOrderChanged, this, &ElementTextItemGroup::updateXref);
737 m_update_slave_Xref_connection << connect(project, &QETProject::diagramRemoved, this, &ElementTextItemGroup::updateXref);
738 m_update_slave_Xref_connection << connect(project, &QETProject::XRefPropertiesChanged, this, &ElementTextItemGroup::updateXref);
739 }
740 else
741 m_slave_Xref_item->setPlainText(xref_label);
742
743 adjustSlaveXrefPos();
744 return;
745 }
746 }
747
748 }
749 }
750
751
752 //There is no reason to have a xref, we delete it if exist
753 if(m_Xref_item)
754 {
755 delete m_Xref_item;
756 m_Xref_item = nullptr;
757 }
758 if(m_slave_Xref_item)
759 {
760 delete m_slave_Xref_item;
761 m_slave_Xref_item = nullptr;
762 m_update_slave_Xref_connection.clear();
763 }
764 }
765
adjustSlaveXrefPos()766 void ElementTextItemGroup::adjustSlaveXrefPos()
767 {
768 QRectF r = boundingRect();
769 QPointF pos(r.center().x() - m_slave_Xref_item->boundingRect().width()/2,
770 r.bottom());
771 m_slave_Xref_item->setPos(pos);
772 }
773
autoPos()774 void ElementTextItemGroup::autoPos()
775 {
776 int offset = 5;
777
778 if(m_parent_element->linkType() == Element::Master)
779 {
780 if(!diagram())
781 return;
782
783 MasterElement *master = static_cast<MasterElement *>(m_parent_element);
784 XRefProperties xrp = diagram()->project()->defaultXRefProperties(master->kindInformations()["type"].toString());
785 if(xrp.snapTo() == XRefProperties::Bottom)
786 {
787 QRectF rectXref = master->XrefBoundingRect();
788 offset = xrp.offset() <= 40 ? 5 : xrp.offset();
789
790 offset += (int)rectXref.height();
791 }
792 }
793 qreal r = rotation();
794 centerToBottomDiagram(this, m_parent_element, offset);
795 //centerToBottomDiagram change the rotation of this group if needed,
796 //but setRotation is not a virtual function of QGraphicsItem, and the function centerToBottomDiagram
797 //work with a QGraphicsItem. So we emit the signal if rotation changed
798 if(rotation() != r)
799 emit rotationChanged(rotation());
800 }
801
802