diff options
author | yangfl <yangfl@users.noreply.github.com> | 2018-04-29 20:08:55 +0800 |
---|---|---|
committer | Christoph Reiter <reiter.christoph@gmail.com> | 2018-05-03 13:20:36 +0000 |
commit | d0b219ca50b52fe219ceb90e80eca833fbba05ab (patch) | |
tree | e38876977910239ff4cf99d77477d662e00cee1f | |
parent | dceb3e339149f0bc7e9f004632a6a24f38ca60ad (diff) | |
download | pygobject-d0b219ca50b52fe219ceb90e80eca833fbba05ab.tar.gz |
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>
-rw-r--r-- | gi/overrides/Gio.py | 78 | ||||
-rw-r--r-- | tests/test_overrides_gio.py | 34 |
2 files changed, 112 insertions, 0 deletions
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' |