not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / khotkeys / kcm_hotkeys / hotkeys_model.cpp
blob1d253680d6c8ca23d95b7aa443d28524526f46bf
1 /*
2 Copyright (C) 2008 Michael Jansen <kde@michael-jansen.biz>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #include "hotkeys_model.h"
22 #include "action_data/simple_action_data.h"
23 #include "action_data/action_data_group.h"
25 #include <typeinfo>
27 #include <QMimeData>
29 #include <KDE/KDebug>
30 #include <KDE/KLocale>
31 #include <KDE/KIcon>
33 static KHotKeys::ActionDataBase *findElement(
34 void *ptr
35 ,KHotKeys::ActionDataGroup *root)
37 Q_ASSERT(root);
38 if (!root) return NULL;
40 KHotKeys::ActionDataBase *match = NULL;
42 Q_FOREACH( KHotKeys::ActionDataBase *element, root->children())
44 if (ptr == element)
46 match = element;
47 break;
50 if (KHotKeys::ActionDataGroup *subGroup = dynamic_cast<KHotKeys::ActionDataGroup*>(element))
52 match = findElement(ptr, subGroup);
53 if (match) break;
57 return match;
62 KHotkeysModel::KHotkeysModel( QObject *parent )
63 : QAbstractItemModel(parent)
64 ,_settings()
65 ,_actions(0)
69 KHotkeysModel::~KHotkeysModel()
74 QModelIndex KHotkeysModel::addGroup( const QModelIndex & parent )
76 KHotKeys::ActionDataGroup *list;
77 if (parent.isValid())
79 list = indexToActionDataGroup(parent);
81 else
83 list = _actions;
85 Q_ASSERT(list);
87 beginInsertRows( parent, list->size(), list->size() );
89 /* KHotKeys:: ActionDataGroup *action = */
90 new KHotKeys::ActionDataGroup( list, i18n("New Group"), i18n("Comment"));
92 endInsertRows();
93 return index( list->size()-1, NameColumn, parent );
97 // Add a group
98 QModelIndex KHotkeysModel::insertActionData( KHotKeys::ActionDataBase *data, const QModelIndex & parent )
100 Q_ASSERT(data);
102 KHotKeys::ActionDataGroup *list;
103 if (parent.isValid())
105 list = indexToActionDataGroup(parent);
107 else
109 list = _actions;
111 Q_ASSERT(list);
113 beginInsertRows( parent, list->size(), list->size() );
115 data->reparent(list);
117 endInsertRows();
118 return index( list->size()-1, NameColumn, parent );
122 int KHotkeysModel::columnCount( const QModelIndex & ) const
124 return 2;
128 QVariant KHotkeysModel::data( const QModelIndex &index, int role ) const
130 // Check that the index is valid
131 if (!index.isValid())
133 return QVariant();
136 // Get the item behind the index
137 KHotKeys::ActionDataBase *action = indexToActionDataBase(index);
138 Q_ASSERT(action);
140 // Handle CheckStateRole
141 if (role==Qt::CheckStateRole)
143 switch(index.column())
145 case 1:
146 // If the parent is enabled we display the state of the object.
147 // If the parent is disabled this object is disabled too.
148 if (action->parent() && !action->parent()->enabled())
150 return Qt::Unchecked;
152 return action->enabled()
153 ? Qt::Checked
154 : Qt::Unchecked;
156 default:
157 return QVariant();
161 // Display and Tooltip. Tooltip displays the complete name. That's nice if
162 // there is not enough space
163 if (role==Qt::DisplayRole || role==Qt::ToolTipRole)
165 switch (index.column())
167 case 0:
168 return action->name();
170 case 1:
171 return QVariant();
173 case 2:
174 return indexToActionDataGroup(index)!=0;
176 case 3:
178 const std::type_info &ti = typeid(*action);
179 if (ti==typeid(KHotKeys::SimpleActionData))
180 return KHotkeysModel::SimpleActionData;
181 else if (ti==typeid(KHotKeys::ActionDataGroup))
182 return KHotkeysModel::ActionDataGroup;
183 else
184 return KHotkeysModel::Other;
187 default:
188 return QVariant();
192 // Decoration role
193 if (role==Qt::DecorationRole)
195 switch (index.column())
197 case 0:
198 return dynamic_cast<KHotKeys::ActionDataGroup*>(action)
199 ? KIcon("folder")
200 : QVariant();
202 default:
203 return QVariant();
208 // For everything else
209 return QVariant();
213 bool KHotkeysModel::dropMimeData(
214 const QMimeData *data
215 ,Qt::DropAction action
216 ,int row
217 ,int column
218 ,const QModelIndex &parent)
220 kDebug()
221 << parent.data(Qt::DisplayRole) << ","
222 << row << ","
223 << column;
225 // We only support move actions and our own mime type
226 if ( (action!=Qt::CopyAction)
227 || !data->hasFormat("application/x-pointer"))
229 kDebug() << "Drop not supported " << data->formats();
230 return false;
233 // Decode the stream
234 QByteArray encodedData = data->data("application/x-pointer");
235 QDataStream stream(&encodedData, QIODevice::ReadOnly);
236 QList<quintptr> ptrs;
237 while (!stream.atEnd())
239 quintptr ptr;
240 stream >> ptr;
241 ptrs << ptr;
244 // No pointers, nothing to do
245 if (ptrs.empty()) return false;
247 // Get the group we have to drop into
248 QModelIndex dropIndex = parent;
249 KHotKeys::ActionDataGroup *dropToGroup = indexToActionDataGroup(dropIndex);
250 if (!dropToGroup)
252 dropIndex = parent.parent();
253 dropToGroup = indexToActionDataGroup(dropIndex);
256 kDebug() << "dropping to " << dropToGroup->name();
258 // Do the moves
259 Q_FOREACH(quintptr ptr, ptrs)
261 KHotKeys::ActionDataBase *element = findElement(
262 reinterpret_cast<void*>(ptr),
263 _actions);
265 if (element) moveElement(element, dropToGroup);
268 return true;
272 void KHotkeysModel::emitChanged(KHotKeys::ActionDataBase *item)
274 Q_ASSERT( item );
276 KHotKeys::ActionDataGroup *parent = item->parent();
277 QModelIndex topLeft;
278 QModelIndex bottomRight;
279 if (!parent)
281 topLeft = createIndex( 0, 0, _actions );
282 bottomRight = createIndex( 0, 0, _actions );
284 else
286 int row = parent->children().indexOf(item);
287 topLeft = createIndex( row, 0, parent );
288 bottomRight = createIndex( row, columnCount(topLeft), parent );
291 emit dataChanged( topLeft, bottomRight );
295 Qt::ItemFlags KHotkeysModel::flags( const QModelIndex &index ) const
297 Qt::ItemFlags flags = QAbstractItemModel::flags(index);
299 if (!index.isValid())
301 return flags | Qt::ItemIsDropEnabled;
304 switch (index.column())
306 case 1:
307 return flags
308 | Qt::ItemIsUserCheckable
309 | Qt::ItemIsDragEnabled
310 | Qt::ItemIsDropEnabled;
312 default:
313 return flags
314 | Qt::ItemIsEditable
315 | Qt::ItemIsDragEnabled
316 | Qt::ItemIsDropEnabled;
321 // Get header data for section
322 QVariant KHotkeysModel::headerData( int section, Qt::Orientation, int role ) const
324 if (role!=Qt::DisplayRole)
326 return QVariant();
329 switch (section)
331 case 0:
332 return QVariant(i18n("Name"));
334 case 1:
335 return QVariant(i18n("Enabled"));
337 case 2:
338 return QVariant(i18n("Type"));
340 default:
341 return QVariant();
346 QModelIndex KHotkeysModel::index( int row, int column, const QModelIndex &parent ) const
348 KHotKeys::ActionDataGroup *actionGroup = indexToActionDataGroup(parent);
349 if (!actionGroup || row>=actionGroup->children().size() )
351 return QModelIndex();
354 KHotKeys::ActionDataBase *action = actionGroup->children().at(row);
355 Q_ASSERT( action );
356 return createIndex( row, column, action );
360 // Convert index to ActionDataBase
361 KHotKeys::ActionDataBase *KHotkeysModel::indexToActionDataBase( const QModelIndex &index ) const
363 if (!index.isValid())
365 return _actions;
367 return static_cast<KHotKeys::ActionDataBase*>( index.internalPointer() );
371 // Convert index to ActionDataGroup
372 KHotKeys::ActionDataGroup *KHotkeysModel::indexToActionDataGroup( const QModelIndex &index ) const
374 if (!index.isValid())
376 return _actions;
378 return dynamic_cast<KHotKeys::ActionDataGroup*>( indexToActionDataBase(index) );
382 void KHotkeysModel::load()
384 _settings.read_settings(true);
385 _actions = _settings.actions();
386 reset();
390 QMimeData *KHotkeysModel::mimeData(const QModelIndexList &indexes) const
392 QMimeData * mimeData = new QMimeData();
393 QByteArray encodedData;
395 QDataStream stream(&encodedData, QIODevice::WriteOnly);
397 Q_FOREACH (QModelIndex index, indexes)
399 if (index.isValid() and index.column() == 0)
401 KHotKeys::ActionDataBase *element = indexToActionDataBase(index);
402 // We use the pointer as id.
403 stream << reinterpret_cast<quintptr>(element);
407 mimeData->setData("application/x-pointer", encodedData);
408 return mimeData;
412 QStringList KHotkeysModel::mimeTypes() const
414 QStringList types;
415 types << "application/x-pointer";
416 return types;
420 bool KHotkeysModel::moveElement(
421 KHotKeys::ActionDataBase *element
422 ,KHotKeys::ActionDataGroup *newGroup
423 ,int position)
425 Q_ASSERT(element && newGroup);
426 if (!element || !newGroup) return false;
428 // TODO: Make this logic more advanced
429 // We do not allow moving into our systemgroup
430 if (newGroup->is_system_group()) return false;
432 // Make sure we don't move a group to one of it's children or
433 // itself.
434 KHotKeys::ActionDataGroup *tmp = newGroup;
435 do {
436 if (tmp == element)
438 kDebug() << "Forbidden move" << tmp->name();
439 return false;
442 while((tmp = tmp->parent()));
444 KHotKeys::ActionDataGroup *oldParent = element->parent();
446 // TODO: Make this logic more advanced
447 // We do not allow moving from our systemgroup
448 if (oldParent->is_system_group()) return false;
450 // Remove it from it's current place
451 kDebug() << "Removing from";
452 kDebug() << KHotkeysModel::data(createIndex(0, 0, oldParent), Qt::DisplayRole);
453 kDebug() << "item " << oldParent->children().indexOf(element);
454 kDebug() << "from " << oldParent->children().size();
455 beginRemoveRows(
456 createIndex(0, 0, oldParent),
457 oldParent->children().indexOf(element),
458 oldParent->children().indexOf(element));
459 element->reparent(0);
460 endRemoveRows();
462 // Add to the new
463 kDebug() << "Adding to";
464 kDebug() << KHotkeysModel::data(createIndex(0, 0, newGroup), Qt::DisplayRole);
465 kDebug() << "from " << newGroup->children().size();
466 beginInsertRows(
467 createIndex(0, 0, newGroup),
468 newGroup->children().size(),
469 newGroup->children().size());
470 element->reparent(newGroup);
471 endInsertRows();
473 return true;
477 // Get parent object for index
478 QModelIndex KHotkeysModel::parent( const QModelIndex &index ) const
480 KHotKeys::ActionDataBase *action = indexToActionDataBase(index);
481 if (!action)
483 return QModelIndex();
486 KHotKeys::ActionDataGroup *parent = action->parent();
487 if (!parent)
489 return QModelIndex();
492 KHotKeys::ActionDataGroup *grandparent = parent->parent();
493 if (!grandparent)
495 return QModelIndex();
498 int row = grandparent->children().indexOf(parent);
499 return createIndex( row, 0, parent );
503 // Remove rows ( items )
504 bool KHotkeysModel::removeRows( int row, int count, const QModelIndex &parent )
506 Q_ASSERT( count == 1 );
508 beginRemoveRows( parent, row, row+count-1 );
510 KHotKeys::ActionDataGroup *list;
511 if (parent.isValid())
513 list = indexToActionDataGroup(parent);
515 else
517 list = _actions;
519 Q_ASSERT(list);
521 KHotKeys::ActionDataBase *action = indexToActionDataBase(index(row,0,parent));
523 action->aboutToBeErased();
524 delete action;
526 endRemoveRows();
527 return true;
531 // Number of rows for index
532 int KHotkeysModel::rowCount( const QModelIndex &index ) const
534 KHotKeys::ActionDataGroup *group = indexToActionDataGroup(index);
535 if (!group)
537 return 0;
540 return group->children().count();
544 void KHotkeysModel::save()
546 _settings.write_settings();
550 // Set data
551 bool KHotkeysModel::setData( const QModelIndex &index, const QVariant &value, int role )
554 if ( !index.isValid() || role != Qt::EditRole )
556 return false;
559 KHotKeys::ActionDataBase *action = indexToActionDataBase(index);
560 Q_ASSERT( action );
562 switch ( index.column() )
564 case NameColumn:
566 action->set_name( value.toString() );
568 break;
570 default:
571 return false;
574 emit dataChanged( index, index );
575 return true;
578 #include "moc_hotkeys_model.cpp"