File: selection.py

package info (click to toggle)
git-cola 4.13.0-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 6,480 kB
  • sloc: python: 36,938; sh: 304; makefile: 223; xml: 100; tcl: 62
file content (128 lines) | stat: -rw-r--r-- 3,753 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
"""Provides a selection model to handle selection."""
import collections

from qtpy import QtCore
from qtpy.QtCore import Signal

State = collections.namedtuple('State', 'staged unmerged modified untracked')


def create():
    """Create a SelectionModel"""
    return SelectionModel()


def pick(selection):
    """Choose the first list from stage, unmerged, modified, untracked"""
    if selection.staged:
        files = selection.staged
    elif selection.unmerged:
        files = selection.unmerged
    elif selection.modified:
        files = selection.modified
    elif selection.untracked:
        files = selection.untracked
    else:
        files = []
    return files


def union(selection):
    """Return the union of all selected items in a sorted list"""
    values = set(
        selection.staged + selection.unmerged + selection.modified + selection.untracked
    )
    return list(sorted(values))


def _filter(values, remove):
    """Filter a list in-place by removing items"""
    remove_set = set(remove)
    values_copy = list(values)
    last = len(values_copy) - 1
    for idx, value in enumerate(reversed(values)):
        if value not in remove_set:
            values.pop(last - idx)


class SelectionModel(QtCore.QObject):
    """Provides information about selected file paths."""

    selection_changed = Signal()

    # These properties wrap the individual selection items
    # to provide higher-level pseudo-selections.
    unstaged = property(lambda self: self.unmerged + self.modified + self.untracked)

    def __init__(self):
        super().__init__()
        self.staged = []
        self.unmerged = []
        self.modified = []
        self.untracked = []
        self.line_number = None

    def reset(self, emit=False):
        self.staged = []
        self.unmerged = []
        self.modified = []
        self.untracked = []
        self.line_number = None
        if emit:
            self.selection_changed.emit()

    def is_empty(self):
        return not (
            bool(self.staged or self.unmerged or self.modified or self.untracked)
        )

    def set_selection(self, s):
        """Set the new selection."""
        self.staged = s.staged
        self.unmerged = s.unmerged
        self.modified = s.modified
        self.untracked = s.untracked
        self.selection_changed.emit()

    def update(self, other):
        _filter(self.staged, other.staged)
        _filter(self.unmerged, other.unmerged)
        _filter(self.modified, other.modified)
        _filter(self.untracked, other.untracked)
        self.selection_changed.emit()

    def selection(self):
        return State(self.staged, self.unmerged, self.modified, self.untracked)

    def single_selection(self):
        """Scan across staged, modified, etc. and return a single item."""
        staged = None
        modified = None
        unmerged = None
        untracked = None
        if self.staged:
            staged = self.staged[0]
        elif self.modified:
            modified = self.modified[0]
        elif self.unmerged:
            unmerged = self.unmerged[0]
        elif self.untracked:
            untracked = self.untracked[0]
        return State(staged, unmerged, modified, untracked)

    def filename(self):
        """Return the currently selected filename"""
        paths = [path for path in self.single_selection() if path is not None]
        if paths:
            filename = paths[0]
        else:
            filename = None
        return filename

    def group(self):
        """A list of selected files in various states of being"""
        return pick(self.selection())

    def union(self):
        """Return the union of all selected items in a sorted list"""
        return union(self)