QElectroTech  0.70
partdynamictextfield.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 "partdynamictextfield.h"
20 #include "qetapp.h"
21 #include "elementscene.h"
22 
23 #include <QGraphicsSceneMouseEvent>
24 #include <QFont>
25 #include <QColor>
26 
28  QGraphicsTextItem(parent),
29  CustomElementPart(editor),
30  m_uuid(QUuid::createUuid())
31 {
32  setDefaultTextColor(Qt::black);
34  QSettings settings;
35  setRotation(settings.value("diagrameditor/dynamic_text_rotation", 0).toInt());
36  setTextWidth(settings.value("diagrameditor/dynamic_text_width", -1).toInt());
37  setText("_");
39  setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges | QGraphicsItem::ItemIsMovable);
40 
41 
42  //Option when text is displayed in multiple line
43  QTextOption option = document()->defaultTextOption();
44  option.setAlignment(Qt::AlignHCenter);
45  option.setWrapMode(QTextOption::WordWrap);
46  document()->setDefaultTextOption(option);
47 }
48 
50 {
51  return tr("Champ de texte dynamique", "element part name");
52 }
53 
55 {
56  return QString("dynamic_text");
57 }
58 
65 void PartDynamicTextField::startUserTransformation(const QRectF &initial_selection_rect)
66 {
67  Q_UNUSED(initial_selection_rect)
68  m_saved_point = pos(); // scene coordinates, no need to mapFromScene()
69 }
70 
77 void PartDynamicTextField::handleUserTransformation(const QRectF &initial_selection_rect, const QRectF &new_selection_rect)
78 {
79  QPointF new_pos = mapPoints(initial_selection_rect, new_selection_rect, QList<QPointF>() << m_saved_point).first();
80  setPos(new_pos);
81 }
82 
88 const QDomElement PartDynamicTextField::toXml(QDomDocument &dom_doc) const
89 {
90  QDomElement root_element = dom_doc.createElement(xmlName());
91 
92  root_element.setAttribute("x", QString::number(pos().x()));
93  root_element.setAttribute("y", QString::number(pos().y()));
94  root_element.setAttribute("z", QString::number(zValue()));
95  root_element.setAttribute("rotation", QString::number(QET::correctAngle(rotation())));
96  root_element.setAttribute("font", font().toString());
97  root_element.setAttribute("uuid", m_uuid.toString());
98  root_element.setAttribute("frame", m_frame? "true" : "false");
99  root_element.setAttribute("text_width", QString::number(m_text_width));
100 
101 
103  root_element.setAttribute("text_from", me.valueToKey(m_text_from));
104 
105  me = QMetaEnum::fromType<Qt::Alignment>();
106  if(this->alignment() &Qt::AlignRight)
107  root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignRight));
108  else if(this->alignment() &Qt::AlignLeft)
109  root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignLeft));
110  else if(this->alignment() &Qt::AlignHCenter)
111  root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignHCenter));
112 
113  if(this->alignment() &Qt::AlignBottom)
114  root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignBottom));
115  else if(this->alignment() & Qt::AlignTop)
116  root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignTop));
117  else if(this->alignment() &Qt::AlignVCenter)
118  root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignVCenter));
119 
120  QDomElement dom_text = dom_doc.createElement("text");
121  dom_text.appendChild(dom_doc.createTextNode(toPlainText()));
122  root_element.appendChild(dom_text);
123 
124  //Info name
125  if(!m_info_name.isEmpty())
126  {
127  QDomElement dom_info_name = dom_doc.createElement("info_name");
128  dom_info_name.appendChild(dom_doc.createTextNode(m_info_name));
129  root_element.appendChild(dom_info_name);
130  }
131 
132  //Composite text
133  if(!m_composite_text.isEmpty())
134  {
135  QDomElement dom_comp_text = dom_doc.createElement("composite_text");
136  dom_comp_text.appendChild(dom_doc.createTextNode(m_composite_text));
137  root_element.appendChild(dom_comp_text);
138  }
139 
140  //Color
141  if(color() != QColor(Qt::black))
142  {
143  QDomElement dom_color = dom_doc.createElement("color");
144  dom_color.appendChild(dom_doc.createTextNode(color().name()));
145  root_element.appendChild(dom_color);
146  }
147 
148  return root_element;
149 }
150 
155 void PartDynamicTextField::fromXml(const QDomElement &dom_elmt)
156 {
157  if (dom_elmt.tagName() != xmlName()) {
158  qDebug() << "PartDynamicTextField::fromXml : Wrong tagg name";
159  return;
160  }
161 
162  QGraphicsTextItem::setPos(dom_elmt.attribute("x", QString::number(0)).toDouble(),
163  dom_elmt.attribute("y", QString::number(0)).toDouble());
164  setZValue(dom_elmt.attribute("z", QString::number(zValue())).toDouble());
165  QGraphicsTextItem::setRotation(dom_elmt.attribute("rotation", QString::number(0)).toDouble());
166 
167  if (dom_elmt.hasAttribute("font"))
168  {
169  QFont font_;
170  font_.fromString(dom_elmt.attribute("font"));
171  setFont(font_);
172  } else { //Keep compatibility TODO remove in futur
174  }
175 
176  m_uuid = QUuid(dom_elmt.attribute("uuid", QUuid::createUuid().toString()));
177  setFrame(dom_elmt.attribute("frame", "false") == "true"? true : false);
178  setTextWidth(dom_elmt.attribute("text_width", QString::number(-1)).toDouble());
179 
181  m_text_from = DynamicElementTextItem::TextFrom(me.keyToValue(dom_elmt.attribute("text_from").toStdString().data()));
182 
183  me = QMetaEnum::fromType<Qt::Alignment>();
184  if(dom_elmt.hasAttribute("Halignment"))
185  setAlignment(Qt::Alignment(me.keyToValue(dom_elmt.attribute("Halignment").toStdString().data())));
186  if(dom_elmt.hasAttribute(("Valignment")))
187  setAlignment(Qt::Alignment(me.keyToValue(dom_elmt.attribute("Valignment").toStdString().data())) | this->alignment());
188 
189  //Text
190  QDomElement dom_text = dom_elmt.firstChildElement("text");
191  if (!dom_text.isNull())
192  {
193  m_text = dom_text.text();
194  m_block_alignment = true;
196  m_block_alignment = false;
197  }
198 
199  //Info name
200  QDomElement dom_info_name = dom_elmt.firstChildElement("info_name");
201  if(!dom_info_name.isNull())
202  m_info_name = dom_info_name.text();
203 
204  //Composite text
205  QDomElement dom_comp_text = dom_elmt.firstChildElement("composite_text");
206  if(!dom_comp_text.isNull())
207  m_composite_text = dom_comp_text.text();
208 
209  //Color
210  QDomElement dom_color = dom_elmt.firstChildElement("color");
211  if(!dom_color.isNull())
212  setColor(QColor(dom_color.text()));
213 }
214 
220 void PartDynamicTextField::fromTextFieldXml(const QDomElement &dom_element)
221 {
222  if(dom_element.tagName() != "input")
223  return;
224 
225  setFont(QETApp::diagramTextsFont(dom_element.attribute("size", QString::number(9)).toInt()));
226 
227  if(dom_element.attribute("tagg", "none") == "none")
228  {
230  setText(dom_element.attribute("text", "_"));
231  }
232  else
233  {
235  setInfoName(dom_element.attribute("tagg", "label"));
236  }
237 
238  QGraphicsTextItem::setRotation(dom_element.attribute("rotation", "0").toDouble());
239 
240  //the origin transformation point of PartDynamicTextField is the top left corner, no matter the font size
241  //The origin transformation point of PartTextField is the middle of left edge, and so by definition, change with the size of the font
242  //We need to use a QTransform to find the pos of this text from the saved pos of text item
243  QTransform transform;
244  //First make the rotation
245  transform.rotate(dom_element.attribute("rotation", "0").toDouble());
246  QPointF pos = transform.map(QPointF(0, -boundingRect().height()/2));
247  transform.reset();
248  //Second translate to the pos
249  transform.translate(dom_element.attribute("x", QString::number(0)).toDouble(),
250  dom_element.attribute("y", QString::number(0)).toDouble());
251  QGraphicsTextItem::setPos(transform.map(pos));
252 }
253 
259  return m_text_from;
260 }
261 
268 {
269  m_text_from = text_from;
270  switch (m_text_from)
271  {
274  break;
277  break;
280  break;
281  default:
282  break;
283  }
285 }
286 
291 QString PartDynamicTextField::text() const {
292  return m_text;
293 }
294 
300 void PartDynamicTextField::setText(const QString &text)
301 {
302  m_text = text;
304  emit textChanged(m_text);
305 }
306 
307 void PartDynamicTextField::setInfoName(const QString &info_name)
308 {
309  m_info_name = info_name;
311  setPlainText(elementScene()->elementInformation().value(m_info_name).toString());
313 }
314 
319 QString PartDynamicTextField::infoName() const{
320  return m_info_name;
321 }
322 
328 void PartDynamicTextField::setCompositeText(const QString &text)
329 {
334 }
335 
341  return m_composite_text;
342 }
343 
348 void PartDynamicTextField::setColor(const QColor& color)
349 {
350  setDefaultTextColor(color);
351  emit colorChanged(color);
352 }
353 
358 QColor PartDynamicTextField::color() const {
359  return defaultTextColor();
360 }
361 
363 {
364  m_frame = frame;
365  update();
366  emit frameChanged(m_frame);
367 }
368 
369 bool PartDynamicTextField::frame() const
370 {
371  return m_frame;
372 }
373 
375 {
376  this->document()->setTextWidth(width);
377 
378  //Adjust the width, to ideal width if needed
379  if(width > 0 && document()->size().width() > width)
380  document()->setTextWidth(document()->idealWidth());
381 
382  m_text_width = document()->textWidth();
384 }
385 
386 void PartDynamicTextField::setPlainText(const QString &text)
387 {
388  if(toPlainText() == text)
389  return;
390 
392  QGraphicsTextItem::setPlainText(text);
393 
394  //User define a text width
395  if(m_text_width > 0)
396  {
397  if(document()->size().width() > m_text_width)
398  {
399  document()->setTextWidth(m_text_width);
400  if(document()->size().width() > m_text_width)
401  {
402  document()->setTextWidth(document()->idealWidth());
403  }
404  }
405  }
406  finishAlignment();
407 }
408 
409 void PartDynamicTextField::setAlignment(Qt::Alignment alignment)
410 {
413 }
414 
415 Qt::Alignment PartDynamicTextField::alignment() const {
416  return m_alignment;
417 }
418 
419 void PartDynamicTextField::setFont(const QFont &font)
420 {
421  if (font == this->font()) {
422  return;
423  }
425  QGraphicsTextItem::setFont(font);
426  finishAlignment();
427  emit fontChanged(font);
428 }
429 
434 void PartDynamicTextField::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
435 {
436  if((event->buttons() & Qt::LeftButton) && (flags() & QGraphicsItem::ItemIsMovable))
437  {
438  QPointF pos = event->scenePos() + (m_origine_pos - event->buttonDownScenePos(Qt::LeftButton));
439  event->modifiers() == Qt::ControlModifier ? setPos(pos) : setPos(elementScene()->snapToGrid(pos));
440  }
441  else
442  QGraphicsObject::mouseMoveEvent(event);
443 }
444 
449 void PartDynamicTextField::mousePressEvent(QGraphicsSceneMouseEvent *event)
450 {
451  if(event->button() == Qt::LeftButton)
452  m_origine_pos = this->pos();
453 
454  QGraphicsObject::mousePressEvent(event);
455 }
456 
461 void PartDynamicTextField::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
462 {
463  if((event->button() & Qt::LeftButton) && (flags() & QGraphicsItem::ItemIsMovable) && m_origine_pos != pos())
464  {
465  QPropertyUndoCommand *undo = new QPropertyUndoCommand(this, "pos", QVariant(m_origine_pos), QVariant(pos()));
466  undo->setText(tr("Déplacer un champ texte"));
467  undo->enableAnimation();
468  elementScene()->undoStack().push(undo);
469  }
470 
471  QGraphicsObject::mouseReleaseEvent(event);
472 }
473 
480 QVariant PartDynamicTextField::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
481 {
482  if (change == QGraphicsItem::ItemPositionHasChanged || change == QGraphicsItem::ItemSceneHasChanged)
483  {
485  if(change == QGraphicsItem::ItemSceneHasChanged &&
486  m_first_add &&
487  elementScene() != nullptr)
488  {
490  m_first_add = false;
491  }
492  }
493  else if ((change == QGraphicsItem::ItemSelectedHasChanged) && (value.toBool() == true))
495 
496  return(QGraphicsTextItem::itemChange(change, value));
497 }
498 
499 void PartDynamicTextField::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
500 {
501  QGraphicsTextItem::paint(painter, option, widget);
502 
503  if (m_frame)
504  {
505  painter->save();
506  painter->setFont(this->font());
507 
508  //Adjust the thickness according to the font size,
509  qreal w=0.3;
510  if(this->font().pointSize() >= 5)
511  {
512  w = this->font().pointSizeF()*0.1;
513  if(w > 2.5)
514  w = 2.5;
515  }
516 
517  QPen pen;
518  pen.setColor(color());
519  pen.setWidthF(w);
520  painter->setPen(pen);
521  painter->setRenderHint(QPainter::Antialiasing);
522 
523  //Get the bounding rectangle of the text
524  QSizeF size = document()->size();
525  size.setWidth(document()->idealWidth());
526  //Remove the margin. Size is exactly the bounding rect of the text
527  size.rheight() -= document()->documentMargin()*2;
528  size.rwidth() -= document()->documentMargin()*2;
529  //Add a little margin only for a better visual;
530  size.rheight() += 2;
531  size.rwidth() += 2;
532 
533  //The pos of the rect
534  QPointF pos = boundingRect().center();
535  pos.rx() -= size.width()/2;
536  pos.ry() -= size.height()/2;
537 
538  //Adjust the rounding of the rectangle according to the size of the font
539  qreal ro = this->font().pointSizeF()/3;
540  painter->drawRoundedRect(QRectF(pos, size), ro, ro);
541 
542  painter->restore();
543  }
544 }
545 
551 {
552  if(!elementScene())
553  return;
554 
556  setPlainText(elementScene()->elementInformation().value(m_info_name).toString());
559 }
560 
562 {
563  m_alignment_rect = boundingRect();
564 }
565 
567 {
569  return;
570 
571  QTransform transform;
572  transform.rotate(this->rotation());
573  qreal x,xa, y,ya;
574  x=xa=0;
575  y=ya=0;
576 
577  if(m_alignment &Qt::AlignRight)
578  {
579  x = m_alignment_rect.right();
580  xa = boundingRect().right();
581  }
582  else if(m_alignment &Qt::AlignHCenter)
583  {
584  x = m_alignment_rect.center().x();
585  xa = boundingRect().center().x();
586  }
587 
588  if(m_alignment &Qt::AlignBottom)
589  {
590  y = m_alignment_rect.bottom();
591  ya = boundingRect().bottom();
592  }
593  else if(m_alignment &Qt::AlignVCenter)
594  {
595  y = m_alignment_rect.center().y();
596  ya = boundingRect().center().y();
597  }
598 
599  QPointF p = transform.map(QPointF(x,y));
600  QPointF pa = transform.map(QPointF(xa,ya));
601  QPointF diff = pa-p;
602 
603  setPos(this->pos() - diff);
604 }
The QPropertyUndoCommand class This undo command manage QProperty of a QObject. This undo command can...
void setInfoName(const QString &info_name)
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override
PartDynamicTextField::itemChange.
void elementInfoChanged()
void setFont(const QFont &font)
DynamicElementTextItem::TextFrom textFrom() const
void setTextWidth(qreal width)
void handleUserTransformation(const QRectF &initial_selection_rect, const QRectF &new_selection_rect) override
PartDynamicTextField::handleUserTransformation.
void compositeTextChanged(QString text)
void colorChanged(QColor color)
void setColor(const QColor &color)
PartDynamicTextField::setColor.
Qt::Alignment alignment() const
QString xmlName() const override
void textChanged(QString text)
void fromTextFieldXml(const QDomElement &dom_element)
PartDynamicTextField::fromTextFieldXml Setup this text from the xml definition of a text field (The x...
void setAlignment(Qt::Alignment alignment)
void setTextFrom(DynamicElementTextItem::TextFrom text_from)
PartDynamicTextField::setTextFrom Set the final text is created from.
void enableAnimation(bool animate=true)
QPropertyUndoCommand::enableAnimation True to enable animation.
void setText(const QString &text)
PartDynamicTextField::setText Set the text of this text.
void mousePressEvent(QGraphicsSceneMouseEvent *event) override
PartDynamicTextField::mousePressEvent.
bool frame() const
QList< QPointF > mapPoints(const QRectF &, const QRectF &, const QList< QPointF > &)
void fontChanged(QFont font)
QUndoStack & undoStack()
qreal correctAngle(const qreal &)
Definition: qet.cpp:505
void fromXml(const QDomElement &dom_elmt) override
PartDynamicTextField::fromXml.
static QMetaEnum textFromMetaEnum()
DynamicElementTextItem::textFromMetaEnum.
void setCompositeText(const QString &text)
PartDynamicTextField::setCompositeText Set the composite text of this text item to ...
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
void alignmentChanged(Qt::Alignment alignment)
void textWidthChanged(qreal width)
QIcon tr
Definition: qeticons.cpp:204
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
PartDynamicTextField::mouseMoveEvent.
static QFont dynamicTextsItemFont(qreal=-1.0)
QETApp::dynamicTextsFont the defaukt font of dynamic element text item.
Definition: qetapp.cpp:962
DynamicElementTextItem::TextFrom m_text_from
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override
PartDynamicTextField::mouseReleaseEvent.
void textFromChanged(DynamicElementTextItem::TextFrom text_from)
virtual void updateCurrentPartEditor() const
void setPlainText(const QString &text)
void infoNameChanged(QString info)
void elementInfoChanged()
PartDynamicTextField::elementInfoChanged Used to up to date this text field, when the element informa...
PartDynamicTextField(QETElementEditor *editor, QGraphicsItem *parent=nullptr)
QIcon ro
Definition: qeticons.cpp:199
QString infoName() const
static QFont diagramTextsFont(qreal=-1.0)
QETApp::diagramTextsFont The font to use By default the font is "sans Serif" and size 9...
Definition: qetapp.cpp:910
QColor color() const
QString text() const
virtual ElementScene * elementScene() const
QString compositeText() const
void frameChanged(bool frame)
void startUserTransformation(const QRectF &initial_selection_rect) override
PartDynamicTextField::startUserTransformation.
QString name() const override
const QDomElement toXml(QDomDocument &dom_doc) const override
PartDynamicTextField::toXml.
static QString replaceVariable(const QString &formula, const DiagramContext &dc)
AssignVariables::replaceVariable Replace the variables in in form %{my-var} to the corresponding val...