This file is indexed.

/usr/lib/thuban/Thuban/UI/tree.py is in thuban 1.2.2-12build3.

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
226
227
228
229
230
231
232
233
234
235
236
# Copyright (c) 2001, 2002, 2003 by Intevation GmbH
# Authors:
# Jan-Oliver Wagner <jan@intevation.de>
# Bernhard Herzog <bh@intevation.de>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with Thuban for details.

__version__ = "$Revision: 2700 $"

from types import StringType, UnicodeType

import wx

from Thuban import _
from Thuban.UI.common import Color2wxColour

from Thuban.Model.color import Color

from Thuban.Model.messages import CHANGED
from Thuban.Model.layer import Layer
from Thuban.Model.map import Map

from dialogs import NonModalNonParentDialog
from messages import SESSION_REPLACED, LAYER_SELECTED

BMP_SIZE = 15

class SessionTreeCtrl(wx.TreeCtrl):

    """Widget to display a tree view of the session.

    The tree view is created recursively from the session object. The
    tree view calls the session's TreeInfo method which should return a
    pair (<title>, <item>) where <title> ist the title of the session
    item in the tree view and <items> is a list of objects to use as the
    children of the session in the tree view.

    The items list can contain three types of items:

       1. a string. The string is used as the title for a leaf item in
          the tree view.

       2. an object with a TreeInfo method. This method is called and
          should return a pair just like the session's TreeInfo method.

       3. a pair (<title>, <item>) which is treated like the return
          value of TreeInfo.
    """

    def __init__(self, parent, ID, mainwindow, app):

        # Use the WANTS_CHARS style so the panel doesn't eat the Return key.
        wx.TreeCtrl.__init__(self, parent, ID)

        self.mainwindow = mainwindow
        self.app = app
        # boolean to indicate that we manipulate the selection ourselves
        # so that we can ignore the selection events generated
        self.changing_selection = 0

        # Dictionary mapping layer id's to tree items
        self.layer_to_item = {}

        self.app.Subscribe(SESSION_REPLACED, self.session_changed)
        self.mainwindow.Subscribe(LAYER_SELECTED, self.layer_selected)

        # the session currently displayed in the tree
        self.session = None


        # pretend the session has changed to build the initial tree
        self.session_changed()

        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=self.GetId())

    def unsubscribe_all(self):
        if self.session is not None:
            self.session.Unsubscribe(CHANGED, self.update_tree)
            self.session = None
        self.app.Unsubscribe(SESSION_REPLACED, self.session_changed)
        self.mainwindow.Unsubscribe(LAYER_SELECTED, self.layer_selected)

    def update_tree(self, *args):
        """Clear and rebuild the tree"""
        self.DeleteAllItems()
        self.layer_to_item.clear()
        self.image_list = wx.ImageList(BMP_SIZE, BMP_SIZE, False, 0)

        bmp = wx.EmptyBitmap(BMP_SIZE, BMP_SIZE)
        dc = wx.MemoryDC()
        dc.SelectObject(bmp)
        dc.SetBrush(wx.BLACK_BRUSH)
        dc.Clear()
        dc.SelectObject(wx.NullBitmap)

        self.emptyImageIndex = \
            self.image_list.AddWithColourMask(bmp, wx.Colour(0, 0, 0))

        self.AssignImageList(self.image_list)

        session = self.app.session
        info = session.TreeInfo()
        root = self.AddRoot(info[0], -1, -1, None)
        self.SetItemImage(root, self.emptyImageIndex)
        self.add_items(root, info[1])
        self.Expand(root)
        # select the selected layer
        selected_layer = self.mainwindow.current_layer()
        if selected_layer is not None:
            # One would expect that the selected_layer's id is in
            # layer_to_item at this point as we've just rebuilt that
            # mapping completely. However, when a new session is loaded
            # for instance, it can happen that the tree view is updated
            # before the canvas's selection in which case selected_layer
            # may be a layer of the old session.
            item = self.layer_to_item.get(id(selected_layer))
            if item is not None:
                self.SelectItem(item)

    def add_items(self, parent, items):

        if items is None: return

        for item in items:
            if hasattr(item, "TreeInfo"):
                # Supports the TreeInfo protocol
                info = item.TreeInfo()
                treeitem = self.AppendItem(parent, info[0], -1, -1, None)
                self.SetItemImage(treeitem, self.emptyImageIndex)
                self.SetPyData(treeitem, item)
                self.add_items(treeitem, info[1])
                self.Expand(treeitem)
                if isinstance(item, Layer):
                    self.layer_to_item[id(item)] = treeitem
            elif isinstance(item, StringType) or \
                 isinstance(item, UnicodeType):
                # it's a string
                treeitem = self.AppendItem(parent, item, -1, -1, None)
                self.SetItemImage(treeitem, self.emptyImageIndex)
            else:
                # assume its a sequence (title, items)
                if isinstance(item[1], Color):

                    treeitem = self.AppendItem(parent, "(%s)" % item[0])

                    bmp = wx.EmptyBitmap(BMP_SIZE, BMP_SIZE)
                    brush = wx.Brush(Color2wxColour(item[1]), wx.SOLID)
                    dc = wx.MemoryDC()
                    dc.SelectObject(bmp)
                    dc.SetBrush(brush)
                    dc.Clear()
                    dc.DrawRoundedRectangle(0, 0,
                                            bmp.GetWidth(), bmp.GetHeight(),
                                            4)
                    dc.SelectObject(wx.NullBitmap)

                    i = self.image_list.Add(bmp)
                    self.SetItemImage(treeitem, i)
                else:
                    treeitem = self.AppendItem(parent, item[0], -1, -1, None)
                    self.SetItemImage(treeitem, self.emptyImageIndex)
                    self.add_items(treeitem, item[1])
                self.Expand(treeitem)

    def session_changed(self, *args):
        new_session = self.app.session
        # if the session has changed subscribe/unsubscribe
        if self.session is not new_session:
            if self.session is not None:
                self.session.Unsubscribe(CHANGED, self.update_tree)
            if new_session is not None:
                new_session.Subscribe(CHANGED, self.update_tree)
            self.session = new_session
        self.update_tree()

    def normalize_selection(self):
        """Select the layer or map containing currently selected item"""
        item = self.GetSelection()
        while item.IsOk():
            object = self.GetPyData(item)
            if isinstance(object, Layer) or isinstance(object, Map):
                break
            item = self.GetItemParent(item)
        else:
            # No layer or map was found in the chain of parents, so
            # there's nothing we can do.
            return

        self.changing_selection = 1
        try:
            self.SelectItem(item)
        finally:
            self.changing_selection = 0

    def SelectedLayer(self):
        """Return the layer object currently selected in the tree.
        Return None if no layer is selected"""
        layer = self.GetPyData(self.GetSelection())
        if isinstance(layer, Layer):
            return layer
        return None

    def OnSelChanged(self, event):
        if self.changing_selection:
            # we're changing the selection ourselves (probably through
            # self.normalize_selection(). ignore the event.
            return
        self.normalize_selection()
        # SelectedLayer returns None if no layer is selected. Since
        # passing None to SelectLayer deselects the layer we can simply
        # pass the result of SelectedLayer on in all cases
        self.mainwindow.SelectLayer(self.SelectedLayer())

    def layer_selected(self, layer):
        item = self.layer_to_item.get(id(layer))
        if item is not None and item != self.GetSelection():
            self.SelectItem(item)


class SessionTreeView(NonModalNonParentDialog):

    """Non modal dialog showing the session as a tree"""

    def __init__(self, parent, app, name):
        NonModalNonParentDialog.__init__(self, parent, name, _("Session"))
        self.tree = SessionTreeCtrl(self, -1, parent, app)

    def OnClose(self, event):
        NonModalNonParentDialog.OnClose(self, event)

        # if there were a way to get notified when the tree control
        # itself is destroyed we could use that to unsubscribe instead
        # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at
        # all)
        self.tree.unsubscribe_all()