mirror of
https://github.com/arsenetar/dupeguru.git
synced 2026-01-22 14:41:39 +00:00
Improved hscommon.gui docs
This commit is contained in:
@@ -11,6 +11,22 @@ from collections import Sequence, MutableSequence
|
||||
from .base import GUIObject
|
||||
|
||||
class Selectable(Sequence):
|
||||
"""Mix-in for a ``Sequence`` that manages its selection status.
|
||||
|
||||
When mixed in with a ``Sequence``, we enable it to manage its selection status. The selection
|
||||
is held as a list of ``int`` indexes. Multiple selection is supported.
|
||||
|
||||
.. attribute:: selected_index
|
||||
|
||||
*int*. *get/set*. Thin wrapper around :attr:`selected_indexes`. Points to the first selected
|
||||
index or ``None`` if it's empty. Using this property only makes sense if your selectable
|
||||
sequence supports single selection only.
|
||||
|
||||
.. attribute:: selected_indexes
|
||||
|
||||
*list*. *get/set*. List of selected indexes. When setting the value, automatically removes
|
||||
out-of-bounds indexes. The list is kept sorted.
|
||||
"""
|
||||
def __init__(self):
|
||||
self._selected_indexes = []
|
||||
|
||||
@@ -26,16 +42,30 @@ class Selectable(Sequence):
|
||||
|
||||
#--- Virtual
|
||||
def _update_selection(self):
|
||||
# Takes the table's selection and does appropriates updates on the view and/or model, when
|
||||
# appropriate. Common sense would dictate that when the selection doesn't change, we don't
|
||||
# update anything (and thus don't call _update_selection() at all), but there are cases
|
||||
# where it's false. For example, if our list updates its items but doesn't change its
|
||||
# selection, we probably want to update the model's selection. A redesign of how this whole
|
||||
# thing works is probably in order, but not now, there's too much breakage at once involved.
|
||||
pass
|
||||
"""(Virtual) Updates the model's selection appropriately.
|
||||
|
||||
Called after selection has been updated. Takes the table's selection and does appropriates
|
||||
updates on the view and/or model. Common sense would dictate that when the selection doesn't
|
||||
change, we don't update anything (and thus don't call ``_update_selection()`` at all), but
|
||||
there are cases where it's false. For example, if our list updates its items but doesn't
|
||||
change its selection, we probably want to update the model's selection.
|
||||
|
||||
By default, does nothing.
|
||||
|
||||
Important note: This is only called on :meth:`select`, not on changes to
|
||||
:attr:`selected_indexes`.
|
||||
"""
|
||||
# A redesign of how this whole thing works is probably in order, but not now, there's too
|
||||
# much breakage at once involved.
|
||||
|
||||
#--- Public
|
||||
def select(self, indexes):
|
||||
"""Update selection to ``indexes``.
|
||||
|
||||
:meth:`_update_selection` is called afterwards.
|
||||
|
||||
:param list indexes: List of ``int`` that is to become the new selection.
|
||||
"""
|
||||
if isinstance(indexes, int):
|
||||
indexes = [indexes]
|
||||
self.selected_indexes = indexes
|
||||
@@ -62,6 +92,10 @@ class Selectable(Sequence):
|
||||
|
||||
|
||||
class SelectableList(MutableSequence, Selectable):
|
||||
"""A list that can manage selection of its items.
|
||||
|
||||
Subclasses :class:`Selectable`. Behaves like a ``list``.
|
||||
"""
|
||||
def __init__(self, items=None):
|
||||
Selectable.__init__(self)
|
||||
if items:
|
||||
@@ -100,10 +134,14 @@ class SelectableList(MutableSequence, Selectable):
|
||||
|
||||
#--- Virtual
|
||||
def _on_change(self):
|
||||
pass
|
||||
"""(Virtual) Called whenever the contents of the list changes.
|
||||
|
||||
By default, does nothing.
|
||||
"""
|
||||
|
||||
#--- Public
|
||||
def search_by_prefix(self, prefix):
|
||||
# XXX Why the heck is this method here?
|
||||
prefix = prefix.lower()
|
||||
for index, s in enumerate(self):
|
||||
if s.lower().startswith(prefix):
|
||||
@@ -111,21 +149,57 @@ class SelectableList(MutableSequence, Selectable):
|
||||
return -1
|
||||
|
||||
|
||||
class GUISelectableList(SelectableList, GUIObject):
|
||||
#--- View interface
|
||||
# refresh()
|
||||
# update_selection()
|
||||
#
|
||||
class GUISelectableListView:
|
||||
"""Expected interface for :class:`GUISelectableList`'s view.
|
||||
|
||||
*Not actually used in the code. For documentation purposes only.*
|
||||
|
||||
Our view, some kind of list view or combobox, is expected to sync with the list's contents by
|
||||
appropriately behave to all callbacks in this interface.
|
||||
"""
|
||||
def refresh(self):
|
||||
"""Refreshes the contents of the list widget.
|
||||
|
||||
Ensures that the contents of the list widget is synced with the model.
|
||||
"""
|
||||
|
||||
def update_selection(self):
|
||||
"""Update selection status.
|
||||
|
||||
Ensures that the list widget's selection is in sync with the model.
|
||||
"""
|
||||
|
||||
class GUISelectableList(SelectableList, GUIObject):
|
||||
"""Cross-toolkit list view.
|
||||
|
||||
Represents a UI element presenting the user with a selectable list of items.
|
||||
|
||||
Subclasses :class:`SelectableList` and :class:`~hscommon.gui.base.GUIObject`. Expected view:
|
||||
:class:`GUISelectableListView`.
|
||||
|
||||
:param iterable items: If specified, items to fill the list with initially.
|
||||
"""
|
||||
def __init__(self, items=None):
|
||||
SelectableList.__init__(self, items)
|
||||
GUIObject.__init__(self)
|
||||
|
||||
def _view_updated(self):
|
||||
"""Refreshes the view contents with :meth:`GUISelectableListView.refresh`.
|
||||
|
||||
Overrides :meth:`~hscommon.gui.base.GUIObject._view_updated`.
|
||||
"""
|
||||
self.view.refresh()
|
||||
|
||||
def _update_selection(self):
|
||||
"""Refreshes the view selection with :meth:`GUISelectableListView.update_selection`.
|
||||
|
||||
Overrides :meth:`Selectable._update_selection`.
|
||||
"""
|
||||
self.view.update_selection()
|
||||
|
||||
def _on_change(self):
|
||||
"""Refreshes the view contents with :meth:`GUISelectableListView.refresh`.
|
||||
|
||||
Overrides :meth:`SelectableList._on_change`.
|
||||
"""
|
||||
self.view.refresh()
|
||||
|
||||
Reference in New Issue
Block a user