[pygobject] Add ActionMap and ActionMap.add_action_entries() to overrides. Fixes #29



commit d0b219ca50b52fe219ceb90e80eca833fbba05ab
Author: yangfl <yangfl users noreply github com>
Date:   Sun Apr 29 20:08:55 2018 +0800

    Add ActionMap and ActionMap.add_action_entries() to overrides. Fixes #29
    
    Adds ActionMap and ActionMap.add_action_entries() to allow for adding
    multiple actions as a list of tuples in which each element defines
    a single action like the GActionEntry C struct.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=678655
    
    Original Author: Micah Carrick <micah quixotix com>

 gi/overrides/Gio.py         | 78 +++++++++++++++++++++++++++++++++++++++++++++
 tests/test_overrides_gio.py | 34 ++++++++++++++++++++
 2 files changed, 112 insertions(+)
---
diff --git a/gi/overrides/Gio.py b/gi/overrides/Gio.py
index f3c26b8d..b282c2aa 100644
--- a/gi/overrides/Gio.py
+++ b/gi/overrides/Gio.py
@@ -64,6 +64,84 @@ VolumeMonitor = override(VolumeMonitor)
 __all__.append('VolumeMonitor')
 
 
+class ActionMap(Gio.ActionMap):
+    def add_action_entries(self, entries, user_data=None):
+        """
+        The add_action_entries() method is a convenience function for creating
+        multiple Gio.SimpleAction instances and adding them to a Gio.ActionMap.
+        Each action is constructed as per one entry.
+
+        :param list entries:
+            List of entry tuples for add_action() method. The entry tuple can
+            vary in size with the following information:
+
+                * The name of the action. Must be specified.
+                * The callback to connect to the "activate" signal of the
+                  action. Since GLib 2.40, this can be None for stateful
+                  actions, in which case the default handler is used. For
+                  boolean-stated actions with no parameter, this is a toggle.
+                  For other state types (and parameter type equal to the state
+                  type) this will be a function that just calls change_state
+                  (which you should provide).
+                * The type of the parameter that must be passed to the activate
+                  function for this action, given as a single GLib.Variant type
+                  string (or None for no parameter)
+                * The initial state for this action, given in GLib.Variant text
+                  format. The state is parsed with no extra type information, so
+                  type tags must be added to the string if they are necessary.
+                  Stateless actions should give None here.
+                * The callback to connect to the "change-state" signal of the
+                  action. All stateful actions should provide a handler here;
+                  stateless actions should not.
+
+        :param user_data:
+            The user data for signal connections, or None
+        """
+        try:
+            iter(entries)
+        except (TypeError):
+            raise TypeError('entries must be iterable')
+
+        def _process_action(name, activate=None, parameter_type=None,
+                            state=None, change_state=None):
+            if parameter_type:
+                if not GLib.VariantType.string_is_valid(parameter_type):
+                    raise TypeError("The type string '%s' given as the "
+                                    "parameter type for action '%s' is "
+                                    "not a valid GVariant type string. " %
+                                    (parameter_type, name))
+                variant_parameter = GLib.VariantType.new(parameter_type)
+            else:
+                variant_parameter = None
+
+            if state is not None:
+                # stateful action
+                variant_state = GLib.Variant.parse(None, state, None, None)
+                action = Gio.SimpleAction.new_stateful(name, variant_parameter,
+                                                       variant_state)
+                if change_state is not None:
+                    action.connect('change-state', change_state, user_data)
+            else:
+                # stateless action
+                if change_state is not None:
+                    raise ValueError("Stateless action '%s' should give "
+                                     "None for 'change_state', not '%s'." %
+                                     (name, change_state))
+                action = Gio.SimpleAction(name=name, parameter_type=variant_parameter)
+
+            if activate is not None:
+                action.connect('activate', activate, user_data)
+            self.add_action(action)
+
+        for entry in entries:
+            # using inner function above since entries can leave out optional arguments
+            _process_action(*entry)
+
+
+ActionMap = override(ActionMap)
+__all__.append('ActionMap')
+
+
 class FileEnumerator(Gio.FileEnumerator):
     def __iter__(self):
         return self
diff --git a/tests/test_overrides_gio.py b/tests/test_overrides_gio.py
index 79f3085c..b6516f9b 100644
--- a/tests/test_overrides_gio.py
+++ b/tests/test_overrides_gio.py
@@ -310,3 +310,37 @@ def test_list_store_setitem_slice():
     with pytest.raises(TypeError):
         store[:] = [Item(), object()]
     assert len(store) == 0
+
+
+def test_action_map_add_action_entries():
+    actionmap = Gio.SimpleActionGroup()
+
+    test_data = []
+
+    def f(action, parameter, data):
+        test_data.append('test back')
+
+    actionmap.add_action_entries((
+        ("simple", f),
+        ("with_type", f, "i"),
+        ("with_state", f, "s", "'left'", f),
+    ))
+    assert actionmap.has_action("simple")
+    assert actionmap.has_action("with_type")
+    assert actionmap.has_action("with_state")
+    actionmap.add_action_entries((
+        ("with_user_data", f),
+    ), "user_data")
+    assert actionmap.has_action("with_user_data")
+
+    with pytest.raises(TypeError):
+        actionmap.add_action_entries((
+            ("invaild_type_string", f, 'asdf'),
+        ))
+    with pytest.raises(ValueError):
+        actionmap.add_action_entries((
+            ("stateless_with_change_state", f, None, None, f),
+        ))
+
+    actionmap.activate_action("simple")
+    assert test_data[0] == 'test back'


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