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 <QtCore/QEvent>
00027 #include <QtCore/QMimeData>
00028
00029 using namespace Kross;
00030
00031
00032
00033
00034
00035 namespace Kross {
00036
00038 class ActionCollectionModelItem : public QObject
00039 {
00040 public:
00041 enum Type { ActionType, CollectionType };
00042 const Type type;
00043 union {
00044 Action* action;
00045 ActionCollection* collection;
00046 };
00047 QVector<ActionCollectionModelItem*> children;
00048 const QModelIndex parent;
00049
00050 QString name() const { return type == ActionType ? action->name() : collection->name(); }
00051
00052 explicit ActionCollectionModelItem(Action* a, const QModelIndex& p = QModelIndex(), ActionCollectionModelItem* parentitem = 0)
00053 : QObject(parentitem), type(ActionType), action(a), parent(p)
00054 {
00055 }
00056
00057 explicit ActionCollectionModelItem(ActionCollection* c, const QModelIndex& p = QModelIndex(), ActionCollectionModelItem* parentitem = 0)
00058 : QObject(parentitem), type(CollectionType), collection(c), parent(p)
00059 {
00060 }
00061 };
00062
00064 class ActionCollectionModel::Private
00065 {
00066 public:
00067 ActionCollection* collection;
00068 ActionCollectionModelItem* item;
00069 Mode mode;
00070
00071 template <class T>
00072 ActionCollectionModelItem* childItem( ActionCollectionModelItem* item,
00073 const QModelIndex& parent,
00074 int row,
00075 int column,
00076 T value );
00077 };
00078
00079 }
00080
00081 template <class T>
00082 ActionCollectionModelItem* ActionCollectionModel::Private::childItem(
00083 ActionCollectionModelItem* item,
00084 const QModelIndex& parent,
00085 int row,
00086 int column,
00087 T value )
00088 {
00089 Q_UNUSED(column);
00090 ActionCollectionModelItem* childItem = 0;
00091 if ( row < item->children.count() && item->children.at(row) != 0 ) {
00092 childItem = item->children.at(row);
00093 }
00094 else {
00095 childItem = new ActionCollectionModelItem(value,parent,item);
00096 item->children.resize(row+1);
00097 item->children[row] = childItem;
00098 }
00099 return childItem;
00100 }
00101
00102 ActionCollectionModel::ActionCollectionModel(QObject* parent, ActionCollection* collection, Mode mode)
00103 : QAbstractItemModel(parent)
00104 , d( new Private() )
00105 {
00106 d->collection = collection ? collection : Kross::Manager::self().actionCollection();
00107
00108 d->item = new ActionCollectionModelItem( d->collection );
00109 d->mode = mode;
00110
00111 QObject::connect(d->collection, SIGNAL(updated()), this, SLOT(slotUpdated()));
00112 }
00113
00114 ActionCollectionModel::~ActionCollectionModel()
00115 {
00116 delete d->item;
00117 delete d;
00118 }
00119
00120 void ActionCollectionModel::slotUpdated()
00121 {
00122 emit layoutAboutToBeChanged();
00123 emit layoutChanged();
00124 }
00125
00126 Action* ActionCollectionModel::action(const QModelIndex& index)
00127 {
00128 ActionCollectionModelItem* item = index.isValid() ? static_cast<ActionCollectionModelItem*>(index.internalPointer()) : 0;
00129 return (item && item->type == ActionCollectionModelItem::ActionType) ? item->action : 0;
00130 }
00131
00132 ActionCollection* ActionCollectionModel::collection(const QModelIndex& index)
00133 {
00134 ActionCollectionModelItem* item = index.isValid() ? static_cast<ActionCollectionModelItem*>(index.internalPointer()) : 0;
00135 return (item && item->type == ActionCollectionModelItem::CollectionType) ? item->collection : 0;
00136 }
00137
00138 int ActionCollectionModel::columnCount(const QModelIndex&) const
00139 {
00140 return 1;
00141 }
00142
00143 int ActionCollectionModel::rowCount(const QModelIndex& index) const
00144 {
00145 ActionCollectionModelItem* item = index.isValid() ? static_cast<ActionCollectionModelItem*>(index.internalPointer()) : d->item;
00146 Q_ASSERT( item );
00147 if( item->type == ActionCollectionModelItem::CollectionType )
00148 return item->collection->actions().count() + item->collection->collections().count();
00149 return 0;
00150 }
00151
00152 QModelIndex ActionCollectionModel::index(int row, int column, const QModelIndex& parent) const
00153 {
00154 ActionCollectionModelItem* item = parent.isValid() ? static_cast<ActionCollectionModelItem*>(parent.internalPointer()) : d->item;
00155 Q_ASSERT( item && item->type == ActionCollectionModelItem::CollectionType );
00156 const int count = item->collection->actions().count();
00157 if( row < count ) {
00158 Action* action = dynamic_cast< Action* >( item->collection->actions().value(row) );
00159 if( action )
00160 {
00161 return createIndex(row, column,d->childItem(item,parent,row,column,action));
00162 }
00163 }
00164 else {
00165 QString name = item->collection->collections().value(row - count);
00166 ActionCollection* collection = item->collection->collection(name);
00167 if( collection )
00168 {
00169 return createIndex(row, column,d->childItem(item,parent,row,column,collection));
00170 }
00171 }
00172 return QModelIndex();
00173 }
00174
00175 QModelIndex ActionCollectionModel::parent(const QModelIndex& index) const
00176 {
00177 if( ! index.isValid() )
00178 return QModelIndex();
00179 return static_cast<ActionCollectionModelItem*>(index.internalPointer())->parent;
00180 }
00181
00182 Qt::ItemFlags ActionCollectionModel::flags(const QModelIndex &index) const
00183 {
00184 Qt::ItemFlags flags = QAbstractItemModel::flags(index);
00185 if( ! index.isValid() )
00186 return Qt::ItemIsDropEnabled | flags;
00187
00188 flags |= Qt::ItemIsSelectable;
00189
00190 flags |= Qt::ItemIsDragEnabled;
00191 flags |= Qt::ItemIsDropEnabled;
00192
00193 if( (index.column() == 0) && (d->mode & UserCheckable) )
00194 flags |= Qt::ItemIsUserCheckable;
00195 return flags;
00196 }
00197
00198 QVariant ActionCollectionModel::data(const QModelIndex& index, int role) const
00199 {
00200 if( index.isValid() ) {
00201 ActionCollectionModelItem* item = static_cast<ActionCollectionModelItem*>(index.internalPointer());
00202 switch( item->type ) {
00203 case ActionCollectionModelItem::ActionType: {
00204 switch( role ) {
00205 case Qt::DecorationRole: {
00206 if( d->mode & Icons )
00207 if( ! item->action->iconName().isEmpty() )
00208 return item->action->icon();
00209 } break;
00210 case Qt::DisplayRole:
00211 return item->action->text().remove("&");
00212 case Qt::ToolTipRole:
00213 case Qt::WhatsThisRole: {
00214 if( d->mode & ToolTips ) {
00215 const QString file = QFileInfo( item->action->file() ).fileName();
00216 return QString("<qt><b>%1</b><br>%2</qt>")
00217 .arg( file.isEmpty() ? item->action->name() : file )
00218 .arg( item->action->description() );
00219 }
00220 } break;
00221 case Qt::CheckStateRole: {
00222 if( d->mode & UserCheckable )
00223 return item->action->isEnabled();
00224 } break;
00225 default: break;
00226 }
00227 } break;
00228 case ActionCollectionModelItem::CollectionType: {
00229 switch( role ) {
00230 case Qt::DecorationRole: {
00231 if( d->mode & Icons )
00232 if( ! item->collection->iconName().isEmpty() )
00233 return item->collection->icon();
00234 } break;
00235 case Qt::DisplayRole:
00236 return item->collection->text();
00237 case Qt::ToolTipRole:
00238 case Qt::WhatsThisRole: {
00239 if( d->mode & ToolTips )
00240 return QString("<qt><b>%1</b><br>%2</qt>").arg(item->collection->text()).arg(item->collection->description());
00241 } break;
00242 case Qt::CheckStateRole: {
00243 if( d->mode & UserCheckable )
00244 return item->collection->isEnabled();
00245 } break;
00246 default: break;
00247 }
00248 } break;
00249 default: break;
00250 }
00251 }
00252 return QVariant();
00253 }
00254
00255 bool ActionCollectionModel::setData(const QModelIndex &index, const QVariant &value, int role)
00256 {
00257 Q_UNUSED(value);
00258 if( ! index.isValid() )
00259 return false;
00260 ActionCollectionModelItem* item = static_cast<ActionCollectionModelItem*>(index.internalPointer());
00261 switch( item->type ) {
00262 case ActionCollectionModelItem::ActionType: {
00263 switch( role ) {
00264
00265 case Qt::CheckStateRole: item->action->setEnabled( ! item->action->isEnabled() ); break;
00266 default: return false;
00267 }
00268 } break;
00269 case ActionCollectionModelItem::CollectionType: {
00270 switch( role ) {
00271
00272 case Qt::CheckStateRole: item->collection->setEnabled( ! item->collection->isEnabled() ); break;
00273 default: return false;
00274 }
00275 } break;
00276 default: return false;
00277 }
00278
00279 return true;
00280 }
00281
00282 bool ActionCollectionModel::insertRows(int row, int count, const QModelIndex& parent)
00283 {
00284 krossdebug( QString("ActionCollectionModel::insertRows: row=%1 count=%2").arg(row).arg(count) );
00285 if( ! parent.isValid() )
00286 return false;
00287
00288 ActionCollectionModelItem* parentitem = static_cast<ActionCollectionModelItem*>(parent.internalPointer());
00289 switch( parentitem->type ) {
00290 case ActionCollectionModelItem::ActionType: {
00291 krossdebug( QString("ActionCollectionModel::insertRows: parentindex is Action with name=%1").arg(parentitem->action->name()) );
00292 } break;
00293 case ActionCollectionModelItem::CollectionType: {
00294 krossdebug( QString("ActionCollectionModel::insertRows: parentindex is ActionCollection with name=%1").arg(parentitem->collection->name()) );
00295 } break;
00296 default: break;
00297 }
00298
00299 return QAbstractItemModel::insertRows(row, count, parent);
00300 }
00301
00302 bool ActionCollectionModel::removeRows(int row, int count, const QModelIndex& parent)
00303 {
00304 krossdebug( QString("ActionCollectionModel::removeRows: row=%1 count=%2").arg(row).arg(count) );
00305 return QAbstractItemModel::removeRows(row, count, parent);
00306 }
00307
00308 bool ActionCollectionModel::insertColumns(int column, int count, const QModelIndex& parent)
00309 {
00310 krossdebug( QString("ActionCollectionModel::insertColumns: column=%1 count=%2").arg(column).arg(count) );
00311 return QAbstractItemModel::insertColumns(column, count, parent);
00312 }
00313
00314 bool ActionCollectionModel::removeColumns(int column, int count, const QModelIndex& parent)
00315 {
00316 krossdebug( QString("ActionCollectionModel::removeColumns: column=%1 count=%2").arg(column).arg(count) );
00317 return QAbstractItemModel::removeColumns(column, count, parent);
00318 }
00319
00320 QStringList ActionCollectionModel::mimeTypes() const
00321 {
00322
00323 return QStringList() << "application/vnd.text.list";
00324 }
00325
00326 QString fullPath(const QModelIndex& index)
00327 {
00328 if( ! index.isValid() ) return QString();
00329 ActionCollectionModelItem* item = static_cast<ActionCollectionModelItem*>(index.internalPointer());
00330 QString n = item->name();
00331 if( item->type == ActionCollectionModelItem::CollectionType ) n += '/';
00332 QString p = fullPath( item->parent );
00333 return p.isNull() ? n : ( p.endsWith('/') ? p + n : p + '/' + n );
00334 }
00335
00336 QMimeData* ActionCollectionModel::mimeData(const QModelIndexList& indexes) const
00337 {
00338
00339 QMimeData* mimeData = new QMimeData();
00340 QByteArray encodedData;
00341
00342 QDataStream stream(&encodedData, QIODevice::WriteOnly);
00343 foreach(const QModelIndex &index, indexes) {
00344
00345
00346 QString path = fullPath(index);
00347 if( ! path.isNull() )
00348 stream << path;
00349 }
00350
00351 mimeData->setData("application/vnd.text.list", encodedData);
00352 return mimeData;
00353 }
00354
00355 bool ActionCollectionModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
00356 {
00357 krossdebug( QString("ActionCollectionModel::dropMimeData: row=%1 col=%2").arg(row).arg(column) );
00358 if( action == Qt::IgnoreAction ) return true;
00359 if( ! data->hasFormat("application/vnd.text.list") ) return false;
00360 if( column > 0 ) return false;
00361
00362 krossdebug( QString("ActionCollectionModel::dropMimeData: ENCODED DATA:") );
00363 QByteArray encodedData = data->data("application/vnd.text.list");
00364 QDataStream stream(&encodedData, QIODevice::ReadOnly);
00365 QStringList newItems;
00366 int rows = 0;
00367 while( ! stream.atEnd() ) {
00368 QString text;
00369 stream >> text;
00370 newItems << text;
00371 krossdebug( QString(" %1 \"%2\"").arg(rows).arg(text) );
00372 ++rows;
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 ActionCollectionModelItem* targetparentitem = parent.isValid() ? static_cast<ActionCollectionModelItem*>(parent.internalPointer()) : d->item;
00390 switch( targetparentitem->type ) {
00391 case ActionCollectionModelItem::ActionType: {
00392 krossdebug( QString("ActionCollectionModel::dropMimeData: parentindex is Action with name=%1").arg(targetparentitem->action->name()) );
00393 } break;
00394 case ActionCollectionModelItem::CollectionType: {
00395 krossdebug( QString("ActionCollectionModel::dropMimeData: parentindex is ActionCollection with name=%1").arg(targetparentitem->collection->name()) );
00396 } break;
00397 default: break;
00398 }
00399
00400
00401
00402 return false;
00403
00404 }
00405
00406 Qt::DropActions ActionCollectionModel::supportedDropActions() const
00407 {
00408 return Qt::CopyAction | Qt::MoveAction | Qt::TargetMoveAction;
00409
00410 }
00411
00412
00413
00414
00415
00416 ActionCollectionProxyModel::ActionCollectionProxyModel(QObject* parent, ActionCollectionModel* model)
00417 : QSortFilterProxyModel(parent)
00418 {
00419 setSourceModel( model ? model : new ActionCollectionModel(this) );
00420 setFilterCaseSensitivity(Qt::CaseInsensitive);
00421 }
00422
00423 ActionCollectionProxyModel::~ActionCollectionProxyModel()
00424 {
00425 }
00426
00427 void ActionCollectionProxyModel::setSourceModel(QAbstractItemModel* sourceModel)
00428 {
00429 Q_ASSERT( dynamic_cast< ActionCollectionModel* >(sourceModel) );
00430 QSortFilterProxyModel::setSourceModel(sourceModel);
00431 }
00432
00433 bool ActionCollectionProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
00434 {
00435 QModelIndex index = sourceModel()->index(source_row, 0, source_parent);
00436 if( ! index.isValid() )
00437 return false;
00438 ActionCollectionModelItem* item = static_cast<ActionCollectionModelItem*>(index.internalPointer());
00439 switch( item->type ) {
00440 case ActionCollectionModelItem::ActionType: {
00441 if( ! item->action->isEnabled() )
00442 return false;
00443 return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
00444 } break;
00445 case ActionCollectionModelItem::CollectionType: {
00446 if( ! item->collection->isEnabled() )
00447 return false;
00448 } break;
00449 default: break;
00450 }
00451 return true;
00452 }
00453
00454 #include "model.moc"