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