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

KDEUI

keditlistbox.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    2000, 2002 Carsten Pfeiffer <pfeiffer@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
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     // maybe supplied lineedit has some text already
00129     q->typedSomething( lineEdit->text() );
00130 
00131 
00132     // fix tab ordering
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             // IMHO changeItem() shouldn't do anything with the value
00386             // of currentItem() ... like changing it or emitting signals ...
00387             // but TT disagree with me on this one (it's been that way since ages ... grrr)
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->lineEdit->hasAcceptableInput() ) {
00402         d->servNewButton->setEnabled(false);
00403         return;
00404     }
00405 
00406     if (!d->checkAtEntering)
00407         d->servNewButton->setEnabled(!text.isEmpty());
00408     else
00409     {
00410         if (text.isEmpty())
00411         {
00412             d->servNewButton->setEnabled(false);
00413         }
00414         else
00415         {
00416             QStringList list = d->model->stringList();
00417             bool enable = !list.contains( text, Qt::CaseSensitive );
00418             d->servNewButton->setEnabled( enable );
00419         }
00420     }
00421 }
00422 
00423 void KEditListBox::moveItemUp()
00424 {
00425     if (!d->listView->isEnabled())
00426     {
00427         KNotification::beep();
00428         return;
00429     }
00430 
00431     QModelIndex index = d->selectedIndex();
00432     if ( index.isValid() ) {
00433       if (index.row() == 0) {
00434           KNotification::beep();
00435           return;
00436       }
00437 
00438       QModelIndex aboveIndex = d->model->index( index.row() - 1, index.column() );
00439 
00440       QString tmp = d->model->data( aboveIndex, Qt::DisplayRole ).toString();
00441       d->model->setData( aboveIndex, d->model->data( index, Qt::DisplayRole ) );
00442       d->model->setData( index, tmp );
00443 
00444       d->listView->selectionModel()->select(index, QItemSelectionModel::Deselect);
00445       d->listView->selectionModel()->select(aboveIndex, QItemSelectionModel::Select);
00446     }
00447 
00448     emit changed();
00449 }
00450 
00451 void KEditListBox::moveItemDown()
00452 {
00453     if (!d->listView->isEnabled())
00454     {
00455         KNotification::beep();
00456         return;
00457     }
00458 
00459     QModelIndex index = d->selectedIndex();
00460     if ( index.isValid() ) {
00461       if (index.row() == d->model->rowCount() - 1) {
00462           KNotification::beep();
00463           return;
00464       }
00465 
00466       QModelIndex belowIndex = d->model->index( index.row() + 1, index.column() );
00467 
00468       QString tmp = d->model->data( belowIndex, Qt::DisplayRole ).toString();
00469       d->model->setData( belowIndex, d->model->data( index, Qt::DisplayRole ) );
00470       d->model->setData( index, tmp );
00471 
00472       d->listView->selectionModel()->select(index, QItemSelectionModel::Deselect);
00473       d->listView->selectionModel()->select(belowIndex, QItemSelectionModel::Select);
00474     }
00475 
00476     emit changed();
00477 }
00478 
00479 void KEditListBox::addItem()
00480 {
00481     // when checkAtEntering is true, the add-button is disabled, but this
00482     // slot can still be called through Key_Return/Key_Enter. So we guard
00483     // against this.
00484     if ( !d->servNewButton || !d->servNewButton->isEnabled() )
00485         return;
00486 
00487     QModelIndex currentIndex = d->selectedIndex();
00488 
00489     const QString& currentTextLE=d->lineEdit->text();
00490     bool alreadyInList(false);
00491     //if we didn't check for dupes at the inserting we have to do it now
00492     if (!d->checkAtEntering)
00493     {
00494         // first check current item instead of dumb iterating the entire list
00495         if ( currentIndex.isValid() ) {
00496           if ( d->model->data( currentIndex, Qt::DisplayRole ).toString() == currentTextLE )
00497             alreadyInList = true;
00498         }
00499         else
00500         {
00501             alreadyInList = d->model->stringList().contains( currentTextLE, Qt::CaseSensitive );
00502         }
00503     }
00504     if ( d->servNewButton )
00505         d->servNewButton->setEnabled(false);
00506 
00507     bool block = d->lineEdit->signalsBlocked();
00508     d->lineEdit->blockSignals(true);
00509     d->lineEdit->clear();
00510     d->lineEdit->blockSignals(block);
00511 
00512     d->listView->selectionModel()->setCurrentIndex(currentIndex, QItemSelectionModel::Deselect);
00513 
00514     if (!alreadyInList)
00515     {
00516         block = d->listView->signalsBlocked();
00517 
00518         if ( currentIndex.isValid() ) {
00519           d->model->setData(currentIndex, currentTextLE );
00520         } else {
00521             QStringList lst;
00522             lst<<currentTextLE;
00523             lst<<d->model->stringList();
00524             d->model->setStringList(lst);
00525         }
00526         emit changed();
00527         emit added( currentTextLE ); // TODO: pass the index too
00528     }
00529 
00530     d->updateButtonState();
00531 }
00532 
00533 int KEditListBox::currentItem() const
00534 {
00535     QModelIndex selectedIndex = d->selectedIndex();
00536     if ( selectedIndex.isValid() )
00537         return selectedIndex.row();
00538     else
00539         return -1;
00540 }
00541 
00542 void KEditListBox::removeItem()
00543 {
00544     QModelIndex currentIndex = d->selectedIndex();
00545     if ( !currentIndex.isValid() )
00546       return;
00547 
00548     if ( currentIndex.row() >= 0 )
00549     {
00550         QString removedText = d->model->data( currentIndex, Qt::DisplayRole ).toString();
00551 
00552         d->model->removeRows( currentIndex.row(), 1 );
00553 
00554         d->listView->selectionModel()->clear();
00555 
00556         emit changed();
00557 
00558         emit removed( removedText );
00559     }
00560 
00561     d->updateButtonState();
00562 }
00563 
00564 void KEditListBox::enableMoveButtons(const QModelIndex &newIndex, const QModelIndex&)
00565 {
00566     int index = newIndex.row();
00567 
00568     // Update the lineEdit when we select a different line.
00569     if(currentText() != d->lineEdit->text())
00570         d->lineEdit->setText(currentText());
00571 
00572     bool moveEnabled = d->servUpButton && d->servDownButton;
00573 
00574     if (moveEnabled )
00575     {
00576         if (d->model->rowCount() <= 1)
00577         {
00578             d->servUpButton->setEnabled(false);
00579             d->servDownButton->setEnabled(false);
00580         }
00581         else if (index == (d->model->rowCount() - 1))
00582         {
00583             d->servUpButton->setEnabled(true);
00584             d->servDownButton->setEnabled(false);
00585         }
00586         else if (index == 0)
00587         {
00588             d->servUpButton->setEnabled(false);
00589             d->servDownButton->setEnabled(true);
00590         }
00591         else
00592         {
00593             d->servUpButton->setEnabled(true);
00594             d->servDownButton->setEnabled(true);
00595         }
00596     }
00597 
00598     if ( d->servRemoveButton )
00599         d->servRemoveButton->setEnabled(true);
00600 }
00601 
00602 void KEditListBox::clear()
00603 {
00604     d->lineEdit->clear();
00605     d->model->setStringList( QStringList() );
00606     emit changed();
00607 }
00608 
00609 void KEditListBox::insertStringList(const QStringList& list, int index)
00610 {
00611     QStringList content = d->model->stringList();
00612     if ( index < 0 )
00613       content += list;
00614     else
00615       for ( int i = 0, j = index; i < list.count(); ++i, ++j )
00616         content.insert( j, list[ i ] );
00617 
00618     d->model->setStringList( content );
00619 }
00620 
00621 void KEditListBox::insertItem(const QString& text, int index)
00622 {
00623   QStringList list = d->model->stringList();
00624 
00625   if ( index < 0 )
00626     list.append( text );
00627   else
00628     list.insert( index, text );
00629 
00630   d->model->setStringList(list);
00631 }
00632 
00633 QString KEditListBox::text(int index) const
00634 {
00635   const QStringList list = d->model->stringList();
00636 
00637   return list[ index ];
00638 }
00639 
00640 QString KEditListBox::currentText() const
00641 {
00642   QModelIndex index = d->selectedIndex();
00643   if ( !index.isValid() )
00644     return QString();
00645   else
00646     return text( index.row() );
00647 }
00648 
00649 QStringList KEditListBox::items() const
00650 {
00651     return d->model->stringList();
00652 }
00653 
00654 void KEditListBox::setItems(const QStringList& items)
00655 {
00656   d->model->setStringList(items);
00657 }
00658 
00659 KEditListBox::Buttons KEditListBox::buttons() const
00660 {
00661   return d->buttons;
00662 }
00663 
00664 void KEditListBox::slotSelectionChanged( const QItemSelection&, const QItemSelection& )
00665 {
00666     d->updateButtonState();
00667     QModelIndex index = d->selectedIndex();
00668     enableMoveButtons(index,  QModelIndex());
00669     if (index.isValid()) {
00670         d->lineEdit->setFocus( Qt::OtherFocusReason );
00671     }
00672 }
00673 
00674 bool KEditListBox::eventFilter( QObject* o, QEvent* e )
00675 {
00676     if (o == d->lineEdit && e->type() == QEvent::KeyPress ) {
00677         QKeyEvent* keyEvent = (QKeyEvent*)e;
00678         if (keyEvent->key() == Qt::Key_Down ||
00679             keyEvent->key() == Qt::Key_Up) {
00680             return ((QObject*)d->listView)->event(e);
00681         }
00682     }
00683 
00684     return false;
00685 }
00686 
00687 #include "keditlistbox.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