00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "keditlistbox.h"
00022
00023 #include <QtCore/QStringList>
00024 #include <QtGui/QKeyEvent>
00025 #include <QtGui/QLabel>
00026 #include <QtGui/QLayout>
00027 #include <QtGui/QListView>
00028
00029 #include <kcombobox.h>
00030 #include <kdebug.h>
00031 #include <kdialog.h>
00032 #include <klineedit.h>
00033 #include <klocale.h>
00034 #include <knotification.h>
00035 #include <kpushbutton.h>
00036
00037 #include <assert.h>
00038
00039 class KEditListBoxPrivate
00040 {
00041 public:
00042 KEditListBoxPrivate( KEditListBox* parent )
00043 : lineEdit(0),
00044 editingWidget(0),
00045 q(parent) {
00046 }
00047 QListView *listView;
00048 QPushButton *servUpButton, *servDownButton;
00049 QPushButton *servNewButton, *servRemoveButton;
00050 KLineEdit *lineEdit;
00051 QWidget* editingWidget;
00052 QGridLayout* mainLayout;
00053 QStringListModel *model;
00054
00055 bool checkAtEntering;
00056 KEditListBox::Buttons buttons;
00057
00058 void init( bool checkAtEntering = false, KEditListBox::Buttons buttons = KEditListBox::All,
00059 QWidget *representationWidget = 0 );
00060 void setEditor( KLineEdit* lineEdit, QWidget* representationWidget = 0 );
00061 void updateButtonState();
00062 QModelIndex selectedIndex();
00063
00064 private:
00065 KEditListBox* q;
00066 };
00067
00068
00069 void KEditListBoxPrivate::init( bool checkAtEntering, KEditListBox::Buttons newButtons,
00070 QWidget *representationWidget )
00071 {
00072 checkAtEntering = checkAtEntering;
00073
00074 servNewButton = servRemoveButton = servUpButton = servDownButton = 0L;
00075 q->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,
00076 QSizePolicy::MinimumExpanding));
00077
00078 mainLayout = new QGridLayout(q);
00079 mainLayout->setMargin( KDialog::marginHint() );
00080 mainLayout->setSpacing( KDialog::spacingHint() );
00081 mainLayout->setRowStretch( 6, 1 );
00082
00083 model = new QStringListModel();
00084 listView = new QListView(q);
00085
00086 listView->setModel(model);
00087
00088 mainLayout->addWidget(listView, 2, 0, 5, 1);
00089
00090 setEditor( lineEdit, representationWidget );
00091
00092 buttons = 0;
00093 q->setButtons( newButtons );
00094
00095 q->connect(listView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
00096 SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection&)));
00097 }
00098
00099
00100 void KEditListBoxPrivate::setEditor( KLineEdit* newLineEdit, QWidget* representationWidget )
00101 {
00102 if (editingWidget != lineEdit &&
00103 editingWidget != representationWidget) {
00104 delete editingWidget;
00105 }
00106 if (lineEdit != newLineEdit) {
00107 delete lineEdit;
00108 }
00109 lineEdit = newLineEdit ? newLineEdit : new KLineEdit(q);
00110 editingWidget = representationWidget ?
00111 representationWidget : lineEdit;
00112
00113 if ( representationWidget )
00114 representationWidget->setParent(q);
00115
00116 mainLayout->addWidget(editingWidget,1,0,1,2);
00117
00118 lineEdit->setTrapReturnKey(true);
00119 lineEdit->installEventFilter(q);
00120
00121 q->connect(lineEdit,SIGNAL(textChanged(const QString&)),SLOT(typedSomething(const QString&)));
00122 q->connect(lineEdit,SIGNAL(returnPressed()),SLOT(addItem()));
00123
00124
00125 q->typedSomething( lineEdit->text() );
00126
00127
00128
00129 q->setTabOrder(editingWidget, listView);
00130 QWidget* w = listView;
00131 if (servNewButton) {
00132 q->setTabOrder(w,servNewButton);
00133 w = servNewButton;
00134 }
00135 if (servRemoveButton) {
00136 q->setTabOrder(w,servRemoveButton);
00137 w = servRemoveButton;
00138 }
00139 if (servUpButton) {
00140 q->setTabOrder(w,servUpButton);
00141 w = servUpButton;
00142 }
00143 if (servDownButton) {
00144 q->setTabOrder(w,servDownButton);
00145 w = servDownButton;
00146 }
00147 }
00148
00149
00150 void KEditListBoxPrivate::updateButtonState()
00151 {
00152 QModelIndex index = selectedIndex();
00153 if (servUpButton) {
00154 servUpButton->setEnabled(index.isValid());
00155 }
00156 if (servDownButton) {
00157 servDownButton->setEnabled(index.isValid());
00158 }
00159 if (servRemoveButton) {
00160 servRemoveButton->setEnabled(index.isValid());
00161 }
00162 }
00163
00164 QModelIndex KEditListBoxPrivate::selectedIndex()
00165 {
00166 QItemSelectionModel *selection = listView->selectionModel();
00167 const QModelIndexList selectedIndexes = selection->selectedIndexes();
00168 if ( !selectedIndexes.isEmpty() && selectedIndexes[0].isValid() )
00169 return selectedIndexes[0];
00170 else
00171 return QModelIndex();
00172 }
00173
00174
00175 class KEditListBox::CustomEditorPrivate
00176 {
00177 public:
00178 CustomEditorPrivate(KEditListBox::CustomEditor *q):
00179 q(q),
00180 representationWidget(0),
00181 lineEdit(0) {}
00182
00183 KEditListBox::CustomEditor *q;
00184 QWidget *representationWidget;
00185 KLineEdit *lineEdit;
00186 };
00187
00188 KEditListBox::CustomEditor::CustomEditor()
00189 : d(new CustomEditorPrivate(this))
00190 {
00191 }
00192
00193 KEditListBox::CustomEditor::CustomEditor( QWidget *repWidget, KLineEdit *edit )
00194 : d(new CustomEditorPrivate(this))
00195 {
00196 d->representationWidget = repWidget;
00197 d->lineEdit = edit;
00198 }
00199
00200 KEditListBox::CustomEditor::CustomEditor( KComboBox *combo )
00201 : d(new CustomEditorPrivate(this))
00202 {
00203 d->representationWidget = combo;
00204 d->lineEdit = qobject_cast<KLineEdit*>( combo->lineEdit() );
00205 Q_ASSERT( d->lineEdit );
00206 }
00207
00208 KEditListBox::CustomEditor::~CustomEditor()
00209 {
00210 delete d;
00211 }
00212
00213 void KEditListBox::CustomEditor::setRepresentationWidget( QWidget *repWidget )
00214 {
00215 d->representationWidget = repWidget;
00216 }
00217
00218 void KEditListBox::CustomEditor::setLineEdit( KLineEdit *edit )
00219 {
00220 d->lineEdit = edit;
00221 }
00222
00223 QWidget *KEditListBox::CustomEditor::representationWidget() const
00224 {
00225 return d->representationWidget;
00226 }
00227
00228 KLineEdit *KEditListBox::CustomEditor::lineEdit() const
00229 {
00230 return d->lineEdit;
00231 }
00232
00233 KEditListBox::KEditListBox(QWidget *parent)
00234 : QGroupBox(parent), d(new KEditListBoxPrivate(this))
00235 {
00236 d->init();
00237 }
00238
00239 KEditListBox::KEditListBox(const QString &title, QWidget *parent)
00240 :QGroupBox(title, parent), d(new KEditListBoxPrivate(this))
00241 {
00242 d->init();
00243 }
00244
00245 KEditListBox::KEditListBox(QWidget *parent, const char *name,
00246 bool checkAtEntering, Buttons buttons )
00247 :QGroupBox(parent ), d(new KEditListBoxPrivate(this))
00248 {
00249 setObjectName(name);
00250 d->init( checkAtEntering, buttons );
00251 }
00252
00253 KEditListBox::KEditListBox(const QString& title, QWidget *parent,
00254 const char *name, bool checkAtEntering, Buttons buttons)
00255 :QGroupBox(title, parent ), d(new KEditListBoxPrivate(this))
00256 {
00257 setObjectName(name);
00258 d->init( checkAtEntering, buttons );
00259 }
00260
00261 KEditListBox::KEditListBox(const QString& title, const CustomEditor& custom,
00262 QWidget *parent, const char *name,
00263 bool checkAtEntering, Buttons buttons)
00264 :QGroupBox(title, parent), d(new KEditListBoxPrivate(this))
00265 {
00266 setObjectName(name);
00267 d->lineEdit = custom.lineEdit();
00268 d->init( checkAtEntering, buttons, custom.representationWidget() );
00269 }
00270
00271 KEditListBox::~KEditListBox()
00272 {
00273 delete d;
00274 }
00275
00276 void KEditListBox::setCustomEditor( const CustomEditor& editor )
00277 {
00278 d->setEditor( editor.lineEdit(), editor.representationWidget() );
00279 }
00280
00281 QListView *KEditListBox::listView() const
00282 {
00283 return d->listView;
00284 }
00285
00286 KLineEdit *KEditListBox::lineEdit() const
00287 {
00288 return d->lineEdit;
00289 }
00290
00291 QPushButton *KEditListBox::addButton() const
00292 {
00293 return d->servNewButton;
00294 }
00295
00296 QPushButton *KEditListBox::removeButton() const
00297 {
00298 return d->servRemoveButton;
00299 }
00300
00301 QPushButton *KEditListBox::upButton() const
00302 {
00303 return d->servUpButton;
00304 }
00305
00306 QPushButton *KEditListBox::downButton() const
00307 {
00308 return d->servDownButton;
00309 }
00310
00311 int KEditListBox::count() const
00312 {
00313 return int(d->model->rowCount());
00314 }
00315
00316 void KEditListBox::setButtons( Buttons buttons )
00317 {
00318 if ( d->buttons == buttons )
00319 return;
00320
00321 QGridLayout* grid = static_cast<QGridLayout *>( layout() );
00322 if ( ( buttons & Add ) && !d->servNewButton ) {
00323 d->servNewButton = new KPushButton(KIcon("list-add"), i18n("&Add"), this);
00324 d->servNewButton->setEnabled(false);
00325 d->servNewButton->show();
00326 connect(d->servNewButton, SIGNAL(clicked()), SLOT(addItem()));
00327
00328 grid->addWidget(d->servNewButton, 2, 1);
00329 } else if ( ( buttons & Add ) == 0 && d->servNewButton ) {
00330 delete d->servNewButton;
00331 d->servNewButton = 0;
00332 }
00333
00334 if ( ( buttons & Remove ) && !d->servRemoveButton ) {
00335 d->servRemoveButton = new KPushButton(KIcon("list-remove"), i18n("&Remove"), this);
00336 d->servRemoveButton->setEnabled(false);
00337 d->servRemoveButton->show();
00338 connect(d->servRemoveButton, SIGNAL(clicked()), SLOT(removeItem()));
00339
00340 grid->addWidget(d->servRemoveButton, 3, 1);
00341 } else if ( ( buttons & Remove ) == 0 && d->servRemoveButton ) {
00342 delete d->servRemoveButton;
00343 d->servRemoveButton = 0;
00344 }
00345
00346 if ( ( buttons & UpDown ) && !d->servUpButton ) {
00347 d->servUpButton = new KPushButton(KIcon("arrow-up"), i18n("Move &Up"), this);
00348 d->servUpButton->setEnabled(false);
00349 d->servUpButton->show();
00350 connect(d->servUpButton, SIGNAL(clicked()), SLOT(moveItemUp()));
00351
00352 d->servDownButton = new KPushButton(KIcon("arrow-down"), i18n("Move &Down"), this);
00353 d->servDownButton->setEnabled(false);
00354 d->servDownButton->show();
00355 connect(d->servDownButton, SIGNAL(clicked()), SLOT(moveItemDown()));
00356
00357 grid->addWidget(d->servUpButton, 4, 1);
00358 grid->addWidget(d->servDownButton, 5, 1);
00359 } else if ( ( buttons & UpDown ) == 0 && d->servUpButton ) {
00360 delete d->servUpButton; d->servUpButton = 0;
00361 delete d->servDownButton; d->servDownButton = 0;
00362 }
00363
00364 d->buttons = buttons;
00365 }
00366
00367 void KEditListBox::setCheckAtEntering(bool check)
00368 {
00369 d->checkAtEntering = check;
00370 }
00371
00372 bool KEditListBox::checkAtEntering()
00373 {
00374 return d->checkAtEntering;
00375 }
00376
00377 void KEditListBox::typedSomething(const QString& text)
00378 {
00379 if(currentItem() >= 0) {
00380 if(currentText() != d->lineEdit->text())
00381 {
00382
00383
00384
00385 bool block = d->listView->signalsBlocked();
00386 d->listView->blockSignals( true );
00387 QModelIndex currentIndex = d->selectedIndex();
00388 if ( currentIndex.isValid() )
00389 d->model->setData(currentIndex,text);
00390 d->listView->blockSignals( block );
00391 emit changed();
00392 }
00393 }
00394
00395 if ( !d->servNewButton )
00396 return;
00397
00398 if (!d->checkAtEntering)
00399 d->servNewButton->setEnabled(!text.isEmpty());
00400 else
00401 {
00402 if (text.isEmpty())
00403 {
00404 d->servNewButton->setEnabled(false);
00405 }
00406 else
00407 {
00408 QStringList list = d->model->stringList();
00409 bool enable = !list.contains( text, Qt::CaseSensitive );
00410 d->servNewButton->setEnabled( enable );
00411 }
00412 }
00413 }
00414
00415 void KEditListBox::moveItemUp()
00416 {
00417 if (!d->listView->isEnabled())
00418 {
00419 KNotification::beep();
00420 return;
00421 }
00422
00423 QModelIndex index = d->selectedIndex();
00424 if ( index.isValid() ) {
00425 if (index.row() == 0) {
00426 KNotification::beep();
00427 return;
00428 }
00429
00430 QModelIndex aboveIndex = d->model->index( index.row() - 1, index.column() );
00431
00432 QString tmp = d->model->data( aboveIndex, Qt::DisplayRole ).toString();
00433 d->model->setData( aboveIndex, d->model->data( index, Qt::DisplayRole ) );
00434 d->model->setData( index, tmp );
00435
00436 d->listView->selectionModel()->select(index, QItemSelectionModel::Deselect);
00437 d->listView->selectionModel()->select(aboveIndex, QItemSelectionModel::Select);
00438 }
00439
00440 emit changed();
00441 }
00442
00443 void KEditListBox::moveItemDown()
00444 {
00445 if (!d->listView->isEnabled())
00446 {
00447 KNotification::beep();
00448 return;
00449 }
00450
00451 QModelIndex index = d->selectedIndex();
00452 if ( index.isValid() ) {
00453 if (index.row() == d->model->rowCount() - 1) {
00454 KNotification::beep();
00455 return;
00456 }
00457
00458 QModelIndex belowIndex = d->model->index( index.row() + 1, index.column() );
00459
00460 QString tmp = d->model->data( belowIndex, Qt::DisplayRole ).toString();
00461 d->model->setData( belowIndex, d->model->data( index, Qt::DisplayRole ) );
00462 d->model->setData( index, tmp );
00463
00464 d->listView->selectionModel()->select(index, QItemSelectionModel::Deselect);
00465 d->listView->selectionModel()->select(belowIndex, QItemSelectionModel::Select);
00466 }
00467
00468 emit changed();
00469 }
00470
00471 void KEditListBox::addItem()
00472 {
00473
00474
00475
00476 if ( !d->servNewButton || !d->servNewButton->isEnabled() )
00477 return;
00478
00479 QModelIndex currentIndex = d->selectedIndex();
00480
00481 const QString& currentTextLE=d->lineEdit->text();
00482 bool alreadyInList(false);
00483
00484 if (!d->checkAtEntering)
00485 {
00486
00487 if ( currentIndex.isValid() ) {
00488 if ( d->model->data( currentIndex, Qt::DisplayRole ).toString() == currentTextLE )
00489 alreadyInList = true;
00490 }
00491 else
00492 {
00493 alreadyInList = d->model->stringList().contains( currentTextLE, Qt::CaseSensitive );
00494 }
00495 }
00496 if ( d->servNewButton )
00497 d->servNewButton->setEnabled(false);
00498
00499 bool block = d->lineEdit->signalsBlocked();
00500 d->lineEdit->blockSignals(true);
00501 d->lineEdit->clear();
00502 d->lineEdit->blockSignals(block);
00503
00504 d->listView->selectionModel()->setCurrentIndex(currentIndex, QItemSelectionModel::Deselect);
00505
00506 if (!alreadyInList)
00507 {
00508 block = d->listView->signalsBlocked();
00509
00510 if ( currentIndex.isValid() ) {
00511 d->model->setData(currentIndex, currentTextLE );
00512 } else {
00513 QStringList lst;
00514 lst<<currentTextLE;
00515 lst<<d->model->stringList();
00516 d->model->setStringList(lst);
00517 }
00518 emit changed();
00519 emit added( currentTextLE );
00520 }
00521
00522 d->updateButtonState();
00523 }
00524
00525 int KEditListBox::currentItem() const
00526 {
00527 QModelIndex selectedIndex = d->selectedIndex();
00528 if ( selectedIndex.isValid() )
00529 return selectedIndex.row();
00530 else
00531 return -1;
00532 }
00533
00534 void KEditListBox::removeItem()
00535 {
00536 QModelIndex currentIndex = d->selectedIndex();
00537 if ( !currentIndex.isValid() )
00538 return;
00539
00540 if ( currentIndex.row() >= 0 )
00541 {
00542 QString removedText = d->model->data( currentIndex, Qt::DisplayRole ).toString();
00543
00544 d->model->removeRows( currentIndex.row(), 1 );
00545
00546 d->listView->selectionModel()->clear();
00547
00548 emit changed();
00549
00550 emit removed( removedText );
00551 }
00552
00553 d->updateButtonState();
00554 }
00555
00556 void KEditListBox::enableMoveButtons(const QModelIndex &newIndex, const QModelIndex&)
00557 {
00558 int index = newIndex.row();
00559
00560
00561 if(currentText() != d->lineEdit->text())
00562 d->lineEdit->setText(currentText());
00563
00564 bool moveEnabled = d->servUpButton && d->servDownButton;
00565
00566 if (moveEnabled )
00567 {
00568 if (d->model->rowCount() <= 1)
00569 {
00570 d->servUpButton->setEnabled(false);
00571 d->servDownButton->setEnabled(false);
00572 }
00573 else if (index == (d->model->rowCount() - 1))
00574 {
00575 d->servUpButton->setEnabled(true);
00576 d->servDownButton->setEnabled(false);
00577 }
00578 else if (index == 0)
00579 {
00580 d->servUpButton->setEnabled(false);
00581 d->servDownButton->setEnabled(true);
00582 }
00583 else
00584 {
00585 d->servUpButton->setEnabled(true);
00586 d->servDownButton->setEnabled(true);
00587 }
00588 }
00589
00590 if ( d->servRemoveButton )
00591 d->servRemoveButton->setEnabled(true);
00592 }
00593
00594 void KEditListBox::clear()
00595 {
00596 d->lineEdit->clear();
00597 d->model->setStringList( QStringList() );
00598 emit changed();
00599 }
00600
00601 void KEditListBox::insertStringList(const QStringList& list, int index)
00602 {
00603 QStringList content = d->model->stringList();
00604 if ( index > content.count() )
00605 content += list;
00606 else
00607 for ( int i = 0, j = index; i < list.count(); ++i, ++j )
00608 content.insert( j, list[ i ] );
00609
00610 d->model->setStringList( content );
00611 }
00612
00613 void KEditListBox::insertItem(const QString& text, int index)
00614 {
00615 QStringList list = d->model->stringList();
00616
00617 if ( index == -1 )
00618 list.append( text );
00619 else
00620 list.insert( index, text );
00621
00622 d->model->setStringList(list);
00623 }
00624
00625 QString KEditListBox::text(int index) const
00626 {
00627 const QStringList list = d->model->stringList();
00628
00629 return list[ index ];
00630 }
00631
00632 QString KEditListBox::currentText() const
00633 {
00634 QModelIndex index = d->selectedIndex();
00635 if ( !index.isValid() )
00636 return QString();
00637 else
00638 return text( index.row() );
00639 }
00640
00641 QStringList KEditListBox::items() const
00642 {
00643 return d->model->stringList();
00644 }
00645
00646 void KEditListBox::setItems(const QStringList& items)
00647 {
00648 d->model->setStringList(items);
00649 }
00650
00651 KEditListBox::Buttons KEditListBox::buttons() const
00652 {
00653 return d->buttons;
00654 }
00655
00656 void KEditListBox::slotSelectionChanged( const QItemSelection&, const QItemSelection& )
00657 {
00658 d->updateButtonState();
00659 QModelIndex index = d->selectedIndex();
00660 enableMoveButtons(index, QModelIndex());
00661 if (index.isValid()) {
00662 d->lineEdit->setFocus( Qt::OtherFocusReason );
00663 }
00664 }
00665
00666 bool KEditListBox::eventFilter( QObject* o, QEvent* e )
00667 {
00668 if (o == d->lineEdit && e->type() == QEvent::KeyPress ) {
00669 QKeyEvent* keyEvent = (QKeyEvent*)e;
00670 if (keyEvent->key() == Qt::Key_Down ||
00671 keyEvent->key() == Qt::Key_Up) {
00672 return ((QObject*)d->listView)->event(e);
00673 }
00674 }
00675
00676 return false;
00677 }
00678
00679 #include "keditlistbox.moc"