• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDEUI

keditlistwidget.cpp

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

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal