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

(cherry picked from commit 42dcb07b26)
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
r14.0.x
Michele Calgaro 10 years ago
parent 6ff4ab89a7
commit fdcad492bd

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

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

@ -287,74 +287,8 @@ public:
struct SortableItem {
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)
extern "C" {
#endif
@ -5106,6 +5040,7 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
}
} break;
#endif
case Key_Home: {
d->currInputString = TQString::null;
if ( !d->firstItem )
@ -5150,6 +5085,7 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
e->state() & ControlButton, TRUE );
}
} break;
case Key_End: {
d->currInputString = TQString::null;
if ( !d->lastItem )
@ -5193,50 +5129,7 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
e->state() & ControlButton, TRUE );
}
} 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: {
d->currInputString = TQString::null;
if ( d->selectionMode == Single)
@ -5244,51 +5137,65 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
d->currentItem->setSelected( !d->currentItem->isSelected(), TRUE );
} break;
case Key_Enter: case Key_Return:
case Key_Enter:
case Key_Return:
d->currInputString = TQString::null;
emit returnPressed( d->currentItem );
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: {
d->currInputString = TQString::null;
TQIconViewItem *item;
selectCurrent = FALSE;
Direction dir = DirDown;
TQRect r( d->currentItem->x(), 0, d->currentItem->width(), contentsHeight() );
item = findItem( dir, d->currentItem->rect().center(), r );
// finding the closest item below and to the right
while ( !item && r.x() < contentsWidth() ) {
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 );
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_Up: {
d->currInputString = TQString::null;
TQIconViewItem *item;
selectCurrent = FALSE;
Direction dir = DirUp;
TQRect r( d->currentItem->x(), 0, d->currentItem->width(), contentsHeight() );
item = findItem( dir, d->currentItem->rect().center(), r );
// finding the closest item above and to the left
while ( !item && r.x() >= 0 ) {
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 );
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_Next: {
d->currInputString = TQString::null;
selectCurrent = FALSE;
@ -5311,6 +5218,7 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
handleItemChange( item, e->state() & ShiftButton, e->state() & ControlButton );
}
} break;
case Key_Prior: {
d->currInputString = TQString::null;
selectCurrent = FALSE;
@ -5333,6 +5241,7 @@ void TQIconView::keyPressEvent( TQKeyEvent *e )
handleItemChange( item, e->state() & ShiftButton, e->state() & ControlButton );
}
} break;
default:
if ( !e->text().isEmpty() && e->text()[ 0 ].isPrint() ) {
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
which intersects with the searchRect.
The function choses the closest item with its center in the searchRect.
Finds the closest item in the direction \a dir starting from the specified \a fromItem.
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
*/
TQIconViewItem* TQIconView::findItem( Direction dir,
const TQPoint &relativeTo,
const TQRect &searchRect ) const
TQIconViewItem* TQIconView::findItem(Direction dir, const TQIconViewItem *fromItem) const
{
TQIconViewItem *item;
TQIconViewItem *centerMatch = 0;
int centerMatchML = 0;
// gets list of containers with potential items
TQPtrList<TQIconViewPrivate::ItemContainer>* cList =
d->findContainers( dir, relativeTo, searchRect);
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();
TQIconViewItem *closestItem=NULL;
int distPri=0, distSec=0;
int itemDistancePri=0, itemDistanceSec=0;
TQPoint pos;
if (d->arrangement == LeftToRight) {
pos=fromItem->rect().center();
}
delete cList;
return centerMatch;
}
/*
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;
else {
pos=fromItem->rect().topLeft();
}
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