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