[pitivi] shortcuts: Allow loading and saving of custom accelerators



commit 9dc539717e1ac04d159f9276d2990f82d57c6c25
Author: Jakub Brindza <jakub brindza gmail com>
Date:   Fri Jul 8 15:45:05 2016 +0100

    shortcuts: Allow loading and saving of custom accelerators
    
    Differential Revision: https://phabricator.freedesktop.org/D1160

 pitivi/shortcuts.py     |   42 ++++++++++++++++++++++++++++++++--
 tests/test_shortcuts.py |   57 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+), 3 deletions(-)
---
diff --git a/pitivi/shortcuts.py b/pitivi/shortcuts.py
index 1f1bc24..456a2b7 100644
--- a/pitivi/shortcuts.py
+++ b/pitivi/shortcuts.py
@@ -17,8 +17,11 @@
 # Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 # Boston, MA 02110-1301, USA.
 """Accelerators info."""
+import os.path
+
 from gi.repository import Gtk
 
+from pitivi.settings import xdg_config_home
 from pitivi.utils.misc import show_user_manual
 
 
@@ -30,6 +33,35 @@ class ShortcutsManager:
         self.groups = []
         self.group_titles = {}
         self.group_actions = {}
+        self.config_path = os.path.sep.join([xdg_config_home(),
+                                             "shortcuts.conf"])
+        self.__loaded = self.__load()
+
+    def __load(self):
+        """Loads the shortcuts from the config file and sets them.
+
+        Returns:
+            bool: Whether the config file exists.
+        """
+        if not os.path.isfile(self.config_path):
+            return False
+
+        for line in open(self.config_path, "r"):
+            action_name, accelerators = line.split(":", 1)
+            accelerators = accelerators.strip("\n").split(",")
+            self.app.set_accels_for_action(action_name, accelerators)
+        return True
+
+    def save(self):
+        """Saves the accelerators for each action to the config file.
+
+        Only the actions added using `add` with a title are considered.
+        """
+        with open(self.config_path, "w") as conf_file:
+            for unused_group_id, actions in self.group_actions.items():
+                for action, unused_title in actions:
+                    accels = ",".join(self.app.get_accels_for_action(action))
+                    conf_file.write(action + ":" + accels + "\n")
 
     def add(self, action, accelerators, title=None, group=None):
         """Adds an action to be displayed.
@@ -37,12 +69,16 @@ class ShortcutsManager:
         Args:
             action (str): The name identifying the action, formatted like
                 "prefix.name".
-            accelerators ([str]): List of accelerators corresponding to the action
+            accelerators ([str]): The default accelerators corresponding to
+                the action. They are set as the accelerators of the action
+                only if no accelerators have been loaded from the config file
+                initially, when the current manager instance has been created.
             title (Optional(str)): The title of the action.
             group (Optional[str]): The group id registered with `register_group`
-                to be used instead of the one extracted from `action`.
+                to be used instead of that extracted from `action`.
         """
-        self.app.set_accels_for_action(action, accelerators)
+        if not self.__loaded:
+            self.app.set_accels_for_action(action, accelerators)
 
         if title:
             action_prefix = group or action.split(".")[0]
diff --git a/tests/test_shortcuts.py b/tests/test_shortcuts.py
index 3f90caa..64fc154 100644
--- a/tests/test_shortcuts.py
+++ b/tests/test_shortcuts.py
@@ -17,6 +17,8 @@
 # Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 # Boston, MA 02110-1301, USA.
 """Test the keyboard shortcuts."""
+import os
+import tempfile
 from unittest import mock
 from unittest import TestCase
 
@@ -55,3 +57,58 @@ class TestShortcutsManager(TestCase):
                     group="beta_group")
         self.assertIn(("anything.third_action", "Third action"),
                       manager.group_actions["beta_group"])
+
+    def test_add_shortcut(self):
+        """Checks the number of calls to set_accels_for_action."""
+        app = mock.MagicMock()
+        with mock.patch("pitivi.shortcuts.xdg_config_home") as xdg_config_home,\
+                tempfile.TemporaryDirectory() as temp_dir:
+            xdg_config_home.return_value = temp_dir
+            manager = ShortcutsManager(app)
+            # Test the add is calling set_accels_for_action(),
+            # since there is no shortcuts.conf in the directory.
+            manager.register_group("general", "General group")
+            manager.add("prefix.action1", ["<Control>P"], "Action one")
+            self.assertEqual(app.set_accels_for_action.call_count, 1)
+
+            # Create the temporary shortcuts.conf file
+            # and test that add is not calling set_accels_for_action()
+            open(os.path.sep.join([temp_dir, "shortcuts.conf"]), "w").close()
+            manager2 = ShortcutsManager(app)
+            manager2.register_group("other", "Other group")
+
+            manager2.add("prefix.action4", ["<Control>W"],
+                         "Action addition not invoking set_accels_for_action")
+            # No. of calls to set_accels_for_action should be unchanged now
+            # because calling set_accels_for_action isn't allowed with .conf existing
+            self.assertEqual(app.set_accels_for_action.call_count, 1)
+
+    def test_load_save(self):
+        """Checks saved shortcuts are loaded by a new instance."""
+        app = mock.MagicMock()
+        with mock.patch("pitivi.shortcuts.xdg_config_home") as xdg_config_home,\
+                tempfile.TemporaryDirectory() as temp_dir:
+            xdg_config_home.return_value = temp_dir
+            manager = ShortcutsManager(app)
+            # No file exists so set_accels_for_action() is not called.
+            self.assertEqual(app.set_accels_for_action.call_count, 0)
+
+            # Set default shortcuts
+            manager.register_group("group", "Test group")
+            manager.add("group.action1", ["<Control>i"], "Action 1")
+            manager.add("group.action2", ["<Shift>p", "<Control>m"], "Action 2")
+            manager.add("group.action3", ["<Control><Shift>a", "a"], "Action 3")
+
+            # After saving the shortcuts, the accels should be set when
+            # initializing a ShortcutsManger.
+            app.get_accels_for_action.side_effect = [(["<Control>i"]),
+                                                     (["<Shift>p", "<Control>m"]),
+                                                     (["<Control><Shift>a", "a"])]
+            manager.save()
+            app.reset_mock()
+            unused_manager2 = ShortcutsManager(app)
+            self.assertEqual(app.set_accels_for_action.call_count, 3)
+            calls = [mock.call("group.action1", ["<Control>i"]),
+                     mock.call("group.action2", ["<Shift>p", "<Control>m"]),
+                     mock.call("group.action3", ["<Control><Shift>a", "a"])]
+            app.set_accels_for_action.assert_has_calls(calls, any_order=True)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]