Allow configuration of shortcuts for platforms other than KDE
[quassel.git] / src / qtui / settingspages / shortcutsmodel.cpp
diff --git a/src/qtui/settingspages/shortcutsmodel.cpp b/src/qtui/settingspages/shortcutsmodel.cpp
new file mode 100644 (file)
index 0000000..f9dcbe2
--- /dev/null
@@ -0,0 +1,232 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by the Quassel Project                             *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) version 3.                                           *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "shortcutsmodel.h"
+
+#include "action.h"
+#include "actioncollection.h"
+#include "util.h"
+
+ShortcutsModel::ShortcutsModel(const QHash<QString, ActionCollection *> &actionCollections, QObject *parent)
+  : QAbstractItemModel(parent),
+  _changedCount(0)
+{
+  for(int r = 0; r < actionCollections.values().count(); r++) {
+    ActionCollection *coll = actionCollections.values().at(r);
+    Item *item = new Item();
+    item->row = r;
+    item->collection = coll;
+    for(int i = 0; i < coll->actions().count(); i++) {
+      Action *action = qobject_cast<Action *>(coll->actions().at(i));
+      if(!action)
+        continue;
+      Item *actionItem = new Item();
+      actionItem->parentItem = item;
+      actionItem->row = i;
+      actionItem->collection = coll;
+      actionItem->action = action;
+      actionItem->shortcut = action->shortcut();
+      item->actionItems.append(actionItem);
+    }
+    _categoryItems.append(item);
+  }
+}
+
+ShortcutsModel::~ShortcutsModel() {
+  qDeleteAll(_categoryItems);
+}
+
+QModelIndex ShortcutsModel::parent(const QModelIndex &child) const {
+  if(!child.isValid())
+    return QModelIndex();
+
+  Item *item = static_cast<Item *>(child.internalPointer());
+  Q_ASSERT(item);
+
+  if(!item->parentItem)
+    return QModelIndex();
+
+  return createIndex(item->parentItem->row, 0, item->parentItem);
+}
+
+QModelIndex ShortcutsModel::index(int row, int column, const QModelIndex &parent) const {
+
+  if(parent.isValid())
+    return createIndex(row, column, static_cast<Item *>(parent.internalPointer())->actionItems.at(row));
+
+  // top level category item
+  return createIndex(row, column, _categoryItems.at(row));
+}
+
+int ShortcutsModel::columnCount(const QModelIndex &parent) const {
+  return 2;
+  if(!parent.isValid())
+    return 2;
+
+  Item *item = static_cast<Item *>(parent.internalPointer());
+  Q_ASSERT(item);
+
+  if(!item->parentItem)
+    return 2;
+
+  return 2;
+}
+
+int ShortcutsModel::rowCount(const QModelIndex &parent) const {
+  if(!parent.isValid())
+    return _categoryItems.count();
+
+  Item *item = static_cast<Item *>(parent.internalPointer());
+  Q_ASSERT(item);
+
+  if(!item->parentItem)
+    return item->actionItems.count();
+
+  return 0;
+}
+
+QVariant ShortcutsModel::headerData(int section, Qt::Orientation orientation, int role) const {
+  if(orientation != Qt::Horizontal || role != Qt::DisplayRole)
+    return QVariant();
+  switch(section) {
+  case 0:
+    return tr("Action");
+  case 1:
+    return tr("Shortcut");
+  default:
+    return QVariant();
+  }
+}
+
+QVariant ShortcutsModel::data(const QModelIndex &index, int role) const {
+  if(!index.isValid())
+    return QVariant();
+
+  Item *item = static_cast<Item *>(index.internalPointer());
+  Q_ASSERT(item);
+
+  if(!item->parentItem) {
+    if(index.column() != 0)
+      return QVariant();
+    switch(role) {
+    case Qt::DisplayRole:
+      return item->collection->property("Category");
+    default:
+      return QVariant();
+    }
+  }
+
+  Action *action = qobject_cast<Action *>(item->action);
+  Q_ASSERT(action);
+
+  switch(role) {
+  case Qt::DisplayRole:
+    switch(index.column()) {
+    case 0:
+      return stripAcceleratorMarkers(action->text());
+    case 1:
+      return item->shortcut.toString();
+    default:
+      return QVariant();
+    }
+
+  case Qt::DecorationRole:
+    if(index.column() == 0)
+      return action->icon();
+    return QVariant();
+
+  case ActionRole:
+    return QVariant::fromValue<QObject *>(action);
+
+  case DefaultShortcutRole:
+    return action->shortcut(Action::DefaultShortcut);
+  case ActiveShortcutRole:
+    return item->shortcut;
+
+  case IsConfigurableRole:
+    return action->isShortcutConfigurable();
+
+  default:
+    return QVariant();
+  }
+}
+
+bool ShortcutsModel::setData(const QModelIndex &index, const QVariant &value, int role) {
+  if(role != ActiveShortcutRole)
+    return false;
+
+  if(!index.parent().isValid())
+    return false;
+
+  Item *item = static_cast<Item *>(index.internalPointer());
+  Q_ASSERT(item);
+
+  QKeySequence newSeq = value.value<QKeySequence>();
+  QKeySequence oldSeq = item->shortcut;
+  QKeySequence storedSeq = item->action->shortcut(Action::ActiveShortcut);
+
+  item->shortcut = newSeq;
+  emit dataChanged(index, index.sibling(index.row(), 1));
+
+  if(oldSeq == storedSeq && newSeq != storedSeq) {
+    if(++_changedCount == 1)
+      emit hasChanged(true);
+  } else if(oldSeq != storedSeq && newSeq == storedSeq) {
+    if(--_changedCount == 0)
+      emit hasChanged(false);
+  }
+
+  return true;
+}
+
+void ShortcutsModel::load() {
+  foreach(Item *catItem, _categoryItems) {
+    foreach(Item *actItem, catItem->actionItems) {
+      actItem->shortcut = actItem->action->shortcut(Action::ActiveShortcut);
+    }
+  }
+  emit dataChanged(index(0, 1), index(rowCount()-1, 1));
+  if(_changedCount != 0) {
+    _changedCount = 0;
+    emit hasChanged(false);
+  }
+}
+
+void ShortcutsModel::commit() {
+  foreach(Item *catItem, _categoryItems) {
+    foreach(Item *actItem, catItem->actionItems) {
+      actItem->action->setShortcut(actItem->shortcut, Action::ActiveShortcut);
+    }
+  }
+  if(_changedCount != 0) {
+    _changedCount = 0;
+    emit hasChanged(false);
+  }
+}
+
+void ShortcutsModel::defaults() {
+  for(int cat = 0; cat < rowCount(); cat++) {
+    QModelIndex catidx = index(cat, 0);
+    for(int act = 0; act < rowCount(catidx); act++) {
+      QModelIndex actidx = index(act, 1, catidx);
+      setData(actidx, actidx.data(DefaultShortcutRole), ActiveShortcutRole);
+    }
+  }
+}