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