You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
8.0 KiB
313 lines
8.0 KiB
13 years ago
|
/**********************************************************************
|
||
|
** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
|
||
|
**
|
||
|
** This file is part of Qt Designer.
|
||
|
**
|
||
|
** This file may be used under the terms of the GNU General
|
||
|
** Public License versions 2.0 or 3.0 as published by the Free
|
||
|
** Software Foundation and appearing in the files LICENSE.GPL2
|
||
|
** and LICENSE.GPL3 included in the packaging of this file.
|
||
|
** Alternatively you may (at your option) use any later version
|
||
|
** of the GNU General Public License if such license has been
|
||
|
** publicly approved by Trolltech ASA (or its successors, if any)
|
||
|
** and the KDE Free Qt Foundation.
|
||
|
**
|
||
|
** Please review the following information to ensure GNU General
|
||
|
** Public Licensing requirements will be met:
|
||
|
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
|
||
|
** If you are unsure which license is appropriate for your use, please
|
||
|
** review the following information:
|
||
|
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
|
||
|
** or contact the sales department at sales@trolltech.com.
|
||
|
**
|
||
|
** Licensees holding valid Qt Commercial licenses may use this file in
|
||
|
** accordance with the Qt Commercial License Agreement provided with
|
||
|
** the Software.
|
||
|
**
|
||
|
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
|
||
|
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
|
||
|
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
|
||
|
** herein.
|
||
|
**
|
||
|
**********************************************************************/
|
||
|
|
||
|
#include "listboxdnd.h"
|
||
|
#include <qwidget.h>
|
||
|
#include <qheader.h>
|
||
|
#include <qpainter.h>
|
||
|
#include <qdragobject.h>
|
||
|
#include <qvaluelist.h>
|
||
|
|
||
|
// The Dragobject Declaration ---------------------------------------
|
||
|
class ListBoxItemDrag : public QStoredDrag
|
||
|
{
|
||
|
public:
|
||
|
ListBoxItemDrag( ListBoxItemList & items, bool sendPtr = FALSE, QListBox * parent = 0, const char * name = 0 );
|
||
|
~ListBoxItemDrag() {};
|
||
|
static bool canDecode( QDragMoveEvent * event );
|
||
|
static bool decode( QDropEvent * event, QListBox * parent, QListBoxItem * insertPoint );
|
||
|
enum ItemType { ListBoxText = 1, ListBoxPixmap = 2 };
|
||
|
};
|
||
|
// ------------------------------------------------------------------
|
||
|
|
||
|
ListBoxDnd::ListBoxDnd( QListBox * eventSource, const char * name )
|
||
|
: ListDnd( eventSource, name ) { }
|
||
|
|
||
|
void ListBoxDnd::confirmDrop( QListBoxItem * )
|
||
|
{
|
||
|
dropConfirmed = TRUE;
|
||
|
}
|
||
|
|
||
|
bool ListBoxDnd::dropEvent( QDropEvent * event )
|
||
|
{
|
||
|
if ( dragInside ) {
|
||
|
|
||
|
if ( dMode & NullDrop ) { // combined with Move, a NullDrop will delete an item
|
||
|
event->accept();
|
||
|
emit dropped( 0 ); // a NullDrop
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
QPoint pos = event->pos();
|
||
|
QListBoxItem * after = itemAt( pos );
|
||
|
|
||
|
if ( ListBoxItemDrag::decode( event, (QListBox *) src, after ) ) {
|
||
|
event->accept();
|
||
|
QListBox * src = (QListBox *) this->src;
|
||
|
QListBoxItem * item = ( after ? after->next() : src->firstItem() );
|
||
|
src->setCurrentItem( item );
|
||
|
emit dropped( item ); // ###FIX: Supports only one item!
|
||
|
}
|
||
|
}
|
||
|
|
||
|
line->hide();
|
||
|
dragInside = FALSE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
bool ListBoxDnd::mouseMoveEvent( QMouseEvent * event )
|
||
|
{
|
||
|
if ( event->state() & LeftButton ) {
|
||
|
if ( ( event->pos() - mousePressPos ).manhattanLength() > 3 ) {
|
||
|
|
||
|
ListBoxItemList list;
|
||
|
buildList( list );
|
||
|
ListBoxItemDrag * dragobject = new ListBoxItemDrag( list, (dMode & Internal), (QListBox *) src );
|
||
|
|
||
|
// Emit signal for all dragged items
|
||
|
QListBoxItem * i = list.first();
|
||
|
while ( i ) {
|
||
|
emit dragged( i );
|
||
|
i = list.next();
|
||
|
}
|
||
|
|
||
|
if ( dMode & Move ) {
|
||
|
removeList( list ); // "hide" items
|
||
|
}
|
||
|
|
||
|
dragobject->dragCopy();
|
||
|
|
||
|
if ( dMode & Move ) {
|
||
|
if ( dropConfirmed ) {
|
||
|
// ###FIX: memleak ? in internal mode, only pointers are transfered...
|
||
|
//list.setAutoDelete( TRUE );
|
||
|
list.clear();
|
||
|
dropConfirmed = FALSE;
|
||
|
}
|
||
|
insertList( list ); // "show" items
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
int ListBoxDnd::buildList( ListBoxItemList & list )
|
||
|
{
|
||
|
QListBoxItem * i = ((QListBox *)src)->firstItem();
|
||
|
while ( i ) {
|
||
|
if ( i->isSelected() ) {
|
||
|
((QListBox *)src)->setSelected( i, FALSE );
|
||
|
list.append( i );
|
||
|
}
|
||
|
i = i->next();
|
||
|
}
|
||
|
return list.count();
|
||
|
}
|
||
|
|
||
|
void ListBoxDnd::insertList( ListBoxItemList & list )
|
||
|
{
|
||
|
QListBoxItem * i = list.first();
|
||
|
while ( i ) {
|
||
|
((QListBox *)src)->insertItem( i, i->prev() );
|
||
|
i = list.next();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ListBoxDnd::removeList( ListBoxItemList & list )
|
||
|
{
|
||
|
QListBoxItem * i = list.first();
|
||
|
while ( i ) {
|
||
|
((QListBox *)src)->takeItem( i ); // remove item from QListBox
|
||
|
i = list.next();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ListBoxDnd::updateLine( const QPoint & dragPos )
|
||
|
{
|
||
|
QListBox * src = (QListBox *) this->src;
|
||
|
QListBoxItem *item = itemAt( dragPos );
|
||
|
|
||
|
int ypos = item ?
|
||
|
( src->itemRect( item ).bottom() - ( line->height() / 2 ) ) :
|
||
|
( src->itemRect( ((QListBox *)src)->firstItem() ).top() );
|
||
|
|
||
|
line->resize( src->viewport()->width(), line->height() );
|
||
|
line->move( 0, ypos );
|
||
|
}
|
||
|
|
||
|
QListBoxItem * ListBoxDnd::itemAt( QPoint pos )
|
||
|
{
|
||
|
QListBox * src = (QListBox *) this->src;
|
||
|
QListBoxItem * result = src->itemAt( pos );
|
||
|
QListBoxItem * last = src->item( src->count() - 1 );
|
||
|
int i = src->index( result );
|
||
|
|
||
|
if ( result && ( pos.y() < (src->itemRect(result).top() + src->itemHeight(i)/2) ) )
|
||
|
result = result->prev();
|
||
|
else if ( !result && pos.y() > src->itemRect( last ).bottom() )
|
||
|
result = last;
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
bool ListBoxDnd::canDecode( QDragEnterEvent * event )
|
||
|
{
|
||
|
return ListBoxItemDrag::canDecode( event );
|
||
|
}
|
||
|
|
||
|
|
||
|
// ------------------------------------------------------------------
|
||
|
// The Dragobject Implementation ------------------------------------
|
||
|
// ------------------------------------------------------------------
|
||
|
|
||
|
ListBoxItemDrag::ListBoxItemDrag( ListBoxItemList & items, bool sendPtr, QListBox * parent, const char * name )
|
||
|
: QStoredDrag( "qt/listboxitem", parent, name )
|
||
|
{
|
||
|
// ### FIX!
|
||
|
QByteArray data( sizeof( Q_INT32 ) + sizeof( QListBoxItem ) * items.count() );
|
||
|
QDataStream stream( data, IO_WriteOnly );
|
||
|
|
||
|
stream << items.count();
|
||
|
stream << (Q_UINT8) sendPtr; // just transfer item pointer; omit data
|
||
|
|
||
|
QListBoxItem * i = items.first();
|
||
|
|
||
|
if ( sendPtr ) {
|
||
|
|
||
|
while ( i ) {
|
||
|
|
||
|
stream << (Q_ULONG) i; //###FIX: demands sizeof(ulong) >= sizeof(void*)
|
||
|
i = items.next();
|
||
|
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
while ( i ) {
|
||
|
|
||
|
Q_UINT8 b = 0;
|
||
|
|
||
|
b = (Q_UINT8) ( i->text() != QString::null ); // does item have text ?
|
||
|
stream << b;
|
||
|
if ( b ) {
|
||
|
stream << i->text();
|
||
|
}
|
||
|
|
||
|
b = (Q_UINT8) ( !!i->pixmap() ); // does item have a pixmap ?
|
||
|
stream << b;
|
||
|
if ( b ) {
|
||
|
stream << ( *i->pixmap() );
|
||
|
}
|
||
|
|
||
|
stream << (Q_UINT8) i->isSelectable();
|
||
|
|
||
|
i = items.next();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
setEncodedData( data );
|
||
|
}
|
||
|
|
||
|
bool ListBoxItemDrag::canDecode( QDragMoveEvent * event )
|
||
|
{
|
||
|
return event->provides( "qt/listboxitem" );
|
||
|
}
|
||
|
|
||
|
bool ListBoxItemDrag::decode( QDropEvent * event, QListBox * parent, QListBoxItem * after )
|
||
|
{
|
||
|
QByteArray data = event->encodedData( "qt/listboxitem" );
|
||
|
|
||
|
if ( data.size() ) {
|
||
|
event->accept();
|
||
|
QDataStream stream( data, IO_ReadOnly );
|
||
|
|
||
|
int count = 0;
|
||
|
stream >> count;
|
||
|
|
||
|
Q_UINT8 recievePtr = 0; // data contains just item pointers; no data
|
||
|
stream >> recievePtr;
|
||
|
|
||
|
QListBoxItem * item = 0;
|
||
|
|
||
|
if ( recievePtr ) {
|
||
|
|
||
|
for( int i = 0; i < count; i++ ) {
|
||
|
|
||
|
Q_ULONG p = 0; //###FIX: demands sizeof(ulong) >= sizeof(void*)
|
||
|
stream >> p;
|
||
|
item = (QListBoxItem *) p;
|
||
|
|
||
|
parent->insertItem( item, after );
|
||
|
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
for ( int i = 0; i < count; i++ ) {
|
||
|
|
||
|
Q_UINT8 hasText = 0;
|
||
|
QString text;
|
||
|
stream >> hasText;
|
||
|
if ( hasText ) {
|
||
|
stream >> text;
|
||
|
}
|
||
|
|
||
|
Q_UINT8 hasPixmap = 0;
|
||
|
QPixmap pixmap;
|
||
|
stream >> hasPixmap;
|
||
|
if ( hasPixmap ) {
|
||
|
stream >> pixmap;
|
||
|
}
|
||
|
|
||
|
Q_UINT8 isSelectable = 0;
|
||
|
stream >> isSelectable;
|
||
|
|
||
|
if ( hasPixmap ) {
|
||
|
item = new QListBoxPixmap( parent, pixmap, text, after );
|
||
|
} else {
|
||
|
item = new QListBoxText( parent, text, after );
|
||
|
}
|
||
|
|
||
|
item->setSelectable( isSelectable );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|