00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <qapplication.h>
00034 #include <qevent.h>
00035 #include <qstyle.h>
00036
00037 #include <opie2/ocompletionbox.h>
00038
00039 #define OListBox QListBox
00040
00041 class OCompletionBox::OCompletionBoxPrivate
00042 {
00043 public:
00044 QWidget *m_parent;
00045 QString cancelText;
00046 bool tabHandling;
00047 bool down_workaround;
00048 };
00049
00050 OCompletionBox::OCompletionBox( QWidget *parent, const char *name )
00051 :OListBox( parent, name, WType_Popup )
00052 {
00053 d = new OCompletionBoxPrivate;
00054 d->m_parent = parent;
00055 d->tabHandling = true;
00056 d->down_workaround = false;
00057
00058 setColumnMode( 1 );
00059 setLineWidth( 1 );
00060 setFrameStyle( QFrame::Box | QFrame::Plain );
00061
00062 if ( parent )
00063 setFocusProxy( parent );
00064 else
00065 setFocusPolicy( NoFocus );
00066
00067 setVScrollBarMode( Auto );
00068 setHScrollBarMode( AlwaysOff );
00069
00070 connect( this, SIGNAL( doubleClicked(QListBoxItem*)),
00071 SLOT( slotActivated(QListBoxItem*)) );
00072
00073
00074 connect( this, SIGNAL( currentChanged(QListBoxItem*)),
00075 SLOT( slotCurrentChanged() ));
00076 connect( this, SIGNAL( clicked(QListBoxItem*)),
00077 SLOT( slotItemClicked(QListBoxItem*)) );
00078 }
00079
00080 OCompletionBox::~OCompletionBox()
00081 {
00082 d->m_parent = 0L;
00083 delete d;
00084 }
00085
00086 QStringList OCompletionBox::items() const
00087 {
00088 QStringList list;
00089 for ( uint i = 0; i < count(); i++ ) {
00090 list.append( text( i ) );
00091 }
00092 return list;
00093 }
00094
00095 void OCompletionBox::slotActivated( QListBoxItem *item )
00096 {
00097 if ( !item )
00098 return;
00099
00100 hide();
00101 emit activated( item->text() );
00102 }
00103
00104 bool OCompletionBox::eventFilter( QObject *o, QEvent *e )
00105 {
00106 int type = e->type();
00107
00108 if ( o == d->m_parent ) {
00109 if ( isVisible() ) {
00110 if ( type == QEvent::KeyPress ) {
00111 QKeyEvent *ev = static_cast<QKeyEvent *>( e );
00112 switch ( ev->key() ) {
00113 case Key_BackTab:
00114 if ( d->tabHandling ) {
00115 up();
00116 ev->accept();
00117 return true;
00118 }
00119 break;
00120 case Key_Tab:
00121 if ( d->tabHandling ) {
00122 down();
00123 ev->accept();
00124 return true;
00125 }
00126 break;
00127 case Key_Down:
00128 down();
00129 ev->accept();
00130 return true;
00131 case Key_Up:
00132 up();
00133 ev->accept();
00134 return true;
00135 case Key_Prior:
00136 pageUp();
00137 ev->accept();
00138 return true;
00139 case Key_Next:
00140 pageDown();
00141 ev->accept();
00142 return true;
00143 case Key_Escape:
00144 cancelled();
00145 ev->accept();
00146 return true;
00147 case Key_Enter:
00148 case Key_Return:
00149 if ( ev->state() & ShiftButton ) {
00150 hide();
00151 ev->accept();
00152 return true;
00153 }
00154 break;
00155 default:
00156 break;
00157 }
00158 }
00159 else if ( type == QEvent::AccelOverride ) {
00160
00161
00162 QKeyEvent *ev = static_cast<QKeyEvent *>( e );
00163 switch ( ev->key() ) {
00164 case Key_Tab:
00165 case Key_BackTab:
00166 case Key_Down:
00167 case Key_Up:
00168 case Key_Prior:
00169 case Key_Next:
00170 case Key_Escape:
00171 case Key_Enter:
00172 case Key_Return:
00173 ev->accept();
00174 return true;
00175 break;
00176 default:
00177 break;
00178 }
00179 }
00180
00181
00182 else if ( type == QEvent::FocusOut || type == QEvent::Resize ||
00183 type == QEvent::Close || type == QEvent::Hide ||
00184 type == QEvent::Move ) {
00185 hide();
00186 }
00187 else if ( type == QEvent::Move )
00188 move( d->m_parent->mapToGlobal(QPoint(0, d->m_parent->height())));
00189 else if ( type == QEvent::Resize )
00190 resize( sizeHint() );
00191 }
00192 }
00193
00194
00195 else if ( type == QEvent::MouseButtonPress ) {
00196 QMouseEvent *ev = static_cast<QMouseEvent *>( e );
00197 if ( !rect().contains( ev->pos() ))
00198 hide();
00199 }
00200
00201 return OListBox::eventFilter( o, e );
00202 }
00203
00204
00205 void OCompletionBox::popup()
00206 {
00207 if ( count() == 0 )
00208 hide();
00209 else {
00210 ensureCurrentVisible();
00211 bool block = signalsBlocked();
00212 blockSignals( true );
00213 setCurrentItem( 0 );
00214 blockSignals( block );
00215 clearSelection();
00216 if ( !isVisible() )
00217 show();
00218 else if ( size().height() < sizeHint().height() )
00219 resize( sizeHint() );
00220 }
00221 }
00222
00223 void OCompletionBox::show()
00224 {
00225 resize( sizeHint() );
00226
00227 if ( d->m_parent )
00228 {
00229
00230 QWidget *screen = QApplication::desktop();
00231
00232 QPoint orig = d->m_parent->mapToGlobal( QPoint(0, d->m_parent->height()) );
00233 int x = orig.x();
00234 int y = orig.y();
00235
00236 if ( x + width() > screen->width() )
00237 x = screen->width() - width();
00238 if (y + height() > screen->height() )
00239 y = y - height() - d->m_parent->height();
00240
00241 move( x, y);
00242 qApp->installEventFilter( this );
00243 }
00244
00245
00246
00247
00248
00249 OListBox::show();
00250 }
00251
00252 void OCompletionBox::hide()
00253 {
00254 if ( d->m_parent )
00255 qApp->removeEventFilter( this );
00256 d->cancelText = QString::null;
00257 OListBox::hide();
00258 }
00259
00260 QSize OCompletionBox::sizeHint() const
00261 {
00262 int ih = itemHeight();
00263 int h = QMIN( 15 * ih, (int) count() * ih ) +1;
00264 h = QMAX( h, OListBox::minimumSizeHint().height() );
00265
00266 int w = (d->m_parent) ? d->m_parent->width() : OListBox::minimumSizeHint().width();
00267 w = QMAX( OListBox::minimumSizeHint().width(), w );
00268 return QSize( w, h );
00269 }
00270
00271 void OCompletionBox::down()
00272 {
00273 int i = currentItem();
00274
00275 if ( i == 0 && d->down_workaround ) {
00276 d->down_workaround = false;
00277 setCurrentItem( 0 );
00278 setSelected( 0, true );
00279 emit highlighted( currentText() );
00280 }
00281
00282 else if ( i < (int) count() - 1 )
00283 setCurrentItem( i + 1 );
00284 }
00285
00286 void OCompletionBox::up()
00287 {
00288 if ( currentItem() > 0 )
00289 setCurrentItem( currentItem() - 1 );
00290 }
00291
00292 void OCompletionBox::pageDown()
00293 {
00294 int i = currentItem() + numItemsVisible();
00295 i = i > (int)count() - 1 ? (int)count() - 1 : i;
00296 setCurrentItem( i );
00297 }
00298
00299 void OCompletionBox::pageUp()
00300 {
00301 int i = currentItem() - numItemsVisible();
00302 i = i < 0 ? 0 : i;
00303 setCurrentItem( i );
00304 }
00305
00306 void OCompletionBox::home()
00307 {
00308 setCurrentItem( 0 );
00309 }
00310
00311 void OCompletionBox::end()
00312 {
00313 setCurrentItem( count() -1 );
00314 }
00315
00316 void OCompletionBox::setTabHandling( bool enable )
00317 {
00318 d->tabHandling = enable;
00319 }
00320
00321 bool OCompletionBox::isTabHandling() const
00322 {
00323 return d->tabHandling;
00324 }
00325
00326 void OCompletionBox::setCancelledText( const QString& text )
00327 {
00328 d->cancelText = text;
00329 }
00330
00331 QString OCompletionBox::cancelledText() const
00332 {
00333 return d->cancelText;
00334 }
00335
00336 void OCompletionBox::cancelled()
00337 {
00338 if ( !d->cancelText.isNull() )
00339 emit userCancelled( d->cancelText );
00340 if ( isVisible() )
00341 hide();
00342 }
00343
00344 class OCompletionBoxItem : public QListBoxItem
00345 {
00346 public:
00347 void reuse( const QString &text ) { setText( text ); }
00348 };
00349
00350
00351 void OCompletionBox::insertItems( const QStringList& items, int index )
00352 {
00353 bool block = signalsBlocked();
00354 blockSignals( true );
00355 insertStringList( items, index );
00356 blockSignals( block );
00357 d->down_workaround = true;
00358 }
00359
00360 void OCompletionBox::setItems( const QStringList& items )
00361 {
00362 bool block = signalsBlocked();
00363 blockSignals( true );
00364
00365 QListBoxItem* item = firstItem();
00366 if ( !item ) {
00367 insertStringList( items );
00368 }
00369 else {
00370 for ( QStringList::ConstIterator it = items.begin(); it != items.end(); it++) {
00371 if ( item ) {
00372 ((OCompletionBoxItem*)item)->reuse( *it );
00373 item = item->next();
00374 }
00375 else {
00376 insertItem( new QListBoxText( *it ) );
00377 }
00378 }
00379 QListBoxItem* tmp = item;
00380 while ( (item = tmp ) ) {
00381 tmp = item->next();
00382 delete item;
00383 }
00384 triggerUpdate( false );
00385 }
00386
00387 blockSignals( block );
00388 d->down_workaround = true;
00389 }
00390
00391 void OCompletionBox::slotCurrentChanged()
00392 {
00393 d->down_workaround = false;
00394 }
00395
00396 void OCompletionBox::slotItemClicked( QListBoxItem *item )
00397 {
00398 if ( item )
00399 {
00400 if ( d->down_workaround ) {
00401 d->down_workaround = false;
00402 emit highlighted( item->text() );
00403 }
00404
00405 hide();
00406 emit activated( item->text() );
00407 }
00408 }