2011-07-05 21:13:22 +02:00
/*
2012-05-04 14:01:29 +02:00
Copyright ( C ) 2010 by BetterInbox < contact @ betterinbox . com >
Original author : Gregory Schlomoff < greg @ betterinbox . com >
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the " Software " ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE .
2011-07-05 21:13:22 +02:00
*/
# include "DeclarativeDragArea.h"
# include "DeclarativeMimeData.h"
# include <QDrag>
# include <QMimeData>
# include <QGraphicsSceneMouseEvent>
# include <QApplication>
# include <QGraphicsScene>
# include <QGraphicsView>
2012-08-27 19:19:22 +02:00
# include <QDeclarativeContext>
2011-07-05 21:13:22 +02:00
/*!
2012-05-04 14:01:29 +02:00
A DragArea is used to make an item draggable .
2011-07-05 21:13:22 +02:00
*/
DeclarativeDragArea : : DeclarativeDragArea ( QDeclarativeItem * parent )
2012-05-04 14:01:29 +02:00
: QDeclarativeItem ( parent ) ,
m_delegate ( 0 ) ,
m_source ( 0 ) ,
m_target ( 0 ) ,
m_enabled ( true ) ,
m_supportedActions ( Qt : : MoveAction ) ,
m_defaultAction ( Qt : : MoveAction ) ,
m_data ( new DeclarativeMimeData ( ) ) // m_data is owned by us, and we shouldn't pass it to Qt directly as it will automatically delete it after the drag and drop.
2011-07-05 21:13:22 +02:00
{
2012-03-02 14:14:21 +01:00
m_startDragDistance = QApplication : : startDragDistance ( ) ;
2012-05-04 14:01:29 +02:00
setAcceptedMouseButtons ( Qt : : LeftButton ) ;
2011-12-15 18:45:15 +01:00
setFiltersChildEvents ( true ) ;
2011-07-05 21:13:22 +02:00
}
DeclarativeDragArea : : ~ DeclarativeDragArea ( )
{
2012-05-04 14:01:29 +02:00
if ( m_data ) {
delete m_data ;
}
2011-07-05 21:13:22 +02:00
}
/*!
The delegate is the item that will be displayed next to the mouse cursor during the drag and drop operation .
It usually consists of a large , semi - transparent icon representing the data being dragged .
*/
QDeclarativeComponent * DeclarativeDragArea : : delegate ( ) const
{
2012-05-04 14:01:29 +02:00
return m_delegate ;
2011-07-05 21:13:22 +02:00
}
2012-05-04 14:08:50 +02:00
2011-07-05 21:13:22 +02:00
void DeclarativeDragArea : : setDelegate ( QDeclarativeComponent * delegate )
{
2012-05-04 14:01:29 +02:00
if ( m_delegate ! = delegate ) {
m_delegate = delegate ;
emit delegateChanged ( ) ;
}
2011-07-05 21:13:22 +02:00
}
void DeclarativeDragArea : : resetDelegate ( )
{
2012-05-04 14:01:29 +02:00
setDelegate ( 0 ) ;
2011-07-05 21:13:22 +02:00
}
/*!
The QML element that is the source of this drag and drop operation . This can be defined to any item , and will
be available to the DropArea as event . data . source
*/
QDeclarativeItem * DeclarativeDragArea : : source ( ) const
{
2012-05-04 14:01:29 +02:00
return m_source ;
2011-07-05 21:13:22 +02:00
}
2012-05-04 14:08:50 +02:00
2011-07-05 21:13:22 +02:00
void DeclarativeDragArea : : setSource ( QDeclarativeItem * source )
{
2012-05-04 14:01:29 +02:00
if ( m_source ! = source ) {
m_source = source ;
emit sourceChanged ( ) ;
}
2011-07-05 21:13:22 +02:00
}
2012-05-04 14:08:50 +02:00
2011-07-05 21:13:22 +02:00
void DeclarativeDragArea : : resetSource ( )
{
2012-05-04 14:01:29 +02:00
setSource ( 0 ) ;
2011-07-05 21:13:22 +02:00
}
// target
QDeclarativeItem * DeclarativeDragArea : : target ( ) const
{
2012-05-04 14:01:29 +02:00
//TODO: implement me
return 0 ;
2011-07-05 21:13:22 +02:00
}
// data
2011-12-15 18:28:57 +01:00
DeclarativeMimeData * DeclarativeDragArea : : mimeData ( ) const
2011-07-05 21:13:22 +02:00
{
2012-05-04 14:01:29 +02:00
return m_data ;
2011-07-05 21:13:22 +02:00
}
2012-03-02 14:14:21 +01:00
// startDragDistance
int DeclarativeDragArea : : startDragDistance ( ) const
{
return m_startDragDistance ;
}
void DeclarativeDragArea : : setStartDragDistance ( int distance )
{
if ( distance = = m_startDragDistance ) {
return ;
}
m_startDragDistance = distance ;
emit startDragDistanceChanged ( ) ;
}
2012-03-02 15:07:29 +01:00
// delegateImage
QVariant DeclarativeDragArea : : delegateImage ( ) const
{
return m_delegateImage ;
}
void DeclarativeDragArea : : setDelegateImage ( const QVariant & image )
{
if ( image . canConvert < QImage > ( ) & & image . value < QImage > ( ) = = m_delegateImage ) {
return ;
}
if ( image . canConvert < QImage > ( ) ) {
m_delegateImage = image . value < QImage > ( ) ;
} else {
m_delegateImage = image . value < QIcon > ( ) . pixmap ( QSize ( 48 , 48 ) ) . toImage ( ) ;
}
emit delegateImageChanged ( ) ;
}
2011-07-05 21:13:22 +02:00
// enabled
bool DeclarativeDragArea : : isEnabled ( ) const
{
2012-05-04 14:01:29 +02:00
return m_enabled ;
2011-07-05 21:13:22 +02:00
}
void DeclarativeDragArea : : setEnabled ( bool enabled )
{
2012-05-04 14:01:29 +02:00
if ( enabled ! = m_enabled ) {
m_enabled = enabled ;
emit enabledChanged ( ) ;
}
2011-07-05 21:13:22 +02:00
}
// supported actions
Qt : : DropActions DeclarativeDragArea : : supportedActions ( ) const
{
2012-05-04 14:01:29 +02:00
return m_supportedActions ;
2011-07-05 21:13:22 +02:00
}
void DeclarativeDragArea : : setSupportedActions ( Qt : : DropActions actions )
{
2012-05-04 14:01:29 +02:00
if ( actions ! = m_supportedActions ) {
m_supportedActions = actions ;
emit supportedActionsChanged ( ) ;
}
2011-07-05 21:13:22 +02:00
}
// default action
Qt : : DropAction DeclarativeDragArea : : defaultAction ( ) const
{
2012-05-04 14:01:29 +02:00
return m_defaultAction ;
2011-07-05 21:13:22 +02:00
}
void DeclarativeDragArea : : setDefaultAction ( Qt : : DropAction action )
{
2012-05-04 14:01:29 +02:00
if ( action ! = m_defaultAction ) {
m_defaultAction = action ;
emit defaultActionChanged ( ) ;
}
2011-07-05 21:13:22 +02:00
}
void DeclarativeDragArea : : mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
{
2012-05-04 14:01:29 +02:00
if ( ! m_enabled
| | QLineF ( event - > screenPos ( ) , event - > buttonDownScreenPos ( Qt : : LeftButton ) ) . length ( )
< m_startDragDistance ) {
return ;
}
2011-07-05 21:13:22 +02:00
2012-05-04 14:08:50 +02:00
emit dragStarted ( ) ;
2012-05-04 14:01:29 +02:00
QDrag * drag = new QDrag ( event - > widget ( ) ) ;
DeclarativeMimeData * dataCopy = new DeclarativeMimeData ( m_data ) ; //Qt will take ownership of this copy and delete it.
drag - > setMimeData ( dataCopy ) ;
2011-07-05 21:13:22 +02:00
2012-03-02 15:07:29 +01:00
if ( ! m_delegateImage . isNull ( ) ) {
drag - > setPixmap ( QPixmap : : fromImage ( m_delegateImage ) ) ;
} else if ( m_delegate ) {
2012-05-04 14:01:29 +02:00
// Render the delegate to a Pixmap
2012-08-27 19:19:22 +02:00
QDeclarativeItem * item = qobject_cast < QDeclarativeItem * > ( m_delegate - > create ( m_delegate - > creationContext ( ) ) ) ;
2011-07-05 21:13:22 +02:00
2012-05-04 14:01:29 +02:00
QGraphicsScene scene ;
scene . addItem ( item ) ;
2011-07-05 21:13:22 +02:00
2012-05-04 14:01:29 +02:00
QPixmap pixmap ( scene . sceneRect ( ) . width ( ) , scene . sceneRect ( ) . height ( ) ) ;
pixmap . fill ( Qt : : transparent ) ;
2011-07-05 21:13:22 +02:00
2012-05-04 14:01:29 +02:00
QPainter painter ( & pixmap ) ;
painter . setRenderHint ( QPainter : : Antialiasing ) ;
2012-08-27 19:19:22 +02:00
painter . setRenderHint ( QPainter : : SmoothPixmapTransform ) ;
2012-05-04 14:01:29 +02:00
scene . render ( & painter ) ;
2012-03-02 14:14:21 +01:00
painter . end ( ) ;
delete item ;
2011-07-05 21:13:22 +02:00
2012-05-04 14:01:29 +02:00
drag - > setPixmap ( pixmap ) ;
}
2011-07-05 21:13:22 +02:00
2012-08-27 19:51:04 +02:00
drag - > setHotSpot ( QPoint ( drag - > pixmap ( ) . width ( ) / 2 , 0 ) ) ; // TODO: Make a property for that
2012-05-04 14:01:29 +02:00
//setCursor(Qt::OpenHandCursor); //TODO? Make a property for the cursor
2011-07-05 21:13:22 +02:00
2012-05-04 14:01:29 +02:00
Qt : : DropAction action = drag - > exec ( m_supportedActions , m_defaultAction ) ;
emit drop ( action ) ;
2011-07-05 21:13:22 +02:00
}
2011-12-15 18:45:15 +01:00
bool DeclarativeDragArea : : sceneEventFilter ( QGraphicsItem * item , QEvent * event )
{
if ( ! isEnabled ( ) ) {
return false ;
}
if ( event - > type ( ) = = QEvent : : GraphicsSceneMouseMove ) {
QGraphicsSceneMouseEvent * me = static_cast < QGraphicsSceneMouseEvent * > ( event ) ;
mouseMoveEvent ( me ) ;
}
return QDeclarativeItem : : sceneEventFilter ( item , event ) ;
2012-05-04 14:08:50 +02:00
}