This file is indexed.

/usr/share/pyshared/quodlibet/qltk/songmodel.py is in exfalso 3.0.2-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# Copyright 2012 Christoph Reiter
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation

from gi.repository import Gtk, GObject

from quodlibet.qltk.playorder import ORDERS


def check_sourced(func):
    # Validate sourced flags after each action that could lead to a changed
    # iter (only ones triggerd by the order, no iter removal!)
    def wrap(self, *args, **kwargs):
        res = func(self, *args, **kwargs)
        if self.q.current is not None:
            self.q.sourced = True
            self.pl.sourced = False
        else:
            self.q.sourced = False
            self.pl.sourced = True
        return res
    return wrap


class PlaylistMux(object):

    def __init__(self, player, q, pl):
        self.q = q
        self.pl = pl
        player.connect('song-started', self.__check_q)

    def __check_q(self, player, song):
        if song is not None:
            iter = self.q.find(song)
            if iter:
                self.q.remove(iter)
            self.q.reset()

    def get_current(self):
        if self.q.current is not None:
            return self.q.current
        else:
            return self.pl.current

    current = property(get_current)

    @check_sourced
    def next(self):
        if self.q.is_empty():
            self.pl.next()
        elif self.q.current is None:
            self.q.next()

    @check_sourced
    def next_ended(self):
        if self.q.is_empty():
            self.pl.next_ended()
        elif self.q.current is None:
            self.q.next()

    @check_sourced
    def previous(self):
        self.pl.previous()

    @check_sourced
    def go_to(self, song, explicit=False):
        print_d("Told to go to %r" % getattr(song, "key", song))
        self.q.go_to(None)
        return self.pl.go_to(song, explicit)

    @check_sourced
    def reset(self):
        self.q.go_to(None)
        self.pl.reset()

    def enqueue(self, songs):
        for song in songs:
            self.q.append(row=[song])

    def unqueue(self, songs):
        map(self.q.remove, filter(None, map(self.q.find, songs)))


class TrackCurrentModel(Gtk.ListStore):
    __iter = None
    __old_value = None

    def set(self, songs):
        print_d("Clearing model.")
        self.clear()
        self.__iter = None
        oldsong = self.__old_value

        print_d("Setting %d songs." % len(songs))

        no_autoconv = (long, float, int, basestring, bool, GObject.Object)
        if not songs or songs[0] is None or isinstance(songs[0], no_autoconv):
            for song in reversed(songs):
                iter_ = self.insert(0, row=[song])
                if song is oldsong:
                    self.__iter = iter_
        else:
            insert = self.insert_with_valuesv
            columns = [0]
            for song in reversed(songs):
                iter_ = insert(0, columns, [song])
                if song is oldsong:
                    self.__iter = iter_

        print_d("Done filling model.")

    def remove(self, iter_):
        if self.__iter and self[iter_].path == self[self.__iter].path:
            self.__iter = None
        super(TrackCurrentModel, self).remove(iter_)

    def clear(self):
        self.__iter = None
        super(TrackCurrentModel, self).clear()

    def get(self):
        songs = []

        def func(model, path, iter_, user_data):
            songs.append(model.get_value(iter_, 0))
        self.foreach(func, None)

        return songs

    @property
    def current(self):
        return self.__iter and self.get_value(self.__iter, 0)

    @property
    def current_path(self):
        return self.__iter and self.get_path(self.__iter)

    def __set_current_iter(self, iter_):
        if iter_ == self.__iter:
            return
        # emit a row-changed for the previous and the new iter after it is set
        # so that the currentcolumn icon gets updated on song changes
        for it in filter(None, (self.__iter, iter_)):
            self.row_changed(self.get_path(it), it)
        self.__iter = iter_
        self.__old_value = self.current

    def __get_current_iter(self):
        return self.__iter

    current_iter = property(__get_current_iter, __set_current_iter)

    def find(self, song):
        for row in self:
            if row[0] == song:
                return row.iter
        return None

    def find_all(self, songs):
        return [row.iter for row in self if row[0] in songs]

    def __contains__(self, song):
        return bool(self.find(song))

    def is_empty(self):
        return not len(self)


class PlaylistModel(TrackCurrentModel):
    order = None
    repeat = False
    sourced = False

    def __init__(self):
        super(PlaylistModel, self).__init__(object)
        self.order = ORDERS[0](self)

        # The playorder plugins use paths atm to remember songs so
        # we need to reset them if the paths change somehow.
        self.__sigs = []
        for sig in ['row-deleted', 'row-inserted', 'rows-reordered']:
            s = self.connect(sig, lambda pl, *x: self.order.reset(pl))
            self.__sigs.append(s)

    def next(self):
        iter_ = self.current_iter
        self.current_iter = self.order.next_explicit(self, iter_)

    def next_ended(self):
        iter_ = self.current_iter
        self.current_iter = self.order.next_implicit(self, iter_)

    def previous(self):
        iter_ = self.current_iter
        self.current_iter = self.order.previous_explicit(self, iter_)

    def go_to(self, song, explicit=False):
        print_d("Told to go to %r" % getattr(song, "key", song))

        iter_ = None
        if isinstance(song, Gtk.TreeIter):
            iter_ = song
        elif song is not None:
            iter_ = self.find(song)

        if explicit:
            self.current_iter = self.order.set_explicit(self, iter_)
        else:
            self.current_iter = self.order.set_implicit(self, iter_)

        return self.current_iter

    def set(self, songs):
        self.order.reset(self)
        map(self.handler_block, self.__sigs)
        super(PlaylistModel, self).set(songs)
        map(self.handler_unblock, self.__sigs)

    def reset(self):
        self.go_to(None)
        self.order.reset(self)
        if not self.is_empty():
            self.next()