RoundRectItem.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * 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 this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "RoundRectItem.h"
25 #include "MorphingItem.h"
26 #include <QtGui>
27 #include <QGraphicsView>
28 #include <QGraphicsSceneMouseEvent>
29 #include <QApplication>
32 #define RESIZE_RECT 30
33 #define ROUNDEDGESIZE 50
34 
35 
36 RoundRectItem::RoundRectItem(const QRectF& bounds, const QColor& color,
37  QGraphicsItem* parent)
38  : QGraphicsObject(parent),
39  rimPen(Qt::black, 1),
40  bounds(bounds)
41 {
42  setCursor = false;
43  scalingActive = false;
44  editable = true;
45  resizingMode = eNone;
46  setCacheMode(DeviceCoordinateCache);
47  setColor(color);
48  setFlag(QGraphicsItem::ItemIsSelectable, true);
49  setFlag(QGraphicsItem::ItemIsMovable, true);
50  // setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
51  setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
52  setAcceptHoverEvents(true);
53 
54 
55  float curScale = scale();
56  // adjustScale(curScale);
57  setScale(curScale);
58  QPointF curPos = pos();
59  adjustPosition(curPos);
60  setPos(curPos);
61 }
62 
63 void RoundRectItem::setColor(QColor newColor)
64 {
65  color = newColor;
66  fillGradient.setStart(bounds.topLeft());
67  fillGradient.setFinalStop(bounds.bottomRight());
68  fillGradient.setColorAt(0, newColor);
69  fillGradient.setColorAt(1, newColor.darker(100));
70  update();
71 }
72 
73 void RoundRectItem::setRimPen(QPen newPen)
74 {
75  rimPen = newPen;
76 }
77 
79 {
80  return bounds.adjusted(0, 0, 2, 2);
81 }
82 
83 void RoundRectItem::setBounds(QRectF newBounds)
84 {
85  if (bounds == newBounds)
86  {
87  return;
88  }
89 
90  prepareGeometryChange();
91  QRectF oldBounds = bounds;
92  bounds = newBounds;
93  itemResized(oldBounds, bounds);
94 }
95 
96 void RoundRectItem::setSize(const QSizeF& newSize)
97 {
98  if (newSize == bounds.size())
99  {
100  return;
101  }
102 
103  QRectF oldBounds = bounds;
104  prepareGeometryChange();
105  bounds.setSize(newSize);
106  setColor(color);
107  itemResized(oldBounds, bounds);
108 }
109 
110 void RoundRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
111  QWidget* widget)
112 {
113 
114 
115  painter->setPen(Qt::NoPen);
116  painter->setBrush(QColor(0, 0, 0, 64));
117  painter->drawRoundedRect(bounds.translated(2, 2), ROUNDEDGESIZE, ROUNDEDGESIZE);
118 
119  QLinearGradient tempGradient = fillGradient;
120  QPen tmpRimPen = rimPen;
121  if (isSelected())
122  {
123  tempGradient.setColorAt(1, color.lighter(130));
124  tmpRimPen.setStyle(Qt::DashLine);
125  // tmpRimPen.setWidthF(tmpRimPen.widthF() * 2);
126  }
127 
128  painter->setBrush(tempGradient);
129  painter->setPen(tmpRimPen);
130  painter->drawRoundedRect(bounds, ROUNDEDGESIZE, ROUNDEDGESIZE);
131 
132  painter->setPen(QPen(Qt::black, 1));
133 
134  // QGraphicsObject::paint(painter, option, widget);
135 }
136 
137 
138 void RoundRectItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
139 {
140  RoundRectItem* parent = dynamic_cast<RoundRectItem*>(parentItem());
141  if (event->modifiers().testFlag(Qt::ShiftModifier)
142  && (!parent || parent->isEditable()))
143  {
144  setFlag(QGraphicsItem::ItemIsMovable, true);
145  }
146  else
147  {
148  setFlag(QGraphicsItem::ItemIsMovable, false);
149  }
150 
151  if (isLevelOfDetailLow(event))
152  {
153  event->ignore();
154  return;
155  }
156 
157  // std::cout << "item pos : " << pos().x() << ", " << pos().y() << std::endl;
158  // std::cout << "item scene pos : " << this->mapToScene(pos()).x() << ", " << this->mapToScene(pos()).y()<< std::endl;
159  QPointF pos = event->pos();
160  // ARMARX_INFO_S << "pos: " << pos;
161  QRectF oldRect = boundingRect();
162  QRectF rect = boundingRect();
163  // rect = rect.size().scale(scale());
164  // ARMARX_INFO_S << "rect: " << rect.width() << ", " << rect.height();
165  rect.setTopLeft(QPointF(rect.bottomRight().rx() - RESIZE_RECT, rect.bottomRight().ry() - RESIZE_RECT));
166 
167  // ARMARX_INFO_S << "rect: " << rect.topLeft() << ", " << rect.bottomRight();
168  if (rect.contains(pos))
169  {
170  scalingActive = true;
171  prepareGeometryChange();
172  // bounds.setBottomRight(QPointF(pos.x()+2, pos.y()+2));
173  itemResized(oldRect, bounds);
174  // update(/*bounds.adjusted(-20,-20,20,20)*/);
175  // if(parentItem())
176  // parentItem()->update(mapRectToParent(bounds.adjusted(-20,-20,20,20)));
177  }
178  else if (getBottomResizeBB().contains(pos))
179  {
180  resizingMode = eBottomResizing;
181  }
182  else if (getTopResizeBB().contains(pos))
183  {
184  resizingMode = eTopResizing;
185 
186  }
187  else if (getLeftResizeBB().contains(pos))
188  {
189  resizingMode = eLeftResizing;
190 
191  }
192  else if (getRightResizeBB().contains(pos))
193  {
194  resizingMode = eRightResizing;
195 
196  }
197  else
198  {
199  QGraphicsObject::mousePressEvent(event);
200  }
201 }
202 
203 void RoundRectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
204 {
205  // ARMARX_INFO_S << "pos: " << event->pos();
206  if (setCursor)
207  {
208  QApplication::restoreOverrideCursor();
209  }
210 
211  setCursor = false;
212  scalingActive = false;
213  resizingMode = eNone;
214  QGraphicsItem::mouseReleaseEvent(event);
215 }
216 
217 void RoundRectItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
218 {
219  QPointF pos = event->pos();
220 
221  if (scalingActive)
222  {
223  QRectF oldRect = boundingRect();
224  prepareGeometryChange();
225  QRectF newRect = oldRect;
226  newRect.setBottomRight(QPointF(pos.x() + 2, pos.y() + 2));
227 
228  // if(parentItem())
229  // {
230  // QRectF boundsP = mapRectFromParent(parentItem()->boundingRect());
231  // float xRatio = newRect.width()/boundsP.width();
232  // float yRatio = newRect.height()/boundsP.height();
233  // float maxRatio = std::max(xRatio,yRatio);
234  //// ARMARX_INFO << VAROUT(ratio) << " " << newRect.width() << ", " << newRect.height() << " --- " << boundsP.width() << ", " << boundsP.height();
235  // if(maxRatio > 0.4)
236  // {
237  // newRect.setWidth(newRect.width() * 0.4/maxRatio);
238  // newRect.setHeight(newRect.height() * 0.4/maxRatio);
239  // }
240  // }
241 
242  float xScale = newRect.width() / oldRect.width();
243  float yScale = newRect.height() / oldRect.height();
244 
245 
246 
247  float resultScalefactor = std::max(xScale, yScale);
248  resultScalefactor *= scale();
249  resultScalefactor = std::max(resultScalefactor, 0.01f);
250  // ARMARX_INFO << resultScalefactor;
251 
252  setScale(resultScalefactor);
253  }
254  else if (resizingMode != eNone)
255  {
256  QRectF oldRect = boundingRect();
257  prepareGeometryChange();
258  QRectF newBounds = bounds;
259 
260  switch (resizingMode)
261  {
262  // TODO: Fix top and left state rezising
263  // case eTopResizing:
264  // bounds.setTop(pos.y()-2);
265  // break;
266  case eBottomResizing:
267  newBounds.setBottom(pos.y() + 2);
268  break;
269 
270  // case eLeftResizing:
271  // bounds.setLeft(pos.x()-2);
272  // break;
273  case eRightResizing:
274  newBounds.setRight(pos.x() + 2);
275  break;
276 
277  default:
278  break;
279  }
280 
281  newBounds.setWidth(std::max(50.0, newBounds.width()));
282  newBounds.setHeight(std::max(50.0, newBounds.height()));
283 
284  QRectF bbInP = mapRectToParent(newBounds);
285  QRectF obbInP = mapRectToParent(oldRect);
286 
287  if (itemResizing(oldRect, newBounds))
288  {
289  bounds = newBounds;
290  itemBoundingBoxChanged(std::max(obbInP.width(), obbInP.height()),
291  std::max(bbInP.width(), bbInP.height()));
292  itemResized(oldRect, newBounds);
293  }
294  }
295  else
296  {
297  QGraphicsItem::mouseMoveEvent(event);
298  }
299 }
300 
301 void RoundRectItem::adjustCursor(Qt::CursorShape shape)
302 {
303  if (!setCursor || (QApplication::overrideCursor() && QApplication::overrideCursor()->shape() != shape))
304  {
305 
306  if (QApplication::overrideCursor() && QApplication::overrideCursor()->shape() != shape)
307  {
308  QApplication::changeOverrideCursor(QCursor(shape));
309  }
310  else
311  {
312  QApplication::setOverrideCursor(QCursor(shape));
313  }
314 
315  setCursor = true;
316  }
317 }
318 
319 void RoundRectItem::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
320 {
321  QPointF pos = event->pos();
322  QRectF rect = boundingRect();
323  rect.setTopLeft(QPointF(rect.bottomRight().rx() - RESIZE_RECT, rect.bottomRight().ry() - RESIZE_RECT));
324 
325  if (isLevelOfDetailLow(event))
326  {
327  event->ignore();
328  return;
329  }
330 
331  if (rect.contains(pos))
332  {
333  adjustCursor(Qt::SizeFDiagCursor);
334  }
335  else if (getBottomResizeBB().contains(pos))
336  {
337  adjustCursor(Qt::SizeVerCursor);
338  }
339  // else if(getTopResizeBB().contains(pos))
340  // {
341  // adjustCursor(Qt::SizeVerCursor);
342  // }
343  // else if(getLeftResizeBB().contains(pos))
344  // {
345  // adjustCursor(Qt::SizeHorCursor);
346  // }
347  else if (getRightResizeBB().contains(pos))
348  {
349  adjustCursor(Qt::SizeHorCursor);
350  }
351  else if (QApplication::overrideCursor())
352  {
353  QApplication::restoreOverrideCursor();
354  setCursor = false;
355  }
356 
357 }
358 
359 void RoundRectItem::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
360 {
361 
362 }
363 
364 void RoundRectItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
365 {
366 
367  if (setCursor)
368  {
369  QApplication::restoreOverrideCursor();
370  }
371 
372  setCursor = false;
373 }
374 
376 {
377  QRectF result = boundingRect();
378  result.setTop(result.bottom());
379  return result.adjusted(0, -RESIZE_RECT, 0, 0);
380 }
381 
383 {
384  QRectF result = boundingRect();
385  result.setBottom(result.top());
386  return result.adjusted(0, 0, 0, RESIZE_RECT);
387 }
388 
390 {
391  QRectF result = boundingRect();
392  result.setRight(result.left());
393  return result.adjusted(0, 0, RESIZE_RECT, 0);
394 }
395 
397 {
398  QRectF result = boundingRect();
399  result.setLeft(result.right());
400  return result.adjusted(-RESIZE_RECT, 0, 0, 0);
401 }
402 
403 
404 void RoundRectItem::adjustScale(float& resultScalefactor)
405 {
406  if (!parentItem())
407  {
408  return;
409  }
410 
411  QRectF rectP = (parentItem()->boundingRect());
412  QRectF rect = boundingRect();
413  float areaP = rectP.width() * rectP.height();
414  float area = rect.width() * rect.height() * resultScalefactor;
415  ARMARX_INFO << VAROUT(rect) << "," << VAROUT(rectP);
416  ARMARX_INFO << VAROUT(area) << ", " << VAROUT(areaP);
417 
418  if (area / areaP > 0.4)
419  {
420  resultScalefactor = std::max(rect.width(), rect.height()) / std::max(rectP.width(), rectP.height());
421  ARMARX_IMPORTANT << "bigger scale prohibited";
422  }
423 }
424 
425 QPointF RoundRectItem::adjustPosition(QPointF& newPos)
426 {
427  if (!parentItem())
428  {
429  return newPos;
430  }
431 
432  QRectF rect = parentItem()->boundingRect();
433  QPointF oldPos = boundingRect().topLeft(); //TODO: Bounding rect is wrong here
434 
435  newPos.setX(qMin(rect.right() - boundingRect().width()*scale() - rect.width() /** itemParent->scale()*/ * 0.03,
436  qMax(newPos.x(),
437  rect.left() + rect.width() /** itemParent->scale()*/ * 0.03)));
438  newPos.setY(qMin(rect.bottom() - boundingRect().height()*scale() - rect.height()/* * itemParent->scale()*/ * 0.03,
439  qMax(newPos.y(),
440  rect.top() + rect.height() /* * itemParent->scale()*/ * 0.20)));
441 
442  return oldPos;
443 }
444 
445 bool RoundRectItem::isLevelOfDetailLow(QGraphicsSceneEvent* event) const
446 {
447  if (event->widget())
448  {
449  QGraphicsView* view = qobject_cast<QGraphicsView*>(event->widget()->parent());
450 
451  if (parentItem())
452  {
453  auto bbparent = view->mapFromScene(parentItem()->mapToScene(parentItem()->boundingRect())).boundingRect();
454  // auto bb = view->mapFromScene(mapToScene(parentItem()->boundingRect())).boundingRect();
455  // auto qlod = QStyleOptionGraphicsItem::levelOfDetailFromTransform((view->transform() * this->sceneTransform()));
456  // float lod = bb.width() / this->boundingRect().width();
457 
458  // if(view)
459  // ARMARX_INFO << "View " << view->metaObject()->className() << VAROUT(lod) << VAROUT(qlod)<< VAROUT(bbparent.width()) << VAROUT(bb.width());
460  // else
461  // ARMARX_INFO << "NoView";
462  if (bbparent.width() < armarx::MorphingItem::minSizeToShowSubstates)
463  {
464  // ARMARX_INFO << "lod low -> no interaction";
465 
466  return true;
467  }
468  }
469  else
470  {
471  // ARMARX_INFO << "no Parent";
472  }
473  }
474 
475  return false;
476 }
477 
479 {
480  return editable;
481 }
482 
483 void RoundRectItem::setEditable(bool editable)
484 {
485  this->editable = editable;
486 }
487 
488 QVariant RoundRectItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value)
489 {
490  if (change == ItemPositionChange)
491  {
492  // value is the new position.
493  QPointF newPos = value.toPointF();
494  RoundRectItem* itemParent = qgraphicsitem_cast<RoundRectItem*>(parentItem());
495 
496  if (itemParent)
497  {
498  /* QPointF oldPos = */adjustPosition(newPos);
499 
500  // ARMARX_INFO << "bounds " << boundingRect() << " newPos " << newPos;
501  itemMoved(boundingRect().topLeft(), newPos/*+QPointF(boundingRect().width()/2, boundingRect().height()/2)*/);
502  return newPos;
503  }
504  }
505  else if (change == ItemScaleChange)
506  {
507  if (parentItem())
508  {
509 
510  float resultScalefactor = value.toFloat();
511  // adjustScale(resultScalefactor);
512  // ARMARX_INFO << "new scale: " << resultScalefactor << " proposed scale: " << value.toFloat();
513  return resultScalefactor;
514  }
515  }
516 
517  return QGraphicsItem::itemChange(change, value);
518 }
519 
520 
521 
522 
523 void RoundRectItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
524 {
525 
526 }
RoundRectItem::isLevelOfDetailLow
bool isLevelOfDetailLow(QGraphicsSceneEvent *event) const
Definition: RoundRectItem.cpp:445
RoundRectItem::mouseDoubleClickEvent
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override
Definition: RoundRectItem.cpp:523
RoundRectItem::boundingRect
QRectF boundingRect() const override
Definition: RoundRectItem.cpp:78
RoundRectItem::adjustCursor
void adjustCursor(Qt::CursorShape shape)
Definition: RoundRectItem.cpp:301
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
RoundRectItem::setEditable
void setEditable(bool editable)
Definition: RoundRectItem.cpp:483
RESIZE_RECT
#define RESIZE_RECT
Definition: RoundRectItem.cpp:32
RoundRectItem::RoundRectItem
RoundRectItem(const QRectF &bounds, const QColor &color, QGraphicsItem *parent=0)
Definition: RoundRectItem.cpp:36
RoundRectItem::itemChange
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override
Definition: RoundRectItem.cpp:488
ROUNDEDGESIZE
#define ROUNDEDGESIZE
Definition: RoundRectItem.cpp:33
RoundRectItem::hoverMoveEvent
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override
Definition: RoundRectItem.cpp:319
RoundRectItem::setBounds
void setBounds(QRectF newBounds)
Definition: RoundRectItem.cpp:83
RoundRectItem::hoverLeaveEvent
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override
Definition: RoundRectItem.cpp:364
RoundRectItem::getLeftResizeBB
QRectF getLeftResizeBB() const
Definition: RoundRectItem.cpp:389
RoundRectItem::itemResized
virtual void itemResized(const QRectF &oldSize, const QRectF &newSize)
Definition: RoundRectItem.h:90
RoundRectItem::setRimPen
void setRimPen(QPen newPen)
Definition: RoundRectItem.cpp:73
RoundRectItem::adjustScale
void adjustScale(float &resultScalefactor)
Definition: RoundRectItem.cpp:404
RoundRectItem::paint
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=0) override
Definition: RoundRectItem.cpp:110
armarx::armem::contains
bool contains(const MemoryID &general, const MemoryID &specific)
Indicates whether general is "less specific" than, or equal to, specific, i.e.
Definition: MemoryID.cpp:558
RoundRectItem::mousePressEvent
void mousePressEvent(QGraphicsSceneMouseEvent *event) override
Definition: RoundRectItem.cpp:138
RoundRectItem::getRightResizeBB
QRectF getRightResizeBB() const
Definition: RoundRectItem.cpp:396
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
RoundRectItem::getTopResizeBB
QRectF getTopResizeBB() const
Definition: RoundRectItem.cpp:382
ArmarXComponentWidgetController.h
MorphingItem.h
armarx::MorphingItem::minSizeToShowSubstates
static constexpr float minSizeToShowSubstates
Definition: MorphingItem.h:49
RoundRectItem::adjustPosition
virtual QPointF adjustPosition(QPointF &newPos)
Definition: RoundRectItem.cpp:425
RoundRectItem::itemMoved
virtual void itemMoved(const QPointF &oldPos, const QPointF &newPos)
Definition: RoundRectItem.h:91
RoundRectItem::setColor
void setColor(QColor newColor)
Definition: RoundRectItem.cpp:63
max
T max(T t1, T t2)
Definition: gdiam.h:48
RoundRectItem::hoverEnterEvent
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override
Definition: RoundRectItem.cpp:359
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:67
RoundRectItem::itemBoundingBoxChanged
virtual void itemBoundingBoxChanged(float oldSize, float size)
Definition: RoundRectItem.h:92
RoundRectItem::getBottomResizeBB
QRectF getBottomResizeBB() const
Definition: RoundRectItem.cpp:375
RoundRectItem::mouseMoveEvent
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
Definition: RoundRectItem.cpp:217
option
#define option(type, fn)
RoundRectItem
Definition: RoundRectItem.h:34
RoundRectItem::itemResizing
virtual bool itemResizing(const QRectF &oldSize, QRectF &proposedSize)
Definition: RoundRectItem.h:86
ArmarXWidgetController.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
RoundRectItem::bounds
QRectF bounds
Definition: RoundRectItem.h:78
RoundRectItem::mouseReleaseEvent
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override
Definition: RoundRectItem.cpp:203
RoundRectItem.h
RoundRectItem::isEditable
bool isEditable() const
Definition: RoundRectItem.cpp:478
RoundRectItem::setSize
void setSize(const QSizeF &newSize)
Definition: RoundRectItem.cpp:96