новые иконки в OpenBoard
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
OpenBoard/src/domain/UBGraphicsDelegateFrame.cpp

593 lines
19 KiB

/*
* UBGraphicsDelegateFrame.cpp
*
* Created on: June 15, 2009
* Author: Patrick
*/
#include "UBGraphicsDelegateFrame.h"
#include <QtGui>
#include <QtSvg>
#include "core/UBApplication.h"
#include "core/UBSettings.h"
#include "domain/UBGraphicsItemDelegate.h"
#include "domain/UBGraphicsScene.h"
#include "domain/UBGraphicsProxyWidget.h"
#include "gui/UBResources.h"
#include "core/memcheck.h"
qreal const UBGraphicsDelegateFrame::mAngleTolerance = 6;
UBGraphicsDelegateFrame::UBGraphicsDelegateFrame(UBGraphicsItemDelegate* pDelegate, QRectF pRect, qreal pFrameWidth, bool respectRatio)
: QGraphicsRectItem(), QObject(pDelegate)
, mCurrentTool(None)
, mDelegate(pDelegate)
, mVisible(true)
, mFrameWidth(pFrameWidth)
, mNominalFrameWidth(pFrameWidth)
, mRespectRatio(respectRatio)
, mAngle(0)
, mAngleOffset(0)
, mTotalScaleX(-1)
, mTotalScaleY(-1)
, mTranslateX(0)
, mTranslateY(0)
, mTotalTranslateX(0)
, mTotalTranslateY(0)
, mOperationMode(Scaling)
{
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
setAcceptedMouseButtons(Qt::LeftButton);
setRect(pRect.adjusted(mFrameWidth, mFrameWidth, mFrameWidth * -1, mFrameWidth * -1));
setBrush(QBrush(UBSettings::paletteColor));
setPen(Qt::NoPen);
setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control));
mBottomRightResizeGripSvgItem = new QGraphicsSvgItem(":/images/resize.svg", this);
mBottomResizeGripSvgItem = new QGraphicsSvgItem(":/images/resizeBottom.svg", this);
mLeftResizeGripSvgItem = new QGraphicsSvgItem(":/images/resizeLeft.svg", this);
mRightResizeGripSvgItem = new QGraphicsSvgItem(":/images/resizeRight.svg", this);
mTopResizeGripSvgItem = new QGraphicsSvgItem(":/images/resizeTop.svg", this);
mBottomRightResizeGrip = new QGraphicsRectItem(this);
mBottomRightResizeGrip->setPen(Qt::NoPen);
mBottomResizeGrip = new QGraphicsRectItem(this);
mBottomResizeGrip->setPen(Qt::NoPen);
mLeftResizeGrip = new QGraphicsRectItem(this);
mLeftResizeGrip->setPen(Qt::NoPen);
mRightResizeGrip = new QGraphicsRectItem(this);
mRightResizeGrip->setPen(Qt::NoPen);
mTopResizeGrip = new QGraphicsRectItem(this);
mTopResizeGrip->setPen(Qt::NoPen);
mRotateButton = new QGraphicsSvgItem(":/images/rotate.svg", this);
mRotateButton->setCursor(UBResources::resources()->rotateCursor);
mRotateButton->setVisible(mDelegate->canRotate());
updateResizeCursors();
setAntiScale(1.0);
positionHandles();
}
UBGraphicsDelegateFrame::~UBGraphicsDelegateFrame()
{
// NOOP
}
void UBGraphicsDelegateFrame::setAntiScale(qreal pAntiScale)
{
mFrameWidth = mNominalFrameWidth * pAntiScale;
QTransform tr;
tr.scale(pAntiScale, pAntiScale);
mBottomRightResizeGripSvgItem->setTransform(tr);
mBottomResizeGripSvgItem->setTransform(tr);
mLeftResizeGripSvgItem->setTransform(tr);
mRightResizeGripSvgItem->setTransform(tr);
mTopResizeGripSvgItem->setTransform(tr);
mRotateButton->setTransform(tr);
}
void UBGraphicsDelegateFrame::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
QPainterPath path;
path.addRoundedRect(rect(), mFrameWidth / 2, mFrameWidth / 2);
if (rect().width() > 1 && rect().height() > 1)
{
QPainterPath extruded;
extruded.addRect(rect().adjusted(mFrameWidth, mFrameWidth, (mFrameWidth * -1), (mFrameWidth * -1)));
path = path.subtracted(extruded);
}
painter->fillPath(path, brush());
}
QPainterPath UBGraphicsDelegateFrame::shape() const
{
QPainterPath path;
//We do not use the rounded rect here because we want the bottom right corner
//to be included in the frame (for resize grip handling : #702)
path.addRect(rect());
if (rect().width() > 0 && rect().height() > 0)
{
QPainterPath extruded;
extruded.addRect(rect().adjusted(mFrameWidth, mFrameWidth, mFrameWidth * -1, mFrameWidth * -1));
path = path.subtracted(extruded);
}
return path;
}
void UBGraphicsDelegateFrame::initializeTransform()
{
QTransform itemTransform = delegated()->sceneTransform();
QRectF itemRect = delegated()->boundingRect();
QPointF topLeft = itemTransform.map(itemRect.topLeft());
QPointF topRight = itemTransform.map(itemRect.topRight());
QPointF bottomLeft = itemTransform.map(itemRect.bottomLeft());
QLineF topLine(topLeft, topRight);
QLineF leftLine(topLeft, bottomLeft);
qreal width = topLine.length();
qreal height = leftLine.length();
mAngle = topLine.angle();
mTotalScaleX = width / itemRect.width();
mTotalScaleY = height / itemRect.height();
QTransform tr;
QPointF center = delegated()->boundingRect().center();
tr.translate(center.x() * mTotalScaleX, center.y() * mTotalScaleY);
tr.rotate(-mAngle);
tr.translate(-center.x() * mTotalScaleX, -center.y() * mTotalScaleY);
tr.scale(mTotalScaleX, mTotalScaleY);
mTotalTranslateX = delegated()->transform().dx() - tr.dx();
mTotalTranslateY = delegated()->transform().dy() - tr.dy();
}
void UBGraphicsDelegateFrame::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
mDelegate->startUndoStep();
mStartingPoint = event->scenePos();
initializeTransform();
mScaleX = 1;
mScaleY = 1;
mTranslateX = 0;
mTranslateY = 0;
mAngleOffset = 0;
mInitialTransform = buildTransform();
mCurrentTool = toolFromPos(event->pos());
event->accept();
}
void UBGraphicsDelegateFrame::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
QLineF move(mStartingPoint, event->scenePos());
qreal moveX = move.length() * cos((move.angle() - mAngle) * PI / 180);
qreal moveY = -move.length() * sin((move.angle() - mAngle) * PI / 180);
qreal width = delegated()->boundingRect().width() * mTotalScaleX;
qreal height = delegated()->boundingRect().height() * mTotalScaleY;
if(mOperationMode == Scaling)
{
if (resizingBottomRight())
{
qreal scaleX = (width + moveX) / width;
qreal scaleY = (height + moveY) / height;
qreal scaleFactor = (scaleX + scaleY) / 2;
// Do not allow resizing of image size under frame size
if (scaleFactor > 1
|| ((width * scaleFactor) > 2 * mFrameWidth
&& (height * scaleFactor) > 2 * mFrameWidth))
{
if (mRespectRatio)
{
mScaleX = scaleFactor;
mScaleY = scaleFactor;
}
else
{
mScaleX = scaleX;
mScaleY = scaleY;
}
}
}
else if (resizingLeft())
{
qreal scaleX = (width - moveX) / width;
if (scaleX > 1 || (width * scaleX) > 2 * mFrameWidth)
{
mScaleX = scaleX;
mTranslateX = moveX;
}
}
else if (resizingRight())
{
qreal scaleX = (width + moveX) / width;
if (scaleX > 1 || (width * scaleX) > 2 * mFrameWidth)
{
mScaleX = scaleX;
}
}
else if (resizingTop())
{
qreal scaleY = (height - moveY) / height;
if (scaleY > 1 || (height * scaleY) > 2 * mFrameWidth)
{
mScaleY = scaleY;
mTranslateY = moveY;
}
}
else if (resizingBottom())
{
qreal scaleY = (height + moveY) / height;
if (scaleY > 1 || (height * scaleY) > 2 * mFrameWidth)
{
mScaleY = scaleY;
}
}
}
else if (mOperationMode == Resizing)
{
UBResizableGraphicsItem* resizableItem = dynamic_cast<UBResizableGraphicsItem*>(delegated());
if (resizableItem)
{
QLineF mousePosDelta(delegated()->mapFromScene(event->lastScenePos())
, delegated()->mapFromScene(event->scenePos()));
QSizeF incVector(0, 0);
if (resizingBottomRight())
{
incVector = QSizeF(mousePosDelta.dx(), mousePosDelta.dy());
}
else if (resizingRight())
{
incVector = QSizeF(mousePosDelta.dx(), 0);
}
else if (resizingBottom())
{
incVector = QSizeF(0, mousePosDelta.dy());
}
else if (resizingLeft())
{
incVector = QSizeF(- mousePosDelta.dx(), 0);
}
else if (resizingTop())
{
incVector = QSizeF(0, - mousePosDelta.dy());
}
QSizeF newSize = resizableItem->size() + incVector;
if (newSize.width() < 0 || newSize.height() < 0)
return;
resizableItem->resize(newSize);
}
}
if (rotating())
{
QLineF startLine(sceneBoundingRect().center(), event->lastScenePos());
QLineF currentLine(sceneBoundingRect().center(), event->scenePos());
mAngle += startLine.angleTo(currentLine);
if ((int)mAngle % 45 >= 45 - mAngleTolerance || (int)mAngle % 45 <= mAngleTolerance)
{
mAngle = qRound(mAngle / 45) * 45;
mAngleOffset += startLine.angleTo(currentLine);
if ((int)mAngleOffset % 360 > mAngleTolerance && (int)mAngleOffset % 360 < 360 - mAngleTolerance)
{
mAngle += mAngleOffset;
mAngleOffset = 0;
}
}
}
else if (moving())
{
mTranslateX = move.dx();
mTranslateY = move.dy();
}
QTransform tr = buildTransform();
//TODO UB 4.x: Could find a better solution ?
if (resizingRight() || resizingBottom() || resizingBottomRight())
{
QPointF topLeft = tr.map(delegated()->boundingRect().topLeft());
QPointF fixedPoint = mInitialTransform.map(delegated()->boundingRect().topLeft());
mTranslateX += fixedPoint.x() - topLeft.x();
mTranslateY += fixedPoint.y() - topLeft.y();
tr = buildTransform();
}
else if (resizingTop() || resizingLeft())
{
if (mOperationMode == Scaling)
{
QPointF bottomRight = tr.map(delegated()->boundingRect().bottomRight());
QPointF fixedPoint = mInitialTransform.map(delegated()->boundingRect().bottomRight());
mTranslateX += fixedPoint.x() - bottomRight.x();
mTranslateY += fixedPoint.y() - bottomRight.y();
}
else
{
QLineF vector;
if (resizingLeft())
{
QPointF topRight1 = mInitialTransform.map(QPointF(delegated()->boundingRect().width() - moveX, 0));
QPointF topRight2 = mInitialTransform.map(QPointF(delegated()->boundingRect().width(), 0));
vector.setPoints(topRight1, topRight2);
}
else
{
QPointF bottomLeft1 = mInitialTransform.map(QPointF(0, delegated()->boundingRect().height() - moveY));
QPointF bottomLeft2 = mInitialTransform.map(QPointF(0, delegated()->boundingRect().height()));
vector.setPoints(bottomLeft1, bottomLeft2);
}
mTranslateX = vector.dx();
mTranslateY = vector.dy();
}
tr = buildTransform();
}
delegated()->setTransform(tr);
event->accept();
}
QTransform UBGraphicsDelegateFrame::buildTransform()
{
QTransform tr;
QPointF center = delegated()->boundingRect().center();
tr.translate(mTotalTranslateX + mTranslateX, mTotalTranslateY + mTranslateY);
tr.translate(center.x() * mTotalScaleX * mScaleX, center.y() * mTotalScaleY * mScaleY);
tr.rotate(-mAngle);
tr.translate(-center.x() * mTotalScaleX * mScaleX, -center.y() * mTotalScaleY * mScaleY);
tr.scale(mTotalScaleX * mScaleX, mTotalScaleY * mScaleY);
return tr;
}
void UBGraphicsDelegateFrame::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
updateResizeCursors();
mDelegate->commitUndoStep();
mTotalScaleX *= mScaleX;
mTotalScaleY *= mScaleY;
mTotalTranslateX += mTranslateX;
mTotalTranslateY += mTranslateY;
event->accept();
mCurrentTool = None;
QGraphicsRectItem::mouseReleaseEvent(event);
}
void UBGraphicsDelegateFrame::updateResizeCursors()
{
QPixmap pix(":/images/cursors/resize.png");
QTransform tr;
tr.rotate(-mAngle);
QCursor resizeCursor = QCursor(pix.transformed(tr, Qt::SmoothTransformation), pix.width() / 2, pix.height() / 2);
mLeftResizeGrip->setCursor(resizeCursor);
mRightResizeGrip->setCursor(resizeCursor);
tr.rotate(-90);
resizeCursor = QCursor(pix.transformed(tr, Qt::SmoothTransformation), pix.width() / 2, pix.height() / 2);
mBottomResizeGrip->setCursor(resizeCursor);
mTopResizeGrip->setCursor(resizeCursor);
tr.rotate(-45);
resizeCursor = QCursor(pix.transformed(tr, Qt::SmoothTransformation), pix.width() / 2, pix.height() / 2);
mBottomRightResizeGrip->setCursor(resizeCursor);
}
void UBGraphicsDelegateFrame::setVisible(bool visible)
{
mVisible = visible;
if (mVisible)
setBrush(QBrush(UBSettings::paletteColor));
else
setBrush(Qt::NoBrush);
}
void UBGraphicsDelegateFrame::positionHandles()
{
QRectF itemRect = delegated()->boundingRect();
QTransform itemTransform = delegated()->sceneTransform();
QPointF topLeft = itemTransform.map(itemRect.topLeft());
QPointF topRight = itemTransform.map(itemRect.topRight());
QPointF bottomLeft = itemTransform.map(itemRect.bottomLeft());
QPointF center = itemTransform.map(itemRect.center());
QLineF topLine(topLeft, topRight);
qreal angle = topLine.angle();
qreal width = topLine.length();
QLineF leftLine(topLeft, bottomLeft);
qreal height = leftLine.length();
if (mVisible)
{
setRect(center.x() - mFrameWidth - width / 2, center.y() - mFrameWidth - height / 2,
width + 2 * mFrameWidth, height + 2 * mFrameWidth);
}
else
{
setRect(center.x() - width / 2, center.y() - height / 2, width, height);
}
resetTransform();
translate(center.x(), center.y());
rotate(-angle);
translate(-center.x(), -center.y());
mBottomRightResizeGripSvgItem->setParentItem(this);
mBottomResizeGripSvgItem->setParentItem(this);
mLeftResizeGripSvgItem->setParentItem(this);
mRightResizeGripSvgItem->setParentItem(this);
mTopResizeGripSvgItem->setParentItem(this);
mRotateButton->setParentItem(this);
mBottomRightResizeGrip->setParentItem(this);
mBottomResizeGrip->setParentItem(this);
mLeftResizeGrip->setParentItem(this);
mRightResizeGrip->setParentItem(this);
mTopResizeGrip->setParentItem(this);
QRectF brRect = mBottomRightResizeGripSvgItem->mapRectToParent(mBottomRightResizeGripSvgItem->boundingRect());
mBottomRightResizeGripSvgItem->setPos(rect().right() - brRect.width()
, rect().bottom() - brRect.height());
QRectF bRect = mBottomResizeGripSvgItem->mapRectToParent(mBottomResizeGripSvgItem->boundingRect());
mBottomResizeGripSvgItem->setPos(rect().center().x() - bRect.width() / 2
, rect().bottom() - bRect.height());
QRectF lRect = mLeftResizeGripSvgItem->mapRectToParent(mLeftResizeGripSvgItem->boundingRect());
mLeftResizeGripSvgItem->setPos(rect().left()
, rect().center().y() - lRect.height() / 2);
QRectF rRect = mRightResizeGripSvgItem->mapRectToParent(mRightResizeGripSvgItem->boundingRect());
mRightResizeGripSvgItem->setPos(rect().right() - rRect.width()
, rect().center().y() - rRect.height() / 2);
QRectF trRect = mTopResizeGripSvgItem->mapRectToParent(mTopResizeGripSvgItem->boundingRect());
mTopResizeGripSvgItem->setPos(rect().center().x() - trRect.width() / 2
, rect().y());
mRotateButton->setPos(rect().right() - mFrameWidth - 5, rect().top() + 5);
mBottomRightResizeGrip->setRect(bottomRightResizeGripRect());
mBottomResizeGrip->setRect(bottomResizeGripRect());
mLeftResizeGrip->setRect(leftResizeGripRect());
mRightResizeGrip->setRect(rightResizeGripRect());
mTopResizeGrip->setRect(topResizeGripRect());
QVariant vLocked = delegated()->data(UBGraphicsItemData::ItemLocked);
bool isLocked = (vLocked.isValid() && vLocked.toBool());
mBottomRightResizeGripSvgItem->setVisible(!isLocked);
mBottomResizeGripSvgItem->setVisible(!isLocked);
mLeftResizeGripSvgItem->setVisible(!isLocked);
mRightResizeGripSvgItem->setVisible(!isLocked);
mTopResizeGripSvgItem->setVisible(!isLocked);
mRotateButton->setVisible(mDelegate->canRotate() && !isLocked);
mBottomRightResizeGrip->setVisible(!isLocked);
mBottomResizeGrip->setVisible(!isLocked);
mLeftResizeGrip->setVisible(!isLocked);
mRightResizeGrip->setVisible(!isLocked);
mTopResizeGrip->setVisible(!isLocked);
if (isLocked)
{
QColor baseColor = UBSettings::paletteColor;
baseColor.setAlphaF(baseColor.alphaF() / 3);
setBrush(QBrush(baseColor));
}
else
{
setBrush(QBrush(UBSettings::paletteColor));
}
}
QGraphicsItem* UBGraphicsDelegateFrame::delegated()
{
return mDelegate->delegated();
}
UBGraphicsDelegateFrame::FrameTool UBGraphicsDelegateFrame::toolFromPos(QPointF pos)
{
if(mDelegate->isLocked())
return None;
else if (bottomRightResizeGripRect().contains(pos))
return ResizeBottomRight;
else if (bottomResizeGripRect().contains(pos))
return ResizeBottom;
else if (leftResizeGripRect().contains(pos))
return ResizeLeft;
else if (rightResizeGripRect().contains(pos))
return ResizeRight;
else if (topResizeGripRect().contains(pos))
return ResizeTop;
else if (rotateButtonBounds().contains(pos) && mDelegate && mDelegate->canRotate())
return Rotate;
else
return Move;
}
QRectF UBGraphicsDelegateFrame::bottomRightResizeGripRect() const
{
return QRectF(rect().right() - mFrameWidth, rect().bottom() - mFrameWidth, mFrameWidth, mFrameWidth);
}
QRectF UBGraphicsDelegateFrame::bottomResizeGripRect() const
{
return QRectF(rect().center().x() - mFrameWidth / 2, rect().bottom() - mFrameWidth, mFrameWidth, mFrameWidth);
}
QRectF UBGraphicsDelegateFrame::leftResizeGripRect() const
{
return QRectF(rect().left(), rect().center().y() - mFrameWidth / 2, mFrameWidth, mFrameWidth);
}
QRectF UBGraphicsDelegateFrame::rightResizeGripRect() const
{
return QRectF(rect().right() - mFrameWidth, rect().center().y() - mFrameWidth / 2, mFrameWidth, mFrameWidth);
}
QRectF UBGraphicsDelegateFrame::topResizeGripRect() const
{
return QRectF(rect().center().x() - mFrameWidth / 2, rect().top(), mFrameWidth, mFrameWidth);
}
QRectF UBGraphicsDelegateFrame::rotateButtonBounds() const
{
return QRectF(rect().right()- mFrameWidth, rect().top(), mFrameWidth, mFrameWidth);
}