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