/*
* 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 < http : //www.gnu.org/licenses/>.
*/
# include <QtGui>
# include <QtSvg>
# include <QDrag>
# include "UBGraphicsItemDelegate.h"
# include "UBGraphicsDelegateFrame.h"
# include "UBGraphicsScene.h"
# include "UBGraphicsItemUndoCommand.h"
# include "UBGraphicsItemTransformUndoCommand.h"
# include "board/UBBoardController.h" // TODO UB 4.x clean that dependency
# include "board/UBBoardView.h" // TODO UB 4.x clean that dependency
# include "core/UBApplication.h"
# include "core/UBApplicationController.h"
# include "core/UBDisplayManager.h"
# include "core/UBSettings.h"
# include "core/UBPersistenceManager.h"
# include "document/UBDocumentProxy.h"
# include "UBGraphicsWidgetItem.h"
# include "domain/UBAbstractWidget.h"
# include "web/UBWebController.h"
# include "frameworks/UBFileSystemUtils.h"
# include "board/UBDrawingController.h"
# include "core/memcheck.h"
class UBGraphicsParaschoolEditorWidgetItem ;
UBGraphicsItemDelegate : : UBGraphicsItemDelegate ( QGraphicsItem * pDelegated , QObject * parent , bool respectRatio , bool canRotate )
: QObject ( parent )
, mDelegated ( pDelegated )
, mDeleteButton ( NULL )
, mDuplicateButton ( NULL )
, mMenuButton ( NULL )
, mMenu ( 0 )
, mLockAction ( 0 )
, mShowOnDisplayAction ( 0 )
, mGotoContentSourceAction ( 0 )
, mFrame ( 0 )
, mFrameWidth ( UBSettings : : settings ( ) - > objectFrameWidth )
, mAntiScaleRatio ( 1.0 )
, mCanRotate ( canRotate )
, mCanDuplicate ( true )
, mRespectRatio ( respectRatio )
, mMimeData ( NULL )
{
// NOOP
}
void UBGraphicsItemDelegate : : init ( )
{
mFrame = new UBGraphicsDelegateFrame ( this , QRectF ( 0 , 0 , 0 , 0 ) , mFrameWidth , mRespectRatio ) ;
mFrame - > hide ( ) ;
mFrame - > setZValue ( UBGraphicsScene : : toolLayerStart + 1 ) ;
mFrame - > setFlag ( QGraphicsItem : : ItemIsSelectable , true ) ;
mDeleteButton = new DelegateButton ( " :/images/close.svg " , mDelegated , mFrame ) ;
mButtons < < mDeleteButton ;
connect ( mDeleteButton , SIGNAL ( clicked ( ) ) , this , SLOT ( remove ( ) ) ) ;
if ( canDuplicate ( ) ) {
mDuplicateButton = new DelegateButton ( " :/images/duplicate.svg " , mDelegated , mFrame ) ;
connect ( mDuplicateButton , SIGNAL ( clicked ( bool ) ) , this , SLOT ( duplicate ( ) ) ) ;
mButtons < < mDuplicateButton ;
}
mMenuButton = new DelegateButton ( " :/images/menu.svg " , mDelegated , mFrame ) ;
connect ( mMenuButton , SIGNAL ( clicked ( ) ) , this , SLOT ( showMenu ( ) ) ) ;
mButtons < < mMenuButton ;
buildButtons ( ) ;
foreach ( DelegateButton * button , mButtons )
{
button - > hide ( ) ;
button - > setZValue ( UBGraphicsScene : : toolLayerStart + 2 ) ;
button - > setFlag ( QGraphicsItem : : ItemIsSelectable , true ) ;
}
}
UBGraphicsItemDelegate : : ~ UBGraphicsItemDelegate ( )
{
qDeleteAll ( mButtons ) ;
// do not release mMimeData.
// the mMimeData is owned by QDrag since the setMimeData call as specified in the documentation
}
QVariant UBGraphicsItemDelegate : : itemChange ( QGraphicsItem : : GraphicsItemChange change , const QVariant & value )
{
if ( ( change = = QGraphicsItem : : ItemSelectedHasChanged
| | change = = QGraphicsItem : : ItemPositionHasChanged
| | change = = QGraphicsItem : : ItemTransformHasChanged )
& & mDelegated - > scene ( ) )
{
mAntiScaleRatio = 1 / ( UBApplication : : boardController - > systemScaleFactor ( ) * UBApplication : : boardController - > currentZoom ( ) ) ;
if ( mDelegated - > isSelected ( ) )
{
QList < QGraphicsItem * > items = mDelegated - > scene ( ) - > selectedItems ( ) ;
foreach ( QGraphicsItem * item , items )
{
if ( item ! = mDelegated )
{
item - > setSelected ( false ) ;
}
}
}
positionHandles ( ) ;
}
if ( change = = QGraphicsItem : : ItemPositionHasChanged
| | change = = QGraphicsItem : : ItemTransformHasChanged
| | change = = QGraphicsItem : : ItemZValueHasChanged )
{
UBGraphicsScene * ubScene = qobject_cast < UBGraphicsScene * > ( mDelegated - > scene ( ) ) ;
if ( ubScene )
ubScene - > setModified ( true ) ;
}
return value ;
}
bool UBGraphicsItemDelegate : : mousePressEvent ( QGraphicsSceneMouseEvent * event )
{
if ( NULL ! = mMimeData )
{
QDrag * mDrag = new QDrag ( event - > widget ( ) ) ;
mDrag - > setMimeData ( mMimeData ) ;
mDrag - > start ( ) ;
}
startUndoStep ( ) ;
if ( ! mDelegated - > isSelected ( ) )
{
mDelegated - > setSelected ( true ) ;
UBGraphicsScene * scene = static_cast < UBGraphicsScene * > ( mDelegated - > scene ( ) ) ;
qDebug ( ) < < mDelegated - > zValue ( ) ;
qDebug ( ) < < scene - > currentObjectZIndex ( ) ;
if ( mDelegated - > zValue ( ) < scene - > currentObjectZIndex ( ) & & ! isLocked ( ) )
mDelegated - > setZValue ( scene - > getNextObjectZIndex ( ) ) ;
positionHandles ( ) ;
return true ;
}
else
{
return false ;
}
}
void UBGraphicsItemDelegate : : setMimeData ( QMimeData * mimeData )
{
mMimeData = mimeData ;
}
bool UBGraphicsItemDelegate : : mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
{
if ( isLocked ( ) )
{
event - > accept ( ) ;
return true ;
}
else
return false ;
}
bool UBGraphicsItemDelegate : : weelEvent ( QGraphicsSceneWheelEvent * event )
{
Q_UNUSED ( event ) ;
if ( mDelegated - > isSelected ( ) )
{
// event->accept();
return true ;
}
else
{
// event->ignore();
return false ;
}
}
bool UBGraphicsItemDelegate : : mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
{
Q_UNUSED ( event ) ;
commitUndoStep ( ) ;
return true ;
}
void UBGraphicsItemDelegate : : positionHandles ( )
{
if ( mDelegated - > isSelected ( ) )
{
if ( mFrame & & ! mFrame - > scene ( ) & & mDelegated - > scene ( ) )
{
mDelegated - > scene ( ) - > addItem ( mFrame ) ;
}
mFrame - > setAntiScale ( mAntiScaleRatio ) ;
mFrame - > positionHandles ( ) ;
mFrame - > show ( ) ;
QTransform tr ;
tr . scale ( mAntiScaleRatio , mAntiScaleRatio ) ;
mDeleteButton - > setTransform ( tr ) ;
qreal x = mFrame - > rect ( ) . left ( ) - mDeleteButton - > renderer ( ) - > viewBox ( ) . width ( ) * mAntiScaleRatio / 2 ;
qreal y = mFrame - > rect ( ) . top ( ) - mDeleteButton - > renderer ( ) - > viewBox ( ) . height ( ) * mAntiScaleRatio / 2 ;
mDeleteButton - > setPos ( x , y ) ;
if ( ! mDeleteButton - > scene ( ) )
{
mDeleteButton - > setParentItem ( mFrame ) ; //update parent for the case the item has been previously removed from scene
if ( mDelegated - > scene ( ) )
mDelegated - > scene ( ) - > addItem ( mDeleteButton ) ;
}
mDeleteButton - > show ( ) ;
bool shownOnDisplay = mDelegated - > data ( UBGraphicsItemData : : ItemLayerType ) . toInt ( ) ! = UBItemLayerType : : Control ;
showHide ( shownOnDisplay ) ;
lock ( isLocked ( ) ) ;
for ( int i = 1 ; i < mButtons . length ( ) ; i + + )
{
DelegateButton * button = mButtons [ i ] ;
button - > setTransform ( tr ) ;
button - > setPos ( x + ( i * 1.6 * mFrameWidth * mAntiScaleRatio ) , y ) ;
if ( ! button - > scene ( ) )
{
button - > setParentItem ( mFrame ) ; //update parent for the case the item has been previously removed from scene
if ( mDelegated - > scene ( ) )
mDelegated - > scene ( ) - > addItem ( button ) ;
}
button - > show ( ) ;
}
}
else
{
foreach ( DelegateButton * button , mButtons )
button - > hide ( ) ;
mFrame - > hide ( ) ;
}
}
void UBGraphicsItemDelegate : : remove ( bool canUndo )
{
QGraphicsScene * scene = mDelegated - > scene ( ) ;
if ( scene )
{
foreach ( DelegateButton * button , mButtons )
scene - > removeItem ( button ) ;
scene - > removeItem ( mFrame ) ;
scene - > removeItem ( mDelegated ) ;
if ( canUndo )
{
UBGraphicsItemUndoCommand * uc = new UBGraphicsItemUndoCommand ( ( UBGraphicsScene * ) scene , mDelegated , 0 ) ;
UBApplication : : undoStack - > push ( uc ) ;
}
}
}
bool UBGraphicsItemDelegate : : isLocked ( )
{
return mDelegated - > data ( UBGraphicsItemData : : ItemLocked ) . toBool ( ) ;
}
void UBGraphicsItemDelegate : : duplicate ( )
{
// TODO UB 4.x .. rewrite .. .this is absurde ... we know what we are duplicating
UBApplication : : boardController - > copy ( ) ;
UBApplication : : boardController - > paste ( ) ;
}
void UBGraphicsItemDelegate : : lock ( bool locked )
{
if ( locked )
{
mDelegated - > setData ( UBGraphicsItemData : : ItemLocked , QVariant ( true ) ) ;
qDebug ( ) < < " item's data is called for locked " < < mDelegated - > data ( UBGraphicsItemData : : ItemLocked ) ;
}
else
{
mDelegated - > setData ( UBGraphicsItemData : : ItemLocked , QVariant ( false ) ) ;
qDebug ( ) < < " item's data is called for unlocked " < < mDelegated - > data ( UBGraphicsItemData : : ItemLocked ) ;
}
mDelegated - > update ( ) ;
mFrame - > positionHandles ( ) ;
}
void UBGraphicsItemDelegate : : showHide ( bool show )
{
if ( show )
{
mDelegated - > setData ( UBGraphicsItemData : : ItemLayerType , QVariant ( UBItemLayerType : : Object ) ) ;
}
else
{
mDelegated - > setData ( UBGraphicsItemData : : ItemLayerType , QVariant ( UBItemLayerType : : Control ) ) ;
}
mDelegated - > update ( ) ;
emit showOnDisplayChanged ( show ) ;
}
void UBGraphicsItemDelegate : : gotoContentSource ( bool checked )
{
Q_UNUSED ( checked )
UBItem * item = dynamic_cast < UBItem * > ( mDelegated ) ;
if ( item & & ! item - > sourceUrl ( ) . isEmpty ( ) )
{
UBApplication : : applicationController - > showInternet ( ) ;
UBApplication : : webController - > loadUrl ( item - > sourceUrl ( ) ) ;
}
}
void UBGraphicsItemDelegate : : startUndoStep ( )
{
mPreviousPosition = mDelegated - > pos ( ) ;
mPreviousTransform = mDelegated - > transform ( ) ;
mPreviousZValue = mDelegated - > zValue ( ) ;
UBResizableGraphicsItem * resizableItem = dynamic_cast < UBResizableGraphicsItem * > ( mDelegated ) ;
if ( resizableItem )
mPreviousSize = resizableItem - > size ( ) ;
else
mPreviousSize = QSizeF ( ) ;
}
void UBGraphicsItemDelegate : : commitUndoStep ( )
{
UBResizableGraphicsItem * resizableItem = dynamic_cast < UBResizableGraphicsItem * > ( mDelegated ) ;
if ( mDelegated - > pos ( ) ! = mPreviousPosition
| | mDelegated - > transform ( ) ! = mPreviousTransform
| | mDelegated - > zValue ( ) ! = mPreviousZValue
| | ( resizableItem & & resizableItem - > size ( ) ! = mPreviousSize ) )
{
UBGraphicsItemTransformUndoCommand * uc =
new UBGraphicsItemTransformUndoCommand ( mDelegated ,
mPreviousPosition ,
mPreviousTransform ,
mPreviousZValue ,
mPreviousSize ) ;
UBApplication : : undoStack - > push ( uc ) ;
}
}
void UBGraphicsItemDelegate : : decorateMenu ( QMenu * menu )
{
mLockAction = menu - > addAction ( tr ( " Locked " ) , this , SLOT ( lock ( bool ) ) ) ;
QIcon lockIcon ;
lockIcon . addPixmap ( QPixmap ( " :/images/locked.svg " ) , QIcon : : Normal , QIcon : : On ) ;
lockIcon . addPixmap ( QPixmap ( " :/images/unlocked.svg " ) , QIcon : : Normal , QIcon : : Off ) ;
mLockAction - > setIcon ( lockIcon ) ;
mLockAction - > setCheckable ( true ) ;
mShowOnDisplayAction = mMenu - > addAction ( tr ( " Visible on Extended Screen " ) , this , SLOT ( showHide ( bool ) ) ) ;
mShowOnDisplayAction - > setCheckable ( true ) ;
QIcon showIcon ;
showIcon . addPixmap ( QPixmap ( " :/images/eyeOpened.svg " ) , QIcon : : Normal , QIcon : : On ) ;
showIcon . addPixmap ( QPixmap ( " :/images/eyeClosed.svg " ) , QIcon : : Normal , QIcon : : Off ) ;
mShowOnDisplayAction - > setIcon ( showIcon ) ;
mGotoContentSourceAction = menu - > addAction ( tr ( " Go to Content Source " ) , this , SLOT ( gotoContentSource ( bool ) ) ) ;
QIcon sourceIcon ;
sourceIcon . addPixmap ( QPixmap ( " :/images/toolbar/internet.png " ) , QIcon : : Normal , QIcon : : On ) ;
mGotoContentSourceAction - > setIcon ( sourceIcon ) ;
}
void UBGraphicsItemDelegate : : updateMenuActionState ( )
{
if ( mLockAction )
mLockAction - > setChecked ( isLocked ( ) ) ;
if ( mShowOnDisplayAction )
{
bool isControl = mDelegated - > data ( UBGraphicsItemData : : ItemLayerType ) = = UBItemLayerType : : Control ;
mShowOnDisplayAction - > setChecked ( ! isControl ) ;
}
if ( mGotoContentSourceAction )
{
UBItem * item = dynamic_cast < UBItem * > ( mDelegated ) ;
mGotoContentSourceAction - > setEnabled ( item & & ! item - > sourceUrl ( ) . isEmpty ( ) ) ;
}
}
void UBGraphicsItemDelegate : : showMenu ( )
{
if ( ! mMenu )
{
mMenu = new QMenu ( UBApplication : : boardController - > controlView ( ) ) ;
decorateMenu ( mMenu ) ;
}
updateMenuActionState ( ) ;
UBBoardView * cv = UBApplication : : boardController - > controlView ( ) ;
QRect pinPos = cv - > mapFromScene ( mMenuButton - > sceneBoundingRect ( ) ) . boundingRect ( ) ;
mMenu - > exec ( cv - > mapToGlobal ( pinPos . bottomRight ( ) ) ) ;
}