Seamly2D
Code documentation
vgraphicssimpletextitem.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2017 Seamly, LLC *
4  * *
5  * https://github.com/fashionfreedom/seamly2d *
6  * *
7  ***************************************************************************
8  **
9  ** Seamly2D is free software: you can redistribute it and/or modify
10  ** it under the terms of the GNU General Public License as published by
11  ** the Free Software Foundation, either version 3 of the License, or
12  ** (at your option) any later version.
13  **
14  ** Seamly2D is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  ** GNU General Public License for more details.
18  **
19  ** You should have received a copy of the GNU General Public License
20  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
21  **
22  **************************************************************************
23 
24  ************************************************************************
25  **
26  ** @file vgraphicssimpletextitem.cpp
27  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
28  ** @date November 15, 2013
29  **
30  ** @brief
31  ** @copyright
32  ** This source code is part of the Valentine project, a pattern making
33  ** program, whose allow create and modeling patterns of clothing.
34  ** Copyright (C) 2013-2015 Seamly2D project
35  ** <https://github.com/fashionfreedom/seamly2d> All Rights Reserved.
36  **
37  ** Seamly2D is free software: you can redistribute it and/or modify
38  ** it under the terms of the GNU General Public License as published by
39  ** the Free Software Foundation, either version 3 of the License, or
40  ** (at your option) any later version.
41  **
42  ** Seamly2D is distributed in the hope that it will be useful,
43  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
44  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45  ** GNU General Public License for more details.
46  **
47  ** You should have received a copy of the GNU General Public License
48  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
49  **
50  *************************************************************************/
51 
53 
54 #include <QEvent>
55 #include <QFlags>
56 #include <QFont>
57 #include <QGraphicsScene>
58 #include <QGraphicsSceneMouseEvent>
59 #include <QGraphicsView>
60 #include <QKeyEvent>
61 #include <QList>
62 #include <QMessageLogger>
63 #include <QPalette>
64 #include <QPoint>
65 #include <QPolygonF>
66 #include <QRectF>
67 #include <Qt>
68 #include <QtDebug>
69 
70 #include "vmaingraphicsscene.h"
71 #include "vmaingraphicsview.h"
72 #include "vscenepoint.h"
73 #include "global.h"
74 #include "../vmisc/vabstractapplication.h"
75 
76 //---------------------------------------------------------------------------------------------------------------------
77 /**
78  * @brief VGraphicsSimpleTextItem default constructor.
79  * @param parent parent object.
80  */
81 VGraphicsSimpleTextItem::VGraphicsSimpleTextItem(QColor textColor, QGraphicsItem *parent)
82  : QGraphicsSimpleTextItem(parent)
83  , m_fontSize(qApp->Settings()->getPointNameSize())
84  , m_scale(1)
85  , m_textColor(textColor)
86  , m_isNameHovered(false)
87  , selectionType(SelectionType::ByMouseRelease)
88  , m_showParentTooltip(true)
89 {
90  initItem();
91 }
92 
93 //---------------------------------------------------------------------------------------------------------------------
94 /**
95  * @brief VGraphicsSimpleTextItem constructor.
96  * @param text text.
97  * @param parent parent object.
98  */
99 VGraphicsSimpleTextItem::VGraphicsSimpleTextItem(const QString &text, QColor textColor, QGraphicsItem *parent)
100  : QGraphicsSimpleTextItem(text, parent)
101  , m_fontSize(qApp->Settings()->getPointNameSize())
102  , m_scale(1)
103  , m_textColor(textColor)
104  , m_isNameHovered(false)
105  , selectionType(SelectionType::ByMouseRelease)
106  , m_showParentTooltip(true)
107 {
108  initItem();
109 }
110 
111 //---------------------------------------------------------------------------------------------------------------------
112 void VGraphicsSimpleTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
113 {
114  QGraphicsScene *scene = this->scene();
115  const qreal scale = sceneScale(scene);
116 
117  if (scale > 1.0 && not VFuzzyComparePossibleNulls(m_scale, scale))
118  {
119  scalePointName(scale);
120  }
121  else if (scale <= 1.0 && not VFuzzyComparePossibleNulls(m_scale, 1.0))
122  {
123  scalePointName(1.0);
124  }
125 
126  QFont fnt = this->font();
127  if (fnt.pointSize() != qApp->Settings()->getPointNameSize() ||
128  fnt.family() != qApp->Settings()->getPointNameFont().family())
129  {
130  fnt.setPointSize(qApp->Settings()->getPointNameSize());
131  fnt.setFamily(qApp->Settings()->getPointNameFont().family());
132  this->setFont(fnt);
133  }
134 
135  if (QGraphicsView *view = scene->views().at(0))
136  {
137  VMainGraphicsView::NewSceneRect(scene, view, this);
138  }
139 
140  if (m_isNameHovered)
141  {
142  this->setBrush(QBrush(QColor(qApp->Settings()->getPointNameHoverColor())));
143  }
144  else
145  {
146  this->setBrush(QBrush(getTextBrushColor()));
147  }
148 
149  QGraphicsSimpleTextItem::paint(painter, option, widget);
150 }
151 
152 //---------------------------------------------------------------------------------------------------------------------
154 {
155  QGraphicsSimpleTextItem::setEnabled(enabled);
156  this->setBrush(QBrush(getTextBrushColor()));
157 }
158 
159 //---------------------------------------------------------------------------------------------------------------------
161 {
163 }
164 
165 //---------------------------------------------------------------------------------------------------------------------
167 {
168  m_showParentTooltip = show;
169 }
170 
171 //---------------------------------------------------------------------------------------------------------------------
172 /**
173  * @brief itemChange handle item change.
174  * @param change change.
175  * @param value value.
176  * @return value.
177  */
178 QVariant VGraphicsSimpleTextItem::itemChange(GraphicsItemChange change, const QVariant &value)
179 {
180  if (change == ItemPositionChange && scene())
181  {
182  // Each time we move something we call recalculation scene rect. In some cases this can cause moving
183  // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last move.
184  static bool changeFinished = true;
185 
186  if (changeFinished)
187  {
188  changeFinished = false;
189  if (scene())
190  {
191  const QList<QGraphicsView *> viewList = scene()->views();
192  if (not viewList.isEmpty())
193  {
194  if (QGraphicsView *view = viewList.at(0))
195  {
196  const int xmargin = 50;
197  const int ymargin = 50;
198 
199  const QRectF viewRect = VMainGraphicsView::SceneVisibleArea(view);
200  const QRectF itemRect = mapToScene(boundingRect()).boundingRect();
201 
202  // If item's rect is bigger than view's rect ensureVisible works very unstable.
203  if (itemRect.height() + 2*ymargin < viewRect.height() &&
204  itemRect.width() + 2*xmargin < viewRect.width())
205  {
206  view->ensureVisible(itemRect, xmargin, ymargin);
207  }
208  else
209  {
210  // Ensure visible only small rect around a cursor
211  VMainGraphicsScene *currentScene = qobject_cast<VMainGraphicsScene *>(scene());
212  SCASSERT(currentScene)
213  const QPointF cursorPosition = currentScene->getScenePos();
214  view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10));
215  }
216  }
217  }
218  }
219 
220  m_pointNamePos = value.toPointF();
221  const qreal scale = sceneScale(scene());
222 
223  if (scale > 1)
224  {
225  QLineF line(QPointF(), m_pointNamePos);
226  line.setLength(line.length() * scale);
227  m_pointNamePos = line.p2();
228  }
229  emit nameChangedPosition(m_pointNamePos + this->parentItem()->pos());
230 
231  changeFinished = true;
232  }
233  }
234 
235  if (change == QGraphicsItem::ItemSelectedChange)
236  {
237  setFlag(QGraphicsItem::ItemIsFocusable, value.toBool());
238  emit pointSelected(value.toBool());
239  }
240  return QGraphicsSimpleTextItem::itemChange(change, value);
241  //return QGraphicsItem::itemChange(change, value);
242 }
243 
244 //---------------------------------------------------------------------------------------------------------------------
245 /**
246  * @brief hoverEnterEvent handle hover enter events.
247  * @param event hover enter event.
248  */
249 void VGraphicsSimpleTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
250 {
251  m_isNameHovered = true;
252  if (flags() & QGraphicsItem::ItemIsMovable)
253  {
255  }
256  else
257  {
258  setCursor(qApp->getSceneView()->viewport()->cursor());
259  }
260 
261  QGraphicsItem *parent = parentItem();
262  if(parent && m_showParentTooltip)
263  {
264  setToolTip(parent->toolTip());
265  }
266 
267  QGraphicsSimpleTextItem::hoverEnterEvent(event);
268 }
269 
270 //---------------------------------------------------------------------------------------------------------------------
271 /**
272  * @brief hoverLeaveEvent handle hover leave events.
273  * @param event hover leave event.
274  */
275 void VGraphicsSimpleTextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
276 {
277  m_isNameHovered = false;
278  if (flags() & QGraphicsItem::ItemIsMovable)
279  {
280  setCursor(QCursor());
281  }
282 
283  QGraphicsSimpleTextItem::hoverLeaveEvent(event);
284 }
285 
286 //---------------------------------------------------------------------------------------------------------------------
287 /**
288  * @brief contextMenuEvent handle context menu events.
289  * @param event context menu event.
290  */
291 void VGraphicsSimpleTextItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
292 {
293  emit showContextMenu(event);
294 }
295 
296 //---------------------------------------------------------------------------------------------------------------------
297 void VGraphicsSimpleTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
298 {
299  // Special for not selectable item first need to call standard mousePressEvent then accept event
300  QGraphicsSimpleTextItem::mousePressEvent(event);
301 
302  // Somehow clicking on notselectable object do not clean previous selections.
303  if (not (flags() & ItemIsSelectable) && scene())
304  {
305  scene()->clearSelection();
306  }
307 
308  if (flags() & QGraphicsItem::ItemIsMovable)
309  {
310  if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
311  {
313  }
314  }
316  {
317  event->accept(); // This help for not selectable items still receive mouseReleaseEvent events
318  }
319  else
320  {
321  if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
322  {
323  emit pointChosen();
324  event->accept();
325  }
326  }
327 }
328 
329 //---------------------------------------------------------------------------------------------------------------------
330 void VGraphicsSimpleTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
331 {
332  if (flags() & QGraphicsItem::ItemIsMovable)
333  {
334  if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
335  {
337  }
338  }
339 
341  {
342  emit pointChosen();
343  }
344 
345  QGraphicsSimpleTextItem::mouseReleaseEvent(event);
346 }
347 
348 //---------------------------------------------------------------------------------------------------------------------
350 {
351  switch (event->key())
352  {
353  case Qt::Key_Delete:
354  emit deleteTool();
355  return; //Leave this method immediately after call!!!
356  default:
357  break;
358  }
359  QGraphicsSimpleTextItem::keyReleaseEvent (event);
360 }
361 
363 {
364  if (qApp->Settings()->getUseToolColor())
365  {
366  QColor textColor = correctColor(this, m_textColor);
367  textColor.setAlpha(224);
368  return textColor;
369  }
370  else
371  {
372  QColor textColor = correctColor(this, QColor(qApp->Settings()->getPointNameColor()));
373  textColor.setAlpha(224);
374  return textColor;
375  }
376 }
377 
378 void VGraphicsSimpleTextItem::setTextColor(const QColor &color)
379 {
380  m_textColor = color;
381  this->setBrush(QBrush(getTextBrushColor()));
382 }
383 
384 //---------------------------------------------------------------------------------------------------------------------
386 {
387  m_pointNamePos = pos;
388 
389  scalePosition();
390 }
391 
393 {
394  this->setFlag(QGraphicsItem::ItemIsMovable, true);
395  this->setFlag(QGraphicsItem::ItemIsSelectable, true);
396  this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
397  this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus
398  this->setAcceptHoverEvents(true);
399 
400  QFont fnt = font();
401  fnt.setPointSize(m_fontSize);
402  fnt.setFamily(qApp->Settings()->getPointNameFont().family());
403  setFont(fnt);
404 
405  setScale(m_scale);
406 
407  setBrush(QBrush(getTextBrushColor()));
408 }
409 
410 //---------------------------------------------------------------------------------------------------------------------
411 /**
412  * @brief scalePointName handle point name scaling to maintain same size when scene scale changes.
413  * @param scale parent scene scale.
414  */
416 {
417  setScale(1/scale);
418  scalePosition();
419  updateLeader();
420  m_scale = scale;
421 }
422 
423 //---------------------------------------------------------------------------------------------------------------------
424 /**
425  * @brief scalePosition handle point name position scaling to maintain same distance when scene scale changes.
426  */
428 {
429  const qreal scale = sceneScale(scene());
430  QPointF newPos = m_pointNamePos;
431 
432  if (scale > 1)
433  {
434  QLineF line(QPointF(), m_pointNamePos);
435  line.setLength(line.length() / scale);
436  newPos = line.p2();
437  }
438 
439  blockSignals(true);
440  setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
441  setPos(newPos);
442  setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
443  blockSignals(false);
444 }
445 
446 //---------------------------------------------------------------------------------------------------------------------
448 {
449  if (VScenePoint *parent = dynamic_cast<VScenePoint *>(parentItem()))
450  {
451  parent->refreshLeader();
452  }
453 }
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE
void setTextColor(const QColor &color)
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) Q_DECL_OVERRIDE
itemChange handle item change.
virtual int type() const Q_DECL_OVERRIDE
void scalePointName(const qreal &scale)
scalePointName handle point name scaling to maintain same size when scene scale changes.
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) Q_DECL_OVERRIDE
hoverEnterEvent handle hover enter events.
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) Q_DECL_OVERRIDE
hoverLeaveEvent handle hover leave events.
qint32 m_fontSize
fontSize label font size.
void textSelectionType(const SelectionType &type)
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE
void showContextMenu(QGraphicsSceneContextMenuEvent *event)
showContextMenu emit when need show tool context menu.
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) Q_DECL_OVERRIDE
virtual void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE
VGraphicsSimpleTextItem(QColor color, QGraphicsItem *parent=nullptr)
VGraphicsSimpleTextItem default constructor.
void nameChangedPosition(const QPointF &pos)
nameChangedPosition emit when label change position.
void pointSelected(bool selected)
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) Q_DECL_OVERRIDE
contextMenuEvent handle context menu events.
void scalePosition()
scalePosition handle point name position scaling to maintain same distance when scene scale changes.
The VMainGraphicsScene class main scene.
QPointF getScenePos() const
static QRectF SceneVisibleArea(QGraphicsView *view)
static void NewSceneRect(QGraphicsScene *sc, QGraphicsView *view, QGraphicsItem *item=nullptr)
NewSceneRect calculate scene rect what contains all items and doesn't less that size of scene view.
const QString cursorArrowOpenHand
Definition: def.cpp:191
void SetItemOverrideCursor(QGraphicsItem *item, const QString &pixmapPath, int hotX, int hotY)
Definition: def.cpp:206
const QString cursorArrowCloseHand
Definition: def.cpp:192
#define SCASSERT(cond)
Definition: def.h:317
static Q_REQUIRED_RESULT bool VFuzzyComparePossibleNulls(double p1, double p2)
Definition: def.h:490
SelectionType
Definition: def.h:108
qreal sceneScale(QGraphicsScene *scene)
Definition: global.cpp:63
QColor correctColor(const QGraphicsItem *item, const QColor &color)
Definition: global.cpp:80
#define qApp
Definition: vapplication.h:67