Fixed search algorithm for iconview widget. This resolves bug 420.

Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
pull/1/head
Michele Calgaro 9 years ago
parent fa440833f9
commit 42dcb07b26

@ -522,12 +522,7 @@ private:
DirLeft, DirLeft,
DirRight DirRight
}; };
TQIconViewItem* findItem( Direction dir, TQIconViewItem* findItem(Direction dir, const TQIconViewItem *fromItem) const;
const TQPoint &amp;relativeTo,
const TQRect &amp;searchRect ) const;
bool neighbourItem( Direction dir,
const TQPoint &amp;relativeTo,
const TQIconViewItem *item ) const;
TQBitmap mask( TQPixmap *pix ) const; TQBitmap mask( TQPixmap *pix ) const;
TQIconViewPrivate *d; TQIconViewPrivate *d;

@ -491,12 +491,7 @@ private:
DirLeft, DirLeft,
DirRight DirRight
}; };
TQIconViewItem* findItem( Direction dir, TQIconViewItem* findItem(Direction dir, const TQIconViewItem *fromItem) const;
const TQPoint &relativeTo,
const TQRect &searchRect ) const;
bool neighbourItem( Direction dir,
const TQPoint &relativeTo,
const TQIconViewItem *item ) const;
TQBitmap mask( TQPixmap *pix ) const; TQBitmap mask( TQPixmap *pix ) const;
int visibleWidthSB() const; int visibleWidthSB() const;
int visibleHeightSB() const; int visibleHeightSB() const;

@ -287,74 +287,8 @@ public:
struct SortableItem { struct SortableItem {
TQIconViewItem *item; TQIconViewItem *item;
}; };
public:
/* finds the containers that intersect with \a searchRect in the direction \a dir relative to \a relativeTo */
TQPtrList<ItemContainer>* findContainers(
TQIconView:: Direction dir,
const TQPoint &relativeTo,
const TQRect &searchRect ) const;
// friend int cmpIconViewItems( const void *n1, const void *n2 );
}; };
TQPtrList<TQIconViewPrivate::ItemContainer>* TQIconViewPrivate::findContainers(
TQIconView:: Direction dir,
const TQPoint &relativeTo,
const TQRect &searchRect ) const
{
TQPtrList<TQIconViewPrivate::ItemContainer>* list =
new TQPtrList<TQIconViewPrivate::ItemContainer>();
if ( arrangement == TQIconView::LeftToRight ) {
if ( dir == TQIconView::DirLeft || dir == TQIconView::DirRight ) {
ItemContainer *c = firstContainer;
for ( ; c; c = c->n )
if ( c->rect.intersects( searchRect ) )
list->append( c );
} else {
if ( dir == TQIconView::DirDown ) {
ItemContainer *c = firstContainer;
for ( ; c; c = c->n )
if ( c->rect.intersects( searchRect ) &&
c->rect.bottom() >= relativeTo.y() )
list->append( c );
} else {
ItemContainer *c = lastContainer;
for ( ; c; c = c->p )
if ( c->rect.intersects( searchRect ) &&
c->rect.top() <= relativeTo.y() )
list->append( c );
}
}
} else {
if ( dir == TQIconView::DirUp || dir == TQIconView::DirDown ) {
ItemContainer *c = firstContainer;
for ( ; c; c = c->n )
if ( c->rect.intersects( searchRect ) )
list->append( c );
} else {
if ( dir == TQIconView::DirRight ) {
ItemContainer *c = firstContainer;
for ( ; c; c = c->n )
if ( c->rect.intersects( searchRect ) &&
c->rect.right() >= relativeTo.x() )
list->append( c );
} else {
ItemContainer *c = lastContainer;
for ( ; c; c = c->p )
if ( c->rect.intersects( searchRect ) &&
c->rect.left() <= relativeTo.x() )
list->append( c );
}
}
}
return list;
}
#if defined(Q_C_CALLBACKS) #if defined(Q_C_CALLBACKS)
extern "C" { extern "C" {
#endif #endif
@ -5106,6 +5040,7 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
} }
} break; } break;
#endif #endif
case Key_Home: { case Key_Home: {
d->currInputString = TQString::null; d->currInputString = TQString::null;
if ( !d->firstItem ) if ( !d->firstItem )
@ -5150,6 +5085,7 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
e->state() & ControlButton, TRUE ); e->state() & ControlButton, TRUE );
} }
} break; } break;
case Key_End: { case Key_End: {
d->currInputString = TQString::null; d->currInputString = TQString::null;
if ( !d->lastItem ) if ( !d->lastItem )
@ -5193,50 +5129,7 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
e->state() & ControlButton, TRUE ); e->state() & ControlButton, TRUE );
} }
} break; } break;
case Key_Right: {
d->currInputString = TQString::null;
TQIconViewItem *item;
selectCurrent = FALSE;
Direction dir = DirRight;
TQRect r( 0, d->currentItem->y(), contentsWidth(), d->currentItem->height() );
item = findItem( dir, d->currentItem->rect().center(), r );
// search the row below from the right
while ( !item && r.y() < contentsHeight() ) {
r.moveBy(0, d->currentItem->height() );
item = findItem( dir, TQPoint( 0, r.center().y() ), r );
}
if ( item ) {
TQIconViewItem *old = d->currentItem;
setCurrentItem( item );
ensureItemVisible( item );
handleItemChange( old, e->state() & ShiftButton, e->state() & ControlButton );
}
} break;
case Key_Left: {
d->currInputString = TQString::null;
TQIconViewItem *item;
selectCurrent = FALSE;
Direction dir = DirLeft;
TQRect r( 0, d->currentItem->y(), contentsWidth(), d->currentItem->height() );
item = findItem( dir, d->currentItem->rect().center(), r );
// search the row above from the left
while ( !item && r.y() >= 0 ) {
r.moveBy(0, - d->currentItem->height() );
item = findItem( dir, TQPoint( contentsWidth(), r.center().y() ), r );
}
if ( item ) {
TQIconViewItem *old = d->currentItem;
setCurrentItem( item );
ensureItemVisible( item );
handleItemChange( old, e->state() & ShiftButton, e->state() & ControlButton );
}
} break;
case Key_Space: { case Key_Space: {
d->currInputString = TQString::null; d->currInputString = TQString::null;
if ( d->selectionMode == Single) if ( d->selectionMode == Single)
@ -5244,51 +5137,65 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
d->currentItem->setSelected( !d->currentItem->isSelected(), TRUE ); d->currentItem->setSelected( !d->currentItem->isSelected(), TRUE );
} break; } break;
case Key_Enter: case Key_Return:
case Key_Enter:
case Key_Return:
d->currInputString = TQString::null; d->currInputString = TQString::null;
emit returnPressed( d->currentItem ); emit returnPressed( d->currentItem );
break; break;
case Key_Right: {
d->currInputString = TQString::null;
selectCurrent = FALSE;
Direction dir = DirRight;
TQIconViewItem *item = findItem(dir, d->currentItem);
if (item) {
TQIconViewItem *old=d->currentItem;
setCurrentItem(item);
ensureItemVisible(item);
handleItemChange(old, e->state() & ShiftButton, e->state() & ControlButton );
}
} break;
case Key_Left: {
d->currInputString = TQString::null;
selectCurrent = FALSE;
Direction dir = DirLeft;
TQIconViewItem *item = findItem(dir, d->currentItem);
if (item) {
TQIconViewItem *old=d->currentItem;
setCurrentItem(item);
ensureItemVisible(item);
handleItemChange(old, e->state() & ShiftButton, e->state() & ControlButton );
}
} break;
case Key_Down: { case Key_Down: {
d->currInputString = TQString::null; d->currInputString = TQString::null;
TQIconViewItem *item;
selectCurrent = FALSE; selectCurrent = FALSE;
Direction dir = DirDown; Direction dir = DirDown;
TQIconViewItem *item = findItem(dir, d->currentItem);
TQRect r( d->currentItem->x(), 0, d->currentItem->width(), contentsHeight() ); if (item) {
item = findItem( dir, d->currentItem->rect().center(), r ); TQIconViewItem *old=d->currentItem;
setCurrentItem(item);
// finding the closest item below and to the right ensureItemVisible(item);
while ( !item && r.x() < contentsWidth() ) { handleItemChange(old, e->state() & ShiftButton, e->state() & ControlButton );
r.moveBy( r.width() , 0 ); }
item = findItem( dir, TQPoint( r.center().x(), 0 ), r );
}
TQIconViewItem *i = d->currentItem;
setCurrentItem( item );
item = i;
handleItemChange( item, e->state() & ShiftButton, e->state() & ControlButton );
} break; } break;
case Key_Up: { case Key_Up: {
d->currInputString = TQString::null; d->currInputString = TQString::null;
TQIconViewItem *item;
selectCurrent = FALSE; selectCurrent = FALSE;
Direction dir = DirUp; Direction dir = DirUp;
TQIconViewItem *item = findItem(dir, d->currentItem);
TQRect r( d->currentItem->x(), 0, d->currentItem->width(), contentsHeight() ); if (item) {
item = findItem( dir, d->currentItem->rect().center(), r ); TQIconViewItem *old=d->currentItem;
setCurrentItem(item);
// finding the closest item above and to the left ensureItemVisible(item);
while ( !item && r.x() >= 0 ) { handleItemChange(old, e->state() & ShiftButton, e->state() & ControlButton );
r.moveBy(- r.width(), 0 ); }
item = findItem( dir, TQPoint(r.center().x(), contentsHeight() ), r );
}
TQIconViewItem *i = d->currentItem;
setCurrentItem( item );
item = i;
handleItemChange( item, e->state() & ShiftButton, e->state() & ControlButton );
} break; } break;
case Key_Next: { case Key_Next: {
d->currInputString = TQString::null; d->currInputString = TQString::null;
selectCurrent = FALSE; selectCurrent = FALSE;
@ -5311,6 +5218,7 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
handleItemChange( item, e->state() & ShiftButton, e->state() & ControlButton ); handleItemChange( item, e->state() & ShiftButton, e->state() & ControlButton );
} }
} break; } break;
case Key_Prior: { case Key_Prior: {
d->currInputString = TQString::null; d->currInputString = TQString::null;
selectCurrent = FALSE; selectCurrent = FALSE;
@ -5333,6 +5241,7 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
handleItemChange( item, e->state() & ShiftButton, e->state() & ControlButton ); handleItemChange( item, e->state() & ShiftButton, e->state() & ControlButton );
} }
} break; } break;
default: default:
if ( !e->text().isEmpty() && e->text()[ 0 ].isPrint() ) { if ( !e->text().isEmpty() && e->text()[ 0 ].isPrint() ) {
selectCurrent = FALSE; selectCurrent = FALSE;
@ -5403,79 +5312,195 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
} }
/* /*
Finds the closest item in the Direction \a dir relative from the point \a relativeTo Finds the closest item in the direction \a dir starting from the specified \a fromItem.
which intersects with the searchRect. If the arrangement is LeftToRight (icon view mode): use center as item reference
If the arrangement is TopToBottom (multicolumn view mode): use left top corner as item reference
The function choses the closest item with its center in the searchRect.
*/ */
TQIconViewItem* TQIconView::findItem( Direction dir, TQIconViewItem* TQIconView::findItem(Direction dir, const TQIconViewItem *fromItem) const
const TQPoint &relativeTo,
const TQRect &searchRect ) const
{ {
TQIconViewItem *item; TQIconViewItem *closestItem=NULL;
TQIconViewItem *centerMatch = 0; int distPri=0, distSec=0;
int centerMatchML = 0; int itemDistancePri=0, itemDistanceSec=0;
// gets list of containers with potential items TQPoint pos;
TQPtrList<TQIconViewPrivate::ItemContainer>* cList = if (d->arrangement == LeftToRight) {
d->findContainers( dir, relativeTo, searchRect); pos=fromItem->rect().center();
cList->first();
while ( cList->current() && !centerMatch ) {
TQPtrList<TQIconViewItem> &list = (cList->current())->items;
for ( item = list.first(); item; item = list.next() ) {
if ( neighbourItem( dir, relativeTo, item ) &&
searchRect.contains( item->rect().center() ) &&
item != currentItem() ) {
int ml = (relativeTo - item->rect().center()).manhattanLength();
if ( centerMatch ) {
if ( ml < centerMatchML ) {
centerMatch = item;
centerMatchML = ml;
}
} else {
centerMatch = item;
centerMatchML = ml;
}
}
}
cList->next();
} }
delete cList; else {
return centerMatch; pos=fromItem->rect().topLeft();
}
/*
Returns TRUE if the items orientation compared to
the point \a relativeTo is correct.
*/
bool TQIconView::neighbourItem( Direction dir,
const TQPoint &relativeTo,
const TQIconViewItem *item ) const
{
switch ( dir ) {
case DirUp:
if ( item->rect().center().y() < relativeTo.y() )
return TRUE;
break;
case DirDown:
if ( item->rect().center().y() > relativeTo.y() )
return TRUE;
break;
case DirLeft:
if ( item->rect().center().x() < relativeTo.x() )
return TRUE;
break;
case DirRight:
if ( item->rect().center().x() > relativeTo.x() )
return TRUE;
break;
default:
// nothing
break;
} }
return FALSE;
TQRect searchRect;
switch (dir) {
case DirDown:
searchRect.setCoords(pos.x(), 0, contentsWidth(), contentsHeight());
break;
case DirUp:
searchRect.setCoords(0, 0, pos.x(), contentsHeight());
break;
case DirRight:
searchRect.setCoords(0, pos.y(), contentsWidth(), contentsHeight());
break;
case DirLeft:
searchRect.setCoords(0, 0, contentsWidth(), pos.y());
break;
}
for (TQIconViewPrivate::ItemContainer *c=d->firstContainer; c; c=c->n) {
if (c->rect.intersects(searchRect)) {
TQPtrList<TQIconViewItem> &list = c->items;
for (TQIconViewItem *item=list.first(); item; item=list.next()) {
if (item != fromItem) {
bool itemOK = true;
const TQRect &ir = item->rect();
// DirDown/DirUp : primary distance X, secondary distance Y
// DirLeft/DirRight: primary distance Y, secondary distance X
if (d->arrangement == LeftToRight) {
// Left to right arrangement (icon view mode): use center as item reference
switch (dir) {
case DirDown:
if (ir.center().x() > pos.x()) {
distPri = ir.center().x()-pos.x();
distSec = ir.center().y();
}
else if (ir.center().x() == pos.x() && ir.center().y() > pos.y()) {
distPri = 0;
distSec = ir.center().y()-pos.y();
}
else {
itemOK = false;
}
break;
case DirUp:
if (ir.center().x() < pos.x()) {
distPri = pos.x()-ir.center().x();
distSec = contentsHeight()-ir.center().y();
}
else if (ir.center().x() == pos.x() && ir.center().y() < pos.y()) {
distPri = 0;
distSec = pos.y()-ir.center().y();
}
else {
itemOK = false;
}
break;
case DirRight:
if (ir.center().y() > pos.y()) {
distPri = ir.center().y()-pos.y();
distSec = ir.center().x();
}
else if (ir.center().y() == pos.y() && ir.center().x() > pos.x()) {
distPri = 0;
distSec = ir.center().x()-pos.x();
}
else {
itemOK = false;
}
break;
case DirLeft:
if (ir.center().y() < pos.y()) {
distPri = pos.y()-ir.center().y();
distSec = contentsWidth()-ir.center().x();
}
else if (ir.center().y() == pos.y() && ir.center().x() < pos.x()) {
distPri = 0;
distSec = pos.x()-ir.center().x();
}
else {
itemOK = false;
}
break;
default:
itemOK = false;
break;
}
}
else {
// Top to bottom arrangement (multicolumn view mode): use left top corner as item reference
switch (dir) {
case DirDown:
if (ir.left() > pos.x()) {
distPri = ir.left()-pos.x();
distSec = ir.top();
}
else if (ir.left() == pos.x() && ir.top() > pos.y()) {
distPri = 0;
distSec = ir.top()-pos.y();
}
else {
itemOK = false;
}
break;
case DirUp:
if (ir.left() < pos.x()) {
distPri = pos.x()-ir.left();
distSec = contentsHeight()-ir.top();
}
else if (ir.left() == pos.x() && ir.top() < pos.y()) {
distPri = 0;
distSec = pos.y()-ir.top();
}
else {
itemOK = false;
}
break;
case DirRight:
if (ir.top() > pos.y()) {
distPri = ir.top()-pos.y();
distSec = ir.left();
}
else if (ir.top() == pos.y() && ir.left() > pos.x()) {
distPri = 0;
distSec = ir.left()-pos.x();
}
else {
itemOK = false;
}
break;
case DirLeft:
if (ir.top() < pos.y()) {
distPri = pos.y()-ir.top();
distSec = contentsWidth()-ir.left();
}
else if (ir.top() == pos.y() && ir.left() < pos.x()) {
distPri = 0;
distSec = pos.x()-ir.left();
}
else {
itemOK = false;
}
break;
default:
itemOK = false;
break;
}
}
if (itemOK) {
if (!closestItem ||
((distPri < itemDistancePri) ||
(distPri == itemDistancePri && distSec < itemDistanceSec))) {
closestItem = item;
itemDistancePri = distPri;
itemDistanceSec = distSec;
}
}
}
}
}
}
return closestItem;
} }
/*! /*!

Loading…
Cancel
Save