From c5cc4b1f131cbfc84622a93716ed421dd57f4da5 Mon Sep 17 00:00:00 2001
From: Eike Ziller <eike.ziller@digia.com>
Date: Mon, 24 Feb 2014 15:20:50 +0100
Subject: [PATCH] Shortcuts: Remember them even for plugins that are not loaded

This also fixes the issue that shortcuts of designer integration gets
lost if it doesn't get initialized.

Task-number: QTCREATORBUG-4264
Task-number: QTCREATORBUG-11399
Change-Id: Ieb4fe5fd345e69aa62403e4578fa6028400aff6f
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Eike Ziller <eike.ziller@digia.com>
---
 .../actionmanager/actionmanager.cpp           | 63 ++++++++++++-------
 .../coreplugin/actionmanager/actionmanager.h  |  2 +-
 .../actionmanager/actionmanager_p.h           |  2 +
 src/plugins/coreplugin/mainwindow.cpp         |  5 +-
 4 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp
index 4db035bfda7..93f31496029 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp
+++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp
@@ -48,6 +48,8 @@ namespace {
     enum { warnAboutFindFailures = 0 };
 }
 
+static const char kKeyboardSettingsKey[] = "KeyboardShortcuts";
+
 using namespace Core;
 using namespace Core::Internal;
 
@@ -281,6 +283,7 @@ Command *ActionManager::registerShortcut(QShortcut *shortcut, Id id, const Conte
     } else {
         sc = new Shortcut(id);
         d->m_idCmdMap.insert(id, sc);
+        d->readUserSettings(id, sc);
     }
 
     if (sc->shortcut()) {
@@ -571,6 +574,7 @@ Action *ActionManagerPrivate::overridableAction(Id id)
     } else {
         a = new Action(id);
         m_idCmdMap.insert(id, a);
+        readUserSettings(id, a);
         ICore::mainWindow()->addAction(a->action());
         a->action()->setObjectName(id.toString());
         a->action()->setShortcutContext(Qt::ApplicationShortcut);
@@ -583,43 +587,60 @@ Action *ActionManagerPrivate::overridableAction(Id id)
     return a;
 }
 
-static const char settingsGroup[] = "KeyBindings";
-static const char idKey[] = "ID";
-static const char sequenceKey[] = "Keysequence";
+void ActionManagerPrivate::readUserSettings(Id id, CommandPrivate *cmd)
+{
+    QSettings *settings = Core::ICore::settings();
+    settings->beginGroup(QLatin1String(kKeyboardSettingsKey));
+    if (settings->contains(id.toString()))
+        cmd->setKeySequence(QKeySequence(settings->value(id.toString()).toString()));
+    settings->endGroup();
+}
+
+static const char oldSettingsGroup[] = "KeyBindings";
+static const char oldIdKey[] = "ID";
+static const char oldSequenceKey[] = "Keysequence";
 
 void ActionManagerPrivate::initialize()
 {
+    // TODO remove me after some period after 3.1
+    // check if settings in old style (pre 3.1) exist
     QSettings *settings = Core::ICore::settings();
-    const int shortcuts = settings->beginReadArray(QLatin1String(settingsGroup));
+    if (settings->contains(QLatin1String(kKeyboardSettingsKey)))
+        return;
+    // move old settings style to new settings style
+    QMap<Id, QKeySequence> shortcutMap;
+    const int shortcuts = settings->beginReadArray(QLatin1String(oldSettingsGroup));
     for (int i = 0; i < shortcuts; ++i) {
         settings->setArrayIndex(i);
-        const QKeySequence key(settings->value(QLatin1String(sequenceKey)).toString());
-        const Id id = Id::fromSetting(settings->value(QLatin1String(idKey)));
-
-        Command *cmd = ActionManager::command(id);
-        if (cmd)
-            cmd->setKeySequence(key);
+        const QKeySequence key(settings->value(QLatin1String(oldSequenceKey)).toString());
+        const Id id = Id::fromSetting(settings->value(QLatin1String(oldIdKey)));
+        shortcutMap.insert(id, key);
     }
     settings->endArray();
+    // write settings in new style
+    settings->beginGroup(QLatin1String(kKeyboardSettingsKey));
+    QMapIterator<Id, QKeySequence> it(shortcutMap);
+    while (it.hasNext()) {
+        it.next();
+        settings->setValue(it.key().toString(), it.value().toString());
+    }
+    settings->endGroup();
+    // remove old settings
+    settings->remove(QLatin1String(oldSettingsGroup));
 }
 
 void ActionManagerPrivate::saveSettings(QSettings *settings)
 {
-    settings->beginWriteArray(QLatin1String(settingsGroup));
-    int count = 0;
-
+    settings->beginGroup(QLatin1String(kKeyboardSettingsKey));
     const IdCmdMap::const_iterator cmdcend = m_idCmdMap.constEnd();
     for (IdCmdMap::const_iterator j = m_idCmdMap.constBegin(); j != cmdcend; ++j) {
         const Id id = j.key();
         CommandPrivate *cmd = j.value();
         QKeySequence key = cmd->keySequence();
-        if (key != cmd->defaultKeySequence()) {
-            settings->setArrayIndex(count);
-            settings->setValue(QLatin1String(idKey), id.toString());
-            settings->setValue(QLatin1String(sequenceKey), key.toString());
-            count++;
-        }
+        if (key != cmd->defaultKeySequence())
+            settings->setValue(id.toString(), key.toString());
+        else
+            settings->remove(id.toString());
     }
-
-    settings->endArray();
+    settings->endGroup();
 }
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.h b/src/plugins/coreplugin/actionmanager/actionmanager.h
index f6d7a7bb734..e014478c84b 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager.h
+++ b/src/plugins/coreplugin/actionmanager/actionmanager.h
@@ -80,7 +80,7 @@ signals:
 private:
     ActionManager(QObject *parent = 0);
     ~ActionManager();
-    void initialize();
+    static void initialize();
     void saveSettings(QSettings *settings);
     void setContext(const Context &context);
 
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager_p.h b/src/plugins/coreplugin/actionmanager/actionmanager_p.h
index 646d03db28d..9df5e200da3 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager_p.h
+++ b/src/plugins/coreplugin/actionmanager/actionmanager_p.h
@@ -74,6 +74,8 @@ public:
     bool hasContext(const Context &context) const;
     Action *overridableAction(Id id);
 
+    void readUserSettings(Id id, CommandPrivate *cmd);
+
 public slots:
     void containerDestroyed();
 
diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp
index 7956e0f472d..55b9db99b02 100644
--- a/src/plugins/coreplugin/mainwindow.cpp
+++ b/src/plugins/coreplugin/mainwindow.cpp
@@ -147,6 +147,8 @@ MainWindow::MainWindow() :
     m_zoomAction(0),
     m_toggleSideBarButton(new QToolButton)
 {
+    ActionManager::initialize(); // must be done before registering any actions
+
     (void) new DocumentManager(this);
     OutputPaneManager::create();
 
@@ -344,9 +346,6 @@ void MainWindow::extensionsInitialized()
     m_vcsManager->extensionsInitialized();
     m_navigationWidget->setFactories(ExtensionSystem::PluginManager::getObjects<INavigationWidgetFactory>());
 
-    // reading the shortcut settings must be done after all shortcuts have been registered
-    m_actionManager->initialize();
-
     readSettings();
     updateContext();
 
-- 
GitLab