Git commit 122d35ffb499f89429efb96f38a03961132bb7d4 by Arjen Hiemstra. Committed on 05/07/2013 at 14:41. Pushed by ahiemstra into branch 'master'.
Make the canvas input configurable This adds a page to the preferences dialog that allows you to select a profile and configure the input for that profile. BUG: 298714 BUG: 298462 BUG: 302478 BUG: 317201 FIXED-IN: 2.8 REVIEW: 111391 GUI: Added a new "Canvas Input Settings" page. DIGEST: Krita's canva input is now configurable. M +1 -0 krita/data/CMakeLists.txt A +4 -0 krita/data/input/CMakeLists.txt A +45 -0 krita/data/input/kritadefault.profile M +21 -0 krita/ui/CMakeLists.txt M +10 -0 krita/ui/dialogs/kis_dlg_preferences.cc M +2 -0 krita/ui/dialogs/kis_dlg_preferences.h A +334 -0 krita/ui/input/config/kis_action_shortcuts_model.cpp [License: GPL (v2+)] A +122 -0 krita/ui/input/config/kis_action_shortcuts_model.h [License: GPL (v2+)] A +88 -0 krita/ui/input/config/kis_edit_profiles_dialog.cpp [License: GPL (v2+)] A +48 -0 krita/ui/input/config/kis_edit_profiles_dialog.h [License: GPL (v2+)] A +88 -0 krita/ui/input/config/kis_edit_profiles_dialog.ui A +230 -0 krita/ui/input/config/kis_input_button.cpp [License: GPL (v2+)] A +143 -0 krita/ui/input/config/kis_input_button.h [License: GPL (v2+)] A +92 -0 krita/ui/input/config/kis_input_configuration_page.cpp [License: GPL (v2+)] A +54 -0 krita/ui/input/config/kis_input_configuration_page.h [License: GPL (v2+)] A +100 -0 krita/ui/input/config/kis_input_configuration_page.ui A +86 -0 krita/ui/input/config/kis_input_configuration_page_item.cpp [License: GPL (v2+)] A +60 -0 krita/ui/input/config/kis_input_configuration_page_item.h [License: GPL (v2+)] A +94 -0 krita/ui/input/config/kis_input_configuration_page_item.ui A +146 -0 krita/ui/input/config/kis_input_editor_delegate.cpp [License: GPL (v2+)] A +46 -0 krita/ui/input/config/kis_input_editor_delegate.h [License: GPL (v2+)] A +80 -0 krita/ui/input/config/kis_input_mode_delegate.cpp [License: GPL (v2+)] A +48 -0 krita/ui/input/config/kis_input_mode_delegate.h [License: GPL (v2+)] A +64 -0 krita/ui/input/config/kis_input_profile_model.cpp [License: GPL (v2+)] A +44 -0 krita/ui/input/config/kis_input_profile_model.h [License: GPL (v2+)] A +75 -0 krita/ui/input/config/kis_input_type_delegate.cpp [License: GPL (v2+)] A +45 -0 krita/ui/input/config/kis_input_type_delegate.h [License: GPL (v2+)] A +77 -0 krita/ui/input/config/kis_key_input_editor.cpp [License: GPL (v2+)] A +54 -0 krita/ui/input/config/kis_key_input_editor.h [License: GPL (v2+)] A +95 -0 krita/ui/input/config/kis_key_input_editor.ui A +100 -0 krita/ui/input/config/kis_mouse_input_editor.cpp [License: GPL (v2+)] A +54 -0 krita/ui/input/config/kis_mouse_input_editor.h [License: GPL (v2+)] A +138 -0 krita/ui/input/config/kis_mouse_input_editor.ui A +99 -0 krita/ui/input/config/kis_wheel_input_editor.cpp [License: GPL (v2+)] A +56 -0 krita/ui/input/config/kis_wheel_input_editor.h [License: GPL (v2+)] A +138 -0 krita/ui/input/config/kis_wheel_input_editor.ui M +11 -5 krita/ui/input/kis_abstract_input_action.cpp M +4 -1 krita/ui/input/kis_abstract_input_action.h M +2 -3 krita/ui/input/kis_alternate_invocation_action.cpp M +1 -1 krita/ui/input/kis_alternate_invocation_action.h M +3 -4 krita/ui/input/kis_change_primary_setting_action.cpp M +1 -1 krita/ui/input/kis_change_primary_setting_action.h M +104 -89 krita/ui/input/kis_input_manager.cpp M +1 -0 krita/ui/input/kis_input_manager.h A +86 -0 krita/ui/input/kis_input_profile.cpp [License: GPL (v2+)] A +95 -0 krita/ui/input/kis_input_profile.h [License: GPL (v2+)] A +287 -0 krita/ui/input/kis_input_profile_manager.cpp [License: GPL (v2+)] A +141 -0 krita/ui/input/kis_input_profile_manager.h [License: GPL (v2+)] M +3 -2 krita/ui/input/kis_pan_action.cpp M +1 -1 krita/ui/input/kis_pan_action.h M +4 -2 krita/ui/input/kis_rotate_canvas_action.cpp M +1 -1 krita/ui/input/kis_rotate_canvas_action.h A +349 -0 krita/ui/input/kis_shortcut_configuration.cpp [License: GPL (v2+)] A +261 -0 krita/ui/input/kis_shortcut_configuration.h [License: GPL (v2+)] M +8 -0 krita/ui/input/kis_shortcut_matcher.cpp M +5 -0 krita/ui/input/kis_shortcut_matcher.h M +2 -2 krita/ui/input/kis_show_palette_action.cpp M +1 -1 krita/ui/input/kis_show_palette_action.h M +3 -1 krita/ui/input/kis_single_action_shortcut.h M +10 -4 krita/ui/input/kis_tool_invocation_action.cpp M +1 -1 krita/ui/input/kis_tool_invocation_action.h M +3 -2 krita/ui/input/kis_zoom_action.cpp M +1 -1 krita/ui/input/kis_zoom_action.h M +9 -0 krita/ui/kis_config.cc M +3 -0 krita/ui/kis_config.h M +3 -0 krita/ui/kis_view2.cpp M +1 -1 krita/ui/tests/kis_input_manager_test.cpp http://commits.kde.org/calligra/122d35ffb499f89429efb96f38a03961132bb7d4 diff --git a/krita/data/CMakeLists.txt b/krita/data/CMakeLists.txt index 7b73e52..2b85ff4 100644 --- a/krita/data/CMakeLists.txt +++ b/krita/data/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory( cursors ) add_subdirectory( workspaces ) add_subdirectory( themes ) add_subdirectory( predefined_image_sizes ) +add_subdirectory( input ) ########### install files ############### install( FILES diff --git a/krita/data/input/CMakeLists.txt b/krita/data/input/CMakeLists.txt new file mode 100644 index 0000000..65bbaad --- /dev/null +++ b/krita/data/input/CMakeLists.txt @@ -0,0 +1,4 @@ +install(FILES + kritadefault.profile + DESTINATION ${DATA_INSTALL_DIR}/krita/input +) diff --git a/krita/data/input/kritadefault.profile b/krita/data/input/kritadefault.profile new file mode 100644 index 0000000..e81013c --- /dev/null +++ b/krita/data/input/kritadefault.profile @@ -0,0 +1,45 @@ +[Alternate Invocation] +0={1;2;[1000021,1000023];1;0;0} +1={0;2;[1000021];1;0;0} + +[Change Primary Setting] +0={0;2;[1000020];1;0;0} + +[General] +name=Krita Default + +[Pan Canvas] +0={4;1;[1000015];0;0;0} +1={3;1;[1000013];0;0;0} +2={2;1;[1000014];0;0;0} +3={1;1;[1000012];0;0;0} +4={0;2;[];4;0;0} +5={0;2;[20];1;0;0} + +[Rotate Canvas] +0={3;1;[36];0;0;0} +1={4;1;[35];0;0;0} +2={2;1;[34];0;0;0} +3={0;2;[1000020];4;0;0} +4={0;2;[1000020,1000023,20];1;0;0} +5={0;2;[1000020,20];1;0;0} + +[Show Popup Palette] +0={0;2;[];2;0;0} + +[Tool Invocation] +0={0;2;[];1;0;0} +1={1;1;[1000004];0;0;0} +2={2;1;[1000000];0;0;0} + +[Zoom Canvas] +0={6;1;[33];0;0;0} +1={5;1;[32];0;0;0} +2={4;1;[31];0;0;0} +3={3;1;[2d];0;0;0} +4={2;1;[3d];0;0;0} +5={3;3;[];0;2;0} +6={2;3;[];0;1;0} +7={0;2;[1000021];4;0;0} +8={1;2;[1000021,1000023,20];1;0;0} +9={0;2;[1000021,20];1;0;0} diff --git a/krita/ui/CMakeLists.txt b/krita/ui/CMakeLists.txt index 6040839..f1a1bf3 100644 --- a/krita/ui/CMakeLists.txt +++ b/krita/ui/CMakeLists.txt @@ -222,6 +222,21 @@ set(kritaui_LIB_SRCS actions/kis_selection_action_factories.cpp kis_document_undo_store.cpp kis_transaction_based_command.cpp + input/kis_input_profile_manager.cpp + input/kis_input_profile.cpp + input/kis_shortcut_configuration.cpp + input/config/kis_input_configuration_page.cpp + input/config/kis_edit_profiles_dialog.cpp + input/config/kis_input_profile_model.cpp + input/config/kis_input_configuration_page_item.cpp + input/config/kis_action_shortcuts_model.cpp + input/config/kis_input_type_delegate.cpp + input/config/kis_input_mode_delegate.cpp + input/config/kis_input_button.cpp + input/config/kis_input_editor_delegate.cpp + input/config/kis_mouse_input_editor.cpp + input/config/kis_wheel_input_editor.cpp + input/config/kis_key_input_editor.cpp ) if(HAVE_OPENGL) @@ -282,6 +297,12 @@ kde4_add_ui_files(kritaui_LIB_SRCS forms/wdgpresetselectorstrip.ui forms/wdgdlgblacklistcleanup.ui forms/wdgflipbookselector.ui + input/config/kis_input_configuration_page.ui + input/config/kis_edit_profiles_dialog.ui + input/config/kis_input_configuration_page_item.ui + input/config/kis_mouse_input_editor.ui + input/config/kis_wheel_input_editor.ui + input/config/kis_key_input_editor.ui ) kde4_add_library(kritaui SHARED ${kritaui_LIB_SRCS} ) diff --git a/krita/ui/dialogs/kis_dlg_preferences.cc b/krita/ui/dialogs/kis_dlg_preferences.cc index a0bb001..ffa46dd 100644 --- a/krita/ui/dialogs/kis_dlg_preferences.cc +++ b/krita/ui/dialogs/kis_dlg_preferences.cc @@ -87,6 +87,8 @@ #include <kis_cubic_curve.h> #include <config-ocio.h> +#include "input/config/kis_input_configuration_page.h" + GeneralTab::GeneralTab(QWidget *_parent, const char *_name) : WdgGeneralSettings(_parent, _name) @@ -677,6 +679,14 @@ KisDlgPreferences::KisDlgPreferences(QWidget* parent, const char* name) page->setHeader(i18n("Author")); page->setIcon(koIcon("user-identity")); + m_inputConfiguration = new KisInputConfigurationPage(); + page = addPage(m_inputConfiguration, i18n("Canvas Input Settings")); + page->setHeader(i18n("Canvas Input")); + page->setIcon(koIcon("input-tablet")); + connect(this, SIGNAL(okClicked()), m_inputConfiguration, SLOT(saveChanges())); + connect(this, SIGNAL(applyClicked()), m_inputConfiguration, SLOT(saveChanges())); + connect(this, SIGNAL(cancelClicked()), m_inputConfiguration, SLOT(revertChanges())); + connect(this, SIGNAL(defaultClicked()), m_inputConfiguration, SLOT(setDefaults())); KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); foreach (KisAbstractPreferenceSetFactory *preferenceSetFactory, preferenceSetRegistry->values()) { diff --git a/krita/ui/dialogs/kis_dlg_preferences.h b/krita/ui/dialogs/kis_dlg_preferences.h index ade1912..7a85260 100644 --- a/krita/ui/dialogs/kis_dlg_preferences.h +++ b/krita/ui/dialogs/kis_dlg_preferences.h @@ -38,6 +38,7 @@ class KoID; class KoConfigAuthorPage; +class KisInputConfigurationPage; /** * "General"-tab for preferences dialog @@ -278,6 +279,7 @@ protected: TabletSettingsTab *m_tabletSettings; FullscreenSettingsTab *m_fullscreenSettings; KoConfigAuthorPage *m_authorSettings; + KisInputConfigurationPage *m_inputConfiguration; protected slots: diff --git a/krita/ui/input/config/kis_action_shortcuts_model.cpp b/krita/ui/input/config/kis_action_shortcuts_model.cpp new file mode 100644 index 0000000..8de11e8 --- /dev/null +++ b/krita/ui/input/config/kis_action_shortcuts_model.cpp @@ -0,0 +1,334 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_action_shortcuts_model.h" + +#include <KLocalizedString> +#include <QMetaClassInfo> +#include <QKeySequence> + +#include "KoIcon.h" + +#include "input/kis_abstract_input_action.h" +#include "input/kis_input_profile.h" +#include "input/kis_input_profile_manager.h" +#include "input/kis_shortcut_configuration.h" + +class KisActionShortcutsModel::Private +{ +public: + Private() : action(0), profile(0), temporaryShortcut(0) { } + + KisAbstractInputAction *action; + KisInputProfile *profile; + QList<KisShortcutConfiguration *> shortcuts; + + KisShortcutConfiguration *temporaryShortcut; +}; + +KisActionShortcutsModel::KisActionShortcutsModel(QObject *parent) + : QAbstractListModel(parent), d(new Private) +{ + connect(KisInputProfileManager::instance(), SIGNAL(currentProfileChanged()), SLOT(currentProfileChanged())); +} + +KisActionShortcutsModel::~KisActionShortcutsModel() +{ +} + +QVariant KisActionShortcutsModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + if (index.row() == d->shortcuts.count() && role == Qt::DisplayRole) { + if (index.column() == 0) { + return i18n("Add shortcut..."); + } + else { + return QVariant(); + } + } + + if (role == Qt::DisplayRole) { + switch (index.column()) { + case 0: + switch (d->shortcuts.at(index.row())->type()) { + case KisShortcutConfiguration::KeyCombinationType: + return i18nc("Shortcut type", "Key Combination"); + + case KisShortcutConfiguration::MouseButtonType: + return i18nc("Shortcut type", "Mouse Button"); + + case KisShortcutConfiguration::MouseWheelType: + return i18nc("Shortcut type", "Mouse Wheel"); + + case KisShortcutConfiguration::GestureType: + return i18nc("Shortcut type", "Gesture"); + + default: + return i18n("Unknown Input"); + } + + break; + + case 1: { + KisShortcutConfiguration *s = d->shortcuts.at(index.row()); + QString output; + + switch (s->type()) { + case KisShortcutConfiguration::KeyCombinationType: + output = KisShortcutConfiguration::keysToText(s->keys()); + break; + + case KisShortcutConfiguration::MouseButtonType: + if (s->keys().size() > 0) { + output.append(KisShortcutConfiguration::keysToText(s->keys())); + output.append(" + "); + } + + output.append(KisShortcutConfiguration::buttonsToText(s->buttons())); + break; + + case KisShortcutConfiguration::MouseWheelType: + if (s->keys().size() > 0) { + output.append(KisShortcutConfiguration::keysToText(s->keys())); + output.append(" + "); + } + + output.append(KisShortcutConfiguration::wheelToText(s->wheel())); + break; + + default: + break; + } + + return output; + } + + case 2: + return d->action->shortcutIndexes().key(d->shortcuts.at(index.row())->mode()); + + case 3: + return koIcon("edit-delete"); + + default: + break; + } + } + else if (role == Qt::EditRole) { + KisShortcutConfiguration *s; + + if (index.row() == d->shortcuts.count()) { + if (!d->temporaryShortcut) { + d->temporaryShortcut = new KisShortcutConfiguration; + } + + s = d->temporaryShortcut; + } + else { + s = d->shortcuts.at(index.row()); + } + + switch (index.column()) { + case 0: + return s->type(); + + case 1: + return QVariant::fromValue(s); + + case 2: + return s->mode(); + + default: + break; + } + } + + return QVariant(); +} + +int KisActionShortcutsModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + + return d->shortcuts.count() + 1; +} + +int KisActionShortcutsModel::columnCount(const QModelIndex & /*parent*/) const +{ + return 3; +} + +QVariant KisActionShortcutsModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Horizontal || role != Qt::DisplayRole) { + return QVariant(); + } + + switch (section) { + case 0: + return i18nc("Type of shortcut", "Type"); + + case 1: + return i18nc("Input for shortcut", "Input"); + + case 2: + return i18nc("Action to trigger with shortcut", "Action"); + + default: + break; + } + + return QVariant(); +} + +Qt::ItemFlags KisActionShortcutsModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) { + return Qt::ItemIsEnabled; + } + + if (index.row() == d->shortcuts.count() && index.column() != 0) { + return Qt::ItemIsEnabled; + } + + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; +} + +bool KisActionShortcutsModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || role != Qt::EditRole) { + return false; + } + + if (index.row() == d->shortcuts.count()) { + if (!d->temporaryShortcut || (index.column() == 0 && value.toUInt() == 0)) { + return false; + } + + beginInsertRows(QModelIndex(), d->shortcuts.count(), d->shortcuts.count()); + d->temporaryShortcut->setAction(d->action); + d->profile->addShortcut(d->temporaryShortcut); + d->shortcuts.append(d->temporaryShortcut); + d->temporaryShortcut = 0; + endInsertRows(); + } + + switch (index.column()) { + case 0: + d->shortcuts.at(index.row())->setType(static_cast<KisShortcutConfiguration::ShortcutType>(value.toUInt())); + break; + + case 1: { + KisShortcutConfiguration *newData = value.value<KisShortcutConfiguration *>(); + KisShortcutConfiguration *oldData = d->shortcuts.at(index.row()); + + if (newData == oldData) + return true; + + oldData->setKeys(newData->keys()); + oldData->setButtons(newData->buttons()); + oldData->setWheel(newData->wheel()); + oldData->setGesture(newData->gesture()); + + break; + } + + case 2: + d->shortcuts.at(index.row())->setMode(value.toUInt()); + break; + } + + return true; +} + +KisAbstractInputAction *KisActionShortcutsModel::action() const +{ + return d->action; +} + +void KisActionShortcutsModel::setAction(KisAbstractInputAction *action) +{ + if (action != d->action) { + if (d->action) { + beginRemoveRows(QModelIndex(), 0, d->shortcuts.count() - 1); + endRemoveRows(); + } + + d->action = action; + + if (d->action && d->profile) { + d->shortcuts = d->profile->shortcutsForAction(d->action); + beginInsertRows(QModelIndex(), 0, d->shortcuts.count() - 1); + endInsertRows(); + } + } +} + +KisInputProfile *KisActionShortcutsModel::profile() const +{ + return d->profile; +} + +void KisActionShortcutsModel::setProfile(KisInputProfile *profile) +{ + if (profile != d->profile) { + if (d->profile) { + beginRemoveRows(QModelIndex(), 0, d->shortcuts.count() - 1); + endRemoveRows(); + } + + d->profile = profile; + + if (d->action && d->profile) { + d->shortcuts = d->profile->shortcutsForAction(d->action); + beginInsertRows(QModelIndex(), 0, d->shortcuts.count() - 1); + endInsertRows(); + } + } +} + +void KisActionShortcutsModel::currentProfileChanged() +{ + setProfile(KisInputProfileManager::instance()->currentProfile()); +} + +bool KisActionShortcutsModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (row < 0 || row >= d->shortcuts.count() || count == 0) { + return false; + } + + beginRemoveRows(parent, row, row + count - 1); + + for (int i = row; i < d->shortcuts.count() && count > 0; ++i, count--) { + KisShortcutConfiguration *s = d->shortcuts.at(i); + d->profile->removeShortcut(s); + d->shortcuts.removeOne(s); + delete s; + } + + endRemoveRows(); + + return true; +} diff --git a/krita/ui/input/config/kis_action_shortcuts_model.h b/krita/ui/input/config/kis_action_shortcuts_model.h new file mode 100644 index 0000000..546cd3b --- /dev/null +++ b/krita/ui/input/config/kis_action_shortcuts_model.h @@ -0,0 +1,122 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISACTIONSHORTCUTSMODEL_H +#define KISACTIONSHORTCUTSMODEL_H + +#include <QAbstractListModel> + +class KisAbstractInputAction; +class KisInputProfile; + +/** + * \brief A QAbstractListModel subclass that lists shortcuts associated with an action from a profile. + * + * This class lists all shortcuts from the set profile that correspond to a specific action. This is + * used to allow editing of shortcuts from the ui. + * + * It defines the following columns: + * - Type: The type of shortcut, can be one of Key Combination, Mouse Button, Mouse Wheel, Gesture + * - Input: What input is used to activate the shortcut. Depends on the type. + * - Action: What mode of the action will be activated by the shortcut. + * + * \note Before this model will provide any data you should call setAction and setProfile. + * \note This model is editable and provides an implementation of removeRows. + */ +class KisActionShortcutsModel : public QAbstractListModel +{ + Q_OBJECT +public: + /** + * Constructor. + */ + explicit KisActionShortcutsModel(QObject *parent = 0); + /** + * Destructor. + */ + ~KisActionShortcutsModel(); + + /** + * Reimplemented from QAbstractItemModel::data() + */ + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + /** + * Reimplemented from QAbstractItemModel::rowCount() + */ + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + /** + * Reimplemented from QAbstractItemModel::columnCount() + */ + virtual int columnCount(const QModelIndex &) const; + /** + * Reimplemented from QAbstractItemModel::headerData() + */ + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = + Qt::DisplayRole) const; + /** + * Reimplemented from QAbstractItemModel::flags() + */ + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + /** + * Reimplemented from QAbstractItemModel::setData() + */ + virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + /** + * Reimplemented from QAbstractItemModel::removeRows. + * + * Removes `count` rows starting at `row`. + * + * \note The associated shortcuts will also be removed from the profile and completely + * deleted. + */ + virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + + /** + * \return The action used as data constraint for this model. + */ + KisAbstractInputAction *action() const; + /** + * \return The profile used as data source for this model. + */ + KisInputProfile *profile() const; + +public Q_SLOTS: + /** + * Set the action used as data constraint for this model. + * + * \param action The action to use. + */ + void setAction(KisAbstractInputAction *action); + /** + * Set the profile used as data source for this model. + * + * \param profile The profile to get the data from. + */ + void setProfile(KisInputProfile *profile); + +private Q_SLOTS: + void currentProfileChanged(); + +private: + class Private; + Private *const d; +}; + +#endif // KISACTIONSHORTCUTSMODEL_H diff --git a/krita/ui/input/config/kis_edit_profiles_dialog.cpp b/krita/ui/input/config/kis_edit_profiles_dialog.cpp new file mode 100644 index 0000000..4982185 --- /dev/null +++ b/krita/ui/input/config/kis_edit_profiles_dialog.cpp @@ -0,0 +1,88 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_edit_profiles_dialog.h" + +#include <QPushButton> +#include <QStringListModel> +#include <KLocalizedString> + +#include "KoIcon.h" +#include "input/kis_input_profile_manager.h" +#include "kis_input_profile_model.h" + +#include "ui_kis_edit_profiles_dialog.h" + +class KisEditProfilesDialog::Private +{ +public: + Private() { } + + Ui::KisEditProfilesDialog *ui; + KisInputProfileModel *profileModel; +}; + +KisEditProfilesDialog::KisEditProfilesDialog(QWidget *parent, Qt::WindowFlags flags) + : KDialog(parent, flags), d(new Private()) +{ + QWidget *mainWidget = new QWidget(this); + d->ui = new Ui::KisEditProfilesDialog(); + d->ui->setupUi(mainWidget); + setMainWidget(mainWidget); + + d->profileModel = new KisInputProfileModel(this); + d->ui->profileList->setModel(d->profileModel); + + connect(d->ui->addButton, SIGNAL(clicked(bool)), SLOT(addButtonClicked())); + connect(d->ui->removeButton, SIGNAL(clicked(bool)), SLOT(removeButtonClicked())); + connect(d->ui->duplicateButton, SIGNAL(clicked(bool)), SLOT(duplicateButtonClicked())); + connect(d->ui->renameButton, SIGNAL(clicked(bool)), SLOT(renameButtonClicked())); + + setButtons(Close | Default); + setWindowTitle(i18n("Edit Profiles")); +} + +KisEditProfilesDialog::~KisEditProfilesDialog() +{ + delete d; +} + +void KisEditProfilesDialog::addButtonClicked() +{ + QString newProfileName = i18n("New Profile"); + KisInputProfileManager::instance()->addProfile(newProfileName); + d->ui->profileList->edit(d->profileModel->find(newProfileName)); +} + +void KisEditProfilesDialog::removeButtonClicked() +{ + KisInputProfileManager::instance()->removeProfile(d->profileModel->profileName(d->ui->profileList->currentIndex())); +} + +void KisEditProfilesDialog::duplicateButtonClicked() +{ + QString currentName = d->profileModel->profileName(d->ui->profileList->currentIndex()); + QString newName = i18n("Copy of %1").arg(currentName); + KisInputProfileManager::instance()->duplicateProfile(currentName, newName); +} + +void KisEditProfilesDialog::renameButtonClicked() +{ + d->ui->profileList->edit(d->ui->profileList->currentIndex()); +} diff --git a/krita/ui/input/config/kis_edit_profiles_dialog.h b/krita/ui/input/config/kis_edit_profiles_dialog.h new file mode 100644 index 0000000..a11f0d5 --- /dev/null +++ b/krita/ui/input/config/kis_edit_profiles_dialog.h @@ -0,0 +1,48 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISEDITPROFILESDIALOG_H +#define KISEDITPROFILESDIALOG_H + +#include <KDialog> + +class QListWidgetItem; +/** + * \brief A dialog that provides facilities to edit all the available profiles. + * + */ +class KisEditProfilesDialog : public KDialog +{ + Q_OBJECT +public: + KisEditProfilesDialog(QWidget *parent = 0, Qt::WindowFlags flags = 0); + ~KisEditProfilesDialog(); + +private Q_SLOTS: + void addButtonClicked(); + void removeButtonClicked(); + void duplicateButtonClicked(); + void renameButtonClicked(); + +private: + class Private; + Private *const d; +}; + +#endif // KISEDITPROFILESDIALOG_H diff --git a/krita/ui/input/config/kis_edit_profiles_dialog.ui b/krita/ui/input/config/kis_edit_profiles_dialog.ui new file mode 100644 index 0000000..a831bf9 --- /dev/null +++ b/krita/ui/input/config/kis_edit_profiles_dialog.ui @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>KisEditProfilesDialog</class> + <widget class="QWidget" name="KisEditProfilesDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>667</width> + <height>682</height> + </rect> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="1"> + <widget class="KPushButton" name="removeButton"> + <property name="text"> + <string>Remove</string> + </property> + <property name="icon"> + <iconset theme="list-remove"> + <normaloff/> + </iconset> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="KPushButton" name="renameButton"> + <property name="text"> + <string>Rename</string> + </property> + <property name="icon"> + <iconset theme="edit-rename"> + <normaloff/> + </iconset> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="KPushButton" name="addButton"> + <property name="text"> + <string>Add</string> + </property> + <property name="icon"> + <iconset theme="list-add"> + <normaloff/> + </iconset> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="KPushButton" name="duplicateButton"> + <property name="text"> + <string>Duplicate</string> + </property> + <property name="icon"> + <iconset theme="edit-copy"> + <normaloff/> + </iconset> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0" colspan="4"> + <widget class="QListView" name="profileList"/> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>KPushButton</class> + <extends>QPushButton</extends> + <header>kpushbutton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/krita/ui/input/config/kis_input_button.cpp b/krita/ui/input/config/kis_input_button.cpp new file mode 100644 index 0000000..a31b04a --- /dev/null +++ b/krita/ui/input/config/kis_input_button.cpp @@ -0,0 +1,230 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_input_button.h" + +#include <QTimer> +#include <QMouseEvent> +#include <QKeyEvent> +#include <KLocalizedString> + +#include "KoIcon.h" + +#include "input/kis_shortcut_configuration.h" + +class KisInputButton::Private +{ +public: + Private(KisInputButton *qq) : q(qq), type(KeyType), newInput(false), resetTimer(0) { } + void updateLabel(); + + KisInputButton *q; + + ButtonType type; + + QList<Qt::Key> keys; + Qt::MouseButtons buttons; + KisShortcutConfiguration::MouseWheelMovement wheel; + bool newInput; + + QTimer *resetTimer; +}; + +KisInputButton::KisInputButton(QWidget *parent) + : KPushButton(parent), d(new Private(this)) +{ + setIcon(koIcon("configure-shortcuts")); + setText(i18nc("No input for this button", "None")); + setCheckable(true); + + d->resetTimer = new QTimer(this); + d->resetTimer->setInterval(5000); + d->resetTimer->setSingleShot(true); + connect(d->resetTimer, SIGNAL(timeout()), SLOT(reset())); +} + +KisInputButton::~KisInputButton() +{ + delete d; +} + +KisInputButton::ButtonType KisInputButton::type() const +{ + return d->type; +} + +void KisInputButton::setType(KisInputButton::ButtonType newType) +{ + d->type = newType; +} + +void KisInputButton::clear() +{ + d->keys.clear(); + d->buttons = 0; + d->wheel = KisShortcutConfiguration::NoMovement; + d->updateLabel(); +} + +QList< Qt::Key > KisInputButton::keys() const +{ + return d->keys; +} + +void KisInputButton::setKeys(const QList< Qt::Key > &newKeys) +{ + if (newKeys != d->keys) { + d->keys = newKeys; + d->updateLabel(); + } +} + +Qt::MouseButtons KisInputButton::buttons() const +{ + return d->buttons; +} + +void KisInputButton::setButtons(Qt::MouseButtons newButtons) +{ + if (newButtons != d->buttons) { + d->buttons = newButtons; + d->updateLabel(); + } +} + +KisShortcutConfiguration::MouseWheelMovement KisInputButton::wheel() const +{ + return d->wheel; +} + +void KisInputButton::setWheel(KisShortcutConfiguration::MouseWheelMovement newWheel) +{ + if (newWheel != d->wheel) { + d->wheel = newWheel; + d->updateLabel(); + } +} + +void KisInputButton::mousePressEvent(QMouseEvent *event) +{ + if (isChecked() && d->type == KisInputButton::MouseType) { + d->buttons = event->buttons(); + d->updateLabel(); + d->resetTimer->start(); + } +} + +void KisInputButton::mouseReleaseEvent(QMouseEvent *) +{ + if (isChecked()) { + reset(); + } + else { + setChecked(true); + setText(i18nc("Waiting for user input", "Input ...")); + d->resetTimer->start(); + d->newInput = true; + } +} + +void KisInputButton::wheelEvent(QWheelEvent *event) +{ + if (isChecked() && event->delta() != 0) { + switch (event->orientation()) { + case Qt::Horizontal: + if (event->delta() < 0) { + d->wheel = KisShortcutConfiguration::WheelRight; + } + else { + d->wheel = KisShortcutConfiguration::WheelLeft; + } + + break; + + case Qt::Vertical: + if (event->delta() > 0) { + d->wheel = KisShortcutConfiguration::WheelUp; + } + else { + d->wheel = KisShortcutConfiguration::WheelDown; + } + + break; + } + + d->updateLabel(); + } +} + +void KisInputButton::keyPressEvent(QKeyEvent *event) +{ + if (isChecked()) { + if (d->newInput) { + d->keys.clear(); + d->newInput = false; + } + + Qt::Key key = static_cast<Qt::Key>(event->key()); + + if (key == Qt::Key_Meta && event->modifiers().testFlag(Qt::ShiftModifier)) { + key = Qt::Key_Alt; + } + + d->keys.append(key); + d->updateLabel(); + d->resetTimer->start(); + } +} + +void KisInputButton::keyReleaseEvent(QKeyEvent *event) +{ + if (isChecked()) { + reset(); + } + else if (event->key() == Qt::Key_Space || event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { + setChecked(true); + setText(i18nc("Waiting for user input", "Input ...")); + d->resetTimer->start(); + d->newInput = true; + } +} + +void KisInputButton::reset() +{ + setChecked(false); + d->updateLabel(); + emit dataChanged(); +} + +void KisInputButton::Private::updateLabel() +{ + switch (type) { + case MouseType: + q->setText(KisShortcutConfiguration::buttonsToText(buttons)); + break; + + case KeyType: + q->setText(KisShortcutConfiguration::keysToText(keys)); + break; + + case WheelType: + q->setText(KisShortcutConfiguration::wheelToText(wheel)); + break; + } +} diff --git a/krita/ui/input/config/kis_input_button.h b/krita/ui/input/config/kis_input_button.h new file mode 100644 index 0000000..19db3a5 --- /dev/null +++ b/krita/ui/input/config/kis_input_button.h @@ -0,0 +1,143 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISINPUTBUTTON_H +#define KISINPUTBUTTON_H + +#include <KPushButton> + +#include "input/kis_shortcut_configuration.h" + +/** + * \brief A button that can detect input and will store its value. + * + * This button, when pressed, will detect input based on what type has been set. + * It is mainly intended for shortcut configuration, that is, picking some input that is + * later reused for shortcuts or similar. + * + */ +class KisInputButton : public KPushButton +{ + Q_OBJECT +public: + /** + * The type of button. + */ + enum ButtonType { + MouseType, ///< Detect and store any combination of pressed mouse buttons. + KeyType, ///< Detect and store any combination of key presses. + WheelType, ///< Detect and store mouse wheel movement. + }; + + /** + * Constructor. + */ + explicit KisInputButton(QWidget *parent = 0); + /** + * Destructor. + */ + virtual ~KisInputButton(); + + /** + * \return The type of input this button detects. + */ + ButtonType type() const; + /** + * Set the type of input this button should detect. + * + * \param newType The type of input to detect. + */ + void setType(ButtonType newType); + + /** + * \return The list of keys that was detected. Only applicable when type is `KeyType`. + */ + QList<Qt::Key> keys() const; + /** + * Set the list of keys to display. + * + * This is mostly intended to make sure the button displays the right keys when viewed + * in a dialog or similar UI. + * + * Only applicable when type is `KeyType`. + * + * \param newKeys The list of keys to display. + */ + void setKeys(const QList<Qt::Key> &newKeys); + + /** + * \return The mouse buttons that were detected. Only applicable when type is `MouseType`. + */ + Qt::MouseButtons buttons() const; + /** + * Set the mouse buttons to display. + * + * This is mostly intended to make sure the button displays the right buttons when viewed + * in a dialog or similar UI. + * + * Only applicable when type is `MouseType`. + * + * \param newButtons The mouse buttons to display. + */ + void setButtons(Qt::MouseButtons newButtons); + + /** + * \return The mouse wheel movement that was detected. Only applicable when type is `WheelType`. + */ + KisShortcutConfiguration::MouseWheelMovement wheel() const; + /** + * Set the mouse wheel movement to display. + * + * This is mostly intended to make sure the button displays the right wheel movement when + * viewed in a dialog or similar UI. + * + * Only applicable when type is `WheelType`. + * + * \param newButtons The wheel movement to display. + */ + void setWheel(KisShortcutConfiguration::MouseWheelMovement wheel); + +public Q_SLOTS: + /** + * Clear all detected input and reset the button to an empty state. + */ + void clear(); + +Q_SIGNALS: + /** + * Emitted whenever one of the values (keys, buttons, wheel) changes. + */ + void dataChanged(); + +protected: + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *); + virtual void wheelEvent(QWheelEvent *event); + virtual void keyPressEvent(QKeyEvent *event); + virtual void keyReleaseEvent(QKeyEvent *event); + +private Q_SLOTS: + void reset(); + +private: + class Private; + Private *const d; +}; + +#endif // KISINPUTBUTTON_H diff --git a/krita/ui/input/config/kis_input_configuration_page.cpp b/krita/ui/input/config/kis_input_configuration_page.cpp new file mode 100644 index 0000000..b440056 --- /dev/null +++ b/krita/ui/input/config/kis_input_configuration_page.cpp @@ -0,0 +1,92 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_input_configuration_page.h" +#include "ui_kis_input_configuration_page.h" + +#include "input/kis_input_profile_manager.h" +#include "input/kis_input_profile.h" +#include "kis_edit_profiles_dialog.h" +#include "kis_input_profile_model.h" +#include "kis_input_configuration_page_item.h" +#include <QDir> +#include <KStandardDirs> + +KisInputConfigurationPage::KisInputConfigurationPage(QWidget *parent, Qt::WindowFlags f) + : QWidget(parent, f) +{ + ui = new Ui::KisInputConfigurationPage; + ui->setupUi(this); + + ui->profileComboBox->setModel(new KisInputProfileModel(ui->profileComboBox)); + updateSelectedProfile(); + connect(ui->profileComboBox, SIGNAL(currentIndexChanged(QString)), SLOT(changeCurrentProfile(QString))); + + connect(ui->editProfilesButton, SIGNAL(clicked(bool)), SLOT(editProfilesButtonClicked())); + connect(KisInputProfileManager::instance(), SIGNAL(profilesChanged()), SLOT(updateSelectedProfile())); + + QList<KisAbstractInputAction *> actions = KisInputProfileManager::instance()->actions(); + Q_FOREACH(KisAbstractInputAction * action, actions) { + KisInputConfigurationPageItem *item = new KisInputConfigurationPageItem(this); + item->setAction(action); + ui->configurationItemsArea->addWidget(item); + } +} + +void KisInputConfigurationPage::saveChanges() +{ + KisInputProfileManager::instance()->saveProfiles(); +} + +void KisInputConfigurationPage::revertChanges() +{ + KisInputProfileManager::instance()->loadProfiles(); +} + +void KisInputConfigurationPage::setDefaults() +{ + QDir profileDir(KGlobal::dirs()->saveLocation("appdata", "input/", false)); + + if (profileDir.exists()) { + QStringList entries = profileDir.entryList(QStringList() << "*.profile", QDir::NoDot | QDir::NoDotDot); + Q_FOREACH(const QString & file, entries) { + profileDir.remove(file); + } + + KisInputProfileManager::instance()->loadProfiles(); + } +} + +void KisInputConfigurationPage::editProfilesButtonClicked() +{ + KisEditProfilesDialog dialog; + dialog.exec(); +} + +void KisInputConfigurationPage::updateSelectedProfile() +{ + if (KisInputProfileManager::instance()->currentProfile()) { + ui->profileComboBox->setCurrentItem(KisInputProfileManager::instance()->currentProfile()->name()); + } +} + +void KisInputConfigurationPage::changeCurrentProfile(const QString &newProfile) +{ + KisInputProfileManager::instance()->setCurrentProfile(KisInputProfileManager::instance()->profile(newProfile)); +} diff --git a/krita/ui/input/config/kis_input_configuration_page.h b/krita/ui/input/config/kis_input_configuration_page.h new file mode 100644 index 0000000..45339fd --- /dev/null +++ b/krita/ui/input/config/kis_input_configuration_page.h @@ -0,0 +1,54 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISINPUTCONFIGURATIONPAGE_H +#define KISINPUTCONFIGURATIONPAGE_H + +#include <QWidget> + +namespace Ui +{ +class KisInputConfigurationPage; +} + +/** + * \brief A Configuration Dialog Page to configure the canvas input. + */ +class KisInputConfigurationPage : public QWidget +{ + Q_OBJECT +public: + KisInputConfigurationPage(QWidget *parent = 0, Qt::WindowFlags f = 0); + +public Q_SLOTS: + void saveChanges(); + void revertChanges(); + void setDefaults(); + +private Q_SLOTS: + void editProfilesButtonClicked(); + void updateSelectedProfile(); + void changeCurrentProfile(const QString &newProfile); + +private: + Ui::KisInputConfigurationPage *ui; + +}; + +#endif // KISINPUTCONFIGURATIONPAGE_H diff --git a/krita/ui/input/config/kis_input_configuration_page.ui b/krita/ui/input/config/kis_input_configuration_page.ui new file mode 100644 index 0000000..d5a9cb3 --- /dev/null +++ b/krita/ui/input/config/kis_input_configuration_page.ui @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>KisInputConfigurationPage</class> + <widget class="QWidget" name="KisInputConfigurationPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1016</width> + <height>979</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Profile</string> + </property> + </widget> + </item> + <item> + <widget class="KComboBox" name="profileComboBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="KPushButton" name="editProfilesButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Duplicate current profile</string> + </property> + <property name="text"> + <string>Edit Profiles</string> + </property> + <property name="icon"> + <iconset theme="document-edit"> + <normaloff/> + </iconset> + </property> + <property name="iconSize"> + <size> + <width>18</width> + <height>20</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="configurationItemsArea"/> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>KComboBox</class> + <extends>QComboBox</extends> + <header>kcombobox.h</header> + </customwidget> + <customwidget> + <class>KPushButton</class> + <extends>QPushButton</extends> + <header>kpushbutton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/krita/ui/input/config/kis_input_configuration_page_item.cpp b/krita/ui/input/config/kis_input_configuration_page_item.cpp new file mode 100644 index 0000000..e3c03e3 --- /dev/null +++ b/krita/ui/input/config/kis_input_configuration_page_item.cpp @@ -0,0 +1,86 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_input_configuration_page_item.h" + +#include "KoIcon.h" + +#include "input/kis_abstract_input_action.h" +#include "input/kis_input_profile_manager.h" +#include "kis_action_shortcuts_model.h" +#include "kis_input_type_delegate.h" +#include "kis_input_mode_delegate.h" +#include "kis_input_editor_delegate.h" +#include "ui_kis_input_configuration_page_item.h" + +KisInputConfigurationPageItem::KisInputConfigurationPageItem(QWidget *parent, Qt::WindowFlags f) + : QWidget(parent, f) +{ + ui = new Ui::KisInputConfigurationPageItem; + ui->setupUi(this); + + m_shortcutsModel = new KisActionShortcutsModel(this); + ui->shortcutsView->setModel(m_shortcutsModel); + ui->shortcutsView->setItemDelegateForColumn(0, new KisInputTypeDelegate(ui->shortcutsView)); + ui->shortcutsView->setItemDelegateForColumn(1, new KisInputEditorDelegate(ui->shortcutsView)); + ui->shortcutsView->setItemDelegateForColumn(2, new KisInputModeDelegate(ui->shortcutsView)); + ui->shortcutsView->header()->setResizeMode(QHeaderView::Stretch); + setExpanded(false); + + QAction *deleteAction = new QAction(koIcon("edit-delete"), i18n("Delete Shortcut"), ui->shortcutsView); + connect(deleteAction, SIGNAL(triggered(bool)), SLOT(deleteShortcut())); + ui->shortcutsView->addAction(deleteAction); + ui->shortcutsView->setContextMenuPolicy(Qt::ActionsContextMenu); + + connect(ui->collapseButton, SIGNAL(clicked(bool)), SLOT(setExpanded(bool))); +} + +KisInputConfigurationPageItem::~KisInputConfigurationPageItem() +{ + delete ui; +} + +void KisInputConfigurationPageItem::setAction(KisAbstractInputAction *action) +{ + m_action = action; + ui->collapseButton->setText(action->name()); + ui->descriptionLabel->setText(action->description()); + m_shortcutsModel->setProfile(KisInputProfileManager::instance()->currentProfile()); + m_shortcutsModel->setAction(action); + qobject_cast<KisInputModeDelegate *>(ui->shortcutsView->itemDelegateForColumn(2))->setAction(action); +} + +void KisInputConfigurationPageItem::setExpanded(bool expand) +{ + if (expand) { + ui->descriptionLabel->setVisible(true); + ui->shortcutsView->setVisible(true); + ui->collapseButton->setArrowType(Qt::DownArrow); + } + else { + ui->descriptionLabel->setVisible(false); + ui->shortcutsView->setVisible(false); + ui->collapseButton->setArrowType(Qt::RightArrow); + } +} + +void KisInputConfigurationPageItem::deleteShortcut() +{ + m_shortcutsModel->removeRow(ui->shortcutsView->selectionModel()->currentIndex().row(), QModelIndex()); +} diff --git a/krita/ui/input/config/kis_input_configuration_page_item.h b/krita/ui/input/config/kis_input_configuration_page_item.h new file mode 100644 index 0000000..25f2f1e --- /dev/null +++ b/krita/ui/input/config/kis_input_configuration_page_item.h @@ -0,0 +1,60 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISINPUTCONFIGURATIONPAGEITEM_H +#define KISINPUTCONFIGURATIONPAGEITEM_H + +#include <QWidget> + +namespace Ui +{ +class KisInputConfigurationPageItem; +} + +class KisActionShortcutsModel; +class QModelIndex; +class KisAbstractInputAction; +/** + * \brief A collapsible widget displaying an action, its description and associated shortcuts. + * + * This is used in KisInputConfigurationPage to display a list of actions and the associated + * shortcuts, depending on the current profile. + */ +class KisInputConfigurationPageItem : public QWidget +{ + Q_OBJECT +public: + KisInputConfigurationPageItem(QWidget *parent = 0, Qt::WindowFlags f = 0); + ~KisInputConfigurationPageItem(); + + void setAction(KisAbstractInputAction *action); + +public Q_SLOTS: + void setExpanded(bool expand); + +private Q_SLOTS: + void deleteShortcut(); + +private: + Ui::KisInputConfigurationPageItem *ui; + KisAbstractInputAction *m_action; + KisActionShortcutsModel *m_shortcutsModel; +}; + +#endif // KISINPUTCONFIGURATIONPAGEITEM_H diff --git a/krita/ui/input/config/kis_input_configuration_page_item.ui b/krita/ui/input/config/kis_input_configuration_page_item.ui new file mode 100644 index 0000000..e9a41fb --- /dev/null +++ b/krita/ui/input/config/kis_input_configuration_page_item.ui @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>KisInputConfigurationPageItem</class> + <widget class="QWidget" name="KisInputConfigurationPageItem"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>605</width> + <height>330</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="1" colspan="2"> + <widget class="QLabel" name="descriptionLabel"> + <property name="text"> + <string><html><head/><body><p>Action Description</p></body></html></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0" colspan="3"> + <widget class="QToolButton" name="collapseButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Action Name</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + <property name="arrowType"> + <enum>Qt::RightArrow</enum> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="QTreeView" name="shortcutsView"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="itemsExpandable"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/krita/ui/input/config/kis_input_editor_delegate.cpp b/krita/ui/input/config/kis_input_editor_delegate.cpp new file mode 100644 index 0000000..b5bd3df --- /dev/null +++ b/krita/ui/input/config/kis_input_editor_delegate.cpp @@ -0,0 +1,146 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_input_editor_delegate.h" + +#include <QApplication> + +#include <KLocalizedString> + +#include "input/kis_input_profile.h" +#include "input/kis_shortcut_configuration.h" +#include "kis_input_button.h" +#include "kis_mouse_input_editor.h" +#include "kis_wheel_input_editor.h" +#include "kis_key_input_editor.h" + +class KisInputEditorDelegate::Private +{ +public: + Private() { } +}; + +KisInputEditorDelegate::KisInputEditorDelegate(QObject *parent) + : QStyledItemDelegate(parent), d(new Private()) +{ +} + +KisInputEditorDelegate::~KisInputEditorDelegate() +{ + delete d; + +} + +QWidget *KisInputEditorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const +{ + KPushButton *editor = 0; + KisShortcutConfiguration *s = index.data(Qt::EditRole).value<KisShortcutConfiguration *>(); + + switch (s->type()) { + case KisShortcutConfiguration::KeyCombinationType: + editor = new KisKeyInputEditor(parent); + break; + + case KisShortcutConfiguration::MouseButtonType: + editor = new KisMouseInputEditor(parent); + break; + + case KisShortcutConfiguration::MouseWheelType: + editor = new KisWheelInputEditor(parent); + break; + + default: + break; + } + + return editor; +} + +void KisInputEditorDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + KisShortcutConfiguration *s = index.model()->data(index, Qt::EditRole).value<KisShortcutConfiguration *>(); + + switch (s->type()) { + case KisShortcutConfiguration::KeyCombinationType: { + KisKeyInputEditor *e = qobject_cast<KisKeyInputEditor *>(editor); + e->setKeys(s->keys()); + break; + } + + case KisShortcutConfiguration::MouseButtonType: { + KisMouseInputEditor *e = qobject_cast<KisMouseInputEditor *>(editor); + e->setKeys(s->keys()); + e->setButtons(s->buttons()); + break; + } + + case KisShortcutConfiguration::MouseWheelType: { + KisWheelInputEditor *e = qobject_cast<KisWheelInputEditor *>(editor); + e->setKeys(s->keys()); + e->setWheel(s->wheel()); + break; + } + + default: + break; + } +} + +void KisInputEditorDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const +{ + KisShortcutConfiguration *s = model->data(index, Qt::EditRole).value<KisShortcutConfiguration *>(); + + switch (s->type()) { + case KisShortcutConfiguration::KeyCombinationType: { + KisKeyInputEditor *e = qobject_cast<KisKeyInputEditor *>(editor); + s->setKeys(e->keys()); + break; + } + + case KisShortcutConfiguration::MouseButtonType: { + KisMouseInputEditor *e = qobject_cast<KisMouseInputEditor *>(editor); + s->setKeys(e->keys()); + s->setButtons(e->buttons()); + break; + } + + case KisShortcutConfiguration::MouseWheelType: { + KisWheelInputEditor *e = qobject_cast<KisWheelInputEditor *>(editor); + s->setKeys(e->keys()); + s->setWheel(e->wheel()); + break; + } + break; + + default: + break; + } + + model->setData(index, QVariant::fromValue(s), Qt::EditRole); +} + +void KisInputEditorDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const +{ + editor->setGeometry(option.rect); +} + +QSize KisInputEditorDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + return QStyledItemDelegate::sizeHint(option, index) + QSize(6, 6); +} diff --git a/krita/ui/input/config/kis_input_editor_delegate.h b/krita/ui/input/config/kis_input_editor_delegate.h new file mode 100644 index 0000000..fbc38a8 --- /dev/null +++ b/krita/ui/input/config/kis_input_editor_delegate.h @@ -0,0 +1,46 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISINPUTEDITORDELEGATE_H +#define KISINPUTEDITORDELEGATE_H + +#include <QStyledItemDelegate> + +/** + * \brief A delegate providing editors for the keys/buttons/etc. of KisShortcutConfiguration. + */ +class KisInputEditorDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + KisInputEditorDelegate(QObject *parent = 0); + ~KisInputEditorDelegate(); + + virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const; + virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; + virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; + virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const; + virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + +private: + class Private; + Private *const d; +}; + +#endif // KISINPUTEDITORDELEGATE_H diff --git a/krita/ui/input/config/kis_input_mode_delegate.cpp b/krita/ui/input/config/kis_input_mode_delegate.cpp new file mode 100644 index 0000000..2e161f1 --- /dev/null +++ b/krita/ui/input/config/kis_input_mode_delegate.cpp @@ -0,0 +1,80 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_input_mode_delegate.h" +#include "../kis_abstract_input_action.h" + +#include <KComboBox> +#include <KLocalizedString> + +class KisInputModeDelegate::Private +{ +public: + Private() { } + + KisAbstractInputAction *action; +}; + +KisInputModeDelegate::KisInputModeDelegate(QObject *parent) + : QStyledItemDelegate(parent), d(new Private) +{ +} + +KisInputModeDelegate::~KisInputModeDelegate() +{ + delete d; + +} + +QWidget *KisInputModeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const +{ + KComboBox *combo = new KComboBox(parent); + QStringList sorted = d->action->shortcutIndexes().keys(); + qSort(sorted); + combo->addItems(sorted); + return combo; +} + +void KisInputModeDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + KComboBox *combo = qobject_cast<KComboBox *>(editor); + Q_ASSERT(combo); + + int i = combo->findText(d->action->shortcutIndexes().key(index.data(Qt::EditRole).toUInt())); + combo->setCurrentIndex(i); +} + +void KisInputModeDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const +{ + KComboBox *combo = qobject_cast<KComboBox *>(editor); + Q_ASSERT(combo); + + int i = d->action->shortcutIndexes().value(combo->currentText()); + model->setData(index, i, Qt::EditRole); +} + +void KisInputModeDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const +{ + editor->setGeometry(option.rect); +} + +void KisInputModeDelegate::setAction(KisAbstractInputAction *action) +{ + d->action = action; +} diff --git a/krita/ui/input/config/kis_input_mode_delegate.h b/krita/ui/input/config/kis_input_mode_delegate.h new file mode 100644 index 0000000..c25908d --- /dev/null +++ b/krita/ui/input/config/kis_input_mode_delegate.h @@ -0,0 +1,48 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISINPUTMODEDELEGATE_H +#define KISINPUTMODEDELEGATE_H + +#include <QStyledItemDelegate> + +class KisAbstractInputAction; +/** + * \brief A delegate providing editors for the mode property of KisShortcutConfiguration. + */ +class KisInputModeDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + explicit KisInputModeDelegate(QObject *parent = 0); + ~KisInputModeDelegate(); + + virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const; + virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; + virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; + virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const; + + void setAction(KisAbstractInputAction *action); + +private: + class Private; + Private *const d; +}; + +#endif // KISINPUTMODEDELEGATE_H diff --git a/krita/ui/input/config/kis_input_profile_model.cpp b/krita/ui/input/config/kis_input_profile_model.cpp new file mode 100644 index 0000000..d7ea00f --- /dev/null +++ b/krita/ui/input/config/kis_input_profile_model.cpp @@ -0,0 +1,64 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_input_profile_model.h" + +#include "input/kis_input_profile_manager.h" + +KisInputProfileModel::KisInputProfileModel(QObject *parent) + : QStringListModel(parent) +{ + setStringList(KisInputProfileManager::instance()->profileNames()); + connect(KisInputProfileManager::instance(), SIGNAL(profilesChanged()), SLOT(profileNamesChanged())); +} + +KisInputProfileModel::~KisInputProfileModel() +{ + +} + +void KisInputProfileModel::profileNamesChanged() +{ + setStringList(KisInputProfileManager::instance()->profileNames()); +} + +bool KisInputProfileModel::setData(const QModelIndex &index, const QVariant &value, int /*role*/) +{ + QString oldName = profileName(index); + return KisInputProfileManager::instance()->renameProfile(oldName, value.toString()); +} + +QString KisInputProfileModel::profileName(const QModelIndex &index) +{ + return data(index, Qt::DisplayRole).toString(); +} + +QModelIndex KisInputProfileModel::find(const QString &name) +{ + for (int i = 0; i < rowCount(); ++i) { + QModelIndex ind = index(i, 0); + + if (profileName(ind) == name) { + return ind; + } + } + + return QModelIndex(); +} + diff --git a/krita/ui/input/config/kis_input_profile_model.h b/krita/ui/input/config/kis_input_profile_model.h new file mode 100644 index 0000000..58f208a --- /dev/null +++ b/krita/ui/input/config/kis_input_profile_model.h @@ -0,0 +1,44 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISINPUTPROFILEMODEL_H +#define KISINPUTPROFILEMODEL_H + +#include <QStringListModel> + +/** + * \brief A model providing a list of profiles available. + */ +class KisInputProfileModel : public QStringListModel +{ + Q_OBJECT +public: + KisInputProfileModel(QObject *parent = 0); + ~KisInputProfileModel(); + + virtual bool setData(const QModelIndex &index, const QVariant &value, int = Qt::EditRole); + + QString profileName(const QModelIndex &index); + QModelIndex find(const QString &name); + +private Q_SLOTS: + void profileNamesChanged(); +}; + +#endif // KISINPUTPROFILEMODEL_H diff --git a/krita/ui/input/config/kis_input_type_delegate.cpp b/krita/ui/input/config/kis_input_type_delegate.cpp new file mode 100644 index 0000000..15307e3 --- /dev/null +++ b/krita/ui/input/config/kis_input_type_delegate.cpp @@ -0,0 +1,75 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_input_type_delegate.h" + +#include <KComboBox> +#include <KLocalizedString> + +class KisInputTypeDelegate::Private +{ +public: + Private() { } +}; + +KisInputTypeDelegate::KisInputTypeDelegate(QObject *parent) + : QStyledItemDelegate(parent), d(new Private) +{ + +} + +KisInputTypeDelegate::~KisInputTypeDelegate() +{ + delete d; + +} + +QWidget *KisInputTypeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const +{ + KComboBox *combo = new KComboBox(parent); + combo->addItems(QStringList() + << i18n("Key Combination") + << i18n("Mouse Button") + << i18n("Mouse Wheel") + //<< i18n("Gesture") + ); + combo->setCurrentIndex(0); + + return combo; +} + +void KisInputTypeDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + KComboBox *combo = qobject_cast<KComboBox *>(editor); + Q_ASSERT(combo); + + combo->setCurrentIndex(index.data(Qt::EditRole).toUInt() - 1); +} + +void KisInputTypeDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const +{ + KComboBox *combo = qobject_cast<KComboBox *>(editor); + Q_ASSERT(combo); + model->setData(index, combo->currentIndex() + 1, Qt::EditRole); +} + +void KisInputTypeDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const +{ + editor->setGeometry(option.rect); +} diff --git a/krita/ui/input/config/kis_input_type_delegate.h b/krita/ui/input/config/kis_input_type_delegate.h new file mode 100644 index 0000000..d3594dd --- /dev/null +++ b/krita/ui/input/config/kis_input_type_delegate.h @@ -0,0 +1,45 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISINPUTTYPEDELEGATE_H +#define KISINPUTTYPEDELEGATE_H + +#include <QStyledItemDelegate> + +/** + * \brief A delegate providing editors for the type property of KisShortcutConfiguration. + */ +class KisInputTypeDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + explicit KisInputTypeDelegate(QObject *parent = 0); + ~KisInputTypeDelegate(); + + virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const; + virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; + virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; + virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const; + +private: + class Private; + Private *const d; +}; + +#endif // KISINPUTTYPEDELEGATE_H diff --git a/krita/ui/input/config/kis_key_input_editor.cpp b/krita/ui/input/config/kis_key_input_editor.cpp new file mode 100644 index 0000000..4179f94 --- /dev/null +++ b/krita/ui/input/config/kis_key_input_editor.cpp @@ -0,0 +1,77 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_key_input_editor.h" + +#include <QWidgetAction> +#include <QMenu> +#include <QTimer> + +#include "ui_kis_key_input_editor.h" + +class KisKeyInputEditor::Private +{ +public: + Private() { } + + Ui::KisKeyInputEditor *ui; +}; + +KisKeyInputEditor::KisKeyInputEditor(QWidget *parent) + : KPushButton(parent), d(new Private) +{ + QWidget *popup = new QWidget(); + + d->ui = new Ui::KisKeyInputEditor; + d->ui->setupUi(popup); + + QWidgetAction *action = new QWidgetAction(this); + action->setDefaultWidget(popup); + + QMenu *menu = new QMenu(this); + menu->addAction(action); + setMenu(menu); + + QTimer::singleShot(0, this, SLOT(showMenu())); + + connect(d->ui->keysButton, SIGNAL(dataChanged()), SLOT(updateLabel())); + connect(d->ui->clearKeysButton, SIGNAL(clicked(bool)), d->ui->keysButton, SLOT(clear())); +} + +KisKeyInputEditor::~KisKeyInputEditor() +{ + delete d->ui; + delete d; +} + +QList< Qt::Key > KisKeyInputEditor::keys() const +{ + return d->ui->keysButton->keys(); +} + +void KisKeyInputEditor::setKeys(const QList< Qt::Key > &newKeys) +{ + d->ui->keysButton->setKeys(newKeys); + updateLabel(); +} + +void KisKeyInputEditor::updateLabel() +{ + setText(KisShortcutConfiguration::keysToText(d->ui->keysButton->keys())); +} diff --git a/krita/ui/input/config/kis_key_input_editor.h b/krita/ui/input/config/kis_key_input_editor.h new file mode 100644 index 0000000..d37af9a --- /dev/null +++ b/krita/ui/input/config/kis_key_input_editor.h @@ -0,0 +1,54 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISKEYINPUTEDITOR_H +#define KISKEYINPUTEDITOR_H + +#include <KPushButton> + +namespace Ui +{ +class KisKeyInputEditor; +} + +/** + * \brief An editor widget for a list of keys. + */ +class KisKeyInputEditor : public KPushButton +{ + Q_OBJECT +public: + KisKeyInputEditor(QWidget *parent = 0); + ~KisKeyInputEditor(); + + QList<Qt::Key> keys() const; + void setKeys(const QList<Qt::Key> &newKeys); + + Qt::MouseButtons buttons() const; + void setButtons(Qt::MouseButtons newButtons); + +private Q_SLOTS: + void updateLabel(); + +private: + class Private; + Private *const d; +}; + +#endif // KISKEYINPUTEDITOR_H diff --git a/krita/ui/input/config/kis_key_input_editor.ui b/krita/ui/input/config/kis_key_input_editor.ui new file mode 100644 index 0000000..efee21b --- /dev/null +++ b/krita/ui/input/config/kis_key_input_editor.ui @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>KisKeyInputEditor</class> + <widget class="QWidget" name="KisKeyInputEditor"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>350</width> + <height>65</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0" colspan="3"> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Edit Key Combination</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="KPushButton" name="clearKeysButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="icon"> + <iconset theme="edit-clear-locationbar-rtl"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="keysLabel"> + <property name="styleSheet"> + <string notr="true">background: none;</string> + </property> + <property name="text"> + <string>Keys</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="KisInputButton" name="keysButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="icon"> + <iconset theme="configure"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>KPushButton</class> + <extends>QPushButton</extends> + <header>kpushbutton.h</header> + </customwidget> + <customwidget> + <class>KisInputButton</class> + <extends>QPushButton</extends> + <header>input/config/kis_input_button.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/krita/ui/input/config/kis_mouse_input_editor.cpp b/krita/ui/input/config/kis_mouse_input_editor.cpp new file mode 100644 index 0000000..9e6bdcb --- /dev/null +++ b/krita/ui/input/config/kis_mouse_input_editor.cpp @@ -0,0 +1,100 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_mouse_input_editor.h" + +#include <QWidgetAction> +#include <QMenu> +#include <QTimer> + +#include "ui_kis_mouse_input_editor.h" + +class KisMouseInputEditor::Private +{ +public: + Private() { } + + Ui::KisMouseInputEditor *ui; +}; + +KisMouseInputEditor::KisMouseInputEditor(QWidget *parent) + : KPushButton(parent), d(new Private) +{ + QWidget *popup = new QWidget(); + + d->ui = new Ui::KisMouseInputEditor; + d->ui->setupUi(popup); + d->ui->mouseButton->setType(KisInputButton::MouseType); + + QWidgetAction *action = new QWidgetAction(this); + action->setDefaultWidget(popup); + + QMenu *menu = new QMenu(this); + menu->addAction(action); + setMenu(menu); + + QTimer::singleShot(0, this, SLOT(showMenu())); + + connect(d->ui->mouseButton, SIGNAL(dataChanged()), SLOT(updateLabel())); + connect(d->ui->modifiersButton, SIGNAL(dataChanged()), SLOT(updateLabel())); + connect(d->ui->clearMouseButton, SIGNAL(clicked(bool)), d->ui->mouseButton, SLOT(clear())); + connect(d->ui->clearModifiersButton, SIGNAL(clicked(bool)), d->ui->modifiersButton, SLOT(clear())); +} + +KisMouseInputEditor::~KisMouseInputEditor() +{ + delete d->ui; + delete d; +} + +QList< Qt::Key > KisMouseInputEditor::keys() const +{ + return d->ui->modifiersButton->keys(); +} + +void KisMouseInputEditor::setKeys(const QList< Qt::Key > &newKeys) +{ + d->ui->modifiersButton->setKeys(newKeys); + updateLabel(); +} + +Qt::MouseButtons KisMouseInputEditor::buttons() const +{ + return d->ui->mouseButton->buttons(); +} + +void KisMouseInputEditor::setButtons(Qt::MouseButtons newButtons) +{ + d->ui->mouseButton->setButtons(newButtons); + updateLabel(); +} + +void KisMouseInputEditor::updateLabel() +{ + QString text; + + if (d->ui->modifiersButton->keys().size() > 0) { + text.append(KisShortcutConfiguration::keysToText(d->ui->modifiersButton->keys())); + text.append(" + "); + } + + text.append(KisShortcutConfiguration::buttonsToText(d->ui->mouseButton->buttons())); + + setText(text); +} diff --git a/krita/ui/input/config/kis_mouse_input_editor.h b/krita/ui/input/config/kis_mouse_input_editor.h new file mode 100644 index 0000000..351ca2e --- /dev/null +++ b/krita/ui/input/config/kis_mouse_input_editor.h @@ -0,0 +1,54 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISMOUSEINPUTEDITOR_H +#define KISMOUSEINPUTEDITOR_H + +#include <KPushButton> + +namespace Ui +{ +class KisMouseInputEditor; +} + +/** + * \brief An editor widget for mouse buttons with modifiers. + */ +class KisMouseInputEditor : public KPushButton +{ + Q_OBJECT +public: + KisMouseInputEditor(QWidget *parent = 0); + ~KisMouseInputEditor(); + + QList<Qt::Key> keys() const; + void setKeys(const QList<Qt::Key> &newKeys); + + Qt::MouseButtons buttons() const; + void setButtons(Qt::MouseButtons newButtons); + +private Q_SLOTS: + void updateLabel(); + +private: + class Private; + Private *const d; +}; + +#endif // KISMOUSEINPUTEDITOR_H diff --git a/krita/ui/input/config/kis_mouse_input_editor.ui b/krita/ui/input/config/kis_mouse_input_editor.ui new file mode 100644 index 0000000..3f1b20b --- /dev/null +++ b/krita/ui/input/config/kis_mouse_input_editor.ui @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>KisMouseInputEditor</class> + <widget class="QWidget" name="KisMouseInputEditor"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>350</width> + <height>100</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="1"> + <widget class="KisInputButton" name="mouseButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="icon"> + <iconset theme="configure"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="KPushButton" name="clearMouseButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="icon"> + <iconset theme="edit-clear-locationbar-rtl"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="KisInputButton" name="modifiersButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="icon"> + <iconset theme="configure"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="modifiersLabel"> + <property name="styleSheet"> + <string notr="true">background: none;</string> + </property> + <property name="text"> + <string>Modifiers</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="mouseLabel"> + <property name="styleSheet"> + <string notr="true">background: none;</string> + </property> + <property name="text"> + <string>Mouse Button</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="KPushButton" name="clearModifiersButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="icon"> + <iconset theme="edit-clear-locationbar-rtl"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + <item row="0" column="0" colspan="4"> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Edit Mouse Input</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>KPushButton</class> + <extends>QPushButton</extends> + <header>kpushbutton.h</header> + </customwidget> + <customwidget> + <class>KisInputButton</class> + <extends>QPushButton</extends> + <header>input/config/kis_input_button.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/krita/ui/input/config/kis_wheel_input_editor.cpp b/krita/ui/input/config/kis_wheel_input_editor.cpp new file mode 100644 index 0000000..f752fb6 --- /dev/null +++ b/krita/ui/input/config/kis_wheel_input_editor.cpp @@ -0,0 +1,99 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_wheel_input_editor.h" + +#include "ui_kis_wheel_input_editor.h" +#include <QMenu> +#include <QWidgetAction> +#include <QTimer> + +class KisWheelInputEditor::Private +{ +public: + Private() { } + + Ui::KisWheelInputEditor *ui; +}; + +KisWheelInputEditor::KisWheelInputEditor(QWidget *parent) + : KPushButton(parent), d(new Private) +{ + QWidget *popup = new QWidget(); + + d->ui = new Ui::KisWheelInputEditor; + d->ui->setupUi(popup); + d->ui->wheelButton->setType(KisInputButton::WheelType); + + QWidgetAction *action = new QWidgetAction(this); + action->setDefaultWidget(popup); + + QMenu *menu = new QMenu(this); + menu->addAction(action); + setMenu(menu); + + QTimer::singleShot(0, this, SLOT(showMenu())); + + connect(d->ui->wheelButton, SIGNAL(dataChanged()), SLOT(updateLabel())); + connect(d->ui->modifiersButton, SIGNAL(dataChanged()), SLOT(updateLabel())); + connect(d->ui->clearWheelButton, SIGNAL(clicked(bool)), d->ui->wheelButton, SLOT(clear())); + connect(d->ui->clearModifiersButton, SIGNAL(clicked(bool)), d->ui->modifiersButton, SLOT(clear())); +} + +KisWheelInputEditor::~KisWheelInputEditor() +{ + delete d->ui; + delete d; +} + +QList< Qt::Key > KisWheelInputEditor::keys() const +{ + return d->ui->modifiersButton->keys(); +} + +void KisWheelInputEditor::setKeys(const QList< Qt::Key > &newKeys) +{ + d->ui->modifiersButton->setKeys(newKeys); + updateLabel(); +} + +KisShortcutConfiguration::MouseWheelMovement KisWheelInputEditor::wheel() const +{ + return d->ui->wheelButton->wheel(); +} + +void KisWheelInputEditor::setWheel(KisShortcutConfiguration::MouseWheelMovement newWheel) +{ + d->ui->wheelButton->setWheel(newWheel); + updateLabel(); +} + +void KisWheelInputEditor::updateLabel() +{ + QString text; + + if (d->ui->modifiersButton->keys().size() > 0) { + text.append(KisShortcutConfiguration::keysToText(d->ui->modifiersButton->keys())); + text.append(" + "); + } + + text.append(KisShortcutConfiguration::wheelToText(d->ui->wheelButton->wheel())); + + setText(text); +} diff --git a/krita/ui/input/config/kis_wheel_input_editor.h b/krita/ui/input/config/kis_wheel_input_editor.h new file mode 100644 index 0000000..7425e57 --- /dev/null +++ b/krita/ui/input/config/kis_wheel_input_editor.h @@ -0,0 +1,56 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISWHEELINPUTEDITOR_H +#define KISWHEELINPUTEDITOR_H + +#include <KPushButton> + +#include "input/kis_shortcut_configuration.h" + +namespace Ui +{ +class KisWheelInputEditor; +} + +/** + * \brief An editor widget for mouse wheel input with modifiers. + */ +class KisWheelInputEditor : public KPushButton +{ + Q_OBJECT +public: + KisWheelInputEditor(QWidget *parent = 0); + ~KisWheelInputEditor(); + + QList<Qt::Key> keys() const; + void setKeys(const QList<Qt::Key> &newKeys); + + KisShortcutConfiguration::MouseWheelMovement wheel() const; + void setWheel(KisShortcutConfiguration::MouseWheelMovement newWheel); + +private Q_SLOTS: + void updateLabel(); + +private: + class Private; + Private *const d; +}; + +#endif // KISWHEELINPUTEDITOR_H diff --git a/krita/ui/input/config/kis_wheel_input_editor.ui b/krita/ui/input/config/kis_wheel_input_editor.ui new file mode 100644 index 0000000..5a813fc --- /dev/null +++ b/krita/ui/input/config/kis_wheel_input_editor.ui @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>KisWheelInputEditor</class> + <widget class="QWidget" name="KisWheelInputEditor"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>350</width> + <height>100</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="2" column="1"> + <widget class="KisInputButton" name="modifiersButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="icon"> + <iconset theme="configure"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="wheelLabel"> + <property name="styleSheet"> + <string notr="true">background: none;</string> + </property> + <property name="text"> + <string>Mouse Wheel</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="0" colspan="3"> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Edit Mouse Wheel Input</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="KisInputButton" name="wheelButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="icon"> + <iconset theme="configure"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="KPushButton" name="clearWheelButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="icon"> + <iconset theme="edit-clear-locationbar-rtl"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="modifiersLabel"> + <property name="styleSheet"> + <string notr="true">background: none;</string> + </property> + <property name="text"> + <string>Modifiers</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="KPushButton" name="clearModifiersButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="icon"> + <iconset theme="edit-clear-locationbar-rtl"> + <normaloff/> + </iconset> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>KPushButton</class> + <extends>QPushButton</extends> + <header>kpushbutton.h</header> + </customwidget> + <customwidget> + <class>KisInputButton</class> + <extends>QPushButton</extends> + <header>input/config/kis_input_button.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/krita/ui/input/kis_abstract_input_action.cpp b/krita/ui/input/kis_abstract_input_action.cpp index 093f872..ebb63ef 100644 --- a/krita/ui/input/kis_abstract_input_action.cpp +++ b/krita/ui/input/kis_abstract_input_action.cpp @@ -25,18 +25,19 @@ class KisAbstractInputAction::Private { public: - KisInputManager* inputManager; - QString name; QString description; QHash<QString, int> indexes; QPointF lastMousePosition; + + static KisInputManager* inputManager; }; -KisAbstractInputAction::KisAbstractInputAction(KisInputManager* manager) : d(new Private) +KisInputManager *KisAbstractInputAction::Private::inputManager = 0; + +KisAbstractInputAction::KisAbstractInputAction() : d(new Private) { - d->inputManager = manager; d->indexes.insert(i18n("Activate"), 0); } @@ -92,7 +93,7 @@ bool KisAbstractInputAction::supportsHiResInputEvents() const KisInputManager* KisAbstractInputAction::inputManager() const { - return d->inputManager; + return Private::inputManager; } QString KisAbstractInputAction::name() const @@ -124,3 +125,8 @@ void KisAbstractInputAction::setShortcutIndexes(const QHash< QString, int >& ind { d->indexes = indexes; } + +void KisAbstractInputAction::setInputManager(KisInputManager *manager) +{ + Private::inputManager = manager; +} diff --git a/krita/ui/input/kis_abstract_input_action.h b/krita/ui/input/kis_abstract_input_action.h index 50afffa..ae5bb46 100644 --- a/krita/ui/input/kis_abstract_input_action.h +++ b/krita/ui/input/kis_abstract_input_action.h @@ -59,7 +59,7 @@ public: * * \param manager The InputManager this action belongs to. */ - explicit KisAbstractInputAction(KisInputManager *manager); + explicit KisAbstractInputAction(); /** * Destructor. */ @@ -160,6 +160,9 @@ protected: virtual void mouseMoved(const QPointF &lastPos, const QPointF &pos); private: + friend class KisInputManager; + static void setInputManager(KisInputManager *manager); + class Private; Private * const d; }; diff --git a/krita/ui/input/kis_alternate_invocation_action.cpp b/krita/ui/input/kis_alternate_invocation_action.cpp index c518215..e05799f 100644 --- a/krita/ui/input/kis_alternate_invocation_action.cpp +++ b/krita/ui/input/kis_alternate_invocation_action.cpp @@ -26,11 +26,10 @@ #include "kis_input_manager.h" -KisAlternateInvocationAction::KisAlternateInvocationAction(KisInputManager *manager) - : KisAbstractInputAction(manager) +KisAlternateInvocationAction::KisAlternateInvocationAction() { setName(i18n("Alternate Invocation")); - setDescription(i18n("Alternate Invocation performs an alternate action with the current tool. For example, using the brush tool it picks a color from the canvas.")); + setDescription(i18n("The <i>Alternate Invocation</i> action performs an alternate action with the current tool. For example, using the brush tool it picks a color from the canvas.")); QHash<QString, int> shortcuts; shortcuts.insert(i18n("Toggle Primary Mode"), PrimaryAlternateToggleShortcut); shortcuts.insert(i18n("Toggle Secondary Mode"), SecondaryAlternateToggleShortcut); diff --git a/krita/ui/input/kis_alternate_invocation_action.h b/krita/ui/input/kis_alternate_invocation_action.h index 5255ea4..bdfc699 100644 --- a/krita/ui/input/kis_alternate_invocation_action.h +++ b/krita/ui/input/kis_alternate_invocation_action.h @@ -39,7 +39,7 @@ public: SecondaryAlternateToggleShortcut, ///< Toggle Secondary mode. }; - explicit KisAlternateInvocationAction(KisInputManager *manager); + explicit KisAlternateInvocationAction(); virtual ~KisAlternateInvocationAction(); void begin(int shortcut, QEvent *event); diff --git a/krita/ui/input/kis_change_primary_setting_action.cpp b/krita/ui/input/kis_change_primary_setting_action.cpp index cd7ecd0..738b631 100644 --- a/krita/ui/input/kis_change_primary_setting_action.cpp +++ b/krita/ui/input/kis_change_primary_setting_action.cpp @@ -23,11 +23,10 @@ #include "kis_input_manager.h" #include <KoToolProxy.h> -KisChangePrimarySettingAction::KisChangePrimarySettingAction(KisInputManager* manager) - : KisAbstractInputAction(manager) +KisChangePrimarySettingAction::KisChangePrimarySettingAction() { - setName(i18n("Change Tool Primary Setting")); - setDescription(i18n("Changes a tool's \"Primary Setting\", for example the brush size for the brush tool.")); + setName(i18n("Change Primary Setting")); + setDescription(i18n("The <i>Change Primary Setting</i> action changes a tool's \"Primary Setting\", for example the brush size for the brush tool.")); } KisChangePrimarySettingAction::~KisChangePrimarySettingAction() diff --git a/krita/ui/input/kis_change_primary_setting_action.h b/krita/ui/input/kis_change_primary_setting_action.h index 0efc167..3a1097d 100644 --- a/krita/ui/input/kis_change_primary_setting_action.h +++ b/krita/ui/input/kis_change_primary_setting_action.h @@ -30,7 +30,7 @@ class KisChangePrimarySettingAction : public KisAbstractInputAction { public: - explicit KisChangePrimarySettingAction(KisInputManager* manager); + explicit KisChangePrimarySettingAction(); virtual ~KisChangePrimarySettingAction(); void begin(int shortcut, QEvent *event); diff --git a/krita/ui/input/kis_input_manager.cpp b/krita/ui/input/kis_input_manager.cpp index 667fdcf..6869b54 100644 --- a/krita/ui/input/kis_input_manager.cpp +++ b/krita/ui/input/kis_input_manager.cpp @@ -47,6 +47,10 @@ #include "kis_stroke_shortcut.h" #include "kis_single_action_shortcut.h" +#include "kis_input_profile.h" +#include "kis_input_profile_manager.h" +#include "kis_shortcut_configuration.h" + class KisInputManager::Private { public: @@ -65,15 +69,10 @@ public: bool trySetMirrorMode(const QPointF &mousePosition); void saveTabletEvent(const QTabletEvent *event); void resetSavedTabletEvent(QEvent::Type type); - void addStrokeShortcut(KisAbstractInputAction* action, int index, - const QList<Qt::Key> &modifiers, - const QList<Qt::MouseButton> &buttons); + void addStrokeShortcut(KisAbstractInputAction* action, int index, const QList< Qt::Key >& modifiers, Qt::MouseButtons buttons); void addKeyShortcut(KisAbstractInputAction* action, int index, - const QList<Qt::Key> &modifiers, - Qt::Key key); - void addWheelShortcut(KisAbstractInputAction* action, int index, - const QList<Qt::Key> &modifiers, - KisSingleActionShortcut::WheelAction wheelAction); + const QList<Qt::Key> &modifiers); + void addWheelShortcut(KisAbstractInputAction* action, int index, const QList< Qt::Key >& modifiers, KisShortcutConfiguration::MouseWheelMovement wheelAction); bool processUnhandledEvent(QEvent *event); Qt::Key workaroundShiftAltMetaHell(const QKeyEvent *keyEvent); void setupActions(); @@ -117,108 +116,85 @@ static inline QList<Qt::MouseButton> BUTTONS(Qt::MouseButton button1, Qt::MouseB void KisInputManager::Private::addStrokeShortcut(KisAbstractInputAction* action, int index, const QList<Qt::Key> &modifiers, - const QList<Qt::MouseButton> &buttons) + Qt::MouseButtons buttons) { KisStrokeShortcut *strokeShortcut = new KisStrokeShortcut(action, index); - strokeShortcut->setButtons(modifiers, buttons); + + QList<Qt::MouseButton> buttonList; + if(buttons & Qt::LeftButton) { + buttonList << Qt::LeftButton; + } + if(buttons & Qt::RightButton) { + buttonList << Qt::RightButton; + } + if(buttons & Qt::MidButton) { + buttonList << Qt::MidButton; + } + if(buttons & Qt::XButton1) { + buttonList << Qt::XButton1; + } + if(buttons & Qt::XButton2) { + buttonList << Qt::XButton2; + } + + strokeShortcut->setButtons(modifiers, buttonList); matcher.addShortcut(strokeShortcut); } void KisInputManager::Private::addKeyShortcut(KisAbstractInputAction* action, int index, - const QList<Qt::Key> &modifiers, - Qt::Key key) + const QList<Qt::Key> &keys) { KisSingleActionShortcut *keyShortcut = new KisSingleActionShortcut(action, index); - keyShortcut->setKey(modifiers, key); + + QList<Qt::Key> modifiers = keys.mid(1); + keyShortcut->setKey(modifiers, keys.at(0)); matcher.addShortcut(keyShortcut); } void KisInputManager::Private::addWheelShortcut(KisAbstractInputAction* action, int index, const QList<Qt::Key> &modifiers, - KisSingleActionShortcut::WheelAction wheelAction) + KisShortcutConfiguration::MouseWheelMovement wheelAction) { KisSingleActionShortcut *keyShortcut = new KisSingleActionShortcut(action, index); - keyShortcut->setWheel(modifiers, wheelAction); + + KisSingleActionShortcut::WheelAction a; + switch(wheelAction) { + case KisShortcutConfiguration::WheelUp: + a = KisSingleActionShortcut::WheelUp; + break; + case KisShortcutConfiguration::WheelDown: + a = KisSingleActionShortcut::WheelDown; + break; + case KisShortcutConfiguration::WheelLeft: + a = KisSingleActionShortcut::WheelLeft; + break; + case KisShortcutConfiguration::WheelRight: + a = KisSingleActionShortcut::WheelRight; + break; + default: + return; + } + + keyShortcut->setWheel(modifiers, a); matcher.addShortcut(keyShortcut); } void KisInputManager::Private::setupActions() { -#if QT_VERSION >= 0x040700 - Qt::MouseButton middleButton = Qt::MiddleButton; -#else - Qt::MouseButton middleButton = Qt::MidButton; -#endif - - //Create all the actions. - KisAbstractInputAction* action = new KisToolInvocationAction(q); - matcher.addAction(action); - addStrokeShortcut(action, KisToolInvocationAction::ActivateShortcut, KEYS(), BUTTONS(Qt::LeftButton)); - addKeyShortcut(action, KisToolInvocationAction::ConfirmShortcut, KEYS(), Qt::Key_Return); - addKeyShortcut(action, KisToolInvocationAction::ConfirmShortcut, KEYS(), Qt::Key_Enter); - addKeyShortcut(action, KisToolInvocationAction::CancelShortcut, KEYS(), Qt::Key_Escape); - defaultInputAction = action; - - action = new KisAlternateInvocationAction(q); - matcher.addAction(action); - addStrokeShortcut(action, KisAlternateInvocationAction::PrimaryAlternateToggleShortcut, KEYS(Qt::Key_Control), BUTTONS(Qt::LeftButton)); - addStrokeShortcut(action, KisAlternateInvocationAction::SecondaryAlternateToggleShortcut, KEYS(Qt::Key_Control, Qt::Key_Alt), BUTTONS(Qt::LeftButton)); - - action = new KisChangePrimarySettingAction(q); - matcher.addAction(action); - addStrokeShortcut(action, 0, KEYS(Qt::Key_Shift), BUTTONS(Qt::LeftButton)); - - - action = new KisPanAction(q); - matcher.addAction(action); - - addStrokeShortcut(action, KisPanAction::PanToggleShortcut, KEYS(Qt::Key_Space), BUTTONS(Qt::LeftButton)); - addStrokeShortcut(action, KisPanAction::PanToggleShortcut, KEYS(), BUTTONS(middleButton)); - - addKeyShortcut(action, KisPanAction::PanLeftShortcut, KEYS(), Qt::Key_Left); - addKeyShortcut(action, KisPanAction::PanRightShortcut, KEYS(), Qt::Key_Right); - addKeyShortcut(action, KisPanAction::PanUpShortcut, KEYS(), Qt::Key_Up); - addKeyShortcut(action, KisPanAction::PanDownShortcut, KEYS(), Qt::Key_Down); - - - action = new KisRotateCanvasAction(q); - matcher.addAction(action); - - addStrokeShortcut(action, KisRotateCanvasAction::RotateToggleShortcut, KEYS(Qt::Key_Shift, Qt::Key_Space), BUTTONS(Qt::LeftButton)); - addStrokeShortcut(action, KisRotateCanvasAction::DiscreteRotateToggleShortcut, KEYS(Qt::Key_Shift, Qt::Key_Alt, Qt::Key_Space), BUTTONS(Qt::LeftButton)); - addStrokeShortcut(action, KisRotateCanvasAction::RotateToggleShortcut, KEYS(Qt::Key_Shift), BUTTONS(middleButton)); - - addKeyShortcut(action, KisRotateCanvasAction::RotateLeftShortcut, KEYS(), Qt::Key_4); - addKeyShortcut(action, KisRotateCanvasAction::RotateResetShortcut, KEYS(), Qt::Key_5); - addKeyShortcut(action, KisRotateCanvasAction::RotateRightShortcut, KEYS(), Qt::Key_6); - - - action = new KisZoomAction(q); - matcher.addAction(action); - - addStrokeShortcut(action, KisZoomAction::ZoomToggleShortcut, KEYS(Qt::Key_Control), BUTTONS(middleButton)); - - addStrokeShortcut(action, KisZoomAction::ZoomToggleShortcut, KEYS(Qt::Key_Control, Qt::Key_Space), BUTTONS(Qt::LeftButton)); - addStrokeShortcut(action, KisZoomAction::DiscreteZoomToggleShortcut, KEYS(Qt::Key_Control, Qt::Key_Alt, Qt::Key_Space), BUTTONS(Qt::LeftButton)); - - addWheelShortcut(action, KisZoomAction::ZoomInShortcut, KEYS(), KisSingleActionShortcut::WheelUp); - addWheelShortcut(action, KisZoomAction::ZoomOutShortcut, KEYS(), KisSingleActionShortcut::WheelDown); - - addKeyShortcut(action, KisZoomAction::ZoomInShortcut, KEYS(), Qt::Key_Plus); - addKeyShortcut(action, KisZoomAction::ZoomOutShortcut, KEYS(), Qt::Key_Minus); - - addKeyShortcut(action, KisZoomAction::ZoomResetShortcut, KEYS(), Qt::Key_1); - addKeyShortcut(action, KisZoomAction::ZoomToPageShortcut, KEYS(), Qt::Key_2); - addKeyShortcut(action, KisZoomAction::ZoomToWidthShortcut, KEYS(), Qt::Key_3); - - action = new KisShowPaletteAction(q); - matcher.addAction(action); + QList<KisAbstractInputAction*> actions = KisInputProfileManager::instance()->actions(); + foreach(KisAbstractInputAction *action, actions) { + if(dynamic_cast<KisToolInvocationAction*>(action)) { + defaultInputAction = action; + } + } - addStrokeShortcut(action, 0, KEYS(), BUTTONS(Qt::RightButton)); - addKeyShortcut(action, 0, KEYS(), Qt::Key_F); + connect(KisInputProfileManager::instance(), SIGNAL(currentProfileChanged()), q, SLOT(profileChanged())); + if(KisInputProfileManager::instance()->currentProfile()) { + q->profileChanged(); + } } bool KisInputManager::Private::processUnhandledEvent(QEvent *event) @@ -452,9 +428,24 @@ bool KisInputManager::eventFilter(QObject* object, QEvent* event) } case QEvent::Wheel: { QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event); - KisSingleActionShortcut::WheelAction action = - wheelEvent->delta() > 0 ? - KisSingleActionShortcut::WheelUp : KisSingleActionShortcut::WheelDown; + KisSingleActionShortcut::WheelAction action; + + if(wheelEvent->orientation() == Qt::Horizontal) { + if(wheelEvent->delta() < 0) { + action = KisSingleActionShortcut::WheelRight; + } + else { + action = KisSingleActionShortcut::WheelLeft; + } + } + else { + if(wheelEvent->delta() > 0) { + action = KisSingleActionShortcut::WheelUp; + } + else { + action = KisSingleActionShortcut::WheelDown; + } + } retval = d->matcher.wheelEvent(action, wheelEvent); break; @@ -466,6 +457,8 @@ bool KisInputManager::eventFilter(QObject* object, QEvent* event) case QEvent::FocusIn: //Clear all state so we don't have half-matched shortcuts dangling around. d->matcher.reset(); + //Make sure the input actions know we are active. + KisAbstractInputAction::setInputManager(this); break; case QEvent::TabletPress: case QEvent::TabletMove: @@ -535,3 +528,25 @@ QPointF KisInputManager::widgetToPixel(const QPointF& position) return d->canvas->coordinatesConverter()->widgetToDocument(pixel); } +void KisInputManager::profileChanged() +{ + d->matcher.reset(); + d->matcher.clearShortcuts(); + + QList<KisShortcutConfiguration*> shortcuts = KisInputProfileManager::instance()->currentProfile()->allShortcuts(); + foreach(KisShortcutConfiguration *shortcut, shortcuts) { + switch(shortcut->type()) { + case KisShortcutConfiguration::KeyCombinationType: + d->addKeyShortcut(shortcut->action(), shortcut->mode(), shortcut->keys()); + break; + case KisShortcutConfiguration::MouseButtonType: + d->addStrokeShortcut(shortcut->action(), shortcut->mode(), shortcut->keys(), shortcut->buttons()); + break; + case KisShortcutConfiguration::MouseWheelType: + d->addWheelShortcut(shortcut->action(), shortcut->mode(), shortcut->keys(), shortcut->wheel()); + break; + default: + break; + } + } +} diff --git a/krita/ui/input/kis_input_manager.h b/krita/ui/input/kis_input_manager.h index 1334e7f..9ca1e0a 100644 --- a/krita/ui/input/kis_input_manager.h +++ b/krita/ui/input/kis_input_manager.h @@ -90,6 +90,7 @@ public: private Q_SLOTS: void setMirrorAxis(); void slotToolChanged(); + void profileChanged(); private: class Private; diff --git a/krita/ui/input/kis_input_profile.cpp b/krita/ui/input/kis_input_profile.cpp new file mode 100644 index 0000000..0377441 --- /dev/null +++ b/krita/ui/input/kis_input_profile.cpp @@ -0,0 +1,86 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_input_profile.h" + +#include <QStringList> +#include <QMultiHash> + +#include "kis_abstract_input_action.h" +#include "kis_shortcut_configuration.h" + +class KisInputProfile::Private +{ +public: + Private() { } + + QString name; + QMultiHash<KisAbstractInputAction *, KisShortcutConfiguration *> shortcuts; +}; + +KisInputProfile::KisInputProfile(QObject *parent) + : QObject(parent), d(new Private()) +{ + +} + +KisInputProfile::~KisInputProfile() +{ + +} + +QString KisInputProfile::name() const +{ + return d->name; +} +void KisInputProfile::setName(const QString &name) +{ + if (d->name != name) { + d->name = name; + emit nameChanged(); + } +} + +QList< KisShortcutConfiguration * > KisInputProfile::allShortcuts() const +{ + return d->shortcuts.values(); +} + +QList< KisShortcutConfiguration * > KisInputProfile::shortcutsForAction(KisAbstractInputAction *action) const +{ + if (d->shortcuts.contains(action)) { + return d->shortcuts.values(action); + } + + return QList<KisShortcutConfiguration *>(); +} + +void KisInputProfile::addShortcut(KisShortcutConfiguration *shortcut) +{ + Q_ASSERT(shortcut); + Q_ASSERT(shortcut->action()); + d->shortcuts.insert(shortcut->action(), shortcut); +} + +void KisInputProfile::removeShortcut(KisShortcutConfiguration *shortcut) +{ + Q_ASSERT(shortcut); + Q_ASSERT(shortcut->action()); + d->shortcuts.remove(shortcut->action(), shortcut); +} diff --git a/krita/ui/input/kis_input_profile.h b/krita/ui/input/kis_input_profile.h new file mode 100644 index 0000000..675e709 --- /dev/null +++ b/krita/ui/input/kis_input_profile.h @@ -0,0 +1,95 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISINPUTPROFILE_H +#define KISINPUTPROFILE_H + +#include <QObject> +#include <QMetaType> + +class KisAbstractInputAction; +class KisShortcutConfiguration; +/** + * \brief A container class for sets of shortcuts associated with an action. + * + * + */ +class KisInputProfile : public QObject +{ + Q_OBJECT + +public: + /** + * Constructor. + */ + KisInputProfile(QObject *parent = 0); + /** + * Destructor. + */ + virtual ~KisInputProfile(); + + /** + * \return The name of the profile. + */ + QString name() const; + + /** + * \return A list of all shortcuts available. + */ + QList<KisShortcutConfiguration *> allShortcuts() const; + /** + * \return A list of shortcuts associated with the given action. + * + * \param action The action for which to list the shortcuts. + */ + QList<KisShortcutConfiguration *> shortcutsForAction(KisAbstractInputAction *action) const; + + /** + * Add a shortcut to this profile. + * + * \param shortcut The shortcut to add. + */ + void addShortcut(KisShortcutConfiguration *shortcut); + /** + * Remove a shortcut from this profile. + * + * \param shortcut The shortcut to remove. + */ + void removeShortcut(KisShortcutConfiguration *shortcut); + +public Q_SLOTS: + /** + * Set the name of this profile. + * + * \param name The name to set. + */ + void setName(const QString &name); + +Q_SIGNALS: + /** + * Emitted when the name of this profile changes. + */ + void nameChanged(); + +private: + class Private; + Private *const d; +}; + +#endif // KISINPUTPROFILE_H diff --git a/krita/ui/input/kis_input_profile_manager.cpp b/krita/ui/input/kis_input_profile_manager.cpp new file mode 100644 index 0000000..7b77691 --- /dev/null +++ b/krita/ui/input/kis_input_profile_manager.cpp @@ -0,0 +1,287 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_input_profile_manager.h" +#include "kis_input_profile.h" + +#include <QMap> +#include <QStringList> +#include <QDir> + +#include <KGlobal> +#include <KStandardDirs> +#include <KConfig> +#include <KConfigGroup> + +#include "kis_config.h" +#include "kis_alternate_invocation_action.h" +#include "kis_change_primary_setting_action.h" +#include "kis_pan_action.h" +#include "kis_rotate_canvas_action.h" +#include "kis_show_palette_action.h" +#include "kis_tool_invocation_action.h" +#include "kis_zoom_action.h" +#include "kis_shortcut_configuration.h" + +class KisInputProfileManager::Private +{ +public: + Private() : currentProfile(0) { } + + void createActions(); + QString profileFileName(const QString &profileName); + + KisInputProfile *currentProfile; + + QMap<QString, KisInputProfile *> profiles; + + QList<KisAbstractInputAction *> actions; +}; + +K_GLOBAL_STATIC(KisInputProfileManager, inputProfileManager) + +KisInputProfileManager *KisInputProfileManager::instance() +{ + return inputProfileManager; +} + +QList< KisInputProfile * > KisInputProfileManager::profiles() const +{ + return d->profiles.values(); +} + +QStringList KisInputProfileManager::profileNames() const +{ + return d->profiles.keys(); +} + +KisInputProfile *KisInputProfileManager::profile(const QString &name) const +{ + if (d->profiles.contains(name)) { + return d->profiles.value(name); + } + + return 0; +} + +KisInputProfile *KisInputProfileManager::currentProfile() const +{ + return d->currentProfile; +} + +void KisInputProfileManager::setCurrentProfile(KisInputProfile *profile) +{ + if (profile && profile != d->currentProfile) { + d->currentProfile = profile; + emit currentProfileChanged(); + } +} + +KisInputProfile *KisInputProfileManager::addProfile(const QString &name) +{ + if (d->profiles.contains(name)) { + return d->profiles.value(name); + } + + KisInputProfile *profile = new KisInputProfile(this); + profile->setName(name); + d->profiles.insert(name, profile); + + emit profilesChanged(); + + return profile; +} + +void KisInputProfileManager::removeProfile(const QString &name) +{ + if (d->profiles.contains(name)) { + QString currentProfileName = d->currentProfile->name(); + + delete d->profiles.value(name); + d->profiles.remove(name); + + //Delete the settings file for the removed profile, if it exists + QDir userDir(KGlobal::dirs()->saveLocation("appdata", "input/")); + + if (userDir.exists(d->profileFileName(name))) { + userDir.remove(d->profileFileName(name)); + } + + if (currentProfileName == name) { + d->currentProfile = d->profiles.begin().value(); + emit currentProfileChanged(); + } + + emit profilesChanged(); + } +} + +bool KisInputProfileManager::renameProfile(const QString &oldName, const QString &newName) +{ + if (!d->profiles.contains(oldName)) { + return false; + } + + KisInputProfile *profile = d->profiles.value(oldName); + d->profiles.remove(oldName); + profile->setName(newName); + d->profiles.insert(newName, profile); + + emit profilesChanged(); + + return true; +} + +void KisInputProfileManager::duplicateProfile(const QString &name, const QString &newName) +{ + if (!d->profiles.contains(name) || d->profiles.contains(newName)) { + return; + } + + KisInputProfile *newProfile = new KisInputProfile(this); + newProfile->setName(newName); + d->profiles.insert(newName, newProfile); + + KisInputProfile *profile = d->profiles.value(name); + QList<KisShortcutConfiguration *> shortcuts = profile->allShortcuts(); + Q_FOREACH(KisShortcutConfiguration * shortcut, shortcuts) { + newProfile->addShortcut(new KisShortcutConfiguration(*shortcut)); + } + + emit profilesChanged(); +} + +QList< KisAbstractInputAction * > KisInputProfileManager::actions() +{ + return d->actions; +} + +void KisInputProfileManager::loadProfiles() +{ + //Remove any profiles that already exist + d->currentProfile = 0; + qDeleteAll(d->profiles); + d->profiles.clear(); + + //Look up all profiles (this includes those installed to $prefix as well as the user's local data dir) + QStringList profiles = KGlobal::dirs()->findAllResources("appdata", "input/*", KStandardDirs::NoDuplicates | KStandardDirs::Recursive); + Q_FOREACH(const QString & p, profiles) { + //Open the file + KConfig config(p, KConfig::SimpleConfig); + + if (!config.hasGroup("General") || !config.group("General").hasKey("name")) { + //Skip if we don't have the proper settings. + continue; + } + + KisInputProfile *newProfile = addProfile(config.group("General").readEntry("name")); + Q_FOREACH(KisAbstractInputAction * action, d->actions) { + if (!config.hasGroup(action->name())) { + continue; + } + + KConfigGroup grp = config.group(action->name()); + //Read the settings for the action and create the appropriate shortcuts. + Q_FOREACH(const QString & entry, grp.entryMap()) { + KisShortcutConfiguration *shortcut = new KisShortcutConfiguration; + shortcut->setAction(action); + + if (shortcut->unserialize(entry)) { + newProfile->addShortcut(shortcut); + } + else { + delete shortcut; + } + } + } + } + + KisConfig cfg; + QString currentProfile = cfg.currentInputProfile(); + + if (currentProfile.isEmpty() || !d->profiles.contains(currentProfile)) { + d->currentProfile = d->profiles.begin().value(); + } + else { + d->currentProfile = d->profiles.value(currentProfile); + } + + emit currentProfileChanged(); +} + +void KisInputProfileManager::saveProfiles() +{ + QString storagePath = KGlobal::dirs()->saveLocation("appdata", "input/"); + Q_FOREACH(KisInputProfile * p, d->profiles) { + QString fileName = d->profileFileName(p->name()); + KConfig config(storagePath + fileName, KConfig::SimpleConfig); + + config.group("General").writeEntry("name", p->name()); + + Q_FOREACH(KisAbstractInputAction * action, d->actions) { + KConfigGroup grp = config.group(action->name()); + grp.deleteGroup(); //Clear the group of any existing shortcuts. + + int index = 0; + QList<KisShortcutConfiguration *> shortcuts = p->shortcutsForAction(action); + Q_FOREACH(KisShortcutConfiguration * shortcut, shortcuts) { + grp.writeEntry(QString("%1").arg(index++), shortcut->serialize()); + } + } + + config.sync(); + } + + KisConfig config; + config.setCurrentInputProfile(d->currentProfile->name()); + + //Force a reload of the current profile in input manager and whatever else uses the profile. + emit currentProfileChanged(); +} + +KisInputProfileManager::KisInputProfileManager(QObject *parent) + : QObject(parent), d(new Private()) +{ + d->createActions(); +} + +KisInputProfileManager::~KisInputProfileManager() +{ + qDeleteAll(d->profiles); + qDeleteAll(d->actions); + delete d; +} + +void KisInputProfileManager::Private::createActions() +{ + //TODO: Make this plugin based + //Note that the ordering here determines how things show up in the UI + actions.append(new KisToolInvocationAction()); + actions.append(new KisAlternateInvocationAction()); + actions.append(new KisChangePrimarySettingAction()); + actions.append(new KisPanAction()); + actions.append(new KisRotateCanvasAction()); + actions.append(new KisZoomAction()); + actions.append(new KisShowPaletteAction()); +} + +QString KisInputProfileManager::Private::profileFileName(const QString &profileName) +{ + return profileName.toLower().replace(QRegExp("[^a-z0-9]"), "").append(".profile"); +} diff --git a/krita/ui/input/kis_input_profile_manager.h b/krita/ui/input/kis_input_profile_manager.h new file mode 100644 index 0000000..5ecf112 --- /dev/null +++ b/krita/ui/input/kis_input_profile_manager.h @@ -0,0 +1,141 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISINPUTPROFILEMANAGER_H +#define KISINPUTPROFILEMANAGER_H + +#include <QObject> + +#include "krita_export.h" + +class KisAbstractInputAction; +class KisInputProfile; + +/** + * \brief A class to manage a list of profiles and actions. + * + * + */ +class KRITAUI_EXPORT KisInputProfileManager : public QObject +{ + Q_OBJECT +public: + KisInputProfileManager(QObject *parent = 0); + ~KisInputProfileManager(); + Q_DISABLE_COPY(KisInputProfileManager); + + /** + * Retrieve a profile by name. + * + * \param name The name of the profile to retrieve. + * + * \return The profile with the given name, or 0 if not found. + */ + KisInputProfile *profile(const QString &name) const; + /** + * \return A list of all profiles. + */ + QList<KisInputProfile *> profiles() const; + /** + * \return A list of the names of all profiles. + */ + QStringList profileNames() const; + + /** + * \return The current active profile. + */ + KisInputProfile *currentProfile() const; + /** + * Set the current active profile. + * + * \param profile The profile to set as current. + */ + void setCurrentProfile(KisInputProfile *profile); + + /** + * Add a profile. + * + * \param name The name of the new profile. + * + * \return The new, empty profile or the non-empty profile if it already exists. + */ + KisInputProfile *addProfile(const QString &name); + /** + * Remove a profile. + * + * This will remove the given profile from the list of profiles and delete it. + * + * \param name The profile to remove. + */ + void removeProfile(const QString &name); + /** + * Rename a profile. + * + * \param oldName The current name of the profile. + * \param newName The new name of the profile. + * + * \return true if successful, false if not. + */ + bool renameProfile(const QString &oldName, const QString &newName); + /** + * Duplicate a profile. + * + * This creates a new profile with the given name and copies all + * data from the old profile to the new profile. + * + * \param name The name of the profile to duplicate. + * \param newName The name of the new profile. + */ + void duplicateProfile(const QString &name, const QString &newName); + + /** + * \return The list of all available actions. + */ + QList< KisAbstractInputAction * > actions(); + + /** + * Load all profiles from the configuration stored on disk. + */ + void loadProfiles(); + /** + * Save all profiles to configuration on disk. + */ + void saveProfiles(); + + /** + * \return The singleton instance of this class. + */ + static KisInputProfileManager *instance(); + +Q_SIGNALS: + /** + * Emitted when the list of profiles changes. + */ + void profilesChanged(); + /** + * Emitted when the current active profile changes. + */ + void currentProfileChanged(); + +private: + class Private; + Private *const d; +}; + +#endif // KISINPUTPROFILEMANAGER_H diff --git a/krita/ui/input/kis_pan_action.cpp b/krita/ui/input/kis_pan_action.cpp index a2ca296..7164dbe 100644 --- a/krita/ui/input/kis_pan_action.cpp +++ b/krita/ui/input/kis_pan_action.cpp @@ -38,10 +38,11 @@ public: const int panDistance; }; -KisPanAction::KisPanAction(KisInputManager *manager) - : KisAbstractInputAction(manager), d(new Private) +KisPanAction::KisPanAction() + : d(new Private) { setName(i18n("Pan Canvas")); + setDescription(i18n("The <i>Pan Canvas</i> action pans the canvas.")); QHash<QString, int> shortcuts; shortcuts.insert(i18n("Toggle Pan Mode"), PanToggleShortcut); diff --git a/krita/ui/input/kis_pan_action.h b/krita/ui/input/kis_pan_action.h index 9944271..656789a 100644 --- a/krita/ui/input/kis_pan_action.h +++ b/krita/ui/input/kis_pan_action.h @@ -40,7 +40,7 @@ public: PanDownShortcut ///< Pan down by a fixed amount. }; - explicit KisPanAction(KisInputManager *manager); + explicit KisPanAction(); virtual ~KisPanAction(); void activate(); diff --git a/krita/ui/input/kis_rotate_canvas_action.cpp b/krita/ui/input/kis_rotate_canvas_action.cpp index 2cc0810..578fda2 100644 --- a/krita/ui/input/kis_rotate_canvas_action.cpp +++ b/krita/ui/input/kis_rotate_canvas_action.cpp @@ -36,10 +36,12 @@ public: }; -KisRotateCanvasAction::KisRotateCanvasAction(KisInputManager* manager) - : KisAbstractInputAction(manager), d(new Private()) +KisRotateCanvasAction::KisRotateCanvasAction() + : d(new Private()) { setName(i18n("Rotate Canvas")); + setDescription(i18n("The <i>Rotate Canvas</i> action rotates the canvas.")); + QHash<QString, int> shortcuts; shortcuts.insert(i18n("Toggle Rotate Mode"), RotateToggleShortcut); shortcuts.insert(i18n("Toggle Discrete Rotate Mode"), DiscreteRotateToggleShortcut); diff --git a/krita/ui/input/kis_rotate_canvas_action.h b/krita/ui/input/kis_rotate_canvas_action.h index 30a700f..e247933 100644 --- a/krita/ui/input/kis_rotate_canvas_action.h +++ b/krita/ui/input/kis_rotate_canvas_action.h @@ -41,7 +41,7 @@ public: RotateRightShortcut, ///< Rotate right by a fixed amount. RotateResetShortcut ///< Reset the rotation to 0. }; - explicit KisRotateCanvasAction(KisInputManager* manager); + explicit KisRotateCanvasAction(); virtual ~KisRotateCanvasAction(); void activate(); diff --git a/krita/ui/input/kis_shortcut_configuration.cpp b/krita/ui/input/kis_shortcut_configuration.cpp new file mode 100644 index 0000000..3eff2c5 --- /dev/null +++ b/krita/ui/input/kis_shortcut_configuration.cpp @@ -0,0 +1,349 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_shortcut_configuration.h" + +#include <QStringList> +#include <QKeySequence> +#include <KLocalizedString> + +class KisShortcutConfiguration::Private +{ +public: + Private() + : action(0), + type(UnknownType), + mode(0), + wheel(NoMovement), + gesture(NoGesture) + { } + + KisAbstractInputAction *action; + ShortcutType type; + uint mode; + + QList<Qt::Key> keys; + Qt::MouseButtons buttons; + MouseWheelMovement wheel; + GestureAction gesture; +}; + +KisShortcutConfiguration::KisShortcutConfiguration() + : d(new Private) +{ + +} + +KisShortcutConfiguration::KisShortcutConfiguration(const KisShortcutConfiguration &other) + : d(new Private) +{ + d->action = other.action(); + d->type = other.type(); + d->mode = other.mode(); + d->keys = other.keys(); + d->buttons = other.buttons(); + d->wheel = other.wheel(); + d->gesture = other.gesture(); +} + +KisShortcutConfiguration::~KisShortcutConfiguration() +{ + delete d; +} + +QString KisShortcutConfiguration::serialize() +{ + QString serialized("{"); + + serialized.append(QString::number(d->mode, 16)); + serialized.append(';'); + serialized.append(QString::number(d->type, 16)); + serialized.append(";["); + + for (QList<Qt::Key>::iterator itr = d->keys.begin(); itr != d->keys.end(); ++itr) { + serialized.append(QString::number(*itr, 16)); + + if (itr + 1 != d->keys.end()) { + serialized.append(','); + } + } + + serialized.append("];"); + + serialized.append(QString::number(d->buttons, 16)); + serialized.append(';'); + serialized.append(QString::number(d->wheel, 16)); + serialized.append(';'); + serialized.append(QString::number(d->gesture, 16)); + serialized.append('}'); + + return serialized; +} + +bool KisShortcutConfiguration::unserialize(const QString &serialized) +{ + if (!serialized.startsWith('{')) + return false; + + //Parse the serialized data and apply it to the current shortcut + QString remainder = serialized; + + //Remove brackets + remainder.remove('{').remove('}'); + + //Split the remainder by ; + QStringList parts = remainder.split(';'); + + if (parts.size() < 6) + return false; //Invalid input, abort + + //First entry in the list is the mode + d->mode = parts.at(0).toUInt(); + + //Second entry is the shortcut type + d->type = static_cast<ShortcutType>(parts.at(1).toInt()); + + if (d->type == UnknownType) { + //Reject input that would set this shortcut to "Unknown" + return false; + } + + //Third entry is the list of keys + QString serializedKeys = parts.at(2); + //Remove brackets + serializedKeys.remove('[').remove(']'); + //Split by , and add each entry as a key + QStringList keylist = serializedKeys.split(','); + Q_FOREACH(QString key, keylist) { + if (!key.isEmpty()) { + d->keys.append(static_cast<Qt::Key>(key.toUInt(0, 16))); + } + } + + //Fourth entry is the button mask + d->buttons = static_cast<Qt::MouseButtons>(parts.at(3).toInt()); + d->wheel = static_cast<MouseWheelMovement>(parts.at(4).toUInt()); + d->gesture = static_cast<GestureAction>(parts.at(5).toUInt()); + + return true; +} + +KisAbstractInputAction *KisShortcutConfiguration::action() const +{ + return d->action; +} + +void KisShortcutConfiguration::setAction(KisAbstractInputAction *newAction) +{ + if (d->action != newAction) { + d->action = newAction; + } +} + +KisShortcutConfiguration::ShortcutType KisShortcutConfiguration::type() const +{ + return d->type; +} + +void KisShortcutConfiguration::setType(KisShortcutConfiguration::ShortcutType newType) +{ + if (d->type != newType) { + d->type = newType; + } +} + +uint KisShortcutConfiguration::mode() const +{ + return d->mode; +} + +void KisShortcutConfiguration::setMode(uint newMode) +{ + if (d->mode != newMode) { + d->mode = newMode; + } +} + +QList< Qt::Key > KisShortcutConfiguration::keys() const +{ + return d->keys; +} + +void KisShortcutConfiguration::setKeys(const QList< Qt::Key > &newKeys) +{ + if (d->keys != newKeys) { + d->keys = newKeys; + } +} + +Qt::MouseButtons KisShortcutConfiguration::buttons() const +{ + return d->buttons; +} + +void KisShortcutConfiguration::setButtons(Qt::MouseButtons newButtons) +{ + if (d->buttons != newButtons) { + d->buttons = newButtons; + } +} + +KisShortcutConfiguration::MouseWheelMovement KisShortcutConfiguration::wheel() const +{ + return d->wheel; +} + +void KisShortcutConfiguration::setWheel(KisShortcutConfiguration::MouseWheelMovement type) +{ + if (d->wheel != type) { + d->wheel = type; + } +} + +KisShortcutConfiguration::GestureAction KisShortcutConfiguration::gesture() const +{ + return d->gesture; +} + +void KisShortcutConfiguration::setGesture(KisShortcutConfiguration::GestureAction type) +{ + if (d->gesture != type) { + d->gesture = type; + } +} + +QString KisShortcutConfiguration::buttonsToText(Qt::MouseButtons buttons) +{ + QString text; + + int buttonCount = 0; + + if (buttons & Qt::LeftButton) { + text.append(i18nc("Left Mouse Button", "Left")); + buttonCount++; + } + + if (buttons & Qt::RightButton) { + if (buttonCount++ > 0) { + text.append(" + "); + } + + text.append(i18nc("Right Mouse Button", "Right")); + } + + if (buttons & Qt::MidButton) { + if (buttonCount++ > 0) { + text.append(" + "); + } + + text.append(i18nc("Middle Mouse Button", "Middle")); + } + + if (buttons & Qt::XButton1) { + if (buttonCount++ > 0) { + text.append(" + "); + } + + text.append(i18nc("Mouse Back Button", "Back")); + } + + if (buttons & Qt::XButton1) { + if (buttonCount++ > 0) { + text.append(" + "); + } + + text.append(i18nc("Mouse Forward Button", "Forward")); + } + + if (buttonCount == 0) { + text.append(i18nc("No input", "None")); + } + else { + text.append(' '); + text.append(i18ncp("Mouse Buttons", "Button", "Buttons", buttonCount)); + } + + return text; +} + +QString KisShortcutConfiguration::keysToText(const QList<Qt::Key> &keys) +{ + QString output; + + foreach (Qt::Key key, keys) { + if (output.size() > 0) { + output.append(" + "); + } + + switch (key) { //Because QKeySequence fails for Ctrl, Alt, Shift and Meta + case Qt::Key_Control: + output.append(i18nc("Ctrl key", "Ctrl")); + break; + + case Qt::Key_Meta: + output.append(i18nc("Meta key", "Meta")); + break; + + case Qt::Key_Alt: + output.append(i18nc("Alt key", "Alt")); + break; + + case Qt::Key_Shift: + output.append(i18nc("Shift key", "Shift")); + break; + + default: + QKeySequence s(key); + output.append(s.toString(QKeySequence::NativeText)); + break; + } + + } + + if (output.size() == 0) { + output = i18nc("No input", "None"); + } + + return output; +} + +QString KisShortcutConfiguration::wheelToText(KisShortcutConfiguration::MouseWheelMovement wheel) +{ + switch (wheel) { + case KisShortcutConfiguration::WheelUp: + return i18n("Mouse Wheel Up"); + break; + + case KisShortcutConfiguration::WheelDown: + return i18n("Mouse Wheel Down"); + break; + + case KisShortcutConfiguration::WheelLeft: + return i18n("Mouse Wheel Left"); + break; + + case KisShortcutConfiguration::WheelRight: + return i18n("Mouse Wheel Right"); + break; + + default: + return i18nc("No input", "None"); + break; + } +} diff --git a/krita/ui/input/kis_shortcut_configuration.h b/krita/ui/input/kis_shortcut_configuration.h new file mode 100644 index 0000000..3e78d41 --- /dev/null +++ b/krita/ui/input/kis_shortcut_configuration.h @@ -0,0 +1,261 @@ +/* + * This file is part of the KDE project + * Copyright (C) 2013 Arjen Hiemstra <ahiemstra at heimr.nl> + * + * 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) 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISSHORTCUTCONFIGURATION_H +#define KISSHORTCUTCONFIGURATION_H + +#include <QList> +#include <QMetaType> + +class QString; +class KisAbstractInputAction; + +/** + * \brief A class encapsulating all settings for a single shortcut. + * + * This class encapsulates mouse buttons, keyboard keys and other settings + * related to a single shortcut for a single action. + * + * \note Each action can have several modes that activate it with usually + * different behaviour for each mode. Different shortcuts can activate + * different modes. + */ +class KisShortcutConfiguration +{ +public: + /** + * The type of shortcut, i.e. what kind of input does it expect. + */ + enum ShortcutType { + UnknownType, ///< Unknown, empty shortcut. + KeyCombinationType, ///< A list of keys that should be pressed. + MouseButtonType, ///< A mouse button, possibly with key modifiers. + MouseWheelType, ///< Mouse wheel movement, possibly with key modifiers. + GestureType, ///< A touch gesture. + }; + + /** + * The type of mouse wheel movement. + */ + enum MouseWheelMovement { + NoMovement, ///< No movement. + WheelUp, ///< Upwards movement, away from the user. + WheelDown, ///< Downwards movement, toward the user. + WheelLeft, ///< Left movement. + WheelRight, ///< Right movement. + }; + + /** + * The type of gesture. + */ + enum GestureAction { + NoGesture, ///< No gesture. + PinchGesture, ///< Pinch gesture, fingers moving towards or away from each other. + PanGesture, ///< Pan gesture, fingers staying together but moving across the screen. + }; + + /** + * Constructor. + */ + KisShortcutConfiguration(); + /** + * Copy constructor. + */ + KisShortcutConfiguration(const KisShortcutConfiguration &other); + /** + * Destructor. + */ + virtual ~KisShortcutConfiguration(); + + /** + * Serialize the data of this shortcut into a string that can be saved into + * a configuration file. + * + * The string will have the following format: + * + * {mode;type;[key,key];buttons;wheel;gesture} + * + * with each property serialized into a base-16 integer. + * + * \return A serialized representation of this shortcut. + */ + QString serialize(); + /** + * Apply the data from a serialized shortcut to this shortcut. + * + * This method expects a string as described in serialize(). + * + * \param serialized The serialized shortcut. + * + * \return true if successful, false if an error occurred. + * + * \sa serialize() + */ + bool unserialize(const QString &serialized); + + /** + * \return The action this shortcut is associated with. + */ + KisAbstractInputAction *action() const; + /** + * Set the action this shortcut should be associated with. + * + * \param newAction The action to set. + */ + void setAction(KisAbstractInputAction *newAction); + + /** + * \return The type of shortcut. + */ + ShortcutType type() const; + /** + * Set the type of shortcut. + * + * \param newType The type to set. + */ + void setType(ShortcutType newType); + + /** + * \return The mode of the action this shortcut will trigger. + */ + uint mode() const; + /** + * Set the mode of the action this shortcut will trigger. + * + * \param newMode The mode to set. + */ + void setMode(uint newMode); + + /** + * \return The list of keys that will trigger this shortcut. + * + * \note Not applicable when type is GestureType. + */ + QList<Qt::Key> keys() const; + /** + * Set the list of keys that will trigger this shortcut. + * + * \param newKeys The list of keys to use. + * + * \note Not applicable when type is GestureType. + */ + void setKeys(const QList<Qt::Key> &newKeys); + + /** + * \return The mouse buttons that will trigger this shortcut. + * + * \note Only applicable when type is MouseButtonType. + */ + Qt::MouseButtons buttons() const; + /** + * Set the mouse buttons that will trigger this shortcut. + * + * \param newButtons The mouse buttons to use. + * + * \note Only applicable when type is MouseButtonType. + */ + void setButtons(Qt::MouseButtons newButtons); + + /** + * \return The mouse wheel movement that will trigger this shortcut. + * + * \note Only applicable when type is MouseWheelType. + */ + MouseWheelMovement wheel() const; + /** + * Set the mouse wheel movement that will trigger this shortcut. + * + * \param type The wheel movement to use. + * + * \note Only applicable when type is MouseWheelType. + */ + void setWheel(MouseWheelMovement type); + + /** + * \return The gesture that will trigger this shortcut. + * + * \note Only applicable when type is GestureType. + */ + GestureAction gesture() const; + /** + * Set the gesture that will trigger this shortcut. + * + * \param type The gesture to use. + * + * \note Only applicable when type is GestureType. + */ + void setGesture(GestureAction type); + + /** + * Convert a set of mouse buttons into a user-readable + * string. + * + * This will convert the given set of buttons into a + * string that can be shown to a user. For example, the + * combination Qt::LeftButton + Qt::RightButton will produce + * the string "Left + Right Button". + * + * \param buttons The buttons to convert. + * + * \return A string representing the buttons that can be shown + * to a user. + * + * \note An empty set will produce the string "No Input". + */ + static QString buttonsToText(Qt::MouseButtons buttons); + /** + * Convert a list of keys to a user-readable string. + * + * This will convert the given list of keys into a string + * that can be shown to a user. For example, the list + * [Qt::Key_Shift, Qt::Key_Space] will produce the string + * "Shift + Space". + * + * \param keys The keys to convert. + * + * \return A string representing the keys that can be shown + * to a user. + * + * \note An empty list will produce the string "No Input". + */ + static QString keysToText(const QList<Qt::Key> &keys); + /** + * Convert the given mouse wheel movement to a string. + * + * This will convert the given mouse wheel movement into a + * string that can be shown to a user. For example, WheelUp + * will produce the string "Mouse Wheel Up". + * + * \param wheel The mouse wheel movement to convert. + * + * \return A string representing the mouse wheel movement + * that can be shown to a user. + * + * \note NoMovement will produce the string "No Input". + */ + static QString wheelToText(MouseWheelMovement wheel); + +private: + class Private; + Private *const d; +}; + +Q_DECLARE_METATYPE(KisShortcutConfiguration *); + +#endif // KISSHORTCUTCONFIGURATION_H diff --git a/krita/ui/input/kis_shortcut_matcher.cpp b/krita/ui/input/kis_shortcut_matcher.cpp index 0f21108..d2392b5 100644 --- a/krita/ui/input/kis_shortcut_matcher.cpp +++ b/krita/ui/input/kis_shortcut_matcher.cpp @@ -213,6 +213,14 @@ void KisShortcutMatcher::suppressAllActions(bool value) m_d->suppressAllActions = value; } +void KisShortcutMatcher::clearShortcuts() +{ + qDeleteAll(m_d->singleActionShortcuts); + m_d->singleActionShortcuts.clear(); + qDeleteAll(m_d->strokeShortcuts); + m_d->strokeShortcuts.clear(); +} + bool KisShortcutMatcher::tryRunWheelShortcut(KisSingleActionShortcut::WheelAction wheelAction, QWheelEvent *event) { return tryRunSingleActionShortcutImpl(wheelAction, event, m_d->keys); diff --git a/krita/ui/input/kis_shortcut_matcher.h b/krita/ui/input/kis_shortcut_matcher.h index 3e3e7cc..f87dd68 100644 --- a/krita/ui/input/kis_shortcut_matcher.h +++ b/krita/ui/input/kis_shortcut_matcher.h @@ -183,6 +183,11 @@ public: */ void suppressAllActions(bool value); + /** + * Remove all shortcuts that have been registered. + */ + void clearShortcuts(); + private: friend class KisInputManagerTest; diff --git a/krita/ui/input/kis_show_palette_action.cpp b/krita/ui/input/kis_show_palette_action.cpp index 96cfd6b..b6fddaa 100644 --- a/krita/ui/input/kis_show_palette_action.cpp +++ b/krita/ui/input/kis_show_palette_action.cpp @@ -25,10 +25,10 @@ #include "kis_input_manager.h" -KisShowPaletteAction::KisShowPaletteAction(KisInputManager* manager) - : KisAbstractInputAction(manager) +KisShowPaletteAction::KisShowPaletteAction() { setName(i18n("Show Popup Palette")); + setDescription(i18n("The <i>Show Popup Palette</i> displays the popup palette.")); } KisShowPaletteAction::~KisShowPaletteAction() diff --git a/krita/ui/input/kis_show_palette_action.h b/krita/ui/input/kis_show_palette_action.h index ebafab3..5f16a9a 100644 --- a/krita/ui/input/kis_show_palette_action.h +++ b/krita/ui/input/kis_show_palette_action.h @@ -29,7 +29,7 @@ class KisShowPaletteAction : public KisAbstractInputAction { public: - explicit KisShowPaletteAction(KisInputManager* manager); + explicit KisShowPaletteAction(); virtual ~KisShowPaletteAction(); virtual void begin(int, QEvent *); diff --git a/krita/ui/input/kis_single_action_shortcut.h b/krita/ui/input/kis_single_action_shortcut.h index 9660947..d90a9ab 100644 --- a/krita/ui/input/kis_single_action_shortcut.h +++ b/krita/ui/input/kis_single_action_shortcut.h @@ -32,7 +32,9 @@ class KRITAUI_EXPORT KisSingleActionShortcut : public KisAbstractShortcut public: enum WheelAction { WheelUp, ///< Mouse wheel moves up. - WheelDown ///< Mouse wheel moves down. + WheelDown, ///< Mouse wheel moves down. + WheelLeft, ///< Mouse wheel moves left. + WheelRight, ///< Mouse wheel moves right. }; KisSingleActionShortcut(KisAbstractInputAction *action, int index); diff --git a/krita/ui/input/kis_tool_invocation_action.cpp b/krita/ui/input/kis_tool_invocation_action.cpp index 3159af1..0537ba6 100644 --- a/krita/ui/input/kis_tool_invocation_action.cpp +++ b/krita/ui/input/kis_tool_invocation_action.cpp @@ -39,11 +39,17 @@ public: bool active; }; -KisToolInvocationAction::KisToolInvocationAction(KisInputManager *manager) - : KisAbstractInputAction(manager), d(new Private(this)) +KisToolInvocationAction::KisToolInvocationAction() + : d(new Private(this)) { setName(i18n("Tool Invocation")); - setDescription(i18n("Tool Invocation invokes the current tool, for example, using the brush tool, it will start painting.")); + setDescription(i18n("The <i>Tool Invocation</i> action invokes the current tool, for example, using the brush tool, it will start painting.")); + + QHash<QString, int> indexes; + indexes.insert(i18n("Activate"), ActivateShortcut); + indexes.insert(i18n("Confirm"), ConfirmShortcut); + indexes.insert(i18n("Cancel"), CancelShortcut); + setShortcutIndexes(indexes); } KisToolInvocationAction::~KisToolInvocationAction() @@ -95,7 +101,7 @@ void KisToolInvocationAction::end(QEvent *event) if (tabletEvent) { inputManager()->toolProxy()->tabletEvent(tabletEvent, d->tabletToPixel(tabletEvent->hiResGlobalPos())); - } else { + } else if (mouseEvent) { inputManager()->toolProxy()->mouseReleaseEvent(mouseEvent, inputManager()->widgetToPixel(mouseEvent->posF())); } diff --git a/krita/ui/input/kis_tool_invocation_action.h b/krita/ui/input/kis_tool_invocation_action.h index 0662c7d..0dc5c62 100644 --- a/krita/ui/input/kis_tool_invocation_action.h +++ b/krita/ui/input/kis_tool_invocation_action.h @@ -35,7 +35,7 @@ public: ConfirmShortcut, CancelShortcut }; - explicit KisToolInvocationAction(KisInputManager *manager); + explicit KisToolInvocationAction(); virtual ~KisToolInvocationAction(); void begin(int shortcut, QEvent *event); diff --git a/krita/ui/input/kis_zoom_action.cpp b/krita/ui/input/kis_zoom_action.cpp index 3d0e96b..8b96a39 100644 --- a/krita/ui/input/kis_zoom_action.cpp +++ b/krita/ui/input/kis_zoom_action.cpp @@ -76,10 +76,11 @@ void KisZoomAction::Private::zoomTo(bool zoomIn, QEvent *event) } } -KisZoomAction::KisZoomAction(KisInputManager* manager) - : KisAbstractInputAction(manager), d(new Private(this)) +KisZoomAction::KisZoomAction() + : d(new Private(this)) { setName(i18n("Zoom Canvas")); + setDescription(i18n("The <i>Zoom Canvas</i> action zooms the canvas.")); QHash< QString, int > shortcuts; shortcuts.insert(i18n("Toggle Zoom Mode"), ZoomToggleShortcut); diff --git a/krita/ui/input/kis_zoom_action.h b/krita/ui/input/kis_zoom_action.h index f49a3f4..ba85575 100644 --- a/krita/ui/input/kis_zoom_action.h +++ b/krita/ui/input/kis_zoom_action.h @@ -41,7 +41,7 @@ public: ZoomToPageShortcut, ///< Zoom fit to page. ZoomToWidthShortcut ///< Zoom fit to width. }; - explicit KisZoomAction(KisInputManager* manager); + explicit KisZoomAction(); virtual ~KisZoomAction(); void activate(); diff --git a/krita/ui/kis_config.cc b/krita/ui/kis_config.cc index c6e50da..8234289 100644 --- a/krita/ui/kis_config.cc +++ b/krita/ui/kis_config.cc @@ -933,6 +933,15 @@ void KisConfig::setToolbarSlider(int sliderNumber, const QString &slider) m_cfg.writeEntry(QString("toolbarslider_%1").arg(sliderNumber), slider); } +QString KisConfig::currentInputProfile() const +{ + return m_cfg.readEntry("currentInputProfile", QString()); +} + +void KisConfig::setCurrentInputProfile(const QString& name) +{ + m_cfg.writeEntry("currentInputProfile", name); +} bool KisConfig::useSystemMonitorProfile() const { diff --git a/krita/ui/kis_config.h b/krita/ui/kis_config.h index dace8b7..bed0a98 100644 --- a/krita/ui/kis_config.h +++ b/krita/ui/kis_config.h @@ -287,6 +287,9 @@ public: QString toolbarSlider(int sliderNumber); void setToolbarSlider(int sliderNumber, const QString &slider); + QString currentInputProfile() const; + void setCurrentInputProfile(const QString& name); + template<class T> void writeEntry(const QString& name, const T& value) { m_cfg.writeEntry(name, value); diff --git a/krita/ui/kis_view2.cpp b/krita/ui/kis_view2.cpp index 0b9a254..c8b8d84 100644 --- a/krita/ui/kis_view2.cpp +++ b/krita/ui/kis_view2.cpp @@ -128,6 +128,7 @@ #include <kis_paintop_preset.h> #include "ko_favorite_resource_manager.h" #include "kis_action_manager.h" +#include "input/kis_input_profile_manager.h" #include "kis_paintop_box.h" @@ -407,6 +408,8 @@ KisView2::KisView2(KoPart *part, KisDoc2 * doc, QWidget * parent) collection->readSettings(&group); } + KisInputProfileManager::instance()->loadProfiles(); + #if 0 //check for colliding shortcuts diff --git a/krita/ui/tests/kis_input_manager_test.cpp b/krita/ui/tests/kis_input_manager_test.cpp index b973f1a..51bfcc8 100644 --- a/krita/ui/tests/kis_input_manager_test.cpp +++ b/krita/ui/tests/kis_input_manager_test.cpp @@ -72,7 +72,7 @@ void KisInputManagerTest::testStrokeShortcut() struct TestingAction : public KisAbstractInputAction { - TestingAction() : KisAbstractInputAction(0), m_isHighResolution(false) { reset(); } + TestingAction() : KisAbstractInputAction(), m_isHighResolution(false) { reset(); } ~TestingAction() {} void begin(int shortcut, QEvent *event) { m_beginIndex = shortcut; m_beginNonNull = event;}
