From 83212cc4944b1ebf6aca7c4b0801c3a0981a0475 Mon Sep 17 00:00:00 2001 From: Anatoly Mihalchenko Date: Thu, 3 May 2012 12:26:48 +0300 Subject: [PATCH] SANKORE-613 Frame buttons Part 1: changes in toolbars --- src/domain/UBGraphicsDelegateFrame.cpp | 1596 ++++++++++---------- src/domain/UBGraphicsItemDelegate.cpp | 80 +- src/domain/UBGraphicsItemDelegate.h | 34 + src/domain/UBGraphicsTextItemDelegate.cpp | 14 +- src/domain/UBGraphicsVideoItemDelegate.cpp | 687 ++++----- src/domain/UBGraphicsVideoItemDelegate.h | 230 +-- 6 files changed, 1389 insertions(+), 1252 deletions(-) diff --git a/src/domain/UBGraphicsDelegateFrame.cpp b/src/domain/UBGraphicsDelegateFrame.cpp index bb47e5c6..54dc4650 100644 --- a/src/domain/UBGraphicsDelegateFrame.cpp +++ b/src/domain/UBGraphicsDelegateFrame.cpp @@ -1,794 +1,802 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "UBGraphicsDelegateFrame.h" - -#include -#include - -#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" - -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) - , mMirrorX(false) - , mMirrorY(false) -{ - mAngleTolerance = UBSettings::settings()->angleTolerance->get().toReal(); - - 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->setToolTip("left"); - mLeftResizeGrip->setPen(Qt::NoPen); - mRightResizeGrip = new QGraphicsRectItem(this); - mRightResizeGrip->setPen(Qt::NoPen); - mRightResizeGrip->setToolTip("Right"); - 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(); - - this->setAcceptHoverEvents(true); - - angleWidget = new UBAngleWidget(); -} - - -UBGraphicsDelegateFrame::~UBGraphicsDelegateFrame() -{ -delete angleWidget; - // 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()); - - qreal horizontalFlip = (topLeft.x() > topRight.x()) ? -1 : 1; - mMirrorX = horizontalFlip < 0 ; - if(horizontalFlip < 0){ - // why this is because of the way of calculating the translations that checks which side is the most is the - // nearest instead of checking which one is the left side. - QPointF tmp = topLeft; - topLeft = topRight; - topRight = tmp; - - // because of the calculation of the height is done by lenght and not deltaY - bottomLeft = itemTransform.map(itemRect.bottomRight()); - } - - qreal verticalFlip = (bottomLeft.y() < topLeft.y()) ? -1 : 1; - // not sure that is usefull - mMirrorY = verticalFlip < 0; - if(verticalFlip < 0 && !mMirrorX){ - topLeft = itemTransform.map(itemRect.bottomLeft()); - topRight = itemTransform.map(itemRect.bottomRight()); - bottomLeft = itemTransform.map(itemRect.topLeft()); - } - - QLineF topLine(topLeft, topRight); - QLineF leftLine(topLeft, bottomLeft); - qreal width = topLine.length(); - qreal height = leftLine.length(); - - mAngle = topLine.angle(); - - // the fact the the length is used we loose the horizontalFlip information - // a better way to do this is using DeltaX that preserve the direction information. - mTotalScaleX = (width / itemRect.width()) * horizontalFlip; - mTotalScaleY = height / itemRect.height() * verticalFlip; - - 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(); -} - -bool UBGraphicsDelegateFrame::canResizeBottomRight(qreal width, qreal height, qreal scaleFactor) -{ - bool res = false; - - if(!mMirrorX && !mMirrorX && ((width * scaleFactor) > 2*mFrameWidth && (height * scaleFactor) > 2*mFrameWidth)){ - res = true; - }else if(mMirrorX && !mMirrorY && (-width * scaleFactor) > 2*mFrameWidth && (height*scaleFactor) > 2*mFrameWidth){ - res = true; - }else if(!mMirrorX && mMirrorY && (width * scaleFactor) > 2*mFrameWidth && (-height*scaleFactor) > 2*mFrameWidth){ - res = true; - }else if(mMirrorX && mMirrorY && (-width * scaleFactor) > 2*mFrameWidth && (-height*scaleFactor) > 2*mFrameWidth){ - res = true; - } - - return res; -} - -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) - { - mTranslateX = moveX; - // Perform the resize - if (resizingBottomRight()) - { - // ----------------------------------------------------- - // ! We want to keep the aspect ratio with this resize ! - // ----------------------------------------------------- - qreal scaleX; - qreal scaleY; - - if(!mMirrorX){ - scaleX = (width + moveX) / width; - }else{ - scaleX = (width - moveX) / width; - } - - if(!mMirrorY){ - scaleY = (height + moveY) / height; - }else{ - scaleY = (height - moveY) / height; - } - - qreal scaleFactor = (scaleX + scaleY) / 2; - - // Do not allow resizing of image size under frame size - if (canResizeBottomRight(width, height, scaleFactor)) - { - if (mRespectRatio) - { - mScaleX = scaleFactor; - mScaleY = scaleFactor; - } - else - { - mScaleX = scaleX; - mScaleY = scaleY; - } - } - }else if (resizingLeft() || resizingRight()) - { - if(width != 0){ - qreal scaleX = 0.0; - if(resizingLeft()){ - scaleX = (width - moveX) / width; - }else if(resizingRight()){ - scaleX = (width + moveX) / width; - } - if(mDelegate->isFlippable() && qAbs(scaleX) != 0){ - if((qAbs(width * scaleX)) < 2*mFrameWidth){ - bool negative = (scaleX < 0)?true:false; - if(negative){ - if(mMirrorX) - scaleX = 2*mFrameWidth/width; - else - scaleX = -2*mFrameWidth/width; - }else{ - scaleX = -1; - } - } - mScaleX = scaleX; - }else if (scaleX > 1 || (width * scaleX) > 2 * mFrameWidth){ - mScaleX = scaleX; - if(resizingLeft()){ - mTranslateX = moveX; - } - } - } - }else if(resizingTop() || resizingBottom()){ - if(height != 0){ - qreal scaleY = 0.0; - if(resizingTop()){ - scaleY = (height - moveY) / height; - }else if(resizingBottom()){ - scaleY = (height + moveY) / height; - } - - if(mDelegate->isFlippable() && qAbs(scaleY) != 0){ - if((qAbs(height * scaleY)) < 2*mFrameWidth){ - bool negative = (scaleY < 0)?true:false; - if(negative){ - if(mMirrorY) - scaleY = 2*mFrameWidth/width; - else - scaleY = -2*mFrameWidth/width; - }else{ - scaleY = -1; - } - } - mScaleY = scaleY; - }else if (scaleY > 1 || (height * scaleY) > 2 * mFrameWidth) - { - mScaleY = scaleY; - if(resizingTop()){ - mTranslateY = moveY; - } - } - } - } - } - else if (mOperationMode == Resizing) - { - mTranslateX = moveX; - UBResizableGraphicsItem* resizableItem = dynamic_cast(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; - - resizableItem->resize(newSize); - } - } - - if (rotating()) - { - mTranslateX = 0; - mTranslateY = 0; - - 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 ((int)mAngle % 30 >= 30 - mAngleTolerance || (int)mAngle % 30 <= mAngleTolerance) - { - mAngle = qRound(mAngle / 30) * 30; - mAngleOffset += startLine.angleTo(currentLine); - if ((int)mAngleOffset % 360 > mAngleTolerance && (int)mAngleOffset % 360 < 360 - mAngleTolerance) - { - mAngle += mAngleOffset; - mAngleOffset = 0; - } - } - - if (!angleWidget->isVisible()) - angleWidget->show(); - - angleWidget->setText(QString::number((int)mAngle % 360)); - angleWidget->update(); - - } - 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 ref; - if(!mMirrorX && !mMirrorY){ - ref = delegated()->boundingRect().topLeft(); - }else if(mMirrorX && !mMirrorY){ - ref = delegated()->boundingRect().topLeft(); - }else if(!mMirrorX && mMirrorY){ - ref = delegated()->boundingRect().topLeft(); - }else if(mMirrorX && mMirrorY){ - ref = delegated()->boundingRect().topRight(); - } - - // Map the item topleft point to the current mouse move transform - QPointF topLeft = tr.map(ref); - - // Map the item topleft point to the mouse press transform - QPointF fixedPoint = mInitialTransform.map(ref); - - // Update the translation coordinates - mTranslateX += fixedPoint.x() - topLeft.x(); - mTranslateY += fixedPoint.y() - topLeft.y(); - - // Update the transform - 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(); - - // Translate - tr.translate(mTotalTranslateX + mTranslateX, mTotalTranslateY + mTranslateY); - - // Set angle - tr.translate(center.x() * mTotalScaleX * mScaleX, center.y() * mTotalScaleY * mScaleY); - tr.rotate(-mAngle); - tr.translate(-center.x() * mTotalScaleX * mScaleX, -center.y() * mTotalScaleY * mScaleY); - - // Scale - tr.scale(mTotalScaleX * mScaleX, mTotalScaleY * mScaleY); - return tr; -} - - -void UBGraphicsDelegateFrame::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - if (angleWidget->isVisible()) - angleWidget->hide(); - - updateResizeCursors(); - - mDelegate->commitUndoStep(); - mTotalScaleX *= mScaleX; - mTotalScaleY *= mScaleY; - mTotalTranslateX += mTranslateX; - mTotalTranslateY += mTranslateY; - event->accept(); - - mCurrentTool = None; - QGraphicsRectItem::mouseReleaseEvent(event); - - // Show the buttons - if(isResizing()){ - mResizing = false; - } - mDelegate->setButtonsVisible(true); -} - - -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 bottomRight = itemTransform.map(itemRect.bottomRight()); - QPointF center = itemTransform.map(itemRect.center()); - int rotateHeight = QLineF(topLeft, bottomLeft).length(); - - // Handle the mirroring - if(topLeft.x() > topRight.x()){ - QPointF topTmp = topRight; - QPointF bottomTmp = bottomRight; - topRight = topLeft; - topLeft = topTmp; - bottomRight = bottomLeft; - bottomLeft = bottomTmp; - } - - if(bottomLeft.y() > topLeft.y()){ - QPointF leftTmp = bottomLeft; - QPointF rightTmp = bottomRight; - bottomLeft = topLeft; - topLeft = leftTmp; - bottomRight = topRight; - topRight = rightTmp; - } - - QLineF topLine(topLeft, topRight); - qreal angle = topLine.angle(); - qreal width = topLine.length(); - - QLineF leftLine(topLeft, bottomLeft); - qreal height = leftLine.length(); - - int h = rotating()?rotateHeight:height; - - if (mVisible) - { - setRect(center.x() - mFrameWidth - width / 2, center.y() - mFrameWidth - h / 2, width + 2 * mFrameWidth, h + 2 * mFrameWidth); - } - else - { - setRect(center.x() - width / 2, center.y() - h / 2, width, h); - } - - 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()); - QRectF bRect = mBottomResizeGripSvgItem->mapRectToParent(mBottomResizeGripSvgItem->boundingRect()); - QRectF lRect = mLeftResizeGripSvgItem->mapRectToParent(mLeftResizeGripSvgItem->boundingRect()); - QRectF rRect = mRightResizeGripSvgItem->mapRectToParent(mRightResizeGripSvgItem->boundingRect()); - QRectF trRect = mTopResizeGripSvgItem->mapRectToParent(mTopResizeGripSvgItem->boundingRect()); - - mBottomRightResizeGripSvgItem->setPos(rect().right() - brRect.width(), rect().bottom() - brRect.height()); - mBottomResizeGripSvgItem->setPos(rect().center().x() - bRect.width() / 2, rect().bottom() - bRect.height()); - - mLeftResizeGripSvgItem->setPos(rect().left(), rect().center().y() - lRect.height() / 2); - mRightResizeGripSvgItem->setPos(rect().right() - rRect.width(), rect().center().y() - rRect.height() / 2); - - 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)); - } - - //make frame interact like delegated item when selected. Maybe should be deleted if selection logic will change - setZValue(delegated()->zValue()); -} - - -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)){ - if(mMirrorY){ - return ResizeTop; - }else{ - return ResizeBottom; - } - } - else if (leftResizeGripRect().contains(pos)){ - if(mMirrorX){ - return ResizeRight; - }else{ - return ResizeLeft; - } - return ResizeLeft; - } - else if (rightResizeGripRect().contains(pos)){ - if(mMirrorX){ - return ResizeLeft; - }else{ - return ResizeRight; - } - } - else if (topResizeGripRect().contains(pos)){ - if(mMirrorY){ - return ResizeBottom; - }else{ - 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); -} - -void UBGraphicsDelegateFrame::refreshGeometry() -{ - // Here we want to have the left on the left, the right on the right, the top on the top and the bottom on the bottom! - 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()); - - QLineF topLine(topLeft, topRight); - qreal width = topLine.length(); - QLineF leftLine(topLeft, bottomLeft); - qreal height = leftLine.length(); - setRect(topRight.x() - mFrameWidth, topLeft.y() - mFrameWidth, width + 2*mFrameWidth, height + 2*mFrameWidth); -} +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "UBGraphicsDelegateFrame.h" + +#include +#include + +#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" + +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) + , mMirrorX(false) + , mMirrorY(false) +{ + mAngleTolerance = UBSettings::settings()->angleTolerance->get().toReal(); + + 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->setToolTip("left"); + mLeftResizeGrip->setPen(Qt::NoPen); + mRightResizeGrip = new QGraphicsRectItem(this); + mRightResizeGrip->setPen(Qt::NoPen); + mRightResizeGrip->setToolTip("Right"); + 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(); + + this->setAcceptHoverEvents(true); + + angleWidget = new UBAngleWidget(); +} + + +UBGraphicsDelegateFrame::~UBGraphicsDelegateFrame() +{ +delete angleWidget; + // 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()); + + qreal horizontalFlip = (topLeft.x() > topRight.x()) ? -1 : 1; + mMirrorX = horizontalFlip < 0 ; + if(horizontalFlip < 0){ + // why this is because of the way of calculating the translations that checks which side is the most is the + // nearest instead of checking which one is the left side. + QPointF tmp = topLeft; + topLeft = topRight; + topRight = tmp; + + // because of the calculation of the height is done by lenght and not deltaY + bottomLeft = itemTransform.map(itemRect.bottomRight()); + } + + qreal verticalFlip = (bottomLeft.y() < topLeft.y()) ? -1 : 1; + // not sure that is usefull + mMirrorY = verticalFlip < 0; + if(verticalFlip < 0 && !mMirrorX){ + topLeft = itemTransform.map(itemRect.bottomLeft()); + topRight = itemTransform.map(itemRect.bottomRight()); + bottomLeft = itemTransform.map(itemRect.topLeft()); + } + + QLineF topLine(topLeft, topRight); + QLineF leftLine(topLeft, bottomLeft); + qreal width = topLine.length(); + qreal height = leftLine.length(); + + mAngle = topLine.angle(); + + // the fact the the length is used we loose the horizontalFlip information + // a better way to do this is using DeltaX that preserve the direction information. + mTotalScaleX = (width / itemRect.width()) * horizontalFlip; + mTotalScaleY = height / itemRect.height() * verticalFlip; + + 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(); +} + +bool UBGraphicsDelegateFrame::canResizeBottomRight(qreal width, qreal height, qreal scaleFactor) +{ + bool res = false; + + if(!mMirrorX && !mMirrorX && ((width * scaleFactor) > 2*mFrameWidth && (height * scaleFactor) > 2*mFrameWidth)){ + res = true; + }else if(mMirrorX && !mMirrorY && (-width * scaleFactor) > 2*mFrameWidth && (height*scaleFactor) > 2*mFrameWidth){ + res = true; + }else if(!mMirrorX && mMirrorY && (width * scaleFactor) > 2*mFrameWidth && (-height*scaleFactor) > 2*mFrameWidth){ + res = true; + }else if(mMirrorX && mMirrorY && (-width * scaleFactor) > 2*mFrameWidth && (-height*scaleFactor) > 2*mFrameWidth){ + res = true; + } + + return res; +} + +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) + { + mTranslateX = moveX; + // Perform the resize + if (resizingBottomRight()) + { + // ----------------------------------------------------- + // ! We want to keep the aspect ratio with this resize ! + // ----------------------------------------------------- + qreal scaleX; + qreal scaleY; + + if(!mMirrorX){ + scaleX = (width + moveX) / width; + }else{ + scaleX = (width - moveX) / width; + } + + if(!mMirrorY){ + scaleY = (height + moveY) / height; + }else{ + scaleY = (height - moveY) / height; + } + + qreal scaleFactor = (scaleX + scaleY) / 2; + + // Do not allow resizing of image size under frame size + if (canResizeBottomRight(width, height, scaleFactor)) + { + if (mRespectRatio) + { + mScaleX = scaleFactor; + mScaleY = scaleFactor; + } + else + { + mScaleX = scaleX; + mScaleY = scaleY; + } + } + }else if (resizingLeft() || resizingRight()) + { + if(width != 0){ + qreal scaleX = 0.0; + if(resizingLeft()){ + scaleX = (width - moveX) / width; + }else if(resizingRight()){ + scaleX = (width + moveX) / width; + } + if(mDelegate->isFlippable() && qAbs(scaleX) != 0){ + if((qAbs(width * scaleX)) < 2*mFrameWidth){ + bool negative = (scaleX < 0)?true:false; + if(negative){ + if(mMirrorX) + scaleX = 2*mFrameWidth/width; + else + scaleX = -2*mFrameWidth/width; + }else{ + scaleX = -1; + } + } + mScaleX = scaleX; + }else if (scaleX > 1 || (width * scaleX) > 2 * mFrameWidth){ + mScaleX = scaleX; + if(resizingLeft()){ + mTranslateX = moveX; + } + } + } + }else if(resizingTop() || resizingBottom()){ + if(height != 0){ + qreal scaleY = 0.0; + if(resizingTop()){ + scaleY = (height - moveY) / height; + }else if(resizingBottom()){ + scaleY = (height + moveY) / height; + } + + if(mDelegate->isFlippable() && qAbs(scaleY) != 0){ + if((qAbs(height * scaleY)) < 2*mFrameWidth){ + bool negative = (scaleY < 0)?true:false; + if(negative){ + if(mMirrorY) + scaleY = 2*mFrameWidth/width; + else + scaleY = -2*mFrameWidth/width; + }else{ + scaleY = -1; + } + } + mScaleY = scaleY; + }else if (scaleY > 1 || (height * scaleY) > 2 * mFrameWidth) + { + mScaleY = scaleY; + if(resizingTop()){ + mTranslateY = moveY; + } + } + } + } + } + else if (mOperationMode == Resizing) + { + mTranslateX = moveX; + UBResizableGraphicsItem* resizableItem = dynamic_cast(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 (!(mDelegate->getToolBarItem()->isVisibleOnBoard() + && (newSize.width() < mDelegate->getToolBarItem()->minWidth() / mDelegate->antiScaleRatio() + || newSize.height() < mDelegate->getToolBarItem()->minWidth() / mDelegate->antiScaleRatio() * 3/4))) + resizableItem->resize(newSize); + } + } + + if (rotating()) + { + mTranslateX = 0; + mTranslateY = 0; + + 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 ((int)mAngle % 30 >= 30 - mAngleTolerance || (int)mAngle % 30 <= mAngleTolerance) + { + mAngle = qRound(mAngle / 30) * 30; + mAngleOffset += startLine.angleTo(currentLine); + if ((int)mAngleOffset % 360 > mAngleTolerance && (int)mAngleOffset % 360 < 360 - mAngleTolerance) + { + mAngle += mAngleOffset; + mAngleOffset = 0; + } + } + + if (!angleWidget->isVisible()) + angleWidget->show(); + + angleWidget->setText(QString::number((int)mAngle % 360)); + angleWidget->update(); + + } + 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 ref; + if(!mMirrorX && !mMirrorY){ + ref = delegated()->boundingRect().topLeft(); + }else if(mMirrorX && !mMirrorY){ + ref = delegated()->boundingRect().topLeft(); + }else if(!mMirrorX && mMirrorY){ + ref = delegated()->boundingRect().topLeft(); + }else if(mMirrorX && mMirrorY){ + ref = delegated()->boundingRect().topRight(); + } + + // Map the item topleft point to the current mouse move transform + QPointF topLeft = tr.map(ref); + + // Map the item topleft point to the mouse press transform + QPointF fixedPoint = mInitialTransform.map(ref); + + // Update the translation coordinates + mTranslateX += fixedPoint.x() - topLeft.x(); + mTranslateY += fixedPoint.y() - topLeft.y(); + + // Update the transform + 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(); + + // Translate + tr.translate(mTotalTranslateX + mTranslateX, mTotalTranslateY + mTranslateY); + + // Set angle + tr.translate(center.x() * mTotalScaleX * mScaleX, center.y() * mTotalScaleY * mScaleY); + tr.rotate(-mAngle); + tr.translate(-center.x() * mTotalScaleX * mScaleX, -center.y() * mTotalScaleY * mScaleY); + + // Scale + tr.scale(mTotalScaleX * mScaleX, mTotalScaleY * mScaleY); + return tr; +} + + +void UBGraphicsDelegateFrame::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (angleWidget->isVisible()) + angleWidget->hide(); + + updateResizeCursors(); + + mDelegate->commitUndoStep(); + mTotalScaleX *= mScaleX; + mTotalScaleY *= mScaleY; + mTotalTranslateX += mTranslateX; + mTotalTranslateY += mTranslateY; + event->accept(); + + mCurrentTool = None; + QGraphicsRectItem::mouseReleaseEvent(event); + + // Show the buttons + if(isResizing()){ + mResizing = false; + } + mDelegate->setButtonsVisible(true); +} + + +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(); + + if (mDelegate->getToolBarItem()->isVisibleOnBoard() + && mDelegate->getToolBarItem()->isShifting()) + itemRect.setHeight(itemRect.height() + mDelegate->getToolBarItem()->rect().height() * mDelegate->antiScaleRatio() * 1.1); + + QTransform itemTransform = delegated()->sceneTransform(); + QPointF topLeft = itemTransform.map(itemRect.topLeft()); + QPointF topRight = itemTransform.map(itemRect.topRight()); + QPointF bottomLeft = itemTransform.map(itemRect.bottomLeft()); + QPointF bottomRight = itemTransform.map(itemRect.bottomRight()); + QPointF center = itemTransform.map(itemRect.center()); + int rotateHeight = QLineF(topLeft, bottomLeft).length(); + + // Handle the mirroring + if(topLeft.x() > topRight.x()){ + QPointF topTmp = topRight; + QPointF bottomTmp = bottomRight; + topRight = topLeft; + topLeft = topTmp; + bottomRight = bottomLeft; + bottomLeft = bottomTmp; + } + + if(bottomLeft.y() > topLeft.y()){ + QPointF leftTmp = bottomLeft; + QPointF rightTmp = bottomRight; + bottomLeft = topLeft; + topLeft = leftTmp; + bottomRight = topRight; + topRight = rightTmp; + } + + QLineF topLine(topLeft, topRight); + qreal angle = topLine.angle(); + qreal width = topLine.length(); + + QLineF leftLine(topLeft, bottomLeft); + qreal height = leftLine.length(); + + int h = rotating()?rotateHeight:height; + + if (mVisible) + { + setRect(center.x() - mFrameWidth - width / 2, center.y() - mFrameWidth - h / 2, width + 2 * mFrameWidth, h + 2 * mFrameWidth); + } + else + { + setRect(center.x() - width / 2, center.y() - h / 2, width, h); + } + + 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()); + QRectF bRect = mBottomResizeGripSvgItem->mapRectToParent(mBottomResizeGripSvgItem->boundingRect()); + QRectF lRect = mLeftResizeGripSvgItem->mapRectToParent(mLeftResizeGripSvgItem->boundingRect()); + QRectF rRect = mRightResizeGripSvgItem->mapRectToParent(mRightResizeGripSvgItem->boundingRect()); + QRectF trRect = mTopResizeGripSvgItem->mapRectToParent(mTopResizeGripSvgItem->boundingRect()); + + mBottomRightResizeGripSvgItem->setPos(rect().right() - brRect.width(), rect().bottom() - brRect.height()); + mBottomResizeGripSvgItem->setPos(rect().center().x() - bRect.width() / 2, rect().bottom() - bRect.height()); + + mLeftResizeGripSvgItem->setPos(rect().left(), rect().center().y() - lRect.height() / 2); + mRightResizeGripSvgItem->setPos(rect().right() - rRect.width(), rect().center().y() - rRect.height() / 2); + + 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)); + } + + //make frame interact like delegated item when selected. Maybe should be deleted if selection logic will change + setZValue(delegated()->zValue()); +} + + +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)){ + if(mMirrorY){ + return ResizeTop; + }else{ + return ResizeBottom; + } + } + else if (leftResizeGripRect().contains(pos)){ + if(mMirrorX){ + return ResizeRight; + }else{ + return ResizeLeft; + } + return ResizeLeft; + } + else if (rightResizeGripRect().contains(pos)){ + if(mMirrorX){ + return ResizeLeft; + }else{ + return ResizeRight; + } + } + else if (topResizeGripRect().contains(pos)){ + if(mMirrorY){ + return ResizeBottom; + }else{ + 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); +} + +void UBGraphicsDelegateFrame::refreshGeometry() +{ + // Here we want to have the left on the left, the right on the right, the top on the top and the bottom on the bottom! + 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()); + + QLineF topLine(topLeft, topRight); + qreal width = topLine.length(); + QLineF leftLine(topLeft, bottomLeft); + qreal height = leftLine.length(); + setRect(topRight.x() - mFrameWidth, topLeft.y() - mFrameWidth, width + 2*mFrameWidth, height + 2*mFrameWidth); +} diff --git a/src/domain/UBGraphicsItemDelegate.cpp b/src/domain/UBGraphicsItemDelegate.cpp index cadbf191..663c5917 100644 --- a/src/domain/UBGraphicsItemDelegate.cpp +++ b/src/domain/UBGraphicsItemDelegate.cpp @@ -37,6 +37,9 @@ #include "UBGraphicsWidgetItem.h" #include "domain/UBAbstractWidget.h" +#include "domain/UBGraphicsTextItem.h" +#include "domain/UBGraphicsAudioItem.h" +#include "domain/UBGraphicsVideoItem.h" #include "web/UBWebController.h" @@ -93,6 +96,8 @@ UBGraphicsItemDelegate::UBGraphicsItemDelegate(QGraphicsItem* pDelegated, QObjec void UBGraphicsItemDelegate::init() { + mToolBarItem = new UBGraphicsToolBarItem(delegated()); + mFrame = new UBGraphicsDelegateFrame(this, QRectF(0, 0, 0, 0), mFrameWidth, mRespectRatio); mFrame->hide(); mFrame->setFlag(QGraphicsItem::ItemIsSelectable, true); @@ -123,10 +128,13 @@ void UBGraphicsItemDelegate::init() foreach(DelegateButton* button, mButtons) { + if (button->getSection() != Qt::TitleBarArea) + { button->hide(); button->setFlag(QGraphicsItem::ItemIsSelectable, true); } } +} UBGraphicsItemDelegate::~UBGraphicsItemDelegate() @@ -292,13 +300,20 @@ void UBGraphicsItemDelegate::positionHandles() updateButtons(true); + if (mToolBarItem->isVisibleOnBoard()) + { + updateToolBar(); + mToolBarItem->show(); + } } else { foreach(DelegateButton* button, mButtons) button->hide(); mFrame->hide(); + mToolBarItem->hide(); } } + void UBGraphicsItemDelegate::setZOrderButtonsVisible(bool visible) { if (visible) { @@ -335,6 +350,7 @@ void UBGraphicsItemDelegate::remove(bool canUndo) scene->removeItem(mFrame); scene->removeItem(mDelegated); + scene->removeItem(mToolBarItem); if (canUndo) { @@ -577,14 +593,16 @@ void UBGraphicsItemDelegate::updateButtons(bool showUpdated) int i = 1, j = 0, k = 0; while ((i + j + k) < mButtons.size()) { DelegateButton* button = mButtons[i + j]; - button->setParentItem(mFrame); - button->setTransform(tr); if (button->getSection() == Qt::TopLeftSection) { + button->setParentItem(mFrame); button->setPos(topX + (i++ * 1.6 * mFrameWidth * mAntiScaleRatio), topY); + button->setTransform(tr); } else if (button->getSection() == Qt::BottomLeftSection) { + button->setParentItem(mFrame); button->setPos(bottomX + (++j * 1.6 * mFrameWidth * mAntiScaleRatio), bottomY); - } else if (button->getSection() == Qt::NoSection) { + button->setTransform(tr); + } else if (button->getSection() == Qt::TitleBarArea || button->getSection() == Qt::NoSection){ ++k; } if (!button->scene()) @@ -599,9 +617,65 @@ void UBGraphicsItemDelegate::updateButtons(bool showUpdated) } } +void UBGraphicsItemDelegate::updateToolBar() +{ + QTransform transformForToolbarButtons; + transformForToolbarButtons.scale(mAntiScaleRatio, 1); + + QRectF toolBarRect = mToolBarItem->rect(); + toolBarRect.setWidth(delegated()->boundingRect().width() - 10); + mToolBarItem->setRect(toolBarRect); + + if (mToolBarItem->isShifting()) + mToolBarItem->setPos(delegated()->boundingRect().bottomLeft() + QPointF(5 * mAntiScaleRatio, 0)); + else mToolBarItem->setPos(delegated()->boundingRect().bottomLeft() - QPointF(-5 * mAntiScaleRatio, mToolBarItem->rect().height() * 1.1 * mAntiScaleRatio)); + + int offsetOnToolBar = 5 * mAntiScaleRatio; + QList itemList = mToolBarItem->itemsOnToolBar(); + foreach (QGraphicsItem* item, itemList) + { + item->setPos(offsetOnToolBar, 0); + offsetOnToolBar += (item->boundingRect().width() + 5) * mAntiScaleRatio; + item->setTransform(transformForToolbarButtons); + item->show(); + } + + mToolBarItem->setOffsetOnToolBar(offsetOnToolBar); + + QTransform tr; + tr.scale(1, mAntiScaleRatio); + mToolBarItem->setTransform(tr); +} + void UBGraphicsItemDelegate::setButtonsVisible(bool visible) { foreach(DelegateButton* pButton, mButtons){ pButton->setVisible(visible); } } + +UBGraphicsToolBarItem::UBGraphicsToolBarItem(QGraphicsItem * parent) : + QGraphicsRectItem(parent), + mShifting(true), + mVisible(false), + mMinWidth(200) +{ + QRectF rect = this->rect(); + rect.setHeight(26); + this->setRect(rect); + + setBrush(QColor(UBSettings::paletteColor)); + setPen(Qt::NoPen); + hide(); +} + +void UBGraphicsToolBarItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + QPainterPath path; + path.addRoundedRect(rect(), 10, 10); + + painter->fillPath(path, brush()); +} \ No newline at end of file diff --git a/src/domain/UBGraphicsItemDelegate.h b/src/domain/UBGraphicsItemDelegate.h index f560b546..2013634f 100644 --- a/src/domain/UBGraphicsItemDelegate.h +++ b/src/domain/UBGraphicsItemDelegate.h @@ -84,6 +84,31 @@ class DelegateButton: public QGraphicsSvgItem }; +class UBGraphicsToolBarItem : public QGraphicsRectItem, public QObject +{ + public: + UBGraphicsToolBarItem(QGraphicsItem * parent = 0); + virtual ~UBGraphicsToolBarItem() {}; + + bool isVisibleOnBoard() const { return mVisible; } + void setVisibleOnBoard(bool visible) { mVisible = visible; } + bool isShifting() const { return mShifting; } + void setShifting(bool shifting) { mShifting = shifting; } + int offsetOnToolBar() const { return mOffsetOnToolBar; } + void setOffsetOnToolBar(int pOffset) { mOffsetOnToolBar = pOffset; } + QList itemsOnToolBar() const { return mItemsOnToolBar; } + void setItemsOnToolBar(QList itemsOnToolBar) { mItemsOnToolBar = itemsOnToolBar;} + int minWidth() { return mMinWidth; } + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget); + + private: + bool mShifting; + bool mVisible; + int mOffsetOnToolBar; + int mMinWidth; + QList mItemsOnToolBar; +}; class UBGraphicsItemDelegate : public QObject { @@ -138,6 +163,10 @@ class UBGraphicsItemDelegate : public QObject void setButtonsVisible(bool visible); + UBGraphicsToolBarItem* getToolBarItem() const { return mToolBarItem; } + + qreal antiScaleRatio() const { return mAntiScaleRatio; } + signals: void showOnDisplayChanged(bool shown); void lockChanged(bool locked); @@ -183,12 +212,17 @@ class UBGraphicsItemDelegate : public QObject QList mButtons; + UBGraphicsToolBarItem* mToolBarItem; + protected slots: virtual void gotoContentSource(bool checked); private: void updateFrame(); void updateButtons(bool showUpdated = false); + void updateToolBar(); + + QPointF mOffset; QTransform mPreviousTransform; diff --git a/src/domain/UBGraphicsTextItemDelegate.cpp b/src/domain/UBGraphicsTextItemDelegate.cpp index c567ef43..8c132325 100644 --- a/src/domain/UBGraphicsTextItemDelegate.cpp +++ b/src/domain/UBGraphicsTextItemDelegate.cpp @@ -94,17 +94,21 @@ void UBGraphicsTextItemDelegate::buildButtons() { UBGraphicsItemDelegate::buildButtons(); - mFontButton = new DelegateButton(":/images/font.svg", mDelegated, mFrame, Qt::TopLeftSection); - mColorButton = new DelegateButton(":/images/color.svg", mDelegated, mFrame, Qt::TopLeftSection); - mDecreaseSizeButton = new DelegateButton(":/images/minus.svg", mDelegated, mFrame, Qt::TopLeftSection); - mIncreaseSizeButton = new DelegateButton(":/images/plus.svg", mDelegated, mFrame, Qt::TopLeftSection); + mFontButton = new DelegateButton(":/images/font.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); + mColorButton = new DelegateButton(":/images/color.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); + mDecreaseSizeButton = new DelegateButton(":/images/minus.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); + mIncreaseSizeButton = new DelegateButton(":/images/plus.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); connect(mFontButton, SIGNAL(clicked(bool)), this, SLOT(pickFont())); connect(mColorButton, SIGNAL(clicked(bool)), this, SLOT(pickColor())); connect(mDecreaseSizeButton, SIGNAL(clicked(bool)), this, SLOT(decreaseSize())); connect(mIncreaseSizeButton, SIGNAL(clicked(bool)), this, SLOT(increaseSize())); - mButtons << mFontButton << mColorButton << mDecreaseSizeButton << mIncreaseSizeButton; + QList itemsOnToolBar; + itemsOnToolBar << mFontButton << mColorButton << mDecreaseSizeButton << mIncreaseSizeButton; + mToolBarItem->setItemsOnToolBar(itemsOnToolBar); + + mToolBarItem->setVisibleOnBoard(true); } void UBGraphicsTextItemDelegate::contentsChanged() diff --git a/src/domain/UBGraphicsVideoItemDelegate.cpp b/src/domain/UBGraphicsVideoItemDelegate.cpp index 35620cf0..e02640c5 100644 --- a/src/domain/UBGraphicsVideoItemDelegate.cpp +++ b/src/domain/UBGraphicsVideoItemDelegate.cpp @@ -1,336 +1,351 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include - -#include "UBGraphicsVideoItemDelegate.h" - -#include "UBGraphicsScene.h" - -#include "core/UBSettings.h" -#include "core/UBApplication.h" -#include "core/UBApplicationController.h" -#include "core/UBDisplayManager.h" - -#include "domain/UBGraphicsVideoItem.h" -#include "domain/UBGraphicsDelegateFrame.h" - -#include "core/memcheck.h" - -UBGraphicsVideoItemDelegate::UBGraphicsVideoItemDelegate(UBGraphicsVideoItem* pDelegated, Phonon::MediaObject* pMedia, QObject * parent) - : UBGraphicsItemDelegate(pDelegated, parent, true, false) - , mMedia(pMedia) -{ - // NOOP -} - -void UBGraphicsVideoItemDelegate::buildButtons() -{ - mPlayPauseButton = new DelegateButton(":/images/play.svg", mDelegated, mFrame); - - mStopButton = new DelegateButton(":/images/stop.svg", mDelegated, mFrame); - mStopButton->hide(); - - if (delegated()->isMuted()) - mMuteButton = new DelegateButton(":/images/soundOff.svg", mDelegated, mFrame); - else - mMuteButton = new DelegateButton(":/images/soundOn.svg", mDelegated, mFrame); - - mMuteButton->hide(); - - mVideoControl = new DelegateVideoControl(delegated(), mFrame); - UBGraphicsItem::assignZValue(mVideoControl, delegated()->zValue()); - mVideoControl->setFlag(QGraphicsItem::ItemIsSelectable, true); - - connect(mPlayPauseButton, SIGNAL(clicked(bool)), this, SLOT(togglePlayPause())); - connect(mStopButton, SIGNAL(clicked(bool)), mMedia, SLOT(stop())); - connect(mMuteButton, SIGNAL(clicked(bool)), delegated(), SLOT(toggleMute())); - connect(mMuteButton, SIGNAL(clicked(bool)), this, SLOT(toggleMute())); - - mButtons << mPlayPauseButton << mStopButton << mMuteButton; - - mMedia->setTickInterval(50); - - connect(mMedia, SIGNAL(stateChanged (Phonon::State, Phonon::State)), this, SLOT(mediaStateChanged (Phonon::State, Phonon::State))); - connect(mMedia, SIGNAL(finished()), this, SLOT(updatePlayPauseState())); - connect(mMedia, SIGNAL(tick(qint64)), this, SLOT(updateTicker(qint64))); - connect(mMedia, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64))); - -} - - -UBGraphicsVideoItemDelegate::~UBGraphicsVideoItemDelegate() -{ - //NOOP -} - - -void UBGraphicsVideoItemDelegate::positionHandles() -{ - UBGraphicsItemDelegate::positionHandles(); - - if (mDelegated->isSelected()) - { - qreal scaledFrameWidth = mFrameWidth * mAntiScaleRatio; - - - qreal width = mFrame->rect().width(); - qreal height = mFrame->rect().height(); - - qreal x = mFrame->rect().left(); - qreal y = mFrame->rect().top(); - - mVideoControl->setRect(x + 2 * scaledFrameWidth - , y + height - 3 * scaledFrameWidth - , width - 4 * scaledFrameWidth - , 2 * scaledFrameWidth); - - if (!mVideoControl->scene()) - { - mVideoControl->setParentItem(mFrame);//update parent for the case the item has been previously removed from scene - mDelegated->scene()->addItem(mVideoControl); - } - - mVideoControl->setAntiScale(mAntiScaleRatio); - mVideoControl->setZValue(delegated()->zValue()); - mVideoControl->show(); - } - else - { - mVideoControl->hide(); - } -} - - -void UBGraphicsVideoItemDelegate::remove(bool canUndo) -{ - if (delegated() && delegated()->mediaObject()) - delegated()->mediaObject()->stop(); - - QGraphicsScene* scene = mDelegated->scene(); - - scene->removeItem(mVideoControl); - - UBGraphicsItemDelegate::remove(canUndo); -} - - -void UBGraphicsVideoItemDelegate::toggleMute() -{ - if (delegated()->isMuted()) - mMuteButton->setFileName(":/images/soundOff.svg"); - else - mMuteButton->setFileName(":/images/soundOn.svg"); - -} - - -UBGraphicsVideoItem* UBGraphicsVideoItemDelegate::delegated() -{ - return static_cast(mDelegated); -} - - -void UBGraphicsVideoItemDelegate::togglePlayPause() -{ - if (delegated() && delegated()->mediaObject()) { - - Phonon::MediaObject* media = delegated()->mediaObject(); - if (media->state() == Phonon::StoppedState) { - media->play(); - } else if (media->state() == Phonon::PlayingState) { - if (media->remainingTime() <= 0) { - media->stop(); - media->play(); - } else { - media->pause(); - if(delegated()->scene()) - delegated()->scene()->setModified(true); - } - } else if (media->state() == Phonon::PausedState) { - if (media->remainingTime() <= 0) { - media->stop(); - } - media->play(); - } else if ( media->state() == Phonon::LoadingState ) { - delegated()->mediaObject()->setCurrentSource(delegated()->mediaFileUrl()); - media->play(); - } else if (media->state() == Phonon::ErrorState){ - qDebug() << "Error appeared." << media->errorString(); - } - } -} - -void UBGraphicsVideoItemDelegate::mediaStateChanged ( Phonon::State newstate, Phonon::State oldstate ) -{ - Q_UNUSED(newstate); - Q_UNUSED(oldstate); - updatePlayPauseState(); -} - - -void UBGraphicsVideoItemDelegate::updatePlayPauseState() -{ - Phonon::MediaObject* media = delegated()->mediaObject(); - - if (media->state() == Phonon::PlayingState) - mPlayPauseButton->setFileName(":/images/pause.svg"); - else - mPlayPauseButton->setFileName(":/images/play.svg"); -} - - -void UBGraphicsVideoItemDelegate::updateTicker(qint64 time) -{ - Phonon::MediaObject* media = delegated()->mediaObject(); - mVideoControl->totalTimeChanged(media->totalTime()); - - mVideoControl->updateTicker(time); -} - - -void UBGraphicsVideoItemDelegate::totalTimeChanged(qint64 newTotalTime) -{ - mVideoControl->totalTimeChanged(newTotalTime); -} - - -DelegateVideoControl::DelegateVideoControl(UBGraphicsVideoItem* pDelegated, QGraphicsItem * parent) - : QGraphicsRectItem(parent) - , mDelegate(pDelegated) - , mDisplayCurrentTime(false) - , mAntiScale(1.0) - , mCurrentTimeInMs(0) - , mTotalTimeInMs(0) -{ - setAcceptedMouseButtons(Qt::LeftButton); - - setBrush(QBrush(UBSettings::paletteColor)); - setPen(Qt::NoPen); - setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); -} - - -void DelegateVideoControl::paint(QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_UNUSED(option); - Q_UNUSED(widget); - - painter->fillPath(shape(), brush()); - - qreal frameWidth = rect().height() / 2; - int position = frameWidth; - - if (mTotalTimeInMs > 0) - { - position = frameWidth + (rect().width() - (2 * frameWidth)) / mTotalTimeInMs * mCurrentTimeInMs; - } - - int radius = rect().height() / 6; - QRectF r(rect().x() + position - radius, rect().y() + (rect().height() / 4) - radius, radius * 2, radius * 2); - - painter->setBrush(UBSettings::documentViewLightColor); - painter->drawEllipse(r); - - if(mDisplayCurrentTime) - { - painter->setBrush(UBSettings::paletteColor); - painter->setPen(QPen(Qt::NoPen)); - QRectF balloon(rect().x() + position - frameWidth, rect().y() - (frameWidth * 1.2), 2 * frameWidth, frameWidth); - painter->drawRoundedRect(balloon, frameWidth/2, frameWidth/2); - - QTime t; - t = t.addMSecs(mCurrentTimeInMs < 0 ? 0 : mCurrentTimeInMs); - QFont f = painter->font(); - f.setPointSizeF(f.pointSizeF() * mAntiScale); - painter->setFont(f); - painter->setPen(Qt::white); - painter->drawText(balloon, Qt::AlignCenter, t.toString("m:ss")); - } -} - - -QPainterPath DelegateVideoControl::shape() const -{ - QPainterPath path; - QRectF r = rect().adjusted(0,0,0,- rect().height() / 2); - path.addRoundedRect(r, rect().height() / 4, rect().height() / 4); - return path; -} - - -void DelegateVideoControl::updateTicker(qint64 time ) -{ - mCurrentTimeInMs = time; - update(); -} - - -void DelegateVideoControl::totalTimeChanged(qint64 newTotalTime) -{ - mTotalTimeInMs = newTotalTime; - update(); -} - - -void DelegateVideoControl::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - mDisplayCurrentTime = true; - seekToMousePos(event->pos()); - update(); - event->accept(); -} - - -void DelegateVideoControl::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - seekToMousePos(event->pos()); - update(); - event->accept(); -} - - -void DelegateVideoControl::seekToMousePos(QPointF mousePos) -{ - qreal minX, length; - qreal frameWidth = rect().height() / 2; - - minX = rect().x() + frameWidth; - length = rect().width() - (2 * frameWidth); - - qreal mouseX = mousePos.x(); - - if (mTotalTimeInMs > 0 && length > 0 && mDelegate - && mDelegate->mediaObject() && mDelegate->mediaObject()->isSeekable()) - { - qint64 tickPos = mTotalTimeInMs / length * (mouseX - minX); - mDelegate->mediaObject()->seek(tickPos); - - //OSX is a bit lazy - updateTicker(tickPos); - } -} - -void DelegateVideoControl::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - mDisplayCurrentTime = false; - update(); - event->accept(); -} - - - +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "UBGraphicsVideoItemDelegate.h" + +#include "UBGraphicsScene.h" + +#include "core/UBSettings.h" +#include "core/UBApplication.h" +#include "core/UBApplicationController.h" +#include "core/UBDisplayManager.h" + +#include "domain/UBGraphicsVideoItem.h" +#include "domain/UBGraphicsDelegateFrame.h" + +#include "core/memcheck.h" + +UBGraphicsVideoItemDelegate::UBGraphicsVideoItemDelegate(UBGraphicsVideoItem* pDelegated, Phonon::MediaObject* pMedia, QObject * parent) + : UBGraphicsItemDelegate(pDelegated, parent, true, false) + , mMedia(pMedia) +{ + // NOOP +} + +void UBGraphicsVideoItemDelegate::buildButtons() +{ + mPlayPauseButton = new DelegateButton(":/images/play.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); + + mStopButton = new DelegateButton(":/images/stop.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); + + mVideoControl = new DelegateVideoControl(delegated(), mToolBarItem); + UBGraphicsItem::assignZValue(mVideoControl, delegated()->zValue()); + mVideoControl->setFlag(QGraphicsItem::ItemIsSelectable, true); + + if (delegated()->isMuted()) + mMuteButton = new DelegateButton(":/images/soundOff.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); + else + mMuteButton = new DelegateButton(":/images/soundOn.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); + + connect(mPlayPauseButton, SIGNAL(clicked(bool)), this, SLOT(togglePlayPause())); + connect(mStopButton, SIGNAL(clicked(bool)), mMedia, SLOT(stop())); + connect(mMuteButton, SIGNAL(clicked(bool)), delegated(), SLOT(toggleMute())); + connect(mMuteButton, SIGNAL(clicked(bool)), this, SLOT(toggleMute())); + + mButtons << mPlayPauseButton << mStopButton << mMuteButton; + + QList itemsOnToolBar; + itemsOnToolBar << mPlayPauseButton << mStopButton << mVideoControl << mMuteButton; + mToolBarItem->setItemsOnToolBar(itemsOnToolBar); + + mMedia->setTickInterval(50); + + connect(mMedia, SIGNAL(stateChanged (Phonon::State, Phonon::State)), this, SLOT(mediaStateChanged (Phonon::State, Phonon::State))); + connect(mMedia, SIGNAL(finished()), this, SLOT(updatePlayPauseState())); + connect(mMedia, SIGNAL(tick(qint64)), this, SLOT(updateTicker(qint64))); + connect(mMedia, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64))); + + mToolBarItem->setVisibleOnBoard(true); + mToolBarItem->setShifting(false); +} + + +UBGraphicsVideoItemDelegate::~UBGraphicsVideoItemDelegate() +{ + //NOOP +} + + +void UBGraphicsVideoItemDelegate::positionHandles() +{ + UBGraphicsItemDelegate::positionHandles(); + + if (mDelegated->isSelected()) + { + qreal scaledFrameWidth = mFrameWidth * mAntiScaleRatio; + + int offset = 0; + foreach (DelegateButton* button, mButtons) + { + if (button->getSection() == Qt::TitleBarArea) + offset += button->boundingRect().width() * mAntiScaleRatio; + } + + mVideoControl->setRect(mVideoControl->rect().x() + , scaledFrameWidth/6 - 0.5 + , (mToolBarItem->rect().width() - 35 - offset) / mAntiScaleRatio + , (2 * scaledFrameWidth) / mAntiScaleRatio); + + offset += (mVideoControl->rect().width() + 5) * mAntiScaleRatio; + mMuteButton->setPos(offset, 0); + + if (!mVideoControl->scene()) + { + mVideoControl->setParentItem(mToolBarItem);//update parent for the case the item has been previously removed from scene + mDelegated->scene()->addItem(mVideoControl); + } + + mVideoControl->setAntiScale(mAntiScaleRatio); + mVideoControl->setZValue(delegated()->zValue()); + mVideoControl->show(); + } + else + { + mVideoControl->hide(); + } +} + + +void UBGraphicsVideoItemDelegate::remove(bool canUndo) +{ + if (delegated() && delegated()->mediaObject()) + delegated()->mediaObject()->stop(); + + QGraphicsScene* scene = mDelegated->scene(); + + scene->removeItem(mVideoControl); + + UBGraphicsItemDelegate::remove(canUndo); +} + + +void UBGraphicsVideoItemDelegate::toggleMute() +{ + if (delegated()->isMuted()) + mMuteButton->setFileName(":/images/soundOff.svg"); + else + mMuteButton->setFileName(":/images/soundOn.svg"); + +} + + +UBGraphicsVideoItem* UBGraphicsVideoItemDelegate::delegated() +{ + return static_cast(mDelegated); +} + + +void UBGraphicsVideoItemDelegate::togglePlayPause() +{ + if (delegated() && delegated()->mediaObject()) { + + Phonon::MediaObject* media = delegated()->mediaObject(); + if (media->state() == Phonon::StoppedState) { + media->play(); + } else if (media->state() == Phonon::PlayingState) { + if (media->remainingTime() <= 0) { + media->stop(); + media->play(); + } else { + media->pause(); + if(delegated()->scene()) + delegated()->scene()->setModified(true); + } + } else if (media->state() == Phonon::PausedState) { + if (media->remainingTime() <= 0) { + media->stop(); + } + media->play(); + } else if ( media->state() == Phonon::LoadingState ) { + delegated()->mediaObject()->setCurrentSource(delegated()->mediaFileUrl()); + media->play(); + } else if (media->state() == Phonon::ErrorState){ + qDebug() << "Error appeared." << media->errorString(); + } + } +} + +void UBGraphicsVideoItemDelegate::mediaStateChanged ( Phonon::State newstate, Phonon::State oldstate ) +{ + Q_UNUSED(newstate); + Q_UNUSED(oldstate); + updatePlayPauseState(); +} + + +void UBGraphicsVideoItemDelegate::updatePlayPauseState() +{ + Phonon::MediaObject* media = delegated()->mediaObject(); + + if (media->state() == Phonon::PlayingState) + mPlayPauseButton->setFileName(":/images/pause.svg"); + else + mPlayPauseButton->setFileName(":/images/play.svg"); +} + + +void UBGraphicsVideoItemDelegate::updateTicker(qint64 time) +{ + Phonon::MediaObject* media = delegated()->mediaObject(); + mVideoControl->totalTimeChanged(media->totalTime()); + + mVideoControl->updateTicker(time); +} + + +void UBGraphicsVideoItemDelegate::totalTimeChanged(qint64 newTotalTime) +{ + mVideoControl->totalTimeChanged(newTotalTime); +} + + +DelegateVideoControl::DelegateVideoControl(UBGraphicsVideoItem* pDelegated, QGraphicsItem * parent) + : QGraphicsRectItem(parent) + , mDelegate(pDelegated) + , mDisplayCurrentTime(false) + , mAntiScale(1.0) + , mCurrentTimeInMs(0) + , mTotalTimeInMs(0) + , mStartWidth(200) +{ + setAcceptedMouseButtons(Qt::LeftButton); + + setBrush(QBrush(Qt::white)); + setPen(Qt::NoPen); + setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); + + QRectF rect = this->rect(); + rect.setWidth(mStartWidth); + this->setRect(rect); +} + + +void DelegateVideoControl::paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + painter->fillPath(shape(), brush()); + + qreal frameWidth = rect().height() / 2; + int position = frameWidth; + + if (mTotalTimeInMs > 0) + { + position = frameWidth + (rect().width() - (2 * frameWidth)) / mTotalTimeInMs * mCurrentTimeInMs; + } + + int radius = rect().height() / 6; + QRectF r(rect().x() + position - radius, rect().y() + (rect().height() / 4) - radius, radius * 2, radius * 2); + + painter->setBrush(UBSettings::documentViewLightColor); + painter->drawEllipse(r); + + if(mDisplayCurrentTime) + { + painter->setBrush(UBSettings::paletteColor); + painter->setPen(QPen(Qt::NoPen)); + mBalloon.setRect(rect().x() + position - frameWidth, rect().y() - (frameWidth * 1.2), 2 * frameWidth, frameWidth); + painter->drawRoundedRect(mBalloon, frameWidth/2, frameWidth/2); + + QTime t; + t = t.addMSecs(mCurrentTimeInMs < 0 ? 0 : mCurrentTimeInMs); + QFont f = painter->font(); + f.setPointSizeF(f.pointSizeF() * mAntiScale); + painter->setFont(f); + painter->setPen(Qt::white); + painter->drawText(mBalloon, Qt::AlignCenter, t.toString("m:ss")); + } +} + + +QPainterPath DelegateVideoControl::shape() const +{ + QPainterPath path; + QRectF r = rect().adjusted(0,0,0,- rect().height() / 2); + path.addRoundedRect(r, rect().height() / 4, rect().height() / 4); + return path; +} + + +void DelegateVideoControl::updateTicker(qint64 time ) +{ + mCurrentTimeInMs = time; + update(); +} + + +void DelegateVideoControl::totalTimeChanged(qint64 newTotalTime) +{ + mTotalTimeInMs = newTotalTime; + update(); +} + + +void DelegateVideoControl::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + mDisplayCurrentTime = true; + seekToMousePos(event->pos()); + update(); + event->accept(); +} + + +void DelegateVideoControl::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (shape().contains(event->pos() - QPointF(mBalloon.width()/2,0)) + && shape().contains(event->pos() + QPointF(mBalloon.width()/2,0))) + { + seekToMousePos(event->pos()); + update(); + event->accept(); + } +} + + +void DelegateVideoControl::seekToMousePos(QPointF mousePos) +{ + qreal minX, length; + qreal frameWidth = rect().height() / 2; + + minX = rect().x() + frameWidth; + length = rect().width() - (2 * frameWidth); + + qreal mouseX = mousePos.x(); + + if (mTotalTimeInMs > 0 && length > 0 && mDelegate + && mDelegate->mediaObject() && mDelegate->mediaObject()->isSeekable()) + { + qint64 tickPos = mTotalTimeInMs / length * (mouseX - minX); + mDelegate->mediaObject()->seek(tickPos); + + //OSX is a bit lazy + updateTicker(tickPos); + } +} + +void DelegateVideoControl::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + mDisplayCurrentTime = false; + update(); + event->accept(); +} + + + diff --git a/src/domain/UBGraphicsVideoItemDelegate.h b/src/domain/UBGraphicsVideoItemDelegate.h index 8fd36bcc..66dcd8a8 100644 --- a/src/domain/UBGraphicsVideoItemDelegate.h +++ b/src/domain/UBGraphicsVideoItemDelegate.h @@ -1,114 +1,116 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UBGRAPHICSVIDEOITEMDELEGATE_H_ -#define UBGRAPHICSVIDEOITEMDELEGATE_H_ - -#include -#include - -#include "core/UB.h" -#include "UBGraphicsItemDelegate.h" - -class QGraphicsSceneMouseEvent; -class QGraphicsItem; -class UBGraphicsVideoItem; - -class DelegateVideoControl: public QGraphicsRectItem -{ - public: - - DelegateVideoControl(UBGraphicsVideoItem* pDelegated, QGraphicsItem * parent = 0); - - virtual ~DelegateVideoControl() - { - // NOOP - } - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, - QWidget *widget); - - QPainterPath shape() const; - - void setAntiScale(qreal antiScale){ mAntiScale = antiScale; } - - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - - void updateTicker(qint64 time); - void totalTimeChanged( qint64 newTotalTime); - - protected: - - - void seekToMousePos(QPointF mousePos); - - UBGraphicsVideoItem* mDelegate; - bool mDisplayCurrentTime; - - qreal mAntiScale; - qint64 mCurrentTimeInMs; - qint64 mTotalTimeInMs; - -}; - - -class UBGraphicsVideoItemDelegate : public UBGraphicsItemDelegate -{ - Q_OBJECT - - public: - UBGraphicsVideoItemDelegate(UBGraphicsVideoItem* pDelegated, Phonon::MediaObject* pMedia, QObject * parent = 0); - virtual ~UBGraphicsVideoItemDelegate(); - - virtual void positionHandles(); - - public slots: - - void toggleMute(); - void updateTicker(qint64 time); - - protected slots: - - virtual void remove(bool canUndo = true); - - void togglePlayPause(); - - void mediaStateChanged ( Phonon::State newstate, Phonon::State oldstate ); - - void updatePlayPauseState(); - - void totalTimeChanged( qint64 newTotalTime); - - protected: - - virtual void buildButtons(); - - private: - - UBGraphicsVideoItem* delegated(); - - DelegateButton* mPlayPauseButton; - DelegateButton* mStopButton; - DelegateButton* mMuteButton; - DelegateVideoControl *mVideoControl; - - Phonon::MediaObject* mMedia; - -}; - - -#endif /* UBGRAPHICSVIDEOITEMDELEGATE_H_ */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UBGRAPHICSVIDEOITEMDELEGATE_H_ +#define UBGRAPHICSVIDEOITEMDELEGATE_H_ + +#include +#include + +#include "core/UB.h" +#include "UBGraphicsItemDelegate.h" + +class QGraphicsSceneMouseEvent; +class QGraphicsItem; +class UBGraphicsVideoItem; + +class DelegateVideoControl: public QGraphicsRectItem +{ + public: + + DelegateVideoControl(UBGraphicsVideoItem* pDelegated, QGraphicsItem * parent = 0); + + virtual ~DelegateVideoControl() + { + // NOOP + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget); + + QPainterPath shape() const; + + void setAntiScale(qreal antiScale){ mAntiScale = antiScale; } + + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + + void updateTicker(qint64 time); + void totalTimeChanged( qint64 newTotalTime); + + protected: + + + void seekToMousePos(QPointF mousePos); + + UBGraphicsVideoItem* mDelegate; + bool mDisplayCurrentTime; + + qreal mAntiScale; + qint64 mCurrentTimeInMs; + qint64 mTotalTimeInMs; + + private: + int mStartWidth; + QRectF mBalloon; +}; + + +class UBGraphicsVideoItemDelegate : public UBGraphicsItemDelegate +{ + Q_OBJECT + + public: + UBGraphicsVideoItemDelegate(UBGraphicsVideoItem* pDelegated, Phonon::MediaObject* pMedia, QObject * parent = 0); + virtual ~UBGraphicsVideoItemDelegate(); + + virtual void positionHandles(); + + public slots: + + void toggleMute(); + void updateTicker(qint64 time); + + protected slots: + + virtual void remove(bool canUndo = true); + + void togglePlayPause(); + + void mediaStateChanged ( Phonon::State newstate, Phonon::State oldstate ); + + void updatePlayPauseState(); + + void totalTimeChanged( qint64 newTotalTime); + + protected: + + virtual void buildButtons(); + + private: + + UBGraphicsVideoItem* delegated(); + + DelegateButton* mPlayPauseButton; + DelegateButton* mStopButton; + DelegateButton* mMuteButton; + DelegateVideoControl *mVideoControl; + + Phonon::MediaObject* mMedia; +}; + + +#endif /* UBGRAPHICSVIDEOITEMDELEGATE_H_ */