diff options
author | Christoph Reiter <reiter.christoph@gmail.com> | 2018-04-16 14:38:50 +0200 |
---|---|---|
committer | Christoph Reiter <reiter.christoph@gmail.com> | 2018-04-16 22:02:36 +0200 |
commit | 14574267f1711b6d51738f9e371837202babd04b (patch) | |
tree | fc4e989413b6753c96627677f84df9c1e2f34c49 /gi | |
parent | ad1bbfa148b7734e2fca3c9f0e14ddab630bc354 (diff) | |
download | pygobject-listmodel-sequence.tar.gz |
Gio.ListModel: implement most of the mutable sequence protocol. See #115listmodel-sequence
Adds all the dunder methods for MutableSequence to Gio.ListModel and
Gio.ListStore.
__delitem__ supports atomic deletion of slices through splice() when
possible.
__setitem__ has to fall back to remove/delete since adding items with
splice doesn't work right, see https://bugzilla.gnome.org/show_bug.cgi?id=795307
Diffstat (limited to 'gi')
-rw-r--r-- | gi/_compat.py | 2 | ||||
-rw-r--r-- | gi/overrides/Gio.py | 106 |
2 files changed, 108 insertions, 0 deletions
diff --git a/gi/_compat.py b/gi/_compat.py index b8a3506c..b4cc46d8 100644 --- a/gi/_compat.py +++ b/gi/_compat.py @@ -29,6 +29,7 @@ if sys.version_info[0] == 2: text_type = eval("unicode") reload = eval("reload") + xrange = eval("xrange") exec("def reraise(tp, value, tb):\n raise tp, value, tb") else: @@ -47,6 +48,7 @@ else: from importlib import reload reload + xrange = range def reraise(tp, value, tb): raise tp(value).with_traceback(tb) diff --git a/gi/overrides/Gio.py b/gi/overrides/Gio.py index 5ab23fcd..8604d550 100644 --- a/gi/overrides/Gio.py +++ b/gi/overrides/Gio.py @@ -23,6 +23,7 @@ import warnings from .._ossighelper import wakeup_on_signal, register_sigint_fallback from ..overrides import override, deprecated_init from ..module import get_introspection_module +from .._compat import xrange from gi import PyGIWarning from gi.repository import GLib @@ -271,3 +272,108 @@ class DBusProxy(Gio.DBusProxy): DBusProxy = override(DBusProxy) __all__.append('DBusProxy') + + +class ListModel(Gio.ListModel): + + def __getitem__(self, key): + if isinstance(key, slice): + return [self.get_item(i) for i in xrange(*key.indices(len(self)))] + elif isinstance(key, int): + if key < 0: + key += len(self) + if key < 0: + raise IndexError + ret = self.get_item(key) + if ret is None: + raise IndexError + return ret + else: + raise TypeError + + def __contains__(self, item): + pytype = self.get_item_type().pytype + if not isinstance(item, pytype): + raise TypeError( + "Expected type %s.%s" % (pytype.__module__, pytype.__name__)) + for i in self: + if i == item: + return True + return False + + def __len__(self): + return self.get_n_items() + + def __iter__(self): + for i in xrange(len(self)): + yield self.get_item(i) + + +ListModel = override(ListModel) +__all__.append('ListModel') + + +class ListStore(Gio.ListStore): + + def __delitem__(self, key): + if isinstance(key, slice): + start, stop, step = key.indices(len(self)) + if step == 1: + self.splice(start, max(stop - start, 0), []) + elif step == -1: + self.splice(stop + 1, max(start - stop, 0), []) + else: + for i in sorted(xrange(start, stop, step), reverse=True): + self.remove(i) + elif isinstance(key, int): + if key < 0: + key += len(self) + if key < 0 or key >= len(self): + raise IndexError + self.remove(key) + else: + raise TypeError + + def __setitem__(self, key, value): + if isinstance(key, slice): + pytype = self.get_item_type().pytype + valuelist = [] + for v in value: + if not isinstance(v, pytype): + raise TypeError( + "Expected type %s.%s" % ( + pytype.__module__, pytype.__name__)) + valuelist.append(v) + + start, stop, step = key.indices(len(self)) + if step == 1: + self.__delitem__(key) + for v in reversed(valuelist): + self.insert(start, v) + else: + indices = list(xrange(start, stop, step)) + if len(indices) != len(valuelist): + raise ValueError + for i, v in zip(indices, valuelist): + self.remove(i) + self.insert(i, v) + elif isinstance(key, int): + if key < 0: + key += len(self) + if key < 0 or key >= len(self): + raise IndexError + + pytype = self.get_item_type().pytype + if not isinstance(value, pytype): + raise TypeError( + "Expected type %s.%s" % ( + pytype.__module__, pytype.__name__)) + + self.remove(key) + self.insert(key, value) + else: + raise TypeError + + +ListStore = override(ListStore) +__all__.append('ListStore') |