25 #include <QVBoxLayout>
33 class TokenDragger :
public QObject
39 bool eventFilter(
QObject *o, QEvent *e )
41 if ( e->type() == QEvent::MouseMove )
43 if ( static_cast<QMouseEvent*>(e)->buttons() & Qt::LeftButton )
44 return drag( qobject_cast<Token*>(o) );
46 else if ( e->type() == QEvent::MouseButtonPress )
48 if ( static_cast<QMouseEvent*>(e)->buttons() & Qt::LeftButton )
50 setCursor( qobject_cast<QWidget*>(o), Qt::ClosedHandCursor );
56 else if ( e->type() == QEvent::MouseButtonRelease )
58 if ( static_cast<QMouseEvent*>(e)->buttons() & Qt::LeftButton )
59 setCursor( qobject_cast<QWidget*>(o), Qt::OpenHandCursor );
62 else if ( e->type() == QEvent::FocusIn )
63 emit static_cast<TokenDropTarget*>( parent() )->focussed( qobject_cast<QWidget*>(o) );
64 else if ( e->type() == QEvent::Hide )
66 setCursor( qobject_cast<QWidget*>(o), Qt::OpenHandCursor );
73 bool drag(
Token *token )
79 bool stacked = token->parentWidget() && qobject_cast<
TokenDropTarget*>( token->parentWidget() );
83 QPixmap pixmap( token->size() );
84 token->render( &pixmap );
85 QDrag *drag =
new QDrag( token );
86 QMimeData *data =
new QMimeData;
89 QDataStream dataStream( &itemData, QIODevice::WriteOnly );
92 data->setData( m_mimeType, itemData );
93 drag->setMimeData( data );
94 drag->setPixmap( pixmap );
95 drag->setHotSpot ( pixmap.rect().center() );
97 Qt::DropAction dropAction = drag->exec( Qt::CopyAction | Qt::MoveAction, Qt::CopyAction );
101 if ( dropAction != Qt::MoveAction && dropAction != Qt::CopyAction )
113 inline void setCursor(
QWidget *w, Qt::CursorShape shape )
117 w->setCursor( shape );
126 m_tokenDragger( new TokenDragger( mimeType, this ) ),
129 new QVBoxLayout(
this );
130 m_mimeType = mimeType;
131 m_limits[0] = m_limits[1] = 0;
133 parent->setAcceptDrops(
true);
135 parent->removeEventFilter(
this );
136 parent->installEventFilter(
this );
139 layout()->setSpacing( 0 );
141 layout()->addItem(
new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::MinimumExpanding ) );
145 TokenDropTarget::accept( QDropEvent *de )
147 if ( !de->mimeData()->hasFormat( m_mimeType ) )
153 if ( de->source() && parentWidget() && de->source()->parentWidget() == parentWidget() )
155 de->setDropAction(Qt::MoveAction);
159 de->acceptProposedAction();
164 TokenDropTarget::appendRow()
166 QHBoxLayout *box =
new QHBoxLayout;
167 box->setSpacing( 0 );
169 static_cast<QVBoxLayout*
>(layout())->insertLayout( layout()->count() - 1, box );
177 if ( QHBoxLayout *
rowBox = qobject_cast<QHBoxLayout*>( layout()->itemAt(
row )->layout() ) )
178 for (
int col = 0; col <
rowBox->count(); ++col )
180 if ( kid->geometry().contains( pos ) )
188 QLayoutItem *
row, *col;
189 while( ( row = layout()->takeAt( 0 ) ) )
191 if ( QLayout *layout = row->layout() )
193 while( ( col = layout->takeAt( 0 ) ) )
195 delete col->widget();
202 layout()->addItem(
new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::MinimumExpanding ) );
208 int lower = 0, upper =
rows();
209 if ( row > -1 && row <
rows() )
216 for ( row = lower; row < upper; ++
row )
217 if ( QHBoxLayout *
rowBox = qobject_cast<QHBoxLayout*>( layout()->itemAt( row )->layout() ) )
228 box = qobject_cast<QBoxLayout*>( layout()->itemAt(
row )->layout() );
229 if ( box && box->count() < 2 )
231 layout()->removeItem( box );
242 int lower = 0, upper =
rows();
243 if ( row > -1 && row <
rows() )
249 QList< Token *> list;
251 for ( row = lower; row < upper; ++
row )
252 if ( QHBoxLayout *
rowBox = qobject_cast<QHBoxLayout*>( layout()->itemAt( row )->layout() ) )
254 for (
int col = 0; col <
rowBox->count() - 1; ++col )
255 if ( ( token = qobject_cast<Token*>(
rowBox->itemAt( col )->widget() ) ) )
263 TokenDropTarget::drop(
Token *token,
const QPoint &pos )
269 if ( QBoxLayout *box =
rowBox( token ) )
270 box->removeWidget( token );
271 token->setParent( parentWidget() );
274 if (
Token *brother = qobject_cast<Token*>(
childAt( pos ) ) )
277 box =
rowBox( brother, &idx );
278 if ( pos.x() > brother->geometry().x() + 2*brother->width()/3 )
279 box->insertWidget( idx.x() + 1, token );
281 box->insertWidget( idx.x(), token );
286 box = qobject_cast<QBoxLayout*>( layout()->itemAt(
rows() - 1 )->layout() );
294 int idx = ( box->count() > 1 && box->itemAt(0)->widget() &&
295 pos.x() < box->itemAt(0)->widget()->geometry().x() ) ? 0 : box->count() - 1;
296 box->insertWidget( idx, token );
307 if ( ev->type() == QEvent::DragMove ||
308 ev->type() == QEvent::DragEnter )
310 accept( static_cast<QDropEvent*>( ev ) );
315 if ( ev->type() == QEvent::Drop )
317 QDropEvent *de =
static_cast<QDropEvent*
>( ev );
320 Token *token = qobject_cast<
Token*>( de->source() );
323 QByteArray itemData = de->mimeData()->data( m_mimeType );
324 QDataStream dataStream(&itemData, QIODevice::ReadOnly);
327 QString tokenIconName;
329 dataStream >> tokenName;
330 dataStream >> tokenIconName;
331 dataStream >> tokenValue;
333 token = m_tokenFactory->
createToken( tokenName, tokenIconName, tokenValue,
this );
334 token->removeEventFilter( m_tokenDragger );
335 token->installEventFilter( m_tokenDragger );
336 token->setCursor( Qt::OpenHandCursor );
338 drop( token, de->pos() );
349 if ( row >
rows() - 1 )
352 box = qobject_cast<QBoxLayout*>( layout()->itemAt( row )->layout() );
353 token->setParent( parentWidget() );
354 if ( col < 0 || col > box->count() - 2 )
355 col = box->count() - 1;
356 box->insertWidget( col, token );
357 token->removeEventFilter( m_tokenDragger );
358 token->installEventFilter( m_tokenDragger );
359 token->setCursor( Qt::OpenHandCursor );
367 QBoxLayout *box = qobject_cast<QBoxLayout*>( layout()->itemAt(
row )->layout() );
368 if ( box && ( box->indexOf( token ) ) > -1 )
377 return layout()->count() - 1;
387 box = qobject_cast<QBoxLayout*>( layout()->itemAt(
row )->layout() );
388 if ( box && ( col = box->indexOf( w ) ) > -1 )
407 box = qobject_cast<QBoxLayout*>( layout()->itemAt(
row )->layout() );
410 for (
int col = 0; col < box->count(); ++col )
412 if (
QWidget *w = box->itemAt( col )->widget() )
414 const QRect &geo = w->geometry();
415 if ( geo.y() <= pt.y() && geo.bottom() >= pt.y() )
427 delete m_tokenFactory;
428 m_tokenFactory = factory;
void setCustomTokenFactory(TokenFactory *factory)
QWidget * childAt(const QPoint &pos) const
bool eventFilter(QObject *, QEvent *)
virtual int count() const
QBoxLayout * rowBox(QWidget *w, QPoint *idx=0) const
TokenDropTarget(const QString &mimeType, QWidget *parent=0)
void insertToken(Token *, int row=-1, int col=-1)
virtual Token * createToken(const QString &text, const QString &iconName, int value, QWidget *parent=0)
QList< Token * > drags(int row=-1)