summaryrefslogtreecommitdiffstats
path: root/kdevdesigner/designer/listviewdnd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdevdesigner/designer/listviewdnd.cpp')
-rw-r--r--kdevdesigner/designer/listviewdnd.cpp432
1 files changed, 432 insertions, 0 deletions
diff --git a/kdevdesigner/designer/listviewdnd.cpp b/kdevdesigner/designer/listviewdnd.cpp
new file mode 100644
index 00000000..32dcc6d5
--- /dev/null
+++ b/kdevdesigner/designer/listviewdnd.cpp
@@ -0,0 +1,432 @@
+/**********************************************************************
+** Copyright (C) 2002 Trolltech AS. All rights reserved.
+**
+** This file is part of TQt Designer.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid TQt Enterprise Edition or TQt Professional Edition
+** licenses may use this file in accordance with the TQt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about TQt Commercial License Agreements.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "listviewdnd.h"
+#include <tqwidget.h>
+#include <tqheader.h>
+#include <tqpainter.h>
+#include <tqdragobject.h>
+#include <tqvaluelist.h>
+
+// The Dragobject Declaration ---------------------------------------
+class ListViewItemDrag : public TQStoredDrag
+{
+public:
+ enum DropRelation { Sibling, Child };
+ ListViewItemDrag( ListViewItemList & items, TQWidget * parent = 0, const char * name = 0 );
+ ~ListViewItemDrag() {};
+ static bool canDecode( TQDragMoveEvent * event );
+ static bool decode( TQDropEvent * event, TQListView * parent, TQListViewItem * insertPoint, DropRelation dr );
+};
+// ------------------------------------------------------------------
+
+ListViewDnd::ListViewDnd( TQListView * eventSource, const char * name )
+ : ListDnd( eventSource, name ) { }
+
+void ListViewDnd::confirmDrop( TQListViewItem * )
+{
+ dropConfirmed = TRUE;
+}
+
+bool ListViewDnd::dropEvent( TQDropEvent * event )
+{
+ if ( dragInside ) {
+
+ if ( dMode & NullDrop ) { // combined with Move, a NullDrop will delete an item
+ event->accept();
+ emit dropped( 0 ); // a NullDrop
+ return TRUE;
+ }
+
+ TQPoint pos = event->pos();
+
+ ListViewItemDrag::DropRelation dr = ListViewItemDrag::Sibling;
+ TQListViewItem *item = itemAt( pos );
+ int dpos = dropDepth( item, pos );
+
+ if ( item ) {
+ if ( dpos > item->depth() && !(dMode & Flat) ) {
+ // Child node
+ dr = ListViewItemDrag::Child;
+ } else if ( dpos < item->depth() ) {
+ // Parent(s) Sibling
+ while ( item && (item->depth() > dpos) )
+ item = item->parent();
+ }
+ }
+
+ if ( ListViewItemDrag::decode( event, (TQListView *) src, item, dr ) ) {
+ event->accept();
+ emit dropped( 0 ); // Use ID instead of item?
+ }
+ }
+
+ line->hide();
+ dragInside = FALSE;
+
+ return TRUE;
+}
+
+bool ListViewDnd::mouseMoveEvent( TQMouseEvent * event )
+{
+ if ( event->state() & Qt::LeftButton ) {
+ if ( ( event->pos() - mousePressPos ).manhattanLength() > 3 ) {
+ ListViewItemList list;
+
+ if ( dMode & Flat )
+ buildFlatList( list );
+ else
+ buildTreeList( list );
+
+ ListViewItemDrag * dragobject = new ListViewItemDrag( list, (TQListView *) src );
+
+ if ( dMode & Move ) {
+ disabledItems = list;
+ setVisibleItems( FALSE );
+ }
+
+ dragobject->dragCopy();
+
+ if ( dMode & Move ) {
+ // Did the target accept the drop?
+ if ( dropConfirmed ) {
+ // Shouldn't autoDelete handle this?
+ for( list.first(); list.current(); list.next() )
+ delete list.current();
+ dropConfirmed = FALSE;
+ } else {
+ // Reenable disabled items since
+ // drag'n'drop was aborted
+ setVisibleItems( TRUE );
+ }
+ disabledItems.clear();
+ }
+ }
+ }
+ return FALSE;
+}
+
+int ListViewDnd::buildFlatList( ListViewItemList & list )
+{
+ bool addKids = FALSE;
+ TQListViewItem *nextSibling = 0;
+ TQListViewItem *nextParent = 0;
+ TQListViewItemIterator it = ((TQListView *)src)->firstChild();
+ for ( ; *it; it++ ) {
+ // Hit the nextSibling, turn of child processing
+ if ( (*it) == nextSibling )
+ addKids = FALSE;
+
+ if ( (*it)->isSelected() ) {
+ if ( (*it)->childCount() == 0 ) {
+ // Selected, no children
+ list.append( *it );
+ } else if ( !addKids ) {
+ // Children processing not set, so set it
+ // Also find the item were we shall quit
+ // processing children...if any such item
+ addKids = TRUE;
+ nextSibling = (*it)->nextSibling();
+ nextParent = (*it)->parent();
+ while ( nextParent && !nextSibling ) {
+ nextSibling = nextParent->nextSibling();
+ nextParent = nextParent->parent();
+ }
+ }
+ } else if ( ((*it)->childCount() == 0) && addKids ) {
+ // Leaf node, and we _do_ process children
+ list.append( *it );
+ }
+ }
+ return list.count();
+}
+
+int ListViewDnd::buildTreeList( ListViewItemList & list )
+{
+ TQListViewItemIterator it = ((TQListView *)src)->firstChild();
+ for ( ; *it; it++ ) {
+ if ( (*it)->isSelected() )
+ list.append( *it );
+ }
+ return list.count();
+}
+
+void ListViewDnd::setVisibleItems( bool b )
+{
+ if ( disabledItems.isEmpty() )
+ return;
+
+ disabledItems.first();
+ do {
+ disabledItems.current()->setVisible( b );
+ } while ( disabledItems.next() );
+}
+
+void ListViewDnd::updateLine( const TQPoint & dragPos )
+{
+ TQListViewItem * item = itemAt(dragPos);
+ TQListView * src = (TQListView *) this->src;
+
+ int ypos = item ?
+ ( src->itemRect( item ).bottom() - ( line->height() / 2 ) ) :
+ ( src->itemRect( src->firstChild() ).top() );
+
+ int xpos = dropDepth( item, dragPos ) * src->treeStepSize();
+ line->resize( src->viewport()->width() - xpos, line->height() );
+ line->move( xpos, ypos );
+}
+
+TQListViewItem * ListViewDnd::itemAt( TQPoint pos )
+{
+ TQListView * src = (TQListView *) this->src;
+ int headerHeight = (int)(src->header()->height());
+ pos.ry() -= headerHeight;
+ TQListViewItem * result = src->itemAt( pos );
+
+ if ( result && ( pos.ry() < (src->itemPos(result) + result->height()/2) ) )
+ result = result->itemAbove();
+
+ // Wind back if has parent, and we're in flat mode
+ while ( result && result->parent() && (dMode & Flat) )
+ result = result->parent();
+
+ // Wind back if has parent, and we're in flat mode
+ while ( result && !result->isVisible() && result->parent() )
+ result = result->parent();
+
+ if ( !result && src->firstChild() && (pos.y() > src->itemRect(src->firstChild()).bottom()) ) {
+ result = src->lastItem();
+ if ( !result->isVisible() )
+ // Handle special case where last item is actually hidden
+ result = result->itemAbove();
+ }
+
+ return result;
+}
+
+int ListViewDnd::dropDepth( TQListViewItem * item, TQPoint pos )
+{
+ if ( !item || (dMode & Flat) )
+ return 0;
+
+ int result = 0;
+ int itemDepth = item->depth();
+ int indentSize = ((TQListView *)src)->treeStepSize();
+ int itemLeft = indentSize * itemDepth;
+ int childMargin = indentSize*2;
+ if ( pos.x() > itemLeft + childMargin ) {
+ result = itemDepth + 1;
+ } else if ( pos.x() < itemLeft ) {
+ result = pos.x() / indentSize;
+ } else {
+ result = itemDepth;
+ }
+ return result;
+}
+
+bool ListViewDnd::canDecode( TQDragEnterEvent * event )
+{
+ return ListViewItemDrag::canDecode( event );
+}
+
+// ------------------------------------------------------------------
+// The Dragobject Implementation ------------------------------------
+// ------------------------------------------------------------------
+
+TQDataStream & operator<< ( TQDataStream & stream, const TQListViewItem & item );
+TQDataStream & operator>> ( TQDataStream & stream, TQListViewItem & item );
+
+ListViewItemDrag::ListViewItemDrag( ListViewItemList & items, TQWidget * parent, const char * name )
+ : TQStoredDrag( "qt/listviewitem", parent, name )
+{
+ // ### FIX!
+ TQByteArray data( sizeof( TQ_INT32 ) + sizeof( TQListViewItem ) * items.count() );
+ TQDataStream stream( data, IO_WriteOnly );
+
+ stream << items.count();
+
+ TQListViewItem *i = items.first();
+ while ( i ) {
+ stream << *i;
+ i = items.next();
+ }
+
+ setEncodedData( data );
+}
+
+bool ListViewItemDrag::canDecode( TQDragMoveEvent * event )
+{
+ return event->provides( "qt/listviewitem" );
+}
+
+bool ListViewItemDrag::decode( TQDropEvent * event, TQListView * parent, TQListViewItem * insertPoint, DropRelation dr )
+{
+ TQByteArray data = event->encodedData( "qt/listviewitem" );
+ TQListViewItem* itemParent = insertPoint ? insertPoint->parent() : 0;
+
+ // Change from sibling (default) to child creation
+ if ( insertPoint && dr == Child ) {
+ itemParent = insertPoint;
+ insertPoint = 0;
+ }
+
+ if ( data.size() ) {
+ event->accept();
+ TQDataStream stream( data, IO_ReadOnly );
+
+ int count = 0;
+ stream >> count;
+
+ for( int i = 0; i < count; i++ ) {
+ if ( itemParent ) {
+ insertPoint = new TQListViewItem( itemParent, insertPoint );
+ itemParent->setOpen( TRUE );
+ } else { // No parent for insertPoint, use TQListView
+ insertPoint = new TQListViewItem( parent, insertPoint );
+ }
+ stream >> *insertPoint;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+TQDataStream & operator<< ( TQDataStream & stream, const TQListViewItem & item )
+{
+ int columns = item.listView()->columns();
+ stream << columns;
+
+ TQ_UINT8 b = 0;
+
+ int i;
+ for ( i = 0; i < columns; i++ ) {
+ b = (TQ_UINT8) ( item.text( i ) != TQString() ); // does column i have a string ?
+ stream << b;
+ if ( b ) {
+ stream << item.text( i );
+ }
+ }
+
+ for ( i = 0; i < columns; i++ ) {
+ b = (TQ_UINT8) ( !!item.pixmap( i ) ); // does column i have a pixmap ?
+ stream << b;
+ if ( b ) {
+ stream << ( *item.pixmap( i ) );
+ }
+ }
+
+ stream << (TQ_UINT8) item.isOpen();
+ stream << (TQ_UINT8) item.isSelectable();
+ stream << (TQ_UINT8) item.isExpandable();
+ stream << (TQ_UINT8) item.dragEnabled();
+ stream << (TQ_UINT8) item.dropEnabled();
+ stream << (TQ_UINT8) item.isVisible();
+
+ for ( i = 0; i < columns; i++ ) {
+ stream << (TQ_UINT8) item.renameEnabled( i );
+ }
+
+ stream << (TQ_UINT8) item.multiLinesEnabled();
+ stream << item.childCount();
+
+ if ( item.childCount() > 0 ) {
+ TQListViewItem * child = item.firstChild();
+ while ( child ) {
+ stream << ( *child ); // recursive call
+ child = child->nextSibling();
+ }
+ }
+
+ return stream;
+}
+
+TQDataStream & operator>> ( TQDataStream & stream, TQListViewItem & item )
+{
+ TQ_INT32 columns;
+ stream >> columns;
+
+ TQ_UINT8 b = 0;
+
+ TQString text;
+ int i;
+ for ( i = 0; i < columns; i++ ) {
+ stream >> b;
+ if ( b ) { // column i has string ?
+ stream >> text;
+ item.setText( i, text );
+ }
+ }
+
+ TQPixmap pixmap;
+ for ( i = 0; i < columns; i++ ) {
+ stream >> b; // column i has pixmap ?
+ if ( b ) {
+ stream >> pixmap;
+ item.setPixmap( i, pixmap );
+ }
+ }
+
+ stream >> b;
+ item.setOpen( b );
+
+ stream >> b;
+ item.setSelectable( b );
+
+ stream >> b;
+ item.setExpandable( b );
+
+ stream >> b;
+ item.setDragEnabled( b );
+
+ stream >> b;
+ item.setDropEnabled( b );
+
+ stream >> b;
+ item.setVisible( b );
+
+ for ( i = 0; i < columns; i++ ) {
+ stream >> b;
+ item.setRenameEnabled( i, b );
+ }
+
+ stream >> b;
+ item.setMultiLinesEnabled( b );
+
+ int childCount;
+ stream >> childCount;
+
+ TQListViewItem *child = 0;
+ TQListViewItem *prevchild = 0;
+ for ( i = 0; i < childCount; i++ ) {
+ child = new TQListViewItem( &item, prevchild );
+ stream >> ( *child );
+ item.insertItem( child );
+ prevchild = child;
+ }
+
+ return stream;
+}