From af3b1ce77818b53fbe49e62488904b109edcf5fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Aum=C3=BCller?= <aumuell@reserv.at>
Date: Wed, 10 Mar 2010 11:21:56 +0100
Subject: [PATCH] factor out the commonalities between the keyboard shortcut &
 ex command mapping dialog

Merge-request: 125
Reviewed-by: Daniel Molkentin <daniel.molkentin@nokia.com>
---
 .../actionmanager/commandmappings.cpp         | 211 ++++++++++++++++++
 .../actionmanager/commandmappings.h           | 103 +++++++++
 .../commandmappings.ui}                       |  18 +-
 src/plugins/coreplugin/coreplugin.pro         |   4 +-
 .../coreplugin/dialogs/shortcutsettings.cpp   | 115 ++--------
 .../coreplugin/dialogs/shortcutsettings.h     |  18 +-
 src/plugins/fakevim/fakevim.pro               |   3 +-
 src/plugins/fakevim/fakevimexcommands.ui      | 156 -------------
 src/plugins/fakevim/fakevimplugin.cpp         | 122 +++-------
 9 files changed, 382 insertions(+), 368 deletions(-)
 create mode 100644 src/plugins/coreplugin/actionmanager/commandmappings.cpp
 create mode 100644 src/plugins/coreplugin/actionmanager/commandmappings.h
 rename src/plugins/coreplugin/{dialogs/shortcutsettings.ui => actionmanager/commandmappings.ui} (91%)
 delete mode 100644 src/plugins/fakevim/fakevimexcommands.ui

diff --git a/src/plugins/coreplugin/actionmanager/commandmappings.cpp b/src/plugins/coreplugin/actionmanager/commandmappings.cpp
new file mode 100644
index 00000000000..114fd1138a4
--- /dev/null
+++ b/src/plugins/coreplugin/actionmanager/commandmappings.cpp
@@ -0,0 +1,211 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "commandmappings.h"
+#include "ui_commandmappings.h"
+#include "actionmanager_p.h"
+#include "actionmanager/command.h"
+#include "command_p.h"
+#include "commandsfile.h"
+#include "coreconstants.h"
+#include "filemanager.h"
+#include "icore.h"
+#include "uniqueidmanager.h"
+#include <utils/treewidgetcolumnstretcher.h>
+
+
+#include <QtGui/QKeyEvent>
+#include <QtGui/QShortcut>
+#include <QtGui/QHeaderView>
+#include <QtGui/QFileDialog>
+#include <QtCore/QCoreApplication>
+#include <QtDebug>
+
+Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*);
+
+using namespace Core;
+using namespace Core::Internal;
+
+CommandMappings::CommandMappings(QObject *parent)
+    : IOptionsPage(parent)
+{
+}
+
+CommandMappings::~CommandMappings()
+{
+}
+
+// IOptionsPage
+
+
+QString CommandMappings::id() const
+{
+    return QLatin1String("D.Keyboard");
+}
+
+QString CommandMappings::displayName() const
+{
+    return tr("Keyboard");
+}
+
+QString CommandMappings::category() const
+{
+    return QLatin1String(Core::Constants::SETTINGS_CATEGORY_CORE);
+}
+
+QString CommandMappings::displayCategory() const
+{
+    return QCoreApplication::translate("Core", Core::Constants::SETTINGS_TR_CATEGORY_CORE);
+}
+
+QWidget *CommandMappings::createPage(QWidget *parent)
+{
+    m_page = new Ui_CommandMappings();
+    QWidget *w = new QWidget(parent);
+    m_page->setupUi(w);
+
+    m_page->resetButton->setIcon(QIcon(Constants::ICON_RESET));
+    m_page->targetEdit->installEventFilter(this);
+
+    connect(m_page->resetButton, SIGNAL(clicked()),
+        this, SLOT(resetTargetIdentifier()));
+    connect(m_page->removeButton, SIGNAL(clicked()),
+        this, SLOT(removeTargetIdentifier()));
+    connect(m_page->exportButton, SIGNAL(clicked()),
+        this, SLOT(exportAction()));
+    connect(m_page->importButton, SIGNAL(clicked()),
+        this, SLOT(importAction()));
+    connect(m_page->defaultButton, SIGNAL(clicked()),
+        this, SLOT(defaultAction()));
+
+    initialize();
+
+    m_page->commandList->sortByColumn(0, Qt::AscendingOrder);
+
+    connect(m_page->filterEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
+    connect(m_page->commandList, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
+        this, SLOT(commandChanged(QTreeWidgetItem *)));
+    connect(m_page->targetEdit, SIGNAL(textChanged(QString)), this, SLOT(targetIdentifierChanged()));
+
+    new Utils::TreeWidgetColumnStretcher(m_page->commandList, 1);
+
+    commandChanged(0);
+
+    return w;
+}
+
+void CommandMappings::setImportExportEnabled(bool enabled)
+{
+    m_page->importButton->setVisible(enabled);
+    m_page->exportButton->setVisible(enabled);
+}
+
+QTreeWidget *CommandMappings::commandList() const
+{
+    return m_page->commandList;
+}
+
+QLineEdit *CommandMappings::targetEdit() const
+{
+    return m_page->targetEdit;
+}
+
+void CommandMappings::setPageTitle(QString s)
+{
+    m_page->groupBox->setTitle(s);
+}
+
+void CommandMappings::setTargetLabelText(QString s)
+{
+    m_page->targetEditLabel->setText(s);
+}
+
+void CommandMappings::setTargetEditTitle(QString s)
+{
+    m_page->targetEditGroup->setTitle(s);
+}
+
+void CommandMappings::setTargetHeader(QString s)
+{
+    m_page->commandList->setHeaderLabels(QStringList() << tr("Command") << tr("Label") << s);
+}
+
+void CommandMappings::finish()
+{
+    delete m_page;
+}
+
+void CommandMappings::commandChanged(QTreeWidgetItem *current)
+{
+    if (!current || !current->data(0, Qt::UserRole).isValid()) {
+        m_page->targetEdit->setText("");
+        m_page->targetEditGroup->setEnabled(false);
+        return;
+    }
+    m_page->targetEditGroup->setEnabled(true);
+}
+
+void CommandMappings::filterChanged(const QString &f)
+{
+    for (int i=0; i<m_page->commandList->topLevelItemCount(); ++i) {
+        QTreeWidgetItem *item = m_page->commandList->topLevelItem(i);
+        item->setHidden(filter(f, item));
+    }
+}
+
+bool CommandMappings::filter(const QString &f, const QTreeWidgetItem *item)
+{
+
+    if (QTreeWidgetItem *parent = item->parent()) {
+        if (parent->text(0).contains(f, Qt::CaseInsensitive))
+            return false;
+    }
+
+    if (item->childCount() == 0) {
+        if (f.isEmpty())
+            return false;
+        for (int i = 0; i < item->columnCount(); ++i) {
+            if (item->text(i).contains(f, Qt::CaseInsensitive))
+                return false;
+        }
+        return true;
+    }
+
+    bool found = false;
+    for (int i = 0; i < item->childCount(); ++i) {
+        QTreeWidgetItem *citem = item->child(i);
+        if (filter(f, citem)) {
+            citem->setHidden(true);
+        } else {
+            citem->setHidden(false);
+            found = true;
+        }
+    }
+    return !found;
+}
diff --git a/src/plugins/coreplugin/actionmanager/commandmappings.h b/src/plugins/coreplugin/actionmanager/commandmappings.h
new file mode 100644
index 00000000000..c39a9e6db7b
--- /dev/null
+++ b/src/plugins/coreplugin/actionmanager/commandmappings.h
@@ -0,0 +1,103 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef COMMANDMAPPINGS_H
+#define COMMANDMAPPINGS_H
+
+#include <coreplugin/dialogs/ioptionspage.h>
+
+#include <QtCore/QObject>
+#include <QtGui/QKeySequence>
+#include <QtGui/QTreeWidgetItem>
+#include <QtGui/QKeyEvent>
+
+class QLineEdit;
+class QTreeWidget;
+
+QT_BEGIN_NAMESPACE
+class Ui_CommandMappings;
+QT_END_NAMESPACE
+
+namespace Core {
+
+class Command;
+
+namespace Internal {
+
+class ActionManagerPrivate;
+class MainWindow;
+
+}
+
+class CORE_EXPORT CommandMappings : public Core::IOptionsPage
+{
+    Q_OBJECT
+
+public:
+    CommandMappings(QObject *parent = 0);
+    ~CommandMappings();
+
+    // IOptionsPage
+    virtual QString id() const = 0;
+    virtual QString displayName() const = 0;
+    virtual QString category() const = 0;
+    virtual QString displayCategory() const = 0;
+
+protected slots:
+    void commandChanged(QTreeWidgetItem *current);
+    void filterChanged(const QString &f);
+    virtual void importAction() {}
+    virtual void exportAction() {}
+    virtual void defaultAction() = 0;
+
+protected:
+    // IOptionsPage
+    QWidget *createPage(QWidget *parent);
+    virtual void apply() {}
+    virtual void finish();
+
+    virtual void initialize() = 0;
+    bool filter(const QString &f, const QTreeWidgetItem *item);
+
+    // access to m_page
+    void setImportExportEnabled(bool enabled);
+    QTreeWidget *commandList() const;
+    QLineEdit *targetEdit() const;
+    void setPageTitle(QString s);
+    void setTargetLabelText(QString s);
+    void setTargetEditTitle(QString s);
+    void setTargetHeader(QString s);
+
+private:
+    Ui_CommandMappings *m_page;
+};
+
+} // namespace Core
+
+#endif // COMMANDMAPPINGS_H
diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.ui b/src/plugins/coreplugin/actionmanager/commandmappings.ui
similarity index 91%
rename from src/plugins/coreplugin/dialogs/shortcutsettings.ui
rename to src/plugins/coreplugin/actionmanager/commandmappings.ui
index 2bfd9bcfafc..5b862875231 100644
--- a/src/plugins/coreplugin/dialogs/shortcutsettings.ui
+++ b/src/plugins/coreplugin/actionmanager/commandmappings.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ui version="4.0">
- <class>ShortcutSettings</class>
- <widget class="QWidget" name="ShortcutSettings">
+ <class>CommandMappings</class>
+ <widget class="QWidget" name="CommandMappings">
   <property name="geometry">
    <rect>
     <x>0</x>
@@ -14,7 +14,7 @@
    <item>
     <widget class="QGroupBox" name="groupBox">
      <property name="title">
-      <string>Keyboard Shortcuts</string>
+      <string>Command Mappings</string>
      </property>
      <layout class="QVBoxLayout">
       <item>
@@ -57,7 +57,7 @@
         </column>
         <column>
          <property name="text">
-          <string>Shortcut</string>
+          <string>Target</string>
          </property>
         </column>
        </widget>
@@ -104,22 +104,22 @@
     </widget>
    </item>
    <item>
-    <widget class="QGroupBox" name="seqGrp">
+    <widget class="QGroupBox" name="targetEditGroup">
      <property name="title">
-      <string>Key Sequence</string>
+      <string>Target Identifier</string>
      </property>
      <layout class="QVBoxLayout">
       <item>
        <layout class="QHBoxLayout">
         <item>
-         <widget class="QLabel" name="label_2">
+         <widget class="QLabel" name="targetEditLabel">
           <property name="text">
-           <string>Shortcut:</string>
+           <string>Target:</string>
           </property>
          </widget>
         </item>
         <item>
-         <widget class="QLineEdit" name="shortcutEdit"/>
+         <widget class="QLineEdit" name="targetEdit"/>
         </item>
         <item>
          <widget class="QToolButton" name="resetButton">
diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro
index 8ccbf253dc7..349a0bffcd7 100644
--- a/src/plugins/coreplugin/coreplugin.pro
+++ b/src/plugins/coreplugin/coreplugin.pro
@@ -47,6 +47,7 @@ SOURCES += mainwindow.cpp \
     dialogs/saveitemsdialog.cpp \
     dialogs/newdialog.cpp \
     dialogs/settingsdialog.cpp \
+    actionmanager/commandmappings.cpp \
     dialogs/shortcutsettings.cpp \
     dialogs/openwithdialog.cpp \
     progressmanager/progressmanager.cpp \
@@ -116,6 +117,7 @@ HEADERS += mainwindow.h \
     dialogs/saveitemsdialog.h \
     dialogs/newdialog.h \
     dialogs/settingsdialog.h \
+    actionmanager/commandmappings.h \
     dialogs/shortcutsettings.h \
     dialogs/openwithdialog.h \
     dialogs/iwizard.h \
@@ -166,7 +168,7 @@ HEADERS += mainwindow.h \
     editortoolbar.h
 
 FORMS += dialogs/newdialog.ui \
-    dialogs/shortcutsettings.ui \
+    actionmanager/commandmappings.ui \
     dialogs/saveitemsdialog.ui \
     dialogs/openwithdialog.ui \
     editormanager/openeditorsview.ui \
diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
index f7d7f2141c7..a0fd5f4b071 100644
--- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
+++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
@@ -28,7 +28,6 @@
 **************************************************************************/
 
 #include "shortcutsettings.h"
-#include "ui_shortcutsettings.h"
 #include "actionmanager_p.h"
 #include "actionmanager/command.h"
 #include "command_p.h"
@@ -44,6 +43,7 @@
 #include <QtGui/QShortcut>
 #include <QtGui/QHeaderView>
 #include <QtGui/QFileDialog>
+#include <QtGui/QLineEdit>
 #include <QtCore/QCoreApplication>
 #include <QtDebug>
 
@@ -53,7 +53,7 @@ using namespace Core;
 using namespace Core::Internal;
 
 ShortcutSettings::ShortcutSettings(QObject *parent)
-    : IOptionsPage(parent)
+    : CommandMappings(parent)
 {
 }
 
@@ -88,36 +88,11 @@ QWidget *ShortcutSettings::createPage(QWidget *parent)
 {
     m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
 
-    m_page = new Ui_ShortcutSettings();
-    QWidget *w = new QWidget(parent);
-    m_page->setupUi(w);
-
-    m_page->resetButton->setIcon(QIcon(Constants::ICON_RESET));
-    m_page->shortcutEdit->installEventFilter(this);
-
-    connect(m_page->resetButton, SIGNAL(clicked()),
-        this, SLOT(resetKeySequence()));
-    connect(m_page->removeButton, SIGNAL(clicked()),
-        this, SLOT(removeKeySequence()));
-    connect(m_page->exportButton, SIGNAL(clicked()),
-        this, SLOT(exportAction()));
-    connect(m_page->importButton, SIGNAL(clicked()),
-        this, SLOT(importAction()));
-    connect(m_page->defaultButton, SIGNAL(clicked()),
-        this, SLOT(defaultAction()));
-
-    initialize();
-
-    m_page->commandList->sortByColumn(0, Qt::AscendingOrder);
-
-    connect(m_page->filterEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
-    connect(m_page->commandList, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
-        this, SLOT(commandChanged(QTreeWidgetItem *)));
-    connect(m_page->shortcutEdit, SIGNAL(textChanged(QString)), this, SLOT(keyChanged()));
-
-    new Utils::TreeWidgetColumnStretcher(m_page->commandList, 1);
-
-    commandChanged(0);
+    QWidget *w = CommandMappings::createPage(parent);
+    setPageTitle(tr("Keyboard Shortcuts"));
+    setTargetLabelText(tr("Shortcut:"));
+    setTargetEditTitle(tr("Keyboard Shortcuts"));
+    setTargetHeader(tr("Shortcut"));
 
     return w;
 }
@@ -133,7 +108,7 @@ void ShortcutSettings::finish()
     qDeleteAll(m_scitems);
     m_scitems.clear();
 
-    delete m_page;
+    CommandMappings::finish();
 }
 
 bool ShortcutSettings::eventFilter(QObject *o, QEvent *e)
@@ -156,27 +131,16 @@ bool ShortcutSettings::eventFilter(QObject *o, QEvent *e)
 
 void ShortcutSettings::commandChanged(QTreeWidgetItem *current)
 {
-    if (!current || !current->data(0, Qt::UserRole).isValid()) {
-        m_page->shortcutEdit->setText("");
-        m_page->seqGrp->setEnabled(false);
+    CommandMappings::commandChanged(current);
+    if (!current || !current->data(0, Qt::UserRole).isValid())
         return;
-    }
-    m_page->seqGrp->setEnabled(true);
     ShortcutItem *scitem = qVariantValue<ShortcutItem *>(current->data(0, Qt::UserRole));
     setKeySequence(scitem->m_key);
 }
 
-void ShortcutSettings::filterChanged(const QString &f)
-{
-    for (int i=0; i<m_page->commandList->topLevelItemCount(); ++i) {
-        QTreeWidgetItem *item = m_page->commandList->topLevelItem(i);
-        item->setHidden(filter(f, item));
-    }
-}
-
-void ShortcutSettings::keyChanged()
+void ShortcutSettings::targetIdentifierChanged()
 {
-    QTreeWidgetItem *current = m_page->commandList->currentItem();
+    QTreeWidgetItem *current = commandList()->currentItem();
     if (current && current->data(0, Qt::UserRole).isValid()) {
         ShortcutItem *scitem = qVariantValue<ShortcutItem *>(current->data(0, Qt::UserRole));
         scitem->m_key = QKeySequence(m_key[0], m_key[1], m_key[2], m_key[3]);
@@ -206,53 +170,22 @@ void ShortcutSettings::setKeySequence(const QKeySequence &key)
     for (int i = 0; i < m_keyNum; ++i) {
         m_key[i] = key[i];
     }
-    m_page->shortcutEdit->setText(key);
-}
-
-bool ShortcutSettings::filter(const QString &f, const QTreeWidgetItem *item)
-{
-
-    if (QTreeWidgetItem *parent = item->parent()) {
-        if (parent->text(0).contains(f, Qt::CaseInsensitive))
-            return false;
-    }
-
-    if (item->childCount() == 0) {
-        if (f.isEmpty())
-            return false;
-        for (int i = 0; i < item->columnCount(); ++i) {
-            if (item->text(i).contains(f, Qt::CaseInsensitive))
-                return false;
-        }
-        return true;
-    }
-
-    bool found = false;
-    for (int i = 0; i < item->childCount(); ++i) {
-        QTreeWidgetItem *citem = item->child(i);
-        if (filter(f, citem)) {
-            citem->setHidden(true);
-        } else {
-            citem->setHidden(false);
-            found = true;
-        }
-    }
-    return !found;
+    targetEdit()->setText(key);
 }
 
-void ShortcutSettings::resetKeySequence()
+void ShortcutSettings::resetTargetIdentifier()
 {
-    QTreeWidgetItem *current = m_page->commandList->currentItem();
+    QTreeWidgetItem *current = commandList()->currentItem();
     if (current && current->data(0, Qt::UserRole).isValid()) {
         ShortcutItem *scitem = qVariantValue<ShortcutItem *>(current->data(0, Qt::UserRole));
         setKeySequence(scitem->m_cmd->defaultKeySequence());
     }
 }
 
-void ShortcutSettings::removeKeySequence()
+void ShortcutSettings::removeTargetIdentifier()
 {
     m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
-    m_page->shortcutEdit->clear();
+    targetEdit()->clear();
 }
 
 void ShortcutSettings::importAction()
@@ -271,7 +204,7 @@ void ShortcutSettings::importAction()
             if (mapping.contains(sid)) {
                 item->m_key = mapping.value(sid);
                 item->m_item->setText(2, item->m_key);
-                if (item->m_item == m_page->commandList->currentItem())
+                if (item->m_item == commandList()->currentItem())
                     commandChanged(item->m_item);
             }
         }
@@ -283,7 +216,7 @@ void ShortcutSettings::defaultAction()
     foreach (ShortcutItem *item, m_scitems) {
         item->m_key = item->m_cmd->defaultKeySequence();
         item->m_item->setText(2, item->m_key);
-        if (item->m_item == m_page->commandList->currentItem())
+        if (item->m_item == commandList()->currentItem())
             commandChanged(item->m_item);
     }
 }
@@ -303,12 +236,12 @@ void ShortcutSettings::exportAction()
 
 void ShortcutSettings::initialize()
 {
-    m_am = ActionManagerPrivate::instance();
+    Core::Internal::ActionManagerPrivate *am = ActionManagerPrivate::instance();
     UniqueIDManager *uidm = UniqueIDManager::instance();
 
     QMap<QString, QTreeWidgetItem *> sections;
 
-    foreach (Command *c, m_am->commands()) {
+    foreach (Command *c, am->commands()) {
         if (c->hasAttribute(Command::CA_NonConfigureable))
             continue;
         if (c->action() && c->action()->isSeparator())
@@ -326,12 +259,12 @@ void ShortcutSettings::initialize()
         const QString section = identifier.left(pos);
         const QString subId = identifier.mid(pos+1);
         if (!sections.contains(section)) {
-            QTreeWidgetItem *categoryItem = new QTreeWidgetItem(m_page->commandList, QStringList() << section);
+            QTreeWidgetItem *categoryItem = new QTreeWidgetItem(commandList(), QStringList() << section);
             QFont f = categoryItem->font(0);
             f.setBold(true);
             categoryItem->setFont(0, f);
             sections.insert(section, categoryItem);
-            m_page->commandList->expandItem(categoryItem);
+            commandList()->expandItem(categoryItem);
         }
         sections[section]->addChild(item);
 
@@ -391,7 +324,7 @@ void ShortcutSettings::handleKeyEvent(QKeyEvent *e)
     }
     m_keyNum++;
     QKeySequence ks(m_key[0], m_key[1], m_key[2], m_key[3]);
-    m_page->shortcutEdit->setText(ks);
+    targetEdit()->setText(ks);
     e->accept();
 }
 
diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.h b/src/plugins/coreplugin/dialogs/shortcutsettings.h
index 48c9e6d5d71..e331fd8d285 100644
--- a/src/plugins/coreplugin/dialogs/shortcutsettings.h
+++ b/src/plugins/coreplugin/dialogs/shortcutsettings.h
@@ -30,17 +30,13 @@
 #ifndef SHORTCUTSETTINGS_H
 #define SHORTCUTSETTINGS_H
 
-#include <coreplugin/dialogs/ioptionspage.h>
+#include <coreplugin/actionmanager/commandmappings.h>
 
 #include <QtCore/QObject>
 #include <QtGui/QKeySequence>
 #include <QtGui/QTreeWidgetItem>
 #include <QtGui/QKeyEvent>
 
-QT_BEGIN_NAMESPACE
-class Ui_ShortcutSettings;
-QT_END_NAMESPACE
-
 namespace Core {
 
 class Command;
@@ -58,7 +54,7 @@ struct ShortcutItem
 };
 
 
-class ShortcutSettings : public Core::IOptionsPage
+class ShortcutSettings : public Core::CommandMappings
 {
     Q_OBJECT
 
@@ -81,26 +77,22 @@ protected:
 
 private slots:
     void commandChanged(QTreeWidgetItem *current);
-    void filterChanged(const QString &f);
-    void keyChanged();
-    void resetKeySequence();
-    void removeKeySequence();
+    void targetIdentifierChanged();
+    void resetTargetIdentifier();
+    void removeTargetIdentifier();
     void importAction();
     void exportAction();
     void defaultAction();
 
 private:
     void setKeySequence(const QKeySequence &key);
-    bool filter(const QString &f, const QTreeWidgetItem *item);
     void initialize();
 
     void handleKeyEvent(QKeyEvent *e);
     int translateModifiers(Qt::KeyboardModifiers state, const QString &text);
 
     QList<ShortcutItem *> m_scitems;
-    ActionManagerPrivate *m_am;
     int m_key[4], m_keyNum;
-    Ui_ShortcutSettings *m_page;
 };
 
 } // namespace Internal
diff --git a/src/plugins/fakevim/fakevim.pro b/src/plugins/fakevim/fakevim.pro
index 71a94b06d78..68d53d8a365 100644
--- a/src/plugins/fakevim/fakevim.pro
+++ b/src/plugins/fakevim/fakevim.pro
@@ -19,6 +19,5 @@ SOURCES += fakevimactions.cpp \
 HEADERS += fakevimactions.h \
     fakevimhandler.h \
     fakevimplugin.h
-FORMS += fakevimoptions.ui \
-    fakevimexcommands.ui
+FORMS += fakevimoptions.ui
 OTHER_FILES += FakeVim.pluginspec
diff --git a/src/plugins/fakevim/fakevimexcommands.ui b/src/plugins/fakevim/fakevimexcommands.ui
deleted file mode 100644
index 98e30b7c072..00000000000
--- a/src/plugins/fakevim/fakevimexcommands.ui
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>FakeVimExCommandsPage</class>
- <widget class="QWidget" name="FakeVimExCommandsPage">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>568</width>
-    <height>451</height>
-   </rect>
-  </property>
-  <layout class="QVBoxLayout">
-   <item>
-    <widget class="QGroupBox" name="groupBox">
-     <property name="title">
-      <string>Ex Command Mapping</string>
-     </property>
-     <layout class="QVBoxLayout">
-      <item>
-       <layout class="QHBoxLayout">
-        <item>
-         <widget class="QLabel" name="filterLabel">
-          <property name="text">
-           <string>Filter:</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QLineEdit" name="filterEdit"/>
-        </item>
-       </layout>
-      </item>
-      <item>
-       <widget class="QTreeWidget" name="commandList">
-        <property name="rootIsDecorated">
-         <bool>false</bool>
-        </property>
-        <property name="uniformRowHeights">
-         <bool>true</bool>
-        </property>
-        <property name="sortingEnabled">
-         <bool>true</bool>
-        </property>
-        <property name="columnCount">
-         <number>3</number>
-        </property>
-        <column>
-         <property name="text">
-          <string>Command</string>
-         </property>
-        </column>
-        <column>
-         <property name="text">
-          <string>Label</string>
-         </property>
-        </column>
-        <column>
-         <property name="text">
-          <string>Ex Trigger Expression</string>
-         </property>
-        </column>
-       </widget>
-      </item>
-      <item>
-       <layout class="QHBoxLayout">
-        <item>
-         <widget class="QPushButton" name="defaultButton">
-          <property name="text">
-           <string>Defaults</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <spacer>
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>40</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-       </layout>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QGroupBox" name="seqGrp">
-     <property name="title">
-      <string>Ex Command</string>
-     </property>
-     <layout class="QVBoxLayout">
-      <item>
-       <layout class="QHBoxLayout">
-        <item>
-         <widget class="QLabel" name="regexLabel">
-          <property name="text">
-           <string>Regular Expression:</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QLineEdit" name="regexEdit"/>
-        </item>
-        <item>
-         <widget class="QToolButton" name="resetButton">
-          <property name="toolTip">
-           <string>Reset</string>
-          </property>
-          <property name="text">
-           <string/>
-          </property>
-          <property name="icon">
-           <iconset resource="../coreplugin/core.qrc">
-            <normaloff>:/core/images/reset.png</normaloff>:/core/images/reset.png</iconset>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QToolButton" name="removeButton">
-          <property name="toolTip">
-           <string>Remove</string>
-          </property>
-          <property name="text">
-           <string/>
-          </property>
-          <property name="icon">
-           <iconset resource="../coreplugin/core.qrc">
-            <normaloff>:/core/images/clear.png</normaloff>:/core/images/clear.png</iconset>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-      <item>
-       <widget class="QLabel" name="infoLabel">
-        <property name="textFormat">
-         <enum>Qt::RichText</enum>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <resources>
-  <include location="../coreplugin/core.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp
index 38471bf28dc..b644ee2063d 100644
--- a/src/plugins/fakevim/fakevimplugin.cpp
+++ b/src/plugins/fakevim/fakevimplugin.cpp
@@ -31,7 +31,6 @@
 
 #include "fakevimhandler.h"
 #include "ui_fakevimoptions.h"
-#include "ui_fakevimexcommands.h"
 
 
 #include <coreplugin/actionmanager/actionmanager.h>
@@ -42,6 +41,7 @@
 #include <coreplugin/icore.h>
 #include <coreplugin/ifile.h>
 #include <coreplugin/dialogs/ioptionspage.h>
+#include <coreplugin/actionmanager/commandmappings.h>
 #include <coreplugin/messagemanager.h>
 #include <coreplugin/modemanager.h>
 #include <coreplugin/uniqueidmanager.h>
@@ -273,7 +273,7 @@ static QMap<QString, QRegExp> s_exCommandMap;
 static QMap<QString, QRegExp> s_defaultExCommandMap;
 
 
-class FakeVimExCommandsPage : public Core::IOptionsPage
+class FakeVimExCommandsPage : public Core::CommandMappings
 {
     Q_OBJECT
 
@@ -288,53 +288,28 @@ public:
 
     QWidget *createPage(QWidget *parent);
     void initialize();
-    void apply() {}
-    void finish() {}
-    virtual bool matches(const QString &) const;
-    bool filter(const QString &f, const QTreeWidgetItem *item);
 
 public slots:
-    void filterChanged(const QString &f);
     void commandChanged(QTreeWidgetItem *current);
-    void regexChanged();
-    void resetRegex();
-    void removeRegex();
+    void targetIdentifierChanged();
+    void resetTargetIdentifier();
+    void removeTargetIdentifier();
     void defaultAction();
 
 private:
-    Ui::FakeVimExCommandsPage m_ui;
-    QString m_searchKeywords;
     void setRegex(const QString &regex);
     QList<CommandItem *> m_citems;
 };
 
 QWidget *FakeVimExCommandsPage::createPage(QWidget *parent)
 {
-    QWidget *w = new QWidget(parent);
-    m_ui.setupUi(w);
-
-    connect(m_ui.resetButton, SIGNAL(clicked()),
-        this, SLOT(resetRegex()));
-    connect(m_ui.removeButton, SIGNAL(clicked()),
-        this, SLOT(removeRegex()));
-    connect(m_ui.defaultButton, SIGNAL(clicked()),
-        this, SLOT(defaultAction()));
+    QWidget *w = CommandMappings::createPage(parent);
+    setPageTitle(tr("Ex Command Mapping"));
+    setTargetHeader(tr("Ex Trigger Expression"));
+    setTargetLabelText(tr("Regular Expression:"));
+    setTargetEditTitle(tr("Ex Command"));
 
-    initialize();
-
-    m_ui.commandList->sortByColumn(0, Qt::AscendingOrder);
-
-    connect(m_ui.filterEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
-    connect(m_ui.commandList, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
-        this, SLOT(commandChanged(QTreeWidgetItem *)));
-    connect(m_ui.regexEdit, SIGNAL(textChanged(QString)), this, SLOT(regexChanged()));
-
-    if (m_searchKeywords.isEmpty()) {
-        QTextStream(&m_searchKeywords)
-            << ' ' << m_ui.groupBox->title();
-        m_searchKeywords.remove(QLatin1Char('&'));
-    }
-    new Utils::TreeWidgetColumnStretcher(m_ui.commandList, 1);
+    setImportExportEnabled(false);
 
     return w;
 }
@@ -364,12 +339,12 @@ void FakeVimExCommandsPage::initialize()
         const QString subId = name.mid(pos+1);
 
         if (!sections.contains(section)) {
-            QTreeWidgetItem *categoryItem = new QTreeWidgetItem(m_ui.commandList, QStringList() << section);
+            QTreeWidgetItem *categoryItem = new QTreeWidgetItem(commandList(), QStringList() << section);
             QFont f = categoryItem->font(0);
             f.setBold(true);
             categoryItem->setFont(0, f);
             sections.insert(section, categoryItem);
-            m_ui.commandList->expandItem(categoryItem);
+            commandList()->expandItem(categoryItem);
         }
         sections[section]->addChild(item);
 
@@ -407,28 +382,18 @@ void FakeVimExCommandsPage::initialize()
 
 void FakeVimExCommandsPage::commandChanged(QTreeWidgetItem *current)
 {
-    if (!current || !current->data(0, Qt::UserRole).isValid()) {
-        m_ui.regexEdit->setText(QString());
-        m_ui.seqGrp->setEnabled(false);
+    CommandMappings::commandChanged(current);
+
+    if (!current || !current->data(0, Qt::UserRole).isValid())
         return;
-    }
 
-    m_ui.seqGrp->setEnabled(true);
     CommandItem *citem = qVariantValue<CommandItem *>(current->data(0, Qt::UserRole));
-    m_ui.regexEdit->setText(citem->m_regex);
+    targetEdit()->setText(citem->m_regex);
 }
 
-void FakeVimExCommandsPage::filterChanged(const QString &f)
+void FakeVimExCommandsPage::targetIdentifierChanged()
 {
-    for (int i=0; i<m_ui.commandList->topLevelItemCount(); ++i) {
-        QTreeWidgetItem *item = m_ui.commandList->topLevelItem(i);
-        item->setHidden(filter(f, item));
-    }
-}
-
-void FakeVimExCommandsPage::regexChanged()
-{
-    QTreeWidgetItem *current = m_ui.commandList->currentItem();
+    QTreeWidgetItem *current = commandList()->currentItem();
     if (!current)
         return;
 
@@ -437,7 +402,7 @@ void FakeVimExCommandsPage::regexChanged()
     const QString name = uidm->stringForUniqueIdentifier(citem->m_cmd->id());
 
     if (current->data(0, Qt::UserRole).isValid()) {
-        citem->m_regex = m_ui.regexEdit->text();
+        citem->m_regex = targetEdit()->text();
         current->setText(2, citem->m_regex);
         s_exCommandMap[name] = QRegExp(citem->m_regex);
     }
@@ -462,43 +427,13 @@ void FakeVimExCommandsPage::regexChanged()
 
 void FakeVimExCommandsPage::setRegex(const QString &regex)
 {
-    m_ui.regexEdit->setText(regex);
-}
-
-bool FakeVimExCommandsPage::filter(const QString &f, const QTreeWidgetItem *item)
-{
-    if (QTreeWidgetItem *parent = item->parent()) {
-        if (parent->text(0).contains(f, Qt::CaseInsensitive))
-            return false;
-    }
-
-    if (item->childCount() == 0) {
-        if (f.isEmpty())
-            return false;
-        for (int i = 0; i < item->columnCount(); ++i) {
-            if (item->text(i).contains(f, Qt::CaseInsensitive))
-                return false;
-        }
-        return true;
-    }
-
-    bool found = false;
-    for (int i = 0; i < item->childCount(); ++i) {
-        QTreeWidgetItem *citem = item->child(i);
-        if (filter(f, citem)) {
-            citem->setHidden(true);
-        } else {
-            citem->setHidden(false);
-            found = true;
-        }
-    }
-    return !found;
+    targetEdit()->setText(regex);
 }
 
-void FakeVimExCommandsPage::resetRegex()
+void FakeVimExCommandsPage::resetTargetIdentifier()
 {
     UniqueIDManager *uidm = UniqueIDManager::instance();
-    QTreeWidgetItem *current = m_ui.commandList->currentItem();
+    QTreeWidgetItem *current = commandList()->currentItem();
     if (current && current->data(0, Qt::UserRole).isValid()) {
         CommandItem *citem = qVariantValue<CommandItem *>(current->data(0, Qt::UserRole));
         const QString &name = uidm->stringForUniqueIdentifier(citem->m_cmd->id());
@@ -509,9 +444,9 @@ void FakeVimExCommandsPage::resetRegex()
     }
 }
 
-void FakeVimExCommandsPage::removeRegex()
+void FakeVimExCommandsPage::removeTargetIdentifier()
 {
-    m_ui.regexEdit->clear();
+    targetEdit()->clear();
 }
 
 void FakeVimExCommandsPage::defaultAction()
@@ -525,16 +460,11 @@ void FakeVimExCommandsPage::defaultAction()
             item->m_regex.clear();
         }
         item->m_item->setText(2, item->m_regex);
-        if (item->m_item == m_ui.commandList->currentItem())
+        if (item->m_item == commandList()->currentItem())
             commandChanged(item->m_item);
     }
 }
 
-bool FakeVimExCommandsPage::matches(const QString &s) const
-{
-    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
-}
-
 } // namespace Internal
 } // namespace FakeVim
 
-- 
GitLab