17#ifndef TQT_NO_COMBOBOX
18#include "tqpopupmenu.h"
19#include "tqlistview.h"
21#include "tqdrawutil.h"
25#include "tqapplication.h"
26#include "tqlineedit.h"
28#include "tqeffects_p.h"
29#include "tqstringlist.h"
30#include "tqcombobox.h"
38 QComboViewData( QComboView *cb ): current(0), lView( 0 ), combo( cb )
40 duplicatesEnabled =
true;
41 cb->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Fixed ) );
44 inline TQListView * listView() {
return lView; }
45 void updateLinedGeometry();
47 void setListView( TQListView *l ) { lView = l ;
48 l->setMouseTracking(
true );}
50 TQListViewItem *current;
56 bool mouseWasInsidePopup;
59 bool discardNextMousePress;
64 bool duplicatesEnabled;
65 int fullHeight, currHeight;
68 TQTimer *completionTimer;
79void QComboViewData::updateLinedGeometry()
83 TQRect r = TQStyle::visualRect( combo->style().querySubControlMetrics(TQStyle::CC_ComboBox, combo,
84 TQStyle::SC_ComboBoxEditField), combo );
87 const TQPixmap *pix = combo->currentItem() ? combo->currentItem()->pixmap(0) : 0;
88 if ( pix && pix->width() < r.width() )
89 r.setLeft( r.left() + pix->width() + 4 );
90 if ( r != ed->geometry() )
94static inline bool checkInsertIndex(
const char *method,
const char * name,
95 int count,
int *index)
97 bool range_err = (*index > count);
98#if defined(TQT_CHECK_RANGE)
100 tqWarning(
"QComboView::%s: (%s) Index %d out of range",
101 method, name ? name :
"<no name>", *index );
112static inline bool checkIndex(
const char *method,
const char * name,
113 int count,
int index )
115 bool range_err = (index >= count);
116#if defined(TQT_CHECK_RANGE)
118 tqWarning(
"QComboView::%s: (%s) Index %i out of range",
119 method, name ? name :
"<no name>", index );
141 : TQWidget( parent, name, WResizeNoErase )
143 d =
new QComboViewData(
this );
147 d->maxCount = INT_MAX;
150 d->autoresize =
false;
152 d->arrowDown =
false;
153 d->discardNextMousePress =
false;
154 d->shortClick =
false;
155 d->useCompletion =
false;
157 d->completeNow =
false;
158 d->completionTimer =
new TQTimer(
this );
160 setFocusPolicy( TQWidget::StrongFocus );
165 setBackgroundMode( PaletteButton, PaletteBase );
179void QComboView::setDuplicatesEnabled(
bool enable )
181 d->duplicatesEnabled = enable;
184bool QComboView::duplicatesEnabled()
const
186 return d->duplicatesEnabled;
189int QComboView::childCount()
const
191 return d->listView()->childCount();
201 d->listView()->resize( 0, 0 );
202 d->listView()->clear();
206 d->ed->setText( TQString::fromLatin1(
"") );
207 d->updateLinedGeometry();
212TQListViewItem *QComboView::currentItem()
const
217void QComboView::setCurrentItem( TQListViewItem *item )
219 if ( item == d->current && !d->ed ) {
228 d->updateLinedGeometry();
236 d->ed->setText( item->text(0) );
238 d->updateLinedGeometry();
240 if ( d->listView() ) {
241 d->listView()->setCurrentItem( item );
243 internalHighlight( item );
249 d->listView()->ensureItemVisible(item);
252bool QComboView::autoResize()
const
254 return d->autoresize;
257void QComboView::setAutoResize(
bool enable )
259 if ( (
bool)d->autoresize != enable ) {
260 d->autoresize = enable;
276 if ( isVisible() && d->sizeHint.isValid() )
281 TQFontMetrics fm = fontMetrics();
283 int maxW = childCount() ? 18 : 7 * fm.width(TQChar(
'x')) + 18;
284 int maxH = TQMAX( fm.lineSpacing(), 14 ) + 2;
292 d->sizeHint = (style().sizeFromContents(TQStyle::CT_ComboBox,
this,
293 TQSize(maxW, maxH)).expandedTo(TQApplication::globalStrut()));
305void QComboView::internalActivate( TQListViewItem * item )
312 d->updateLinedGeometry();
321 TQString t( item->text(0) );
325 d->updateLinedGeometry();
327 emit activated( item );
339void QComboView::internalHighlight( TQListViewItem * item )
346 d->updateLinedGeometry();
350 emit highlighted( item );
351 TQString t = item->text(0);
353 emit highlighted( t );
361void QComboView::internalClickTimeout()
363 d->shortClick =
false;
373 TQWidget::setPalette( palette );
376 d->listView()->setPalette( palette );
387 d->sizeHint = TQSize();
388 TQWidget::setFont( font );
389 d->listView()->setFont( font );
391 d->ed->setFont( font );
403 d->updateLinedGeometry();
404 d->listView()->resize( width(), d->listView()->height() );
405 TQWidget::resizeEvent( e );
414 const TQColorGroup & g = colorGroup();
417 TQStyle::SFlags flags = TQStyle::Style_Default;
419 flags |= TQStyle::Style_Enabled;
421 flags |= TQStyle::Style_HasFocus;
423 if ( width() < 5 || height() < 5 ) {
424 qDrawShadePanel( &p, rect(), g,
false, 2,
425 &g.brush( TQColorGroup::Button ) );
430 style().drawComplexControl( TQStyle::CC_ComboBox, &p,
this, rect(), g,
431 flags, TQStyle::SC_All,
433 TQStyle::SC_ComboBoxArrow :
436 TQRect re = style().querySubControlMetrics( TQStyle::CC_ComboBox,
this,
437 TQStyle::SC_ComboBoxEditField );
438 re = TQStyle::visualRect(re,
this);
442 TQListViewItem * item = d->current;
445 int itemh = d->listView()->fontMetrics().lineSpacing() + 2;
446 p.translate( re.x(), re.y() + (re.height() - itemh)/2 );
447 item->paintCell( &p, d->listView()->colorGroup(), 0, width(), AlignLeft | AlignVCenter );
449 }
else if ( d->listView() && d->listView()->currentItem( ) && d->current ) {
450 TQListViewItem * item = d->current ;
451 const TQPixmap *pix = item->pixmap(0);
453 p.fillRect( re.x(), re.y(), pix->width() + 4, re.height(),
454 colorGroup().brush( TQColorGroup::Base ) );
455 p.drawPixmap( re.x() + 2, re.y() +
456 ( re.height() - pix->height() ) / 2, *pix );
459 p.setClipping(
false );
468 if ( e->button() != TQt::LeftButton )
470 if ( d->discardNextMousePress ) {
471 d->discardNextMousePress =
false;
474 TQRect arrowRect = style().querySubControlMetrics( TQStyle::CC_ComboBox,
this,
475 TQStyle::SC_ComboBoxArrow);
476 arrowRect = TQStyle::visualRect(arrowRect,
this);
480 arrowRect.setHeight( TQMAX( height() - (2 * arrowRect.y()), arrowRect.height() ) );
482 if ( childCount() && ( !editable() || arrowRect.contains( e->pos() ) ) ) {
483 d->arrowPressed =
false;
488 if ( arrowRect.contains( e->pos() ) ) {
489 d->arrowPressed =
true;
493 TQTimer::singleShot( 200,
this, TQ_SLOT(internalClickTimeout()));
494 d->shortClick =
true;
526 TQListViewItem *c = currentItem();
527 if ( ( e->key() == Key_F4 && e->state() == 0 ) ||
528 ( e->key() == Key_Down && (e->state() & AltButton) ) ||
529 ( !d->ed && e->key() == Key_Space ) ) {
530 if ( childCount() ) {
534 }
else if ( e->key() == Key_Up ) {
537 if (c && c->itemAbove() )
538 setCurrentItem( c->itemAbove() );
541 }
else if ( e->key() == Key_Down ) {
542 if ((!c) && (
listView()->firstChild()))
544 setCurrentItem(
listView()->firstChild());
547 if ( c && c->itemBelow() )
548 setCurrentItem( c->itemBelow() );
551 }
else if ( e->key() == Key_Home && ( !d->ed || !d->ed->hasFocus() ) ) {
553 setCurrentItem(
listView()->firstChild() );
556 }
else if ( e->key() == Key_End && ( !d->ed || !d->ed->hasFocus() ) ) {
558 setCurrentItem(
listView()->lastItem() );
561 }
else if ( !d->ed && e->ascii() >= 32 && !e->text().isEmpty() ) {
562 if ( !d->completionTimer->isActive() ) {
564 c = completionIndex( e->text(), c->itemBelow() );
567 d->completeAt = e->text().length();
572 d->completionTimer->stop();
573 TQString ct = currentText().left( d->completeAt ) + e->text();
574 c = completionIndex( ct, c );
575 if ( c == 0 && d->completeAt > 0 ) {
576 c = completionIndex( e->text(),
listView()->firstChild() );
582 d->completeAt = ct.length();
587 d->completionTimer->start( 400,
true );
594 if ( childCount() && c && !c->text(0).isNull() )
595 emit activated( c->text(0) );
599TQString QComboView::currentText()
const
602 return d->ed->text();
603 else if ( d->current )
604 return currentItem()->text(0);
614 TQWidget::focusInEvent( e );
615 d->completeNow =
false;
626 TQWidget::focusOutEvent( e );
627 d->completeNow =
false;
639 TQApplication::sendEvent( d->listView(), e );
641 if ( e->delta() > 0 ) {
642 TQListViewItem *c = currentItem();
643 if ( c && c->itemAbove() ) {
644 setCurrentItem( c->itemAbove() );
645 emit activated( currentItem() );
646 emit activated( currentText() );
649 TQListViewItem *c = currentItem();
650 if ( c && c->itemBelow() ) {
651 setCurrentItem( c->itemBelow() );
652 emit activated( currentItem() );
653 emit activated( currentText() );
660int childCount(TQListViewItem *it)
663 TQListViewItem * myChild = it->firstChild();
665 count += childCount(myChild);
666 myChild = myChild->nextSibling();
671int childCount(TQListView *lv)
674 TQListViewItem * myChild = lv->firstChild();
676 count += childCount(myChild);
678 myChild = myChild->nextSibling();
688static int listHeight( TQListView *l,
int )
695 int ch = childCount(l);
699 prefH = ch * l->firstChild()->height();
702 prefH = l->sizeHint().height();
704 if (l->header()->isVisible())
705 prefH += l->header()->sizeHint().height();
724 TQListView* lb = d->listView();
725 lb->triggerUpdate( );
726 lb->installEventFilter(
this );
727 lb->viewport()->installEventFilter(
this );
728 d->mouseWasInsidePopup =
false;
731 int h = listHeight( lb, d->sizeLimit );
732 TQRect screen = TQApplication::desktop()->availableGeometry(
const_cast<QComboView*
>(
this) );
736 int sw = screen.width();
737 int sh = screen.height();
738 TQPoint pos = mapToGlobal( TQPoint(0,height()) );
744 if ( x + w > sx + sw )
748 if (y + h > sy+sh && y - h - height() >= 0 )
749 y = y - h - height();
751 style().querySubControlMetrics( TQStyle::CC_ComboBox,
this,
752 TQStyle::SC_ComboBoxListBoxPopup,
753 TQStyleOption( x, y, w, h ) );
755 rect.setRect( x, y, w, h );
756 lb->setGeometry( rect );
759 bool block = lb->signalsBlocked();
760 lb->blockSignals(
true );
761 TQListViewItem *currentLBItem = d->current ;
762 lb->setCurrentItem( currentLBItem );
764 if ( currentLBItem && currentLBItem->isSelectable() && !currentLBItem->isSelected() )
765 lb->setSelected( currentLBItem,
true );
766 lb->blockSignals( block );
767 lb->setVScrollBarMode(TQScrollView::Auto);
787 TQBitmap bm( size() );
791 TQPainter p( &bm,
this );
792 style().drawComplexControlMask(TQStyle::CC_ComboBox, &p,
this, rect());
802void QComboView::popDownListView()
804 d->listView()->removeEventFilter(
this );
805 d->listView()->viewport()->removeEventFilter(
this );
806 d->listView()->hide();
807 d->listView()->setCurrentItem( d->current );
808 if ( d->arrowDown ) {
809 d->arrowDown =
false;
821void QComboView::reIndex()
830void QComboView::currentChanged()
852 else if (
object == d->ed ) {
853 if ( event->type() == TQEvent::KeyPress ) {
854 bool isAccepted = ( (TQKeyEvent*)event )->isAccepted();
856 if ( ((TQKeyEvent *)event)->isAccepted() ) {
857 d->completeNow =
false;
859 }
else if ( ((TQKeyEvent *)event)->key() != Key_End ) {
860 d->completeNow =
true;
861 d->completeAt = d->ed->cursorPosition();
864 ( (TQKeyEvent*)event )->accept();
866 ( (TQKeyEvent*)event )->ignore();
867 }
else if ( event->type() == TQEvent::KeyRelease ) {
868 d->completeNow =
false;
869 keyReleaseEvent( (TQKeyEvent *)event );
870 return ((TQKeyEvent *)event)->isAccepted();
871 }
else if ( event->type() == TQEvent::FocusIn ) {
873 }
else if ( event->type() == TQEvent::FocusOut ) {
875 }
else if ( d->useCompletion && d->completeNow ) {
876 if ( !d->ed->text().isNull() &&
877 d->ed->cursorPosition() > d->completeAt &&
878 d->ed->cursorPosition() == (
int)d->ed->text().length() ) {
879 d->completeNow =
false;
880 TQString ct( d->ed->text() );
881 TQListViewItem *i = completionIndex( ct, currentItem() );
883 TQString it = i->text(0);
884 d->ed->validateAndSet( it, ct.length(),
885 ct.length(), it.length() );
889 }
else if ( (
object == d->listView() ||
890 object == d->listView()->viewport() )) {
891 TQMouseEvent *e = (TQMouseEvent*)event;
892 switch( event->type() ) {
893 case TQEvent::MouseMove:
894 if ( !d->mouseWasInsidePopup ) {
896 TQPoint pos = e->pos();
897 if ( d->listView()->rect().contains( pos ) )
898 d->mouseWasInsidePopup =
true;
900 if ( d->arrowPressed ) {
902 comboPos = mapFromGlobal( d->listView()->mapToGlobal(pos) );
904 style().querySubControlMetrics( TQStyle::CC_ComboBox,
this,
905 TQStyle::SC_ComboBoxArrow);
906 arrowRect = TQStyle::visualRect(arrowRect,
this);
907 if ( arrowRect.contains( comboPos ) ) {
908 if ( !d->arrowDown ) {
913 if ( d->arrowDown ) {
914 d->arrowDown =
false;
919 }
else if ((e->state() & ( TQt::RightButton | TQt::LeftButton | TQt::MidButton ) ) == 0 &&
920 style().styleHint(TQStyle::SH_ComboBox_ListMouseTracking,
this)) {
922 TQWidget *mouseW = TQApplication::widgetAt( e->globalPos(),
true );
924 if ( mouseW == d->listView()->viewport() ) {
925 TQListViewItem *sel = d->listView()->itemAt(e->pos());
928 d->listView()->setCurrentItem(sel);
929 d->listView()->setSelected(sel,
true);
936 case TQEvent::MouseButtonRelease:
937 if ( d->listView()->rect().contains( e->pos() ) ) {
938 TQMouseEvent tmp( TQEvent::MouseButtonDblClick,
939 e->pos(), e->button(), e->state() ) ;
941 TQApplication::sendEvent(
object, &tmp );
944 if ( d->mouseWasInsidePopup ) {
947 d->arrowPressed =
false;
948 if ( d->arrowDown ) {
949 d->arrowDown =
false;
955 case TQEvent::MouseButtonDblClick:
956 case TQEvent::MouseButtonPress:
957 if ( !d->listView()->rect().contains( e->pos() ) ) {
958 TQPoint globalPos = d->listView()->mapToGlobal(e->pos());
959 if ( TQApplication::widgetAt( globalPos,
true ) ==
this ) {
960 d->discardNextMousePress =
true;
967 case TQEvent::KeyPress:
968 switch( ((TQKeyEvent *)event)->key() ) {
971 if ( !(((TQKeyEvent *)event)->state() & AltButton) )
995 return TQWidget::eventFilter(
object, event );
1005TQListViewItem *QComboView::completionIndex(
const TQString & prefix,
1006 TQListViewItem *startingAt )
const
1008 TQListViewItem *start = startingAt;
1019 TQString match = prefix.lower();
1020 if ( match.length() < 1 )
1024 TQListViewItem *i = start;
1026 current = i->text(0).lower();
1027 if ( current.startsWith( match ) )
1032 }
while ( i != start );
1037int QComboView::sizeLimit()
const
1039 return d ? d->sizeLimit : INT_MAX;
1042void QComboView::setSizeLimit(
int lines )
1044 d->sizeLimit = lines;
1061QComboView::Policy QComboView::insertionPolicy()
const
1066void QComboView::setInsertionPolicy( Policy policy )
1077void QComboView::returnPressed()
1079 TQString s( d->ed->text() );
1084 TQListViewItem *c = 0;
1085 bool doInsert =
true;
1086 if ( !d->duplicatesEnabled ) {
1093 if ( insertionPolicy() != NoInsertion ) {
1100 switch ( insertionPolicy() ) {
1102 if ( s != currentItem()->text(0) )
1103 currentItem()->setText(0, s);
1104 emit activated( currentItem() );
1105 emit activated( s );
1108 emit activated( s );
1118 if (currentItem() && currentItem()->itemAbove())
1119 c =
new TQListViewItem(
listView(), currentItem()->itemAbove(), s);
1127 if (currentItem() && currentItem()->itemBelow())
1128 c =
new TQListViewItem(
listView(), currentItem()->itemBelow(), s);
1140 setCurrentItem( c );
1141 emit activated( c );
1142 emit activated( s );
1152 TQWidget::setEnabled( enable );
1169 d->ed->setValidator( v );
1182 return d && d->ed ? d->ed->validator() : 0;
1193 d->ed->setValidator( 0 );
1211 delete d->listView();
1213 newListView->reparent(
this, WType_Popup, TQPoint(0,0),
false );
1214 d->setListView( newListView );
1215 d->listView()->setFont( font() );
1216 d->listView()->setPalette( palette() );
1219 d->listView()->setFrameStyle( TQFrame::Box | TQFrame::Plain );
1220 d->listView()->setLineWidth( 1 );
1223 d->listView()->resize( 100, 10 );
1225 if (d->listView()->firstChild())
1226 d->current = d->listView()->firstChild();
1243 connect( d->listView(), TQ_SIGNAL(returnPressed(TQListViewItem*)),
1244 TQ_SLOT(internalActivate(TQListViewItem*)));
1245 connect( d->listView(), TQ_SIGNAL(doubleClicked(TQListViewItem*)),
1246 TQ_SLOT(internalActivate(TQListViewItem*)));
1247 connect( d->listView(), TQ_SIGNAL(doubleClicked(TQListViewItem*)),
1248 TQ_SLOT(checkState(TQListViewItem*)));
1249 connect( d->listView(), TQ_SIGNAL(currentChanged(TQListViewItem*)),
1250 TQ_SLOT(internalHighlight(TQListViewItem*)));
1251 connect( d->listView(), TQ_SIGNAL(selectionChanged(TQListViewItem*)),
1252 TQ_SLOT(internalHighlight(TQListViewItem*)));
1266 return d ? d->listView() : 0;
1314 d->updateLinedGeometry();
1315 d->ed->setText( newText );
1319void QComboView::setAutoCompletion(
bool enable )
1321 d->useCompletion = enable;
1322 d->completeNow =
false;
1326bool QComboView::autoCompletion()
const
1328 return d->useCompletion;
1335 d->sizeHint = TQSize();
1337 d->updateLinedGeometry();
1338 TQWidget::styleChange( s );
1341bool QComboView::editable()
const
1346void QComboView::setEditable(
bool y )
1348 if ( y == editable() )
1354 if ( currentItem() )
1361 setFocusPolicy( TQWidget::StrongFocus );
1367void QComboView::setUpListView()
1369 d->setListView(
new TQListView(
this,
"in-combo", WType_Popup ) );
1371 d->listView()->setFont( font() );
1372 d->listView()->setPalette( palette() );
1375 d->listView()->setFrameStyle( TQFrame::Box | TQFrame::Plain );
1376 d->listView()->setLineWidth( 1 );
1377 d->listView()->setRootIsDecorated(
false );
1378 d->listView()->setAllColumnsShowFocus(
true);
1379 d->listView()->addColumn(
"");
1380 d->listView()->resize( 100, 10 );
1381 d->listView()->setResizeMode(TQListView::LastColumn);
1383 if (d->listView()->firstChild())
1384 d->current = d->listView()->firstChild();
1386 d->listView()->header()->hide();
1388 connect( d->listView(), TQ_SIGNAL(returnPressed(TQListViewItem*)),
1389 TQ_SLOT(internalActivate(TQListViewItem*)));
1390 connect( d->listView(), TQ_SIGNAL(doubleClicked(TQListViewItem*)),
1391 TQ_SLOT(internalActivate(TQListViewItem*)));
1392 connect( d->listView(), TQ_SIGNAL(doubleClicked(TQListViewItem*)),
1393 TQ_SLOT(checkState(TQListViewItem*)));
1394 connect( d->listView(), TQ_SIGNAL(currentChanged(TQListViewItem*)),
1395 TQ_SLOT(internalHighlight(TQListViewItem*)));
1396 connect( d->listView(), TQ_SIGNAL(selectionChanged(TQListViewItem*)),
1397 TQ_SLOT(internalHighlight(TQListViewItem*)));
1401void QComboView::setUpLineEdit()
1404 setLineEdit(
new TQLineEdit(
this,
"combo edit" ) );
1414#if defined(TQT_CHECK_NULL)
1415 Q_ASSERT( edit != 0 );
1420 edit->setText( currentText() );
1422 int start = 0, end = 0;
1423 d->ed->getSelection( &start, &end );
1424 edit->setSelection( start, end );
1425 edit->setCursorPosition( d->ed->cursorPosition() );
1426 edit->setEdited( d->ed->edited() );
1432 if ( edit->parent() !=
this ) {
1433 edit->reparent(
this, TQPoint(0,0),
false );
1434 edit->setFont( font() );
1437 connect (edit, TQ_SIGNAL( textChanged(
const TQString& ) ),
1438 this, TQ_SIGNAL( textChanged(
const TQString& ) ) );
1439 connect( edit, TQ_SIGNAL(returnPressed()), TQ_SLOT(returnPressed()) );
1441 edit->setFrame(
false );
1442 d->updateLinedGeometry();
1443 edit->installEventFilter(
this );
1444 setFocusProxy( edit );
1445 setFocusPolicy( TQWidget::StrongFocus );
1456void QComboView::setCurrentText(
const TQString& txt )
1461 setCurrentItem( i );
1463 d->ed->setText( txt );
1464 else if (currentItem())
1465 currentItem()->setText(0, txt);
1468void QComboView::checkState( TQListViewItem * item)
1470 item->setOpen(!item->isOpen());
1473void QComboView::setCurrentActiveItem( TQListViewItem * item )
1475 if ( item == d->current && !d->ed ) {
1482 d->ed->setText( item->text(0) );
1483 d->ed->setCursorPosition(0);
1485 d->updateLinedGeometry();
1487 if ( d->listView() ) {
1488 d->listView()->setCurrentItem( item );
1489 emit activated( item );
1490 emit activated( item->text(0) );
1492 internalHighlight( item );
1493 internalActivate( item );
1498 d->listView()->ensureItemVisible(item);
1501#include "qcomboview.moc"
void setPalette(const TQPalette &)
void focusInEvent(TQFocusEvent *e)
virtual void setEditText(const TQString &)
void wheelEvent(TQWheelEvent *e)
bool eventFilter(TQObject *object, TQEvent *event)
TQLineEdit * lineEdit() const
void mousePressEvent(TQMouseEvent *)
void mouseDoubleClickEvent(TQMouseEvent *)
void setFont(const TQFont &)
virtual void setListView(TQListView *)
virtual void setLineEdit(TQLineEdit *edit)
void focusOutEvent(TQFocusEvent *e)
virtual void setValidator(const TQValidator *)
QComboView(bool rw, TQWidget *parent=0, const char *name=0)
void styleChange(TQStyle &)
const TQValidator * validator() const
TQListView * listView() const
void keyPressEvent(TQKeyEvent *e)
void resizeEvent(TQResizeEvent *)
void paintEvent(TQPaintEvent *)
void mouseReleaseEvent(TQMouseEvent *)
void mouseMoveEvent(TQMouseEvent *)