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

Kross

model.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  * model.cpp
00003  * This file is part of the KDE project
00004  * copyright (C) 2006-2007 by Sebastian Sauer (mail@dipe.org)
00005  *
00006  * This program 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  * This program 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  * You should have received a copy of the GNU Library General Public License
00015  * along with this program; see the file COPYING.  If not, write to
00016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018  ***************************************************************************/
00019 
00020 #include "model.h"
00021 
00022 #include <kross/core/action.h>
00023 #include <kross/core/actioncollection.h>
00024 #include <kross/core/manager.h>
00025 
00026 #include <kglobal.h>
00027 #include <klocale.h>
00028 #include <kdebug.h>
00029 
00030 #include <QtCore/QEvent>
00031 #include <QtCore/QMimeData>
00032 
00033 using namespace Kross;
00034 
00035 /******************************************************************************
00036  * ActionCollectionModel
00037  */
00038 
00039 namespace Kross {
00040 
00042     class ActionCollectionModel::Private
00043     {
00044         public:
00045             ActionCollection* collection;
00046             Mode mode;
00047     };
00048 
00049 }
00050 
00051 ActionCollectionModel::ActionCollectionModel(QObject* parent, ActionCollection* collection, Mode mode)
00052     : QAbstractItemModel(parent)
00053     , d( new Private() )
00054 {
00055     //krossdebug( QString( "ActionCollectionModel::ActionCollectionModel:") );
00056     d->collection = collection ? collection : Kross::Manager::self().actionCollection();
00057     d->mode = mode;
00058     //setSupportedDragActions(Qt::MoveAction);
00059 
00060     //ActionCollection propagates signals to parent
00061     QObject::connect( d->collection, SIGNAL( dataChanged( Action* ) ), this, SLOT( slotDataChanged( Action* ) ) );
00062     QObject::connect( d->collection, SIGNAL( dataChanged( ActionCollection* ) ), this, SLOT( slotDataChanged( ActionCollection* ) ) );
00063 
00064     QObject::connect( d->collection, SIGNAL( collectionToBeInserted( ActionCollection*, ActionCollection* ) ), this, SLOT( slotCollectionToBeInserted( ActionCollection*, ActionCollection* ) ) );
00065     QObject::connect( d->collection, SIGNAL( collectionInserted( ActionCollection*, ActionCollection* ) ), this, SLOT( slotCollectionInserted( ActionCollection*, ActionCollection* ) ) );
00066     QObject::connect( d->collection, SIGNAL( collectionToBeRemoved( ActionCollection*, ActionCollection* ) ), this, SLOT( slotCollectionToBeRemoved( ActionCollection*, ActionCollection* ) ) );
00067     QObject::connect( d->collection, SIGNAL( collectionRemoved( ActionCollection*, ActionCollection* ) ), this, SLOT( slotCollectionRemoved( ActionCollection*, ActionCollection* ) ) );
00068 
00069     QObject::connect( d->collection, SIGNAL( actionToBeInserted( Action*, ActionCollection* ) ), this, SLOT( slotActionToBeInserted( Action*, ActionCollection* ) ) );
00070     QObject::connect( d->collection, SIGNAL( actionInserted( Action*, ActionCollection* ) ), this, SLOT( slotActionInserted( Action*, ActionCollection* ) ) );
00071     QObject::connect( d->collection, SIGNAL( actionToBeRemoved( Action*, ActionCollection* ) ), this, SLOT( slotActionToBeRemoved( Action*, ActionCollection* ) ) );
00072     QObject::connect( d->collection, SIGNAL( actionRemoved( Action*, ActionCollection* ) ), this, SLOT( slotActionRemoved( Action*, ActionCollection* ) ) );
00073 }
00074 
00075 ActionCollectionModel::~ActionCollectionModel()
00076 {
00077     delete d;
00078 }
00079 
00080 ActionCollection *ActionCollectionModel::rootCollection() const
00081 {
00082     return d->collection;
00083 }
00084 
00085 int ActionCollectionModel::rowNumber( ActionCollection *collection ) const
00086 {
00087     Q_ASSERT( collection != 0 );
00088     ActionCollection *par = collection->parentCollection();
00089     Q_ASSERT( par != 0 );
00090     int row = par->collections().indexOf( collection->objectName() ) + par->actions().count();
00091     return row;
00092 }
00093 
00094 QModelIndex ActionCollectionModel::indexForCollection( ActionCollection *collection ) const
00095 {
00096     if ( collection == d->collection ) {
00097         return QModelIndex();
00098     }
00099     return createIndex( rowNumber( collection ), 0, collection->parentCollection() );
00100 }
00101 
00102 QModelIndex ActionCollectionModel::indexForAction( Action *act ) const
00103 {
00104     ActionCollection *coll = static_cast<ActionCollection*>( act->parent() );
00105     return createIndex( coll->actions().indexOf( act ), 0, coll );
00106 }
00107 
00108 void ActionCollectionModel::slotCollectionToBeInserted( ActionCollection* child, ActionCollection* parent )
00109 {
00110     //krossdebug( QString( "ActionCollectionModel::slotCollectionToBeInserted: %1 %2" ).arg( child->name() ).arg( parent->name( ) )  );
00111     Q_ASSERT( parent );
00112     Q_UNUSED( child )
00113     int row = parent->actions().count() + parent->collections().count(); // we assume child is appended!!
00114     QModelIndex parIdx = indexForCollection( parent );
00115     beginInsertRows( parIdx, row, row );
00116 }
00117 
00118 void ActionCollectionModel::slotCollectionInserted( ActionCollection*, ActionCollection* )
00119 {
00120     //krossdebug( QString( "ActionCollectionModel::slotCollectionInserted: %1 %2" ).arg( child->name( ) ).arg( parent->name( ) )  );
00121     endInsertRows();
00122 }
00123 
00124 void ActionCollectionModel::slotCollectionToBeRemoved( ActionCollection* child, ActionCollection* parent )
00125 {
00126     //krossdebug( QString( "ActionCollectionModel::slotCollectionToBeRemoved: %1 %2" ).arg( child->name() ).arg( parent->name() ) );
00127     int row = rowNumber( child );
00128     QModelIndex parIdx = indexForCollection( parent );
00129     beginRemoveRows( parIdx, row, row );
00130 }
00131 
00132 void ActionCollectionModel::slotCollectionRemoved( ActionCollection*, ActionCollection* )
00133 {
00134     //krossdebug( QString( "ActionCollectionModel::slotCollectionRemoved: %1 %2" ).arg( child->name() ).arg( parent->name() ) );
00135     endRemoveRows();
00136 }
00137 
00138 void ActionCollectionModel::slotActionToBeInserted( Action* child, ActionCollection* parent )
00139 {
00140     //krossdebug( QString( "ActionCollectionModel::slotActionInserted: %1 %2" ).arg( child->name() ).arg( parent->name() ) );
00141     Q_ASSERT( parent );
00142     Q_UNUSED( child )
00143     int row = parent->actions().count(); // assume child is appended to actions!!
00144     QModelIndex parIdx = indexForCollection( parent );
00145     beginInsertRows( parIdx, row, row );
00146 }
00147 
00148 void ActionCollectionModel::slotActionInserted( Action*, ActionCollection* )
00149 {
00150     //krossdebug( QString( "ActionCollectionModel::slotActionInserted: %1 %2" ).arg( child->name() ).arg( parent->name() ) );
00151     endInsertRows();
00152 }
00153 
00154 void ActionCollectionModel::slotActionToBeRemoved( Action* child, ActionCollection* parent )
00155 {
00156     //krossdebug( QString( "ActionCollectionModel::slotActionToBeRemoved: %1 %2" ).arg( child->name() ).arg( parent->name() ) );
00157     Q_ASSERT( parent );
00158     int row = parent->actions().indexOf( child );
00159     QModelIndex parIdx = indexForCollection( parent );
00160     beginRemoveRows( parIdx, row, row );
00161 }
00162 
00163 void ActionCollectionModel::slotActionRemoved( Action*, ActionCollection* )
00164 {
00165     //krossdebug( QString( "ActionCollectionModel::slotActionRemoved: %1 %2" ).arg( child->name() ).arg( parent->name() ) );
00166     endRemoveRows();
00167 }
00168 
00169 //NOTE: not used anymore, remove?
00170 void ActionCollectionModel::slotUpdated()
00171 {
00172     //emit layoutAboutToBeChanged();
00173     //emit layoutChanged();
00174 }
00175 
00176 void ActionCollectionModel::slotDataChanged( ActionCollection* coll )
00177 {
00178     //krossdebug( QString( "ActionCollectionModel::slotDataChanged: %1" ).arg( coll->name() ) );
00179     QModelIndex idx = indexForCollection( coll );
00180     emit dataChanged( idx, idx ); // NOTE: change if more than one column
00181 }
00182 
00183 void ActionCollectionModel::slotDataChanged( Action* act )
00184 {
00185     //krossdebug( QString( "ActionCollectionModel::slotDataChanged: %1" ).arg( act->name() ) );
00186     QModelIndex idx = indexForAction( act );
00187     emit dataChanged( idx, idx ); // NOTE: change if more than one column
00188 }
00189 
00190 Action* ActionCollectionModel::action(const QModelIndex& index)
00191 {
00192     ActionCollection *par = static_cast<ActionCollection*>( index.internalPointer() );
00193     if ( par == 0 || index.row() >= par->actions().count() ) {
00194         return 0;
00195     }
00196     return par->actions().value( index.row() );
00197 }
00198 
00199 ActionCollection* ActionCollectionModel::collection(const QModelIndex& index)
00200 {
00201     ActionCollection *par = static_cast<ActionCollection*>( index.internalPointer() );
00202     if ( par == 0 ) {
00203         return 0;
00204     }
00205     int row = index.row() - par->actions().count();
00206     if ( row < 0 ) {
00207         return 0; // this is probably an action
00208     }
00209     return par->collection( par->collections().value( row) );
00210 }
00211 
00212 int ActionCollectionModel::columnCount(const QModelIndex&) const
00213 {
00214     return 1;
00215 }
00216 
00217 int ActionCollectionModel::rowCount(const QModelIndex& index) const
00218 {
00219     if ( action( index) ) {
00220         return 0;
00221     }
00222     ActionCollection* par = index.isValid() ? collection( index ) : d->collection;
00223     Q_ASSERT_X( par, "ActionCollectionModel::rowCount", "index is not an action nor a collection" );
00224     if (!par) {
00225         kWarning()<<"index is not an action nor a collection"<<index;
00226         return 0;
00227     }
00228     int rows = par->actions().count() + par->collections().count();
00229     return rows;
00230 }
00231 
00232 QModelIndex ActionCollectionModel::index(int row, int column, const QModelIndex& parent) const
00233 {
00234     if ( ! hasIndex( row, column, parent ) ) {
00235         return QModelIndex();
00236     }
00237     ActionCollection* par = parent.isValid() ? collection( parent ) : d->collection;
00238     if ( par == 0 ) {
00239         // safety: may happen if parent index is an action (ModelTest tests this)
00240         return QModelIndex();
00241     }
00242     return createIndex( row, column, par );
00243 }
00244 
00245 QModelIndex ActionCollectionModel::parent(const QModelIndex& index) const
00246 {
00247     if( ! index.isValid() ) {
00248         return QModelIndex();
00249     }
00250     ActionCollection *par = static_cast<ActionCollection*>( index.internalPointer() );
00251     Q_ASSERT( par != 0 );
00252     if ( par == d->collection ) {
00253         return QModelIndex();
00254     }
00255     return createIndex( rowNumber( par ), 0, par->parentCollection() );
00256 }
00257 
00258 Qt::ItemFlags ActionCollectionModel::flags(const QModelIndex &index) const
00259 {
00260     Qt::ItemFlags flags = QAbstractItemModel::flags(index);
00261     if( ! index.isValid() )
00262         return Qt::ItemIsDropEnabled | flags;
00263 
00264     flags |= Qt::ItemIsSelectable;
00265     //flags |= Qt::ItemIsEditable;
00266     flags |= Qt::ItemIsDragEnabled;
00267     flags |= Qt::ItemIsDropEnabled;
00268 
00269     if( (index.column() == 0) && (d->mode & UserCheckable) )
00270         flags |= Qt::ItemIsUserCheckable;
00271     return flags;
00272 }
00273 
00274 QVariant ActionCollectionModel::data(const QModelIndex& index, int role) const
00275 {
00276     if( index.isValid() ) {
00277         Action *act = action( index );
00278         if ( act ) {
00279             switch( role ) {
00280                 case Qt::DecorationRole: {
00281                     if( d->mode & Icons )
00282                         if( ! act->iconName().isEmpty() )
00283                             return act->icon();
00284                 } break;
00285                 case Qt::DisplayRole:
00286                     return KGlobal::locale()->removeAcceleratorMarker( act->text() );
00287                 case Qt::ToolTipRole: // fall through
00288                 case Qt::WhatsThisRole: {
00289                     if( d->mode & ToolTips ) {
00290                         const QString file = QFileInfo( act->file() ).fileName();
00291                         return QString( "<qt><b>%1</b><br>%2</qt>" )
00292                             .arg( file.isEmpty() ? act->name() : file )
00293                             .arg( act->description() );
00294                     }
00295                 } break;
00296                 case Qt::CheckStateRole: {
00297                     if( d->mode & UserCheckable )
00298                         return act->isEnabled() ? Qt::Checked : Qt::Unchecked;
00299                 } break;
00300                 default: break;
00301             }
00302             return QVariant();
00303         }
00304         ActionCollection *coll = collection( index );
00305         if ( coll ) {
00306             switch( role ) {
00307                 case Qt::DecorationRole: {
00308                     if( d->mode & Icons )
00309                         if( ! coll->iconName().isEmpty() )
00310                             return coll->icon();
00311                 } break;
00312                 case Qt::DisplayRole:
00313                     return coll->text();
00314                 case Qt::ToolTipRole: // fall through
00315                 case Qt::WhatsThisRole: {
00316                     if( d->mode & ToolTips )
00317                         return QString( "<qt><b>%1</b><br>%2</qt>" ).arg( coll->text() ).arg( coll->description() );
00318                 } break;
00319                 case Qt::CheckStateRole: {
00320                     if( d->mode & UserCheckable )
00321                         return coll->isEnabled() ? Qt::Checked : Qt::Unchecked;
00322                 } break;
00323                 default: break;
00324             }
00325             return QVariant();
00326         }
00327     }
00328     return QVariant();
00329 }
00330 
00331 bool ActionCollectionModel::setData(const QModelIndex &index, const QVariant &value, int role)
00332 {
00333     Q_UNUSED(value);
00334     if( ! index.isValid() /*|| ! (d->mode & UserCheckable)*/ )
00335         return false;
00336     
00337     Action *act = action( index );
00338     if ( act ) {
00339         switch( role ) {
00340             //case Qt::EditRole: act->setText( value.toString() ); break;
00341             case Qt::CheckStateRole: act->setEnabled( ! act->isEnabled() ); break;
00342             default: return false;
00343         }
00344         return false;
00345     }
00346     ActionCollection *coll = collection( index );
00347     if ( coll ) {
00348         switch( role ) {
00349             //case Qt::EditRole: item->coll->setText( value.toString() ); break;
00350             case Qt::CheckStateRole: coll->setEnabled( ! coll->isEnabled() ); break;
00351             default: return false;
00352         }
00353         return false;
00354     }
00355     //emit dataChanged(index, index);
00356     return true;
00357 }
00358 
00359 bool ActionCollectionModel::insertRows(int row, int count, const QModelIndex& parent)
00360 {
00361     krossdebug( QString("ActionCollectionModel::insertRows: row=%1 count=%2").arg(row).arg(count) );
00362     if( ! parent.isValid() )
00363         return false;
00364 
00365     ActionCollection* coll = collection( parent );
00366     if ( coll ) {
00367         krossdebug( QString( "ActionCollectionModel::insertRows: parentindex is ActionCollection with name=%1" ).arg( coll->name() ) );
00368     } else {
00369         Action *act = action( parent );
00370         if ( act ) {
00371             krossdebug( QString( "ActionCollectionModel::insertRows: parentindex is Action with name=%1" ).arg( act->name() ) );
00372         }
00373     }
00374     return QAbstractItemModel::insertRows(row, count, parent);
00375 }
00376 
00377 bool ActionCollectionModel::removeRows(int row, int count, const QModelIndex& parent)
00378 {
00379     krossdebug( QString("ActionCollectionModel::removeRows: row=%1 count=%2").arg(row).arg(count) );
00380     return QAbstractItemModel::removeRows(row, count, parent);
00381 }
00382 
00383 bool ActionCollectionModel::insertColumns(int column, int count, const QModelIndex& parent)
00384 {
00385     krossdebug( QString("ActionCollectionModel::insertColumns: column=%1 count=%2").arg(column).arg(count) );
00386     return QAbstractItemModel::insertColumns(column, count, parent);
00387 }
00388 
00389 bool ActionCollectionModel::removeColumns(int column, int count, const QModelIndex& parent)
00390 {
00391     krossdebug( QString("ActionCollectionModel::removeColumns: column=%1 count=%2").arg(column).arg(count) );
00392     return QAbstractItemModel::removeColumns(column, count, parent);
00393 }
00394 
00395 QStringList ActionCollectionModel::mimeTypes() const
00396 {
00397     //krossdebug( QString("ActionCollectionModel::mimeTypes") );
00398     return QStringList() << "application/vnd.text.list";
00399 }
00400 
00401 QString fullPath(const QModelIndex& index)
00402 {
00403     if( ! index.isValid() ) return QString();
00404     QString n;
00405     Action *a = ActionCollectionModel::action( index );
00406     if ( a ) {
00407         n = a->name();
00408     } else {
00409         ActionCollection *c = ActionCollectionModel::collection( index );
00410         if ( c ) {
00411             n = c->name() + '/';
00412             if ( ! n.endsWith('/' ) )
00413                 n += '/';
00414         }
00415     }
00416     ActionCollection* par = static_cast<ActionCollection*>( index.internalPointer() );
00417     for ( ActionCollection *p = par; p != 0; p = par->parentCollection() ) {
00418         QString s = p->name();
00419         if ( ! s.endsWith( '/' ) ) {
00420             s += '/';
00421         }
00422         n = s + n;
00423     }
00424     return n;
00425 }
00426 
00427 QMimeData* ActionCollectionModel::mimeData(const QModelIndexList& indexes) const
00428 {
00429     //krossdebug( QString("ActionCollectionModel::mimeData") );
00430     QMimeData* mimeData = new QMimeData();
00431     QByteArray encodedData;
00432 
00433     QDataStream stream(&encodedData, QIODevice::WriteOnly);
00434     foreach(const QModelIndex &index, indexes) {
00435         //if( ! index.isValid() ) continue;
00436         //QString text = data(index, Qt::DisplayRole).toString();
00437         QString path = fullPath(index);
00438         if( ! path.isNull() )
00439             stream << path;
00440     }
00441 
00442     mimeData->setData("application/vnd.text.list", encodedData);
00443     return mimeData;
00444 }
00445 
00446 bool ActionCollectionModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
00447 {
00448     krossdebug( QString("ActionCollectionModel::dropMimeData: row=%1 col=%2").arg(row).arg(column) );
00449     if( action == Qt::IgnoreAction ) return true;
00450     if( ! data->hasFormat("application/vnd.text.list") ) return false;
00451     if( column > 0 ) return false;
00452 
00453     krossdebug( QString("ActionCollectionModel::dropMimeData: ENCODED DATA:") );
00454     QByteArray encodedData = data->data("application/vnd.text.list");
00455     QDataStream stream(&encodedData, QIODevice::ReadOnly);
00456     QStringList newItems;
00457     int rows = 0;
00458     while( ! stream.atEnd() ) {
00459         QString text;
00460         stream >> text;
00461         newItems << text;
00462         krossdebug( QString("  %1 \"%2\"").arg(rows).arg(text) );
00463         ++rows;
00464     }
00465 
00466     //FIXME: return false for now since insertRows/removeRows need to be implemented before!
00467     //return false;
00468 
00469     /*
00470     int beginRow;
00471     if( row != -1 )
00472         beginRow = row;
00473     else if( parent.isValid() )
00474         beginRow = parent.row();
00475     else
00476         beginRow = rowCount( QModelIndex() );
00477     krossdebug( QString("ActionCollectionModel::dropMimeData: beginRow=%1").arg(beginRow) );
00478     */
00479 
00480     QModelIndex targetindex = index( row, column, parent );
00481     ActionCollection *coll = collection( targetindex );
00482     if ( coll ) {
00483         krossdebug( QString( "ActionCollectionModel::dropMimeData: parentindex is ActionCollection with name=%1" ).arg( coll->name() ) );
00484     } else {
00485         Action *act = this->action( targetindex );
00486         if ( act ) {
00487             krossdebug( QString( "ActionCollectionModel::dropMimeData: parentindex is Action with name=%1" ).arg( act->name() ) );
00488         }
00489     }
00490     return false;
00491     //return QAbstractItemModel::dropMimeData(data, action, row, column, parent);
00492 }
00493 
00494 Qt::DropActions ActionCollectionModel::supportedDropActions() const
00495 {
00496     return Qt::CopyAction | Qt::MoveAction | Qt::TargetMoveAction;
00497     //return Qt::CopyAction | Qt::MoveAction | Qt::TargetMoveAction | Qt::LinkAction;
00498 }
00499 
00500 /******************************************************************************
00501  * ActionCollectionProxyModel
00502  */
00503 
00504 ActionCollectionProxyModel::ActionCollectionProxyModel(QObject* parent, ActionCollectionModel* model)
00505     : QSortFilterProxyModel(parent)
00506 {
00507     setSourceModel( model ? model : new ActionCollectionModel(this) );
00508     setFilterCaseSensitivity(Qt::CaseInsensitive);
00509     setDynamicSortFilter(true);
00510 }
00511 
00512 ActionCollectionProxyModel::~ActionCollectionProxyModel()
00513 {
00514 }
00515 
00516 void ActionCollectionProxyModel::setSourceModel(QAbstractItemModel* sourceModel)
00517 {
00518     Q_ASSERT( dynamic_cast< ActionCollectionModel* >(sourceModel) );
00519     QSortFilterProxyModel::setSourceModel(sourceModel);
00520 }
00521 
00522 bool ActionCollectionProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
00523 {
00524     //krossdebug( QString( "ActionCollectionProxyModel::filterAcceptsRow: row=%1 parentrow=%2" ).arg( source_row ).arg( source_parent.row() ) );
00525     QModelIndex index = sourceModel()->index(source_row, 0, source_parent);
00526     if( ! index.isValid() )
00527         return false;
00528 
00529     Action *action = ActionCollectionModel::action( index );
00530     if ( action ) {
00531         return action->isEnabled() && QSortFilterProxyModel::filterAcceptsRow( source_row, source_parent );
00532     }
00533     ActionCollection *collection = ActionCollectionModel::collection( index );
00534     if( collection ) {
00535         return collection->isEnabled();
00536     }
00537     return true;
00538 }
00539 
00540 #include "model.moc"

Kross

Skip menu "Kross"
  • Main Page
  • 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