/*
* 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 "UBDocumentThumbnailWidget.h"
# include "core/UBApplication.h"
# include "core/UBMimeData.h"
# include "core/UBSettings.h"
# include "board/UBBoardController.h"
# include "document/UBDocumentController.h"
# include "core/memcheck.h"
UBDocumentThumbnailWidget : : UBDocumentThumbnailWidget ( QWidget * parent )
: UBThumbnailWidget ( parent )
, mDropCaretRectItem ( 0 )
, mClosestDropItem ( 0 )
, mDragEnabled ( true )
, mScrollMagnitude ( 0 )
{
mScrollTimer = new QTimer ( this ) ;
connect ( mScrollTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( autoScroll ( ) ) ) ;
}
UBDocumentThumbnailWidget : : ~ UBDocumentThumbnailWidget ( )
{
// NOOP
}
void UBDocumentThumbnailWidget : : mouseMoveEvent ( QMouseEvent * event )
{
if ( ! dragEnabled ( ) )
{
event - > ignore ( ) ;
return ;
}
if ( ! ( event - > buttons ( ) & Qt : : LeftButton ) )
return ;
if ( ( event - > pos ( ) - mMousePressPos ) . manhattanLength ( ) < QApplication : : startDragDistance ( ) )
return ;
QList < QGraphicsItem * > graphicsItems = items ( mMousePressPos ) ;
UBSceneThumbnailPixmap * sceneItem = 0 ;
while ( ! graphicsItems . isEmpty ( ) & & ! sceneItem )
sceneItem = dynamic_cast < UBSceneThumbnailPixmap * > ( graphicsItems . takeFirst ( ) ) ;
if ( sceneItem )
{
int pageIndex = UBApplication : : boardController - > pageFromSceneIndex ( sceneItem - > sceneIndex ( ) ) ;
if ( pageIndex ! = 0 ) {
QDrag * drag = new QDrag ( this ) ;
QList < UBMimeDataItem > mimeDataItems ;
foreach ( QGraphicsItem * item , selectedItems ( ) )
mimeDataItems . append ( UBMimeDataItem ( sceneItem - > proxy ( ) , mGraphicItems . indexOf ( item ) ) ) ;
UBMimeData * mime = new UBMimeData ( mimeDataItems ) ;
drag - > setMimeData ( mime ) ;
drag - > setPixmap ( sceneItem - > pixmap ( ) . scaledToWidth ( 100 ) ) ;
drag - > setHotSpot ( QPoint ( drag - > pixmap ( ) . width ( ) / 2 , drag - > pixmap ( ) . height ( ) / 2 ) ) ;
drag - > exec ( Qt : : MoveAction ) ;
}
}
UBThumbnailWidget : : mouseMoveEvent ( event ) ;
}
void UBDocumentThumbnailWidget : : dragEnterEvent ( QDragEnterEvent * event )
{
if ( ! event - > mimeData ( ) - > hasFormat ( UBApplication : : mimeTypeUniboardPage ) )
{
event - > setDropAction ( Qt : : IgnoreAction ) ;
event - > ignore ( ) ;
return ;
}
UBThumbnailWidget : : dragEnterEvent ( event ) ;
}
void UBDocumentThumbnailWidget : : dragLeaveEvent ( QDragLeaveEvent * event )
{
Q_UNUSED ( event ) ;
if ( mScrollTimer - > isActive ( ) )
{
mScrollMagnitude = 0 ;
mScrollTimer - > stop ( ) ;
}
deleteDropCaret ( ) ;
UBThumbnailWidget : : dragLeaveEvent ( event ) ;
}
void UBDocumentThumbnailWidget : : autoScroll ( )
{
this - > verticalScrollBar ( ) - > setValue ( this - > verticalScrollBar ( ) - > value ( ) + mScrollMagnitude ) ;
}
void UBDocumentThumbnailWidget : : dragMoveEvent ( QDragMoveEvent * event )
{
QRect boundingFrame = frameRect ( ) ;
//setting up automatic scrolling
const int SCROLL_DISTANCE = 16 ;
int bottomDist = boundingFrame . bottom ( ) - event - > pos ( ) . y ( ) , topDist = boundingFrame . top ( ) - event - > pos ( ) . y ( ) ;
if ( qAbs ( bottomDist ) < = SCROLL_DISTANCE )
{
mScrollMagnitude = ( SCROLL_DISTANCE - bottomDist ) * 4 ;
if ( verticalScrollBar ( ) - > isVisible ( ) & & ! mScrollTimer - > isActive ( ) ) mScrollTimer - > start ( 100 ) ;
}
else if ( qAbs ( topDist ) < = SCROLL_DISTANCE )
{
mScrollMagnitude = ( - SCROLL_DISTANCE - topDist ) * 4 ;
if ( verticalScrollBar ( ) - > isVisible ( ) & & ! mScrollTimer - > isActive ( ) ) mScrollTimer - > start ( 100 ) ;
}
else
{
mScrollMagnitude = 0 ;
mScrollTimer - > stop ( ) ;
}
QList < UBSceneThumbnailPixmap * > pixmapItems ;
foreach ( QGraphicsItem * item , scene ( ) - > items ( mapToScene ( boundingFrame ) ) )
{
UBSceneThumbnailPixmap * sceneItem = dynamic_cast < UBSceneThumbnailPixmap * > ( item ) ;
if ( sceneItem )
pixmapItems . append ( sceneItem ) ;
}
int minDistance = 0 ;
QGraphicsItem * underlyingItem = itemAt ( event - > pos ( ) ) ;
mClosestDropItem = dynamic_cast < UBSceneThumbnailPixmap * > ( underlyingItem ) ;
int pageIndex = - 1 ;
if ( mClosestDropItem ) {
pageIndex = UBApplication : : boardController - > pageFromSceneIndex ( mClosestDropItem - > sceneIndex ( ) ) ;
if ( pageIndex = = 0 ) {
event - > acceptProposedAction ( ) ;
return ;
}
}
if ( ! mClosestDropItem )
{
foreach ( UBSceneThumbnailPixmap * item , pixmapItems )
{
qreal scale = item - > transform ( ) . m11 ( ) ;
QPointF itemCenter (
item - > pos ( ) . x ( ) + item - > boundingRect ( ) . width ( ) * scale / 2 ,
item - > pos ( ) . y ( ) + item - > boundingRect ( ) . height ( ) * scale / 2 ) ;
int distance = ( itemCenter . toPoint ( ) - mapToScene ( event - > pos ( ) ) . toPoint ( ) ) . manhattanLength ( ) ;
if ( ! mClosestDropItem | | distance < minDistance )
{
mClosestDropItem = item ;
minDistance = distance ;
pageIndex = UBApplication : : boardController - > pageFromSceneIndex ( mClosestDropItem - > sceneIndex ( ) ) ;
}
}
}
if ( mClosestDropItem & & pageIndex ! = 0 )
{
qreal scale = mClosestDropItem - > transform ( ) . m11 ( ) ;
QPointF itemCenter (
mClosestDropItem - > pos ( ) . x ( ) + mClosestDropItem - > boundingRect ( ) . width ( ) * scale / 2 ,
mClosestDropItem - > pos ( ) . y ( ) + mClosestDropItem - > boundingRect ( ) . height ( ) * scale / 2 ) ;
mDropIsRight = mapToScene ( event - > pos ( ) ) . x ( ) > itemCenter . x ( ) ;
if ( ! mDropCaretRectItem & & selectedItems ( ) . count ( ) < mGraphicItems . count ( ) )
{
mDropCaretRectItem = new QGraphicsRectItem ( 0 , scene ( ) ) ;
mDropCaretRectItem - > setPen ( QPen ( Qt : : darkGray ) ) ;
mDropCaretRectItem - > setBrush ( QBrush ( Qt : : lightGray ) ) ;
}
QRectF dropCaretRect (
mDropIsRight ? mClosestDropItem - > pos ( ) . x ( ) + mClosestDropItem - > boundingRect ( ) . width ( ) * scale + spacing ( ) / 2 - 1 : mClosestDropItem - > pos ( ) . x ( ) - spacing ( ) / 2 - 1 ,
mClosestDropItem - > pos ( ) . y ( ) ,
3 ,
mClosestDropItem - > boundingRect ( ) . height ( ) * scale ) ;
if ( mDropCaretRectItem )
mDropCaretRectItem - > setRect ( dropCaretRect ) ;
}
event - > acceptProposedAction ( ) ;
}
void UBDocumentThumbnailWidget : : dropEvent ( QDropEvent * event )
{
if ( mScrollTimer - > isActive ( ) )
{
mScrollMagnitude = 0 ;
mScrollTimer - > stop ( ) ;
}
deleteDropCaret ( ) ;
if ( mClosestDropItem )
{
int targetIndex = mDropIsRight ? mGraphicItems . indexOf ( mClosestDropItem ) + 1 : mGraphicItems . indexOf ( mClosestDropItem ) ;
if ( UBApplication : : boardController - > pageFromSceneIndex ( targetIndex ) = = 0 ) {
event - > ignore ( ) ;
return ;
}
QList < UBMimeDataItem > mimeDataItems ;
if ( event - > mimeData ( ) - > hasFormat ( UBApplication : : mimeTypeUniboardPage ) )
{
const UBMimeData * mimeData = qobject_cast < const UBMimeData * > ( event - > mimeData ( ) ) ;
if ( mimeData )
mimeDataItems = mimeData - > items ( ) ;
}
if ( 1 = = mimeDataItems . count ( ) & &
( mimeDataItems . at ( 0 ) . sceneIndex ( ) = = mGraphicItems . indexOf ( mClosestDropItem ) | |
targetIndex = = mimeDataItems . at ( 0 ) . sceneIndex ( ) | |
targetIndex = = mimeDataItems . at ( 0 ) . sceneIndex ( ) + 1 ) )
{
return ;
}
int sourceIndexOffset = 0 ;
int actualTargetIndex = targetIndex ;
for ( int i = mimeDataItems . count ( ) - 1 ; i > = 0 ; i - - )
{
UBMimeDataItem sourceItem = mimeDataItems . at ( i ) ;
int actualSourceIndex = sourceItem . sceneIndex ( ) ;
if ( sourceItem . sceneIndex ( ) > = targetIndex )
actualSourceIndex + = sourceIndexOffset ;
event - > acceptProposedAction ( ) ;
if ( sourceItem . sceneIndex ( ) < targetIndex )
{
if ( actualSourceIndex ! = actualTargetIndex - 1 )
emit sceneDropped ( sourceItem . documentProxy ( ) , actualSourceIndex , actualTargetIndex - 1 ) ;
actualTargetIndex - = 1 ;
}
else
{
if ( actualSourceIndex ! = actualTargetIndex )
emit sceneDropped ( sourceItem . documentProxy ( ) , actualSourceIndex , actualTargetIndex ) ;
sourceIndexOffset + = 1 ;
}
}
}
}
void UBDocumentThumbnailWidget : : deleteDropCaret ( )
{
if ( mDropCaretRectItem & & scene ( ) )
{
scene ( ) - > removeItem ( mDropCaretRectItem ) ;
delete mDropCaretRectItem ;
mDropCaretRectItem = 0 ;
}
}
void UBDocumentThumbnailWidget : : setGraphicsItems ( const QList < QGraphicsItem * > & pGraphicsItems ,
const QList < QUrl > & pItemPaths , const QStringList pLabels ,
const QString & pMimeType )
{
deleteDropCaret ( ) ;
UBThumbnailWidget : : setGraphicsItems ( pGraphicsItems , pItemPaths , pLabels , pMimeType ) ;
}
void UBDocumentThumbnailWidget : : setDragEnabled ( bool enabled )
{
mDragEnabled = enabled ;
}
bool UBDocumentThumbnailWidget : : dragEnabled ( ) const
{
return mDragEnabled ;
}
void UBDocumentThumbnailWidget : : hightlightItem ( int index )
{
if ( 0 < = index & & index < mLabelsItems . length ( ) )
{
mLabelsItems . at ( index ) - > highlight ( ) ;
}
if ( 0 < = index & & index < mGraphicItems . length ( ) )
{
UBSceneThumbnailPixmap * thumbnail = dynamic_cast < UBSceneThumbnailPixmap * > ( mGraphicItems . at ( index ) ) ;
if ( thumbnail )
thumbnail - > highlight ( ) ;
}
selectItemAt ( index ) ;
}