00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
00055 d->collection = collection ? collection : Kross::Manager::self().actionCollection();
00056 d->mode = mode;
00057
00058
00059
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
00110 Q_ASSERT( parent );
00111 int row = parent->actions().count() + parent->collections().count();
00112 QModelIndex parIdx = indexForCollection( parent );
00113 beginInsertRows( parIdx, row, row );
00114 }
00115
00116 void ActionCollectionModel::slotCollectionInserted( ActionCollection*, ActionCollection* )
00117 {
00118
00119 endInsertRows();
00120 }
00121
00122 void ActionCollectionModel::slotCollectionToBeRemoved( ActionCollection* child, ActionCollection* parent )
00123 {
00124
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
00133 endRemoveRows();
00134 }
00135
00136 void ActionCollectionModel::slotActionToBeInserted( Action* child, ActionCollection* parent )
00137 {
00138
00139 Q_ASSERT( parent );
00140 int row = parent->actions().count();
00141 QModelIndex parIdx = indexForCollection( parent );
00142 beginInsertRows( parIdx, row, row );
00143 }
00144
00145 void ActionCollectionModel::slotActionInserted( Action*, ActionCollection* )
00146 {
00147
00148 endInsertRows();
00149 }
00150
00151 void ActionCollectionModel::slotActionToBeRemoved( Action* child, ActionCollection* parent )
00152 {
00153
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
00163 endRemoveRows();
00164 }
00165
00166
00167 void ActionCollectionModel::slotUpdated()
00168 {
00169
00170
00171 }
00172
00173 void ActionCollectionModel::slotDataChanged( ActionCollection* coll )
00174 {
00175
00176 QModelIndex idx = indexForCollection( coll );
00177 emit dataChanged( idx, idx );
00178 }
00179
00180 void ActionCollectionModel::slotDataChanged( Action* act )
00181 {
00182
00183 QModelIndex idx = indexForAction( act );
00184 emit dataChanged( idx, idx );
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;
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
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
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:
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:
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() )
00328 return false;
00329
00330 Action *act = action( index );
00331 if ( act ) {
00332 switch( role ) {
00333
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
00343 case Qt::CheckStateRole: coll->setEnabled( ! coll->isEnabled() ); break;
00344 default: return false;
00345 }
00346 return false;
00347 }
00348
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
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
00423 QMimeData* mimeData = new QMimeData();
00424 QByteArray encodedData;
00425
00426 QDataStream stream(&encodedData, QIODevice::WriteOnly);
00427 foreach(const QModelIndex &index, indexes) {
00428
00429
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
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
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
00485 }
00486
00487 Qt::DropActions ActionCollectionModel::supportedDropActions() const
00488 {
00489 return Qt::CopyAction | Qt::MoveAction | Qt::TargetMoveAction;
00490
00491 }
00492
00493
00494
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
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 return action->isEnabled() && QSortFilterProxyModel::filterAcceptsRow( source_row, source_parent );
00525 }
00526 ActionCollection *collection = ActionCollectionModel::collection( index );
00527 if( collection ) {
00528 return collection->isEnabled();
00529 }
00530 return true;
00531 }
00532
00533 #include "model.moc"