src/dialogs/shortcutsmodel.cpp

changeset 1433
bd3a9e237ef5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dialogs/shortcutsmodel.cpp	Wed Dec 26 23:01:45 2018 +0200
@@ -0,0 +1,262 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2018 Teemu Piippo
+ *
+ *  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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <QKeySequenceEdit>
+#include <QSettings>
+#include "mainwindow.h"
+#include "widgets/extendedkeysequenceeditor.h"
+#include "shortcutsmodel.h"
+
+/*
+ * Constructs a new shortcuts model.
+ * Actions are acquired from the provided mainwindow.
+ */
+ShortcutsModel::ShortcutsModel(MainWindow* parent)
+{
+	for (QAction* action : parent->findChildren<QAction*>())
+	{
+		if (not action->objectName().isEmpty())
+			shortcuts.append({action, action->shortcut(), parent->defaultShortcut(action)});
+	}
+}
+
+/*
+ * Returns the amount of shortcuts.
+ */
+int ShortcutsModel::rowCount(const QModelIndex &) const
+{
+	return shortcuts.size();
+}
+
+/*
+ * Returns the amount of columns.
+ */
+int ShortcutsModel::columnCount(const QModelIndex &) const
+{
+	return 2;
+}
+
+/*
+ * Returns various shortcut data.
+ */
+QVariant ShortcutsModel::data(const QModelIndex &index, int role) const
+{
+	if (not isValidIndex(index))
+		return {};
+
+	Item const& entry = shortcuts[index.row()];
+
+	switch (role)
+	{
+	case Qt::DisplayRole:
+		switch (index.column())
+		{
+		case ActionColumn:
+			return entry.action->text().replace("&", "");
+
+		case KeySequenceColumn:
+			return entry.sequence.toString(QKeySequence::NativeText);
+
+		default:
+			return "";
+		}
+
+	case Qt::DecorationRole:
+		if (index.column() == ActionColumn)
+			return entry.action->icon();
+		else
+			return {};
+
+	case Qt::EditRole:
+		switch (index.column())
+		{
+		case KeySequenceColumn:
+			return QVariant::fromValue(entry.sequence);
+
+		default:
+			return {};
+		}
+
+	case DefaultKeySequenceRole:
+		return entry.defaultSequence;
+
+	default:
+		return {};
+	}
+}
+
+/*
+ * Reimplementation of QAbstractItemModel::flags that supplies the editable flag
+ * for the key sequence cells.
+ */
+Qt::ItemFlags ShortcutsModel::flags(const QModelIndex& index) const
+{
+	Qt::ItemFlags flags = QAbstractItemModel::flags(index);
+
+	if (index.column() == KeySequenceColumn)
+		flags |= Qt::ItemIsEditable;
+
+	return flags;
+}
+
+/*
+ * Returns whether or not the specified row is valid.
+ */
+bool ShortcutsModel::isValidRow(int row) const
+{
+	return row >= 0 and row < shortcuts.size();
+}
+
+/*
+ * Returns whether or not the specified model index is valid.
+ */
+bool ShortcutsModel::isValidIndex(const QModelIndex &index) const
+{
+	return index.column() >= 0 and index.column() < 2 and isValidRow(index.row());
+}
+
+/*
+ * Provides an interface for changing the key sequence.
+ */
+bool ShortcutsModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+	if (isValidIndex(index) and index.column() == KeySequenceColumn and role == Qt::EditRole)
+	{
+		shortcuts[index.row()].sequence = value.value<QKeySequence>();
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+/*
+ * Saves shortcuts to the settings object and updates the actions.
+ */
+void ShortcutsModel::saveChanges()
+{
+	for (Item& shortcut : shortcuts)
+	{
+		shortcut.action->setShortcut(shortcut.sequence);
+		QString const key = "shortcut_" + shortcut.action->objectName();
+
+		if (shortcut.defaultSequence != shortcut.sequence)
+			settingsObject().setValue(key, shortcut.sequence);
+		else
+			settingsObject().remove(key);
+	}
+}
+
+/*
+ * Returns an index.
+ */
+QModelIndex ShortcutsModel::index(int row, int column, const QModelIndex& parent) const
+{
+	ignore(parent);
+	return createIndex(row, column);
+}
+
+/*
+ * Returns nothing, because the shortcuts model does not use parents.
+ */
+QModelIndex ShortcutsModel::parent(const QModelIndex &child) const
+{
+	ignore(child);
+	return {};
+}
+
+/*
+ * Returns headers.
+ */
+QVariant ShortcutsModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+	if (role == Qt::DisplayRole and orientation == Qt::Horizontal)
+	{
+		switch (section)
+		{
+		case ActionColumn:
+			return "Action";
+
+		case KeySequenceColumn:
+			return "Shortcut";
+
+		default:
+			return "";
+		}
+	}
+	else
+	{
+		return {};
+	}
+}
+
+/*
+ * Constructs a new key sequence delegate.
+ */
+KeySequenceDelegate::KeySequenceDelegate(QObject *parent) :
+	QStyledItemDelegate {parent} {}
+
+/*
+ * Creates a key sequence editor.
+ */
+QWidget *KeySequenceDelegate::createEditor(
+	QWidget *parent,
+	const QStyleOptionViewItem &option,
+	const QModelIndex &index) const
+{
+	ignore(option, index);
+	const QVariant variant = index.model()->data(index, ShortcutsModel::DefaultKeySequenceRole);
+	const QKeySequence defaultSequence = variant.value<QKeySequence>();
+	ExtendedKeySequenceEditor* editor = new ExtendedKeySequenceEditor {{}, defaultSequence, parent};
+	return editor;
+}
+
+/*
+ * Sets the initial key sequence used in the key sequence editor.
+ */
+void KeySequenceDelegate::setEditorData(QWidget *widget, const QModelIndex &index) const
+{
+	QKeySequence sequence = index.model()->data(index, Qt::EditRole).value<QKeySequence>();
+	ExtendedKeySequenceEditor* editor = static_cast<ExtendedKeySequenceEditor*>(widget);
+	editor->setKeySequence(sequence);
+}
+
+/*
+ * Updates the shortcuts model when the key sequence has been accepted by the user.
+ */
+void KeySequenceDelegate::setModelData(
+	QWidget *widget,
+	QAbstractItemModel *model,
+	const QModelIndex &index) const
+{
+	ExtendedKeySequenceEditor* editor = static_cast<ExtendedKeySequenceEditor*>(widget);
+	model->setData(index, editor->keySequence(), Qt::EditRole);
+}
+
+/*
+ * Updates editor geometry.
+ */
+void KeySequenceDelegate::updateEditorGeometry(
+	QWidget *editor,
+	const QStyleOptionViewItem &option,
+	const QModelIndex &index) const
+{
+	ignore(index);
+	editor->setGeometry(option.rect);
+}

mercurial