17const qreal VuoRendererComment::cornerRadius = 10 ;
18const qreal VuoRendererComment::borderWidth = 5.5 ;
19const qreal VuoRendererComment::textMargin = 5 ;
28 setZValue(commentZValue);
29 this->resizeDragInProgress =
false;
30 this->resizeDeltaIgnored = QPointF(0,0);
31 this->dragHandleHovered =
false;
32 this->titleHandleHovered =
false;
33 this->bodySelectable =
true;
35 this->textItem =
new QGraphicsTextItem(
this);
38 textItem->setDefaultTextColor(colors->
commentText());
40 textItem->setPos(QPoint(textMargin, textMargin));
41 textItem->setTextInteractionFlags(Qt::TextBrowserInteraction);
42 textItem->setFlag(QGraphicsItem::ItemIsSelectable,
false);
43 textItem->setFlag(QGraphicsItem::ItemIsFocusable,
false);
44 textItem->setOpenExternalLinks(
true);
45 updateFormattedCommentText();
48 this->signaler = NULL;
50 this->setFlags(QGraphicsItem::ItemIsMovable |
51 QGraphicsItem::ItemIsSelectable |
52 QGraphicsItem::ItemIsFocusable |
53 QGraphicsItem::ItemSendsGeometryChanges);
55 this->setAcceptHoverEvents(
true);
57 setPos(baseComment->
getX(), baseComment->
getY());
66QPainterPath VuoRendererComment::getCommentFrame(QRectF commentFrameRect)
const
70 frame.moveTo(commentFrameRect.right(), commentFrameRect.center().y());
71 addRoundedCorner(frame,
true, commentFrameRect.bottomRight(), cornerRadius,
false,
false);
72 addRoundedCorner(frame,
true, commentFrameRect.bottomLeft(), cornerRadius,
false,
true);
73 addRoundedCorner(frame,
true, commentFrameRect.topLeft(), cornerRadius,
true,
true);
74 addRoundedCorner(frame,
true, commentFrameRect.topRight(), cornerRadius,
true,
false);
82QRectF VuoRendererComment::extendedTitleHandleBoundingRect(
void)
const
84 QRectF r = getTitleHandlePath(frameRect).boundingRect();
88 r.adjust(0,0,0,textMargin-r.bottom());
90 return r.toAlignedRect();
96QRectF VuoRendererComment::extendedDragHandleBoundingRect(
void)
const
98 QRectF r = getDragHandlePath(frameRect).boundingRect();
99 r.adjust(-borderWidth/2.0, -borderWidth/2.0, borderWidth/2.0, borderWidth/2.0);
100 r.adjust(-10, -10, 10, 10);
102 return r.toAlignedRect();
110 QRectF r = this->frameRect;
115 return r.toAlignedRect();
124 if (bodySelectable || isSelected())
133 p.addPath(getTitleHandlePath(frameRect));
135 QPainterPathStroker s;
136 s.setWidth(textMargin);
138 return s.createStroke(p);
147 painter->setRenderHint(QPainter::Antialiasing,
true);
154 drawCommentFrame(painter, colors);
155 drawTextContent(painter);
156 drawTitleHandle(painter, colors);
157 drawDragHandle(painter, colors);
165void VuoRendererComment::drawCommentFrame(QPainter *painter,
VuoRendererColors *colors)
const
168 painter->fillPath(commentFrame, colors->
commentFill());
174void VuoRendererComment::drawTextContent(QPainter *painter)
const
177 QRectF textContentBoundingRect = QRectF(textMargin,
179 frameRect.width() - 2*textMargin,
180 frameRect.height() - 2*textMargin);
187void VuoRendererComment::drawTitleHandle(QPainter *painter,
VuoRendererColors *colors)
const
189 bool paintTitleHandle = (titleHandleHovered || isSelected());
190 painter->setPen(QPen(paintTitleHandle? colors->
commentFrame() : colors->commentFill(), borderWidth, Qt::SolidLine, Qt::RoundCap));
191 painter->drawPath(getTitleHandlePath(frameRect));
198QPainterPath VuoRendererComment::getTitleHandlePath(QRectF commentFrameRect)
const
201 p.moveTo(commentFrameRect.topLeft()+QPointF(0.5*borderWidth+cornerRadius, 0.5*borderWidth));
202 p.lineTo(commentFrameRect.topRight()+QPointF(-0.5*borderWidth-cornerRadius, 0.5*borderWidth));
210void VuoRendererComment::drawDragHandle(QPainter *painter,
VuoRendererColors *colors)
const
212 painter->setPen(QPen(dragHandleHovered? colors->
commentFrame() : colors->commentFill(), borderWidth, Qt::SolidLine, Qt::RoundCap));
213 painter->drawPath(getDragHandlePath(frameRect));
220QPainterPath VuoRendererComment::getDragHandlePath(QRectF commentFrameRect)
const
223 addRoundedCorner(p,
false, commentFrameRect.bottomRight()-QPointF(0.5*borderWidth, 0.5*borderWidth), cornerRadius,
false,
false);
233 QVariant newValue = value;
235 if (change == QGraphicsItem::ItemSceneHasChanged)
239 textItem->installSceneEventFilter(
this);
242 if (change == QGraphicsItem::ItemPositionChange)
252 newValue = value.toPoint();
257 if (change == QGraphicsItem::ItemPositionHasChanged)
259 QPointF newPos = value.toPointF();
260 if ((
getBase()->getX() != newPos.x()) || (
getBase()->getY() != newPos.y()))
270 set<VuoRendererComment *> movedComments;
271 movedComments.insert(
this);
279 if (change == QGraphicsItem::ItemSelectedHasChanged)
285 return QGraphicsItem::itemChange(change, newValue);
293 if (watched == this->textItem)
297 if (event->type() == QEvent::GraphicsSceneMouseDoubleClick)
299 QGraphicsSceneMouseEvent *mouseEvent =
static_cast<QGraphicsSceneMouseEvent *
>(event);
302 mouseEvent->setPos(mapFromItem(this->textItem, mouseEvent->pos()));
310 if (event->type() == QEvent::GraphicsSceneMouseMove)
312 QGraphicsSceneMouseEvent *mouseEvent =
static_cast<QGraphicsSceneMouseEvent *
>(event);
315 mouseEvent->setPos(mapFromItem(this->textItem, mouseEvent->pos()));
320 if (event->type() == QEvent::GraphicsSceneMousePress)
322 QGraphicsSceneMouseEvent *mouseEvent =
static_cast<QGraphicsSceneMouseEvent *
>(event);
325 mouseEvent->setPos(mapFromItem(this->textItem, mouseEvent->pos()));
328 Qt::KeyboardModifiers modifiersOtherThanShift = (mouseEvent->modifiers() & ~Qt::ShiftModifier);
329 mouseEvent->setModifiers(modifiersOtherThanShift);
334 mouseEvent->setPos(mapToItem(this->textItem, mouseEvent->pos()));
338 if (event->type() == QEvent::GraphicsSceneMouseRelease)
340 QGraphicsSceneMouseEvent *mouseEvent =
static_cast<QGraphicsSceneMouseEvent *
>(event);
343 mouseEvent->setPos(mapFromItem(this->textItem, mouseEvent->pos()));
348 mouseEvent->setPos(mapToItem(this->textItem, mouseEvent->pos()));
356 if (event->type() == QEvent::GraphicsSceneHoverMove)
358 QGraphicsSceneHoverEvent *hoverEvent =
static_cast<QGraphicsSceneHoverEvent *
>(event);
361 hoverEvent->setPos(mapFromItem(this->textItem, hoverEvent->pos()));
385 QGraphicsItem::CacheMode normalCacheMode = cacheMode();
386 setCacheMode(QGraphicsItem::NoCache);
387 prepareGeometryChange();
388 dragHandleHovered = dragHandleHoveredForEventPos(event->pos());
389 titleHandleHovered = titleHandleHoveredForEventPos(event->pos());
390 setCacheMode(normalCacheMode);
398 QGraphicsItem::CacheMode normalCacheMode = cacheMode();
399 setCacheMode(QGraphicsItem::NoCache);
400 prepareGeometryChange();
401 dragHandleHovered =
false;
402 titleHandleHovered =
false;
403 setCacheMode(normalCacheMode);
411 if (event->modifiers() & Qt::ShiftModifier)
422 if ((event->button() == Qt::LeftButton) && dragHandleHoveredForEventPos(event->pos()))
424 resizeDragInProgress =
true;
425 resizeDeltaIgnored = QPointF(0,0);
427 else if ((event->button() == Qt::LeftButton) && titleHandleActiveForEventPos(event->pos()))
428 QGraphicsItem::mousePressEvent(event);
438 if ((event->buttons() & Qt::LeftButton) && resizeDragInProgress)
441 const QPointF eventDelta =
event->scenePos().toPoint() -
event->lastScenePos().toPoint();
443 QPointF requestedDelta = eventDelta;
446 if ((requestedDelta.x() > 0) && (resizeDeltaIgnored.x() < 0))
448 requestedDelta.setX(requestedDelta.x() + resizeDeltaIgnored.x());
449 resizeDeltaIgnored.setX(0);
452 if ((requestedDelta.y() > 0) && (resizeDeltaIgnored.y() < 0))
454 requestedDelta.setY(requestedDelta.y() + resizeDeltaIgnored.y());
455 resizeDeltaIgnored.setY(0);
458 qreal widthUnderflow = minSize - (
getBase()->
getWidth()+requestedDelta.x());
459 qreal heightUnderflow = minSize - (
getBase()->
getHeight()+requestedDelta.y());
462 QPointF adjustedDelta((widthUnderflow <= 0? requestedDelta.x() : requestedDelta.x()+widthUnderflow),
463 (heightUnderflow <= 0? requestedDelta.y() : requestedDelta.y()+heightUnderflow));
470 resizeDeltaIgnored += requestedDelta - adjustedDelta;
473 int yTextOverflow = textItem->boundingRect().height()+2*textMargin - frameRect.height();
474 if ((yTextOverflow > 0) && ((adjustedDelta.y() < 0) || adjustedDelta.x() < 0))
481 resizeDeltaIgnored += adjustedDelta;
488 else if ((event->buttons() & Qt::LeftButton) && titleHandleActiveForEventPos(event->buttonDownPos(Qt::LeftButton)))
489 QGraphicsItem::mouseMoveEvent(event);
500 if (event->button() == Qt::LeftButton)
501 resizeDragInProgress =
false;
503 if ((event->button() == Qt::LeftButton) && titleHandleActiveForEventPos(event->buttonDownPos(Qt::LeftButton)))
504 QGraphicsItem::mouseReleaseEvent(event);
514 this->prepareGeometryChange();
522 QGraphicsItem::CacheMode normalCacheMode = cacheMode();
523 setCacheMode(QGraphicsItem::NoCache);
527 updateFormattedCommentText();
532 QPointF minSize(max(
getBase()->getWidth()*1.,
533 this->textItem->boundingRect().toAlignedRect().width()+2*textMargin),
535 this->textItem->boundingRect().toAlignedRect().height()+2*textMargin));
541 setCacheMode(normalCacheMode);
551 QGraphicsItem::CacheMode normalCacheMode = cacheMode();
552 setCacheMode(QGraphicsItem::NoCache);
555 this->bodySelectable = bodySelectable;
557 setCacheMode(normalCacheMode);
564void VuoRendererComment::updateFormattedCommentText()
566 string textWithoutQuotes =
"";
569 json_object *js = json_tokener_parse(
getBase()->getContent().c_str());
570 if (json_object_get_type(js) == json_type_string)
571 textWithoutQuotes = json_object_get_string(js);
574 QString textContent = QString::fromUtf8(textWithoutQuotes.c_str());
578 textContent = textContent.normalized(QString::NormalizationForm_C);
579 this->textItem->setHtml(generateTextStyleString()
586void VuoRendererComment::updateFrameRect(
void)
588 QRectF updatedFrameRect;
589 int unalignedFrameWidth = floor(
getBase()->getWidth());
590 int unalignedFrameHeight = floor(
getBase()->getHeight());
595 unalignedFrameWidth);
597 if (alignedFrameWidth < unalignedFrameWidth)
600 int alignedFrameHeight = unalignedFrameHeight;
608 + nodeHeightOverflow;
610 if (alignedFrameHeight < unalignedFrameHeight)
614 updatedFrameRect.setWidth(alignedFrameWidth);
615 updatedFrameRect.setHeight(alignedFrameHeight);
622 const int xAlignmentCorrection = -1;
623 updatedFrameRect.adjust(xAlignmentCorrection, 0, xAlignmentCorrection, 0);
625 if (this->frameRect != updatedFrameRect)
627 this->frameRect = updatedFrameRect;
628 this->commentFrame = getCommentFrame(this->frameRect);
629 this->textItem->setTextWidth(frameRect.width() - 2*textMargin);
638 QGraphicsItem::CacheMode normalCacheMode = cacheMode();
639 setCacheMode(QGraphicsItem::NoCache);
640 prepareGeometryChange();
644 this->textItem->setDefaultTextColor(colors->
commentText());
645 updateFormattedCommentText();
647 setCacheMode(normalCacheMode);
654bool VuoRendererComment::titleHandleActiveForEventPos(QPointF pos)
656 return (titleHandleHoveredForEventPos(pos) || (textItem->boundingRect().contains(pos)) || isSelected());
662bool VuoRendererComment::titleHandleHoveredForEventPos(QPointF pos)
664 return (extendedTitleHandleBoundingRect().contains(pos) && !dragHandleHoveredForEventPos(pos));
670bool VuoRendererComment::dragHandleHoveredForEventPos(QPointF pos)
672 return extendedDragHandleBoundingRect().contains(pos);
678QString VuoRendererComment::generateTextStyleString()
681 return VUO_QSTRINGIFY(
689 h1,h2,h3,h4,h5,h6,b,strong,th {
693 font-family:
'Monaco';
695 background-color: %3;
696 white-space: pre-wrap;
700 .arg(f->getCSS(f->commentFont()))