/* Copyright 2013, 2016 Adam Reichold This file is part of qpdfview. qpdfview 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) any later version. qpdfview 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 qpdfview. If not, see . */ #include "shortcuthandler.h" #include #include #include "documentview.h" namespace { QList< QKeySequence > toShortcuts(const QStringList& stringList) { QList< QKeySequence > shortcuts; foreach(const QString& string, stringList) { QKeySequence shortcut(string.trimmed()); if(!shortcut.isEmpty()) { shortcuts.append(shortcut); } } return shortcuts; } QStringList toStringList(const QList< QKeySequence >& shortcuts, QKeySequence::SequenceFormat format = QKeySequence::PortableText) { QStringList stringList; foreach(const QKeySequence& shortcut, shortcuts) { stringList.append(shortcut.toString(format)); } return stringList; } inline bool matches(const QKeySequence& keySequence, const QList< QKeySequence >& shortcuts) { foreach(const QKeySequence& shortcut, shortcuts) { if(keySequence.matches(shortcut) == QKeySequence::ExactMatch) { return true; } } return false; } } // anonymous namespace qpdfview { ShortcutHandler* ShortcutHandler::s_instance = 0; ShortcutHandler* ShortcutHandler::instance() { if(s_instance == 0) { s_instance = new ShortcutHandler(qApp); } return s_instance; } ShortcutHandler::~ShortcutHandler() { s_instance = 0; } void ShortcutHandler::registerAction(QAction* action) { Q_ASSERT(!action->objectName().isEmpty()); const QList< QKeySequence > defaultShortcuts = action->shortcuts(); const QList< QKeySequence > shortcuts = toShortcuts(m_settings->value(action->objectName(), toStringList(defaultShortcuts)).toStringList()); action->setShortcuts(shortcuts); m_actions.append(action); m_shortcuts.insert(action, shortcuts); m_defaultShortcuts.insert(action, defaultShortcuts); } int ShortcutHandler::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); return 2; } int ShortcutHandler::rowCount(const QModelIndex& parent) const { Q_UNUSED(parent); return m_actions.count(); } Qt::ItemFlags ShortcutHandler::flags(const QModelIndex& index) const { switch(index.column()) { case 0: return Qt::ItemIsEnabled; case 1: return Qt::ItemIsEnabled | Qt::ItemIsEditable; } return Qt::NoItemFlags; } QVariant ShortcutHandler::headerData(int section, Qt::Orientation orientation, int role) const { Q_UNUSED(orientation); if(role == Qt::DisplayRole) { switch(section) { case 0: return tr("Action"); case 1: return tr("Key sequence"); } } return QVariant(); } QVariant ShortcutHandler::data(const QModelIndex& index, int role) const { if((role == Qt::DisplayRole || role == Qt::EditRole) && index.row() >= 0 && index.row() < m_actions.count()) { QAction* action = m_actions.at(index.row()); switch(index.column()) { case 0: return action->text().remove(QLatin1Char('&')); case 1: return toStringList(m_shortcuts.value(action), QKeySequence::NativeText).join(";"); } } return QVariant(); } bool ShortcutHandler::setData(const QModelIndex& index, const QVariant& value, int role) { if(role == Qt::EditRole && index.column() == 1 && index.row() >= 0 && index.row() < m_actions.count()) { QList< QKeySequence > shortcuts = toShortcuts(value.toString().split(";", QString::SkipEmptyParts)); if(!shortcuts.isEmpty() || value.toString().isEmpty()) { m_shortcuts.insert(m_actions.at(index.row()), shortcuts); emit dataChanged(index, index); return true; } } return false; } bool ShortcutHandler::matchesSkipBackward(const QKeySequence& keySequence) const { return matches(keySequence, m_skipBackwardAction->shortcuts()); } bool ShortcutHandler::matchesSkipForward(const QKeySequence& keySequence) const { return matches(keySequence, m_skipForwardAction->shortcuts()); } bool ShortcutHandler::matchesMoveUp(const QKeySequence& keySequence) const { return matches(keySequence, m_moveUpAction->shortcuts()); } bool ShortcutHandler::matchesMoveDown(const QKeySequence& keySequence) const { return matches(keySequence, m_moveDownAction->shortcuts()); } bool ShortcutHandler::matchesMoveLeft(const QKeySequence& keySequence) const { return matches(keySequence, m_moveLeftAction->shortcuts()); } bool ShortcutHandler::matchesMoveRight(const QKeySequence& keySequence) const { return matches(keySequence, m_moveRightAction->shortcuts()); } bool ShortcutHandler::submit() { for(Shortcuts::iterator iterator = m_shortcuts.begin(); iterator != m_shortcuts.end(); ++iterator) { iterator.key()->setShortcuts(iterator.value()); } foreach(const QAction* action, m_actions) { m_settings->setValue(action->objectName(), toStringList(action->shortcuts())); } return true; } void ShortcutHandler::revert() { for(Shortcuts::iterator iterator = m_shortcuts.begin(); iterator != m_shortcuts.end(); ++iterator) { iterator.value() = iterator.key()->shortcuts(); } } void ShortcutHandler::reset() { for(Shortcuts::iterator iterator = m_defaultShortcuts.begin(); iterator != m_defaultShortcuts.end(); ++iterator) { m_shortcuts.insert(iterator.key(), iterator.value()); } emit dataChanged(createIndex(0, 1), createIndex(m_actions.count(), 1)); } ShortcutHandler::ShortcutHandler(QObject* parent) : QAbstractTableModel(parent), m_settings(new QSettings("qpdfview", "shortcuts", this)), m_actions(), m_shortcuts(), m_defaultShortcuts() { m_skipBackwardAction = createAction( tr("Skip backward"), QLatin1String("skipBackward"), QList< QKeySequence >() << QKeySequence(Qt::Key_PageUp) << QKeySequence(Qt::KeypadModifier + Qt::Key_PageUp)); m_skipForwardAction = createAction( tr("Skip forward"), QLatin1String("skipForward"), QList< QKeySequence >() << QKeySequence(Qt::Key_PageDown) << QKeySequence(Qt::KeypadModifier + Qt::Key_PageDown)); m_moveUpAction = createAction( tr("Move up"), QLatin1String("moveUp"), QList< QKeySequence >() << QKeySequence(Qt::Key_Up) << QKeySequence(Qt::KeypadModifier + Qt::Key_Up)); m_moveDownAction = createAction( tr("Move down"), QLatin1String("moveDown"), QList< QKeySequence >() << QKeySequence(Qt::Key_Down) << QKeySequence(Qt::KeypadModifier + Qt::Key_Down)); m_moveLeftAction = createAction( tr("Move left"), QLatin1String("moveLeft"), QList< QKeySequence >() << QKeySequence(Qt::Key_Left) << QKeySequence(Qt::KeypadModifier + Qt::Key_Left)); m_moveRightAction = createAction( tr("Move right"), QLatin1String("moveRight"), QList< QKeySequence >() << QKeySequence(Qt::Key_Right) << QKeySequence(Qt::KeypadModifier + Qt::Key_Right)); } QAction* ShortcutHandler::createAction(const QString& text, const QString& objectName, const QList& shortcuts) { QAction* action = new QAction(text, this); action->setObjectName(objectName); action->setShortcuts(shortcuts); registerAction(action); return action; } } // qpdfview